From ef4a61c7696305098cac7fabb0629b22ba82586d Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 13 Sep 2018 11:04:39 +0200 Subject: [PATCH] new ethabi (#9511) * new ethabi migration in progress * parity migrated to new ethabi * migrated secred-store to new ethabi * bump ethabi to 6.0 * fixed review suggestions --- Cargo.lock | 89 ++-- ethcore/Cargo.toml | 6 +- ethcore/node_filter/Cargo.toml | 6 +- ethcore/node_filter/src/lib.rs | 11 +- ethcore/private-tx/Cargo.toml | 6 +- ethcore/private-tx/src/lib.rs | 45 +- ethcore/src/client/client.rs | 23 +- ethcore/src/engines/block_reward.rs | 8 +- ethcore/src/engines/validator_set/contract.rs | 8 +- .../engines/validator_set/safe_contract.rs | 105 ++--- .../src/miner/service_transaction_checker.rs | 14 +- .../src/snapshot/tests/proof_of_authority.rs | 6 +- ethcore/src/tx_filter.rs | 49 +- hash-fetch/Cargo.toml | 6 +- hash-fetch/src/urlhint.rs | 11 +- registrar/Cargo.toml | 6 +- registrar/src/registrar.rs | 13 +- secret_store/Cargo.toml | 6 +- secret_store/src/acl_storage.rs | 14 +- secret_store/src/key_server_set.rs | 104 +++-- secret_store/src/listener/service_contract.rs | 437 ++++++++---------- updater/Cargo.toml | 6 +- updater/src/updater.rs | 54 +-- 23 files changed, 458 insertions(+), 575 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bc6a36b3..964095175 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -456,7 +456,7 @@ dependencies = [ [[package]] name = "ethabi" -version = "5.1.2" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -470,18 +470,18 @@ dependencies = [ [[package]] name = "ethabi-contract" -version = "5.1.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ethabi-derive" -version = "5.1.3" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -522,9 +522,9 @@ dependencies = [ "common-types 0.1.0", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.12.0", "ethcore-bloom-journal 0.1.0", "ethcore-io 1.12.0", @@ -747,9 +747,9 @@ name = "ethcore-private-tx" version = "1.0.0" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-io 1.12.0", "ethcore-logger 1.12.0", @@ -785,9 +785,9 @@ name = "ethcore-secretstore" version = "1.0.0" dependencies = [ "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-logger 1.12.0", "ethcore-sync 1.12.0", @@ -1863,9 +1863,9 @@ dependencies = [ name = "node-filter" version = "1.12.0" dependencies = [ - "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-io 1.12.0", "ethcore-network 1.12.0", @@ -2097,9 +2097,9 @@ dependencies = [ name = "parity-hash-fetch" version = "1.12.0" dependencies = [ - "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-fetch 0.0.1", "fetch 0.1.0", @@ -2313,9 +2313,9 @@ dependencies = [ name = "parity-updater" version = "1.12.0" dependencies = [ - "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-sync 1.12.0", "ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2563,14 +2563,6 @@ dependencies = [ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "proc-macro2" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "proc-macro2" version = "0.3.8" @@ -2631,14 +2623,6 @@ name = "quick-error" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "quote" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quote" version = "0.5.2" @@ -2770,9 +2754,9 @@ dependencies = [ name = "registrar" version = "0.0.1" dependencies = [ - "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3103,16 +3087,6 @@ name = "strsim" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "syn" -version = "0.12.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "syn" version = "0.13.11" @@ -3960,9 +3934,9 @@ dependencies = [ "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "" -"checksum ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cf28f7a4a82229af21a4b2233eb411c459034010ad524976c4fb4556c5969b5b" -"checksum ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7311354f2a46a4b564004047bf8dce9a57cbd8d7ce30021a56bd1a975baaf2f9" -"checksum ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7caf91e5d37033970be4a66cdef1e5e267af1c999e48b78d6ba86564c1081fab" +"checksum ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "36c7bf66bd7ff02c3bc512a276a0f95300e3abb87060704fddf588ae11b86d99" +"checksum ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "795e25fd868e12a59ca235dbe1f6cc8f1eba8f67d6a39438b29535e0126e0c27" +"checksum ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6853ea4d3aa9ee8cda9252c7e3f3080e6af58796e9ae3d8cfd90d3f03f6c0fb9" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" "checksum ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35b3c5a18bc5e73a32a110ac743ec04b02bbbcd3b71d3118d40a6113d509378a" "checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002" @@ -4084,14 +4058,12 @@ dependencies = [ "checksum primal-check 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e65f96c0a171f887198c274392c99a116ef65aa7f53f3b6d4902f493965c2d1" "checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5" "checksum primal-sieve 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "da2d6ed369bb4b0273aeeb43f07c105c0117717cbae827b20719438eb2eb798c" -"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" "checksum protobuf 1.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "52fbc45bf6709565e44ef31847eb7407b3c3c80af811ee884a04da071dcca12b" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" "checksum pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "90d2b3c5bf24275fc77db6b14ec00a7a085d8ff9d1c4215fb6f6263e8d7b01bc" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" @@ -4146,7 +4118,6 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 098eb5f17..e21a5bf08 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -29,9 +29,9 @@ ethcore-stratum = { path = "./stratum", optional = true } ethcore-transaction = { path = "./transaction" } ethereum-types = "0.4" memory-cache = { path = "../util/memory_cache" } -ethabi = "5.1.2" -ethabi-derive = "5.1.3" -ethabi-contract = "5.1.1" +ethabi = "6.0" +ethabi-derive = "6.0" +ethabi-contract = "6.0" ethjson = { path = "../json" } ethkey = { path = "../ethkey" } ethstore = { path = "../ethstore" } diff --git a/ethcore/node_filter/Cargo.toml b/ethcore/node_filter/Cargo.toml index ea5e1a57f..d7ce7886e 100644 --- a/ethcore/node_filter/Cargo.toml +++ b/ethcore/node_filter/Cargo.toml @@ -13,9 +13,9 @@ ethcore-network-devp2p = { path = "../../util/network-devp2p" } ethereum-types = "0.4" log = "0.4" parking_lot = "0.6" -ethabi = "5.1.2" -ethabi-derive = "5.1.3" -ethabi-contract = "5.1.1" +ethabi = "6.0" +ethabi-derive = "6.0" +ethabi-contract = "6.0" lru-cache = "0.1" [dev-dependencies] diff --git a/ethcore/node_filter/src/lib.rs b/ethcore/node_filter/src/lib.rs index 22267ff98..ec314f191 100644 --- a/ethcore/node_filter/src/lib.rs +++ b/ethcore/node_filter/src/lib.rs @@ -44,16 +44,16 @@ use parking_lot::Mutex; use ethcore::client::{BlockChainClient, BlockId}; use ethereum_types::{H256, Address}; +use ethabi::FunctionOutputDecoder; use network::{ConnectionFilter, ConnectionDirection}; use devp2p::NodeId; -use_contract!(peer_set, "PeerSet", "res/peer_set.json"); +use_contract!(peer_set, "res/peer_set.json"); const MAX_CACHE_SIZE: usize = 4096; /// Connection filter that uses a contract to manage permissions. pub struct NodeFilter { - contract: peer_set::PeerSet, client: Weak, contract_address: Address, permission_cache: Mutex>, @@ -63,7 +63,6 @@ impl NodeFilter { /// Create a new instance. Accepts a contract address. pub fn new(client: Weak, contract_address: Address) -> NodeFilter { NodeFilter { - contract: peer_set::PeerSet::default(), client, contract_address, permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)), @@ -96,9 +95,9 @@ impl ConnectionFilter for NodeFilter { let id_low = H256::from_slice(&connecting_id[0..32]); let id_high = H256::from_slice(&connecting_id[32..64]); - let allowed = self.contract.functions() - .connection_allowed() - .call(own_low, own_high, id_low, id_high, &|data| client.call_contract(BlockId::Latest, address, data)) + let (data, decoder) = peer_set::functions::connection_allowed::call(own_low, own_high, id_low, id_high); + let allowed = client.call_contract(BlockId::Latest, address, data) + .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) .unwrap_or_else(|e| { debug!("Error callling peer set contract: {:?}", e); false diff --git a/ethcore/private-tx/Cargo.toml b/ethcore/private-tx/Cargo.toml index ed098c182..8f0a7361f 100644 --- a/ethcore/private-tx/Cargo.toml +++ b/ethcore/private-tx/Cargo.toml @@ -7,9 +7,9 @@ authors = ["Parity Technologies "] [dependencies] error-chain = { version = "0.12", default-features = false } -ethabi = "5.1.2" -ethabi-derive = "5.1.3" -ethabi-contract = "5.1.1" +ethabi = "6.0" +ethabi-derive = "6.0" +ethabi-contract = "6.0" ethcore = { path = ".." } parity-bytes = "0.1" parity-crypto = "0.1" diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index 24727fe0f..92b673056 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -89,11 +89,12 @@ use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache}; use ethcore::trace::{Tracer, VMTracer}; use rustc_hex::FromHex; use ethkey::Password; +use ethabi::FunctionOutputDecoder; // Source avaiable at https://github.com/parity-contracts/private-tx/blob/master/contracts/PrivateContract.sol const DEFAULT_STUB_CONTRACT: &'static str = include_str!("../res/private.evm"); -use_contract!(private, "PrivateContract", "res/private.json"); +use_contract!(private_contract, "res/private.json"); /// Initialization vector length. const INIT_VEC_LEN: usize = 16; @@ -425,31 +426,23 @@ impl Provider where { } fn get_decrypted_state(&self, address: &Address, block: BlockId) -> Result { - let contract = private::PrivateContract::default(); - let state = contract.functions() - .state() - .call(&|data| self.client.call_contract(block, *address, data)) - .map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?; - + let (data, decoder) = private_contract::functions::state::call(); + let value = self.client.call_contract(block, *address, data)?; + let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?; self.decrypt(address, &state) } fn get_decrypted_code(&self, address: &Address, block: BlockId) -> Result { - let contract = private::PrivateContract::default(); - let code = contract.functions() - .code() - .call(&|data| self.client.call_contract(block, *address, data)) - .map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?; - - self.decrypt(address, &code) + let (data, decoder) = private_contract::functions::code::call(); + let value = self.client.call_contract(block, *address, data)?; + let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?; + self.decrypt(address, &state) } pub fn get_contract_nonce(&self, address: &Address, block: BlockId) -> Result { - let contract = private::PrivateContract::default(); - Ok(contract.functions() - .nonce() - .call(&|data| self.client.call_contract(block, *address, data)) - .map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?) + let (data, decoder) = private_contract::functions::nonce::call(); + let value = self.client.call_contract(block, *address, data)?; + decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into()) } fn snapshot_to_storage(raw: Bytes) -> HashMap { @@ -524,13 +517,11 @@ impl Provider where { fn generate_constructor(validators: &[Address], code: Bytes, storage: Bytes) -> Bytes { let constructor_code = DEFAULT_STUB_CONTRACT.from_hex().expect("Default contract code is valid"); - let private = private::PrivateContract::default(); - private.constructor(constructor_code, validators.iter().map(|a| *a).collect::>(), code, storage) + private_contract::constructor(constructor_code, validators.iter().map(|a| *a).collect::>(), code, storage) } fn generate_set_state_call(signatures: &[Signature], storage: Bytes) -> Bytes { - let private = private::PrivateContract::default(); - private.functions().set_state().input( + private_contract::functions::set_state::encode_input( storage, signatures.iter().map(|s| { let mut v: [u8; 32] = [0; 32]; @@ -604,11 +595,9 @@ impl Provider where { /// Returns private validators for a contract. pub fn get_validators(&self, block: BlockId, address: &Address) -> Result, Error> { - let contract = private::PrivateContract::default(); - Ok(contract.functions() - .get_validators() - .call(&|data| self.client.call_contract(block, *address, data)) - .map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?) + let (data, decoder) = private_contract::functions::get_validators::call(); + let value = self.client.call_contract(block, *address, data)?; + decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into()) } } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 470c5361e..5d670d280 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -86,7 +86,7 @@ pub use types::block_status::BlockStatus; pub use blockchain::CacheSize as BlockChainCacheSize; pub use verification::QueueInfo as BlockQueueInfo; -use_contract!(registry, "Registry", "res/contracts/registrar.json"); +use_contract!(registry, "res/contracts/registrar.json"); const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096; // Max number of blocks imported at once. @@ -232,8 +232,6 @@ pub struct Client { /// An action to be done if a mode/spec_name change happens on_user_defaults_change: Mutex) + 'static + Send>>>, - /// Link to a registry object useful for looking up names - registrar: registry::Registry, registrar_address: Option
, /// A closure to call when we want to restart the client @@ -776,7 +774,6 @@ impl Client { factories: factories, history: history, on_user_defaults_change: Mutex::new(None), - registrar: registry::Registry::default(), registrar_address, exit_handler: Mutex::new(None), importer, @@ -1365,17 +1362,17 @@ impl BlockChainTrait for Client {} impl RegistryInfo for Client { fn registry_address(&self, name: String, block: BlockId) -> Option
{ + use ethabi::FunctionOutputDecoder; + let address = self.registrar_address?; - self.registrar.functions() - .get_address() - .call(keccak(name.as_bytes()), "A", &|data| self.call_contract(block, address, data)) - .ok() - .and_then(|a| if a.is_zero() { - None - } else { - Some(a) - }) + let (data, decoder) = registry::functions::get_address::call(keccak(name.as_bytes()), "A"); + let value = decoder.decode(&self.call_contract(block, address, data).ok()?).ok()?; + if value.is_zero() { + None + } else { + Some(value) + } } } diff --git a/ethcore/src/engines/block_reward.rs b/ethcore/src/engines/block_reward.rs index 9488465e5..becb776b8 100644 --- a/ethcore/src/engines/block_reward.rs +++ b/ethcore/src/engines/block_reward.rs @@ -30,7 +30,7 @@ use trace; use types::BlockNumber; use super::{SystemOrCodeCall, SystemOrCodeCallKind}; -use_contract!(block_reward_contract, "BlockReward", "res/contracts/block_reward.json"); +use_contract!(block_reward_contract, "res/contracts/block_reward.json"); /// The kind of block reward. /// Depending on the consensus engine the allocated block reward might have @@ -81,7 +81,6 @@ impl Into for RewardKind { #[derive(PartialEq, Debug)] pub struct BlockRewardContract { kind: SystemOrCodeCallKind, - block_reward_contract: block_reward_contract::BlockReward, } impl BlockRewardContract { @@ -89,7 +88,6 @@ impl BlockRewardContract { pub fn new(kind: SystemOrCodeCallKind) -> BlockRewardContract { BlockRewardContract { kind, - block_reward_contract: block_reward_contract::BlockReward::default(), } } @@ -114,9 +112,7 @@ impl BlockRewardContract { beneficiaries: &[(Address, RewardKind)], caller: &mut SystemOrCodeCall, ) -> Result, Error> { - let reward = self.block_reward_contract.functions().reward(); - - let input = reward.input( + let input = block_reward_contract::functions::reward::encode_input( beneficiaries.iter().map(|&(address, _)| H160::from(address)), beneficiaries.iter().map(|&(_, ref reward_kind)| u16::from(*reward_kind)), ); diff --git a/ethcore/src/engines/validator_set/contract.rs b/ethcore/src/engines/validator_set/contract.rs index e4fcc83cb..637ff046d 100644 --- a/ethcore/src/engines/validator_set/contract.rs +++ b/ethcore/src/engines/validator_set/contract.rs @@ -30,13 +30,12 @@ use machine::{AuxiliaryData, Call, EthereumMachine}; use super::{ValidatorSet, SimpleList, SystemCall}; use super::safe_contract::ValidatorSafeContract; -use_contract!(validator_report, "ValidatorReport", "res/contracts/validator_report.json"); +use_contract!(validator_report, "res/contracts/validator_report.json"); /// A validator contract with reporting. pub struct ValidatorContract { contract_address: Address, validators: ValidatorSafeContract, - provider: validator_report::ValidatorReport, client: RwLock>>, // TODO [keorn]: remove } @@ -45,7 +44,6 @@ impl ValidatorContract { ValidatorContract { contract_address, validators: ValidatorSafeContract::new(contract_address), - provider: validator_report::ValidatorReport::default(), client: RwLock::new(None), } } @@ -111,7 +109,7 @@ impl ValidatorSet for ValidatorContract { } fn report_malicious(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber, proof: Bytes) { - let data = self.provider.functions().report_malicious().input(*address, block, proof); + let data = validator_report::functions::report_malicious::encode_input(*address, block, proof); match self.transact(data) { Ok(_) => warn!(target: "engine", "Reported malicious validator {}", address), Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), @@ -119,7 +117,7 @@ impl ValidatorSet for ValidatorContract { } fn report_benign(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber) { - let data = self.provider.functions().report_benign().input(*address, block); + let data = validator_report::functions::report_benign::encode_input(*address, block); match self.transact(data) { Ok(_) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address), Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index adaa63f0b..1814e4ec0 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -33,8 +33,9 @@ use std::sync::{Weak, Arc}; use super::{SystemCall, ValidatorSet}; use super::simple_list::SimpleList; use unexpected::Mismatch; +use ethabi::FunctionOutputDecoder; -use_contract!(validator_set, "ValidatorSet", "res/contracts/validator_set.json"); +use_contract!(validator_set, "res/contracts/validator_set.json"); const MEMOIZE_CAPACITY: usize = 500; @@ -50,12 +51,11 @@ lazy_static! { struct StateProof { contract_address: Address, header: Header, - provider: validator_set::ValidatorSet, } impl ::engines::StateDependentProof for StateProof { fn generate_proof(&self, caller: &Call) -> Result, String> { - prove_initial(&self.provider, self.contract_address, &self.header, caller) + prove_initial(self.contract_address, &self.header, caller) } fn check_proof(&self, machine: &EthereumMachine, proof: &[u8]) -> Result<(), String> { @@ -65,7 +65,7 @@ impl ::engines::StateDependentProof for StateProof { return Err("wrong header in proof".into()); } - check_first_proof(machine, &self.provider, self.contract_address, header, &state_items).map(|_| ()) + check_first_proof(machine, self.contract_address, header, &state_items).map(|_| ()) } } @@ -73,7 +73,6 @@ impl ::engines::StateDependentProof for StateProof { pub struct ValidatorSafeContract { contract_address: Address, validators: RwLock>, - provider: validator_set::ValidatorSet, client: RwLock>>, // TODO [keorn]: remove } @@ -89,7 +88,7 @@ fn encode_first_proof(header: &Header, state_items: &[Vec]) -> Bytes { } // check a first proof: fetch the validator set at the given block. -fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::ValidatorSet, contract_address: Address, old_header: Header, state_items: &[DBValue]) +fn check_first_proof(machine: &EthereumMachine, contract_address: Address, old_header: Header, state_items: &[DBValue]) -> Result, String> { use transaction::{Action, Transaction}; @@ -114,31 +113,31 @@ fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::Valida // check state proof using given machine. let number = old_header.number(); - provider.functions().get_validators().call(&|data| { - let from = Address::default(); - let tx = Transaction { - nonce: machine.account_start_nonce(number), - action: Action::Call(contract_address), - gas: PROVIDED_GAS.into(), - gas_price: U256::default(), - value: U256::default(), - data, - }.fake_sign(from); + let (data, decoder) = validator_set::functions::get_validators::call(); - let res = ::state::check_proof( - state_items, - *old_header.state_root(), - &tx, - machine, - &env_info, - ); + let from = Address::default(); + let tx = Transaction { + nonce: machine.account_start_nonce(number), + action: Action::Call(contract_address), + gas: PROVIDED_GAS.into(), + gas_price: U256::default(), + value: U256::default(), + data, + }.fake_sign(from); - match res { - ::state::ProvedExecution::BadProof => Err("Bad proof".into()), - ::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)), - ::state::ProvedExecution::Complete(e) => Ok(e.output), - } - }).map_err(|err| err.to_string()) + let res = ::state::check_proof( + state_items, + *old_header.state_root(), + &tx, + machine, + &env_info, + ); + + match res { + ::state::ProvedExecution::BadProof => Err("Bad proof".into()), + ::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)), + ::state::ProvedExecution::Complete(e) => decoder.decode(&e.output).map_err(|e| e.to_string()), + } } fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec), ::error::Error> { @@ -167,32 +166,26 @@ fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec), ::error::Error> { // given a provider and caller, generate proof. this will just be a state proof // of `getValidators`. -fn prove_initial(provider: &validator_set::ValidatorSet, contract_address: Address, header: &Header, caller: &Call) -> Result, String> { +fn prove_initial(contract_address: Address, header: &Header, caller: &Call) -> Result, String> { use std::cell::RefCell; let epoch_proof = RefCell::new(None); - let res = { - let caller = |data| { - let (result, proof) = caller(contract_address, data)?; - *epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof)); - Ok(result) - }; - - provider.functions().get_validators().call(&caller) - .map_err(|err| err.to_string()) + let validators = { + let (data, decoder) = validator_set::functions::get_validators::call(); + let (value, proof) = caller(contract_address, data)?; + *epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof)); + decoder.decode(&value).map_err(|e| e.to_string())? }; - res.map(|validators| { - let proof = epoch_proof.into_inner().expect("epoch_proof always set after call; qed"); + let proof = epoch_proof.into_inner().expect("epoch_proof always set after call; qed"); - trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes", - validators.len(), proof.len()); + trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes", + validators.len(), proof.len()); - info!(target: "engine", "Signal for switch to contract-based validator set."); - info!(target: "engine", "Initial contract validators: {:?}", validators); + info!(target: "engine", "Signal for switch to contract-based validator set."); + info!(target: "engine", "Initial contract validators: {:?}", validators); - proof - }) + Ok(proof) } impl ValidatorSafeContract { @@ -200,7 +193,6 @@ impl ValidatorSafeContract { ValidatorSafeContract { contract_address, validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)), - provider: validator_set::ValidatorSet::default(), client: RwLock::new(None), } } @@ -208,8 +200,11 @@ impl ValidatorSafeContract { /// Queries the state and gets the set of validators. fn get_list(&self, caller: &Call) -> Option { let contract_address = self.contract_address; - let caller = move |data| caller(contract_address, data).map(|x| x.0); - match self.provider.functions().get_validators().call(&caller) { + + let (data, decoder) = validator_set::functions::get_validators::call(); + let value = caller(contract_address, data).and_then(|x| decoder.decode(&x.0).map_err(|e| e.to_string())); + + match value { Ok(new) => { debug!(target: "engine", "Set of validators obtained: {:?}", new); Some(SimpleList::new(new)) @@ -259,7 +254,6 @@ impl ValidatorSafeContract { log.topics[1] == *header.parent_hash() }; - let event = self.provider.events().initiate_change(); //// iterate in reverse because only the _last_ change in a given //// block actually has any effect. //// the contract should only increment the nonce once. @@ -269,7 +263,7 @@ impl ValidatorSafeContract { .flat_map(|r| r.logs.iter()) .filter(move |l| check_log(l)) .filter_map(|log| { - event.parse_log((log.topics.clone(), log.data.clone()).into()).ok() + validator_set::events::initiate_change::parse_log((log.topics.clone(), log.data.clone()).into()).ok() }); // only last log is taken into account @@ -296,7 +290,7 @@ impl ValidatorSet for ValidatorSafeContract { } fn on_epoch_begin(&self, _first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), ::error::Error> { - let data = self.provider.functions().finalize_change().input(); + let data = validator_set::functions::finalize_change::encode_input(); caller(self.contract_address, data) .map(|_| ()) .map_err(::engines::EngineError::FailedSystemCall) @@ -304,7 +298,7 @@ impl ValidatorSet for ValidatorSafeContract { } fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result, String> { - prove_initial(&self.provider, self.contract_address, header, call) + prove_initial(self.contract_address, header, call) } fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option> { @@ -322,7 +316,6 @@ impl ValidatorSet for ValidatorSafeContract { let state_proof = Arc::new(StateProof { contract_address: self.contract_address, header: header.clone(), - provider: validator_set::ValidatorSet::default(), }); return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Arc<_>)); } @@ -361,7 +354,7 @@ impl ValidatorSet for ValidatorSafeContract { let (old_header, state_items) = decode_first_proof(&rlp)?; let number = old_header.number(); let old_hash = old_header.hash(); - let addresses = check_first_proof(machine, &self.provider, self.contract_address, old_header, &state_items) + let addresses = check_first_proof(machine, self.contract_address, old_header, &state_items) .map_err(::engines::EngineError::InsufficientProof)?; trace!(target: "engine", "extracted epoch set at #{}: {} addresses", diff --git a/ethcore/src/miner/service_transaction_checker.rs b/ethcore/src/miner/service_transaction_checker.rs index adae0c36e..ecae30558 100644 --- a/ethcore/src/miner/service_transaction_checker.rs +++ b/ethcore/src/miner/service_transaction_checker.rs @@ -18,16 +18,15 @@ use client::{RegistryInfo, CallContract, BlockId}; use transaction::SignedTransaction; +use ethabi::FunctionOutputDecoder; -use_contract!(service_transaction, "ServiceTransaction", "res/contracts/service_transaction.json"); +use_contract!(service_transaction, "res/contracts/service_transaction.json"); const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transaction_checker"; /// Service transactions checker. #[derive(Default, Clone)] -pub struct ServiceTransactionChecker { - contract: service_transaction::ServiceTransaction, -} +pub struct ServiceTransactionChecker; impl ServiceTransactionChecker { /// Checks if given address is whitelisted to send service transactions. @@ -45,9 +44,8 @@ impl ServiceTransactionChecker { trace!(target: "txqueue", "[{:?}] Checking service transaction checker contract from {}", hash, sender); - self.contract.functions() - .certified() - .call(sender, &|data| client.call_contract(BlockId::Latest, address, data)) - .map_err(|e| e.to_string()) + let (data, decoder) = service_transaction::functions::certified::call(sender); + let value = client.call_contract(BlockId::Latest, address, data)?; + decoder.decode(&value).map_err(|e| e.to_string()) } } diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs index 5c88a4443..d8c721518 100644 --- a/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -32,7 +32,7 @@ use tempdir::TempDir; use ethereum_types::Address; use test_helpers; -use_contract!(test_validator_set, "ValidatorSet", "res/contracts/test_validator_set.json"); +use_contract!(test_validator_set, "res/contracts/test_validator_set.json"); const PASS: &'static str = ""; const TRANSITION_BLOCK_1: usize = 2; // block at which the contract becomes activated. @@ -135,8 +135,6 @@ fn make_chain(accounts: Arc, blocks_beyond: usize, transitions: vec![transaction] }; - let contract = test_validator_set::ValidatorSet::default(); - // apply all transitions. for transition in transitions { let (num, manual, new_set) = match transition { @@ -163,7 +161,7 @@ fn make_chain(accounts: Arc, blocks_beyond: usize, transitions: false => &CONTRACT_ADDR_1 as &Address, }; - let data = contract.functions().set_validators().input(new_set.clone()); + let data = test_validator_set::functions::set_validators::encode_input(new_set.clone()); let mut nonce = nonce.borrow_mut(); let transaction = Transaction { nonce: *nonce, diff --git a/ethcore/src/tx_filter.rs b/ethcore/src/tx_filter.rs index 78b495b26..4a80c259b 100644 --- a/ethcore/src/tx_filter.rs +++ b/ethcore/src/tx_filter.rs @@ -18,6 +18,7 @@ use ethereum_types::{H256, U256, Address}; use lru_cache::LruCache; +use ethabi::FunctionOutputDecoder; use client::{BlockInfo, CallContract, BlockId}; use parking_lot::Mutex; @@ -26,8 +27,8 @@ use transaction::{Action, SignedTransaction}; use types::BlockNumber; use hash::KECCAK_EMPTY; -use_contract!(transact_acl_deprecated, "TransactAclDeprecated", "res/contracts/tx_acl_deprecated.json"); -use_contract!(transact_acl, "TransactAcl", "res/contracts/tx_acl.json"); +use_contract!(transact_acl_deprecated, "res/contracts/tx_acl_deprecated.json"); +use_contract!(transact_acl, "res/contracts/tx_acl.json"); const MAX_CACHE_SIZE: usize = 4096; @@ -42,8 +43,6 @@ mod tx_permissions { /// Connection filter that uses a contract to manage permissions. pub struct TransactionFilter { - contract_deprecated: transact_acl_deprecated::TransactAclDeprecated, - contract: transact_acl::TransactAcl, contract_address: Address, transition_block: BlockNumber, permission_cache: Mutex>, @@ -55,8 +54,6 @@ impl TransactionFilter { pub fn from_params(params: &CommonParams) -> Option { params.transaction_permission_contract.map(|address| TransactionFilter { - contract_deprecated: transact_acl_deprecated::TransactAclDeprecated::default(), - contract: transact_acl::TransactAcl::default(), contract_address: address, transition_block: params.transaction_permission_contract_transition, permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)), @@ -91,10 +88,8 @@ impl TransactionFilter { let contract_address = self.contract_address; let contract_version = contract_version_cache.get_mut(parent_hash).and_then(|v| *v).or_else(|| { - self.contract.functions() - .contract_version() - .call(&|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)) - .ok() + let (data, decoder) = transact_acl::functions::contract_version::call(); + decoder.decode(&client.call_contract(BlockId::Hash(*parent_hash), contract_address, data).ok()?).ok() }); contract_version_cache.insert(*parent_hash, contract_version); @@ -104,14 +99,16 @@ impl TransactionFilter { let version_u64 = version.low_u64(); trace!(target: "tx_filter", "Version of tx permission contract: {}", version); match version_u64 { - 2 => self.contract.functions() - .allowed_tx_types() - .call(sender, to, value, &|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)) - .map(|(p, f)| (p.low_u32(), f)) - .unwrap_or_else(|e| { - error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e); - (tx_permissions::NONE, true) - }), + 2 => { + let (data, decoder) = transact_acl::functions::allowed_tx_types::call(sender, to, value); + client.call_contract(BlockId::Hash(*parent_hash), contract_address, data) + .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) + .map(|(p, f)| (p.low_u32(), f)) + .unwrap_or_else(|e| { + error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e); + (tx_permissions::NONE, true) + }) + }, _ => { error!(target: "tx_filter", "Unknown version of tx permissions contract is used"); (tx_permissions::NONE, true) @@ -120,14 +117,14 @@ impl TransactionFilter { }, None => { trace!(target: "tx_filter", "Fallback to the deprecated version of tx permission contract"); - (self.contract_deprecated.functions() - .allowed_tx_types() - .call(sender, &|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)) - .map(|p| p.low_u32()) - .unwrap_or_else(|e| { - error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e); - tx_permissions::NONE - }), true) + let (data, decoder) = transact_acl_deprecated::functions::allowed_tx_types::call(sender); + (client.call_contract(BlockId::Hash(*parent_hash), contract_address, data) + .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) + .map(|p| p.low_u32()) + .unwrap_or_else(|e| { + error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e); + tx_permissions::NONE + }), true) } }; diff --git a/hash-fetch/Cargo.toml b/hash-fetch/Cargo.toml index a2f94fe76..683fc3b4b 100644 --- a/hash-fetch/Cargo.toml +++ b/hash-fetch/Cargo.toml @@ -21,9 +21,9 @@ parity-reactor = { path = "../util/reactor" } keccak-hash = "0.1" registrar = { path = "../registrar" } -ethabi = "5.1.2" -ethabi-derive = "5.1.3" -ethabi-contract = "5.1.1" +ethabi = "6.0" +ethabi-derive = "6.0" +ethabi-contract = "6.0" [dev-dependencies] hyper = "0.11" diff --git a/hash-fetch/src/urlhint.rs b/hash-fetch/src/urlhint.rs index d80566ea6..d3a9af2bf 100644 --- a/hash-fetch/src/urlhint.rs +++ b/hash-fetch/src/urlhint.rs @@ -26,7 +26,7 @@ use futures::future::Either; use ethereum_types::{H256, Address}; use registrar::{Registrar, RegistrarClient, Asynchronous}; -use_contract!(urlhint, "Urlhint", "res/urlhint.json"); +use_contract!(urlhint, "res/urlhint.json"); const COMMIT_LEN: usize = 20; const GITHUB_HINT: &'static str = "githubhint"; @@ -100,16 +100,14 @@ pub trait URLHint: Send + Sync { /// `URLHintContract` API pub struct URLHintContract { - urlhint: urlhint::Urlhint, registrar: Registrar, client: Arc>, } impl URLHintContract { /// Creates new `URLHintContract` - pub fn new(client: Arc>) -> Self { + pub fn new(client: Arc>) -> Self { URLHintContract { - urlhint: urlhint::Urlhint::default(), registrar: Registrar::new(client.clone()), client: client, } @@ -162,14 +160,13 @@ fn decode_urlhint_output(output: (String, [u8; 20], Address)) -> Option Box, Error = String> + Send> { - let entries = self.urlhint.functions().entries(); let client = self.client.clone(); let future = self.registrar.get_address(GITHUB_HINT) .and_then(move |addr| if !addr.is_zero() { - let data = entries.input(id); + let data = urlhint::functions::entries::encode_input(id); let result = client.call_contract(addr, data) - .and_then(move |output| entries.output(&output).map_err(|e| e.to_string())) + .and_then(move |output| urlhint::functions::entries::decode_output(&output).map_err(|e| e.to_string())) .map(decode_urlhint_output); Either::B(result) } else { diff --git a/registrar/Cargo.toml b/registrar/Cargo.toml index 2ce83f784..6f526af28 100644 --- a/registrar/Cargo.toml +++ b/registrar/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Parity Technologies "] [dependencies] futures = "0.1" -ethabi = "5.1.2" -ethabi-derive = "5.1.3" -ethabi-contract = "5.1.1" +ethabi = "6.0" +ethabi-derive = "6.0" +ethabi-contract = "6.0" keccak-hash = "0.1" diff --git a/registrar/src/registrar.rs b/registrar/src/registrar.rs index a3f6144a5..e16701642 100644 --- a/registrar/src/registrar.rs +++ b/registrar/src/registrar.rs @@ -19,7 +19,7 @@ use ethabi::{Address, Bytes}; use std::sync::Arc; use keccak_hash::keccak; -use_contract!(registry, "Registry", "res/registrar.json"); +use_contract!(registrar, "res/registrar.json"); // Maps a domain name to an Ethereum address const DNS_A_RECORD: &'static str = "A"; @@ -30,7 +30,6 @@ pub type Synchronous = Result; /// Registrar is dedicated interface to access the registrar contract /// which in turn generates an address when a client requests one pub struct Registrar { - registrar: registry::Registry, client: Arc>, } @@ -38,7 +37,6 @@ impl Registrar { /// Registrar constructor pub fn new(client: Arc>) -> Self { Self { - registrar: registry::Registry::default(), client: client, } } @@ -51,14 +49,11 @@ impl Registrar { Err(e) => return Box::new(future::err(e)), }; - let address_fetcher = self.registrar.functions().get_address(); let hashed_key: [u8; 32] = keccak(key).into(); - let id = address_fetcher.input(hashed_key, DNS_A_RECORD); + let id = registrar::functions::get_address::encode_input(hashed_key, DNS_A_RECORD); - let future = self.client.call_contract(registrar_address, id).and_then(move |address| { - address_fetcher.output(&address) - } - .map_err(|e| e.to_string())); + let future = self.client.call_contract(registrar_address, id) + .and_then(move |address| registrar::functions::get_address::decode_output(&address).map_err(|e| e.to_string())); Box::new(future) } diff --git a/secret_store/Cargo.toml b/secret_store/Cargo.toml index 06b6a8f0f..0d1904ce1 100644 --- a/secret_store/Cargo.toml +++ b/secret_store/Cargo.toml @@ -34,9 +34,9 @@ kvdb = "0.1" keccak-hash = "0.1" ethkey = { path = "../ethkey" } lazy_static = "1.0" -ethabi = "5.1.2" -ethabi-derive = "5.1.3" -ethabi-contract = "5.1.1" +ethabi = "6.0" +ethabi-derive = "6.0" +ethabi-contract = "6.0" [dev-dependencies] ethcore = { path = "../ethcore", features = ["test-helpers"] } diff --git a/secret_store/src/acl_storage.rs b/secret_store/src/acl_storage.rs index efc01f030..6bc9aa0e6 100644 --- a/secret_store/src/acl_storage.rs +++ b/secret_store/src/acl_storage.rs @@ -20,11 +20,12 @@ use std::time::Duration; use parking_lot::{Mutex, RwLock}; use ethcore::client::{BlockId, ChainNotify, ChainRoute, CallContract}; use ethereum_types::{H256, Address}; +use ethabi::FunctionOutputDecoder; use bytes::Bytes; use trusted_client::TrustedClient; use types::{Error, ServerKeyId, ContractAddress}; -use_contract!(acl_storage, "AclStorage", "res/acl_storage.json"); +use_contract!(acl_storage, "res/acl_storage.json"); const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker"; @@ -48,8 +49,6 @@ struct CachedContract { address_source: ContractAddress, /// Current contract address. contract_address: Option
, - /// Contract at given address. - contract: acl_storage::AclStorage, } /// Dummy ACL storage implementation (check always passed). @@ -91,7 +90,6 @@ impl CachedContract { client, address_source, contract_address: None, - contract: acl_storage::AclStorage::default(), }; contract.update_contract_address(); contract @@ -112,10 +110,10 @@ impl CachedContract { // call contract to check accesss match self.contract_address { Some(contract_address) => { - let do_call = |data| client.call_contract(BlockId::Latest, contract_address, data); - self.contract.functions() - .check_permissions() - .call(requester, document.clone(), &do_call) + let (encoded, decoder) = acl_storage::functions::check_permissions::call(requester, document.clone()); + let d = client.call_contract(BlockId::Latest, contract_address, encoded) + .map_err(|e| Error::Internal(format!("ACL checker call error: {}", e.to_string())))?; + decoder.decode(&d) .map_err(|e| Error::Internal(format!("ACL checker call error: {}", e.to_string()))) }, None => Err(Error::Internal("ACL checker contract is not configured".to_owned())), diff --git a/secret_store/src/key_server_set.rs b/secret_store/src/key_server_set.rs index 7bae27017..128d865b8 100644 --- a/secret_store/src/key_server_set.rs +++ b/secret_store/src/key_server_set.rs @@ -19,15 +19,16 @@ use std::net::SocketAddr; use std::collections::{BTreeMap, HashSet}; use std::time::Duration; use parking_lot::Mutex; +use ethabi::FunctionOutputDecoder; use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify, ChainRoute, CallContract}; -use ethkey::public_to_address; use ethereum_types::{H256, Address}; +use ethkey::public_to_address; use bytes::Bytes; use types::{Error, Public, NodeAddress, NodeId}; use trusted_client::TrustedClient; use {NodeKeyPair, ContractAddress}; -use_contract!(key_server, "KeyServerSet", "res/key_server_set.json"); +use_contract!(key_server, "res/key_server_set.json"); /// Name of KeyServerSet contract in registry. const KEY_SERVER_SET_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_server_set"; @@ -104,8 +105,6 @@ struct CachedContract { contract_address_source: Option, /// Current contract address. contract_address: Option
, - /// Contract interface. - contract: key_server::KeyServerSet, /// Is auto-migrate enabled? auto_migrate_enabled: bool, /// Current contract state. @@ -169,66 +168,60 @@ trait KeyServerSubset) -> Result, String>> { fn read_address(&self, address: Address, f: &F) -> Result; } -#[derive(Default)] -struct CurrentKeyServerSubset { - read_list: key_server::functions::GetCurrentKeyServers, - read_public: key_server::functions::GetCurrentKeyServerPublic, - read_address: key_server::functions::GetCurrentKeyServerAddress, -} +struct CurrentKeyServerSubset; impl ) -> Result, String>> KeyServerSubset for CurrentKeyServerSubset { fn read_list(&self, f: &F) -> Result, String> { - self.read_list.call(f).map_err(|e| e.to_string()) + let (encoded, decoder) = key_server::functions::get_current_key_servers::call(); + decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) } fn read_public(&self, address: Address, f: &F) -> Result { - self.read_public.call(address, f).map_err(|e| e.to_string()) + let (encoded, decoder) = key_server::functions::get_current_key_server_public::call(address); + decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) } fn read_address(&self, address: Address, f: &F) -> Result { - self.read_address.call(address, f).map_err(|e| e.to_string()) + let (encoded, decoder) = key_server::functions::get_current_key_server_address::call(address); + decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) } } -#[derive(Default)] -struct MigrationKeyServerSubset { - read_list: key_server::functions::GetMigrationKeyServers, - read_public: key_server::functions::GetMigrationKeyServerPublic, - read_address: key_server::functions::GetMigrationKeyServerAddress, -} +struct MigrationKeyServerSubset; impl ) -> Result, String>> KeyServerSubset for MigrationKeyServerSubset { fn read_list(&self, f: &F) -> Result, String> { - self.read_list.call(f).map_err(|e| e.to_string()) + let (encoded, decoder) = key_server::functions::get_migration_key_servers::call(); + decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) } fn read_public(&self, address: Address, f: &F) -> Result { - self.read_public.call(address, f).map_err(|e| e.to_string()) + let (encoded, decoder) = key_server::functions::get_migration_key_server_public::call(address); + decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) } fn read_address(&self, address: Address, f: &F) -> Result { - self.read_address.call(address, f).map_err(|e| e.to_string()) + let (encoded, decoder) = key_server::functions::get_migration_key_server_address::call(address); + decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) } } -#[derive(Default)] -struct NewKeyServerSubset { - read_list: key_server::functions::GetNewKeyServers, - read_public: key_server::functions::GetNewKeyServerPublic, - read_address: key_server::functions::GetNewKeyServerAddress, -} +struct NewKeyServerSubset; impl ) -> Result, String>> KeyServerSubset for NewKeyServerSubset { fn read_list(&self, f: &F) -> Result, String> { - self.read_list.call(f).map_err(|e| e.to_string()) + let (encoded, decoder) = key_server::functions::get_new_key_servers::call(); + decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) } fn read_public(&self, address: Address, f: &F) -> Result { - self.read_public.call(address, f).map_err(|e| e.to_string()) + let (encoded, decoder) = key_server::functions::get_new_key_server_public::call(address); + decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) } fn read_address(&self, address: Address, f: &F) -> Result { - self.read_address.call(address, f).map_err(|e| e.to_string()) + let (encoded, decoder) = key_server::functions::get_new_key_server_address::call(address); + decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) } } @@ -249,7 +242,6 @@ impl CachedContract { client: client, contract_address_source: contract_address_source, contract_address: None, - contract: key_server::KeyServerSet::default(), auto_migrate_enabled: auto_migrate_enabled, future_new_set: None, confirm_migration_tx: None, @@ -313,7 +305,7 @@ impl CachedContract { } // prepare transaction data - let transaction_data = self.contract.functions().start_migration().input(migration_id); + let transaction_data = key_server::functions::start_migration::encode_input(migration_id); // send transaction match self.client.transact_contract(*contract_address, transaction_data) { @@ -334,7 +326,7 @@ impl CachedContract { } // prepare transaction data - let transaction_data = self.contract.functions().confirm_migration().input(migration_id); + let transaction_data = key_server::functions::confirm_migration::encode_input(migration_id); // send transaction match self.client.transact_contract(contract_address, transaction_data) { @@ -362,36 +354,50 @@ impl CachedContract { let do_call = |data| client.call_contract(BlockId::Latest, contract_address, data); - let current_set = Self::read_key_server_set(CurrentKeyServerSubset::default(), &do_call); + let current_set = Self::read_key_server_set(CurrentKeyServerSubset, &do_call); // read migration-related data if auto migration is enabled let (new_set, migration) = match self.auto_migrate_enabled { true => { - let new_set = Self::read_key_server_set(NewKeyServerSubset::default(), &do_call); - let migration_set = Self::read_key_server_set(MigrationKeyServerSubset::default(), &do_call); + let new_set = Self::read_key_server_set(NewKeyServerSubset, &do_call); + let migration_set = Self::read_key_server_set(MigrationKeyServerSubset, &do_call); let migration_id = match migration_set.is_empty() { - false => self.contract.functions().get_migration_id().call(&do_call) - .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration id from contract", err); err }) - .ok(), + false => { + let (encoded, decoder) = key_server::functions::get_migration_id::call(); + do_call(encoded) + .map_err(|e| e.to_string()) + .and_then(|data| decoder.decode(&data).map_err(|e| e.to_string())) + .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration id from contract", err); err }) + .ok() + }, true => None, }; let migration_master = match migration_set.is_empty() { - false => self.contract.functions().get_migration_master().call(&do_call) - .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration master from contract", err); err }) - .ok() - .and_then(|address| current_set.keys().chain(migration_set.keys()) - .find(|public| public_to_address(public) == address) - .cloned()), + false => { + let (encoded, decoder) = key_server::functions::get_migration_master::call(); + do_call(encoded) + .map_err(|e| e.to_string()) + .and_then(|data| decoder.decode(&data).map_err(|e| e.to_string())) + .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration master from contract", err); err }) + .ok() + .and_then(|address| current_set.keys().chain(migration_set.keys()) + .find(|public| public_to_address(public) == address) + .cloned()) + }, true => None, }; let is_migration_confirmed = match migration_set.is_empty() { - false if current_set.contains_key(self.self_key_pair.public()) || migration_set.contains_key(self.self_key_pair.public()) => - self.contract.functions().is_migration_confirmed().call(self.self_key_pair.address(), &do_call) + false if current_set.contains_key(self.self_key_pair.public()) || migration_set.contains_key(self.self_key_pair.public()) => { + let (encoded, decoder) = key_server::functions::is_migration_confirmed::call(self.self_key_pair.address()); + do_call(encoded) + .map_err(|e| e.to_string()) + .and_then(|data| decoder.decode(&data).map_err(|e| e.to_string())) .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration confirmation from contract", err); err }) - .ok(), + .ok() + }, _ => None, }; diff --git a/secret_store/src/listener/service_contract.rs b/secret_store/src/listener/service_contract.rs index dfa102599..545ce8000 100644 --- a/secret_store/src/listener/service_contract.rs +++ b/secret_store/src/listener/service_contract.rs @@ -17,8 +17,9 @@ use std::sync::Arc; use parking_lot::RwLock; use ethabi::RawLog; -use ethcore::filter::Filter; +use ethabi::FunctionOutputDecoder; use ethcore::client::{Client, BlockChainClient, BlockId, CallContract}; +use ethcore::filter::Filter; use ethkey::{Public, public_to_address}; use hash::keccak; use bytes::Bytes; @@ -29,7 +30,7 @@ use trusted_client::TrustedClient; use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED}; use {ServerKeyId, NodeKeyPair, ContractAddress}; -use_contract!(service, "Service", "res/service.json"); +use_contract!(service, "res/service.json"); /// Name of the general SecretStore contract in the registry. pub const SERVICE_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_service"; @@ -102,8 +103,6 @@ pub struct OnChainServiceContract { /// Contract address source. address_source: ContractAddress, /// Contract. - contract: service::Service, - /// Contract. data: RwLock, } @@ -143,7 +142,6 @@ impl OnChainServiceContract { self_key_pair: self_key_pair, name: name, address_source: address_source, - contract: service::Service::default(), data: RwLock::new(ServiceData { contract_address: None, last_log_block: None, @@ -156,8 +154,8 @@ impl OnChainServiceContract { /// Send transaction to the service contract. fn send_contract_transaction(&self, tx_name: &str, origin: &Address, server_key_id: &ServerKeyId, is_response_required: C, prepare_tx: P) -> Result<(), String> - where C: FnOnce(&Client, &Address, &service::Service, &ServerKeyId, &Address) -> bool, - P: FnOnce(&Client, &Address, &service::Service) -> Result { + where C: FnOnce(&Client, &Address, &ServerKeyId, &Address) -> bool, + P: FnOnce(&Client, &Address) -> Result { // only publish if contract address is set && client is online let client = match self.client.get() { Some(client) => client, @@ -168,12 +166,12 @@ impl OnChainServiceContract { // failing is ok here - it could be that enough confirmations have been recevied // or key has been requested using HTTP API let self_address = public_to_address(self.self_key_pair.public()); - if !is_response_required(&*client, origin, &self.contract, server_key_id, &self_address) { + if !is_response_required(&*client, origin, server_key_id, &self_address) { return Ok(()); } // prepare transaction data - let transaction_data = prepare_tx(&*client, origin, &self.contract)?; + let transaction_data = prepare_tx(&*client, origin)?; // send transaction self.client.transact_contract( @@ -189,18 +187,17 @@ impl OnChainServiceContract { /// Create task-specific pending requests iterator. fn create_pending_requests_iterator< - C: 'static + Fn(&Client, &Address, &service::Service, &BlockId) -> Result, - R: 'static + Fn(&NodeKeyPair, &Client, &Address, &service::Service, &BlockId, U256) -> Result<(bool, ServiceTask), String> + C: 'static + Fn(&Client, &Address, &BlockId) -> Result, + R: 'static + Fn(&NodeKeyPair, &Client, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { - let contract = service::Service::default(); - get_count(&*client, contract_address, &contract, block) + get_count(&*client, contract_address, block) .map(|count| { let client = client.clone(); let self_key_pair = self.self_key_pair.clone(); let contract_address = contract_address.clone(); let block = block.clone(); Box::new(PendingRequestsIterator { - read_request: move |index| read_item(&*self_key_pair, &*client, &contract_address, &contract, &block, index) + read_request: move |index| read_item(&*self_key_pair, &*client, &contract_address, &block, index) .map_err(|error| { warn!(target: "secretstore", "{}: reading pending request failed: {}", self_key_pair.public(), error); @@ -289,15 +286,15 @@ impl ServiceContract for OnChainServiceContract { .filter_map(|log| { let raw_log: RawLog = (log.entry.topics.into_iter().map(|t| t.0.into()).collect(), log.entry.data).into(); if raw_log.topics[0] == *SERVER_KEY_GENERATION_REQUESTED_EVENT_NAME_HASH { - ServerKeyGenerationService::parse_log(&address, &self.contract, raw_log) + ServerKeyGenerationService::parse_log(&address, raw_log) } else if raw_log.topics[0] == *SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { - ServerKeyRetrievalService::parse_log(&address, &self.contract, raw_log) + ServerKeyRetrievalService::parse_log(&address, raw_log) } else if raw_log.topics[0] == *DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME_HASH { - DocumentKeyStoreService::parse_log(&address, &self.contract, raw_log) + DocumentKeyStoreService::parse_log(&address, raw_log) } else if raw_log.topics[0] == *DOCUMENT_KEY_COMMON_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { - DocumentKeyShadowRetrievalService::parse_common_request_log(&address, &self.contract, raw_log) + DocumentKeyShadowRetrievalService::parse_common_request_log(&address, raw_log) } else if raw_log.topics[0] == *DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { - DocumentKeyShadowRetrievalService::parse_personal_request_log(&address, &self.contract, raw_log) + DocumentKeyShadowRetrievalService::parse_personal_request_log(&address, raw_log) } else { Err("unknown type of log entry".into()) } @@ -357,58 +354,58 @@ impl ServiceContract for OnChainServiceContract { fn publish_generated_server_key(&self, origin: &Address, server_key_id: &ServerKeyId, server_key: Public) -> Result<(), String> { self.send_contract_transaction("publish_generated_server_key", origin, server_key_id, ServerKeyGenerationService::is_response_required, - |_, _, service| Ok(ServerKeyGenerationService::prepare_pubish_tx_data(service, server_key_id, &server_key))) + |_, _| Ok(ServerKeyGenerationService::prepare_pubish_tx_data(server_key_id, &server_key))) } fn publish_server_key_generation_error(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> { self.send_contract_transaction("publish_server_key_generation_error", origin, server_key_id, ServerKeyGenerationService::is_response_required, - |_, _, service| Ok(ServerKeyGenerationService::prepare_error_tx_data(service, server_key_id))) + |_, _| Ok(ServerKeyGenerationService::prepare_error_tx_data(server_key_id))) } fn publish_retrieved_server_key(&self, origin: &Address, server_key_id: &ServerKeyId, server_key: Public, threshold: usize) -> Result<(), String> { let threshold = serialize_threshold(threshold)?; self.send_contract_transaction("publish_retrieved_server_key", origin, server_key_id, ServerKeyRetrievalService::is_response_required, - |_, _, service| Ok(ServerKeyRetrievalService::prepare_pubish_tx_data(service, server_key_id, server_key, threshold))) + |_, _| Ok(ServerKeyRetrievalService::prepare_pubish_tx_data(server_key_id, server_key, threshold))) } fn publish_server_key_retrieval_error(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> { self.send_contract_transaction("publish_server_key_retrieval_error", origin, server_key_id, ServerKeyRetrievalService::is_response_required, - |_, _, service| Ok(ServerKeyRetrievalService::prepare_error_tx_data(service, server_key_id))) + |_, _| Ok(ServerKeyRetrievalService::prepare_error_tx_data(server_key_id))) } fn publish_stored_document_key(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> { self.send_contract_transaction("publish_stored_document_key", origin, server_key_id, DocumentKeyStoreService::is_response_required, - |_, _, service| Ok(DocumentKeyStoreService::prepare_pubish_tx_data(service, server_key_id))) + |_, _| Ok(DocumentKeyStoreService::prepare_pubish_tx_data(server_key_id))) } fn publish_document_key_store_error(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> { self.send_contract_transaction("publish_document_key_store_error", origin, server_key_id, DocumentKeyStoreService::is_response_required, - |_, _, service| Ok(DocumentKeyStoreService::prepare_error_tx_data(service, server_key_id))) + |_, _| Ok(DocumentKeyStoreService::prepare_error_tx_data(server_key_id))) } fn publish_retrieved_document_key_common(&self, origin: &Address, server_key_id: &ServerKeyId, requester: &Address, common_point: Public, threshold: usize) -> Result<(), String> { let threshold = serialize_threshold(threshold)?; self.send_contract_transaction("publish_retrieved_document_key_common", origin, server_key_id, - |client, contract_address, contract, server_key_id, key_server| - DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, contract, server_key_id, requester, key_server), - |_, _, service| - Ok(DocumentKeyShadowRetrievalService::prepare_pubish_common_tx_data(service, server_key_id, requester, common_point, threshold)) + |client, contract_address, server_key_id, key_server| + DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, server_key_id, requester, key_server), + |_, _| + Ok(DocumentKeyShadowRetrievalService::prepare_pubish_common_tx_data(server_key_id, requester, common_point, threshold)) ) } fn publish_retrieved_document_key_personal(&self, origin: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result<(), String> { - self.send_contract_transaction("publish_retrieved_document_key_personal", origin, server_key_id, |_, _, _, _, _| true, - move |client, address, service| - DocumentKeyShadowRetrievalService::prepare_pubish_personal_tx_data(client, address, service, server_key_id, requester, participants, decrypted_secret, shadow) + self.send_contract_transaction("publish_retrieved_document_key_personal", origin, server_key_id, |_, _, _, _| true, + move |client, address| + DocumentKeyShadowRetrievalService::prepare_pubish_personal_tx_data(client, address, server_key_id, requester, participants, decrypted_secret, shadow) ) } fn publish_document_key_retrieval_error(&self, origin: &Address, server_key_id: &ServerKeyId, requester: &Address) -> Result<(), String> { self.send_contract_transaction("publish_document_key_retrieval_error", origin, server_key_id, - |client, contract_address, contract, server_key_id, key_server| - DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, contract, server_key_id, requester, key_server), - |_, _, service| - Ok(DocumentKeyShadowRetrievalService::prepare_error_tx_data(service, server_key_id, requester)) + |client, contract_address, server_key_id, key_server| + DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, server_key_id, requester, key_server), + |_, _| + Ok(DocumentKeyShadowRetrievalService::prepare_error_tx_data(server_key_id, requester)) ) } } @@ -449,318 +446,280 @@ pub fn mask_topics(mask: &ApiMask) -> Vec { impl ServerKeyGenerationService { /// Parse request log entry. - pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result { - let event = contract.events().server_key_generation_requested(); - match event.parse_log(raw_log) { + pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result { + match service::events::server_key_generation_requested::parse_log(raw_log) { Ok(l) => Ok(ServiceTask::GenerateServerKey(origin.clone(), l.server_key_id, l.author, parse_threshold(l.threshold)?)), Err(e) => Err(format!("{}", e)), } } /// Check if response from key server is required. - pub fn is_response_required(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { // we're checking confirmation in Latest block, because we're interested in latest contract state here - let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); - contract.functions() - .is_server_key_generation_response_required() - .call(*server_key_id, key_server.clone(), &do_call) - .unwrap_or(true) + let (encoded, decoder) = service::functions::is_server_key_generation_response_required::call(*server_key_id, *key_server); + match client.call_contract(BlockId::Latest, *contract_address, encoded) { + Err(_) => true, + Ok(data) => decoder.decode(&data).unwrap_or(true) + } } /// Prepare publish key transaction data. - pub fn prepare_pubish_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, server_key_public: &Public) -> Bytes { - contract.functions() - .server_key_generated() - .input(*server_key_id, server_key_public.to_vec()) + pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId, server_key_public: &Public) -> Bytes { + service::functions::server_key_generated::encode_input(*server_key_id, server_key_public.to_vec()) } /// Prepare error transaction data. - pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes { - contract.functions() - .server_key_generation_error() - .input(*server_key_id) + pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes { + service::functions::server_key_generation_error::encode_input(*server_key_id) } /// Read pending requests count. - fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result { - let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data); - let contract = service::Service::default(); - contract.functions() - .server_key_generation_requests_count() - .call(&do_call) - .map_err(|error| format!("{}", error)) + fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result { + let (encoded, decoder) = service::functions::server_key_generation_requests_count::call(); + decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, contract: &service::Service, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); - let do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d); - contract.functions() - .get_server_key_generation_request() - .call(index, &do_call) - .map_err(|error| format!("{}", error)) - .and_then(|(server_key_id, author, threshold)| parse_threshold(threshold) - .map(|threshold| (server_key_id, author, threshold))) - .and_then(|(server_key_id, author, threshold)| contract.functions() - .is_server_key_generation_response_required() - .call(server_key_id.clone(), self_address, &do_call) - .map(|not_confirmed| ( - not_confirmed, - ServiceTask::GenerateServerKey( - contract_address.clone(), - server_key_id, - author, - threshold, - ))) - .map_err(|error| format!("{}", error))) + + let (encoded, decoder) = service::functions::get_server_key_generation_request::call(index); + let (server_key_id, author, threshold) = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string())?; + let threshold = parse_threshold(threshold)?; + + let (encoded, decoder) = service::functions::is_server_key_generation_response_required::call(server_key_id, self_address); + let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string())?; + + let task = ServiceTask::GenerateServerKey( + contract_address.clone(), + server_key_id, + author, + threshold, + ); + + Ok((not_confirmed, task)) } } impl ServerKeyRetrievalService { /// Parse request log entry. - pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result { - let event = contract.events().server_key_retrieval_requested(); - match event.parse_log(raw_log) { - Ok(l) => Ok(ServiceTask::RetrieveServerKey(origin.clone(), l.server_key_id)), - Err(e) => Err(format!("{}", e)), + pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result { + match service::events::server_key_retrieval_requested::parse_log(raw_log) { + Ok(l) => Ok(ServiceTask::RetrieveServerKey(*origin, l.server_key_id)), + Err(e) => Err(e.to_string()) } } /// Check if response from key server is required. - pub fn is_response_required(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { // we're checking confirmation in Latest block, because we're interested in latest contract state here - let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); - contract.functions() - .is_server_key_retrieval_response_required() - .call(*server_key_id, key_server.clone(), &do_call) - .unwrap_or(true) + let (encoded, decoder) = service::functions::is_server_key_retrieval_response_required::call(*server_key_id, *key_server); + match client.call_contract(BlockId::Latest, *contract_address, encoded) { + Err(_) => true, + Ok(data) => decoder.decode(&data).unwrap_or(true) + } } /// Prepare publish key transaction data. - pub fn prepare_pubish_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, server_key_public: Public, threshold: U256) -> Bytes { - contract.functions() - .server_key_retrieved() - .input(*server_key_id, server_key_public.to_vec(), threshold) + pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId, server_key_public: Public, threshold: U256) -> Bytes { + service::functions::server_key_retrieved::encode_input(*server_key_id, server_key_public.to_vec(), threshold) } /// Prepare error transaction data. - pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes { - contract.functions() - .server_key_retrieval_error() - .input(*server_key_id) + pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes { + service::functions::server_key_retrieval_error::encode_input(*server_key_id) } /// Read pending requests count. - fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result { - let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data); - let contract = service::Service::default(); - contract.functions() - .server_key_retrieval_requests_count() - .call(&do_call) - .map_err(|error| format!("{}", error)) + fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result { + let (encoded, decoder) = service::functions::server_key_retrieval_requests_count::call(); + decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, contract: &service::Service, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); - let do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d); - contract.functions() - .get_server_key_retrieval_request() - .call(index, &do_call) - .map_err(|error| format!("{}", error)) - .and_then(|server_key_id| contract.functions() - .is_server_key_retrieval_response_required() - .call(server_key_id.clone(), self_address, &do_call) - .map(|not_confirmed| ( - not_confirmed, - ServiceTask::RetrieveServerKey( - contract_address.clone(), - server_key_id, - ))) - .map_err(|error| format!("{}", error))) + + let (encoded, decoder) = service::functions::get_server_key_retrieval_request::call(index); + let server_key_id = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string())?; + + let (encoded, decoder) = service::functions::is_server_key_retrieval_response_required::call(server_key_id, self_address); + let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string())?; + + let task = ServiceTask::RetrieveServerKey( + *contract_address, + server_key_id, + ); + + Ok((not_confirmed, task)) } } impl DocumentKeyStoreService { /// Parse request log entry. - pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result { - let event = contract.events().document_key_store_requested(); - match event.parse_log(raw_log) { + pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result { + match service::events::document_key_store_requested::parse_log(raw_log) { Ok(l) => Ok(ServiceTask::StoreDocumentKey(origin.clone(), l.server_key_id, l.author, (*l.common_point).into(), (*l.encrypted_point).into())), Err(e) => Err(format!("{}", e)), } } /// Check if response from key server is required. - pub fn is_response_required(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { // we're checking confirmation in Latest block, because we're interested in latest contract state here - let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); - contract.functions() - .is_document_key_store_response_required() - .call(*server_key_id, key_server.clone(), &do_call) - .unwrap_or(true) + let (encoded, decoder) = service::functions::is_document_key_store_response_required::call(*server_key_id, *key_server); + match client.call_contract(BlockId::Latest, *contract_address, encoded) { + Err(_) => true, + Ok(data) => decoder.decode(&data).unwrap_or(true) + } } /// Prepare publish key transaction data. - pub fn prepare_pubish_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes { - contract.functions() - .document_key_stored() - .input(*server_key_id) + pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId) -> Bytes { + service::functions::document_key_stored::encode_input(*server_key_id) } /// Prepare error transaction data. - pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes { - contract.functions() - .document_key_store_error() - .input(*server_key_id) + pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes { + service::functions::document_key_store_error::encode_input(*server_key_id) } /// Read pending requests count. - fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result { - let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data); - let contract = service::Service::default(); - contract.functions() - .document_key_store_requests_count() - .call(&do_call) - .map_err(|error| format!("{}", error)) + fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result { + let (encoded, decoder) = service::functions::document_key_store_requests_count::call(); + decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, contract: &service::Service, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); - let do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d); - contract.functions() - .get_document_key_store_request() - .call(index, &do_call) - .map_err(|error| format!("{}", error)) - .and_then(|(server_key_id, author, common_point, encrypted_point)| contract.functions() - .is_document_key_store_response_required() - .call(server_key_id.clone(), self_address, &do_call) - .map(|not_confirmed| ( - not_confirmed, - ServiceTask::StoreDocumentKey( - contract_address.clone(), - server_key_id, - author, - Public::from_slice(&common_point), - Public::from_slice(&encrypted_point), - ))) - .map_err(|error| format!("{}", error))) + let (encoded, decoder) = service::functions::get_document_key_store_request::call(index); + let (server_key_id, author, common_point, encrypted_point) = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string())?; + + let (encoded, decoder) = service::functions::is_document_key_store_response_required::call(server_key_id, self_address); + let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string())?; + + let task = ServiceTask::StoreDocumentKey( + *contract_address, + server_key_id, + author, + Public::from_slice(&common_point), + Public::from_slice(&encrypted_point), + ); + + Ok((not_confirmed, task)) } } impl DocumentKeyShadowRetrievalService { /// Parse common request log entry. - pub fn parse_common_request_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result { - let event = contract.events().document_key_common_retrieval_requested(); - match event.parse_log(raw_log) { + pub fn parse_common_request_log(origin: &Address, raw_log: RawLog) -> Result { + match service::events::document_key_common_retrieval_requested::parse_log(raw_log) { Ok(l) => Ok(ServiceTask::RetrieveShadowDocumentKeyCommon(origin.clone(), l.server_key_id, l.requester)), - Err(e) => Err(format!("{}", e)), + Err(e) => Err(e.to_string()) } } /// Parse personal request log entry. - pub fn parse_personal_request_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result { - let event = contract.events().document_key_personal_retrieval_requested(); - match event.parse_log(raw_log) { + pub fn parse_personal_request_log(origin: &Address, raw_log: RawLog) -> Result { + match service::events::document_key_personal_retrieval_requested::parse_log(raw_log) { Ok(l) => Ok(ServiceTask::RetrieveShadowDocumentKeyPersonal(origin.clone(), l.server_key_id, (*l.requester_public).into())), - Err(e) => Err(format!("{}", e)), + Err(e) => Err(e.to_string()) } } /// Check if response from key server is required. - pub fn is_response_required(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, requester: &Address, key_server: &Address) -> bool { + pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, key_server: &Address) -> bool { // we're checking confirmation in Latest block, because we're interested in latest contract state here - let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); - contract.functions() - .is_document_key_shadow_retrieval_response_required() - .call(*server_key_id, *requester, key_server.clone(), &do_call) - .unwrap_or(true) + let (encoded, decoder) = service::functions::is_document_key_shadow_retrieval_response_required::call(*server_key_id, *requester, *key_server); + match client.call_contract(BlockId::Latest, *contract_address, encoded) { + Err(_) => true, + Ok(data) => decoder.decode(&data).unwrap_or(true) + } } /// Prepare publish common key transaction data. - pub fn prepare_pubish_common_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, requester: &Address, common_point: Public, threshold: U256) -> Bytes { - contract.functions() - .document_key_common_retrieved() - .input(*server_key_id, *requester, common_point.to_vec(), threshold) + pub fn prepare_pubish_common_tx_data(server_key_id: &ServerKeyId, requester: &Address, common_point: Public, threshold: U256) -> Bytes { + service::functions::document_key_common_retrieved::encode_input(*server_key_id, *requester, common_point.to_vec(), threshold) } /// Prepare publish personal key transaction data. - pub fn prepare_pubish_personal_tx_data(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result { + pub fn prepare_pubish_personal_tx_data(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result { let mut participants_mask = U256::default(); for participant in participants { - let participant_index = Self::map_key_server_address(client, contract_address, contract, participant.clone()) + let participant_index = Self::map_key_server_address(client, contract_address, participant.clone()) .map_err(|e| format!("Error searching for {} participant: {}", participant, e))?; participants_mask = participants_mask | (U256::one() << participant_index); } - Ok(contract.functions() - .document_key_personal_retrieved() - .input(*server_key_id, *requester, participants_mask, decrypted_secret.to_vec(), shadow)) + Ok(service::functions::document_key_personal_retrieved::encode_input( + *server_key_id, *requester, participants_mask, decrypted_secret.to_vec(), shadow + )) } /// Prepare error transaction data. - pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, requester: &Address) -> Bytes { - contract.functions() - .document_key_shadow_retrieval_error() - .input(*server_key_id, *requester) + pub fn prepare_error_tx_data(server_key_id: &ServerKeyId, requester: &Address) -> Bytes { + service::functions::document_key_shadow_retrieval_error::encode_input(*server_key_id, *requester) } /// Read pending requests count. - fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result { - let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data); - let contract = service::Service::default(); - contract.functions() - .document_key_shadow_retrieval_requests_count() - .call(&do_call) - .map_err(|error| format!("{}", error)) + fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result { + let (encoded, decoder) = service::functions::document_key_shadow_retrieval_requests_count::call(); + decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, contract: &service::Service, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); - let do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d); - contract.functions() - .get_document_key_shadow_retrieval_request() - .call(index, &do_call) - .map_err(|error| format!("{}", error)) - .and_then(|(server_key_id, requester, is_common_retrieval_completed)| { - let requester = Public::from_slice(&requester); - contract.functions() - .is_document_key_shadow_retrieval_response_required() - .call(server_key_id.clone(), public_to_address(&requester), self_address, &do_call) - .map(|not_confirmed| ( - not_confirmed, - match is_common_retrieval_completed { - true => ServiceTask::RetrieveShadowDocumentKeyPersonal( - contract_address.clone(), - server_key_id, - requester, - ), - false => ServiceTask::RetrieveShadowDocumentKeyCommon( - contract_address.clone(), - server_key_id, - public_to_address(&requester), - ), - }, - )) - .map_err(|error| format!("{}", error)) - }) + + let (encoded, decoder) = service::functions::get_document_key_shadow_retrieval_request::call(index); + let (server_key_id, requester, is_common_retrieval_completed) = + decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string())?; + + let requester = Public::from_slice(&requester); + let (encoded, decoder) = service::functions::is_document_key_shadow_retrieval_response_required::call(server_key_id, public_to_address(&requester), self_address); + let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) + .map_err(|e| e.to_string())?; + + let task = match is_common_retrieval_completed { + true => ServiceTask::RetrieveShadowDocumentKeyPersonal( + *contract_address, + server_key_id, + requester, + ), + false => ServiceTask::RetrieveShadowDocumentKeyCommon( + *contract_address, + server_key_id, + public_to_address(&requester), + ), + }; + + Ok((not_confirmed, task)) } /// Map from key server address to key server index. - fn map_key_server_address(client: &Client, contract_address: &Address, contract: &service::Service, key_server: Address) -> Result { + fn map_key_server_address(client: &Client, contract_address: &Address, key_server: Address) -> Result { // we're checking confirmation in Latest block, because tx ,ust be appended to the latest state - let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); - contract.functions() - .require_key_server() - .call(key_server, &do_call) - .map_err(|e| format!("{}", e)) - .and_then(|index| if index > ::std::u8::MAX.into() { - Err(format!("key server index is too big: {}", index)) - } else { - let index: u32 = index.into(); - Ok(index as u8) - }) + let (encoded, decoder) = service::functions::require_key_server::call(key_server); + let index = decoder.decode(&client.call_contract(BlockId::Latest, *contract_address, encoded)?) + .map_err(|e| e.to_string())?; + + if index > u8::max_value().into() { + Err(format!("key server index is too big: {}", index)) + } else { + let index: u32 = index.into(); + Ok(index as u8) + } } } diff --git a/updater/Cargo.toml b/updater/Cargo.toml index 10337cfc0..00cb0071c 100644 --- a/updater/Cargo.toml +++ b/updater/Cargo.toml @@ -9,9 +9,9 @@ authors = ["Parity Technologies "] keccak-hash = "0.1" lazy_static = "1.0" log = "0.4" -ethabi = "5.1.2" -ethabi-derive = "5.1.3" -ethabi-contract = "5.1.1" +ethabi = "6.0" +ethabi-derive = "6.0" +ethabi-contract = "6.0" target_info = "0.1" semver = "0.9" ethcore = { path = "../ethcore" } diff --git a/updater/src/updater.rs b/updater/src/updater.rs index 16e71f46f..1e939b97e 100644 --- a/updater/src/updater.rs +++ b/updater/src/updater.rs @@ -37,8 +37,9 @@ use sync::{SyncProvider}; use types::{ReleaseInfo, OperationsInfo, CapState, VersionInfo, ReleaseTrack}; use version; use semver::Version; +use ethabi::FunctionOutputDecoder; -use_contract!(operations_contract, "Operations", "res/operations.json"); +use_contract!(operations, "res/operations.json"); /// Filter for releases. #[derive(Debug, Eq, PartialEq, Clone)] @@ -192,41 +193,35 @@ pub trait OperationsClient: Send + Sync + 'static { /// `OperationsClient` that delegates calls to the operations contract. pub struct OperationsContractClient { - operations_contract: operations_contract::Operations, client: Weak, } impl OperationsContractClient { - fn new( - operations_contract: operations_contract::Operations, - client: Weak, - ) -> OperationsContractClient { - OperationsContractClient { operations_contract, client } + fn new(client: Weak) -> Self { + OperationsContractClient { + client + } } /// Get the hash of the latest release for the given track fn latest_hash(&self, track: ReleaseTrack, do_call: &F) -> Result where F: Fn(Vec) -> Result, String> { - self.operations_contract.functions() - .latest_in_track() - .call(*CLIENT_ID_HASH, u8::from(track), do_call) - .map_err(|e| format!("{:?}", e)) + let (data, decoder) = operations::functions::latest_in_track::call(*CLIENT_ID_HASH, u8::from(track)); + let value = do_call(data)?; + decoder.decode(&value).map_err(|e| e.to_string()) } /// Get release info for the given release fn release_info(&self, release_id: H256, do_call: &F) -> Result where F: Fn(Vec) -> Result, String> { - let (fork, track, semver, is_critical) = self.operations_contract.functions() - .release() - .call(*CLIENT_ID_HASH, release_id, &do_call) - .map_err(|e| format!("{:?}", e))?; + let (data, decoder) = operations::functions::release::call(*CLIENT_ID_HASH, release_id); + + let (fork, track, semver, is_critical) = decoder.decode(&do_call(data)?).map_err(|e| e.to_string())?; let (fork, track, semver) = (fork.low_u64(), track.low_u32(), semver.low_u32()); - let latest_binary = self.operations_contract.functions() - .checksum() - .call(*CLIENT_ID_HASH, release_id, *PLATFORM_ID_HASH, &do_call) - .map_err(|e| format!("{:?}", e))?; + let (data, decoder) = operations::functions::checksum::call(*CLIENT_ID_HASH, release_id, *PLATFORM_ID_HASH); + let latest_binary = decoder.decode(&do_call(data)?).map_err(|e| e.to_string())?; Ok(ReleaseInfo { version: VersionInfo::from_raw(semver, track as u8, release_id.into()), @@ -250,9 +245,9 @@ impl OperationsClient for OperationsContractClient { trace!(target: "updater", "Looking up this_fork for our release: {}/{:?}", CLIENT_ID, this.hash); // get the fork number of this release - let this_fork = self.operations_contract.functions() - .release() - .call(*CLIENT_ID_HASH, this.hash, &do_call) + let (data, decoder) = operations::functions::release::call(*CLIENT_ID_HASH, this.hash); + let this_fork = do_call(data) + .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) .ok() .and_then(|(fork, track, _, _)| { let this_track: ReleaseTrack = (track.low_u64() as u8).into(); @@ -282,10 +277,10 @@ impl OperationsClient for OperationsContractClient { in_minor = Some(self.release_info(latest_in_track, &do_call)?); } - let fork = self.operations_contract.functions() - .latest_fork() - .call(&do_call) - .map_err(|e| format!("{:?}", e))?.low_u64(); + let (data, decoder) = operations::functions::latest_fork::call(); + let fork = do_call(data) + .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))? + .low_u64(); Ok(OperationsInfo { fork, @@ -299,9 +294,7 @@ impl OperationsClient for OperationsContractClient { let client = self.client.upgrade()?; let address = client.registry_address("operations".into(), BlockId::Latest)?; - let event = self.operations_contract.events().release_added(); - - let topics = event.create_filter(Some(*CLIENT_ID_HASH), Some(release.fork.into()), Some(release.is_critical)); + let topics = operations::events::release_added::filter(Some(*CLIENT_ID_HASH), Some(release.fork.into()), Some(release.is_critical)); let topics = vec![topics.topic0, topics.topic1, topics.topic2, topics.topic3]; let topics = topics.into_iter().map(Into::into).map(Some).collect(); @@ -317,7 +310,7 @@ impl OperationsClient for OperationsContractClient { .unwrap_or_default() .iter() .filter_map(|log| { - let event = event.parse_log((log.topics.clone(), log.data.clone()).into()).ok()?; + let event = operations::events::release_added::parse_log((log.topics.clone(), log.data.clone()).into()).ok()?; let version_info = VersionInfo::from_raw(event.semver.low_u32(), event.track.low_u32() as u8, event.release.into()); if version_info == release.version { Some(log.block_number) @@ -375,7 +368,6 @@ impl Updater { sync: Some(sync.clone()), fetcher, operations_client: OperationsContractClient::new( - operations_contract::Operations::default(), client.clone()), exit_handler: Mutex::new(None), this: if cfg!(feature = "test-updater") {