From e540dcf9c2e2935f845d9aafe221debe128a9419 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 1 Nov 2019 14:08:20 +0100 Subject: [PATCH 01/16] Move all client usages into trusted_client --- secret-store/src/acl_storage.rs | 31 ++--- secret-store/src/helpers.rs | 5 +- secret-store/src/key_server_set.rs | 72 +++++------ secret-store/src/lib.rs | 2 +- secret-store/src/listener/service_contract.rs | 94 +++++++------- .../src/listener/service_contract_listener.rs | 15 +-- secret-store/src/trusted_client.rs | 115 ++++++++++++++++-- 7 files changed, 193 insertions(+), 141 deletions(-) diff --git a/secret-store/src/acl_storage.rs b/secret-store/src/acl_storage.rs index d3f8bddde96..30687761e3e 100644 --- a/secret-store/src/acl_storage.rs +++ b/secret-store/src/acl_storage.rs @@ -17,15 +17,12 @@ use std::sync::Arc; use std::collections::{HashMap, HashSet}; use common_types::{ - chain_notify::NewBlocks, ids::BlockId }; use parking_lot::{Mutex, RwLock}; -use call_contract::CallContract; -use client_traits::ChainNotify; use ethereum_types::Address; use ethabi::FunctionOutputDecoder; -use trusted_client::TrustedClient; +use trusted_client::{TrustedClient, NewBlocksNotify}; use types::{Error, ServerKeyId, ContractAddress}; use_contract!(acl_storage, "res/acl_storage.json"); @@ -47,7 +44,7 @@ pub struct OnChainAclStorage { /// Cached on-chain ACL storage contract. struct CachedContract { /// Blockchain client. - client: TrustedClient, + client: Arc, /// Contract address source. address_source: ContractAddress, /// Current contract address. @@ -61,14 +58,11 @@ pub struct DummyAclStorage { } impl OnChainAclStorage { - pub fn new(trusted_client: TrustedClient, address_source: ContractAddress) -> Result, Error> { - let client = trusted_client.get_untrusted(); + pub fn new(trusted_client: Arc, address_source: ContractAddress) -> Result, Error> { let acl_storage = Arc::new(OnChainAclStorage { - contract: Mutex::new(CachedContract::new(trusted_client, address_source)), + contract: Mutex::new(CachedContract::new(trusted_client.clone(), address_source)), }); - client - .ok_or_else(|| Error::Internal("Constructing OnChainAclStorage without active Client".into()))? - .add_notify(acl_storage.clone()); + trusted_client.add_listener(acl_storage.clone()); Ok(acl_storage) } } @@ -79,17 +73,14 @@ impl AclStorage for OnChainAclStorage { } } -impl ChainNotify for OnChainAclStorage { - fn new_blocks(&self, new_blocks: NewBlocks) { - if new_blocks.has_more_blocks_to_import { return } - if !new_blocks.route.enacted().is_empty() || !new_blocks.route.retracted().is_empty() { - self.contract.lock().update_contract_address() - } +impl NewBlocksNotify for OnChainAclStorage { + fn new_blocks(&self, _new_enacted_len: usize) { + self.contract.lock().update_contract_address() } } impl CachedContract { - pub fn new(client: TrustedClient, address_source: ContractAddress) -> Self { + pub fn new(client: Arc, address_source: ContractAddress) -> Self { let mut contract = CachedContract { client, address_source, @@ -113,12 +104,12 @@ impl CachedContract { } pub fn check(&mut self, requester: Address, document: &ServerKeyId) -> Result { - if let Some(client) = self.client.get() { + if self.client.is_trusted() { // call contract to check accesss match self.contract_address { Some(contract_address) => { let (encoded, decoder) = acl_storage::functions::check_permissions::call(requester, document.clone()); - let d = client.call_contract(BlockId::Latest, contract_address, encoded) + let d = self.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()))) diff --git a/secret-store/src/helpers.rs b/secret-store/src/helpers.rs index cdb235ac91c..ad668efad44 100644 --- a/secret-store/src/helpers.rs +++ b/secret-store/src/helpers.rs @@ -14,8 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use ethcore::client::Client; -use client_traits::BlockChainClient; +use trusted_client::TrustedClient; use common_types::ids::BlockId; use ethereum_types::H256; @@ -24,7 +23,7 @@ use ethereum_types::H256; pub const REQUEST_CONFIRMATIONS_REQUIRED: u64 = 3; /// Get hash of the last block with at least n confirmations. -pub fn get_confirmed_block_hash(client: &Client, confirmations: u64) -> Option { +pub fn get_confirmed_block_hash(client: &TrustedClient, confirmations: u64) -> Option { client.block_number(BlockId::Latest) .map(|b| b.saturating_sub(confirmations)) .and_then(|b| client.block_hash(BlockId::Number(b))) diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index 4b09e69cab1..3335526f050 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -18,19 +18,15 @@ use std::sync::Arc; use std::net::SocketAddr; use std::collections::{BTreeMap, HashSet}; use parking_lot::Mutex; -use call_contract::CallContract; use ethabi::FunctionOutputDecoder; -use ethcore::client::Client; -use client_traits::{BlockChainClient, ChainNotify}; use common_types::{ - chain_notify::NewBlocks, ids::BlockId, }; use ethereum_types::{H256, Address}; use crypto::publickey::public_to_address; use bytes::Bytes; use types::{Error, Public, NodeAddress, NodeId}; -use trusted_client::TrustedClient; +use trusted_client::{TrustedClient, NewBlocksNotify}; use {NodeKeyPair, ContractAddress}; use_contract!(key_server, "res/key_server_set.json"); @@ -105,7 +101,7 @@ struct PreviousMigrationTransaction { /// Cached on-chain Key Server set contract. struct CachedContract { /// Blockchain client. - client: TrustedClient, + client: Arc, /// Contract address source. contract_address_source: Option, /// Current contract address. @@ -125,14 +121,11 @@ struct CachedContract { } impl OnChainKeyServerSet { - pub fn new(trusted_client: TrustedClient, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { - let client = trusted_client.get_untrusted(); + pub fn new(trusted_client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { let key_server_set = Arc::new(OnChainKeyServerSet { - contract: Mutex::new(CachedContract::new(trusted_client, contract_address_source, self_key_pair, auto_migrate_enabled, key_servers)?), + contract: Mutex::new(CachedContract::new(trusted_client.clone(), contract_address_source, self_key_pair, auto_migrate_enabled, key_servers)?), }); - client - .ok_or_else(|| Error::Internal("Constructing OnChainKeyServerSet without active Client".into()))? - .add_notify(key_server_set.clone()); + trusted_client.add_listener(key_server_set.clone()); Ok(key_server_set) } } @@ -155,14 +148,9 @@ impl KeyServerSet for OnChainKeyServerSet { } } -impl ChainNotify for OnChainKeyServerSet { - fn new_blocks(&self, new_blocks: NewBlocks) { - if new_blocks.has_more_blocks_to_import { return } - let (enacted, retracted) = new_blocks.route.into_enacted_retracted(); - - if !enacted.is_empty() || !retracted.is_empty() { - self.contract.lock().update(enacted, retracted) - } +impl NewBlocksNotify for OnChainKeyServerSet { + fn new_blocks(&self, _new_enacted_len: usize) { + self.contract.lock().update() } } @@ -232,7 +220,7 @@ impl ) -> Result, String>> KeyServerSubset for NewKeySe } impl CachedContract { - pub fn new(client: TrustedClient, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { + pub fn new(client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { let server_set = match contract_address_source.is_none() { true => key_servers.into_iter() .map(|(p, addr)| { @@ -279,21 +267,19 @@ impl CachedContract { } } - pub fn update(&mut self, enacted: Vec, retracted: Vec) { + pub fn update(&mut self) { // no need to update when servers set is hardcoded if self.contract_address_source.is_none() { return; } - if let Some(client) = self.client.get() { - // read new snapshot from reqistry (if something has chnaged) - if !enacted.is_empty() || !retracted.is_empty() { - self.update_contract_address(); - self.read_from_registry(&*client); - } + if self.client.is_trusted() { + // read new snapshot from reqistry + self.update_contract_address(); + self.read_from_registry(); // update number of confirmations (if there's future new set) - self.update_number_of_confirmations_if_required(&*client); + self.update_number_of_confirmations_if_required(); } } @@ -307,9 +293,9 @@ impl CachedContract { fn start_migration(&mut self, migration_id: H256) { // trust is not needed here, because it is the reaction to the read of the trusted client - if let (Some(client), Some(contract_address)) = (self.client.get_untrusted(), self.contract_address.as_ref()) { + if let Some(contract_address) = self.contract_address.as_ref() { // check if we need to send start migration transaction - if !update_last_transaction_block(&*client, &migration_id, &mut self.start_migration_tx) { + if !update_last_transaction_block(&*self.client, &migration_id, &mut self.start_migration_tx) { return; } @@ -328,9 +314,9 @@ impl CachedContract { fn confirm_migration(&mut self, migration_id: H256) { // trust is not needed here, because we have already completed the action - if let (Some(client), Some(contract_address)) = (self.client.get(), self.contract_address) { + if let (true, Some(contract_address)) = (self.client.is_trusted(), self.contract_address) { // check if we need to send start migration transaction - if !update_last_transaction_block(&*client, &migration_id, &mut self.confirm_migration_tx) { + if !update_last_transaction_block(&*self.client, &migration_id, &mut self.confirm_migration_tx) { return; } @@ -347,7 +333,7 @@ impl CachedContract { } } - fn read_from_registry(&mut self, client: &Client) { + fn read_from_registry(&mut self) { let contract_address = match self.contract_address { Some(contract_address) => contract_address, None => { @@ -361,7 +347,7 @@ impl CachedContract { }, }; - let do_call = |data| client.call_contract(BlockId::Latest, contract_address, data); + let do_call = |data| self.client.call_contract(BlockId::Latest, contract_address, data); let current_set = Self::read_key_server_set(CurrentKeyServerSubset, &do_call); @@ -434,7 +420,7 @@ impl CachedContract { // we might want to adjust new_set if auto migration is enabled if self.auto_migrate_enabled { - let block = client.block_hash(BlockId::Latest).unwrap_or_default(); + let block = self.client.block_hash(BlockId::Latest).unwrap_or_default(); update_future_set(&mut self.future_new_set, &mut new_snapshot, block); } @@ -474,14 +460,14 @@ impl CachedContract { key_servers } - fn update_number_of_confirmations_if_required(&mut self, client: &dyn BlockChainClient) { + fn update_number_of_confirmations_if_required(&mut self) { if !self.auto_migrate_enabled { return; } - + let client = &*self.client; update_number_of_confirmations( - &|| latest_block_hash(&*client), - &|block| block_confirmations(&*client, block), + &|| latest_block_hash(client), + &|block| block_confirmations(client, block), &mut self.future_new_set, &mut self.snapshot); } } @@ -549,7 +535,7 @@ fn update_number_of_confirmations H256, F2: Fn(H256) -> Option> snapshot.new_set = future_new_set.new_set; } -fn update_last_transaction_block(client: &Client, migration_id: &H256, previous_transaction: &mut Option) -> bool { +fn update_last_transaction_block(client: &TrustedClient, migration_id: &H256, previous_transaction: &mut Option) -> bool { let last_block = client.block_number(BlockId::Latest).unwrap_or_default(); match previous_transaction.as_ref() { // no previous transaction => send immediately @@ -577,11 +563,11 @@ fn update_last_transaction_block(client: &Client, migration_id: &H256, previous_ true } -fn latest_block_hash(client: &dyn BlockChainClient) -> H256 { +fn latest_block_hash(client: &TrustedClient) -> H256 { client.block_hash(BlockId::Latest).unwrap_or_default() } -fn block_confirmations(client: &dyn BlockChainClient, block: H256) -> Option { +fn block_confirmations(client: &TrustedClient, block: H256) -> Option { client.block_number(BlockId::Hash(block)) .and_then(|block| client.block_number(BlockId::Latest).map(|last_block| (block, last_block))) .map(|(block, last_block)| last_block - block) diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index ebf0228e9d4..1dd120bb303 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -186,7 +186,7 @@ pub fn start(client: Arc, sync: Arc, miner: Arc key_storage: key_storage, } )?; - client.add_notify(listener.clone()); + trusted_client.add_listener(listener.clone()); listener }), None => None, diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index 78acdaf582e..2d24f4e9efe 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -19,9 +19,6 @@ use parking_lot::RwLock; use common_types::filter::Filter; use ethabi::RawLog; use ethabi::FunctionOutputDecoder; -use call_contract::CallContract; -use ethcore::client::Client; -use client_traits::BlockChainClient; use common_types::ids::BlockId; use crypto::publickey::{Public, public_to_address}; use hash::keccak; @@ -98,7 +95,7 @@ pub struct OnChainServiceContract { /// Requests mask. mask: ApiMask, /// Blockchain client. - client: TrustedClient, + client: Arc, /// This node key pair. self_key_pair: Arc, /// Contract registry name (if any). @@ -138,7 +135,7 @@ struct DocumentKeyShadowRetrievalService; impl OnChainServiceContract { /// Create new on-chain service contract. - pub fn new(mask: ApiMask, client: TrustedClient, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { + pub fn new(mask: ApiMask, client: Arc, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { let contract = OnChainServiceContract { mask: mask, client: client, @@ -157,24 +154,23 @@ impl OnChainServiceContract { /// Send transaction to the service contract. fn send_contract_transaction(&self, tx_name: &str, origin: &Address, server_key_id: &ServerKeyId, is_response_required: C, prepare_tx: P) -> Result<(), String> - where C: FnOnce(&Client, &Address, &ServerKeyId, &Address) -> bool, - P: FnOnce(&Client, &Address) -> Result { + where C: FnOnce(&TrustedClient, &Address, &ServerKeyId, &Address) -> bool, + P: FnOnce(&TrustedClient, &Address) -> Result { // only publish if contract address is set && client is online - let client = match self.client.get() { - Some(client) => client, - None => return Err("trusted client is required to publish key".into()), - }; + if !self.client.is_trusted() { + return Err("trusted client is required to publish key".into()) + } // only publish key if contract waits for publication // 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, server_key_id, &self_address) { + if !is_response_required(&*self.client, origin, server_key_id, &self_address) { return Ok(()); } // prepare transaction data - let transaction_data = prepare_tx(&*client, origin)?; + let transaction_data = prepare_tx(&*self.client, origin)?; // send transaction self.client.transact_contract( @@ -190,9 +186,9 @@ impl OnChainServiceContract { /// Create task-specific pending requests iterator. fn create_pending_requests_iterator< - C: 'static + Fn(&Client, &Address, &BlockId) -> Result, - R: 'static + Fn(&dyn NodeKeyPair, &Client, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> - >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { + C: 'static + Fn(&TrustedClient, &Address, &BlockId) -> Result, + R: 'static + Fn(&dyn NodeKeyPair, &TrustedClient, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> + >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { get_count(&*client, contract_address, block) .map(|count| { let client = client.clone(); @@ -237,18 +233,15 @@ impl OnChainServiceContract { impl ServiceContract for OnChainServiceContract { fn update(&self) -> bool { - self.update_contract_address() && self.client.get().is_some() + self.update_contract_address() && self.client.is_trusted() } fn read_logs(&self) -> Box> { - let client = match self.client.get() { - Some(client) => client, - None => { - warn!(target: "secretstore", "{}: client is offline during read_logs call", - self.self_key_pair.public()); - return Box::new(::std::iter::empty()); - }, - }; + if !self.client.is_trusted() { + warn!(target: "secretstore", "{}: client is offline during read_logs call", + self.self_key_pair.public()); + return Box::new(::std::iter::empty()); + } // prepare range of blocks to read logs from let (address, first_block, last_block) = { @@ -257,11 +250,11 @@ impl ServiceContract for OnChainServiceContract { Some(address) => address, None => return Box::new(::std::iter::empty()), // no contract installed }; - let confirmed_block = match get_confirmed_block_hash(&*client, REQUEST_CONFIRMATIONS_REQUIRED) { + let confirmed_block = match get_confirmed_block_hash(&*self.client, REQUEST_CONFIRMATIONS_REQUIRED) { Some(confirmed_block) => confirmed_block, None => return Box::new(::std::iter::empty()), // no block with enough confirmations }; - let first_block = match data.last_log_block.take().and_then(|b| client.tree_route(&b, &confirmed_block)) { + let first_block = match data.last_log_block.take().and_then(|b| self.client.tree_route(&b, &confirmed_block)) { // if we have a route from last_log_block to confirmed_block => search for logs on this route // // potentially this could lead us to reading same logs twice when reorganizing to the fork, which @@ -277,7 +270,7 @@ impl ServiceContract for OnChainServiceContract { }; // read server key generation requests - let request_logs = client.logs(Filter { + let request_logs = self.client.logs(Filter { from_block: BlockId::Hash(first_block), to_block: BlockId::Hash(last_block), address: Some(vec![address]), @@ -311,39 +304,38 @@ impl ServiceContract for OnChainServiceContract { } fn read_pending_requests(&self) -> Box> { - let client = match self.client.get() { - Some(client) => client, - None => return Box::new(::std::iter::empty()), - }; + if !self.client.is_trusted() { + return Box::new(::std::iter::empty()) + } // we only need requests that are here for more than REQUEST_CONFIRMATIONS_REQUIRED blocks // => we're reading from Latest - (REQUEST_CONFIRMATIONS_REQUIRED + 1) block let data = self.data.read(); match data.contract_address { None => Box::new(::std::iter::empty()), - Some(contract_address) => get_confirmed_block_hash(&*client, REQUEST_CONFIRMATIONS_REQUIRED + 1) + Some(contract_address) => get_confirmed_block_hash(&*self.client, REQUEST_CONFIRMATIONS_REQUIRED + 1) .map(|b| { let block = BlockId::Hash(b); let iter = match self.mask.server_key_generation_requests { - true => Box::new(self.create_pending_requests_iterator(client.clone(), &contract_address, &block, + true => Box::new(self.create_pending_requests_iterator(self.client.clone(), &contract_address, &block, &ServerKeyGenerationService::read_pending_requests_count, &ServerKeyGenerationService::read_pending_request)) as Box>, false => Box::new(::std::iter::empty()), }; let iter = match self.mask.server_key_retrieval_requests { - true => Box::new(iter.chain(self.create_pending_requests_iterator(client.clone(), &contract_address, &block, + true => Box::new(iter.chain(self.create_pending_requests_iterator(self.client.clone(), &contract_address, &block, &ServerKeyRetrievalService::read_pending_requests_count, &ServerKeyRetrievalService::read_pending_request))), false => iter, }; let iter = match self.mask.document_key_store_requests { - true => Box::new(iter.chain(self.create_pending_requests_iterator(client.clone(), &contract_address, &block, + true => Box::new(iter.chain(self.create_pending_requests_iterator(self.client.clone(), &contract_address, &block, &DocumentKeyStoreService::read_pending_requests_count, &DocumentKeyStoreService::read_pending_request))), false => iter, }; let iter = match self.mask.document_key_shadow_retrieval_requests { - true => Box::new(iter.chain(self.create_pending_requests_iterator(client, &contract_address, &block, + true => Box::new(iter.chain(self.create_pending_requests_iterator(self.client.clone(), &contract_address, &block, &DocumentKeyShadowRetrievalService::read_pending_requests_count, &DocumentKeyShadowRetrievalService::read_pending_request))), false => iter @@ -457,7 +449,7 @@ impl ServerKeyGenerationService { } /// Check if response from key server is required. - pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &TrustedClient, 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 (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) { @@ -477,14 +469,14 @@ impl ServerKeyGenerationService { } /// Read pending requests count. - fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &TrustedClient, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::server_key_generation_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_generation_request::call(index); @@ -517,7 +509,7 @@ impl ServerKeyRetrievalService { } /// Check if response from key server is required. - pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &TrustedClient, 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 (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) { @@ -537,14 +529,14 @@ impl ServerKeyRetrievalService { } /// Read pending requests count. - fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &TrustedClient, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::server_key_retrieval_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_retrieval_request::call(index); @@ -580,7 +572,7 @@ impl DocumentKeyStoreService { } /// Check if response from key server is required. - pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &TrustedClient, 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 (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) { @@ -600,14 +592,14 @@ impl DocumentKeyStoreService { } /// Read pending requests count. - fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &TrustedClient, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::document_key_store_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); 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)?) @@ -647,7 +639,7 @@ impl DocumentKeyShadowRetrievalService { } /// Check if response from key server is required. - pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, key_server: &Address) -> bool { + pub fn is_response_required(client: &TrustedClient, 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 (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) { @@ -662,7 +654,7 @@ impl DocumentKeyShadowRetrievalService { } /// Prepare publish personal key transaction data. - 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 { + pub fn prepare_pubish_personal_tx_data(client: &TrustedClient, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result { let mut participants_mask = U256::default(); for participant in participants { let participant_index = Self::map_key_server_address(client, contract_address, participant.clone()) @@ -680,14 +672,14 @@ impl DocumentKeyShadowRetrievalService { } /// Read pending requests count. - fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &TrustedClient, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::document_key_shadow_retrieval_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_document_key_shadow_retrieval_request::call(index); @@ -717,7 +709,7 @@ impl DocumentKeyShadowRetrievalService { } /// Map from key server address to key server index. - fn map_key_server_address(client: &Client, contract_address: &Address, key_server: Address) -> Result { + fn map_key_server_address(client: &TrustedClient, contract_address: &Address, key_server: Address) -> Result { // we're checking confirmation in Latest block, because tx ,ust be appended to the latest state let (encoded, decoder) = service::functions::require_key_server::call(key_server); let index = decoder.decode(&client.call_contract(BlockId::Latest, *contract_address, encoded)?) diff --git a/secret-store/src/listener/service_contract_listener.rs b/secret-store/src/listener/service_contract_listener.rs index 63cacf01de2..b654ea7c800 100644 --- a/secret-store/src/listener/service_contract_listener.rs +++ b/secret-store/src/listener/service_contract_listener.rs @@ -18,8 +18,6 @@ use std::collections::HashSet; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread; -use client_traits::ChainNotify; -use common_types::chain_notify::NewBlocks; use bytes::Bytes; use crypto::publickey::{Public, public_to_address}; use ethereum_types::{H256, U256, Address, BigEndianHash as _}; @@ -37,6 +35,7 @@ use acl_storage::AclStorage; use listener::service_contract::ServiceContract; use listener::tasks_queue::TasksQueue; use {ServerKeyId, NodeKeyPair, Error}; +use trusted_client::NewBlocksNotify; /// Retry interval (in blocks). Every RETRY_INTERVAL_BLOCKS blocks each KeyServer reads pending requests from /// service contract && tries to re-execute. The reason to have this mechanism is primarily because keys @@ -434,14 +433,8 @@ impl Drop for ServiceContractListener { } } -impl ChainNotify for ServiceContractListener { - fn new_blocks(&self, new_blocks: NewBlocks) { - if new_blocks.has_more_blocks_to_import { return } - let enacted_len = new_blocks.route.enacted().len(); - if enacted_len == 0 && new_blocks.route.retracted().is_empty() { - return; - } - +impl NewBlocksNotify for ServiceContractListener { + fn new_blocks(&self, new_enacted_len: usize) { if !self.data.contract.update() { return; } @@ -450,7 +443,7 @@ impl ChainNotify for ServiceContractListener { // schedule retry if received enough blocks since last retry // it maybe inaccurate when switching syncing/synced states, but that's ok - if self.data.last_retry.fetch_add(enacted_len, Ordering::Relaxed) >= RETRY_INTERVAL_BLOCKS { + if self.data.last_retry.fetch_add(new_enacted_len, Ordering::Relaxed) >= RETRY_INTERVAL_BLOCKS { // shortcut: do not retry if we're isolated from the cluster if !self.data.key_server_set.is_isolated() { self.data.tasks_queue.push(ServiceTask::Retry); diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 32df03c4b79..792689cf4cb 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -18,10 +18,19 @@ use std::sync::{Arc, Weak}; use bytes::Bytes; use common_types::{ ids::BlockId, + BlockNumber, transaction::{Transaction, SignedTransaction, Action}, + chain_notify::NewBlocks, + tree_route::TreeRoute, + filter::Filter, + log_entry::LocalizedLogEntry, }; -use ethereum_types::Address; +use parking_lot::RwLock; +use ethereum_types::{H256, Address}; use ethcore::client::Client; +use client_traits::BlockChainClient; +use call_contract::CallContract; +use client_traits::ChainNotify; use client_traits::{ChainInfo, Nonce}; use ethcore::miner::{Miner, MinerService}; use sync::SyncProvider; @@ -29,7 +38,15 @@ use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED}; use {Error, NodeKeyPair, ContractAddress}; use registrar::RegistrarClient; -#[derive(Clone)] +/// Wrapps client ChainNotify in order to send signal about new blocks +pub trait NewBlocksNotify: Send + Sync { + /// Fires when chain has new blocks. + /// Sends this signal only, if contracts' update required + fn new_blocks(&self, _new_enacted_len: usize) { + // does nothing by default + } +} + /// 'Trusted' client weak reference. pub struct TrustedClient { /// This key server node key pair. @@ -40,21 +57,44 @@ pub struct TrustedClient { sync: Weak, /// Miner service. miner: Weak, + /// Chain new blocks listeners + listeners: RwLock>>, } impl TrustedClient { /// Create new trusted client. - pub fn new(self_key_pair: Arc, client: Arc, sync: Arc, miner: Arc) -> Self { - TrustedClient { + pub fn new(self_key_pair: Arc, client: Arc, sync: Arc, miner: Arc) -> Arc { + let trusted_client = Arc::new(TrustedClient { self_key_pair, client: Arc::downgrade(&client), sync: Arc::downgrade(&sync), miner: Arc::downgrade(&miner), + listeners: RwLock::default(), + }); + client.add_notify(trusted_client.clone()); + trusted_client + } + + /// Adds listener for chain's NewBlocks event + pub fn add_listener(&self, target: Arc) { + self.listeners.write().push(Arc::downgrade(&target)); + } + + fn notify_listeners(&self, new_enacted_len: usize) { + for np in self.listeners.read().iter() { + if let Some(n) = np.upgrade() { + n.new_blocks(new_enacted_len); + } } } + /// Check if the underlying client is in the trusted state + pub fn is_trusted(&self) -> bool { + self.get_trusted().is_some() + } + /// Get 'trusted' `Client` reference only if it is synchronized && trusted. - pub fn get(&self) -> Option> { + fn get_trusted(&self) -> Option> { self.client.upgrade() .and_then(|client| self.sync.upgrade().map(|sync| (client, sync))) .and_then(|(client, sync)| { @@ -67,11 +107,6 @@ impl TrustedClient { }) } - /// Get untrusted `Client` reference. - pub fn get_untrusted(&self) -> Option> { - self.client.upgrade() - } - /// Transact contract. pub fn transact_contract(&self, contract: Address, tx_data: Bytes) -> Result<(), Error> { let client = self.client.upgrade().ok_or_else(|| Error::Internal("cannot submit tx when client is offline".into()))?; @@ -102,8 +137,8 @@ impl TrustedClient { ) -> Option
{ match *address { ContractAddress::Address(ref address) => Some(address.clone()), - ContractAddress::Registry => self.get().and_then(|client| - get_confirmed_block_hash(&*client, REQUEST_CONFIRMATIONS_REQUIRED) + ContractAddress::Registry => self.get_trusted().and_then(|client| + get_confirmed_block_hash(&*self, REQUEST_CONFIRMATIONS_REQUIRED) .and_then(|block| { client.get_address(registry_name, BlockId::Hash(block)) .unwrap_or(None) @@ -111,4 +146,60 @@ impl TrustedClient { ), } } + + /// Client's call_contract wrapper + pub fn call_contract(&self, block_id: BlockId, contract_address: Address, data: Bytes) -> Result { + if let Some(client) = self.get_trusted() { + client.call_contract(block_id, contract_address, data) + } else { + Err("Calling ACL contract without trusted blockchain client".into()) + } + } + + /// Client's block_hash wrapper + pub fn block_hash(&self, id: BlockId) -> Option { + if let Some(client) = self.get_trusted() { + client.block_hash(id) + } else { + None + } + } + + /// Client's block_number wrapper + pub fn block_number(&self, id: BlockId) -> Option { + if let Some(client) = self.get_trusted() { + client.block_number(id) + } else { + None + } + } + + /// Client's tree_route wrapper + pub fn tree_route(&self, from: &H256, to: &H256) -> Option { + if let Some(client) = self.get_trusted() { + client.tree_route(from, to) + } else { + None + } + } + + /// Client's logs wrapper + pub fn logs(&self, filter: Filter) -> Option> { + if let Some(client) = self.get_trusted() { + client.logs(filter).ok() + } else { + None + } + } +} + +impl ChainNotify for TrustedClient { + fn new_blocks(&self, new_blocks: NewBlocks) { + if new_blocks.has_more_blocks_to_import { return } + if !new_blocks.route.enacted().is_empty() || !new_blocks.route.retracted().is_empty() { + let enacted_len = new_blocks.route.enacted().len(); + self.notify_listeners(enacted_len); + } + } } + From 039c91d157bd431aea8c127667e85aedf097e8c7 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 11 Nov 2019 17:43:12 +0100 Subject: [PATCH 02/16] Move confirmed hash method to trusted client --- secret-store/src/helpers.rs | 30 ------------------- secret-store/src/lib.rs | 1 - secret-store/src/listener/service_contract.rs | 8 ++--- secret-store/src/trusted_client.rs | 14 +++++++-- 4 files changed, 15 insertions(+), 38 deletions(-) delete mode 100644 secret-store/src/helpers.rs diff --git a/secret-store/src/helpers.rs b/secret-store/src/helpers.rs deleted file mode 100644 index ad668efad44..00000000000 --- a/secret-store/src/helpers.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -use trusted_client::TrustedClient; -use common_types::ids::BlockId; -use ethereum_types::H256; - -// TODO: Instead of a constant, make this based on consensus finality. -/// Number of confirmations required before request can be processed. -pub const REQUEST_CONFIRMATIONS_REQUIRED: u64 = 3; - -/// Get hash of the last block with at least n confirmations. -pub fn get_confirmed_block_hash(client: &TrustedClient, confirmations: u64) -> Option { - client.block_number(BlockId::Latest) - .map(|b| b.saturating_sub(confirmations)) - .and_then(|b| client.block_hash(BlockId::Number(b))) -} diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index 1dd120bb303..37958c5af2e 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -66,7 +66,6 @@ extern crate ethcore_accounts as accounts; mod key_server_cluster; mod types; -mod helpers; mod traits; mod acl_storage; diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index 2d24f4e9efe..0bddb74b5b7 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -27,7 +27,6 @@ use ethereum_types::{H256, U256, Address, H512}; use listener::ApiMask; use listener::service_contract_listener::ServiceTask; use trusted_client::TrustedClient; -use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED}; use {ServerKeyId, NodeKeyPair, ContractAddress}; use_contract!(service, "res/service.json"); @@ -250,7 +249,7 @@ impl ServiceContract for OnChainServiceContract { Some(address) => address, None => return Box::new(::std::iter::empty()), // no contract installed }; - let confirmed_block = match get_confirmed_block_hash(&*self.client, REQUEST_CONFIRMATIONS_REQUIRED) { + let confirmed_block = match self.client.get_confirmed_block_hash() { Some(confirmed_block) => confirmed_block, None => return Box::new(::std::iter::empty()), // no block with enough confirmations }; @@ -308,12 +307,11 @@ impl ServiceContract for OnChainServiceContract { return Box::new(::std::iter::empty()) } - // we only need requests that are here for more than REQUEST_CONFIRMATIONS_REQUIRED blocks - // => we're reading from Latest - (REQUEST_CONFIRMATIONS_REQUIRED + 1) block + // we only need requests that are here from the last confirm block let data = self.data.read(); match data.contract_address { None => Box::new(::std::iter::empty()), - Some(contract_address) => get_confirmed_block_hash(&*self.client, REQUEST_CONFIRMATIONS_REQUIRED + 1) + Some(contract_address) => self.client.get_confirmed_block_hash() .map(|b| { let block = BlockId::Hash(b); let iter = match self.mask.server_key_generation_requests { diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 792689cf4cb..58dbcbff8a0 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -34,10 +34,13 @@ use client_traits::ChainNotify; use client_traits::{ChainInfo, Nonce}; use ethcore::miner::{Miner, MinerService}; use sync::SyncProvider; -use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED}; use {Error, NodeKeyPair, ContractAddress}; use registrar::RegistrarClient; +// TODO: Instead of a constant, make this based on consensus finality. +/// Number of confirmations required before request can be processed. +const REQUEST_CONFIRMATIONS_REQUIRED: u64 = 3; + /// Wrapps client ChainNotify in order to send signal about new blocks pub trait NewBlocksNotify: Send + Sync { /// Fires when chain has new blocks. @@ -138,7 +141,7 @@ impl TrustedClient { match *address { ContractAddress::Address(ref address) => Some(address.clone()), ContractAddress::Registry => self.get_trusted().and_then(|client| - get_confirmed_block_hash(&*self, REQUEST_CONFIRMATIONS_REQUIRED) + self.get_confirmed_block_hash() .and_then(|block| { client.get_address(registry_name, BlockId::Hash(block)) .unwrap_or(None) @@ -191,6 +194,13 @@ impl TrustedClient { None } } + + /// Get hash of the last block with at least n confirmations. + pub fn get_confirmed_block_hash(&self) -> Option { + self.block_number(BlockId::Latest) + .map(|b| b.saturating_sub(REQUEST_CONFIRMATIONS_REQUIRED)) + .and_then(|b| self.block_hash(BlockId::Number(b))) + } } impl ChainNotify for TrustedClient { From fe5f1cf6e61fae05aa7fd4295ad0f3cdf6bb988c Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 12 Nov 2019 10:35:24 +0100 Subject: [PATCH 03/16] Tree route and logs encapsuluted --- secret-store/src/listener/service_contract.rs | 65 +++++++------------ secret-store/src/trusted_client.rs | 63 +++++++++++++++++- 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index 0bddb74b5b7..51c89d9a1d4 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -16,7 +16,6 @@ use std::sync::Arc; use parking_lot::RwLock; -use common_types::filter::Filter; use ethabi::RawLog; use ethabi::FunctionOutputDecoder; use common_types::ids::BlockId; @@ -26,7 +25,7 @@ use bytes::Bytes; use ethereum_types::{H256, U256, Address, H512}; use listener::ApiMask; use listener::service_contract_listener::ServiceTask; -use trusted_client::TrustedClient; +use trusted_client::{TrustedClient, Filter}; use {ServerKeyId, NodeKeyPair, ContractAddress}; use_contract!(service, "res/service.json"); @@ -242,54 +241,36 @@ impl ServiceContract for OnChainServiceContract { return Box::new(::std::iter::empty()); } - // prepare range of blocks to read logs from - let (address, first_block, last_block) = { - let mut data = self.data.write(); - let address = match data.contract_address { - Some(address) => address, - None => return Box::new(::std::iter::empty()), // no contract installed - }; - let confirmed_block = match self.client.get_confirmed_block_hash() { - Some(confirmed_block) => confirmed_block, - None => return Box::new(::std::iter::empty()), // no block with enough confirmations - }; - let first_block = match data.last_log_block.take().and_then(|b| self.client.tree_route(&b, &confirmed_block)) { - // if we have a route from last_log_block to confirmed_block => search for logs on this route - // - // potentially this could lead us to reading same logs twice when reorganizing to the fork, which - // already has been canonical previosuly - // the worst thing that can happen in this case is spending some time reading unneeded data from SS db - Some(ref route) if route.index < route.blocks.len() => route.blocks[route.index], - // else we care only about confirmed block - _ => confirmed_block.clone(), - }; - - data.last_log_block = Some(confirmed_block.clone()); - (address, first_block, confirmed_block) + let address = match self.data.read().contract_address { + Some(address) => address, + None => return Box::new(::std::iter::empty()), // no contract installed + }; + let confirmed_block = match self.client.get_confirmed_block_hash() { + Some(confirmed_block) => confirmed_block, + None => return Box::new(::std::iter::empty()), // no block with enough confirmations }; - // read server key generation requests - let request_logs = self.client.logs(Filter { - from_block: BlockId::Hash(first_block), - to_block: BlockId::Hash(last_block), + let request_logs = self.client.retrieve_last_logs(Filter { + from_block: BlockId::Hash(self.data.read().last_log_block.unwrap_or_else(|| confirmed_block)), address: Some(vec![address]), topics: vec![Some(mask_topics(&self.mask))], - limit: None, }).unwrap_or_default(); + let mut data = self.data.write(); + data.last_log_block = Some(confirmed_block.clone()); + Box::new(request_logs.into_iter() .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, raw_log) - } else if raw_log.topics[0] == *SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { - ServerKeyRetrievalService::parse_log(&address, raw_log) - } else if raw_log.topics[0] == *DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME_HASH { - 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, raw_log) - } else if raw_log.topics[0] == *DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { - DocumentKeyShadowRetrievalService::parse_personal_request_log(&address, raw_log) + if log.topics[0] == *SERVER_KEY_GENERATION_REQUESTED_EVENT_NAME_HASH { + ServerKeyGenerationService::parse_log(&address, log) + } else if log.topics[0] == *SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { + ServerKeyRetrievalService::parse_log(&address, log) + } else if log.topics[0] == *DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME_HASH { + DocumentKeyStoreService::parse_log(&address, log) + } else if log.topics[0] == *DOCUMENT_KEY_COMMON_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { + DocumentKeyShadowRetrievalService::parse_common_request_log(&address, log) + } else if log.topics[0] == *DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { + DocumentKeyShadowRetrievalService::parse_personal_request_log(&address, log) } else { Err("unknown type of log entry".into()) } diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 58dbcbff8a0..836e8d6bc0b 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -22,12 +22,13 @@ use common_types::{ transaction::{Transaction, SignedTransaction, Action}, chain_notify::NewBlocks, tree_route::TreeRoute, - filter::Filter, + filter::Filter as BlockchainFilter, log_entry::LocalizedLogEntry, }; use parking_lot::RwLock; use ethereum_types::{H256, Address}; use ethcore::client::Client; +use ethabi::RawLog; use client_traits::BlockChainClient; use call_contract::CallContract; use client_traits::ChainNotify; @@ -50,6 +51,25 @@ pub trait NewBlocksNotify: Send + Sync { } } +/// Blockchain logs Filter. +#[derive(Debug, PartialEq)] +pub struct Filter { + /// Blockchain will be searched from this block. + pub from_block: BlockId, + + /// Search addresses. + /// + /// If None, match all. + /// If specified, log must be produced by one of these addresses. + pub address: Option>, + + /// Search topics. + /// + /// If None, match all. + /// If specified, log must contain one of these topics. + pub topics: Vec>>, +} + /// 'Trusted' client weak reference. pub struct TrustedClient { /// This key server node key pair. @@ -178,7 +198,7 @@ impl TrustedClient { } /// Client's tree_route wrapper - pub fn tree_route(&self, from: &H256, to: &H256) -> Option { + fn tree_route(&self, from: &H256, to: &H256) -> Option { if let Some(client) = self.get_trusted() { client.tree_route(from, to) } else { @@ -187,7 +207,7 @@ impl TrustedClient { } /// Client's logs wrapper - pub fn logs(&self, filter: Filter) -> Option> { + fn logs(&self, filter: BlockchainFilter) -> Option> { if let Some(client) = self.get_trusted() { client.logs(filter).ok() } else { @@ -195,6 +215,43 @@ impl TrustedClient { } } + /// Retrieve last blockchain logs for the filter + pub fn retrieve_last_logs(&self, filter: Filter) -> Option> { + let confirmed_block = match self.get_confirmed_block_hash() { + Some(confirmed_block) => confirmed_block, + None => return None, // no block with enough confirmations + }; + + let from_block = self.block_hash(filter.from_block).unwrap_or_else(|| confirmed_block); + let first_block = match self.tree_route(&from_block, &confirmed_block) { + // if we have a route from last_log_block to confirmed_block => search for logs on this route + // + // potentially this could lead us to reading same logs twice when reorganizing to the fork, which + // already has been canonical previosuly + // the worst thing that can happen in this case is spending some time reading unneeded data from SS db + Some(ref route) if route.index < route.blocks.len() => route.blocks[route.index], + // else we care only about confirmed block + _ => confirmed_block.clone(), + }; + + self.logs(BlockchainFilter { + from_block: BlockId::Hash(first_block), + to_block: BlockId::Hash(confirmed_block), + address: filter.address, + topics: filter.topics, + limit: None, + }) + .map(|blockchain_logs| { + blockchain_logs + .into_iter() + .map(|log| { + let raw_log: RawLog = (log.entry.topics.into_iter().map(|t| t.0.into()).collect(), log.entry.data).into(); + raw_log + }) + .collect::>() + }) + } + /// Get hash of the last block with at least n confirmations. pub fn get_confirmed_block_hash(&self) -> Option { self.block_number(BlockId::Latest) From 16cb9c8429e178eda5e8a84fb131f0fb1e881c64 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 12 Nov 2019 15:58:56 +0100 Subject: [PATCH 04/16] Remove not used method for keys sharing --- secret-store/src/node_key_pair.rs | 12 ------------ secret-store/src/traits.rs | 4 +--- secret-store/src/trusted_client.rs | 3 +-- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/secret-store/src/node_key_pair.rs b/secret-store/src/node_key_pair.rs index c3f02c3f637..5dbcf915c0d 100644 --- a/secret-store/src/node_key_pair.rs +++ b/secret-store/src/node_key_pair.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use crypto::publickey::ecdh::agree; use crypto::publickey::{KeyPair, Public, Signature, Error as EthKeyError, sign, public_to_address}; use ethereum_types::{H256, Address}; use traits::NodeKeyPair; @@ -48,12 +47,6 @@ impl NodeKeyPair for PlainNodeKeyPair { fn sign(&self, data: &H256) -> Result { sign(self.key_pair.secret(), data) } - - fn compute_shared_key(&self, peer_public: &Public) -> Result { - agree(self.key_pair.secret(), peer_public) - .map_err(|e| EthKeyError::Custom(e.to_string())) - .and_then(KeyPair::from_secret) - } } #[cfg(feature = "accounts")] @@ -95,11 +88,6 @@ mod accounts { self.account_provider.sign(self.address.clone(), Some(self.password.clone()), data.clone()) .map_err(|e| EthKeyError::Custom(format!("{}", e))) } - - fn compute_shared_key(&self, peer_public: &Public) -> Result { - KeyPair::from_secret(self.account_provider.agree(self.address.clone(), Some(self.password.clone()), peer_public) - .map_err(|e| EthKeyError::Custom(format!("{}", e)))?) - } } } diff --git a/secret-store/src/traits.rs b/secret-store/src/traits.rs index d62210ed1e0..2b509a4b5c0 100644 --- a/secret-store/src/traits.rs +++ b/secret-store/src/traits.rs @@ -16,7 +16,7 @@ use std::collections::BTreeSet; use futures::Future; -use crypto::publickey::{KeyPair, Signature, Error as EthKeyError}; +use crypto::publickey::{Signature, Error as EthKeyError}; use ethereum_types::{H256, Address}; use types::{Error, Public, ServerKeyId, MessageHash, EncryptedMessageSignature, RequestSignature, Requester, EncryptedDocumentKey, EncryptedDocumentKeyShadow, NodeId}; @@ -29,8 +29,6 @@ pub trait NodeKeyPair: Send + Sync { fn address(&self) -> Address; /// Sign data with node key. fn sign(&self, data: &H256) -> Result; - /// Compute shared key to encrypt channel between two nodes. - fn compute_shared_key(&self, peer_public: &Public) -> Result; } /// Server key (SK) generator. diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 836e8d6bc0b..2222ebbbbfa 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -31,8 +31,7 @@ use ethcore::client::Client; use ethabi::RawLog; use client_traits::BlockChainClient; use call_contract::CallContract; -use client_traits::ChainNotify; -use client_traits::{ChainInfo, Nonce}; +use client_traits::{ChainInfo, Nonce, ChainNotify}; use ethcore::miner::{Miner, MinerService}; use sync::SyncProvider; use {Error, NodeKeyPair, ContractAddress}; From 7048d254b715f82ebf920080684df10f2d24ad06 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 12 Nov 2019 16:30:41 +0100 Subject: [PATCH 05/16] NodeKeyPair renamed and moved to trusted client --- secret-store/src/key_server.rs | 7 ++++--- .../servers_set_change_session.rs | 3 ++- .../admin_sessions/share_add_session.rs | 3 ++- .../src/key_server_cluster/cluster.rs | 16 +++++++++------- .../cluster_connections_net.rs | 5 +++-- .../cluster_message_processor.rs | 7 ++++--- .../key_server_cluster/cluster_sessions.rs | 5 +++-- .../key_server_cluster/connection_trigger.rs | 6 +++--- .../connection_trigger_with_migration.rs | 8 ++++---- .../src/key_server_cluster/io/handshake.rs | 13 +++++++------ secret-store/src/key_server_cluster/mod.rs | 2 +- .../net/accept_connection.rs | 5 +++-- .../src/key_server_cluster/net/connect.rs | 7 ++++--- secret-store/src/key_server_set.rs | 10 +++++----- secret-store/src/lib.rs | 5 +++-- secret-store/src/listener/service_contract.rs | 18 +++++++++--------- .../src/listener/service_contract_listener.rs | 11 ++++++----- secret-store/src/node_key_pair.rs | 6 +++--- secret-store/src/traits.rs | 12 ------------ secret-store/src/trusted_client.rs | 19 +++++++++++++++---- 20 files changed, 90 insertions(+), 78 deletions(-) diff --git a/secret-store/src/key_server.rs b/secret-store/src/key_server.rs index bbb45b5afdd..6b64ad349d9 100644 --- a/secret-store/src/key_server.rs +++ b/secret-store/src/key_server.rs @@ -24,8 +24,9 @@ use parity_runtime::Executor; use super::acl_storage::AclStorage; use super::key_storage::KeyStorage; use super::key_server_set::KeyServerSet; +use trusted_client::SigningKeyPair; use key_server_cluster::{math, new_network_cluster, ClusterSession, WaitableSession}; -use traits::{AdminSessionsServer, ServerKeyGenerator, DocumentKeyServer, MessageSigner, KeyServer, NodeKeyPair}; +use traits::{AdminSessionsServer, ServerKeyGenerator, DocumentKeyServer, MessageSigner, KeyServer}; use types::{Error, Public, RequestSignature, Requester, ServerKeyId, EncryptedDocumentKey, EncryptedDocumentKeyShadow, ClusterConfiguration, MessageHash, EncryptedMessageSignature, NodeId}; use key_server_cluster::{ClusterClient, ClusterConfiguration as NetClusterConfiguration, NetConnectionsManagerConfig}; @@ -42,7 +43,7 @@ pub struct KeyServerCore { impl KeyServerImpl { /// Create new key server instance - pub fn new(config: &ClusterConfiguration, key_server_set: Arc, self_key_pair: Arc, + pub fn new(config: &ClusterConfiguration, key_server_set: Arc, self_key_pair: Arc, acl_storage: Arc, key_storage: Arc, executor: Executor) -> Result { Ok(KeyServerImpl { @@ -269,7 +270,7 @@ impl MessageSigner for KeyServerImpl { } impl KeyServerCore { - pub fn new(config: &ClusterConfiguration, key_server_set: Arc, self_key_pair: Arc, + pub fn new(config: &ClusterConfiguration, key_server_set: Arc, self_key_pair: Arc, acl_storage: Arc, key_storage: Arc, executor: Executor) -> Result { let cconfig = NetClusterConfiguration { diff --git a/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs b/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs index 9bc6d1df81f..3cce0fcd23d 100644 --- a/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs +++ b/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs @@ -1051,7 +1051,8 @@ pub mod tests { use std::collections::{VecDeque, BTreeMap, BTreeSet}; use ethereum_types::H256; use crypto::publickey::{Random, Generator, Public, Signature, KeyPair, sign}; - use key_server_cluster::{NodeId, SessionId, Error, KeyStorage, NodeKeyPair, PlainNodeKeyPair}; + use trusted_client::SigningKeyPair; + use key_server_cluster::{NodeId, SessionId, Error, KeyStorage, PlainNodeKeyPair}; use key_server_cluster::cluster_sessions::ClusterSession; use key_server_cluster::cluster::tests::MessageLoop as ClusterMessageLoop; use key_server_cluster::generation_session::tests::{MessageLoop as GenerationMessageLoop}; diff --git a/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs b/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs index 94e6e989379..386f91a35b9 100644 --- a/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs +++ b/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs @@ -889,7 +889,8 @@ impl SessionTransport for IsolatedSessionTransport { pub mod tests { use std::collections::BTreeSet; use crypto::publickey::{Random, Generator, Public}; - use key_server_cluster::{NodeId, Error, KeyStorage, NodeKeyPair}; + use trusted_client::SigningKeyPair; + use key_server_cluster::{NodeId, Error, KeyStorage}; use key_server_cluster::cluster::tests::MessageLoop as ClusterMessageLoop; use key_server_cluster::servers_set_change_session::tests::{MessageLoop, AdminSessionAdapter, generate_key}; use key_server_cluster::admin_sessions::ShareChangeSessionMeta; diff --git a/secret-store/src/key_server_cluster/cluster.rs b/secret-store/src/key_server_cluster/cluster.rs index 44e6a22fed4..9f67148fcca 100644 --- a/secret-store/src/key_server_cluster/cluster.rs +++ b/secret-store/src/key_server_cluster/cluster.rs @@ -20,7 +20,8 @@ use parking_lot::RwLock; use crypto::publickey::{Public, Signature, Random, Generator}; use ethereum_types::{Address, H256}; use parity_runtime::Executor; -use key_server_cluster::{Error, NodeId, SessionId, Requester, AclStorage, KeyStorage, KeyServerSet, NodeKeyPair}; +use trusted_client::SigningKeyPair; +use key_server_cluster::{Error, NodeId, SessionId, Requester, AclStorage, KeyStorage, KeyServerSet}; use key_server_cluster::cluster_sessions::{WaitableSession, ClusterSession, AdminSession, ClusterSessions, SessionIdWithSubSession, ClusterSessionsContainer, SERVERS_SET_CHANGE_SESSION_ID, create_cluster_view, AdminSessionCreationData, ClusterSessionsListener}; @@ -143,7 +144,7 @@ pub trait Cluster: Send + Sync { #[derive(Clone)] pub struct ClusterConfiguration { /// KeyPair this node holds. - pub self_key_pair: Arc, + pub self_key_pair: Arc, /// Cluster nodes set. pub key_server_set: Arc, /// Reference to key storage @@ -173,7 +174,7 @@ pub struct ClusterView { configured_nodes_count: usize, connected_nodes: BTreeSet, connections: Arc, - self_key_pair: Arc, + self_key_pair: Arc, } /// Cross-thread shareable cluster data. @@ -181,7 +182,7 @@ pub struct ClusterData { /// Cluster configuration. pub config: ClusterConfiguration, /// KeyPair this node holds. - pub self_key_pair: Arc, + pub self_key_pair: Arc, /// Connections data. pub connections: C, /// Active sessions data. @@ -311,7 +312,7 @@ impl ClusterCore { impl ClusterView { pub fn new( - self_key_pair: Arc, + self_key_pair: Arc, connections: Arc, nodes: BTreeSet, configured_nodes_count: usize @@ -597,7 +598,7 @@ pub struct ServersSetChangeParams { } pub fn new_servers_set_change_session( - self_key_pair: Arc, + self_key_pair: Arc, sessions: &ClusterSessions, connections: Arc, servers_set_change_creator_connector: Arc, @@ -656,8 +657,9 @@ pub mod tests { use parking_lot::{Mutex, RwLock}; use ethereum_types::{Address, H256}; use crypto::publickey::{Random, Generator, Public, Signature, sign}; + use trusted_client::SigningKeyPair; use key_server_cluster::{NodeId, SessionId, Requester, Error, DummyAclStorage, DummyKeyStorage, - MapKeyServerSet, PlainNodeKeyPair, NodeKeyPair}; + MapKeyServerSet, PlainNodeKeyPair}; use key_server_cluster::message::Message; use key_server_cluster::cluster::{new_test_cluster, Cluster, ClusterCore, ClusterConfiguration, ClusterClient}; use key_server_cluster::cluster_connections::ConnectionManager; diff --git a/secret-store/src/key_server_cluster/cluster_connections_net.rs b/secret-store/src/key_server_cluster/cluster_connections_net.rs index b402d001875..77ae12afaef 100644 --- a/secret-store/src/key_server_cluster/cluster_connections_net.rs +++ b/secret-store/src/key_server_cluster/cluster_connections_net.rs @@ -27,7 +27,8 @@ use tokio::timer::{Interval, timeout::Error as TimeoutError}; use tokio_io::IoFuture; use crypto::publickey::KeyPair; use parity_runtime::Executor; -use key_server_cluster::{Error, NodeId, ClusterConfiguration, NodeKeyPair}; +use trusted_client::SigningKeyPair; +use key_server_cluster::{Error, NodeId, ClusterConfiguration}; use key_server_cluster::cluster_connections::{ConnectionProvider, Connection, ConnectionManager}; use key_server_cluster::connection_trigger::{Maintain, ConnectionTrigger}; use key_server_cluster::cluster_message_processor::MessageProcessor; @@ -79,7 +80,7 @@ struct NetConnectionsData { /// Reference to tokio task executor. executor: Executor, /// Key pair of this node. - self_key_pair: Arc, + self_key_pair: Arc, /// Network messages processor. message_processor: Arc, /// Connections trigger. diff --git a/secret-store/src/key_server_cluster/cluster_message_processor.rs b/secret-store/src/key_server_cluster/cluster_message_processor.rs index d0ab712b6bf..c9b42bb012b 100644 --- a/secret-store/src/key_server_cluster/cluster_message_processor.rs +++ b/secret-store/src/key_server_cluster/cluster_message_processor.rs @@ -15,7 +15,8 @@ // along with Parity. If not, see . use std::sync::Arc; -use key_server_cluster::{Error, NodeId, NodeKeyPair}; +use trusted_client::SigningKeyPair; +use key_server_cluster::{Error, NodeId}; use key_server_cluster::cluster::{ServersSetChangeParams, new_servers_set_change_session}; use key_server_cluster::cluster_sessions::{AdminSession}; use key_server_cluster::cluster_connections::{ConnectionProvider, Connection}; @@ -49,7 +50,7 @@ pub trait MessageProcessor: Send + Sync { /// Bridge between ConnectionManager and ClusterSessions. pub struct SessionsMessageProcessor { - self_key_pair: Arc, + self_key_pair: Arc, servers_set_change_creator_connector: Arc, sessions: Arc, connections: Arc, @@ -58,7 +59,7 @@ pub struct SessionsMessageProcessor { impl SessionsMessageProcessor { /// Create new instance of SessionsMessageProcessor. pub fn new( - self_key_pair: Arc, + self_key_pair: Arc, servers_set_change_creator_connector: Arc, sessions: Arc, connections: Arc, diff --git a/secret-store/src/key_server_cluster/cluster_sessions.rs b/secret-store/src/key_server_cluster/cluster_sessions.rs index 1e5a046b993..bf589dce453 100644 --- a/secret-store/src/key_server_cluster/cluster_sessions.rs +++ b/secret-store/src/key_server_cluster/cluster_sessions.rs @@ -22,7 +22,8 @@ use futures::{oneshot, Oneshot, Complete, Future}; use parking_lot::{Mutex, RwLock, Condvar}; use ethereum_types::H256; use crypto::publickey::Secret; -use key_server_cluster::{Error, NodeId, SessionId, NodeKeyPair}; +use trusted_client::SigningKeyPair; +use key_server_cluster::{Error, NodeId, SessionId}; use key_server_cluster::cluster::{Cluster, ClusterConfiguration, ClusterView}; use key_server_cluster::cluster_connections::ConnectionProvider; use key_server_cluster::connection_trigger::ServersSetChangeSessionCreatorConnector; @@ -647,7 +648,7 @@ impl CompletionSignal { } } -pub fn create_cluster_view(self_key_pair: Arc, connections: Arc, requires_all_connections: bool) -> Result, Error> { +pub fn create_cluster_view(self_key_pair: Arc, connections: Arc, requires_all_connections: bool) -> Result, Error> { let mut connected_nodes = connections.connected_nodes()?; let disconnected_nodes = connections.disconnected_nodes(); diff --git a/secret-store/src/key_server_cluster/connection_trigger.rs b/secret-store/src/key_server_cluster/connection_trigger.rs index 40d415dffe0..356e38690bf 100644 --- a/secret-store/src/key_server_cluster/connection_trigger.rs +++ b/secret-store/src/key_server_cluster/connection_trigger.rs @@ -26,7 +26,7 @@ use key_server_cluster::cluster_sessions::AdminSession; use key_server_cluster::cluster_connections::{Connection}; use key_server_cluster::cluster_connections_net::{NetConnectionsContainer}; use types::{Error, NodeId}; -use NodeKeyPair; +use trusted_client::SigningKeyPair; #[derive(Debug, Clone, Copy, PartialEq)] /// Describes which maintain() call is required. @@ -93,7 +93,7 @@ pub enum ConnectionsAction { /// Trigger connections. pub struct TriggerConnections { /// This node key pair. - pub self_key_pair: Arc, + pub self_key_pair: Arc, } impl SimpleConnectionTrigger { @@ -103,7 +103,7 @@ impl SimpleConnectionTrigger { } /// Create new simple connection trigger. - pub fn new(key_server_set: Arc, self_key_pair: Arc, admin_public: Option) -> Self { + pub fn new(key_server_set: Arc, self_key_pair: Arc, admin_public: Option) -> Self { SimpleConnectionTrigger { key_server_set: key_server_set, connections: TriggerConnections { diff --git a/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs b/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs index 92db652d5ec..5c945ad2764 100644 --- a/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs +++ b/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs @@ -28,12 +28,12 @@ use key_server_cluster::jobs::servers_set_change_access_job::ordered_nodes_hash; use key_server_cluster::connection_trigger::{Maintain, ConnectionsAction, ConnectionTrigger, ServersSetChangeSessionCreatorConnector, TriggerConnections}; use types::{Error, NodeId}; -use {NodeKeyPair}; +use trusted_client::SigningKeyPair; /// Key servers set change trigger with automated migration procedure. pub struct ConnectionTriggerWithMigration { /// This node key pair. - self_key_pair: Arc, + self_key_pair: Arc, /// Key server set. key_server_set: Arc, /// Last server set state. @@ -105,7 +105,7 @@ struct TriggerSession { /// Servers set change session creator connector. connector: Arc, /// This node key pair. - self_key_pair: Arc, + self_key_pair: Arc, /// Key server set. key_server_set: Arc, } @@ -117,7 +117,7 @@ impl ConnectionTriggerWithMigration { } /// Create new trigge with migration. - pub fn new(key_server_set: Arc, self_key_pair: Arc) -> Self { + pub fn new(key_server_set: Arc, self_key_pair: Arc) -> Self { let snapshot = key_server_set.snapshot(); let migration = snapshot.migration.clone(); diff --git a/secret-store/src/key_server_cluster/io/handshake.rs b/secret-store/src/key_server_cluster/io/handshake.rs index a09e035e43a..2b58f5988ed 100644 --- a/secret-store/src/key_server_cluster/io/handshake.rs +++ b/secret-store/src/key_server_cluster/io/handshake.rs @@ -40,20 +40,21 @@ use tokio_io::{AsyncRead, AsyncWrite}; use crypto::publickey::ecdh::agree; use crypto::publickey::{Random, Generator, KeyPair, Public, Signature, verify_public, sign, recover}; use ethereum_types::H256; -use key_server_cluster::{NodeId, Error, NodeKeyPair}; +use trusted_client::SigningKeyPair; +use key_server_cluster::{NodeId, Error}; use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature}; use key_server_cluster::io::{write_message, write_encrypted_message, WriteMessage, ReadMessage, read_message, read_encrypted_message, fix_shared_key}; /// Start handshake procedure with another node from the cluster. -pub fn handshake(a: A, self_key_pair: Arc, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { +pub fn handshake(a: A, self_key_pair: Arc, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { let init_data = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into) .and_then(|cp| Random.generate().map(|kp| (cp, kp)).map_err(Into::into)); handshake_with_init_data(a, init_data, self_key_pair, trusted_nodes) } /// Start handshake procedure with another node from the cluster and given plain confirmation + session key pair. -pub fn handshake_with_init_data(a: A, init_data: Result<(H256, KeyPair), Error>, self_key_pair: Arc, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { +pub fn handshake_with_init_data(a: A, init_data: Result<(H256, KeyPair), Error>, self_key_pair: Arc, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { let handshake_input_data = init_data .and_then(|(cp, kp)| sign(kp.secret(), &cp).map(|sp| (cp, kp, sp)).map_err(Into::into)) .and_then(|(cp, kp, sp)| Handshake::::make_public_key_message(self_key_pair.public().clone(), cp.clone(), sp).map(|msg| (cp, kp, msg))); @@ -79,7 +80,7 @@ pub fn handshake_with_init_data(a: A, init_data: Result<(H256, KeyPair), Erro } /// Wait for handshake procedure to be started by another node from the cluster. -pub fn accept_handshake(a: A, self_key_pair: Arc) -> Handshake where A: AsyncWrite + AsyncRead { +pub fn accept_handshake(a: A, self_key_pair: Arc) -> Handshake where A: AsyncWrite + AsyncRead { let self_confirmation_plain = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into); let handshake_input_data = self_confirmation_plain .and_then(|cp| Random.generate().map(|kp| (cp, kp)).map_err(Into::into)); @@ -118,7 +119,7 @@ pub struct Handshake { is_active: bool, error: Option<(A, Result)>, state: HandshakeState, - self_key_pair: Arc, + self_key_pair: Arc, self_session_key_pair: Option, self_confirmation_plain: H256, trusted_nodes: Option>, @@ -156,7 +157,7 @@ impl Handshake where A: AsyncRead + AsyncWrite { }))) } - fn make_private_key_signature_message(self_key_pair: &dyn NodeKeyPair, confirmation_plain: &H256) -> Result { + fn make_private_key_signature_message(self_key_pair: &dyn SigningKeyPair, confirmation_plain: &H256) -> Result { Ok(Message::Cluster(ClusterMessage::NodePrivateKeySignature(NodePrivateKeySignature { confirmation_signed: self_key_pair.sign(confirmation_plain)?.into(), }))) diff --git a/secret-store/src/key_server_cluster/mod.rs b/secret-store/src/key_server_cluster/mod.rs index c1c91ef8a53..6d033d69b02 100644 --- a/secret-store/src/key_server_cluster/mod.rs +++ b/secret-store/src/key_server_cluster/mod.rs @@ -16,7 +16,7 @@ use super::types::ServerKeyId; -pub use super::traits::NodeKeyPair; +pub use super::trusted_client::SigningKeyPair; pub use super::types::{Error, NodeId, Requester, EncryptedDocumentKeyShadow}; pub use super::acl_storage::AclStorage; pub use super::key_storage::{KeyStorage, DocumentKeyShare, DocumentKeyShareVersion}; diff --git a/secret-store/src/key_server_cluster/net/accept_connection.rs b/secret-store/src/key_server_cluster/net/accept_connection.rs index 88ee9b3d5f8..bf567116cdd 100644 --- a/secret-store/src/key_server_cluster/net/accept_connection.rs +++ b/secret-store/src/key_server_cluster/net/accept_connection.rs @@ -20,12 +20,13 @@ use std::net::SocketAddr; use std::time::Duration; use futures::{Future, Poll}; use tokio::net::TcpStream; -use key_server_cluster::{Error, NodeKeyPair}; +use trusted_client::SigningKeyPair; +use key_server_cluster::Error; use key_server_cluster::io::{accept_handshake, Handshake, Deadline, deadline}; use key_server_cluster::net::Connection; /// Create future for accepting incoming connection. -pub fn accept_connection(stream: TcpStream, self_key_pair: Arc) -> Deadline { +pub fn accept_connection(stream: TcpStream, self_key_pair: Arc) -> Deadline { // TODO: This could fail so it would be better either to accept the // address as a separate argument or return a result. let address = stream.peer_addr().expect("Unable to determine tcp peer address"); diff --git a/secret-store/src/key_server_cluster/net/connect.rs b/secret-store/src/key_server_cluster/net/connect.rs index c5be9be0e8c..0fd1c1318fd 100644 --- a/secret-store/src/key_server_cluster/net/connect.rs +++ b/secret-store/src/key_server_cluster/net/connect.rs @@ -21,12 +21,13 @@ use std::time::Duration; use std::net::SocketAddr; use futures::{Future, Poll, Async}; use tokio::net::{TcpStream, tcp::ConnectFuture}; -use key_server_cluster::{Error, NodeId, NodeKeyPair}; +use trusted_client::SigningKeyPair; +use key_server_cluster::{Error, NodeId}; use key_server_cluster::io::{handshake, Handshake, Deadline, deadline}; use key_server_cluster::net::Connection; /// Create future for connecting to other node. -pub fn connect(address: &SocketAddr, self_key_pair: Arc, trusted_nodes: BTreeSet) -> Deadline { +pub fn connect(address: &SocketAddr, self_key_pair: Arc, trusted_nodes: BTreeSet) -> Deadline { let connect = Connect { state: ConnectState::TcpConnect(TcpStream::connect(address)), address: address.clone(), @@ -47,7 +48,7 @@ enum ConnectState { pub struct Connect { state: ConnectState, address: SocketAddr, - self_key_pair: Arc, + self_key_pair: Arc, trusted_nodes: BTreeSet, } diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index 3335526f050..41d34d815a2 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -26,8 +26,8 @@ use ethereum_types::{H256, Address}; use crypto::publickey::public_to_address; use bytes::Bytes; use types::{Error, Public, NodeAddress, NodeId}; -use trusted_client::{TrustedClient, NewBlocksNotify}; -use {NodeKeyPair, ContractAddress}; +use trusted_client::{TrustedClient, NewBlocksNotify, SigningKeyPair}; +use ContractAddress; use_contract!(key_server, "res/key_server_set.json"); @@ -117,11 +117,11 @@ struct CachedContract { /// Previous confirm migration transaction. confirm_migration_tx: Option, /// This node key pair. - self_key_pair: Arc, + self_key_pair: Arc, } impl OnChainKeyServerSet { - pub fn new(trusted_client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { + pub fn new(trusted_client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { let key_server_set = Arc::new(OnChainKeyServerSet { contract: Mutex::new(CachedContract::new(trusted_client.clone(), contract_address_source, self_key_pair, auto_migrate_enabled, key_servers)?), }); @@ -220,7 +220,7 @@ impl ) -> Result, String>> KeyServerSubset for NewKeySe } impl CachedContract { - pub fn new(client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { + pub fn new(client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { let server_set = match contract_address_source.is_none() { true => key_servers.into_iter() .map(|(p, addr)| { diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index 37958c5af2e..4660df641ec 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -88,7 +88,8 @@ use parity_runtime::Executor; pub use types::{ServerKeyId, EncryptedDocumentKey, RequestSignature, Public, Error, NodeAddress, ContractAddress, ServiceConfiguration, ClusterConfiguration}; -pub use traits::{NodeKeyPair, KeyServer}; +pub use traits::KeyServer; +pub use trusted_client::SigningKeyPair; pub use self::node_key_pair::PlainNodeKeyPair; #[cfg(feature = "accounts")] pub use self::node_key_pair::KeyStoreNodeKeyPair; @@ -108,7 +109,7 @@ pub fn open_secretstore_db(data_path: &str) -> Result, Strin } /// Start new key server instance -pub fn start(client: Arc, sync: Arc, miner: Arc, self_key_pair: Arc, mut config: ServiceConfiguration, +pub fn start(client: Arc, sync: Arc, miner: Arc, self_key_pair: Arc, mut config: ServiceConfiguration, db: Arc, executor: Executor) -> Result, Error> { let trusted_client = trusted_client::TrustedClient::new(self_key_pair.clone(), client.clone(), sync, miner); diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index 51c89d9a1d4..2ec19a76ab8 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -25,8 +25,8 @@ use bytes::Bytes; use ethereum_types::{H256, U256, Address, H512}; use listener::ApiMask; use listener::service_contract_listener::ServiceTask; -use trusted_client::{TrustedClient, Filter}; -use {ServerKeyId, NodeKeyPair, ContractAddress}; +use trusted_client::{TrustedClient, Filter, SigningKeyPair}; +use {ServerKeyId, ContractAddress}; use_contract!(service, "res/service.json"); @@ -95,7 +95,7 @@ pub struct OnChainServiceContract { /// Blockchain client. client: Arc, /// This node key pair. - self_key_pair: Arc, + self_key_pair: Arc, /// Contract registry name (if any). name: String, /// Contract address source. @@ -133,7 +133,7 @@ struct DocumentKeyShadowRetrievalService; impl OnChainServiceContract { /// Create new on-chain service contract. - pub fn new(mask: ApiMask, client: Arc, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { + pub fn new(mask: ApiMask, client: Arc, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { let contract = OnChainServiceContract { mask: mask, client: client, @@ -185,7 +185,7 @@ impl OnChainServiceContract { /// Create task-specific pending requests iterator. fn create_pending_requests_iterator< C: 'static + Fn(&TrustedClient, &Address, &BlockId) -> Result, - R: 'static + Fn(&dyn NodeKeyPair, &TrustedClient, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> + R: 'static + Fn(&dyn SigningKeyPair, &TrustedClient, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { get_count(&*client, contract_address, block) .map(|count| { @@ -455,7 +455,7 @@ impl ServerKeyGenerationService { } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_generation_request::call(index); @@ -515,7 +515,7 @@ impl ServerKeyRetrievalService { } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_retrieval_request::call(index); @@ -578,7 +578,7 @@ impl DocumentKeyStoreService { } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); 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)?) @@ -658,7 +658,7 @@ impl DocumentKeyShadowRetrievalService { } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn NodeKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_document_key_shadow_retrieval_request::call(index); diff --git a/secret-store/src/listener/service_contract_listener.rs b/secret-store/src/listener/service_contract_listener.rs index b654ea7c800..5dd6e98721a 100644 --- a/secret-store/src/listener/service_contract_listener.rs +++ b/secret-store/src/listener/service_contract_listener.rs @@ -34,8 +34,8 @@ use parking_lot::Mutex; use acl_storage::AclStorage; use listener::service_contract::ServiceContract; use listener::tasks_queue::TasksQueue; -use {ServerKeyId, NodeKeyPair, Error}; -use trusted_client::NewBlocksNotify; +use {ServerKeyId, Error}; +use trusted_client::{NewBlocksNotify, SigningKeyPair}; /// Retry interval (in blocks). Every RETRY_INTERVAL_BLOCKS blocks each KeyServer reads pending requests from /// service contract && tries to re-execute. The reason to have this mechanism is primarily because keys @@ -63,7 +63,7 @@ pub struct ServiceContractListenerParams { /// Service contract. pub contract: Arc, /// This node key pair. - pub self_key_pair: Arc, + pub self_key_pair: Arc, /// Key servers set. pub key_server_set: Arc, /// ACL storage reference. @@ -89,7 +89,7 @@ struct ServiceContractListenerData { /// Cluster client reference. pub cluster: Arc, /// This node key pair. - pub self_key_pair: Arc, + pub self_key_pair: Arc, /// Key servers set. pub key_server_set: Arc, /// Key storage reference. @@ -589,7 +589,8 @@ mod tests { use key_storage::tests::DummyKeyStorage; use key_server_set::KeyServerSet; use key_server_set::tests::MapKeyServerSet; - use {NodeKeyPair, PlainNodeKeyPair, ServerKeyId}; + use trusted_client::SigningKeyPair; + use {PlainNodeKeyPair, ServerKeyId}; use super::{ServiceTask, ServiceContractListener, ServiceContractListenerParams, is_processed_by_this_key_server}; use ethereum_types::Address; diff --git a/secret-store/src/node_key_pair.rs b/secret-store/src/node_key_pair.rs index 5dbcf915c0d..bbcf9b96f41 100644 --- a/secret-store/src/node_key_pair.rs +++ b/secret-store/src/node_key_pair.rs @@ -16,7 +16,7 @@ use crypto::publickey::{KeyPair, Public, Signature, Error as EthKeyError, sign, public_to_address}; use ethereum_types::{H256, Address}; -use traits::NodeKeyPair; +use trusted_client::SigningKeyPair; pub struct PlainNodeKeyPair { key_pair: KeyPair, @@ -35,7 +35,7 @@ impl PlainNodeKeyPair { } } -impl NodeKeyPair for PlainNodeKeyPair { +impl SigningKeyPair for PlainNodeKeyPair { fn public(&self) -> &Public { self.key_pair.public() } @@ -75,7 +75,7 @@ mod accounts { } } - impl NodeKeyPair for KeyStoreNodeKeyPair { + impl SigningKeyPair for KeyStoreNodeKeyPair { fn public(&self) -> &Public { &self.public } diff --git a/secret-store/src/traits.rs b/secret-store/src/traits.rs index 2b509a4b5c0..de112fc9f29 100644 --- a/secret-store/src/traits.rs +++ b/secret-store/src/traits.rs @@ -16,21 +16,9 @@ use std::collections::BTreeSet; use futures::Future; -use crypto::publickey::{Signature, Error as EthKeyError}; -use ethereum_types::{H256, Address}; use types::{Error, Public, ServerKeyId, MessageHash, EncryptedMessageSignature, RequestSignature, Requester, EncryptedDocumentKey, EncryptedDocumentKeyShadow, NodeId}; -/// Node key pair. -pub trait NodeKeyPair: Send + Sync { - /// Public portion of key. - fn public(&self) -> &Public; - /// Address of key owner. - fn address(&self) -> Address; - /// Sign data with node key. - fn sign(&self, data: &H256) -> Result; -} - /// Server key (SK) generator. pub trait ServerKeyGenerator { /// Generate new SK. diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 2222ebbbbfa..6faa5bf9a9b 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -26,21 +26,32 @@ use common_types::{ log_entry::LocalizedLogEntry, }; use parking_lot::RwLock; -use ethereum_types::{H256, Address}; +use ethereum_types::{H256, Address, Public}; use ethcore::client::Client; use ethabi::RawLog; +use crypto::publickey::{Signature, Error as EthKeyError}; use client_traits::BlockChainClient; use call_contract::CallContract; use client_traits::{ChainInfo, Nonce, ChainNotify}; use ethcore::miner::{Miner, MinerService}; use sync::SyncProvider; -use {Error, NodeKeyPair, ContractAddress}; +use {Error, ContractAddress}; use registrar::RegistrarClient; // TODO: Instead of a constant, make this based on consensus finality. /// Number of confirmations required before request can be processed. const REQUEST_CONFIRMATIONS_REQUIRED: u64 = 3; +/// Key pair with signing ability. +pub trait SigningKeyPair: Send + Sync { + /// Public portion of key. + fn public(&self) -> &Public; + /// Address of key owner. + fn address(&self) -> Address; + /// Sign data with the key. + fn sign(&self, data: &H256) -> Result; +} + /// Wrapps client ChainNotify in order to send signal about new blocks pub trait NewBlocksNotify: Send + Sync { /// Fires when chain has new blocks. @@ -72,7 +83,7 @@ pub struct Filter { /// 'Trusted' client weak reference. pub struct TrustedClient { /// This key server node key pair. - self_key_pair: Arc, + self_key_pair: Arc, /// Blockchain client. client: Weak, /// Sync provider. @@ -85,7 +96,7 @@ pub struct TrustedClient { impl TrustedClient { /// Create new trusted client. - pub fn new(self_key_pair: Arc, client: Arc, sync: Arc, miner: Arc) -> Arc { + pub fn new(self_key_pair: Arc, client: Arc, sync: Arc, miner: Arc) -> Arc { let trusted_client = Arc::new(TrustedClient { self_key_pair, client: Arc::downgrade(&client), From e38acb312097955120546d3c73d910b240c4ba6a Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 18 Nov 2019 12:22:46 +0100 Subject: [PATCH 06/16] Use public key error in trusted client --- secret-store/src/trusted_client.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 6faa5bf9a9b..2165180dde7 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -35,7 +35,7 @@ use call_contract::CallContract; use client_traits::{ChainInfo, Nonce, ChainNotify}; use ethcore::miner::{Miner, MinerService}; use sync::SyncProvider; -use {Error, ContractAddress}; +use ContractAddress; use registrar::RegistrarClient; // TODO: Instead of a constant, make this based on consensus finality. @@ -141,9 +141,9 @@ impl TrustedClient { } /// Transact contract. - pub fn transact_contract(&self, contract: Address, tx_data: Bytes) -> Result<(), Error> { - let client = self.client.upgrade().ok_or_else(|| Error::Internal("cannot submit tx when client is offline".into()))?; - let miner = self.miner.upgrade().ok_or_else(|| Error::Internal("cannot submit tx when miner is offline".into()))?; + pub fn transact_contract(&self, contract: Address, tx_data: Bytes) -> Result<(), EthKeyError> { + let client = self.client.upgrade().ok_or_else(|| EthKeyError::Custom("cannot submit tx when client is offline".into()))?; + let miner = self.miner.upgrade().ok_or_else(|| EthKeyError::Custom("cannot submit tx when miner is offline".into()))?; let engine = client.engine(); let transaction = Transaction { nonce: client.latest_nonce(&self.self_key_pair.address()), @@ -157,7 +157,7 @@ impl TrustedClient { let signature = self.self_key_pair.sign(&transaction.hash(chain_id))?; let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?; miner.import_own_transaction(&*client, signed.into()) - .map_err(|e| Error::Internal(format!("failed to import tx: {}", e))) + .map_err(|e| EthKeyError::Custom(format!("failed to import tx: {}", e))) } /// Read contract address. If address source is registry, address only returned if current client state is From 3cb884b8c3c034b21f777403b10b2ec28fa3c044 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 18 Nov 2019 12:36:45 +0100 Subject: [PATCH 07/16] Move contract address definition into trusted client --- secret-store/src/acl_storage.rs | 4 ++-- secret-store/src/key_server_set.rs | 3 +-- secret-store/src/lib.rs | 4 ++-- secret-store/src/listener/service_contract.rs | 4 ++-- secret-store/src/trusted_client.rs | 10 +++++++++- secret-store/src/types/all.rs | 10 +--------- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/secret-store/src/acl_storage.rs b/secret-store/src/acl_storage.rs index 30687761e3e..85c1c79acf6 100644 --- a/secret-store/src/acl_storage.rs +++ b/secret-store/src/acl_storage.rs @@ -22,8 +22,8 @@ use common_types::{ use parking_lot::{Mutex, RwLock}; use ethereum_types::Address; use ethabi::FunctionOutputDecoder; -use trusted_client::{TrustedClient, NewBlocksNotify}; -use types::{Error, ServerKeyId, ContractAddress}; +use trusted_client::{TrustedClient, NewBlocksNotify, ContractAddress}; +use types::{Error, ServerKeyId}; use_contract!(acl_storage, "res/acl_storage.json"); diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index 41d34d815a2..fb48d7a713a 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -26,8 +26,7 @@ use ethereum_types::{H256, Address}; use crypto::publickey::public_to_address; use bytes::Bytes; use types::{Error, Public, NodeAddress, NodeId}; -use trusted_client::{TrustedClient, NewBlocksNotify, SigningKeyPair}; -use ContractAddress; +use trusted_client::{TrustedClient, NewBlocksNotify, SigningKeyPair, ContractAddress}; use_contract!(key_server, "res/key_server_set.json"); diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index 4660df641ec..13be71b582b 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -87,9 +87,9 @@ use sync::SyncProvider; use parity_runtime::Executor; pub use types::{ServerKeyId, EncryptedDocumentKey, RequestSignature, Public, - Error, NodeAddress, ContractAddress, ServiceConfiguration, ClusterConfiguration}; + Error, NodeAddress, ServiceConfiguration, ClusterConfiguration}; pub use traits::KeyServer; -pub use trusted_client::SigningKeyPair; +pub use trusted_client::{SigningKeyPair, ContractAddress}; pub use self::node_key_pair::PlainNodeKeyPair; #[cfg(feature = "accounts")] pub use self::node_key_pair::KeyStoreNodeKeyPair; diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index 2ec19a76ab8..01a9f53022a 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -25,8 +25,8 @@ use bytes::Bytes; use ethereum_types::{H256, U256, Address, H512}; use listener::ApiMask; use listener::service_contract_listener::ServiceTask; -use trusted_client::{TrustedClient, Filter, SigningKeyPair}; -use {ServerKeyId, ContractAddress}; +use trusted_client::{TrustedClient, Filter, SigningKeyPair, ContractAddress}; +use ServerKeyId; use_contract!(service, "res/service.json"); diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 2165180dde7..9915feb977f 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -35,13 +35,21 @@ use call_contract::CallContract; use client_traits::{ChainInfo, Nonce, ChainNotify}; use ethcore::miner::{Miner, MinerService}; use sync::SyncProvider; -use ContractAddress; use registrar::RegistrarClient; // TODO: Instead of a constant, make this based on consensus finality. /// Number of confirmations required before request can be processed. const REQUEST_CONFIRMATIONS_REQUIRED: u64 = 3; +/// Contract address. +#[derive(Debug, Clone)] +pub enum ContractAddress { + /// Address is read from registry. + Registry, + /// Address is specified. + Address(ethereum_types::Address), +} + /// Key pair with signing ability. pub trait SigningKeyPair: Send + Sync { /// Public portion of key. diff --git a/secret-store/src/types/all.rs b/secret-store/src/types/all.rs index 65ebbbc96da..45e6ec5b837 100644 --- a/secret-store/src/types/all.rs +++ b/secret-store/src/types/all.rs @@ -16,6 +16,7 @@ use std::collections::BTreeMap; +use trusted_client::ContractAddress; use {bytes, ethereum_types}; /// Node id. @@ -42,15 +43,6 @@ pub struct NodeAddress { pub port: u16, } -/// Contract address. -#[derive(Debug, Clone)] -pub enum ContractAddress { - /// Address is read from registry. - Registry, - /// Address is specified. - Address(crypto::publickey::Address), -} - /// Secret store configuration #[derive(Debug)] pub struct ServiceConfiguration { From c0a0198cc8d7f988572c770ef0b50d9671c2d503 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 18 Nov 2019 13:25:32 +0100 Subject: [PATCH 08/16] Block id and number types from ethcore wrapped --- secret-store/src/acl_storage.rs | 5 +-- secret-store/src/key_server_set.rs | 5 +-- secret-store/src/listener/service_contract.rs | 3 +- secret-store/src/trusted_client.rs | 45 +++++++++++++++---- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/secret-store/src/acl_storage.rs b/secret-store/src/acl_storage.rs index 85c1c79acf6..72d1a83601f 100644 --- a/secret-store/src/acl_storage.rs +++ b/secret-store/src/acl_storage.rs @@ -16,13 +16,10 @@ use std::sync::Arc; use std::collections::{HashMap, HashSet}; -use common_types::{ - ids::BlockId -}; use parking_lot::{Mutex, RwLock}; use ethereum_types::Address; use ethabi::FunctionOutputDecoder; -use trusted_client::{TrustedClient, NewBlocksNotify, ContractAddress}; +use trusted_client::{TrustedClient, NewBlocksNotify, ContractAddress, BlockId}; use types::{Error, ServerKeyId}; use_contract!(acl_storage, "res/acl_storage.json"); diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index fb48d7a713a..dd43d1502ad 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -19,14 +19,11 @@ use std::net::SocketAddr; use std::collections::{BTreeMap, HashSet}; use parking_lot::Mutex; use ethabi::FunctionOutputDecoder; -use common_types::{ - ids::BlockId, -}; use ethereum_types::{H256, Address}; use crypto::publickey::public_to_address; use bytes::Bytes; use types::{Error, Public, NodeAddress, NodeId}; -use trusted_client::{TrustedClient, NewBlocksNotify, SigningKeyPair, ContractAddress}; +use trusted_client::{TrustedClient, NewBlocksNotify, SigningKeyPair, ContractAddress, BlockId}; use_contract!(key_server, "res/key_server_set.json"); diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index 01a9f53022a..568d8465c35 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -18,14 +18,13 @@ use std::sync::Arc; use parking_lot::RwLock; use ethabi::RawLog; use ethabi::FunctionOutputDecoder; -use common_types::ids::BlockId; use crypto::publickey::{Public, public_to_address}; use hash::keccak; use bytes::Bytes; use ethereum_types::{H256, U256, Address, H512}; use listener::ApiMask; use listener::service_contract_listener::ServiceTask; -use trusted_client::{TrustedClient, Filter, SigningKeyPair, ContractAddress}; +use trusted_client::{TrustedClient, Filter, SigningKeyPair, ContractAddress, BlockId}; use ServerKeyId; use_contract!(service, "res/service.json"); diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 9915feb977f..1414a936a88 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -17,8 +17,7 @@ use std::sync::{Arc, Weak}; use bytes::Bytes; use common_types::{ - ids::BlockId, - BlockNumber, + ids::BlockId as EthcoreBlockId, transaction::{Transaction, SignedTransaction, Action}, chain_notify::NewBlocks, tree_route::TreeRoute, @@ -41,6 +40,36 @@ use registrar::RegistrarClient; /// Number of confirmations required before request can be processed. const REQUEST_CONFIRMATIONS_REQUIRED: u64 = 3; +/// Type for block number. +/// Duplicated from ethcore types +pub type BlockNumber = u64; + +/// Uniquely identifies block. +/// Duplicated from ethcore types +#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)] +pub enum BlockId { + /// Block's sha3. + /// Querying by hash is always faster. + Hash(H256), + /// Block number within canon blockchain. + Number(BlockNumber), + /// Earliest block (genesis). + Earliest, + /// Latest mined block. + Latest, +} + +impl From for EthcoreBlockId { + fn from(id: BlockId) -> Self { + match id { + BlockId::Hash(hash) => EthcoreBlockId::Hash(hash), + BlockId::Number(number) => EthcoreBlockId::Number(number), + BlockId::Earliest => EthcoreBlockId::Earliest, + BlockId::Latest => EthcoreBlockId::Latest, + } + } +} + /// Contract address. #[derive(Debug, Clone)] pub enum ContractAddress { @@ -181,7 +210,7 @@ impl TrustedClient { ContractAddress::Registry => self.get_trusted().and_then(|client| self.get_confirmed_block_hash() .and_then(|block| { - client.get_address(registry_name, BlockId::Hash(block)) + client.get_address(registry_name, EthcoreBlockId::Hash(block)) .unwrap_or(None) }) ), @@ -191,7 +220,7 @@ impl TrustedClient { /// Client's call_contract wrapper pub fn call_contract(&self, block_id: BlockId, contract_address: Address, data: Bytes) -> Result { if let Some(client) = self.get_trusted() { - client.call_contract(block_id, contract_address, data) + client.call_contract(EthcoreBlockId::from(block_id), contract_address, data) } else { Err("Calling ACL contract without trusted blockchain client".into()) } @@ -200,7 +229,7 @@ impl TrustedClient { /// Client's block_hash wrapper pub fn block_hash(&self, id: BlockId) -> Option { if let Some(client) = self.get_trusted() { - client.block_hash(id) + client.block_hash(EthcoreBlockId::from(id)) } else { None } @@ -209,7 +238,7 @@ impl TrustedClient { /// Client's block_number wrapper pub fn block_number(&self, id: BlockId) -> Option { if let Some(client) = self.get_trusted() { - client.block_number(id) + client.block_number(EthcoreBlockId::from(id)) } else { None } @@ -253,8 +282,8 @@ impl TrustedClient { }; self.logs(BlockchainFilter { - from_block: BlockId::Hash(first_block), - to_block: BlockId::Hash(confirmed_block), + from_block: EthcoreBlockId::Hash(first_block), + to_block: EthcoreBlockId::Hash(confirmed_block), address: filter.address, topics: filter.topics, limit: None, From 7d4e35e58b1779414c3089191bbcaca4a478ad1f Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 20 Nov 2019 11:56:45 +0100 Subject: [PATCH 09/16] Trusted client renamed to more general Blockchain --- secret-store/src/acl_storage.rs | 8 ++-- .../src/{trusted_client.rs => blockchain.rs} | 8 ++-- secret-store/src/key_server.rs | 2 +- .../servers_set_change_session.rs | 2 +- .../admin_sessions/share_add_session.rs | 2 +- .../src/key_server_cluster/cluster.rs | 4 +- .../cluster_connections_net.rs | 2 +- .../cluster_message_processor.rs | 2 +- .../key_server_cluster/cluster_sessions.rs | 2 +- .../key_server_cluster/connection_trigger.rs | 2 +- .../connection_trigger_with_migration.rs | 2 +- .../src/key_server_cluster/io/handshake.rs | 2 +- secret-store/src/key_server_cluster/mod.rs | 2 +- .../net/accept_connection.rs | 2 +- .../src/key_server_cluster/net/connect.rs | 2 +- secret-store/src/key_server_set.rs | 14 +++--- secret-store/src/lib.rs | 6 +-- secret-store/src/listener/service_contract.rs | 44 +++++++++---------- .../src/listener/service_contract_listener.rs | 4 +- secret-store/src/node_key_pair.rs | 2 +- secret-store/src/types/all.rs | 2 +- 21 files changed, 58 insertions(+), 58 deletions(-) rename secret-store/src/{trusted_client.rs => blockchain.rs} (98%) diff --git a/secret-store/src/acl_storage.rs b/secret-store/src/acl_storage.rs index 72d1a83601f..3c405ace314 100644 --- a/secret-store/src/acl_storage.rs +++ b/secret-store/src/acl_storage.rs @@ -19,7 +19,7 @@ use std::collections::{HashMap, HashSet}; use parking_lot::{Mutex, RwLock}; use ethereum_types::Address; use ethabi::FunctionOutputDecoder; -use trusted_client::{TrustedClient, NewBlocksNotify, ContractAddress, BlockId}; +use blockchain::{Blockchain, NewBlocksNotify, ContractAddress, BlockId}; use types::{Error, ServerKeyId}; use_contract!(acl_storage, "res/acl_storage.json"); @@ -41,7 +41,7 @@ pub struct OnChainAclStorage { /// Cached on-chain ACL storage contract. struct CachedContract { /// Blockchain client. - client: Arc, + client: Arc, /// Contract address source. address_source: ContractAddress, /// Current contract address. @@ -55,7 +55,7 @@ pub struct DummyAclStorage { } impl OnChainAclStorage { - pub fn new(trusted_client: Arc, address_source: ContractAddress) -> Result, Error> { + pub fn new(trusted_client: Arc, address_source: ContractAddress) -> Result, Error> { let acl_storage = Arc::new(OnChainAclStorage { contract: Mutex::new(CachedContract::new(trusted_client.clone(), address_source)), }); @@ -77,7 +77,7 @@ impl NewBlocksNotify for OnChainAclStorage { } impl CachedContract { - pub fn new(client: Arc, address_source: ContractAddress) -> Self { + pub fn new(client: Arc, address_source: ContractAddress) -> Self { let mut contract = CachedContract { client, address_source, diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/blockchain.rs similarity index 98% rename from secret-store/src/trusted_client.rs rename to secret-store/src/blockchain.rs index 1414a936a88..014f8396043 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/blockchain.rs @@ -118,7 +118,7 @@ pub struct Filter { } /// 'Trusted' client weak reference. -pub struct TrustedClient { +pub struct Blockchain { /// This key server node key pair. self_key_pair: Arc, /// Blockchain client. @@ -131,10 +131,10 @@ pub struct TrustedClient { listeners: RwLock>>, } -impl TrustedClient { +impl Blockchain { /// Create new trusted client. pub fn new(self_key_pair: Arc, client: Arc, sync: Arc, miner: Arc) -> Arc { - let trusted_client = Arc::new(TrustedClient { + let trusted_client = Arc::new(Blockchain { self_key_pair, client: Arc::downgrade(&client), sync: Arc::downgrade(&sync), @@ -307,7 +307,7 @@ impl TrustedClient { } } -impl ChainNotify for TrustedClient { +impl ChainNotify for Blockchain { fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return } if !new_blocks.route.enacted().is_empty() || !new_blocks.route.retracted().is_empty() { diff --git a/secret-store/src/key_server.rs b/secret-store/src/key_server.rs index 6b64ad349d9..6cb901dd85c 100644 --- a/secret-store/src/key_server.rs +++ b/secret-store/src/key_server.rs @@ -24,7 +24,7 @@ use parity_runtime::Executor; use super::acl_storage::AclStorage; use super::key_storage::KeyStorage; use super::key_server_set::KeyServerSet; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; use key_server_cluster::{math, new_network_cluster, ClusterSession, WaitableSession}; use traits::{AdminSessionsServer, ServerKeyGenerator, DocumentKeyServer, MessageSigner, KeyServer}; use types::{Error, Public, RequestSignature, Requester, ServerKeyId, EncryptedDocumentKey, EncryptedDocumentKeyShadow, diff --git a/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs b/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs index 3cce0fcd23d..0d35457de87 100644 --- a/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs +++ b/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs @@ -1051,7 +1051,7 @@ pub mod tests { use std::collections::{VecDeque, BTreeMap, BTreeSet}; use ethereum_types::H256; use crypto::publickey::{Random, Generator, Public, Signature, KeyPair, sign}; - use trusted_client::SigningKeyPair; + use blockchain::SigningKeyPair; use key_server_cluster::{NodeId, SessionId, Error, KeyStorage, PlainNodeKeyPair}; use key_server_cluster::cluster_sessions::ClusterSession; use key_server_cluster::cluster::tests::MessageLoop as ClusterMessageLoop; diff --git a/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs b/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs index 386f91a35b9..b6d1d5a2e5c 100644 --- a/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs +++ b/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs @@ -889,7 +889,7 @@ impl SessionTransport for IsolatedSessionTransport { pub mod tests { use std::collections::BTreeSet; use crypto::publickey::{Random, Generator, Public}; - use trusted_client::SigningKeyPair; + use blockchain::SigningKeyPair; use key_server_cluster::{NodeId, Error, KeyStorage}; use key_server_cluster::cluster::tests::MessageLoop as ClusterMessageLoop; use key_server_cluster::servers_set_change_session::tests::{MessageLoop, AdminSessionAdapter, generate_key}; diff --git a/secret-store/src/key_server_cluster/cluster.rs b/secret-store/src/key_server_cluster/cluster.rs index 9f67148fcca..741d6963559 100644 --- a/secret-store/src/key_server_cluster/cluster.rs +++ b/secret-store/src/key_server_cluster/cluster.rs @@ -20,7 +20,7 @@ use parking_lot::RwLock; use crypto::publickey::{Public, Signature, Random, Generator}; use ethereum_types::{Address, H256}; use parity_runtime::Executor; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; use key_server_cluster::{Error, NodeId, SessionId, Requester, AclStorage, KeyStorage, KeyServerSet}; use key_server_cluster::cluster_sessions::{WaitableSession, ClusterSession, AdminSession, ClusterSessions, SessionIdWithSubSession, ClusterSessionsContainer, SERVERS_SET_CHANGE_SESSION_ID, create_cluster_view, @@ -657,7 +657,7 @@ pub mod tests { use parking_lot::{Mutex, RwLock}; use ethereum_types::{Address, H256}; use crypto::publickey::{Random, Generator, Public, Signature, sign}; - use trusted_client::SigningKeyPair; + use blockchain::SigningKeyPair; use key_server_cluster::{NodeId, SessionId, Requester, Error, DummyAclStorage, DummyKeyStorage, MapKeyServerSet, PlainNodeKeyPair}; use key_server_cluster::message::Message; diff --git a/secret-store/src/key_server_cluster/cluster_connections_net.rs b/secret-store/src/key_server_cluster/cluster_connections_net.rs index 77ae12afaef..dcd7daeedbf 100644 --- a/secret-store/src/key_server_cluster/cluster_connections_net.rs +++ b/secret-store/src/key_server_cluster/cluster_connections_net.rs @@ -27,7 +27,7 @@ use tokio::timer::{Interval, timeout::Error as TimeoutError}; use tokio_io::IoFuture; use crypto::publickey::KeyPair; use parity_runtime::Executor; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; use key_server_cluster::{Error, NodeId, ClusterConfiguration}; use key_server_cluster::cluster_connections::{ConnectionProvider, Connection, ConnectionManager}; use key_server_cluster::connection_trigger::{Maintain, ConnectionTrigger}; diff --git a/secret-store/src/key_server_cluster/cluster_message_processor.rs b/secret-store/src/key_server_cluster/cluster_message_processor.rs index c9b42bb012b..ac21e760206 100644 --- a/secret-store/src/key_server_cluster/cluster_message_processor.rs +++ b/secret-store/src/key_server_cluster/cluster_message_processor.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::sync::Arc; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; use key_server_cluster::{Error, NodeId}; use key_server_cluster::cluster::{ServersSetChangeParams, new_servers_set_change_session}; use key_server_cluster::cluster_sessions::{AdminSession}; diff --git a/secret-store/src/key_server_cluster/cluster_sessions.rs b/secret-store/src/key_server_cluster/cluster_sessions.rs index bf589dce453..1e2510a362e 100644 --- a/secret-store/src/key_server_cluster/cluster_sessions.rs +++ b/secret-store/src/key_server_cluster/cluster_sessions.rs @@ -22,7 +22,7 @@ use futures::{oneshot, Oneshot, Complete, Future}; use parking_lot::{Mutex, RwLock, Condvar}; use ethereum_types::H256; use crypto::publickey::Secret; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; use key_server_cluster::{Error, NodeId, SessionId}; use key_server_cluster::cluster::{Cluster, ClusterConfiguration, ClusterView}; use key_server_cluster::cluster_connections::ConnectionProvider; diff --git a/secret-store/src/key_server_cluster/connection_trigger.rs b/secret-store/src/key_server_cluster/connection_trigger.rs index 356e38690bf..34578946fc9 100644 --- a/secret-store/src/key_server_cluster/connection_trigger.rs +++ b/secret-store/src/key_server_cluster/connection_trigger.rs @@ -26,7 +26,7 @@ use key_server_cluster::cluster_sessions::AdminSession; use key_server_cluster::cluster_connections::{Connection}; use key_server_cluster::cluster_connections_net::{NetConnectionsContainer}; use types::{Error, NodeId}; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; #[derive(Debug, Clone, Copy, PartialEq)] /// Describes which maintain() call is required. diff --git a/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs b/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs index 5c945ad2764..dc6d112c903 100644 --- a/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs +++ b/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs @@ -28,7 +28,7 @@ use key_server_cluster::jobs::servers_set_change_access_job::ordered_nodes_hash; use key_server_cluster::connection_trigger::{Maintain, ConnectionsAction, ConnectionTrigger, ServersSetChangeSessionCreatorConnector, TriggerConnections}; use types::{Error, NodeId}; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; /// Key servers set change trigger with automated migration procedure. pub struct ConnectionTriggerWithMigration { diff --git a/secret-store/src/key_server_cluster/io/handshake.rs b/secret-store/src/key_server_cluster/io/handshake.rs index 2b58f5988ed..e8febe2e96a 100644 --- a/secret-store/src/key_server_cluster/io/handshake.rs +++ b/secret-store/src/key_server_cluster/io/handshake.rs @@ -40,7 +40,7 @@ use tokio_io::{AsyncRead, AsyncWrite}; use crypto::publickey::ecdh::agree; use crypto::publickey::{Random, Generator, KeyPair, Public, Signature, verify_public, sign, recover}; use ethereum_types::H256; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; use key_server_cluster::{NodeId, Error}; use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature}; use key_server_cluster::io::{write_message, write_encrypted_message, WriteMessage, ReadMessage, diff --git a/secret-store/src/key_server_cluster/mod.rs b/secret-store/src/key_server_cluster/mod.rs index 6d033d69b02..5286c323f26 100644 --- a/secret-store/src/key_server_cluster/mod.rs +++ b/secret-store/src/key_server_cluster/mod.rs @@ -16,7 +16,7 @@ use super::types::ServerKeyId; -pub use super::trusted_client::SigningKeyPair; +pub use super::blockchain::SigningKeyPair; pub use super::types::{Error, NodeId, Requester, EncryptedDocumentKeyShadow}; pub use super::acl_storage::AclStorage; pub use super::key_storage::{KeyStorage, DocumentKeyShare, DocumentKeyShareVersion}; diff --git a/secret-store/src/key_server_cluster/net/accept_connection.rs b/secret-store/src/key_server_cluster/net/accept_connection.rs index bf567116cdd..ea3452c6eb7 100644 --- a/secret-store/src/key_server_cluster/net/accept_connection.rs +++ b/secret-store/src/key_server_cluster/net/accept_connection.rs @@ -20,7 +20,7 @@ use std::net::SocketAddr; use std::time::Duration; use futures::{Future, Poll}; use tokio::net::TcpStream; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; use key_server_cluster::Error; use key_server_cluster::io::{accept_handshake, Handshake, Deadline, deadline}; use key_server_cluster::net::Connection; diff --git a/secret-store/src/key_server_cluster/net/connect.rs b/secret-store/src/key_server_cluster/net/connect.rs index 0fd1c1318fd..448b7824367 100644 --- a/secret-store/src/key_server_cluster/net/connect.rs +++ b/secret-store/src/key_server_cluster/net/connect.rs @@ -21,7 +21,7 @@ use std::time::Duration; use std::net::SocketAddr; use futures::{Future, Poll, Async}; use tokio::net::{TcpStream, tcp::ConnectFuture}; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; use key_server_cluster::{Error, NodeId}; use key_server_cluster::io::{handshake, Handshake, Deadline, deadline}; use key_server_cluster::net::Connection; diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index dd43d1502ad..0f93a27a3e2 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -23,7 +23,7 @@ use ethereum_types::{H256, Address}; use crypto::publickey::public_to_address; use bytes::Bytes; use types::{Error, Public, NodeAddress, NodeId}; -use trusted_client::{TrustedClient, NewBlocksNotify, SigningKeyPair, ContractAddress, BlockId}; +use blockchain::{Blockchain, NewBlocksNotify, SigningKeyPair, ContractAddress, BlockId}; use_contract!(key_server, "res/key_server_set.json"); @@ -97,7 +97,7 @@ struct PreviousMigrationTransaction { /// Cached on-chain Key Server set contract. struct CachedContract { /// Blockchain client. - client: Arc, + client: Arc, /// Contract address source. contract_address_source: Option, /// Current contract address. @@ -117,7 +117,7 @@ struct CachedContract { } impl OnChainKeyServerSet { - pub fn new(trusted_client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { + pub fn new(trusted_client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { let key_server_set = Arc::new(OnChainKeyServerSet { contract: Mutex::new(CachedContract::new(trusted_client.clone(), contract_address_source, self_key_pair, auto_migrate_enabled, key_servers)?), }); @@ -216,7 +216,7 @@ impl ) -> Result, String>> KeyServerSubset for NewKeySe } impl CachedContract { - pub fn new(client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { + pub fn new(client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { let server_set = match contract_address_source.is_none() { true => key_servers.into_iter() .map(|(p, addr)| { @@ -531,7 +531,7 @@ fn update_number_of_confirmations H256, F2: Fn(H256) -> Option> snapshot.new_set = future_new_set.new_set; } -fn update_last_transaction_block(client: &TrustedClient, migration_id: &H256, previous_transaction: &mut Option) -> bool { +fn update_last_transaction_block(client: &Blockchain, migration_id: &H256, previous_transaction: &mut Option) -> bool { let last_block = client.block_number(BlockId::Latest).unwrap_or_default(); match previous_transaction.as_ref() { // no previous transaction => send immediately @@ -559,11 +559,11 @@ fn update_last_transaction_block(client: &TrustedClient, migration_id: &H256, pr true } -fn latest_block_hash(client: &TrustedClient) -> H256 { +fn latest_block_hash(client: &Blockchain) -> H256 { client.block_hash(BlockId::Latest).unwrap_or_default() } -fn block_confirmations(client: &TrustedClient, block: H256) -> Option { +fn block_confirmations(client: &Blockchain, block: H256) -> Option { client.block_number(BlockId::Hash(block)) .and_then(|block| client.block_number(BlockId::Latest).map(|last_block| (block, last_block))) .map(|(block, last_block)| last_block - block) diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index 13be71b582b..5a282b57c33 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -75,7 +75,7 @@ mod serialization; mod key_server_set; mod node_key_pair; mod listener; -mod trusted_client; +mod blockchain; mod migration; use std::sync::Arc; @@ -89,7 +89,7 @@ use parity_runtime::Executor; pub use types::{ServerKeyId, EncryptedDocumentKey, RequestSignature, Public, Error, NodeAddress, ServiceConfiguration, ClusterConfiguration}; pub use traits::KeyServer; -pub use trusted_client::{SigningKeyPair, ContractAddress}; +pub use blockchain::{SigningKeyPair, ContractAddress}; pub use self::node_key_pair::PlainNodeKeyPair; #[cfg(feature = "accounts")] pub use self::node_key_pair::KeyStoreNodeKeyPair; @@ -112,7 +112,7 @@ pub fn open_secretstore_db(data_path: &str) -> Result, Strin pub fn start(client: Arc, sync: Arc, miner: Arc, self_key_pair: Arc, mut config: ServiceConfiguration, db: Arc, executor: Executor) -> Result, Error> { - let trusted_client = trusted_client::TrustedClient::new(self_key_pair.clone(), client.clone(), sync, miner); + let trusted_client = blockchain::Blockchain::new(self_key_pair.clone(), client.clone(), sync, miner); let acl_storage: Arc = match config.acl_check_contract_address.take() { Some(acl_check_contract_address) => acl_storage::OnChainAclStorage::new(trusted_client.clone(), acl_check_contract_address)?, None => Arc::new(acl_storage::DummyAclStorage::default()), diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index 568d8465c35..00d58526bcf 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -24,7 +24,7 @@ use bytes::Bytes; use ethereum_types::{H256, U256, Address, H512}; use listener::ApiMask; use listener::service_contract_listener::ServiceTask; -use trusted_client::{TrustedClient, Filter, SigningKeyPair, ContractAddress, BlockId}; +use blockchain::{Blockchain, Filter, SigningKeyPair, ContractAddress, BlockId}; use ServerKeyId; use_contract!(service, "res/service.json"); @@ -92,7 +92,7 @@ pub struct OnChainServiceContract { /// Requests mask. mask: ApiMask, /// Blockchain client. - client: Arc, + client: Arc, /// This node key pair. self_key_pair: Arc, /// Contract registry name (if any). @@ -132,7 +132,7 @@ struct DocumentKeyShadowRetrievalService; impl OnChainServiceContract { /// Create new on-chain service contract. - pub fn new(mask: ApiMask, client: Arc, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { + pub fn new(mask: ApiMask, client: Arc, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { let contract = OnChainServiceContract { mask: mask, client: client, @@ -151,8 +151,8 @@ impl OnChainServiceContract { /// Send transaction to the service contract. fn send_contract_transaction(&self, tx_name: &str, origin: &Address, server_key_id: &ServerKeyId, is_response_required: C, prepare_tx: P) -> Result<(), String> - where C: FnOnce(&TrustedClient, &Address, &ServerKeyId, &Address) -> bool, - P: FnOnce(&TrustedClient, &Address) -> Result { + where C: FnOnce(&Blockchain, &Address, &ServerKeyId, &Address) -> bool, + P: FnOnce(&Blockchain, &Address) -> Result { // only publish if contract address is set && client is online if !self.client.is_trusted() { return Err("trusted client is required to publish key".into()) @@ -183,9 +183,9 @@ impl OnChainServiceContract { /// Create task-specific pending requests iterator. fn create_pending_requests_iterator< - C: 'static + Fn(&TrustedClient, &Address, &BlockId) -> Result, - R: 'static + Fn(&dyn SigningKeyPair, &TrustedClient, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> - >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { + C: 'static + Fn(&Blockchain, &Address, &BlockId) -> Result, + R: 'static + Fn(&dyn SigningKeyPair, &Blockchain, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> + >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { get_count(&*client, contract_address, block) .map(|count| { let client = client.clone(); @@ -427,7 +427,7 @@ impl ServerKeyGenerationService { } /// Check if response from key server is required. - pub fn is_response_required(client: &TrustedClient, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &Blockchain, 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 (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) { @@ -447,14 +447,14 @@ impl ServerKeyGenerationService { } /// Read pending requests count. - fn read_pending_requests_count(client: &TrustedClient, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &Blockchain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::server_key_generation_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_generation_request::call(index); @@ -487,7 +487,7 @@ impl ServerKeyRetrievalService { } /// Check if response from key server is required. - pub fn is_response_required(client: &TrustedClient, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &Blockchain, 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 (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) { @@ -507,14 +507,14 @@ impl ServerKeyRetrievalService { } /// Read pending requests count. - fn read_pending_requests_count(client: &TrustedClient, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &Blockchain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::server_key_retrieval_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_retrieval_request::call(index); @@ -550,7 +550,7 @@ impl DocumentKeyStoreService { } /// Check if response from key server is required. - pub fn is_response_required(client: &TrustedClient, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &Blockchain, 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 (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) { @@ -570,14 +570,14 @@ impl DocumentKeyStoreService { } /// Read pending requests count. - fn read_pending_requests_count(client: &TrustedClient, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &Blockchain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::document_key_store_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); 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)?) @@ -617,7 +617,7 @@ impl DocumentKeyShadowRetrievalService { } /// Check if response from key server is required. - pub fn is_response_required(client: &TrustedClient, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, key_server: &Address) -> bool { + pub fn is_response_required(client: &Blockchain, 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 (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) { @@ -632,7 +632,7 @@ impl DocumentKeyShadowRetrievalService { } /// Prepare publish personal key transaction data. - pub fn prepare_pubish_personal_tx_data(client: &TrustedClient, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result { + pub fn prepare_pubish_personal_tx_data(client: &Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result { let mut participants_mask = U256::default(); for participant in participants { let participant_index = Self::map_key_server_address(client, contract_address, participant.clone()) @@ -650,14 +650,14 @@ impl DocumentKeyShadowRetrievalService { } /// Read pending requests count. - fn read_pending_requests_count(client: &TrustedClient, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &Blockchain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::document_key_shadow_retrieval_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &TrustedClient, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_document_key_shadow_retrieval_request::call(index); @@ -687,7 +687,7 @@ impl DocumentKeyShadowRetrievalService { } /// Map from key server address to key server index. - fn map_key_server_address(client: &TrustedClient, contract_address: &Address, key_server: Address) -> Result { + fn map_key_server_address(client: &Blockchain, contract_address: &Address, key_server: Address) -> Result { // we're checking confirmation in Latest block, because tx ,ust be appended to the latest state let (encoded, decoder) = service::functions::require_key_server::call(key_server); let index = decoder.decode(&client.call_contract(BlockId::Latest, *contract_address, encoded)?) diff --git a/secret-store/src/listener/service_contract_listener.rs b/secret-store/src/listener/service_contract_listener.rs index 5dd6e98721a..9ed44fbb4ae 100644 --- a/secret-store/src/listener/service_contract_listener.rs +++ b/secret-store/src/listener/service_contract_listener.rs @@ -35,7 +35,7 @@ use acl_storage::AclStorage; use listener::service_contract::ServiceContract; use listener::tasks_queue::TasksQueue; use {ServerKeyId, Error}; -use trusted_client::{NewBlocksNotify, SigningKeyPair}; +use blockchain::{NewBlocksNotify, SigningKeyPair}; /// Retry interval (in blocks). Every RETRY_INTERVAL_BLOCKS blocks each KeyServer reads pending requests from /// service contract && tries to re-execute. The reason to have this mechanism is primarily because keys @@ -589,7 +589,7 @@ mod tests { use key_storage::tests::DummyKeyStorage; use key_server_set::KeyServerSet; use key_server_set::tests::MapKeyServerSet; - use trusted_client::SigningKeyPair; + use blockchain::SigningKeyPair; use {PlainNodeKeyPair, ServerKeyId}; use super::{ServiceTask, ServiceContractListener, ServiceContractListenerParams, is_processed_by_this_key_server}; use ethereum_types::Address; diff --git a/secret-store/src/node_key_pair.rs b/secret-store/src/node_key_pair.rs index bbcf9b96f41..4c169e2d174 100644 --- a/secret-store/src/node_key_pair.rs +++ b/secret-store/src/node_key_pair.rs @@ -16,7 +16,7 @@ use crypto::publickey::{KeyPair, Public, Signature, Error as EthKeyError, sign, public_to_address}; use ethereum_types::{H256, Address}; -use trusted_client::SigningKeyPair; +use blockchain::SigningKeyPair; pub struct PlainNodeKeyPair { key_pair: KeyPair, diff --git a/secret-store/src/types/all.rs b/secret-store/src/types/all.rs index 45e6ec5b837..b37ffe6b094 100644 --- a/secret-store/src/types/all.rs +++ b/secret-store/src/types/all.rs @@ -16,7 +16,7 @@ use std::collections::BTreeMap; -use trusted_client::ContractAddress; +use blockchain::ContractAddress; use {bytes, ethereum_types}; /// Node id. From 966ba3f69deb6656c2786a292d1edbf6edeb1845 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 20 Nov 2019 14:50:05 +0100 Subject: [PATCH 10/16] Trusted client implementation moved to parity code --- Cargo.lock | 8 +- Cargo.toml | 4 +- parity/lib.rs | 6 + parity/secretstore/blockchain.rs | 242 ++++++++++++++++++ parity/secretstore/mod.rs | 31 +++ parity/secretstore/nodekeypair.rs | 57 +++++ .../{secretstore.rs => secretstore/server.rs} | 13 +- secret-store/Cargo.toml | 9 +- secret-store/src/acl_storage.rs | 6 +- secret-store/src/blockchain.rs | 234 ++--------------- secret-store/src/key_server_set.rs | 12 +- secret-store/src/lib.rs | 20 +- secret-store/src/listener/service_contract.rs | 42 +-- secret-store/src/node_key_pair.rs | 45 ---- 14 files changed, 402 insertions(+), 327 deletions(-) create mode 100644 parity/secretstore/blockchain.rs create mode 100644 parity/secretstore/mod.rs create mode 100644 parity/secretstore/nodekeypair.rs rename parity/{secretstore.rs => secretstore/server.rs} (93%) diff --git a/Cargo.lock b/Cargo.lock index 8d60c228956..182bf6a069c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1477,18 +1477,12 @@ name = "ethcore-secretstore" version = "1.0.0" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "client-traits 0.1.0", - "common-types 0.1.0", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", - "ethcore-accounts 0.1.0", - "ethcore-call-contract 0.1.0", - "ethcore-sync 1.12.0", "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethkey 0.4.0", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-server-utils 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3085,9 +3079,11 @@ dependencies = [ "dir 0.1.2", "docopt 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "engine 0.1.0", + "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-accounts 0.1.0", "ethcore-blockchain 0.1.0", + "ethcore-call-contract 0.1.0", "ethcore-db 0.1.0", "ethcore-io 1.12.0", "ethcore-light 1.12.0", diff --git a/Cargo.toml b/Cargo.toml index 53ffb641ee8..fdae74303df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,9 +18,11 @@ ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" } dir = { path = "util/dir" } docopt = "1.0" engine = { path = "ethcore/engine" } +ethabi = { version = "9.0.1", optional = true } ethcore = { path = "ethcore", features = ["parity"] } ethcore-accounts = { path = "accounts", optional = true } ethcore-blockchain = { path = "ethcore/blockchain" } +ethcore-call-contract = { path = "ethcore/call-contract", optional = true } ethcore-db = { path = "ethcore/db" } ethcore-io = { path = "util/io" } ethcore-light = { path = "ethcore/light" } @@ -97,7 +99,7 @@ test-heavy = ["ethcore/test-heavy"] evm-debug = ["ethcore/evm-debug"] evm-debug-tests = ["ethcore/evm-debug-tests"] slow-blocks = ["ethcore/slow-blocks"] -secretstore = ["ethcore-secretstore", "ethcore-secretstore/accounts"] +secretstore = ["ethcore-secretstore", "ethcore-secretstore/accounts", "ethabi", "ethcore-call-contract"] final = ["parity-version/final"] deadlock_detection = ["parking_lot/deadlock_detection"] # to create a memory profile (requires nightly rust), use e.g. diff --git a/parity/lib.rs b/parity/lib.rs index 0af8ce4190f..c814200bbf1 100644 --- a/parity/lib.rs +++ b/parity/lib.rs @@ -86,6 +86,12 @@ extern crate ethcore_accounts as accounts; #[cfg(feature = "secretstore")] extern crate ethcore_secretstore; +#[cfg(feature = "secretstore")] +extern crate ethabi; + +#[cfg(feature = "secretstore")] +extern crate ethcore_call_contract as call_contract; + #[cfg(test)] #[macro_use] extern crate pretty_assertions; diff --git a/parity/secretstore/blockchain.rs b/parity/secretstore/blockchain.rs new file mode 100644 index 00000000000..d46160fe079 --- /dev/null +++ b/parity/secretstore/blockchain.rs @@ -0,0 +1,242 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Ethereum. If not, see . + +use std::sync::{Arc, Weak}; +use ethereum_types::{H256, Address}; +use parking_lot::RwLock; +use types::{ + ids::BlockId as EthcoreBlockId, + transaction::{Transaction, SignedTransaction, Action}, + chain_notify::NewBlocks, + tree_route::TreeRoute, + filter::Filter as BlockchainFilter, + log_entry::LocalizedLogEntry, +}; +use ethcore::client::Client; +use bytes::Bytes; +use ethabi::RawLog; +use client_traits::BlockChainClient; +use call_contract::CallContract; +use client_traits::{ChainInfo, Nonce, ChainNotify}; +use ethcore::miner::{Miner, MinerService}; +use parity_crypto::publickey::Error as EthKeyError; +use sync::SyncProvider; +use registrar::RegistrarClient; +use ethcore_secretstore::{BlockId, BlockNumber, Blockchain, NewBlocksNotify, SigningKeyPair, ContractAddress, Filter}; + +// TODO: Instead of a constant, make this based on consensus finality. +/// Number of confirmations required before request can be processed. +const REQUEST_CONFIRMATIONS_REQUIRED: u64 = 3; + +fn into_ethcore_block_id(id: BlockId) -> EthcoreBlockId { + match id { + BlockId::Hash(hash) => EthcoreBlockId::Hash(hash), + BlockId::Number(number) => EthcoreBlockId::Number(number), + BlockId::Earliest => EthcoreBlockId::Earliest, + BlockId::Latest => EthcoreBlockId::Latest, + } +} + +/// SecretStore blockchain implementation (client's wrapper) +pub struct TrustedClient { + /// This key server node key pair. + self_key_pair: Arc, + /// Blockchain client. + client: Weak, + /// Sync provider. + sync: Weak, + /// Miner service. + miner: Weak, + /// Chain new blocks listeners + listeners: RwLock>>, +} + +impl TrustedClient { + /// Create new trusted client. + pub fn new(self_key_pair: Arc, client: Arc, sync: Arc, miner: Arc) -> Arc { + let trusted_client = Arc::new(TrustedClient { + self_key_pair, + client: Arc::downgrade(&client), + sync: Arc::downgrade(&sync), + miner: Arc::downgrade(&miner), + listeners: RwLock::default(), + }); + client.add_notify(trusted_client.clone()); + trusted_client + } + + fn notify_listeners(&self, new_enacted_len: usize) { + for np in self.listeners.read().iter() { + if let Some(n) = np.upgrade() { + n.new_blocks(new_enacted_len); + } + } + } + + /// Get 'trusted' `Client` reference only if it is synchronized && trusted. + fn get_trusted(&self) -> Option> { + self.client.upgrade() + .and_then(|client| self.sync.upgrade().map(|sync| (client, sync))) + .and_then(|(client, sync)| { + let is_synced = !sync.is_major_syncing(); + let is_trusted = client.chain_info().security_level().is_full(); + match is_synced && is_trusted { + true => Some(client), + false => None, + } + }) + } + + fn tree_route(&self, from: &H256, to: &H256) -> Option { + if let Some(client) = self.get_trusted() { + client.tree_route(from, to) + } else { + None + } + } + + fn logs(&self, filter: BlockchainFilter) -> Option> { + if let Some(client) = self.get_trusted() { + client.logs(filter).ok() + } else { + None + } + } + +} + +impl Blockchain for TrustedClient { + fn add_listener(&self, target: Arc) { + self.listeners.write().push(Arc::downgrade(&target)); + } + + fn is_trusted(&self) -> bool { + self.get_trusted().is_some() + } + + fn transact_contract(&self, contract: Address, tx_data: Bytes) -> Result<(), EthKeyError> { + let client = self.client.upgrade().ok_or_else(|| EthKeyError::Custom("cannot submit tx when client is offline".into()))?; + let miner = self.miner.upgrade().ok_or_else(|| EthKeyError::Custom("cannot submit tx when miner is offline".into()))?; + let engine = client.engine(); + let transaction = Transaction { + nonce: client.latest_nonce(&self.self_key_pair.address()), + action: Action::Call(contract), + gas: miner.authoring_params().gas_range_target.0, + gas_price: miner.sensible_gas_price(), + value: Default::default(), + data: tx_data, + }; + let chain_id = engine.signing_chain_id(&client.latest_env_info()); + let signature = self.self_key_pair.sign(&transaction.hash(chain_id))?; + let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?; + miner.import_own_transaction(&*client, signed.into()) + .map_err(|e| EthKeyError::Custom(format!("failed to import tx: {}", e))) + } + + fn read_contract_address( + &self, + registry_name: &str, + address: &ContractAddress + ) -> Option
{ + match *address { + ContractAddress::Address(ref address) => Some(address.clone()), + ContractAddress::Registry => self.get_trusted().and_then(|client| + self.get_confirmed_block_hash() + .and_then(|block| { + client.get_address(registry_name, EthcoreBlockId::Hash(block)) + .unwrap_or(None) + }) + ), + } + } + + fn call_contract(&self, block_id: BlockId, contract_address: Address, data: Bytes) -> Result { + if let Some(client) = self.get_trusted() { + client.call_contract(into_ethcore_block_id(block_id), contract_address, data) + } else { + Err("Calling ACL contract without trusted blockchain client".into()) + } + } + + fn block_hash(&self, id: BlockId) -> Option { + if let Some(client) = self.get_trusted() { + client.block_hash(into_ethcore_block_id(id)) + } else { + None + } + } + + fn block_number(&self, id: BlockId) -> Option { + if let Some(client) = self.get_trusted() { + client.block_number(into_ethcore_block_id(id)) + } else { + None + } + } + + fn retrieve_last_logs(&self, filter: Filter) -> Option> { + let confirmed_block = match self.get_confirmed_block_hash() { + Some(confirmed_block) => confirmed_block, + None => return None, // no block with enough confirmations + }; + + let from_block = self.block_hash(filter.from_block).unwrap_or_else(|| confirmed_block); + let first_block = match self.tree_route(&from_block, &confirmed_block) { + // if we have a route from last_log_block to confirmed_block => search for logs on this route + // + // potentially this could lead us to reading same logs twice when reorganizing to the fork, which + // already has been canonical previosuly + // the worst thing that can happen in this case is spending some time reading unneeded data from SS db + Some(ref route) if route.index < route.blocks.len() => route.blocks[route.index], + // else we care only about confirmed block + _ => confirmed_block.clone(), + }; + + self.logs(BlockchainFilter { + from_block: EthcoreBlockId::Hash(first_block), + to_block: EthcoreBlockId::Hash(confirmed_block), + address: filter.address, + topics: filter.topics, + limit: None, + }) + .map(|blockchain_logs| { + blockchain_logs + .into_iter() + .map(|log| { + let raw_log: RawLog = (log.entry.topics.into_iter().map(|t| t.0.into()).collect(), log.entry.data).into(); + raw_log + }) + .collect::>() + }) + } + + fn get_confirmed_block_hash(&self) -> Option { + self.block_number(BlockId::Latest) + .map(|b| b.saturating_sub(REQUEST_CONFIRMATIONS_REQUIRED)) + .and_then(|b| self.block_hash(BlockId::Number(b))) + } +} + +impl ChainNotify for TrustedClient { + fn new_blocks(&self, new_blocks: NewBlocks) { + if new_blocks.has_more_blocks_to_import { return } + if !new_blocks.route.enacted().is_empty() || !new_blocks.route.retracted().is_empty() { + let enacted_len = new_blocks.route.enacted().len(); + self.notify_listeners(enacted_len); + } + } +} + diff --git a/parity/secretstore/mod.rs b/parity/secretstore/mod.rs new file mode 100644 index 00000000000..3c34ad2ad0c --- /dev/null +++ b/parity/secretstore/mod.rs @@ -0,0 +1,31 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Ethereum. If not, see . + +//! Secret store related components. + +mod server; + +#[cfg(feature = "secretstore")] +mod blockchain; + +#[cfg(feature = "accounts")] +mod nodekeypair; + +pub use self::server::{Configuration, NodeSecretKey, ContractAddress, Dependencies, start}; +#[cfg(feature = "secretstore")] +use self::blockchain::TrustedClient; +#[cfg(feature = "accounts")] +use self::nodekeypair::KeyStoreNodeKeyPair; \ No newline at end of file diff --git a/parity/secretstore/nodekeypair.rs b/parity/secretstore/nodekeypair.rs new file mode 100644 index 00000000000..2c9e9353f1a --- /dev/null +++ b/parity/secretstore/nodekeypair.rs @@ -0,0 +1,57 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Ethereum. If not, see . + +use std::sync::Arc; +use accounts::AccountProvider; +use ethkey::Password; +use parity_crypto::publickey::public_to_address; +use ethereum_types::{H256, Address, Public}; +use parity_crypto::publickey::{Signature, Error as EthKeyError}; +use ethcore_secretstore::SigningKeyPair; + +pub struct KeyStoreNodeKeyPair { + account_provider: Arc, + address: Address, + public: Public, + password: Password, +} + +impl KeyStoreNodeKeyPair { + pub fn new(account_provider: Arc, address: Address, password: Password) -> Result { + let public = account_provider.account_public(address.clone(), &password).map_err(|e| EthKeyError::Custom(format!("{}", e)))?; + Ok(KeyStoreNodeKeyPair { + account_provider: account_provider, + address: address, + public: public, + password: password, + }) + } +} + +impl SigningKeyPair for KeyStoreNodeKeyPair { + fn public(&self) -> &Public { + &self.public + } + + fn address(&self) -> Address { + public_to_address(&self.public) + } + + fn sign(&self, data: &H256) -> Result { + self.account_provider.sign(self.address.clone(), Some(self.password.clone()), data.clone()) + .map_err(|e| EthKeyError::Custom(format!("{}", e))) + } +} diff --git a/parity/secretstore.rs b/parity/secretstore/server.rs similarity index 93% rename from parity/secretstore.rs rename to parity/secretstore/server.rs index 25af61e870d..d46b97c7520 100644 --- a/parity/secretstore.rs +++ b/parity/secretstore/server.rs @@ -125,6 +125,9 @@ mod server { use parity_crypto::publickey::KeyPair; use ansi_term::Colour::{Red, White}; use super::{Configuration, Dependencies, NodeSecretKey, ContractAddress, Executor}; + use super::super::TrustedClient; + #[cfg(feature = "accounts")] + use super::super::KeyStoreNodeKeyPair; fn into_service_contract_address(address: ContractAddress) -> ethcore_secretstore::ContractAddress { match address { @@ -141,7 +144,7 @@ mod server { impl KeyServer { /// Create new key server pub fn new(mut conf: Configuration, deps: Dependencies, executor: Executor) -> Result { - let self_secret: Arc = match conf.self_secret.take() { + let self_secret: Arc = match conf.self_secret.take() { Some(NodeSecretKey::Plain(secret)) => Arc::new(ethcore_secretstore::PlainNodeKeyPair::new( KeyPair::from_secret(secret).map_err(|e| format!("invalid secret: {}", e))?)), #[cfg(feature = "accounts")] @@ -160,7 +163,7 @@ mod server { let password = deps.accounts_passwords.iter() .find(|p| deps.account_provider.sign(account.clone(), Some((*p).clone()), Default::default()).is_ok()) .ok_or_else(|| format!("No valid password for the secret store node account {}", account))?; - Arc::new(ethcore_secretstore::KeyStoreNodeKeyPair::new(deps.account_provider, account, password.clone()) + Arc::new(KeyStoreNodeKeyPair::new(deps.account_provider, account, password.clone()) .map_err(|e| format!("{}", e))?) }, None => return Err("self secret is required when using secretstore".into()), @@ -202,8 +205,14 @@ mod server { cconf.cluster_config.nodes.insert(self_secret.public().clone(), cconf.cluster_config.listener_address.clone()); +<<<<<<< HEAD:parity/secretstore.rs let db = ethcore_secretstore::open_secretstore_db(&conf.data_path)?; let key_server = ethcore_secretstore::start(deps.client, deps.sync, deps.miner, self_secret, cconf, db, executor) +======= + let db = db::open_secretstore_db(&conf.data_path)?; + let trusted_client = TrustedClient::new(self_secret.clone(), deps.client, deps.sync, deps.miner); + let key_server = ethcore_secretstore::start(trusted_client, self_secret, cconf, db, executor) +>>>>>>> 3040bcd... Trusted client implementation moved to parity code:parity/secretstore/server.rs .map_err(|e| format!("Error starting KeyServer {}: {}", key_server_name, e))?; Ok(KeyServer { diff --git a/secret-store/Cargo.toml b/secret-store/Cargo.toml index 11cad8ba211..254acfb8783 100644 --- a/secret-store/Cargo.toml +++ b/secret-store/Cargo.toml @@ -7,15 +7,9 @@ authors = ["Parity Technologies "] [dependencies] byteorder = "1.0" -client-traits = { path = "../ethcore/client-traits" } -common-types = { path = "../ethcore/types" } ethabi = "9.0.1" ethabi-contract = "9.0.0" ethabi-derive = "9.0.1" -ethcore = { path = "../ethcore" } -ethcore-accounts = { path = "../accounts", optional = true} -ethcore-call-contract = { path = "../ethcore/call-contract" } -ethcore-sync = { path = "../ethcore/sync" } ethereum-types = "0.8.0" ethkey = { path = "../accounts/ethkey", optional = true } futures = "0.1" @@ -44,10 +38,9 @@ jsonrpc-server-utils = "14.0.3" [dev-dependencies] env_logger = "0.5" -ethkey = { path = "../accounts/ethkey" } ethcore = { path = "../ethcore", features = ["test-helpers"] } tempdir = "0.3" kvdb-rocksdb = "0.3.0" [features] -accounts = ["ethcore-accounts", "ethkey"] +accounts = [] diff --git a/secret-store/src/acl_storage.rs b/secret-store/src/acl_storage.rs index 3c405ace314..b57f10a59d9 100644 --- a/secret-store/src/acl_storage.rs +++ b/secret-store/src/acl_storage.rs @@ -41,7 +41,7 @@ pub struct OnChainAclStorage { /// Cached on-chain ACL storage contract. struct CachedContract { /// Blockchain client. - client: Arc, + client: Arc, /// Contract address source. address_source: ContractAddress, /// Current contract address. @@ -55,7 +55,7 @@ pub struct DummyAclStorage { } impl OnChainAclStorage { - pub fn new(trusted_client: Arc, address_source: ContractAddress) -> Result, Error> { + pub fn new(trusted_client: Arc, address_source: ContractAddress) -> Result, Error> { let acl_storage = Arc::new(OnChainAclStorage { contract: Mutex::new(CachedContract::new(trusted_client.clone(), address_source)), }); @@ -77,7 +77,7 @@ impl NewBlocksNotify for OnChainAclStorage { } impl CachedContract { - pub fn new(client: Arc, address_source: ContractAddress) -> Self { + pub fn new(client: Arc, address_source: ContractAddress) -> Self { let mut contract = CachedContract { client, address_source, diff --git a/secret-store/src/blockchain.rs b/secret-store/src/blockchain.rs index 014f8396043..4e91e7a4db9 100644 --- a/secret-store/src/blockchain.rs +++ b/secret-store/src/blockchain.rs @@ -14,31 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use std::sync::{Arc, Weak}; +use std::sync::Arc; use bytes::Bytes; -use common_types::{ - ids::BlockId as EthcoreBlockId, - transaction::{Transaction, SignedTransaction, Action}, - chain_notify::NewBlocks, - tree_route::TreeRoute, - filter::Filter as BlockchainFilter, - log_entry::LocalizedLogEntry, -}; -use parking_lot::RwLock; use ethereum_types::{H256, Address, Public}; -use ethcore::client::Client; use ethabi::RawLog; use crypto::publickey::{Signature, Error as EthKeyError}; -use client_traits::BlockChainClient; -use call_contract::CallContract; -use client_traits::{ChainInfo, Nonce, ChainNotify}; -use ethcore::miner::{Miner, MinerService}; -use sync::SyncProvider; -use registrar::RegistrarClient; - -// TODO: Instead of a constant, make this based on consensus finality. -/// Number of confirmations required before request can be processed. -const REQUEST_CONFIRMATIONS_REQUIRED: u64 = 3; /// Type for block number. /// Duplicated from ethcore types @@ -59,17 +39,6 @@ pub enum BlockId { Latest, } -impl From for EthcoreBlockId { - fn from(id: BlockId) -> Self { - match id { - BlockId::Hash(hash) => EthcoreBlockId::Hash(hash), - BlockId::Number(number) => EthcoreBlockId::Number(number), - BlockId::Earliest => EthcoreBlockId::Earliest, - BlockId::Latest => EthcoreBlockId::Latest, - } - } -} - /// Contract address. #[derive(Debug, Clone)] pub enum ContractAddress { @@ -117,203 +86,34 @@ pub struct Filter { pub topics: Vec>>, } -/// 'Trusted' client weak reference. -pub struct Blockchain { - /// This key server node key pair. - self_key_pair: Arc, - /// Blockchain client. - client: Weak, - /// Sync provider. - sync: Weak, - /// Miner service. - miner: Weak, - /// Chain new blocks listeners - listeners: RwLock>>, -} - -impl Blockchain { - /// Create new trusted client. - pub fn new(self_key_pair: Arc, client: Arc, sync: Arc, miner: Arc) -> Arc { - let trusted_client = Arc::new(Blockchain { - self_key_pair, - client: Arc::downgrade(&client), - sync: Arc::downgrade(&sync), - miner: Arc::downgrade(&miner), - listeners: RwLock::default(), - }); - client.add_notify(trusted_client.clone()); - trusted_client - } - +/// Blockchain representation for Secret Store +pub trait Blockchain: Send + Sync + 'static { /// Adds listener for chain's NewBlocks event - pub fn add_listener(&self, target: Arc) { - self.listeners.write().push(Arc::downgrade(&target)); - } - - fn notify_listeners(&self, new_enacted_len: usize) { - for np in self.listeners.read().iter() { - if let Some(n) = np.upgrade() { - n.new_blocks(new_enacted_len); - } - } - } - - /// Check if the underlying client is in the trusted state - pub fn is_trusted(&self) -> bool { - self.get_trusted().is_some() - } + fn add_listener(&self, target: Arc); - /// Get 'trusted' `Client` reference only if it is synchronized && trusted. - fn get_trusted(&self) -> Option> { - self.client.upgrade() - .and_then(|client| self.sync.upgrade().map(|sync| (client, sync))) - .and_then(|(client, sync)| { - let is_synced = !sync.is_major_syncing(); - let is_trusted = client.chain_info().security_level().is_full(); - match is_synced && is_trusted { - true => Some(client), - false => None, - } - }) - } + /// Check if the underlying chain is in the trusted state + fn is_trusted(&self) -> bool; /// Transact contract. - pub fn transact_contract(&self, contract: Address, tx_data: Bytes) -> Result<(), EthKeyError> { - let client = self.client.upgrade().ok_or_else(|| EthKeyError::Custom("cannot submit tx when client is offline".into()))?; - let miner = self.miner.upgrade().ok_or_else(|| EthKeyError::Custom("cannot submit tx when miner is offline".into()))?; - let engine = client.engine(); - let transaction = Transaction { - nonce: client.latest_nonce(&self.self_key_pair.address()), - action: Action::Call(contract), - gas: miner.authoring_params().gas_range_target.0, - gas_price: miner.sensible_gas_price(), - value: Default::default(), - data: tx_data, - }; - let chain_id = engine.signing_chain_id(&client.latest_env_info()); - let signature = self.self_key_pair.sign(&transaction.hash(chain_id))?; - let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?; - miner.import_own_transaction(&*client, signed.into()) - .map_err(|e| EthKeyError::Custom(format!("failed to import tx: {}", e))) - } + fn transact_contract(&self, contract: Address, tx_data: Bytes) -> Result<(), EthKeyError>; /// Read contract address. If address source is registry, address only returned if current client state is /// trusted. Address from registry is read from registry from block latest block with /// REQUEST_CONFIRMATIONS_REQUIRED confirmations. - pub fn read_contract_address( - &self, - registry_name: &str, - address: &ContractAddress - ) -> Option
{ - match *address { - ContractAddress::Address(ref address) => Some(address.clone()), - ContractAddress::Registry => self.get_trusted().and_then(|client| - self.get_confirmed_block_hash() - .and_then(|block| { - client.get_address(registry_name, EthcoreBlockId::Hash(block)) - .unwrap_or(None) - }) - ), - } - } + fn read_contract_address(&self, registry_name: &str, address: &ContractAddress) -> Option
; - /// Client's call_contract wrapper - pub fn call_contract(&self, block_id: BlockId, contract_address: Address, data: Bytes) -> Result { - if let Some(client) = self.get_trusted() { - client.call_contract(EthcoreBlockId::from(block_id), contract_address, data) - } else { - Err("Calling ACL contract without trusted blockchain client".into()) - } - } - - /// Client's block_hash wrapper - pub fn block_hash(&self, id: BlockId) -> Option { - if let Some(client) = self.get_trusted() { - client.block_hash(EthcoreBlockId::from(id)) - } else { - None - } - } - - /// Client's block_number wrapper - pub fn block_number(&self, id: BlockId) -> Option { - if let Some(client) = self.get_trusted() { - client.block_number(EthcoreBlockId::from(id)) - } else { - None - } - } + /// Call contract in the blockchain + fn call_contract(&self, block_id: BlockId, contract_address: Address, data: Bytes) -> Result; - /// Client's tree_route wrapper - fn tree_route(&self, from: &H256, to: &H256) -> Option { - if let Some(client) = self.get_trusted() { - client.tree_route(from, to) - } else { - None - } - } + /// Returns blockhash for block id + fn block_hash(&self, id: BlockId) -> Option; - /// Client's logs wrapper - fn logs(&self, filter: BlockchainFilter) -> Option> { - if let Some(client) = self.get_trusted() { - client.logs(filter).ok() - } else { - None - } - } + /// Returns block number for block id + fn block_number(&self, id: BlockId) -> Option; /// Retrieve last blockchain logs for the filter - pub fn retrieve_last_logs(&self, filter: Filter) -> Option> { - let confirmed_block = match self.get_confirmed_block_hash() { - Some(confirmed_block) => confirmed_block, - None => return None, // no block with enough confirmations - }; - - let from_block = self.block_hash(filter.from_block).unwrap_or_else(|| confirmed_block); - let first_block = match self.tree_route(&from_block, &confirmed_block) { - // if we have a route from last_log_block to confirmed_block => search for logs on this route - // - // potentially this could lead us to reading same logs twice when reorganizing to the fork, which - // already has been canonical previosuly - // the worst thing that can happen in this case is spending some time reading unneeded data from SS db - Some(ref route) if route.index < route.blocks.len() => route.blocks[route.index], - // else we care only about confirmed block - _ => confirmed_block.clone(), - }; + fn retrieve_last_logs(&self, filter: Filter) -> Option>; - self.logs(BlockchainFilter { - from_block: EthcoreBlockId::Hash(first_block), - to_block: EthcoreBlockId::Hash(confirmed_block), - address: filter.address, - topics: filter.topics, - limit: None, - }) - .map(|blockchain_logs| { - blockchain_logs - .into_iter() - .map(|log| { - let raw_log: RawLog = (log.entry.topics.into_iter().map(|t| t.0.into()).collect(), log.entry.data).into(); - raw_log - }) - .collect::>() - }) - } - - /// Get hash of the last block with at least n confirmations. - pub fn get_confirmed_block_hash(&self) -> Option { - self.block_number(BlockId::Latest) - .map(|b| b.saturating_sub(REQUEST_CONFIRMATIONS_REQUIRED)) - .and_then(|b| self.block_hash(BlockId::Number(b))) - } + /// Get hash of the last block with predefined number of confirmations (depends on the chain). + fn get_confirmed_block_hash(&self) -> Option; } - -impl ChainNotify for Blockchain { - fn new_blocks(&self, new_blocks: NewBlocks) { - if new_blocks.has_more_blocks_to_import { return } - if !new_blocks.route.enacted().is_empty() || !new_blocks.route.retracted().is_empty() { - let enacted_len = new_blocks.route.enacted().len(); - self.notify_listeners(enacted_len); - } - } -} - diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index 0f93a27a3e2..25ca5543187 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -97,7 +97,7 @@ struct PreviousMigrationTransaction { /// Cached on-chain Key Server set contract. struct CachedContract { /// Blockchain client. - client: Arc, + client: Arc, /// Contract address source. contract_address_source: Option, /// Current contract address. @@ -117,7 +117,7 @@ struct CachedContract { } impl OnChainKeyServerSet { - pub fn new(trusted_client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { + pub fn new(trusted_client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { let key_server_set = Arc::new(OnChainKeyServerSet { contract: Mutex::new(CachedContract::new(trusted_client.clone(), contract_address_source, self_key_pair, auto_migrate_enabled, key_servers)?), }); @@ -216,7 +216,7 @@ impl ) -> Result, String>> KeyServerSubset for NewKeySe } impl CachedContract { - pub fn new(client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { + pub fn new(client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { let server_set = match contract_address_source.is_none() { true => key_servers.into_iter() .map(|(p, addr)| { @@ -531,7 +531,7 @@ fn update_number_of_confirmations H256, F2: Fn(H256) -> Option> snapshot.new_set = future_new_set.new_set; } -fn update_last_transaction_block(client: &Blockchain, migration_id: &H256, previous_transaction: &mut Option) -> bool { +fn update_last_transaction_block(client: &dyn Blockchain, migration_id: &H256, previous_transaction: &mut Option) -> bool { let last_block = client.block_number(BlockId::Latest).unwrap_or_default(); match previous_transaction.as_ref() { // no previous transaction => send immediately @@ -559,11 +559,11 @@ fn update_last_transaction_block(client: &Blockchain, migration_id: &H256, previ true } -fn latest_block_hash(client: &Blockchain) -> H256 { +fn latest_block_hash(client: &dyn Blockchain) -> H256 { client.block_hash(BlockId::Latest).unwrap_or_default() } -fn block_confirmations(client: &Blockchain, block: H256) -> Option { +fn block_confirmations(client: &dyn Blockchain, block: H256) -> Option { client.block_number(BlockId::Hash(block)) .and_then(|block| client.block_number(BlockId::Latest).map(|last_block| (block, last_block))) .map(|(block, last_block)| last_block - block) diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index 5a282b57c33..65d22029d2a 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -15,12 +15,7 @@ // along with Parity Ethereum. If not, see . extern crate byteorder; -extern crate client_traits; -extern crate common_types; extern crate ethabi; -extern crate ethcore; -extern crate ethcore_call_contract as call_contract; -extern crate ethcore_sync as sync; extern crate ethereum_types; extern crate hyper; extern crate keccak_hash as hash; @@ -54,16 +49,11 @@ extern crate lazy_static; #[macro_use] extern crate log; -#[cfg(any(test, feature = "accounts"))] -extern crate ethkey; #[cfg(test)] extern crate env_logger; #[cfg(test)] extern crate tempdir; -#[cfg(feature = "accounts")] -extern crate ethcore_accounts as accounts; - mod key_server_cluster; mod types; @@ -81,18 +71,13 @@ mod migration; use std::sync::Arc; use kvdb::KeyValueDB; use kvdb_rocksdb::{Database, DatabaseConfig}; -use ethcore::client::Client; -use ethcore::miner::Miner; -use sync::SyncProvider; use parity_runtime::Executor; pub use types::{ServerKeyId, EncryptedDocumentKey, RequestSignature, Public, Error, NodeAddress, ServiceConfiguration, ClusterConfiguration}; pub use traits::KeyServer; -pub use blockchain::{SigningKeyPair, ContractAddress}; +pub use blockchain::{Blockchain, SigningKeyPair, ContractAddress, BlockId, BlockNumber, NewBlocksNotify, Filter}; pub use self::node_key_pair::PlainNodeKeyPair; -#[cfg(feature = "accounts")] -pub use self::node_key_pair::KeyStoreNodeKeyPair; /// Open a secret store DB using the given secret store data path. The DB path is one level beneath the data path. pub fn open_secretstore_db(data_path: &str) -> Result, String> { @@ -109,10 +94,9 @@ pub fn open_secretstore_db(data_path: &str) -> Result, Strin } /// Start new key server instance -pub fn start(client: Arc, sync: Arc, miner: Arc, self_key_pair: Arc, mut config: ServiceConfiguration, +pub fn start(trusted_client: Arc, self_key_pair: Arc, mut config: ServiceConfiguration, db: Arc, executor: Executor) -> Result, Error> { - let trusted_client = blockchain::Blockchain::new(self_key_pair.clone(), client.clone(), sync, miner); let acl_storage: Arc = match config.acl_check_contract_address.take() { Some(acl_check_contract_address) => acl_storage::OnChainAclStorage::new(trusted_client.clone(), acl_check_contract_address)?, None => Arc::new(acl_storage::DummyAclStorage::default()), diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index 00d58526bcf..d859fc2003a 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -92,7 +92,7 @@ pub struct OnChainServiceContract { /// Requests mask. mask: ApiMask, /// Blockchain client. - client: Arc, + client: Arc, /// This node key pair. self_key_pair: Arc, /// Contract registry name (if any). @@ -132,7 +132,7 @@ struct DocumentKeyShadowRetrievalService; impl OnChainServiceContract { /// Create new on-chain service contract. - pub fn new(mask: ApiMask, client: Arc, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { + pub fn new(mask: ApiMask, client: Arc, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { let contract = OnChainServiceContract { mask: mask, client: client, @@ -151,8 +151,8 @@ impl OnChainServiceContract { /// Send transaction to the service contract. fn send_contract_transaction(&self, tx_name: &str, origin: &Address, server_key_id: &ServerKeyId, is_response_required: C, prepare_tx: P) -> Result<(), String> - where C: FnOnce(&Blockchain, &Address, &ServerKeyId, &Address) -> bool, - P: FnOnce(&Blockchain, &Address) -> Result { + where C: FnOnce(&dyn Blockchain, &Address, &ServerKeyId, &Address) -> bool, + P: FnOnce(&dyn Blockchain, &Address) -> Result { // only publish if contract address is set && client is online if !self.client.is_trusted() { return Err("trusted client is required to publish key".into()) @@ -183,9 +183,9 @@ impl OnChainServiceContract { /// Create task-specific pending requests iterator. fn create_pending_requests_iterator< - C: 'static + Fn(&Blockchain, &Address, &BlockId) -> Result, - R: 'static + Fn(&dyn SigningKeyPair, &Blockchain, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> - >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { + C: 'static + Fn(&dyn Blockchain, &Address, &BlockId) -> Result, + R: 'static + Fn(&dyn SigningKeyPair, &dyn Blockchain, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> + >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { get_count(&*client, contract_address, block) .map(|count| { let client = client.clone(); @@ -427,7 +427,7 @@ impl ServerKeyGenerationService { } /// Check if response from key server is required. - pub fn is_response_required(client: &Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &dyn Blockchain, 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 (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) { @@ -447,14 +447,14 @@ impl ServerKeyGenerationService { } /// Read pending requests count. - fn read_pending_requests_count(client: &Blockchain, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &dyn Blockchain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::server_key_generation_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_generation_request::call(index); @@ -487,7 +487,7 @@ impl ServerKeyRetrievalService { } /// Check if response from key server is required. - pub fn is_response_required(client: &Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &dyn Blockchain, 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 (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) { @@ -507,14 +507,14 @@ impl ServerKeyRetrievalService { } /// Read pending requests count. - fn read_pending_requests_count(client: &Blockchain, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &dyn Blockchain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::server_key_retrieval_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_retrieval_request::call(index); @@ -550,7 +550,7 @@ impl DocumentKeyStoreService { } /// Check if response from key server is required. - pub fn is_response_required(client: &Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &dyn Blockchain, 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 (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) { @@ -570,14 +570,14 @@ impl DocumentKeyStoreService { } /// Read pending requests count. - fn read_pending_requests_count(client: &Blockchain, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &dyn Blockchain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::document_key_store_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); 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)?) @@ -617,7 +617,7 @@ impl DocumentKeyShadowRetrievalService { } /// Check if response from key server is required. - pub fn is_response_required(client: &Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, key_server: &Address) -> bool { + pub fn is_response_required(client: &dyn Blockchain, 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 (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) { @@ -632,7 +632,7 @@ impl DocumentKeyShadowRetrievalService { } /// Prepare publish personal key transaction data. - pub fn prepare_pubish_personal_tx_data(client: &Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result { + pub fn prepare_pubish_personal_tx_data(client: &dyn Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result { let mut participants_mask = U256::default(); for participant in participants { let participant_index = Self::map_key_server_address(client, contract_address, participant.clone()) @@ -650,14 +650,14 @@ impl DocumentKeyShadowRetrievalService { } /// Read pending requests count. - fn read_pending_requests_count(client: &Blockchain, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &dyn Blockchain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::document_key_shadow_retrieval_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_document_key_shadow_retrieval_request::call(index); @@ -687,7 +687,7 @@ impl DocumentKeyShadowRetrievalService { } /// Map from key server address to key server index. - fn map_key_server_address(client: &Blockchain, contract_address: &Address, key_server: Address) -> Result { + fn map_key_server_address(client: &dyn Blockchain, contract_address: &Address, key_server: Address) -> Result { // we're checking confirmation in Latest block, because tx ,ust be appended to the latest state let (encoded, decoder) = service::functions::require_key_server::call(key_server); let index = decoder.decode(&client.call_contract(BlockId::Latest, *contract_address, encoded)?) diff --git a/secret-store/src/node_key_pair.rs b/secret-store/src/node_key_pair.rs index 4c169e2d174..f31c46c864e 100644 --- a/secret-store/src/node_key_pair.rs +++ b/secret-store/src/node_key_pair.rs @@ -48,48 +48,3 @@ impl SigningKeyPair for PlainNodeKeyPair { sign(self.key_pair.secret(), data) } } - -#[cfg(feature = "accounts")] -mod accounts { - use super::*; - use std::sync::Arc; - use ethkey::Password; - use accounts::AccountProvider; - - pub struct KeyStoreNodeKeyPair { - account_provider: Arc, - address: Address, - public: Public, - password: Password, - } - - impl KeyStoreNodeKeyPair { - pub fn new(account_provider: Arc, address: Address, password: Password) -> Result { - let public = account_provider.account_public(address.clone(), &password).map_err(|e| EthKeyError::Custom(format!("{}", e)))?; - Ok(KeyStoreNodeKeyPair { - account_provider, - address, - public, - password, - }) - } - } - - impl SigningKeyPair for KeyStoreNodeKeyPair { - fn public(&self) -> &Public { - &self.public - } - - fn address(&self) -> Address { - public_to_address(&self.public) - } - - fn sign(&self, data: &H256) -> Result { - self.account_provider.sign(self.address.clone(), Some(self.password.clone()), data.clone()) - .map_err(|e| EthKeyError::Custom(format!("{}", e))) - } - } -} - -#[cfg(feature = "accounts")] -pub use self::accounts::KeyStoreNodeKeyPair; From 84dd6f786df3c4b263945b06b89c2f60e4329fa0 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 20 Nov 2019 16:00:57 +0100 Subject: [PATCH 11/16] Move node key pair under secret store feature as well --- parity/secretstore/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parity/secretstore/mod.rs b/parity/secretstore/mod.rs index 3c34ad2ad0c..2b16965fa3d 100644 --- a/parity/secretstore/mod.rs +++ b/parity/secretstore/mod.rs @@ -21,11 +21,11 @@ mod server; #[cfg(feature = "secretstore")] mod blockchain; -#[cfg(feature = "accounts")] +#[cfg(all(feature = "accounts", feature = "secretstore"))] mod nodekeypair; pub use self::server::{Configuration, NodeSecretKey, ContractAddress, Dependencies, start}; #[cfg(feature = "secretstore")] use self::blockchain::TrustedClient; -#[cfg(feature = "accounts")] +#[cfg(all(feature = "accounts", feature = "secretstore"))] use self::nodekeypair::KeyStoreNodeKeyPair; \ No newline at end of file From 1da874ac1ac90a7649bcd9b777f12b317bce3a4c Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 21 Nov 2019 12:27:23 +0100 Subject: [PATCH 12/16] Registar crate removed from deps --- Cargo.lock | 2 -- secret-store/Cargo.toml | 2 -- secret-store/src/lib.rs | 1 - 3 files changed, 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 182bf6a069c..0d4f82a559c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1481,7 +1481,6 @@ dependencies = [ "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.12.0", "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1496,7 +1495,6 @@ dependencies = [ "parity-runtime 0.1.0", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "registrar 0.0.1", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/secret-store/Cargo.toml b/secret-store/Cargo.toml index 254acfb8783..f2bd5d367bb 100644 --- a/secret-store/Cargo.toml +++ b/secret-store/Cargo.toml @@ -24,7 +24,6 @@ parity-crypto = { version = "0.4.2", features = ["publickey"] } parity-runtime = { path = "../util/runtime" } parking_lot = "0.9" percent-encoding = "2.1.0" -registrar = { path = "../util/registrar" } rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" @@ -38,7 +37,6 @@ jsonrpc-server-utils = "14.0.3" [dev-dependencies] env_logger = "0.5" -ethcore = { path = "../ethcore", features = ["test-helpers"] } tempdir = "0.3" kvdb-rocksdb = "0.3.0" diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index 65d22029d2a..897f8da6f85 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -26,7 +26,6 @@ extern crate parity_crypto as crypto; extern crate parity_runtime; extern crate parking_lot; extern crate percent_encoding; -extern crate registrar; extern crate rustc_hex; extern crate serde; extern crate serde_json; From df7dc81d713397ea2edf4e406654c478eafb4e06 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 27 Nov 2019 13:22:54 +0100 Subject: [PATCH 13/16] Accounts feature removed from secret store --- Cargo.toml | 2 +- secret-store/Cargo.toml | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fdae74303df..9d667e9efce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,7 +99,7 @@ test-heavy = ["ethcore/test-heavy"] evm-debug = ["ethcore/evm-debug"] evm-debug-tests = ["ethcore/evm-debug-tests"] slow-blocks = ["ethcore/slow-blocks"] -secretstore = ["ethcore-secretstore", "ethcore-secretstore/accounts", "ethabi", "ethcore-call-contract"] +secretstore = ["ethcore-secretstore", "accounts", "ethabi", "ethcore-call-contract"] final = ["parity-version/final"] deadlock_detection = ["parking_lot/deadlock_detection"] # to create a memory profile (requires nightly rust), use e.g. diff --git a/secret-store/Cargo.toml b/secret-store/Cargo.toml index f2bd5d367bb..609e5ff62c3 100644 --- a/secret-store/Cargo.toml +++ b/secret-store/Cargo.toml @@ -39,6 +39,3 @@ jsonrpc-server-utils = "14.0.3" env_logger = "0.5" tempdir = "0.3" kvdb-rocksdb = "0.3.0" - -[features] -accounts = [] From f1ace367bd9225f7a38ecf4bd929043224228556 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 2 Jan 2020 16:40:52 +0100 Subject: [PATCH 14/16] Fix after merge --- Cargo.lock | 1 + parity/secretstore/server.rs | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d4f82a559c..f7ab1ad9e87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1482,6 +1482,7 @@ dependencies = [ "ethabi-contract 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.4.0", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-server-utils 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/parity/secretstore/server.rs b/parity/secretstore/server.rs index d46b97c7520..ad90f2bd562 100644 --- a/parity/secretstore/server.rs +++ b/parity/secretstore/server.rs @@ -205,14 +205,9 @@ mod server { cconf.cluster_config.nodes.insert(self_secret.public().clone(), cconf.cluster_config.listener_address.clone()); -<<<<<<< HEAD:parity/secretstore.rs let db = ethcore_secretstore::open_secretstore_db(&conf.data_path)?; - let key_server = ethcore_secretstore::start(deps.client, deps.sync, deps.miner, self_secret, cconf, db, executor) -======= - let db = db::open_secretstore_db(&conf.data_path)?; let trusted_client = TrustedClient::new(self_secret.clone(), deps.client, deps.sync, deps.miner); let key_server = ethcore_secretstore::start(trusted_client, self_secret, cconf, db, executor) ->>>>>>> 3040bcd... Trusted client implementation moved to parity code:parity/secretstore/server.rs .map_err(|e| format!("Error starting KeyServer {}: {}", key_server_name, e))?; Ok(KeyServer { From cf238576da51af83fb3b705f1cfc405e4f36c59a Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 6 Jan 2020 10:55:18 +0100 Subject: [PATCH 15/16] Blockchain renamed to SecretStoreChain --- parity/secretstore/blockchain.rs | 10 ++--- parity/secretstore/nodekeypair.rs | 8 ++-- secret-store/src/acl_storage.rs | 8 ++-- secret-store/src/blockchain.rs | 2 +- secret-store/src/key_server_set.rs | 14 +++--- secret-store/src/lib.rs | 4 +- secret-store/src/listener/service_contract.rs | 44 +++++++++---------- 7 files changed, 45 insertions(+), 45 deletions(-) diff --git a/parity/secretstore/blockchain.rs b/parity/secretstore/blockchain.rs index d46160fe079..5f975558745 100644 --- a/parity/secretstore/blockchain.rs +++ b/parity/secretstore/blockchain.rs @@ -35,7 +35,7 @@ use ethcore::miner::{Miner, MinerService}; use parity_crypto::publickey::Error as EthKeyError; use sync::SyncProvider; use registrar::RegistrarClient; -use ethcore_secretstore::{BlockId, BlockNumber, Blockchain, NewBlocksNotify, SigningKeyPair, ContractAddress, Filter}; +use ethcore_secretstore::{BlockId, BlockNumber, SecretStoreChain, NewBlocksNotify, SigningKeyPair, ContractAddress, Filter}; // TODO: Instead of a constant, make this based on consensus finality. /// Number of confirmations required before request can be processed. @@ -79,9 +79,9 @@ impl TrustedClient { } fn notify_listeners(&self, new_enacted_len: usize) { - for np in self.listeners.read().iter() { - if let Some(n) = np.upgrade() { - n.new_blocks(new_enacted_len); + for listener_pointer in self.listeners.read().iter() { + if let Some(listener) = listener_pointer.upgrade() { + listener.new_blocks(new_enacted_len); } } } @@ -118,7 +118,7 @@ impl TrustedClient { } -impl Blockchain for TrustedClient { +impl SecretStoreChain for TrustedClient { fn add_listener(&self, target: Arc) { self.listeners.write().push(Arc::downgrade(&target)); } diff --git a/parity/secretstore/nodekeypair.rs b/parity/secretstore/nodekeypair.rs index 2c9e9353f1a..a6739f3aa2e 100644 --- a/parity/secretstore/nodekeypair.rs +++ b/parity/secretstore/nodekeypair.rs @@ -33,10 +33,10 @@ impl KeyStoreNodeKeyPair { pub fn new(account_provider: Arc, address: Address, password: Password) -> Result { let public = account_provider.account_public(address.clone(), &password).map_err(|e| EthKeyError::Custom(format!("{}", e)))?; Ok(KeyStoreNodeKeyPair { - account_provider: account_provider, - address: address, - public: public, - password: password, + account_provider, + address, + public, + password, }) } } diff --git a/secret-store/src/acl_storage.rs b/secret-store/src/acl_storage.rs index b57f10a59d9..0da50e310a2 100644 --- a/secret-store/src/acl_storage.rs +++ b/secret-store/src/acl_storage.rs @@ -19,7 +19,7 @@ use std::collections::{HashMap, HashSet}; use parking_lot::{Mutex, RwLock}; use ethereum_types::Address; use ethabi::FunctionOutputDecoder; -use blockchain::{Blockchain, NewBlocksNotify, ContractAddress, BlockId}; +use blockchain::{SecretStoreChain, NewBlocksNotify, ContractAddress, BlockId}; use types::{Error, ServerKeyId}; use_contract!(acl_storage, "res/acl_storage.json"); @@ -41,7 +41,7 @@ pub struct OnChainAclStorage { /// Cached on-chain ACL storage contract. struct CachedContract { /// Blockchain client. - client: Arc, + client: Arc, /// Contract address source. address_source: ContractAddress, /// Current contract address. @@ -55,7 +55,7 @@ pub struct DummyAclStorage { } impl OnChainAclStorage { - pub fn new(trusted_client: Arc, address_source: ContractAddress) -> Result, Error> { + pub fn new(trusted_client: Arc, address_source: ContractAddress) -> Result, Error> { let acl_storage = Arc::new(OnChainAclStorage { contract: Mutex::new(CachedContract::new(trusted_client.clone(), address_source)), }); @@ -77,7 +77,7 @@ impl NewBlocksNotify for OnChainAclStorage { } impl CachedContract { - pub fn new(client: Arc, address_source: ContractAddress) -> Self { + pub fn new(client: Arc, address_source: ContractAddress) -> Self { let mut contract = CachedContract { client, address_source, diff --git a/secret-store/src/blockchain.rs b/secret-store/src/blockchain.rs index 4e91e7a4db9..d2ad28d7e0c 100644 --- a/secret-store/src/blockchain.rs +++ b/secret-store/src/blockchain.rs @@ -87,7 +87,7 @@ pub struct Filter { } /// Blockchain representation for Secret Store -pub trait Blockchain: Send + Sync + 'static { +pub trait SecretStoreChain: Send + Sync + 'static { /// Adds listener for chain's NewBlocks event fn add_listener(&self, target: Arc); diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index 25ca5543187..a558fbeec5b 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -23,7 +23,7 @@ use ethereum_types::{H256, Address}; use crypto::publickey::public_to_address; use bytes::Bytes; use types::{Error, Public, NodeAddress, NodeId}; -use blockchain::{Blockchain, NewBlocksNotify, SigningKeyPair, ContractAddress, BlockId}; +use blockchain::{SecretStoreChain, NewBlocksNotify, SigningKeyPair, ContractAddress, BlockId}; use_contract!(key_server, "res/key_server_set.json"); @@ -97,7 +97,7 @@ struct PreviousMigrationTransaction { /// Cached on-chain Key Server set contract. struct CachedContract { /// Blockchain client. - client: Arc, + client: Arc, /// Contract address source. contract_address_source: Option, /// Current contract address. @@ -117,7 +117,7 @@ struct CachedContract { } impl OnChainKeyServerSet { - pub fn new(trusted_client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { + pub fn new(trusted_client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result, Error> { let key_server_set = Arc::new(OnChainKeyServerSet { contract: Mutex::new(CachedContract::new(trusted_client.clone(), contract_address_source, self_key_pair, auto_migrate_enabled, key_servers)?), }); @@ -216,7 +216,7 @@ impl ) -> Result, String>> KeyServerSubset for NewKeySe } impl CachedContract { - pub fn new(client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { + pub fn new(client: Arc, contract_address_source: Option, self_key_pair: Arc, auto_migrate_enabled: bool, key_servers: BTreeMap) -> Result { let server_set = match contract_address_source.is_none() { true => key_servers.into_iter() .map(|(p, addr)| { @@ -531,7 +531,7 @@ fn update_number_of_confirmations H256, F2: Fn(H256) -> Option> snapshot.new_set = future_new_set.new_set; } -fn update_last_transaction_block(client: &dyn Blockchain, migration_id: &H256, previous_transaction: &mut Option) -> bool { +fn update_last_transaction_block(client: &dyn SecretStoreChain, migration_id: &H256, previous_transaction: &mut Option) -> bool { let last_block = client.block_number(BlockId::Latest).unwrap_or_default(); match previous_transaction.as_ref() { // no previous transaction => send immediately @@ -559,11 +559,11 @@ fn update_last_transaction_block(client: &dyn Blockchain, migration_id: &H256, p true } -fn latest_block_hash(client: &dyn Blockchain) -> H256 { +fn latest_block_hash(client: &dyn SecretStoreChain) -> H256 { client.block_hash(BlockId::Latest).unwrap_or_default() } -fn block_confirmations(client: &dyn Blockchain, block: H256) -> Option { +fn block_confirmations(client: &dyn SecretStoreChain, block: H256) -> Option { client.block_number(BlockId::Hash(block)) .and_then(|block| client.block_number(BlockId::Latest).map(|last_block| (block, last_block))) .map(|(block, last_block)| last_block - block) diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index 897f8da6f85..a8fe7141e25 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -75,7 +75,7 @@ use parity_runtime::Executor; pub use types::{ServerKeyId, EncryptedDocumentKey, RequestSignature, Public, Error, NodeAddress, ServiceConfiguration, ClusterConfiguration}; pub use traits::KeyServer; -pub use blockchain::{Blockchain, SigningKeyPair, ContractAddress, BlockId, BlockNumber, NewBlocksNotify, Filter}; +pub use blockchain::{SecretStoreChain, SigningKeyPair, ContractAddress, BlockId, BlockNumber, NewBlocksNotify, Filter}; pub use self::node_key_pair::PlainNodeKeyPair; /// Open a secret store DB using the given secret store data path. The DB path is one level beneath the data path. @@ -93,7 +93,7 @@ pub fn open_secretstore_db(data_path: &str) -> Result, Strin } /// Start new key server instance -pub fn start(trusted_client: Arc, self_key_pair: Arc, mut config: ServiceConfiguration, +pub fn start(trusted_client: Arc, self_key_pair: Arc, mut config: ServiceConfiguration, db: Arc, executor: Executor) -> Result, Error> { let acl_storage: Arc = match config.acl_check_contract_address.take() { diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index d859fc2003a..d09f267b2a1 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -24,7 +24,7 @@ use bytes::Bytes; use ethereum_types::{H256, U256, Address, H512}; use listener::ApiMask; use listener::service_contract_listener::ServiceTask; -use blockchain::{Blockchain, Filter, SigningKeyPair, ContractAddress, BlockId}; +use blockchain::{SecretStoreChain, Filter, SigningKeyPair, ContractAddress, BlockId}; use ServerKeyId; use_contract!(service, "res/service.json"); @@ -92,7 +92,7 @@ pub struct OnChainServiceContract { /// Requests mask. mask: ApiMask, /// Blockchain client. - client: Arc, + client: Arc, /// This node key pair. self_key_pair: Arc, /// Contract registry name (if any). @@ -132,7 +132,7 @@ struct DocumentKeyShadowRetrievalService; impl OnChainServiceContract { /// Create new on-chain service contract. - pub fn new(mask: ApiMask, client: Arc, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { + pub fn new(mask: ApiMask, client: Arc, name: String, address_source: ContractAddress, self_key_pair: Arc) -> Self { let contract = OnChainServiceContract { mask: mask, client: client, @@ -151,8 +151,8 @@ impl OnChainServiceContract { /// Send transaction to the service contract. fn send_contract_transaction(&self, tx_name: &str, origin: &Address, server_key_id: &ServerKeyId, is_response_required: C, prepare_tx: P) -> Result<(), String> - where C: FnOnce(&dyn Blockchain, &Address, &ServerKeyId, &Address) -> bool, - P: FnOnce(&dyn Blockchain, &Address) -> Result { + where C: FnOnce(&dyn SecretStoreChain, &Address, &ServerKeyId, &Address) -> bool, + P: FnOnce(&dyn SecretStoreChain, &Address) -> Result { // only publish if contract address is set && client is online if !self.client.is_trusted() { return Err("trusted client is required to publish key".into()) @@ -183,9 +183,9 @@ impl OnChainServiceContract { /// Create task-specific pending requests iterator. fn create_pending_requests_iterator< - C: 'static + Fn(&dyn Blockchain, &Address, &BlockId) -> Result, - R: 'static + Fn(&dyn SigningKeyPair, &dyn Blockchain, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> - >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { + C: 'static + Fn(&dyn SecretStoreChain, &Address, &BlockId) -> Result, + R: 'static + Fn(&dyn SigningKeyPair, &dyn SecretStoreChain, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String> + >(&self, client: Arc, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box> { get_count(&*client, contract_address, block) .map(|count| { let client = client.clone(); @@ -427,7 +427,7 @@ impl ServerKeyGenerationService { } /// Check if response from key server is required. - pub fn is_response_required(client: &dyn Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &dyn SecretStoreChain, 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 (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) { @@ -447,14 +447,14 @@ impl ServerKeyGenerationService { } /// Read pending requests count. - fn read_pending_requests_count(client: &dyn Blockchain, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &dyn SecretStoreChain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::server_key_generation_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn SecretStoreChain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_generation_request::call(index); @@ -487,7 +487,7 @@ impl ServerKeyRetrievalService { } /// Check if response from key server is required. - pub fn is_response_required(client: &dyn Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &dyn SecretStoreChain, 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 (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) { @@ -507,14 +507,14 @@ impl ServerKeyRetrievalService { } /// Read pending requests count. - fn read_pending_requests_count(client: &dyn Blockchain, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &dyn SecretStoreChain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::server_key_retrieval_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn SecretStoreChain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_server_key_retrieval_request::call(index); @@ -550,7 +550,7 @@ impl DocumentKeyStoreService { } /// Check if response from key server is required. - pub fn is_response_required(client: &dyn Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool { + pub fn is_response_required(client: &dyn SecretStoreChain, 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 (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) { @@ -570,14 +570,14 @@ impl DocumentKeyStoreService { } /// Read pending requests count. - fn read_pending_requests_count(client: &dyn Blockchain, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &dyn SecretStoreChain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::document_key_store_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn SecretStoreChain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); 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)?) @@ -617,7 +617,7 @@ impl DocumentKeyShadowRetrievalService { } /// Check if response from key server is required. - pub fn is_response_required(client: &dyn Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, key_server: &Address) -> bool { + pub fn is_response_required(client: &dyn SecretStoreChain, 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 (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) { @@ -632,7 +632,7 @@ impl DocumentKeyShadowRetrievalService { } /// Prepare publish personal key transaction data. - pub fn prepare_pubish_personal_tx_data(client: &dyn Blockchain, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result { + pub fn prepare_pubish_personal_tx_data(client: &dyn SecretStoreChain, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result { let mut participants_mask = U256::default(); for participant in participants { let participant_index = Self::map_key_server_address(client, contract_address, participant.clone()) @@ -650,14 +650,14 @@ impl DocumentKeyShadowRetrievalService { } /// Read pending requests count. - fn read_pending_requests_count(client: &dyn Blockchain, contract_address: &Address, block: &BlockId) -> Result { + fn read_pending_requests_count(client: &dyn SecretStoreChain, contract_address: &Address, block: &BlockId) -> Result { let (encoded, decoder) = service::functions::document_key_shadow_retrieval_requests_count::call(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?) .map_err(|e| e.to_string()) } /// Read pending request. - fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn Blockchain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { + fn read_pending_request(self_key_pair: &dyn SigningKeyPair, client: &dyn SecretStoreChain, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { let self_address = public_to_address(self_key_pair.public()); let (encoded, decoder) = service::functions::get_document_key_shadow_retrieval_request::call(index); @@ -687,7 +687,7 @@ impl DocumentKeyShadowRetrievalService { } /// Map from key server address to key server index. - fn map_key_server_address(client: &dyn Blockchain, contract_address: &Address, key_server: Address) -> Result { + fn map_key_server_address(client: &dyn SecretStoreChain, contract_address: &Address, key_server: Address) -> Result { // we're checking confirmation in Latest block, because tx ,ust be appended to the latest state let (encoded, decoder) = service::functions::require_key_server::call(key_server); let index = decoder.decode(&client.call_contract(BlockId::Latest, *contract_address, encoded)?) From a54495ea605300de8fef412da507f4d9149b4e19 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 6 Jan 2020 11:37:23 +0100 Subject: [PATCH 16/16] Module documentations added --- parity/secretstore/blockchain.rs | 4 ++++ parity/secretstore/nodekeypair.rs | 2 ++ parity/secretstore/server.rs | 2 ++ 3 files changed, 8 insertions(+) diff --git a/parity/secretstore/blockchain.rs b/parity/secretstore/blockchain.rs index 5f975558745..6c058753868 100644 --- a/parity/secretstore/blockchain.rs +++ b/parity/secretstore/blockchain.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +//! SecretStoreChain implementation with information about blockchain, retrieved from the client + use std::sync::{Arc, Weak}; use ethereum_types::{H256, Address}; use parking_lot::RwLock; @@ -51,6 +53,8 @@ fn into_ethcore_block_id(id: BlockId) -> EthcoreBlockId { } /// SecretStore blockchain implementation (client's wrapper) +/// This implementation is trusted, when underlying client is synced and chain's security level is full +/// This trust is guaranteed by return result in get_trusted method (if it's not trusted, None is returned) pub struct TrustedClient { /// This key server node key pair. self_key_pair: Arc, diff --git a/parity/secretstore/nodekeypair.rs b/parity/secretstore/nodekeypair.rs index a6739f3aa2e..67ad3d1ec34 100644 --- a/parity/secretstore/nodekeypair.rs +++ b/parity/secretstore/nodekeypair.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +//! Key pair with signing ability + use std::sync::Arc; use accounts::AccountProvider; use ethkey::Password; diff --git a/parity/secretstore/server.rs b/parity/secretstore/server.rs index ad90f2bd562..033f290e76a 100644 --- a/parity/secretstore/server.rs +++ b/parity/secretstore/server.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +//! Secret store server's launcher, contains required configuration parameters and launch method + use std::collections::BTreeMap; use std::sync::Arc; use account_utils::AccountProvider;