From 732ff29d1428e059803c2394fd85315a6e2850b7 Mon Sep 17 00:00:00 2001 From: lerencao Date: Fri, 19 Feb 2021 14:34:56 +0800 Subject: [PATCH] make abigen reproducible (#200) * use BTreeMap to make abigen bindings deterministic --- .../ethers-contract-abigen/src/contract.rs | 6 +++--- .../src/contract/events.rs | 18 ++++++++++-------- .../src/contract/methods.rs | 12 ++++++------ 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/ethers-contract/ethers-contract-abigen/src/contract.rs b/ethers-contract/ethers-contract-abigen/src/contract.rs index 4e1c5301..02b623a7 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract.rs @@ -14,7 +14,7 @@ use ethers_core::{ use inflector::Inflector; use proc_macro2::{Ident, Literal, TokenStream}; use quote::quote; -use std::collections::HashMap; +use std::collections::BTreeMap; use syn::{Path, Visibility}; /// Internal shared context for generating smart contract bindings. @@ -32,7 +32,7 @@ pub(crate) struct Context { contract_name: Ident, /// Manually specified method aliases. - method_aliases: HashMap, + method_aliases: BTreeMap, /// Derives added to event structs and enums. event_derives: Vec, @@ -122,7 +122,7 @@ impl Context { // NOTE: We only check for duplicate signatures here, since if there are // duplicate aliases, the compiler will produce a warning because a // method will be re-defined. - let mut method_aliases = HashMap::new(); + let mut method_aliases = BTreeMap::new(); for (signature, alias) in args.method_aliases.into_iter() { let alias = syn::parse_str(&alias)?; if method_aliases.insert(signature.clone(), alias).is_some() { diff --git a/ethers-contract/ethers-contract-abigen/src/contract/events.rs b/ethers-contract/ethers-contract-abigen/src/contract/events.rs index 7c28f19e..9063d5f3 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract/events.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract/events.rs @@ -1,18 +1,19 @@ use super::{types, util, Context}; -use ethers_core::abi::{Event, EventExt, EventParam, Hash, ParamType}; - use anyhow::Result; +use ethers_core::abi::{Event, EventExt, EventParam, Hash, ParamType}; use inflector::Inflector; use proc_macro2::{Literal, TokenStream}; use quote::quote; +use std::collections::BTreeMap; use syn::Path; impl Context { /// Expands each event to a struct + its impl Detokenize block pub fn events_declaration(&self) -> Result { - let data_types = self - .abi - .events() + let sorted_events: BTreeMap<_, _> = self.abi.events.clone().into_iter().collect(); + let data_types = sorted_events + .values() + .flatten() .map(|event| expand_event(event, &self.event_derives)) .collect::>>()?; @@ -26,9 +27,10 @@ impl Context { } pub fn events(&self) -> Result { - let data_types = self - .abi - .events() + let sorted_events: BTreeMap<_, _> = self.abi.events.clone().into_iter().collect(); + let data_types = sorted_events + .values() + .flatten() .map(|event| expand_filter(event)) .collect::>(); diff --git a/ethers-contract/ethers-contract-abigen/src/contract/methods.rs b/ethers-contract/ethers-contract-abigen/src/contract/methods.rs index c9ad79eb..4c15d6d7 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract/methods.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract/methods.rs @@ -1,13 +1,13 @@ use super::{types, util, Context}; +use anyhow::{anyhow, Context as _, Result}; use ethers_core::{ abi::{Function, FunctionExt, Param, StateMutability}, types::Selector, }; - -use anyhow::{anyhow, Context as _, Result}; use inflector::Inflector; use proc_macro2::{Literal, TokenStream}; use quote::quote; +use std::collections::BTreeMap; use syn::Ident; /// Expands a context into a method struct containing all the generated bindings @@ -15,10 +15,10 @@ use syn::Ident; impl Context { pub(crate) fn methods(&self) -> Result { let mut aliases = self.method_aliases.clone(); - - let functions = self - .abi - .functions() + let sorted_functions: BTreeMap<_, _> = self.abi.functions.clone().into_iter().collect(); + let functions = sorted_functions + .values() + .flatten() .map(|function| { let signature = function.abi_signature(); expand_function(function, aliases.remove(&signature))