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
This commit is contained in:
Marek Kotewicz 2018-09-13 11:04:39 +02:00 committed by GitHub
parent 7dfb5ff5bd
commit ef4a61c769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 458 additions and 575 deletions

89
Cargo.lock generated
View File

@ -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)" = "<none>"
"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"

View File

@ -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" }

View File

@ -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]

View File

@ -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<BlockChainClient>,
contract_address: Address,
permission_cache: Mutex<LruCache<(H256, NodeId), bool>>,
@ -63,7 +63,6 @@ impl NodeFilter {
/// Create a new instance. Accepts a contract address.
pub fn new(client: Weak<BlockChainClient>, 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

View File

@ -7,9 +7,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
[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"

View File

@ -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<Bytes, Error> {
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<Bytes, Error> {
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<U256, Error> {
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<H256, H256> {
@ -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::<Vec<Address>>(), code, storage)
private_contract::constructor(constructor_code, validators.iter().map(|a| *a).collect::<Vec<Address>>(), 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<Vec<Address>, 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())
}
}

View File

@ -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<Option<Box<FnMut(Option<Mode>) + 'static + Send>>>,
/// Link to a registry object useful for looking up names
registrar: registry::Registry,
registrar_address: Option<Address>,
/// 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<Address> {
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)
}
}
}

View File

@ -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<trace::RewardType> 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<Vec<(Address, U256)>, 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)),
);

View File

@ -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<Option<Weak<EngineClient>>>, // 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),

View File

@ -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<EthereumMachine> for StateProof {
fn generate_proof(&self, caller: &Call) -> Result<Vec<u8>, 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<EthereumMachine> 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<EthereumMachine> for StateProof {
pub struct ValidatorSafeContract {
contract_address: Address,
validators: RwLock<MemoryLruCache<H256, SimpleList>>,
provider: validator_set::ValidatorSet,
client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove
}
@ -89,7 +88,7 @@ fn encode_first_proof(header: &Header, state_items: &[Vec<u8>]) -> 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<Vec<Address>, 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<DBValue>), ::error::Error> {
@ -167,32 +166,26 @@ fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<Receipt>), ::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<Vec<u8>, String> {
fn prove_initial(contract_address: Address, header: &Header, caller: &Call) -> Result<Vec<u8>, 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<SimpleList> {
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<Vec<u8>, 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<Vec<u8>> {
@ -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",

View File

@ -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())
}
}

View File

@ -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<AccountProvider>, 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<AccountProvider>, 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,

View File

@ -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<LruCache<(H256, Address), u32>>,
@ -55,8 +54,6 @@ impl TransactionFilter {
pub fn from_params(params: &CommonParams) -> Option<TransactionFilter> {
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)
}
};

View File

@ -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"

View File

@ -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<RegistrarClient<Call=Asynchronous>>,
}
impl URLHintContract {
/// Creates new `URLHintContract`
pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> Self {
pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> 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<URLHintR
impl URLHint for URLHintContract {
fn resolve(&self, id: H256) -> Box<Future<Item = Option<URLHintResult>, 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 {

View File

@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[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"

View File

@ -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<Bytes, String>;
/// 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<RegistrarClient<Call=Asynchronous>>,
}
@ -38,7 +37,6 @@ impl Registrar {
/// Registrar constructor
pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> 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)
}

View File

@ -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"] }

View File

@ -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<Address>,
/// 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())),

View File

@ -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<ContractAddress>,
/// Current contract address.
contract_address: Option<Address>,
/// Contract interface.
contract: key_server::KeyServerSet,
/// Is auto-migrate enabled?
auto_migrate_enabled: bool,
/// Current contract state.
@ -169,66 +168,60 @@ trait KeyServerSubset<F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> {
fn read_address(&self, address: Address, f: &F) -> Result<String, String>;
}
#[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 <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for CurrentKeyServerSubset {
fn read_list(&self, f: &F) -> Result<Vec<Address>, 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<Bytes, String> {
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<String, String> {
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 <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for MigrationKeyServerSubset {
fn read_list(&self, f: &F) -> Result<Vec<Address>, 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<Bytes, String> {
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<String, String> {
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 <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for NewKeyServerSubset {
fn read_list(&self, f: &F) -> Result<Vec<Address>, 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<Bytes, String> {
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<String, String> {
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,
};

View File

@ -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<ServiceData>,
}
@ -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<C, P>(&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<Bytes, String> {
where C: FnOnce(&Client, &Address, &ServerKeyId, &Address) -> bool,
P: FnOnce(&Client, &Address) -> Result<Bytes, String> {
// 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<U256, String>,
R: 'static + Fn(&NodeKeyPair, &Client, &Address, &service::Service, &BlockId, U256) -> Result<(bool, ServiceTask), String>
C: 'static + Fn(&Client, &Address, &BlockId) -> Result<U256, String>,
R: 'static + Fn(&NodeKeyPair, &Client, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String>
>(&self, client: Arc<Client>, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box<Iterator<Item=(bool, ServiceTask)>> {
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<H256> {
impl ServerKeyGenerationService {
/// Parse request log entry.
pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> {
let event = contract.events().server_key_generation_requested();
match event.parse_log(raw_log) {
pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
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<U256, String> {
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<U256, String> {
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<ServiceTask, String> {
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<ServiceTask, String> {
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<U256, String> {
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<U256, String> {
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<ServiceTask, String> {
let event = contract.events().document_key_store_requested();
match event.parse_log(raw_log) {
pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
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<U256, String> {
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<U256, String> {
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<ServiceTask, String> {
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<ServiceTask, String> {
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<ServiceTask, String> {
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<ServiceTask, String> {
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<Bytes, String> {
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<Bytes, String> {
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<U256, String> {
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<U256, String> {
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<u8, String> {
fn map_key_server_address(client: &Client, contract_address: &Address, key_server: Address) -> Result<u8, String> {
// 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)
}
}
}

View File

@ -9,9 +9,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
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" }

View File

@ -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<BlockChainClient>,
}
impl OperationsContractClient {
fn new(
operations_contract: operations_contract::Operations,
client: Weak<BlockChainClient>,
) -> OperationsContractClient {
OperationsContractClient { operations_contract, client }
fn new(client: Weak<BlockChainClient>) -> Self {
OperationsContractClient {
client
}
}
/// Get the hash of the latest release for the given track
fn latest_hash<F>(&self, track: ReleaseTrack, do_call: &F) -> Result<H256, String>
where F: Fn(Vec<u8>) -> Result<Vec<u8>, 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<F>(&self, release_id: H256, do_call: &F) -> Result<ReleaseInfo, String>
where F: Fn(Vec<u8>) -> Result<Vec<u8>, 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") {