From 0cd864429202cdf50c8f2f51538c4bcf2a079d49 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 16:41:15 +0200 Subject: [PATCH 01/21] split interfaces --- ethcore/src/client/client.rs | 146 +++++++++++++++--------------- ethcore/src/client/mod.rs | 20 ++-- ethcore/src/client/test_client.rs | 21 +++-- miner/src/lib.rs | 24 ++--- miner/src/miner.rs | 34 +++---- 5 files changed, 126 insertions(+), 119 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index ab1c21af1..8f6d607ba 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -37,7 +37,7 @@ use filter::Filter; use log_entry::LocalizedLogEntry; use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; -use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, TraceFilter}; +use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, ExtendedBlockChainClient, TraceFilter}; use client::Error as ClientError; use env_info::EnvInfo; use executive::{Executive, Executed, TransactOptions, contract_address}; @@ -448,81 +448,10 @@ impl BlockChainClient for Client where V: Verifier { Executive::new(&mut state, &env_info, self.engine.deref().deref(), &self.vm_factory).transact(t, options) } - // TODO [todr] Should be moved to miner crate eventually. - fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result { - block.try_seal(self.engine.deref().deref(), seal) - } - fn vm_factory(&self) -> &EvmFactory { &self.vm_factory } - // TODO [todr] Should be moved to miner crate eventually. - fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) - -> (Option, HashSet) { - let engine = self.engine.deref().deref(); - let h = self.chain.best_block_hash(); - let mut invalid_transactions = HashSet::new(); - - let mut b = OpenBlock::new( - engine, - &self.vm_factory, - false, // TODO: this will need to be parameterised once we want to do immediate mining insertion. - self.state_db.lock().unwrap().boxed_clone(), - match self.chain.block_header(&h) { Some(ref x) => x, None => { return (None, invalid_transactions) } }, - self.build_last_hashes(h.clone()), - author, - gas_floor_target, - extra_data, - ); - - // Add uncles - self.chain - .find_uncle_headers(&h, engine.maximum_uncle_age()) - .unwrap() - .into_iter() - .take(engine.maximum_uncle_count()) - .foreach(|h| { - b.push_uncle(h).unwrap(); - }); - - // Add transactions - let block_number = b.block().header().number(); - let min_tx_gas = U256::from(self.engine.schedule(&b.env_info()).tx_gas); - - for tx in transactions { - // Push transaction to block - let hash = tx.hash(); - let import = b.push_transaction(tx, None); - - match import { - Err(Error::Execution(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, .. })) => { - trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", hash); - // Exit early if gas left is smaller then min_tx_gas - if gas_limit - gas_used < min_tx_gas { - break; - } - }, - Err(e) => { - invalid_transactions.insert(hash); - trace!(target: "miner", - "Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}", - block_number, hash, e); - }, - _ => {} - } - } - - // And close - let b = b.close(); - trace!(target: "miner", "Sealing: number={}, hash={}, diff={}", - b.block().header().number(), - b.hash(), - b.block().header().difficulty() - ); - (Some(b), invalid_transactions) - } - fn block_header(&self, id: BlockID) -> Option { Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block(&hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec())) } @@ -776,6 +705,79 @@ impl BlockChainClient for Client where V: Verifier { } } +impl ExtendedBlockChainClient for Client where V: Verifier { + // TODO [todr] Should be moved to miner crate eventually. + fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) + -> (Option, HashSet) { + let engine = self.engine.deref().deref(); + let h = self.chain.best_block_hash(); + let mut invalid_transactions = HashSet::new(); + + let mut b = OpenBlock::new( + engine, + &self.vm_factory, + false, // TODO: this will need to be parameterised once we want to do immediate mining insertion. + self.state_db.lock().unwrap().boxed_clone(), + match self.chain.block_header(&h) { Some(ref x) => x, None => { return (None, invalid_transactions) } }, + self.build_last_hashes(h.clone()), + author, + gas_floor_target, + extra_data, + ); + + // Add uncles + self.chain + .find_uncle_headers(&h, engine.maximum_uncle_age()) + .unwrap() + .into_iter() + .take(engine.maximum_uncle_count()) + .foreach(|h| { + b.push_uncle(h).unwrap(); + }); + + // Add transactions + let block_number = b.block().header().number(); + let min_tx_gas = U256::from(self.engine.schedule(&b.env_info()).tx_gas); + + for tx in transactions { + // Push transaction to block + let hash = tx.hash(); + let import = b.push_transaction(tx, None); + + match import { + Err(Error::Execution(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, .. })) => { + trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", hash); + // Exit early if gas left is smaller then min_tx_gas + if gas_limit - gas_used < min_tx_gas { + break; + } + }, + Err(e) => { + invalid_transactions.insert(hash); + trace!(target: "miner", + "Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}", + block_number, hash, e); + }, + _ => {} + } + } + + // And close + let b = b.close(); + trace!(target: "miner", "Sealing: number={}, hash={}, diff={}", + b.block().header().number(), + b.hash(), + b.block().header().difficulty() + ); + (Some(b), invalid_transactions) + } + + // TODO [todr] Should be moved to miner crate eventually. + fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result { + block.try_seal(self.engine.deref().deref(), seal) + } +} + impl MayPanic for Client { fn on_panic(&self, closure: F) where F: OnPanicListener { self.panic_handler.on_panic(closure); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 8e0a7b2dd..5537f8e66 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -154,15 +154,6 @@ pub trait BlockChainClient : Sync + Send { /// Returns logs matching given filter. fn logs(&self, filter: Filter) -> Vec; - // TODO [todr] Should be moved to miner crate eventually. - /// Returns ClosedBlock prepared for sealing. - fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) - -> (Option, HashSet); - - // TODO [todr] Should be moved to miner crate eventually. - /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. - fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; - /// Makes a non-persistent transaction call. fn call(&self, t: &SignedTransaction) -> Result; @@ -185,3 +176,14 @@ pub trait BlockChainClient : Sync + Send { fn last_hashes(&self) -> LastHashes; } +/// Extended client interface used for mining +pub trait ExtendedBlockChainClient : BlockChainClient { + // TODO [todr] Should be moved to miner crate eventually. + /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. + fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; + + // TODO [todr] Should be moved to miner crate eventually. + /// Returns ClosedBlock prepared for sealing. + fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) + -> (Option, HashSet); +} diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index de2973029..5c093b720 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder}; use util::*; use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action}; use blockchain::TreeRoute; -use client::{BlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes}; +use client::{BlockChainClient, ExtendedBlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes}; use header::{Header as BlockHeader, BlockNumber}; use filter::Filter; use log_entry::LocalizedLogEntry; @@ -232,6 +232,17 @@ impl TestBlockChainClient { } } +impl ExtendedBlockChainClient for TestBlockChainClient { + fn try_seal(&self, block: LockedBlock, _seal: Vec) -> Result { + Err(block) + } + + + fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> (Option, HashSet) { + (None, HashSet::new()) + } +} + impl BlockChainClient for TestBlockChainClient { fn call(&self, _t: &SignedTransaction) -> Result { Ok(self.execution_result.read().unwrap().clone().unwrap()) @@ -296,14 +307,6 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> (Option, HashSet) { - (None, HashSet::new()) - } - - fn try_seal(&self, block: LockedBlock, _seal: Vec) -> Result { - Err(block) - } - fn block_header(&self, id: BlockID) -> Option { self.block_hash(id).and_then(|hash| self.blocks.read().unwrap().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec())) } diff --git a/miner/src/lib.rs b/miner/src/lib.rs index a1780efff..db3315376 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -62,7 +62,7 @@ pub use external::{ExternalMiner, ExternalMinerService}; use std::collections::BTreeMap; use util::{H256, U256, Address, Bytes}; -use ethcore::client::{BlockChainClient, Executed}; +use ethcore::client::{ExtendedBlockChainClient, Executed}; use ethcore::block::ClosedBlock; use ethcore::receipt::Receipt; use ethcore::error::{Error, ExecutionError}; @@ -110,7 +110,7 @@ pub trait MinerService : Send + Sync { where T: Fn(&Address) -> AccountDetails, Self: Sized; /// Imports own (node owner) transaction to queue. - fn import_own_transaction(&self, chain: &BlockChainClient, transaction: SignedTransaction, fetch_account: T) -> + fn import_own_transaction(&self, chain: &ExtendedBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails, Self: Sized; @@ -118,20 +118,20 @@ pub trait MinerService : Send + Sync { fn pending_transactions_hashes(&self) -> Vec; /// Removes all transactions from the queue and restart mining operation. - fn clear_and_reset(&self, chain: &BlockChainClient); + fn clear_and_reset(&self, chain: &ExtendedBlockChainClient); /// Called when blocks are imported to chain, updates transactions queue. - fn chain_new_blocks(&self, chain: &BlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); + fn chain_new_blocks(&self, chain: &ExtendedBlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); /// New chain head event. Restart mining operation. - fn update_sealing(&self, chain: &BlockChainClient); + fn update_sealing(&self, chain: &ExtendedBlockChainClient); /// Submit `seal` as a valid solution for the header of `pow_hash`. /// Will check the seal, but not actually insert the block into the chain. - fn submit_seal(&self, chain: &BlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error>; + fn submit_seal(&self, chain: &ExtendedBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error>; /// Get the sealing work package and if `Some`, apply some transform. - fn map_sealing_work(&self, chain: &BlockChainClient, f: F) -> Option + fn map_sealing_work(&self, chain: &ExtendedBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T, Self: Sized; /// Query pending transactions for hash. @@ -156,19 +156,19 @@ pub trait MinerService : Send + Sync { fn sensible_gas_limit(&self) -> U256 { x!(21000) } /// Latest account balance in pending state. - fn balance(&self, chain: &BlockChainClient, address: &Address) -> U256; + fn balance(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256; /// Call into contract code using pending state. - fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result; + fn call(&self, chain: &ExtendedBlockChainClient, t: &SignedTransaction) -> Result; /// Get storage value in pending state. - fn storage_at(&self, chain: &BlockChainClient, address: &Address, position: &H256) -> H256; + fn storage_at(&self, chain: &ExtendedBlockChainClient, address: &Address, position: &H256) -> H256; /// Get account nonce in pending state. - fn nonce(&self, chain: &BlockChainClient, address: &Address) -> U256; + fn nonce(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256; /// Get contract code in pending state. - fn code(&self, chain: &BlockChainClient, address: &Address) -> Option; + fn code(&self, chain: &ExtendedBlockChainClient, address: &Address) -> Option; } /// Mining status diff --git a/miner/src/miner.rs b/miner/src/miner.rs index fc63aec6c..7438e7e9b 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -20,7 +20,7 @@ use std::sync::atomic::AtomicBool; use util::*; use util::keys::store::{AccountService, AccountProvider}; use ethcore::views::{BlockView, HeaderView}; -use ethcore::client::{BlockChainClient, BlockID}; +use ethcore::client::{ExtendedBlockChainClient, BlockID}; use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::error::*; use ethcore::client::{Executive, Executed, EnvInfo, TransactOptions}; @@ -104,7 +104,7 @@ impl Miner { /// Prepares new block for sealing including top transactions from queue. #[cfg_attr(feature="dev", allow(match_same_arms))] #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] - fn prepare_sealing(&self, chain: &BlockChainClient) { + fn prepare_sealing(&self, chain: &ExtendedBlockChainClient) { trace!(target: "miner", "prepare_sealing: entering"); let transactions = self.transaction_queue.lock().unwrap().top_transactions(); let mut sealing_work = self.sealing_work.lock().unwrap(); @@ -206,14 +206,14 @@ impl Miner { trace!(target: "miner", "prepare_sealing: leaving (last={:?})", sealing_work.peek_last_ref().map(|b| b.block().fields().header.hash())); } - fn update_gas_limit(&self, chain: &BlockChainClient) { + fn update_gas_limit(&self, chain: &ExtendedBlockChainClient) { let gas_limit = HeaderView::new(&chain.best_block_header()).gas_limit(); let mut queue = self.transaction_queue.lock().unwrap(); queue.set_gas_limit(gas_limit); } /// Returns true if we had to prepare new pending block - fn enable_and_prepare_sealing(&self, chain: &BlockChainClient) -> bool { + fn enable_and_prepare_sealing(&self, chain: &ExtendedBlockChainClient) -> bool { trace!(target: "miner", "enable_and_prepare_sealing: entering"); let have_work = self.sealing_work.lock().unwrap().peek_last_ref().is_some(); trace!(target: "miner", "enable_and_prepare_sealing: have_work={}", have_work); @@ -237,7 +237,7 @@ const SEALING_TIMEOUT_IN_BLOCKS : u64 = 5; impl MinerService for Miner { - fn clear_and_reset(&self, chain: &BlockChainClient) { + fn clear_and_reset(&self, chain: &ExtendedBlockChainClient) { self.transaction_queue.lock().unwrap().clear(); self.update_sealing(chain); } @@ -252,7 +252,7 @@ impl MinerService for Miner { } } - fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result { + fn call(&self, chain: &ExtendedBlockChainClient, t: &SignedTransaction) -> Result { let sealing_work = self.sealing_work.lock().unwrap(); match sealing_work.peek_last_ref() { Some(work) => { @@ -288,7 +288,7 @@ impl MinerService for Miner { } } - fn balance(&self, chain: &BlockChainClient, address: &Address) -> U256 { + fn balance(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else( || chain.latest_balance(address), @@ -296,7 +296,7 @@ impl MinerService for Miner { ) } - fn storage_at(&self, chain: &BlockChainClient, address: &Address, position: &H256) -> H256 { + fn storage_at(&self, chain: &ExtendedBlockChainClient, address: &Address, position: &H256) -> H256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else( || chain.latest_storage_at(address, position), @@ -304,12 +304,12 @@ impl MinerService for Miner { ) } - fn nonce(&self, chain: &BlockChainClient, address: &Address) -> U256 { + fn nonce(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else(|| chain.latest_nonce(address), |b| b.block().fields().state.nonce(address)) } - fn code(&self, chain: &BlockChainClient, address: &Address) -> Option { + fn code(&self, chain: &ExtendedBlockChainClient, address: &Address) -> Option { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else(|| chain.code(address), |b| b.block().fields().state.code(address)) } @@ -376,7 +376,7 @@ impl MinerService for Miner { .collect() } - fn import_own_transaction(&self, chain: &BlockChainClient, transaction: SignedTransaction, fetch_account: T) -> + fn import_own_transaction(&self, chain: &ExtendedBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails { let hash = transaction.hash(); @@ -470,7 +470,7 @@ impl MinerService for Miner { self.transaction_queue.lock().unwrap().last_nonce(address) } - fn update_sealing(&self, chain: &BlockChainClient) { + fn update_sealing(&self, chain: &ExtendedBlockChainClient) { if self.sealing_enabled.load(atomic::Ordering::Relaxed) { let current_no = chain.chain_info().best_block_number; let has_local_transactions = self.transaction_queue.lock().unwrap().has_local_pending_transactions(); @@ -490,7 +490,7 @@ impl MinerService for Miner { } } - fn map_sealing_work(&self, chain: &BlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { + fn map_sealing_work(&self, chain: &ExtendedBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { trace!(target: "miner", "map_sealing_work: entering"); self.enable_and_prepare_sealing(chain); trace!(target: "miner", "map_sealing_work: sealing prepared"); @@ -500,7 +500,7 @@ impl MinerService for Miner { ret.map(f) } - fn submit_seal(&self, chain: &BlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error> { + fn submit_seal(&self, chain: &ExtendedBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error> { if let Some(b) = self.sealing_work.lock().unwrap().take_used_if(|b| &b.hash() == &pow_hash) { match chain.try_seal(b.lock(), seal) { Err(_) => { @@ -523,8 +523,8 @@ impl MinerService for Miner { } } - fn chain_new_blocks(&self, chain: &BlockChainClient, _imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) { - fn fetch_transactions(chain: &BlockChainClient, hash: &H256) -> Vec { + fn chain_new_blocks(&self, chain: &ExtendedBlockChainClient, _imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) { + fn fetch_transactions(chain: &ExtendedBlockChainClient, hash: &H256) -> Vec { let block = chain .block(BlockID::Hash(*hash)) // Client should send message after commit to db and inserting to chain. @@ -591,7 +591,7 @@ mod tests { use ethcore::client::{TestBlockChainClient, EachBlockWith}; use ethcore::block::*; - // TODO [ToDr] To uncomment when TestBlockChainClient can actually return a ClosedBlock. + // TODO [ToDr] To uncomment` when TestBlockChainClient can actually return a ClosedBlock. #[ignore] #[test] fn should_prepare_block_to_seal() { From 4f732972bc366b758ef97190380d86192cef779c Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 19:01:37 +0200 Subject: [PATCH 02/21] refactoring to hold miner within the client --- ethcore/Cargo.toml | 1 + ethcore/src/client/client.rs | 32 ++++++++++++++++++++++++-------- ethcore/src/client/mod.rs | 11 +++++++++-- sync/src/chain.rs | 22 ++-------------------- sync/src/io.rs | 8 ++++---- sync/src/lib.rs | 11 ----------- sync/src/tests/chain.rs | 2 +- sync/src/tests/helpers.rs | 2 +- 8 files changed, 42 insertions(+), 47 deletions(-) diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 34a010794..f63eb957c 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -29,6 +29,7 @@ ethcore-devtools = { path = "../devtools" } ethjson = { path = "../json" } bloomchain = "0.1" "ethcore-ipc" = { path = "../ipc/rpc" } +ethminer = { path = "../miner" } [features] jit = ["evmjit"] diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 8f6d607ba..7a616fdbc 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -90,6 +90,7 @@ pub struct Client where V: Verifier { panic_handler: Arc, verifier: PhantomData, vm_factory: Arc, + miner: Arc, } const HISTORY: u64 = 1200; @@ -126,7 +127,13 @@ pub fn append_path(path: &Path, item: &str) -> String { impl Client where V: Verifier { /// Create a new client with given spec and DB path and custom verifier. - pub fn new_with_verifier(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel ) -> Result>, ClientError> { + pub fn new_with_verifier( + config: ClientConfig, + spec: Spec, + path: &Path, + message_channel: IoChannel) + -> Result>, ClientError> + { let path = get_db_path(path, config.pruning, spec.genesis_header().hash()); let gb = spec.genesis_block(); let chain = Arc::new(BlockChain::new(config.blockchain, &gb, &path)); @@ -328,18 +335,13 @@ impl Client where V: Verifier { { if !imported_blocks.is_empty() && self.block_queue.queue_info().is_empty() { let (enacted, retracted) = self.calculate_enacted_retracted(import_results); - io.send(NetworkIoMessage::User(SyncMessage::NewChainBlocks { - imported: imported_blocks, - invalid: invalid_blocks, - enacted: enacted, - retracted: retracted, - })).unwrap(); + self.miner.chain_new_blocks(imported_blocks, invalid_blocks, enacted, retracted); } } { if self.chain_info().best_block_hash != original_best { - io.send(NetworkIoMessage::User(SyncMessage::NewChainHead)).unwrap(); + self.miner.update_sealing(&self); } } @@ -778,6 +780,20 @@ impl ExtendedBlockChainClient for Client where V: Verifier { } } +impl MiningClient for Client { + fn import_transactions(&self, transactions: Vec) -> Vec> { + let fetch_account = |a: &Address| AccountDetails { + nonce: self.latest_nonce(a), + balance: self.latest_balance(a), + }; + self.miner.import_transactions(transactions, fetch_account) + } + + fn all_transactions(&self) -> Vec { + self.miner.all_transactions() + } +} + impl MayPanic for Client { fn on_panic(&self, closure: F) where F: OnPanicListener { self.panic_handler.on_panic(closure); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 5537f8e66..dfef54a40 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -178,12 +178,19 @@ pub trait BlockChainClient : Sync + Send { /// Extended client interface used for mining pub trait ExtendedBlockChainClient : BlockChainClient { - // TODO [todr] Should be moved to miner crate eventually. /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; - // TODO [todr] Should be moved to miner crate eventually. /// Returns ClosedBlock prepared for sealing. fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> (Option, HashSet); } + +/// Extended client interface that supports mining +pub trait MiningClient : BlockChainClient { + /// import transactions from network/other 3rd party + fn import_transactions(&self, transactions: Vec) -> Vec>; + + /// list all transactions + fn all_transactions(&self) -> Vec; +} diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 2f31f1d47..a0d0ba1fa 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -903,7 +903,7 @@ impl ChainSync { nonce: chain.latest_nonce(a), balance: chain.latest_balance(a), }; - let _ = self.miner.import_transactions(transactions, fetch_account); + let _ = io.chain().import_transactions(transactions, fetch_account); Ok(()) } @@ -1226,7 +1226,7 @@ impl ChainSync { return 0; } - let mut transactions = self.miner.all_transactions(); + let mut transactions = io.chain().all_transactions(); if transactions.is_empty() { return 0; } @@ -1275,24 +1275,6 @@ impl ChainSync { pub fn maintain_sync(&mut self, io: &mut SyncIo) { self.check_resume(io); } - - /// called when block is imported to chain, updates transactions queue and propagates the blocks - pub fn chain_new_blocks(&mut self, io: &mut SyncIo, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]) { - if io.is_chain_queue_empty() { - // Notify miner - self.miner.chain_new_blocks(io.chain(), imported, invalid, enacted, retracted); - // Propagate latests blocks - self.propagate_latest_blocks(io); - } - if !invalid.is_empty() { - trace!(target: "sync", "Bad blocks in the queue, restarting"); - self.restart_on_bad_block(io); - } - } - - pub fn chain_new_head(&mut self, io: &mut SyncIo) { - self.miner.update_sealing(io.chain()); - } } #[cfg(test)] diff --git a/sync/src/io.rs b/sync/src/io.rs index 84697a021..49cccd7ca 100644 --- a/sync/src/io.rs +++ b/sync/src/io.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethcore::client::BlockChainClient; +use ethcore::client::MiningClient; use util::{NetworkContext, PeerId, PacketId,}; use util::error::UtilError; use ethcore::service::SyncMessage; @@ -32,7 +32,7 @@ pub trait SyncIo { /// Send a packet to a peer. fn send(&mut self, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), UtilError>; /// Get the blockchain - fn chain(&self) -> &BlockChainClient; + fn chain(&self) -> &MiningClient; /// Returns peer client identifier string fn peer_info(&self, peer_id: PeerId) -> String { peer_id.to_string() @@ -46,12 +46,12 @@ pub trait SyncIo { /// Wraps `NetworkContext` and the blockchain client pub struct NetSyncIo<'s, 'h> where 'h: 's { network: &'s NetworkContext<'h, SyncMessage>, - chain: &'s BlockChainClient + chain: &'s MiningClient } impl<'s, 'h> NetSyncIo<'s, 'h> { /// Creates a new instance from the `NetworkContext` and the blockchain client reference. - pub fn new(network: &'s NetworkContext<'h, SyncMessage>, chain: &'s BlockChainClient) -> NetSyncIo<'s, 'h> { + pub fn new(network: &'s NetworkContext<'h, SyncMessage>, chain: &'s MiningClient) -> NetSyncIo<'s, 'h> { NetSyncIo { network: network, chain: chain, diff --git a/sync/src/lib.rs b/sync/src/lib.rs index c8dc93db6..6b72a24fc 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -166,16 +166,5 @@ impl NetworkProtocolHandler for EthSync { } fn message(&self, io: &NetworkContext, message: &SyncMessage) { - match *message { - SyncMessage::NewChainBlocks { ref imported, ref invalid, ref enacted, ref retracted } => { - let mut sync_io = NetSyncIo::new(io, self.chain.deref()); - self.sync.write().unwrap().chain_new_blocks(&mut sync_io, imported, invalid, enacted, retracted); - }, - SyncMessage::NewChainHead => { - let mut sync_io = NetSyncIo::new(io, self.chain.deref()); - self.sync.write().unwrap().chain_new_head(&mut sync_io); - }, - _ => {/* Ignore other messages */}, - } } } diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index 09e83e358..463771ffe 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use util::*; -use ethcore::client::{BlockChainClient, BlockID, EachBlockWith}; +use ethcore::client::{MiningClient, BlockID, EachBlockWith}; use chain::{SyncState}; use super::helpers::*; diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index d1ffde0f0..70ddb78db 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -63,7 +63,7 @@ impl<'p> SyncIo for TestIo<'p> { Ok(()) } - fn chain(&self) -> &BlockChainClient { + fn chain(&self) -> &MiningClient { self.chain } } From 8e252d5f1ba81585292477be869f3e1843c16fa1 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 19:52:53 +0200 Subject: [PATCH 03/21] refactored to merge client & client --- ethcore/Cargo.toml | 2 +- ethcore/src/client/client.rs | 41 +++++++++---------- ethcore/src/client/mod.rs | 17 ++++---- ethcore/src/client/test_client.rs | 11 +++++ ethcore/src/lib.rs | 2 + {miner/src => ethcore/src/miner}/external.rs | 0 {miner/src => ethcore/src/miner}/miner.rs | 20 ++++----- miner/src/lib.rs => ethcore/src/miner/mod.rs | 32 +++++---------- .../src/miner}/transaction_queue.rs | 4 +- ethcore/src/service.rs | 5 ++- 10 files changed, 68 insertions(+), 66 deletions(-) rename {miner/src => ethcore/src/miner}/external.rs (100%) rename {miner/src => ethcore/src/miner}/miner.rs (98%) rename miner/src/lib.rs => ethcore/src/miner/mod.rs (89%) rename {miner/src => ethcore/src/miner}/transaction_queue.rs (99%) diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index f63eb957c..1de24ee32 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -29,7 +29,7 @@ ethcore-devtools = { path = "../devtools" } ethjson = { path = "../json" } bloomchain = "0.1" "ethcore-ipc" = { path = "../ipc/rpc" } -ethminer = { path = "../miner" } +rayon = "0.3.1" [features] jit = ["evmjit"] diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 7a616fdbc..d23bffa31 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -48,6 +48,7 @@ use trace; pub use types::blockchain_info::BlockChainInfo; pub use types::block_status::BlockStatus; use evm::Factory as EvmFactory; +use miner::{Miner, MinerService, TransactionImportResult, AccountDetails}; impl fmt::Display for BlockChainInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -90,7 +91,7 @@ pub struct Client where V: Verifier { panic_handler: Arc, verifier: PhantomData, vm_factory: Arc, - miner: Arc, + miner: Arc, } const HISTORY: u64 = 1200; @@ -103,8 +104,8 @@ const CLIENT_DB_VER_STR: &'static str = "5.3"; impl Client { /// Create a new client with given spec and DB path. - pub fn new(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel ) -> Result, ClientError> { - Client::::new_with_verifier(config, spec, path, message_channel) + pub fn new(config: ClientConfig, spec: Spec, path: &Path, miner: Arc, message_channel: IoChannel ) -> Result, ClientError> { + Client::::new_with_verifier(config, spec, path, miner, message_channel) } } @@ -131,6 +132,7 @@ impl Client where V: Verifier { config: ClientConfig, spec: Spec, path: &Path, + miner: Arc, message_channel: IoChannel) -> Result>, ClientError> { @@ -162,6 +164,7 @@ impl Client where V: Verifier { panic_handler: panic_handler, verifier: PhantomData, vm_factory: Arc::new(EvmFactory::new(config.vm_type)), + miner: miner, }; Ok(Arc::new(client)) @@ -335,13 +338,13 @@ impl Client where V: Verifier { { if !imported_blocks.is_empty() && self.block_queue.queue_info().is_empty() { let (enacted, retracted) = self.calculate_enacted_retracted(import_results); - self.miner.chain_new_blocks(imported_blocks, invalid_blocks, enacted, retracted); + self.miner.chain_new_blocks(self, &imported_blocks, &invalid_blocks, &enacted, &retracted); } } { if self.chain_info().best_block_hash != original_best { - self.miner.update_sealing(&self); + self.miner.update_sealing(self); } } @@ -705,10 +708,21 @@ impl BlockChainClient for Client where V: Verifier { fn last_hashes(&self) -> LastHashes { self.build_last_hashes(self.chain.best_block_hash()) } + + fn import_transactions(&self, transactions: Vec) -> Vec> { + let fetch_account = |a: &Address| AccountDetails { + nonce: self.latest_nonce(a), + balance: self.latest_balance(a), + }; + self.miner.import_transactions(transactions, fetch_account) + } + + fn all_transactions(&self) -> Vec { + self.miner.all_transactions() + } } impl ExtendedBlockChainClient for Client where V: Verifier { - // TODO [todr] Should be moved to miner crate eventually. fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> (Option, HashSet) { let engine = self.engine.deref().deref(); @@ -774,26 +788,11 @@ impl ExtendedBlockChainClient for Client where V: Verifier { (Some(b), invalid_transactions) } - // TODO [todr] Should be moved to miner crate eventually. fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result { block.try_seal(self.engine.deref().deref(), seal) } } -impl MiningClient for Client { - fn import_transactions(&self, transactions: Vec) -> Vec> { - let fetch_account = |a: &Address| AccountDetails { - nonce: self.latest_nonce(a), - balance: self.latest_balance(a), - }; - self.miner.import_transactions(transactions, fetch_account) - } - - fn all_transactions(&self) -> Vec { - self.miner.all_transactions() - } -} - impl MayPanic for Client { fn on_panic(&self, closure: F) where F: OnPanicListener { self.panic_handler.on_panic(closure); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index dfef54a40..67c753d46 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -46,6 +46,8 @@ use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use trace::LocalizedTrace; use evm::Factory as EvmFactory; +use miner::{TransactionImportResult, AccountDetails}; +use error::Error as EthError; /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { @@ -174,6 +176,12 @@ pub trait BlockChainClient : Sync + Send { /// Get last hashes starting from best block. fn last_hashes(&self) -> LastHashes; + + /// import transactions from network/other 3rd party + fn import_transactions(&self, transactions: Vec) -> Vec>; + + /// list all transactions + fn all_transactions(&self) -> Vec; } /// Extended client interface used for mining @@ -185,12 +193,3 @@ pub trait ExtendedBlockChainClient : BlockChainClient { fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> (Option, HashSet); } - -/// Extended client interface that supports mining -pub trait MiningClient : BlockChainClient { - /// import transactions from network/other 3rd party - fn import_transactions(&self, transactions: Vec) -> Vec>; - - /// list all transactions - fn all_transactions(&self) -> Vec; -} diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 5c093b720..ad398bbcb 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -35,6 +35,9 @@ use executive::Executed; use error::{ExecutionError}; use trace::LocalizedTrace; +use miner::{TransactionImportResult, AccountDetails}; +use error::Error as EthError; + /// Test client. pub struct TestBlockChainClient { /// Blocks. @@ -479,4 +482,12 @@ impl BlockChainClient for TestBlockChainClient { fn block_traces(&self, _trace: BlockID) -> Option> { unimplemented!(); } + + fn import_transactions(&self, transactions: Vec) -> Vec> { + unimplemented!(); + } + + fn all_transactions(&self) -> Vec { + unimplemented!(); + } } diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 1d4ddadbc..5cf9d50a1 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -90,6 +90,7 @@ extern crate crossbeam; extern crate ethjson; extern crate bloomchain; #[macro_use] extern crate ethcore_ipc as ipc; +extern crate rayon; #[cfg(test)] extern crate ethcore_devtools as devtools; #[cfg(feature = "jit" )] extern crate evmjit; @@ -109,6 +110,7 @@ pub mod views; pub mod pod_state; pub mod engine; pub mod migrations; +pub mod miner; mod blooms; mod db; diff --git a/miner/src/external.rs b/ethcore/src/miner/external.rs similarity index 100% rename from miner/src/external.rs rename to ethcore/src/miner/external.rs diff --git a/miner/src/miner.rs b/ethcore/src/miner/miner.rs similarity index 98% rename from miner/src/miner.rs rename to ethcore/src/miner/miner.rs index 7438e7e9b..c4bec7659 100644 --- a/miner/src/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -19,16 +19,16 @@ use std::sync::atomic::AtomicBool; use util::*; use util::keys::store::{AccountService, AccountProvider}; -use ethcore::views::{BlockView, HeaderView}; -use ethcore::client::{ExtendedBlockChainClient, BlockID}; -use ethcore::block::{ClosedBlock, IsBlock}; -use ethcore::error::*; -use ethcore::client::{Executive, Executed, EnvInfo, TransactOptions}; -use ethcore::transaction::SignedTransaction; -use ethcore::receipt::{Receipt}; -use ethcore::spec::Spec; -use ethcore::engine::Engine; -use super::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; +use views::{BlockView, HeaderView}; +use client::{ExtendedBlockChainClient, BlockID}; +use block::{ClosedBlock, IsBlock}; +use error::*; +use client::{Executive, Executed, EnvInfo, TransactOptions}; +use transaction::SignedTransaction; +use receipt::{Receipt}; +use spec::Spec; +use engine::Engine; +use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; /// Keeps track of transactions using priority queue and holds currently mined block. pub struct Miner { diff --git a/miner/src/lib.rs b/ethcore/src/miner/mod.rs similarity index 89% rename from miner/src/lib.rs rename to ethcore/src/miner/mod.rs index db3315376..95453027c 100644 --- a/miner/src/lib.rs +++ b/ethcore/src/miner/mod.rs @@ -26,12 +26,11 @@ //! ```rust //! extern crate ethcore_util as util; //! extern crate ethcore; -//! extern crate ethminer; //! use std::env; //! use util::network::{NetworkService, NetworkConfiguration}; -//! use ethcore::client::{Client, ClientConfig}; -//! use ethcore::ethereum; -//! use ethminer::{Miner, MinerService}; +//! use client::{Client, ClientConfig}; +//! use ethereum; +//! use ethcore::miner::{Miner, MinerService}; //! //! fn main() { //! let miner: Miner = Miner::default(); @@ -43,30 +42,21 @@ //! } //! ``` - -#[macro_use] -extern crate log; -#[macro_use] -extern crate ethcore_util as util; -extern crate ethcore; -extern crate env_logger; -extern crate rayon; - mod miner; mod external; mod transaction_queue; -pub use transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; -pub use miner::{Miner}; -pub use external::{ExternalMiner, ExternalMinerService}; +pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; +pub use self::miner::{Miner}; +pub use self::external::{ExternalMiner, ExternalMinerService}; use std::collections::BTreeMap; use util::{H256, U256, Address, Bytes}; -use ethcore::client::{ExtendedBlockChainClient, Executed}; -use ethcore::block::ClosedBlock; -use ethcore::receipt::Receipt; -use ethcore::error::{Error, ExecutionError}; -use ethcore::transaction::SignedTransaction; +use client::{ExtendedBlockChainClient, Executed}; +use block::ClosedBlock; +use receipt::Receipt; +use error::{Error, ExecutionError}; +use transaction::SignedTransaction; /// Miner client API pub trait MinerService : Send + Sync { diff --git a/miner/src/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs similarity index 99% rename from miner/src/transaction_queue.rs rename to ethcore/src/miner/transaction_queue.rs index fc62c411e..1b88a7a11 100644 --- a/miner/src/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -89,8 +89,8 @@ use std::collections::{HashMap, BTreeSet}; use util::numbers::{Uint, U256}; use util::hash::{Address, H256}; use util::table::*; -use ethcore::transaction::*; -use ethcore::error::{Error, TransactionError}; +use transaction::*; +use error::{Error, TransactionError}; /// Transaction origin #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 38bd873b8..e82f6725b 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -21,6 +21,7 @@ use util::panics::*; use spec::Spec; use error::*; use client::{Client, ClientConfig}; +use miner::Miner; /// Message type for external and internal events #[derive(Clone)] @@ -54,14 +55,14 @@ pub struct ClientService { impl ClientService { /// Start the service in a separate thread. - pub fn start(config: ClientConfig, spec: Spec, net_config: NetworkConfiguration, db_path: &Path) -> Result { + pub fn start(config: ClientConfig, spec: Spec, net_config: NetworkConfiguration, db_path: &Path, miner: Arc) -> Result { let panic_handler = PanicHandler::new_in_arc(); let mut net_service = try!(NetworkService::start(net_config)); panic_handler.forward_from(&net_service); info!("Starting {}", net_service.host_info()); info!("Configured for {} using {:?} engine", spec.name, spec.engine.name()); - let client = try!(Client::new(config, spec, db_path, net_service.io().channel())); + let client = try!(Client::new(config, spec, db_path, miner, net_service.io().channel())); panic_handler.forward_from(client.deref()); let client_io = Arc::new(ClientIoHandler { client: client.clone() From a845e08bc6ab8f8f8073fd659e731c76b815cb6a Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 20:33:26 +0200 Subject: [PATCH 04/21] rename of the trait --- ethcore/src/client/client.rs | 4 ++-- ethcore/src/client/mod.rs | 2 +- ethcore/src/client/test_client.rs | 4 ++-- ethcore/src/miner/miner.rs | 32 +++++++++++++++---------------- ethcore/src/miner/mod.rs | 24 +++++++++++------------ 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index d23bffa31..6ff56b3ea 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -37,7 +37,7 @@ use filter::Filter; use log_entry::LocalizedLogEntry; use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; -use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, ExtendedBlockChainClient, TraceFilter}; +use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, MiningBlockChainClient, TraceFilter}; use client::Error as ClientError; use env_info::EnvInfo; use executive::{Executive, Executed, TransactOptions, contract_address}; @@ -722,7 +722,7 @@ impl BlockChainClient for Client where V: Verifier { } } -impl ExtendedBlockChainClient for Client where V: Verifier { +impl MiningBlockChainClient for Client where V: Verifier { fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> (Option, HashSet) { let engine = self.engine.deref().deref(); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 67c753d46..209a9f6e2 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -185,7 +185,7 @@ pub trait BlockChainClient : Sync + Send { } /// Extended client interface used for mining -pub trait ExtendedBlockChainClient : BlockChainClient { +pub trait MiningBlockChainClient : BlockChainClient { /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index ad398bbcb..fd392f025 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder}; use util::*; use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action}; use blockchain::TreeRoute; -use client::{BlockChainClient, ExtendedBlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes}; +use client::{BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes}; use header::{Header as BlockHeader, BlockNumber}; use filter::Filter; use log_entry::LocalizedLogEntry; @@ -235,7 +235,7 @@ impl TestBlockChainClient { } } -impl ExtendedBlockChainClient for TestBlockChainClient { +impl MiningBlockChainClient for TestBlockChainClient { fn try_seal(&self, block: LockedBlock, _seal: Vec) -> Result { Err(block) } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index c4bec7659..5f49a38c9 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -20,7 +20,7 @@ use std::sync::atomic::AtomicBool; use util::*; use util::keys::store::{AccountService, AccountProvider}; use views::{BlockView, HeaderView}; -use client::{ExtendedBlockChainClient, BlockID}; +use client::{MiningBlockChainClient, BlockID}; use block::{ClosedBlock, IsBlock}; use error::*; use client::{Executive, Executed, EnvInfo, TransactOptions}; @@ -104,7 +104,7 @@ impl Miner { /// Prepares new block for sealing including top transactions from queue. #[cfg_attr(feature="dev", allow(match_same_arms))] #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] - fn prepare_sealing(&self, chain: &ExtendedBlockChainClient) { + fn prepare_sealing(&self, chain: &MiningBlockChainClient) { trace!(target: "miner", "prepare_sealing: entering"); let transactions = self.transaction_queue.lock().unwrap().top_transactions(); let mut sealing_work = self.sealing_work.lock().unwrap(); @@ -206,14 +206,14 @@ impl Miner { trace!(target: "miner", "prepare_sealing: leaving (last={:?})", sealing_work.peek_last_ref().map(|b| b.block().fields().header.hash())); } - fn update_gas_limit(&self, chain: &ExtendedBlockChainClient) { + fn update_gas_limit(&self, chain: &MiningBlockChainClient) { let gas_limit = HeaderView::new(&chain.best_block_header()).gas_limit(); let mut queue = self.transaction_queue.lock().unwrap(); queue.set_gas_limit(gas_limit); } /// Returns true if we had to prepare new pending block - fn enable_and_prepare_sealing(&self, chain: &ExtendedBlockChainClient) -> bool { + fn enable_and_prepare_sealing(&self, chain: &MiningBlockChainClient) -> bool { trace!(target: "miner", "enable_and_prepare_sealing: entering"); let have_work = self.sealing_work.lock().unwrap().peek_last_ref().is_some(); trace!(target: "miner", "enable_and_prepare_sealing: have_work={}", have_work); @@ -237,7 +237,7 @@ const SEALING_TIMEOUT_IN_BLOCKS : u64 = 5; impl MinerService for Miner { - fn clear_and_reset(&self, chain: &ExtendedBlockChainClient) { + fn clear_and_reset(&self, chain: &MiningBlockChainClient) { self.transaction_queue.lock().unwrap().clear(); self.update_sealing(chain); } @@ -252,7 +252,7 @@ impl MinerService for Miner { } } - fn call(&self, chain: &ExtendedBlockChainClient, t: &SignedTransaction) -> Result { + fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction) -> Result { let sealing_work = self.sealing_work.lock().unwrap(); match sealing_work.peek_last_ref() { Some(work) => { @@ -288,7 +288,7 @@ impl MinerService for Miner { } } - fn balance(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256 { + fn balance(&self, chain: &MiningBlockChainClient, address: &Address) -> U256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else( || chain.latest_balance(address), @@ -296,7 +296,7 @@ impl MinerService for Miner { ) } - fn storage_at(&self, chain: &ExtendedBlockChainClient, address: &Address, position: &H256) -> H256 { + fn storage_at(&self, chain: &MiningBlockChainClient, address: &Address, position: &H256) -> H256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else( || chain.latest_storage_at(address, position), @@ -304,12 +304,12 @@ impl MinerService for Miner { ) } - fn nonce(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256 { + fn nonce(&self, chain: &MiningBlockChainClient, address: &Address) -> U256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else(|| chain.latest_nonce(address), |b| b.block().fields().state.nonce(address)) } - fn code(&self, chain: &ExtendedBlockChainClient, address: &Address) -> Option { + fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else(|| chain.code(address), |b| b.block().fields().state.code(address)) } @@ -376,7 +376,7 @@ impl MinerService for Miner { .collect() } - fn import_own_transaction(&self, chain: &ExtendedBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> + fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails { let hash = transaction.hash(); @@ -470,7 +470,7 @@ impl MinerService for Miner { self.transaction_queue.lock().unwrap().last_nonce(address) } - fn update_sealing(&self, chain: &ExtendedBlockChainClient) { + fn update_sealing(&self, chain: &MiningBlockChainClient) { if self.sealing_enabled.load(atomic::Ordering::Relaxed) { let current_no = chain.chain_info().best_block_number; let has_local_transactions = self.transaction_queue.lock().unwrap().has_local_pending_transactions(); @@ -490,7 +490,7 @@ impl MinerService for Miner { } } - fn map_sealing_work(&self, chain: &ExtendedBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { + fn map_sealing_work(&self, chain: &MiningBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { trace!(target: "miner", "map_sealing_work: entering"); self.enable_and_prepare_sealing(chain); trace!(target: "miner", "map_sealing_work: sealing prepared"); @@ -500,7 +500,7 @@ impl MinerService for Miner { ret.map(f) } - fn submit_seal(&self, chain: &ExtendedBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error> { + fn submit_seal(&self, chain: &MiningBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error> { if let Some(b) = self.sealing_work.lock().unwrap().take_used_if(|b| &b.hash() == &pow_hash) { match chain.try_seal(b.lock(), seal) { Err(_) => { @@ -523,8 +523,8 @@ impl MinerService for Miner { } } - fn chain_new_blocks(&self, chain: &ExtendedBlockChainClient, _imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) { - fn fetch_transactions(chain: &ExtendedBlockChainClient, hash: &H256) -> Vec { + fn chain_new_blocks(&self, chain: &MiningBlockChainClient, _imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) { + fn fetch_transactions(chain: &MiningBlockChainClient, hash: &H256) -> Vec { let block = chain .block(BlockID::Hash(*hash)) // Client should send message after commit to db and inserting to chain. diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 95453027c..824b1f51b 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -52,7 +52,7 @@ pub use self::external::{ExternalMiner, ExternalMinerService}; use std::collections::BTreeMap; use util::{H256, U256, Address, Bytes}; -use client::{ExtendedBlockChainClient, Executed}; +use client::{MiningBlockChainClient, Executed}; use block::ClosedBlock; use receipt::Receipt; use error::{Error, ExecutionError}; @@ -100,7 +100,7 @@ pub trait MinerService : Send + Sync { where T: Fn(&Address) -> AccountDetails, Self: Sized; /// Imports own (node owner) transaction to queue. - fn import_own_transaction(&self, chain: &ExtendedBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> + fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails, Self: Sized; @@ -108,20 +108,20 @@ pub trait MinerService : Send + Sync { fn pending_transactions_hashes(&self) -> Vec; /// Removes all transactions from the queue and restart mining operation. - fn clear_and_reset(&self, chain: &ExtendedBlockChainClient); + fn clear_and_reset(&self, chain: &MiningBlockChainClient); /// Called when blocks are imported to chain, updates transactions queue. - fn chain_new_blocks(&self, chain: &ExtendedBlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); + fn chain_new_blocks(&self, chain: &MiningBlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); /// New chain head event. Restart mining operation. - fn update_sealing(&self, chain: &ExtendedBlockChainClient); + fn update_sealing(&self, chain: &MiningBlockChainClient); /// Submit `seal` as a valid solution for the header of `pow_hash`. /// Will check the seal, but not actually insert the block into the chain. - fn submit_seal(&self, chain: &ExtendedBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error>; + fn submit_seal(&self, chain: &MiningBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error>; /// Get the sealing work package and if `Some`, apply some transform. - fn map_sealing_work(&self, chain: &ExtendedBlockChainClient, f: F) -> Option + fn map_sealing_work(&self, chain: &MiningBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T, Self: Sized; /// Query pending transactions for hash. @@ -146,19 +146,19 @@ pub trait MinerService : Send + Sync { fn sensible_gas_limit(&self) -> U256 { x!(21000) } /// Latest account balance in pending state. - fn balance(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256; + fn balance(&self, chain: &MiningBlockChainClient, address: &Address) -> U256; /// Call into contract code using pending state. - fn call(&self, chain: &ExtendedBlockChainClient, t: &SignedTransaction) -> Result; + fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction) -> Result; /// Get storage value in pending state. - fn storage_at(&self, chain: &ExtendedBlockChainClient, address: &Address, position: &H256) -> H256; + fn storage_at(&self, chain: &MiningBlockChainClient, address: &Address, position: &H256) -> H256; /// Get account nonce in pending state. - fn nonce(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256; + fn nonce(&self, chain: &MiningBlockChainClient, address: &Address) -> U256; /// Get contract code in pending state. - fn code(&self, chain: &ExtendedBlockChainClient, address: &Address) -> Option; + fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option; } /// Mining status From f5ed31792fcd6daa252e748725c243c106edd55f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 20:54:02 +0200 Subject: [PATCH 05/21] fixed sync with client only --- Cargo.lock | 18 +----------------- Cargo.toml | 3 +-- miner/Cargo.toml | 24 ------------------------ miner/build.rs | 25 ------------------------- rpc/Cargo.toml | 3 +-- sync/Cargo.toml | 3 +-- sync/src/chain.rs | 10 +++------- sync/src/io.rs | 8 ++++---- sync/src/lib.rs | 6 ++---- sync/src/tests/helpers.rs | 1 - 10 files changed, 13 insertions(+), 88 deletions(-) delete mode 100644 miner/Cargo.toml delete mode 100644 miner/build.rs diff --git a/Cargo.lock b/Cargo.lock index cc2a8ef8c..291e90562 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,6 @@ dependencies = [ "ethcore-rpc 1.2.0", "ethcore-signer 1.2.0", "ethcore-util 1.2.0", - "ethminer 1.2.0", "ethsync 1.2.0", "fdlimit 0.1.0", "hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -255,6 +254,7 @@ dependencies = [ "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -334,7 +334,6 @@ dependencies = [ "ethcore-devtools 1.2.0", "ethcore-util 1.2.0", "ethjson 0.1.0", - "ethminer 1.2.0", "ethsync 1.2.0", "json-ipc-server 0.1.0 (git+https://github.com/ethcore/json-ipc-server.git)", "jsonrpc-core 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -415,20 +414,6 @@ dependencies = [ "syntex 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ethminer" -version = "1.2.0" -dependencies = [ - "clippy 0.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.2.0", - "ethcore-util 1.2.0", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ethsync" version = "1.2.0" @@ -437,7 +422,6 @@ dependencies = [ "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.2.0", "ethcore-util 1.2.0", - "ethminer 1.2.0", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index d7813468a..ce8823bd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ clippy = { version = "0.0.69", optional = true} ethcore = { path = "ethcore" } ethcore-util = { path = "util" } ethsync = { path = "sync" } -ethminer = { path = "miner" } ethcore-devtools = { path = "devtools" } ethcore-rpc = { path = "rpc", optional = true } ethcore-signer = { path = "signer", optional = true } @@ -46,7 +45,7 @@ default-features = false default = ["rpc", "dapps", "ethcore-signer"] rpc = ["ethcore-rpc"] dapps = ["ethcore-dapps"] -dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "ethcore-rpc/dev", "ethminer/dev", +dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "ethcore-rpc/dev", "ethcore-dapps/dev", "ethcore-signer/dev"] travis-beta = ["ethcore/json-tests"] travis-nightly = ["ethcore/json-tests", "dev"] diff --git a/miner/Cargo.toml b/miner/Cargo.toml deleted file mode 100644 index a3a1c059f..000000000 --- a/miner/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -description = "Ethminer library" -homepage = "http://ethcore.io" -license = "GPL-3.0" -name = "ethminer" -version = "1.2.0" -authors = ["Ethcore "] -build = "build.rs" - -[build-dependencies] -rustc_version = "0.1" - -[dependencies] -ethcore-util = { path = "../util" } -ethcore = { path = "../ethcore" } -log = "0.3" -env_logger = "0.3" -rustc-serialize = "0.3" -rayon = "0.3.1" -clippy = { version = "0.0.69", optional = true} - -[features] -default = [] -dev = ["clippy"] diff --git a/miner/build.rs b/miner/build.rs deleted file mode 100644 index 41b9a1b3e..000000000 --- a/miner/build.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015, 2016 Ethcore (UK) Ltd. -// This file is part of Parity. - -// Parity 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 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. If not, see . - -extern crate rustc_version; - -use rustc_version::{version_meta, Channel}; - -fn main() { - if let Channel::Nightly = version_meta().channel { - println!("cargo:rustc-cfg=nightly"); - } -} diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 61b51cf88..2dbefd7f4 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -18,7 +18,6 @@ ethcore-util = { path = "../util" } ethcore = { path = "../ethcore" } ethash = { path = "../ethash" } ethsync = { path = "../sync" } -ethminer = { path = "../miner" } ethjson = { path = "../json" } ethcore-devtools = { path = "../devtools" } rustc-serialize = "0.3" @@ -34,4 +33,4 @@ syntex = "^0.32.0" [features] default = ["serde_codegen"] nightly = ["serde_macros"] -dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "ethminer/dev"] +dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev"] diff --git a/sync/Cargo.toml b/sync/Cargo.toml index 7940aaa2d..1b80e23fc 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -11,7 +11,6 @@ authors = ["Ethcore , /// Network ID network_id: U256, - /// Miner - miner: Arc, } type RlpResponseResult = Result, PacketDecodeError>; impl ChainSync { /// Create a new instance of syncing strategy. - pub fn new(config: SyncConfig, miner: Arc, chain: &BlockChainClient) -> ChainSync { + pub fn new(config: SyncConfig, chain: &BlockChainClient) -> ChainSync { let chain = chain.chain_info(); let mut sync = ChainSync { state: SyncState::ChainHead, @@ -265,7 +263,6 @@ impl ChainSync { imported_this_round: None, _max_download_ahead_blocks: max(MAX_HEADERS_TO_REQUEST, config.max_download_ahead_blocks), network_id: config.network_id, - miner: miner, }; sync.reset(); sync @@ -903,7 +900,7 @@ impl ChainSync { nonce: chain.latest_nonce(a), balance: chain.latest_balance(a), }; - let _ = io.chain().import_transactions(transactions, fetch_account); + let _ = io.chain().import_transactions(transactions); Ok(()) } @@ -1288,7 +1285,6 @@ mod tests { use ethcore::header::*; use ethcore::client::*; use ethcore::spec::Spec; - use ethminer::{Miner, MinerService}; fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { let mut header = Header::new(); diff --git a/sync/src/io.rs b/sync/src/io.rs index 49cccd7ca..53a546e1c 100644 --- a/sync/src/io.rs +++ b/sync/src/io.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethcore::client::MiningClient; use util::{NetworkContext, PeerId, PacketId,}; use util::error::UtilError; use ethcore::service::SyncMessage; +use ethcore::client::BlockChainClient; /// IO interface for the syning handler. /// Provides peer connection management and an interface to the blockchain client. @@ -32,7 +32,7 @@ pub trait SyncIo { /// Send a packet to a peer. fn send(&mut self, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), UtilError>; /// Get the blockchain - fn chain(&self) -> &MiningClient; + fn chain(&self) -> &BlockChainClient; /// Returns peer client identifier string fn peer_info(&self, peer_id: PeerId) -> String { peer_id.to_string() @@ -46,12 +46,12 @@ pub trait SyncIo { /// Wraps `NetworkContext` and the blockchain client pub struct NetSyncIo<'s, 'h> where 'h: 's { network: &'s NetworkContext<'h, SyncMessage>, - chain: &'s MiningClient + chain: &'s BlockChainClient } impl<'s, 'h> NetSyncIo<'s, 'h> { /// Creates a new instance from the `NetworkContext` and the blockchain client reference. - pub fn new(network: &'s NetworkContext<'h, SyncMessage>, chain: &'s MiningClient) -> NetSyncIo<'s, 'h> { + pub fn new(network: &'s NetworkContext<'h, SyncMessage>, chain: &'s BlockChainClient) -> NetSyncIo<'s, 'h> { NetSyncIo { network: network, chain: chain, diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 6b72a24fc..9fa6501a2 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -55,7 +55,6 @@ extern crate log; #[macro_use] extern crate ethcore_util as util; extern crate ethcore; -extern crate ethminer; extern crate env_logger; extern crate time; extern crate rand; @@ -69,7 +68,6 @@ use util::TimerToken; use util::{U256, ONE_U256}; use ethcore::client::Client; use ethcore::service::SyncMessage; -use ethminer::Miner; use io::NetSyncIo; use chain::ChainSync; @@ -115,8 +113,8 @@ pub use self::chain::{SyncStatus, SyncState}; impl EthSync { /// Creates and register protocol with the network service - pub fn register(service: &mut NetworkService, config: SyncConfig, chain: Arc, miner: Arc) -> Arc { - let sync = ChainSync::new(config, miner, chain.deref()); + pub fn register(service: &mut NetworkService, config: SyncConfig, chain: Arc) -> Arc { + let sync = ChainSync::new(config, chain.deref()); let sync = Arc::new(EthSync { chain: chain, sync: RwLock::new(sync), diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 70ddb78db..c2e0e2d04 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -19,7 +19,6 @@ use ethcore::client::{TestBlockChainClient, BlockChainClient}; use ethcore::spec::Spec; use io::SyncIo; use chain::ChainSync; -use ethminer::Miner; use ::SyncConfig; pub struct TestIo<'p> { From 10d914d6c663a0f9bb9b2d517bebee7ae3115832 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 20:58:33 +0200 Subject: [PATCH 06/21] restored chain_new_blocks --- sync/src/chain.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 42d425af9..1270f775f 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1272,6 +1272,18 @@ impl ChainSync { pub fn maintain_sync(&mut self, io: &mut SyncIo) { self.check_resume(io); } + + /// called when block is imported to chain, updates transactions queue and propagates the blocks + pub fn chain_new_blocks(&mut self, io: &mut SyncIo, _imported: &[H256], invalid: &[H256], _enacted: &[H256], _retracted: &[H256]) { + if io.is_chain_queue_empty() { + // Propagate latests blocks + self.propagate_latest_blocks(io); + } + if !invalid.is_empty() { + trace!(target: "sync", "Bad blocks in the queue, restarting"); + self.restart_on_bad_block(io); + } + } } #[cfg(test)] From 495e7feb62807ec90f3548cfae16d606453d05fc Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:13:32 +0200 Subject: [PATCH 07/21] dispatching message return --- sync/src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 9fa6501a2..863ad6382 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -164,5 +164,12 @@ impl NetworkProtocolHandler for EthSync { } fn message(&self, io: &NetworkContext, message: &SyncMessage) { + match *message { + SyncMessage::NewChainBlocks { ref imported, ref invalid, ref enacted, ref retracted } => { + let mut sync_io = NetSyncIo::new(io, self.chain.deref()); + self.sync.write().unwrap().chain_new_blocks(&mut sync_io, imported, invalid, enacted, retracted); + }, + _ => {/* Ignore other messages */}, + } } } From 2a08fb8fe3ffaff3de41aa7427ba5c38c1559232 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:17:46 +0200 Subject: [PATCH 08/21] and conditional dispatch --- ethcore/src/client/client.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 6ff56b3ea..4df72f1fd 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -338,7 +338,17 @@ impl Client where V: Verifier { { if !imported_blocks.is_empty() && self.block_queue.queue_info().is_empty() { let (enacted, retracted) = self.calculate_enacted_retracted(import_results); - self.miner.chain_new_blocks(self, &imported_blocks, &invalid_blocks, &enacted, &retracted); + + if self.queue_info().is_empty() { + self.miner.chain_new_blocks(self, &imported_blocks, &invalid_blocks, &enacted, &retracted); + } + + io.send(NetworkIoMessage::User(SyncMessage::NewChainBlocks { + imported: imported_blocks, + invalid: invalid_blocks, + enacted: enacted, + retracted: retracted, + })).unwrap(); } } From 77cef765183491e69d53210258824c43e22bf5d0 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:31:42 +0200 Subject: [PATCH 09/21] rpc bindings resolved --- parity/dapps.rs | 2 +- parity/main.rs | 2 +- parity/rpc.rs | 2 +- parity/signer.rs | 2 +- rpc/src/lib.rs | 1 - rpc/src/v1/impls/eth.rs | 16 +++++++------- rpc/src/v1/impls/ethcore.rs | 2 +- rpc/src/v1/impls/mod.rs | 10 ++++----- rpc/src/v1/impls/personal.rs | 10 ++++----- rpc/src/v1/tests/eth.rs | 6 +++--- rpc/src/v1/tests/helpers/miner_service.rs | 26 +++++++++++------------ rpc/src/v1/tests/mocked/eth.rs | 2 +- rpc/src/v1/tests/mocked/ethcore.rs | 2 +- sync/src/chain.rs | 2 +- sync/src/tests/helpers.rs | 2 +- 15 files changed, 43 insertions(+), 44 deletions(-) diff --git a/parity/dapps.rs b/parity/dapps.rs index 986e3dd07..7909bb9bc 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -19,7 +19,7 @@ use std::str::FromStr; use std::net::SocketAddr; use ethcore::client::Client; use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; +use ethcore::miner::{Miner, ExternalMiner}; use util::RotatingLogger; use util::panics::PanicHandler; use util::keys::store::AccountService; diff --git a/parity/main.rs b/parity/main.rs index 7f16d28a5..539797fb9 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -85,7 +85,7 @@ use ethcore::error::{Error, ImportError}; use ethcore::service::ClientService; use ethcore::spec::Spec; use ethsync::EthSync; -use ethminer::{Miner, MinerService, ExternalMiner}; +use ethcore::miner::{Miner, MinerService, ExternalMiner}; use daemonize::Daemonize; use migration::migrate; use informant::Informant; diff --git a/parity/rpc.rs b/parity/rpc.rs index 60766263b..0d8d7562e 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -21,7 +21,7 @@ use std::sync::Arc; use std::net::SocketAddr; use ethcore::client::Client; use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; +use ethcore::miner::{Miner, ExternalMiner}; use util::RotatingLogger; use util::panics::PanicHandler; use util::keys::store::AccountService; diff --git a/parity/signer.rs b/parity/signer.rs index 5e3339bcc..3f6197e3a 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use ethcore::client::Client; use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; +use ethcore::miner::{Miner, ExternalMiner}; use util::keys::store::AccountService; use util::panics::{PanicHandler, ForwardPanic}; use die::*; diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 24d58819c..80c92388a 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -29,7 +29,6 @@ extern crate jsonrpc_http_server; extern crate ethcore_util as util; extern crate ethcore; extern crate ethsync; -extern crate ethminer; extern crate transient_hashmap; extern crate json_ipc_server as ipc; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index a57fc333c..ad15fb2f7 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -22,13 +22,13 @@ use std::collections::HashSet; use std::sync::{Arc, Weak, Mutex}; use std::ops::Deref; use ethsync::{SyncProvider, SyncState}; -use ethminer::{MinerService, ExternalMinerService}; +use ethcore::miner::{MinerService, ExternalMinerService}; use jsonrpc_core::*; use util::numbers::*; use util::sha3::*; use util::rlp::{encode, decode, UntrustedRlp, View}; use util::keys::store::AccountProvider; -use ethcore::client::{BlockChainClient, BlockID, TransactionID, UncleID}; +use ethcore::client::{MiningBlockChainClient, BlockID, TransactionID, UncleID}; use ethcore::block::IsBlock; use ethcore::views::*; use ethcore::ethereum::Ethash; @@ -44,7 +44,7 @@ use serde; /// Eth rpc implementation. pub struct EthClient where - C: BlockChainClient, + C: MiningBlockChainClient, S: SyncProvider, A: AccountProvider, M: MinerService, @@ -59,7 +59,7 @@ pub struct EthClient where } impl EthClient where - C: BlockChainClient, + C: MiningBlockChainClient, S: SyncProvider, A: AccountProvider, M: MinerService, @@ -224,7 +224,7 @@ fn make_unsupported_err() -> Error { } impl Eth for EthClient where - C: BlockChainClient + 'static, + C: MiningBlockChainClient + 'static, S: SyncProvider + 'static, A: AccountProvider + 'static, M: MinerService + 'static, @@ -566,7 +566,7 @@ impl Eth for EthClient where /// Eth filter rpc implementation. pub struct EthFilterClient where - C: BlockChainClient, + C: MiningBlockChainClient, M: MinerService { client: Weak, @@ -575,7 +575,7 @@ pub struct EthFilterClient where } impl EthFilterClient where - C: BlockChainClient, + C: MiningBlockChainClient, M: MinerService { /// Creates new Eth filter client. @@ -589,7 +589,7 @@ impl EthFilterClient where } impl EthFilter for EthFilterClient where - C: BlockChainClient + 'static, + C: MiningBlockChainClient + 'static, M: MinerService + 'static { fn new_filter(&self, params: Params) -> Result { diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs index f5d6f1fda..e649e37f4 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/ethcore.rs @@ -22,7 +22,7 @@ use std::sync::{Arc, Weak}; use std::ops::Deref; use std::collections::BTreeMap; use jsonrpc_core::*; -use ethminer::MinerService; +use ethcore::miner::MinerService; use v1::traits::Ethcore; use v1::types::Bytes; diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 7ee8b8b8a..2f1c07ff6 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -47,8 +47,8 @@ pub use self::rpc::RpcClient; use v1::types::TransactionRequest; use std::sync::Weak; -use ethminer::{AccountDetails, MinerService}; -use ethcore::client::BlockChainClient; +use ethcore::miner::{AccountDetails, MinerService}; +use ethcore::client::MiningBlockChainClient; use ethcore::transaction::{Action, SignedTransaction, Transaction}; use util::numbers::*; use util::rlp::encode; @@ -56,7 +56,7 @@ use util::bytes::ToPretty; use jsonrpc_core::{Error, to_value, Value}; fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result - where C: BlockChainClient, M: MinerService { + where C: MiningBlockChainClient, M: MinerService { let hash = signed_transaction.hash(); let import = miner.import_own_transaction(client, signed_transaction, |a: &Address| { @@ -70,7 +70,7 @@ fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedT } fn sign_and_dispatch(client: &Weak, miner: &Weak, request: TransactionRequest, secret: H256) -> Result - where C: BlockChainClient, M: MinerService { + where C: MiningBlockChainClient, M: MinerService { let client = take_weak!(client); let miner = take_weak!(miner); @@ -92,4 +92,4 @@ fn sign_and_dispatch(client: &Weak, miner: &Weak, request: Transacti trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); dispatch_transaction(&*client, &*miner, signed_transaction) -} \ No newline at end of file +} diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 19e902996..074bb8c77 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -22,19 +22,19 @@ use v1::types::TransactionRequest; use v1::impls::sign_and_dispatch; use util::keys::store::*; use util::numbers::*; -use ethcore::client::BlockChainClient; -use ethminer::MinerService; +use ethcore::client::MiningBlockChainClient; +use ethcore::miner::MinerService; /// Account management (personal) rpc implementation. pub struct PersonalClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { accounts: Weak, client: Weak, miner: Weak, } impl PersonalClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { /// Creates new PersonalClient pub fn new(store: &Arc, client: &Arc, miner: &Arc) -> Self { PersonalClient { @@ -46,7 +46,7 @@ impl PersonalClient } impl Personal for PersonalClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { fn accounts(&self, _: Params) -> Result { let store = take_weak!(self.accounts); match store.accounts() { diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 80a856aca..7f5d5e333 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,12 +19,12 @@ use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; -use ethcore::client::{BlockChainClient, Client, ClientConfig}; +use ethcore::client::{MiningBlockChainClient, Client, ClientConfig}; use ethcore::spec::Genesis; use ethcore::block::Block; use ethcore::ethereum; use ethcore::transaction::{Transaction, Action}; -use ethminer::{MinerService, ExternalMiner}; +use ethcore::miner::{MinerService, ExternalMiner}; use devtools::RandomTempPath; use util::io::IoChannel; use util::hash::Address; @@ -38,7 +38,7 @@ use v1::impls::EthClient; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; struct EthTester { - _client: Arc, + _client: Arc, _miner: Arc, accounts: Arc, handler: IoHandler, diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 600f88508..a53ca3a08 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -19,11 +19,11 @@ use util::{Address, H256, Bytes, U256, FixedHash, Uint}; use util::standard::*; use ethcore::error::{Error, ExecutionError}; -use ethcore::client::{BlockChainClient, Executed}; +use ethcore::client::{MiningBlockChainClient, Executed}; use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::transaction::SignedTransaction; use ethcore::receipt::Receipt; -use ethminer::{MinerService, MinerStatus, AccountDetails, TransactionImportResult}; +use ethcore::miner::{MinerService, MinerStatus, AccountDetails, TransactionImportResult}; /// Test miner service. pub struct TestMinerService { @@ -132,7 +132,7 @@ impl MinerService for TestMinerService { } /// Imports transactions to transaction queue. - fn import_own_transaction(&self, chain: &BlockChainClient, transaction: SignedTransaction, _fetch_account: T) -> + fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction, _fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails { @@ -154,21 +154,21 @@ impl MinerService for TestMinerService { } /// Removes all transactions from the queue and restart mining operation. - fn clear_and_reset(&self, _chain: &BlockChainClient) { + fn clear_and_reset(&self, _chain: &MiningBlockChainClient) { unimplemented!(); } /// Called when blocks are imported to chain, updates transactions queue. - fn chain_new_blocks(&self, _chain: &BlockChainClient, _imported: &[H256], _invalid: &[H256], _enacted: &[H256], _retracted: &[H256]) { + fn chain_new_blocks(&self, _chain: &MiningBlockChainClient, _imported: &[H256], _invalid: &[H256], _enacted: &[H256], _retracted: &[H256]) { unimplemented!(); } /// New chain head event. Restart mining operation. - fn update_sealing(&self, _chain: &BlockChainClient) { + fn update_sealing(&self, _chain: &MiningBlockChainClient) { unimplemented!(); } - fn map_sealing_work(&self, _chain: &BlockChainClient, _f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { + fn map_sealing_work(&self, _chain: &MiningBlockChainClient, _f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { unimplemented!(); } @@ -194,29 +194,29 @@ impl MinerService for TestMinerService { /// Submit `seal` as a valid solution for the header of `pow_hash`. /// Will check the seal, but not actually insert the block into the chain. - fn submit_seal(&self, _chain: &BlockChainClient, _pow_hash: H256, _seal: Vec) -> Result<(), Error> { + fn submit_seal(&self, _chain: &MiningBlockChainClient, _pow_hash: H256, _seal: Vec) -> Result<(), Error> { unimplemented!(); } - fn balance(&self, _chain: &BlockChainClient, address: &Address) -> U256 { + fn balance(&self, _chain: &MiningBlockChainClient, address: &Address) -> U256 { self.latest_closed_block.lock().unwrap().as_ref().map_or_else(U256::zero, |b| b.block().fields().state.balance(address).clone()) } - fn call(&self, _chain: &BlockChainClient, _t: &SignedTransaction) -> Result { + fn call(&self, _chain: &MiningBlockChainClient, _t: &SignedTransaction) -> Result { unimplemented!(); } - fn storage_at(&self, _chain: &BlockChainClient, address: &Address, position: &H256) -> H256 { + fn storage_at(&self, _chain: &MiningBlockChainClient, address: &Address, position: &H256) -> H256 { self.latest_closed_block.lock().unwrap().as_ref().map_or_else(H256::default, |b| b.block().fields().state.storage_at(address, position).clone()) } - fn nonce(&self, _chain: &BlockChainClient, address: &Address) -> U256 { + fn nonce(&self, _chain: &MiningBlockChainClient, address: &Address) -> U256 { // we assume all transactions are in a pending block, ignoring the // reality of gas limits. self.last_nonce(address).unwrap_or(U256::zero()) } - fn code(&self, _chain: &BlockChainClient, address: &Address) -> Option { + fn code(&self, _chain: &MiningBlockChainClient, address: &Address) -> Option { self.latest_closed_block.lock().unwrap().as_ref().map_or(None, |b| b.block().fields().state.code(address).clone()) } diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index c51d6d7da..579f57e6c 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -25,7 +25,7 @@ use ethcore::client::{TestBlockChainClient, EachBlockWith, Executed, Transaction use ethcore::log_entry::{LocalizedLogEntry, LogEntry}; use ethcore::receipt::LocalizedReceipt; use ethcore::transaction::{Transaction, Action}; -use ethminer::{ExternalMiner, MinerService}; +use ethcore::miner::{ExternalMiner, MinerService}; use ethsync::SyncState; use v1::{Eth, EthClient}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; diff --git a/rpc/src/v1/tests/mocked/ethcore.rs b/rpc/src/v1/tests/mocked/ethcore.rs index cc822daef..d51545d86 100644 --- a/rpc/src/v1/tests/mocked/ethcore.rs +++ b/rpc/src/v1/tests/mocked/ethcore.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use std::str::FromStr; use jsonrpc_core::IoHandler; use v1::{Ethcore, EthcoreClient}; -use ethminer::MinerService; +use ethcore::miner::MinerService; use v1::tests::helpers::TestMinerService; use util::numbers::*; use rustc_serialize::hex::FromHex; diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 1270f775f..dc397d77d 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1470,7 +1470,7 @@ mod tests { } fn dummy_sync_with_peer(peer_latest_hash: H256, client: &BlockChainClient) -> ChainSync { - let mut sync = ChainSync::new(SyncConfig::default(), Miner::new(false, Spec::new_test()), client); + let mut sync = ChainSync::new(SyncConfig::default(), client); sync.peers.insert(0, PeerInfo { protocol_version: 0, diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index c2e0e2d04..7cde0b54c 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -92,7 +92,7 @@ impl TestNet { }; for _ in 0..n { let chain = TestBlockChainClient::new(); - let sync = ChainSync::new(SyncConfig::default(), Miner::new(false, Spec::new_test()), &chain); + let sync = ChainSync::new(SyncConfig::default(), &chain); net.peers.push(TestPeer { sync: sync, chain: chain, From c33b1caf21d67ce3f5b56b2894ec000ff10a79e7 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:38:07 +0200 Subject: [PATCH 10/21] executable all issues resolved --- parity/main.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 539797fb9..0575d80ea 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -27,7 +27,6 @@ extern crate rustc_serialize; extern crate ethcore_util as util; extern crate ethcore; extern crate ethsync; -extern crate ethminer; #[macro_use] extern crate log as rlog; extern crate env_logger; @@ -173,14 +172,6 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Secret Store let account_service = Arc::new(conf.account_service()); - // Build client - let mut service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()) - ).unwrap_or_else(|e| die_with_error("Client", e)); - - panic_handler.forward_from(&service); - let client = service.client(); - // Miner let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), account_service.clone()); miner.set_author(conf.author()); @@ -189,11 +180,19 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) miner.set_minimal_gas_price(conf.gas_price()); miner.set_transactions_limit(conf.args.flag_tx_limit); + // Build client + let mut service = ClientService::start( + client_config, spec, net_settings, Path::new(&conf.path()), miner.clone() + ).unwrap_or_else(|e| die_with_error("Client", e)); + + panic_handler.forward_from(&service); + let client = service.client(); + let external_miner = Arc::new(ExternalMiner::default()); let network_settings = Arc::new(conf.network_settings()); // Sync - let sync = EthSync::register(service.network(), sync_config, client.clone(), miner.clone()); + let sync = EthSync::register(service.network(), sync_config, client.clone()); let dependencies = Arc::new(rpc::Dependencies { panic_handler: panic_handler.clone(), @@ -295,7 +294,7 @@ fn execute_export(conf: Configuration) { // Build client let service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()) + client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); @@ -366,7 +365,7 @@ fn execute_import(conf: Configuration) { // Build client let service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()) + client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); From dad61bb7cfb26f252a56236dcfb1368ffc64d676 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:40:26 +0200 Subject: [PATCH 11/21] test and travis fix for absent crate --- .travis.yml | 1 - test.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0f0766ee4..995b765c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,7 +72,6 @@ after_success: | $KCOV_CMD target/debug/deps/ethcore_rpc-* && $KCOV_CMD target/debug/deps/ethcore_dapps-* && $KCOV_CMD target/debug/deps/ethcore_signer-* && - $KCOV_CMD target/debug/deps/ethminer-* && $KCOV_CMD target/debug/deps/ethjson-* && $KCOV_CMD target/debug/parity-* && [ $TRAVIS_BRANCH = master ] && diff --git a/test.sh b/test.sh index e70718afc..d89740aba 100755 --- a/test.sh +++ b/test.sh @@ -10,5 +10,4 @@ cargo test --features ethcore/json-tests $1 \ -p ethcore-signer \ -p ethcore-dapps \ -p parity \ - -p ethminer \ -p bigint From d45a676dc0db78cb2ef3a85a2b7b3e647d950929 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 22:24:32 +0200 Subject: [PATCH 12/21] all tests fixed --- ethcore/src/client/test_client.rs | 4 ++++ ethcore/src/json_tests/chain.rs | 3 ++- ethcore/src/miner/miner.rs | 8 ++++---- ethcore/src/miner/transaction_queue.rs | 4 ++-- ethcore/src/service.rs | 4 +++- ethcore/src/tests/client.rs | 9 +++++---- ethcore/src/tests/helpers.rs | 5 +++-- rpc/src/v1/tests/eth.rs | 6 +++--- sync/src/chain.rs | 15 ++++++++------- sync/src/tests/chain.rs | 2 +- sync/src/tests/helpers.rs | 4 ++-- 11 files changed, 37 insertions(+), 27 deletions(-) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index fd392f025..fa91aab4a 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -28,6 +28,7 @@ use receipt::{Receipt, LocalizedReceipt}; use blockchain::extras::BlockReceipts; use error::{ImportResult}; use evm::Factory as EvmFactory; +use miner::Miner; use block_queue::BlockQueueInfo; use block::{SealedBlock, ClosedBlock, LockedBlock}; @@ -64,6 +65,8 @@ pub struct TestBlockChainClient { pub receipts: RwLock>, /// Block queue size. pub queue_size: AtomicUsize, + /// Miner + pub miner: Arc, } #[derive(Clone)] @@ -102,6 +105,7 @@ impl TestBlockChainClient { execution_result: RwLock::new(None), receipts: RwLock::new(HashMap::new()), queue_size: AtomicUsize::new(0), + miner: Arc::new(Miner::default()), }; client.add_blocks(1, EachBlockWith::Nothing); // add genesis block client.genesis_hash = client.last_hash.read().unwrap().clone(); diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index a1154f6a9..53052d8dc 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -22,6 +22,7 @@ use tests::helpers::*; use devtools::*; use spec::Genesis; use ethjson; +use miner::Miner; pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { init_log(); @@ -53,7 +54,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { let temp = RandomTempPath::new(); { - let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), spec, temp.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); for b in &blockchain.blocks_rlp() { if Block::is_good(&b) { let _ = client.import_block(b.clone()); diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 5f49a38c9..66ede48bf 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -585,11 +585,11 @@ impl MinerService for Miner { #[cfg(test)] mod tests { - use MinerService; - use super::{Miner}; + use super::super::MinerService; + use super::Miner; use util::*; - use ethcore::client::{TestBlockChainClient, EachBlockWith}; - use ethcore::block::*; + use client::{TestBlockChainClient, EachBlockWith}; + use block::*; // TODO [ToDr] To uncomment` when TestBlockChainClient can actually return a ClosedBlock. #[ignore] diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 1b88a7a11..bf1512bde 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -778,8 +778,8 @@ mod test { extern crate rustc_serialize; use util::table::*; use util::*; - use ethcore::transaction::*; - use ethcore::error::{Error, TransactionError}; + use transaction::*; + use error::{Error, TransactionError}; use super::*; use super::{TransactionSet, TransactionOrder, VerifiedTransaction}; diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index e82f6725b..13f1c9f74 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -142,12 +142,14 @@ mod tests { use util::network::*; use devtools::*; use client::ClientConfig; + use std::sync::Arc; + use miner::Miner; #[test] fn it_can_be_started() { let spec = get_test_spec(); let temp_path = RandomTempPath::new(); - let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path()); + let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path(), Arc::new(Miner::default())); assert!(service.is_ok()); } } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index d734b0b47..84bfb716f 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -14,16 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use client::{BlockChainClient, Client, ClientConfig, BlockID}; +use client::{BlockChainClient, MiningBlockChainClient, Client, ClientConfig, BlockID}; use block::IsBlock; use tests::helpers::*; use common::*; use devtools::*; +use miner::Miner; #[test] fn imports_from_empty() { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); client.import_verified_blocks(&IoChannel::disconnected()); client.flush_queue(); } @@ -41,7 +42,7 @@ fn returns_state_root_basic() { #[test] fn imports_good_block() { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let good_block = get_good_dummy_block(); if let Err(_) = client.import_block(good_block) { panic!("error importing block being good by definition"); @@ -56,7 +57,7 @@ fn imports_good_block() { #[test] fn query_none_block() { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let non_existant = client.block_header(BlockID::Number(188)); assert!(non_existant.is_none()); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 7262da9e8..cc841d7f4 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -23,6 +23,7 @@ use evm::Schedule; use engine::*; use ethereum; use devtools::*; +use miner::Miner; #[cfg(feature = "json-tests")] pub enum ChainEra { @@ -139,7 +140,7 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[&SignedTrans pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult> { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let test_spec = get_test_spec(); let test_engine = &test_spec.engine; let state_root = test_spec.genesis_header().state_root; @@ -205,7 +206,7 @@ pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting pub fn get_test_client_with_blocks(blocks: Vec) -> GuardedTempResult> { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); for block in &blocks { if let Err(_) = client.import_block(block.clone()) { panic!("panic importing block which is well-formed"); diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 7f5d5e333..eb50ea5d1 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,12 +19,12 @@ use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; -use ethcore::client::{MiningBlockChainClient, Client, ClientConfig}; +use ethcore::client::{MiningBlockChainClient, BlockChainClient, Client, ClientConfig}; use ethcore::spec::Genesis; use ethcore::block::Block; use ethcore::ethereum; use ethcore::transaction::{Transaction, Action}; -use ethcore::miner::{MinerService, ExternalMiner}; +use ethcore::miner::{MinerService, ExternalMiner, Miner}; use devtools::RandomTempPath; use util::io::IoChannel; use util::hash::Address; @@ -195,7 +195,7 @@ fn chain_harness(chain: BlockChain, mut cb: F) -> U assert!(spec.is_state_root_valid()); let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), spec, dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), spec, dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let sync_provider = sync_provider(); let miner_service = miner_service(); let account_provider = account_provider(); diff --git a/sync/src/chain.rs b/sync/src/chain.rs index dc397d77d..e3e773c26 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -101,7 +101,7 @@ use io::SyncIo; use time; use super::SyncConfig; use blocks::BlockCollection; -use ethcore::miner::{AccountDetails, TransactionImportResult}; +use ethcore::miner::{AccountDetails, TransactionImportResult, MinerService}; known_heap_size!(0, PeerInfo); @@ -1297,6 +1297,7 @@ mod tests { use ethcore::header::*; use ethcore::client::*; use ethcore::spec::Spec; + use ethcore::miner::MinerService; fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { let mut header = Header::new(); @@ -1702,8 +1703,8 @@ mod tests { let mut queue = VecDeque::new(); let mut io = TestIo::new(&mut client, &mut queue, None); sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); - assert_eq!(sync.miner.status().transactions_in_future_queue, 0); - assert_eq!(sync.miner.status().transactions_in_pending_queue, 1); + assert_eq!(io.chain.miner.status().transactions_in_future_queue, 0); + assert_eq!(io.chain.miner.status().transactions_in_pending_queue, 1); } // We need to update nonce status (because we say that the block has been imported) for h in &[good_blocks[0]] { @@ -1718,7 +1719,7 @@ mod tests { } // then - let status = sync.miner.status(); + let status = client.miner.status(); assert_eq!(status.transactions_in_pending_queue, 1); assert_eq!(status.transactions_in_future_queue, 0); } @@ -1740,12 +1741,12 @@ mod tests { // when sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); - assert_eq!(sync.miner.status().transactions_in_future_queue, 0); - assert_eq!(sync.miner.status().transactions_in_pending_queue, 0); + assert_eq!(io.chain.miner.status().transactions_in_future_queue, 0); + assert_eq!(io.chain.miner.status().transactions_in_pending_queue, 0); sync.chain_new_blocks(&mut io, &[], &[], &good_blocks, &retracted_blocks); // then - let status = sync.miner.status(); + let status = io.chain.miner.status(); assert_eq!(status.transactions_in_pending_queue, 0); assert_eq!(status.transactions_in_future_queue, 0); } diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index 463771ffe..09e83e358 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use util::*; -use ethcore::client::{MiningClient, BlockID, EachBlockWith}; +use ethcore::client::{BlockChainClient, BlockID, EachBlockWith}; use chain::{SyncState}; use super::helpers::*; diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 7cde0b54c..9ca0065ee 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use util::*; -use ethcore::client::{TestBlockChainClient, BlockChainClient}; +use ethcore::client::{TestBlockChainClient, MiningBlockChainClient, BlockChainClient}; use ethcore::spec::Spec; use io::SyncIo; use chain::ChainSync; @@ -62,7 +62,7 @@ impl<'p> SyncIo for TestIo<'p> { Ok(()) } - fn chain(&self) -> &MiningClient { + fn chain(&self) -> &BlockChainClient { self.chain } } From cee31f9e8da4d51b1bbf3bac714f86fe7575cf82 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 03:19:20 +0200 Subject: [PATCH 13/21] fix travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 995b765c2..230e7862f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ env: global: # GH_TOKEN - secure: bumJASbZSU8bxJ0EyPUJmu16AiV9EXOpyOj86Jlq/Ty9CfwGqsSXt96uDyE+OUJf34RUFQMsw0nk37/zC4lcn6kqk2wpuH3N/o85Zo/cVZY/NusBWLQqtT5VbYWsV+u2Ua4Tmmsw8yVYQhYwU2ZOejNpflL+Cs9XGgORp1L+/gMRMC2y5Se6ZhwnKPQlRJ8LGsG1dzjQULxzADIt3/zuspNBS8a2urJwlHfGMkvHDoUWCviP/GXoSqw3TZR7FmKyxE19I8n9+iSvm9+oZZquvcgfUxMHn8Gq/b44UbPvjtFOg2yam4xdWXF/RyWCHdc/R9EHorSABeCbefIsm+zcUF3/YQxwpSxM4IZEeH2rTiC7dcrsKw3XsO16xFQz5YI5Bay+CT/wTdMmJd7DdYz7Dyf+pOvcM9WOf/zorxYWSBOMYy0uzbusU2iyIghQ82s7E/Ahg+WARtPgkuTLSB5aL1oCTBKHqQscMr7lo5Ti6RpWLxEdTQMBznc+bMr+6dEtkEcG9zqc6cE9XX+ox3wTU6+HVMfQ1ltCntJ4UKcw3A6INEbw9wgocQa812CIASQ2fE+SCAbz6JxBjIAlFUnD1lUB7S8PdMPwn9plfQgKQ2A5YZqg6FnBdf0rQXIJYxQWKHXj/rBHSUCT0tHACDlzTA+EwWggvkP5AGIxRxm8jhw= - - TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethminer -p ethjson -p ethcore-dapps -p ethcore-signer" + - TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethjson -p ethcore-dapps -p ethcore-signer" - ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}" - KCOV_FEATURES="" - KCOV_CMD="./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov" From db749dc564bda58f07c71879db34b76b2ad0a2b1 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 12:44:11 +0200 Subject: [PATCH 14/21] fix remaining tests & doctest --- ethcore/src/client/test_client.rs | 13 ++++++++++--- sync/src/chain.rs | 9 ++------- sync/src/lib.rs | 7 +++---- sync/src/tests/helpers.rs | 3 +-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index fa91aab4a..83799c78f 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -28,7 +28,7 @@ use receipt::{Receipt, LocalizedReceipt}; use blockchain::extras::BlockReceipts; use error::{ImportResult}; use evm::Factory as EvmFactory; -use miner::Miner; +use miner::{Miner, MinerService}; use block_queue::BlockQueueInfo; use block::{SealedBlock, ClosedBlock, LockedBlock}; @@ -488,10 +488,17 @@ impl BlockChainClient for TestBlockChainClient { } fn import_transactions(&self, transactions: Vec) -> Vec> { - unimplemented!(); + let nonces = self.nonces.read().unwrap(); + let balances = self.balances.read().unwrap(); + let fetch_account = |a: &Address| AccountDetails { + nonce: nonces[a], + balance: balances[a], + }; + + self.miner.import_transactions(transactions, &fetch_account) } fn all_transactions(&self) -> Vec { - unimplemented!(); + self.miner.all_transactions() } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index e3e773c26..38d3a53f9 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -101,7 +101,6 @@ use io::SyncIo; use time; use super::SyncConfig; use blocks::BlockCollection; -use ethcore::miner::{AccountDetails, TransactionImportResult, MinerService}; known_heap_size!(0, PeerInfo); @@ -895,11 +894,6 @@ impl ChainSync { let tx: SignedTransaction = try!(r.val_at(i)); transactions.push(tx); } - let chain = io.chain(); - let fetch_account = |a: &Address| AccountDetails { - nonce: chain.latest_nonce(a), - balance: chain.latest_balance(a), - }; let _ = io.chain().import_transactions(transactions); Ok(()) } @@ -1296,7 +1290,6 @@ mod tests { use ethcore::views::BlockView; use ethcore::header::*; use ethcore::client::*; - use ethcore::spec::Spec; use ethcore::miner::MinerService; fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { @@ -1702,6 +1695,7 @@ mod tests { { let mut queue = VecDeque::new(); let mut io = TestIo::new(&mut client, &mut queue, None); + io.chain.miner.chain_new_blocks(io.chain, &[], &[], &[], &good_blocks); sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); assert_eq!(io.chain.miner.status().transactions_in_future_queue, 0); assert_eq!(io.chain.miner.status().transactions_in_pending_queue, 1); @@ -1715,6 +1709,7 @@ mod tests { { let mut queue = VecDeque::new(); let mut io = TestIo::new(&mut client, &mut queue, None); + io.chain.miner.chain_new_blocks(io.chain, &[], &[], &good_blocks, &retracted_blocks); sync.chain_new_blocks(&mut io, &[], &[], &good_blocks, &retracted_blocks); } diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 863ad6382..9f69bb7da 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -32,21 +32,20 @@ //! extern crate ethcore_util as util; //! extern crate ethcore; //! extern crate ethsync; -//! extern crate ethminer; //! use std::env; //! use std::sync::Arc; //! use util::network::{NetworkService, NetworkConfiguration}; //! use ethcore::client::{Client, ClientConfig}; //! use ethsync::{EthSync, SyncConfig}; -//! use ethminer::Miner; //! use ethcore::ethereum; +//! use ethcore::miner::Miner; //! //! fn main() { //! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap(); //! let dir = env::temp_dir(); -//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, service.io().channel()).unwrap(); +//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, Arc::new(Miner::default()), service.io().channel()).unwrap(); //! let miner = Miner::new(false, ethereum::new_frontier()); -//! EthSync::register(&mut service, SyncConfig::default(), client, miner); +//! EthSync::register(&mut service, SyncConfig::default(), client); //! } //! ``` diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 9ca0065ee..a9163b52e 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -15,8 +15,7 @@ // along with Parity. If not, see . use util::*; -use ethcore::client::{TestBlockChainClient, MiningBlockChainClient, BlockChainClient}; -use ethcore::spec::Spec; +use ethcore::client::{TestBlockChainClient, BlockChainClient}; use io::SyncIo; use chain::ChainSync; use ::SyncConfig; From 985d412c483bf993b76b22b5628a7169f62c4e76 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 13:03:26 +0200 Subject: [PATCH 15/21] fix merges again --- rpc/src/v1/tests/eth.rs | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 8cfc13191..4dc22df56 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,12 +19,8 @@ use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; -<<<<<<< HEAD use ethcore::client::{MiningBlockChainClient, BlockChainClient, Client, ClientConfig}; -use ethcore::spec::Genesis; -======= use ethcore::ids::BlockID; -use ethcore::client::{Client, BlockChainClient, ClientConfig}; use ethcore::spec::{Genesis, Spec}; use ethcore::block::Block; use ethcore::views::BlockView; @@ -73,7 +69,7 @@ fn make_spec(chain: &BlockChain) -> Spec { } struct EthTester { - _client: Arc, + client: Arc, _miner: Arc, accounts: Arc, handler: IoHandler, @@ -101,10 +97,10 @@ impl EthTester { where F: Fn() -> Spec { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), spec_provider(), dir.as_path(), IoChannel::disconnected()).unwrap(); - let sync_provider = sync_provider(); let account_provider = account_provider(); let miner_service = miner_service(spec_provider(), account_provider.clone()); + let client = Client::new(ClientConfig::default(), spec_provider(), dir.as_path(), miner_service.clone(), IoChannel::disconnected()).unwrap(); + let sync_provider = sync_provider(); let external_miner = Arc::new(ExternalMiner::default()); let eth_client = EthClient::new( @@ -347,25 +343,10 @@ fn verify_transaction_counts(name: String, chain: BlockChain) { let (req, res) = by_hash(hash, count, &mut id); assert_eq!(tester.handler.handle_request(&req), Some(res)); -<<<<<<< HEAD - let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), spec, dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); - let sync_provider = sync_provider(); - let miner_service = miner_service(); - let account_provider = account_provider(); - let external_miner = Arc::new(ExternalMiner::default()); - - for b in &chain.blocks_rlp() { - if Block::is_good(&b) { - let _ = client.import_block(b.clone()); - client.flush_queue(); - client.import_verified_blocks(&IoChannel::disconnected()); -======= // uncles can share block numbers, so skip them. if tester.client.block_hash(BlockID::Number(number)) == Some(hash) { let (req, res) = by_number(number, count, &mut id); assert_eq!(tester.handler.handle_request(&req), Some(res)); ->>>>>>> master } } } From 1ef4db82e80bf6f7ed2459b8ce1036922c6370af Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 14:50:06 +0200 Subject: [PATCH 16/21] doctest fixes --- ethcore/src/client/mod.rs | 2 +- ethcore/src/miner/mod.rs | 3 +-- ethcore/src/miner/transaction_queue.rs | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 209a9f6e2..3f64cb620 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -46,7 +46,7 @@ use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use trace::LocalizedTrace; use evm::Factory as EvmFactory; -use miner::{TransactionImportResult, AccountDetails}; +use miner::{TransactionImportResult}; use error::Error as EthError; /// Blockchain database client. Owns and manages a blockchain and a block queue. diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 0159d7fd6..60b680f7a 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -28,8 +28,7 @@ //! extern crate ethcore; //! use std::env; //! use util::network::{NetworkService, NetworkConfiguration}; -//! use client::{Client, ClientConfig}; -//! use ethereum; +//! use ethcore::client::{Client, ClientConfig}; //! use ethcore::miner::{Miner, MinerService}; //! //! fn main() { diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index bf1512bde..8f34d78d1 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -26,13 +26,12 @@ //! ```rust //! extern crate ethcore_util as util; //! extern crate ethcore; -//! extern crate ethminer; //! extern crate rustc_serialize; //! //! use util::crypto::KeyPair; //! use util::hash::Address; //! use util::numbers::{Uint, U256}; -//! use ethminer::{TransactionQueue, AccountDetails, TransactionOrigin}; +//! use ethcore::miner::{TransactionQueue, AccountDetails, TransactionOrigin}; //! use ethcore::transaction::*; //! use rustc_serialize::hex::FromHex; //! From c370bcaded498e1e4c42b9c8d42674881f344ade Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 19:57:34 +0200 Subject: [PATCH 17/21] merge fixes --- parity/rpc_apis.rs | 2 +- rpc/src/v1/impls/eth.rs | 183 ---------------------------- rpc/src/v1/impls/eth_filter.rs | 2 +- rpc/src/v1/impls/eth_signing.rs | 10 +- rpc/src/v1/impls/personal_signer.rs | 10 +- 5 files changed, 12 insertions(+), 195 deletions(-) diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index c73a70fee..d9f0cd4eb 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use die::*; use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; +use ethcore::miner::{Miner, ExternalMiner}; use ethcore::client::Client; use util::RotatingLogger; use util::keys::store::AccountService; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 1af4491f2..83a788599 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -544,186 +544,3 @@ impl Eth for EthClient where rpc_unimplemented!() } } - -/// Eth filter rpc implementation. -pub struct EthFilterClient where - C: MiningBlockChainClient, - M: MinerService { - - client: Weak, - miner: Weak, - polls: Mutex>, -} - -impl EthFilterClient where - C: MiningBlockChainClient, - M: MinerService { - - /// Creates new Eth filter client. - pub fn new(client: &Arc, miner: &Arc) -> Self { - EthFilterClient { - client: Arc::downgrade(client), - miner: Arc::downgrade(miner), - polls: Mutex::new(PollManager::new()), - } - } -} - -impl EthFilter for EthFilterClient where - C: MiningBlockChainClient + 'static, - M: MinerService + 'static { - - fn new_filter(&self, params: Params) -> Result { - from_params::<(Filter,)>(params) - .and_then(|(filter,)| { - let mut polls = self.polls.lock().unwrap(); - let block_number = take_weak!(self.client).chain_info().best_block_number; - let id = polls.create_poll(PollFilter::Logs(block_number, Default::default(), filter)); - to_value(&U256::from(id)) - }) - } - - fn new_block_filter(&self, params: Params) -> Result { - match params { - Params::None => { - let mut polls = self.polls.lock().unwrap(); - let id = polls.create_poll(PollFilter::Block(take_weak!(self.client).chain_info().best_block_number)); - to_value(&U256::from(id)) - }, - _ => Err(Error::invalid_params()) - } - } - - fn new_pending_transaction_filter(&self, params: Params) -> Result { - match params { - Params::None => { - let mut polls = self.polls.lock().unwrap(); - let pending_transactions = take_weak!(self.miner).pending_transactions_hashes(); - let id = polls.create_poll(PollFilter::PendingTransaction(pending_transactions)); - - to_value(&U256::from(id)) - }, - _ => Err(Error::invalid_params()) - } - } - - fn filter_changes(&self, params: Params) -> Result { - let client = take_weak!(self.client); - from_params::<(Index,)>(params) - .and_then(|(index,)| { - let mut polls = self.polls.lock().unwrap(); - match polls.poll_mut(&index.value()) { - None => Ok(Value::Array(vec![] as Vec)), - Some(filter) => match *filter { - PollFilter::Block(ref mut block_number) => { - // + 1, cause we want to return hashes including current block hash. - let current_number = client.chain_info().best_block_number + 1; - let hashes = (*block_number..current_number).into_iter() - .map(BlockID::Number) - .filter_map(|id| client.block_hash(id)) - .collect::>(); - - *block_number = current_number; - - to_value(&hashes) - }, - PollFilter::PendingTransaction(ref mut previous_hashes) => { - // get hashes of pending transactions - let current_hashes = take_weak!(self.miner).pending_transactions_hashes(); - - let new_hashes = - { - let previous_hashes_set = previous_hashes.iter().collect::>(); - - // find all new hashes - current_hashes - .iter() - .filter(|hash| !previous_hashes_set.contains(hash)) - .cloned() - .collect::>() - }; - - // save all hashes of pending transactions - *previous_hashes = current_hashes; - - // return new hashes - to_value(&new_hashes) - }, - PollFilter::Logs(ref mut block_number, ref mut previous_logs, ref filter) => { - // retrive the current block number - let current_number = client.chain_info().best_block_number; - - // check if we need to check pending hashes - let include_pending = filter.to_block == Some(BlockNumber::Pending); - - // build appropriate filter - let mut filter: EthcoreFilter = filter.clone().into(); - filter.from_block = BlockID::Number(*block_number); - filter.to_block = BlockID::Latest; - - // retrieve logs in range from_block..min(BlockID::Latest..to_block) - let mut logs = client.logs(filter.clone()) - .into_iter() - .map(From::from) - .collect::>(); - - // additionally retrieve pending logs - if include_pending { - let pending_logs = pending_logs(take_weak!(self.miner).deref(), &filter); - - // remove logs about which client was already notified about - let new_pending_logs: Vec<_> = pending_logs.iter() - .filter(|p| !previous_logs.contains(p)) - .cloned() - .collect(); - - // save all logs retrieved by client - *previous_logs = pending_logs.into_iter().collect(); - - // append logs array with new pending logs - logs.extend(new_pending_logs); - } - - // save current block number as next from block number - *block_number = current_number; - - to_value(&logs) - } - } - } - }) - } - - fn filter_logs(&self, params: Params) -> Result { - from_params::<(Index,)>(params) - .and_then(|(index,)| { - let mut polls = self.polls.lock().unwrap(); - match polls.poll(&index.value()) { - Some(&PollFilter::Logs(ref _block_number, ref _previous_log, ref filter)) => { - let include_pending = filter.to_block == Some(BlockNumber::Pending); - let filter: EthcoreFilter = filter.clone().into(); - let mut logs = take_weak!(self.client).logs(filter.clone()) - .into_iter() - .map(From::from) - .collect::>(); - - if include_pending { - logs.extend(pending_logs(take_weak!(self.miner).deref(), &filter)); - } - - to_value(&logs) - }, - // just empty array - _ => Ok(Value::Array(vec![] as Vec)), - } - }) - } - - fn uninstall_filter(&self, params: Params) -> Result { - from_params::<(Index,)>(params) - .and_then(|(index,)| { - self.polls.lock().unwrap().remove_poll(&index.value()); - to_value(&true) - }) - } -} diff --git a/rpc/src/v1/impls/eth_filter.rs b/rpc/src/v1/impls/eth_filter.rs index c6aecdca2..4f44f5193 100644 --- a/rpc/src/v1/impls/eth_filter.rs +++ b/rpc/src/v1/impls/eth_filter.rs @@ -21,7 +21,7 @@ use std::sync::{Arc, Weak, Mutex}; use std::collections::HashSet; use jsonrpc_core::*; use util::numbers::*; -use ethminer::MinerService; +use ethcore::miner::MinerService; use ethcore::filter::Filter as EthcoreFilter; use ethcore::client::{BlockChainClient, BlockID}; use v1::traits::EthFilter; diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index 04011902b..f0973484f 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -18,8 +18,8 @@ use std::sync::{Arc, Weak}; use jsonrpc_core::*; -use ethminer::MinerService; -use ethcore::client::BlockChainClient; +use ethcore::miner::MinerService; +use ethcore::client::MiningBlockChainClient; use util::numbers::*; use util::keys::store::AccountProvider; use v1::helpers::{SigningQueue, ConfirmationsQueue}; @@ -62,7 +62,7 @@ impl EthSigning for EthSigningQueueClient { /// Implementation of functions that require signing when no trusted signer is used. pub struct EthSigningUnsafeClient where - C: BlockChainClient, + C: MiningBlockChainClient, A: AccountProvider, M: MinerService { client: Weak, @@ -71,7 +71,7 @@ pub struct EthSigningUnsafeClient where } impl EthSigningUnsafeClient where - C: BlockChainClient, + C: MiningBlockChainClient, A: AccountProvider, M: MinerService { @@ -87,7 +87,7 @@ impl EthSigningUnsafeClient where } impl EthSigning for EthSigningUnsafeClient where - C: BlockChainClient + 'static, + C: MiningBlockChainClient + 'static, A: AccountProvider + 'static, M: MinerService + 'static { diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/personal_signer.rs index cf4e927ac..2d52e07f9 100644 --- a/rpc/src/v1/impls/personal_signer.rs +++ b/rpc/src/v1/impls/personal_signer.rs @@ -24,12 +24,12 @@ use v1::impls::sign_and_dispatch; use v1::helpers::{SigningQueue, ConfirmationsQueue}; use util::keys::store::AccountProvider; use util::numbers::*; -use ethcore::client::BlockChainClient; -use ethminer::MinerService; +use ethcore::client::MiningBlockChainClient; +use ethcore::miner::MinerService; /// Transactions confirmation (personal) rpc implementation. pub struct SignerClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { queue: Weak, accounts: Weak, client: Weak, @@ -37,7 +37,7 @@ pub struct SignerClient } impl SignerClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { /// Create new instance of signer client. pub fn new(store: &Arc, client: &Arc, miner: &Arc, queue: &Arc) -> Self { @@ -51,7 +51,7 @@ impl SignerClient } impl PersonalSigner for SignerClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { fn transactions_to_confirm(&self, _params: Params) -> Result { let queue = take_weak!(self.queue); From b7ada4dee02ec2fc08415a2a3302c8aea92729e9 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 1 Jun 2016 20:10:51 +0200 Subject: [PATCH 18/21] update readme (#1201) * update readme [ci skip] * minor fixes * mention dapps server. [ci skip] --- README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 903794e80..193cbeb8f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# ethcore +# [Parity](https://ethcore.io/parity.html) +### Fast, light, and robust Ethereum implementation [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Join the chat at https://gitter.im/trogdoro/xiki][gitter-image]][gitter-url] [![GPLv3][license-image]][license-url] @@ -11,30 +12,64 @@ [license-image]: https://img.shields.io/badge/license-GPL%20v3-green.svg [license-url]: http://www.gnu.org/licenses/gpl-3.0.en.html -[Documentation](http://ethcore.github.io/parity/ethcore/index.html) +[Internal Documentation](http://ethcore.github.io/parity/ethcore/index.html) -### Building from source +---- -First (if you don't already have it) get multirust: +## About Parity + +Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and +cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs. + +By default, Parity will run a JSONRPC server on `127.0.0.1:8545`. This is fully configurable and supports a number +of RPC APIs. + +Parity also runs a server for running decentralized apps, or "Dapps", on `http://127.0.0.1:8080`. +This includes a few useful Dapps, including Ethereum Wallet, Maker OTC, and a node status page. +In a near-future release, it will be easy to install Dapps and use them through this web interface. + +If you run into an issue while using parity, feel free to file one in this repository +or hop on our [gitter chat room]([gitter-url]) to ask a question. We are glad to help! + +Parity's current release is 1.1. You can download it at https://ethcore.io/parity.html or follow the instructions +below to build from source. + +---- + +## Building from source + +Parity is fully compatible with Stable Rust. + +We recommend installing Rust through [multirust](https://github.com/brson/multirust). If you don't already have multirust, you can install it like this: - Linux: ```bash -curl -sf https://raw.githubusercontent.com/brson/multirust/master/quick-install.sh | sh +$ curl -sf https://raw.githubusercontent.com/brson/multirust/master/quick-install.sh | sh ``` - OSX with Homebrew: ```bash -brew update && brew install multirust -multirust default stable +$ brew update && brew install multirust +$ multirust default stable ``` Then, download and build Parity: ```bash # download Parity code -git clone https://github.com/ethcore/parity -cd parity +$ git clone https://github.com/ethcore/parity +$ cd parity # build in release mode -cargo build --release +$ cargo build --release ``` + +This will produce an executable in the `target/release` subdirectory. +Either run `cd target/release`, or copy `target/release/parity` to another location. + +To get started, just run +```bash +$ parity +``` + +and parity will begin syncing the Ethereum blockchain. \ No newline at end of file From 626acda6a3275df74578826f1538d53362926720 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 20:11:05 +0200 Subject: [PATCH 19/21] fix warnings --- parity/dapps.rs | 4 ---- parity/rpc.rs | 4 ---- parity/signer.rs | 4 ---- 3 files changed, 12 deletions(-) diff --git a/parity/dapps.rs b/parity/dapps.rs index 6a0a8cea7..91742d9e3 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -17,10 +17,6 @@ use std::sync::Arc; use std::str::FromStr; use std::net::SocketAddr; -use ethcore::client::Client; -use ethsync::EthSync; -use ethcore::miner::{Miner, ExternalMiner}; -use util::RotatingLogger; use util::panics::PanicHandler; use die::*; use rpc_apis; diff --git a/parity/rpc.rs b/parity/rpc.rs index 65e6b72e1..66f504408 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -18,10 +18,6 @@ use std::str::FromStr; use std::sync::Arc; use std::net::SocketAddr; -use ethcore::client::Client; -use ethsync::EthSync; -use ethcore::miner::{Miner, ExternalMiner}; -use util::RotatingLogger; use util::panics::PanicHandler; use die::*; use jsonipc; diff --git a/parity/signer.rs b/parity/signer.rs index c250771eb..d549b89cb 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -15,10 +15,6 @@ // along with Parity. If not, see . use std::sync::Arc; -use ethcore::client::Client; -use ethsync::EthSync; -use ethcore::miner::{Miner, ExternalMiner}; -use util::keys::store::AccountService; use util::panics::{PanicHandler, ForwardPanic}; use die::*; use rpc_apis; From 8596a347ead1c053e50ebc6f412bacc9e50182ec Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Thu, 2 Jun 2016 11:49:56 +0200 Subject: [PATCH 20/21] Networking refactoring (#1172) * Networking refactoring * Make sure the same socket is reused * Safer atomic ordering * Replaced eq with == --- Cargo.lock | 7 +- util/Cargo.toml | 2 +- util/src/network/connection.rs | 59 ++------ util/src/network/handshake.rs | 54 ++------ util/src/network/host.rs | 245 ++++++++++----------------------- util/src/network/session.rs | 151 ++++++++++++++------ 6 files changed, 209 insertions(+), 309 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce5c1f481..723bca872 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -390,7 +390,7 @@ dependencies = [ "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.1.0", - "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1176,6 +1176,11 @@ name = "slab" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "slab" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "solicit" version = "0.4.4" diff --git a/util/Cargo.toml b/util/Cargo.toml index 7d03fd320..a88ffe037 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -25,7 +25,7 @@ elastic-array = "0.4" heapsize = "0.3" itertools = "0.4" crossbeam = "0.2" -slab = "0.1" +slab = "0.2" sha3 = { path = "sha3" } serde = "0.7.0" clippy = { version = "0.0.69", optional = true} diff --git a/util/src/network/connection.rs b/util/src/network/connection.rs index 589fc0106..3f20b8f7b 100644 --- a/util/src/network/connection.rs +++ b/util/src/network/connection.rs @@ -170,16 +170,16 @@ impl Connection { self.token } - /// Replace socket token - pub fn set_token(&mut self, token: StreamToken) { - self.token = token; - } - /// Get remote peer address pub fn remote_addr(&self) -> io::Result { self.socket.peer_addr() } + /// Get remote peer address string + pub fn remote_addr_str(&self) -> String { + self.socket.peer_addr().map(|a| a.to_string()).unwrap_or_else(|_| "Unknown".to_owned()) + } + /// Clone this connection. Clears the receiving buffer of the returned connection. pub fn try_clone(&self) -> io::Result { Ok(Connection { @@ -196,7 +196,7 @@ impl Connection { /// Register this connection with the IO event loop. pub fn register_socket(&self, reg: Token, event_loop: &mut EventLoop) -> io::Result<()> { trace!(target: "network", "connection register; token={:?}", reg); - if let Err(e) = event_loop.register(&self.socket, reg, self.interest, PollOpt::edge() | PollOpt::oneshot()) { + if let Err(e) = event_loop.register(&self.socket, reg, self.interest, PollOpt::edge() /* | PollOpt::oneshot() */) { // TODO: oneshot is broken on windows trace!(target: "network", "Failed to register {:?}, {:?}", reg, e); } Ok(()) @@ -205,7 +205,7 @@ impl Connection { /// Update connection registration. Should be called at the end of the IO handler. pub fn update_socket(&self, reg: Token, event_loop: &mut EventLoop) -> io::Result<()> { trace!(target: "network", "connection reregister; token={:?}", reg); - event_loop.reregister( &self.socket, reg, self.interest, PollOpt::edge() | PollOpt::oneshot()).or_else(|e| { + event_loop.reregister( &self.socket, reg, self.interest, PollOpt::edge() /* | PollOpt::oneshot() */ ).or_else(|e| { // TODO: oneshot is broken on windows trace!(target: "network", "Failed to reregister {:?}, {:?}", reg, e); Ok(()) }) @@ -246,7 +246,7 @@ enum EncryptedConnectionState { /// https://github.com/ethereum/devp2p/blob/master/rlpx.md#framing pub struct EncryptedConnection { /// Underlying tcp connection - connection: Connection, + pub connection: Connection, /// Egress data encryptor encoder: CtrMode, /// Ingress data decryptor @@ -266,27 +266,6 @@ pub struct EncryptedConnection { } impl EncryptedConnection { - - /// Get socket token - pub fn token(&self) -> StreamToken { - self.connection.token - } - - /// Replace socket token - pub fn set_token(&mut self, token: StreamToken) { - self.connection.set_token(token); - } - - /// Get remote peer address - pub fn remote_addr(&self) -> io::Result { - self.connection.remote_addr() - } - - /// Check if this connection has data to be sent. - pub fn is_sending(&self) -> bool { - self.connection.is_sending() - } - /// Create an encrypted connection out of the handshake. Consumes a handshake object. pub fn new(handshake: &mut Handshake) -> Result { let shared = try!(crypto::ecdh::agree(handshake.ecdhe.secret(), &handshake.remote_ephemeral)); @@ -323,8 +302,10 @@ impl EncryptedConnection { ingress_mac.update(&mac_material); ingress_mac.update(if handshake.originated { &handshake.ack_cipher } else { &handshake.auth_cipher }); + let old_connection = try!(handshake.connection.try_clone()); + let connection = ::std::mem::replace(&mut handshake.connection, old_connection); let mut enc = EncryptedConnection { - connection: try!(handshake.connection.try_clone()), + connection: connection, encoder: encoder, decoder: decoder, mac_encoder: mac_encoder, @@ -463,24 +444,6 @@ impl EncryptedConnection { try!(self.connection.writable()); Ok(()) } - - /// Register socket with the event lpop. This should be called at the end of the event loop. - pub fn register_socket(&self, reg: Token, event_loop: &mut EventLoop) -> Result<(), UtilError> { - try!(self.connection.register_socket(reg, event_loop)); - Ok(()) - } - - /// Update connection registration. This should be called at the end of the event loop. - pub fn update_socket(&self, reg: Token, event_loop: &mut EventLoop) -> Result<(), UtilError> { - try!(self.connection.update_socket(reg, event_loop)); - Ok(()) - } - - /// Delete connection registration. This should be called at the end of the event loop. - pub fn deregister_socket(&self, event_loop: &mut EventLoop) -> Result<(), UtilError> { - try!(self.connection.deregister_socket(event_loop)); - Ok(()) - } } #[test] diff --git a/util/src/network/handshake.rs b/util/src/network/handshake.rs index 123531d8d..e02da3d4c 100644 --- a/util/src/network/handshake.rs +++ b/util/src/network/handshake.rs @@ -16,7 +16,6 @@ use std::sync::Arc; use rand::random; -use mio::*; use mio::tcp::*; use hash::*; use rlp::*; @@ -102,21 +101,6 @@ impl Handshake { }) } - /// Get id of the remote node if known - pub fn id(&self) -> &NodeId { - &self.id - } - - /// Get stream token id - pub fn token(&self) -> StreamToken { - self.connection.token() - } - - /// Mark this handshake as inactive to be deleted lated. - pub fn set_expired(&mut self) { - self.expired = true; - } - /// Check if this handshake is expired. pub fn expired(&self) -> bool { self.expired @@ -177,7 +161,7 @@ impl Handshake { } /// Writabe IO handler. - pub fn writable(&mut self, io: &IoContext, _host: &HostInfo) -> Result<(), UtilError> where Message: Send + Clone { + pub fn writable(&mut self, io: &IoContext) -> Result<(), UtilError> where Message: Send + Clone { if !self.expired() { io.clear_timer(self.connection.token).unwrap(); try!(self.connection.writable()); @@ -188,28 +172,6 @@ impl Handshake { Ok(()) } - /// Register the socket with the event loop - pub fn register_socket>(&self, reg: Token, event_loop: &mut EventLoop) -> Result<(), UtilError> { - if !self.expired() { - try!(self.connection.register_socket(reg, event_loop)); - } - Ok(()) - } - - /// Update socket registration with the event loop. - pub fn update_socket>(&self, reg: Token, event_loop: &mut EventLoop) -> Result<(), UtilError> { - if !self.expired() { - try!(self.connection.update_socket(reg, event_loop)); - } - Ok(()) - } - - /// Delete registration - pub fn deregister_socket(&self, event_loop: &mut EventLoop) -> Result<(), UtilError> { - try!(self.connection.deregister_socket(event_loop)); - Ok(()) - } - fn set_auth(&mut self, host_secret: &Secret, sig: &[u8], remote_public: &[u8], remote_nonce: &[u8], remote_version: u64) -> Result<(), UtilError> { self.id.clone_from_slice(remote_public); self.remote_nonce.clone_from_slice(remote_nonce); @@ -222,7 +184,7 @@ impl Handshake { /// Parse, validate and confirm auth message fn read_auth(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { - trace!(target:"network", "Received handshake auth from {:?}", self.connection.socket.peer_addr()); + trace!(target:"network", "Received handshake auth from {:?}", self.connection.remote_addr_str()); if data.len() != V4_AUTH_PACKET_SIZE { debug!(target:"net", "Wrong auth packet size"); return Err(From::from(NetworkError::BadProtocol)); @@ -253,7 +215,7 @@ impl Handshake { } fn read_auth_eip8(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { - trace!(target:"network", "Received EIP8 handshake auth from {:?}", self.connection.socket.peer_addr()); + trace!(target:"network", "Received EIP8 handshake auth from {:?}", self.connection.remote_addr_str()); self.auth_cipher.extend_from_slice(data); let auth = try!(ecies::decrypt(secret, &self.auth_cipher[0..2], &self.auth_cipher[2..])); let rlp = UntrustedRlp::new(&auth); @@ -268,7 +230,7 @@ impl Handshake { /// Parse and validate ack message fn read_ack(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { - trace!(target:"network", "Received handshake auth to {:?}", self.connection.socket.peer_addr()); + trace!(target:"network", "Received handshake auth to {:?}", self.connection.remote_addr_str()); if data.len() != V4_ACK_PACKET_SIZE { debug!(target:"net", "Wrong ack packet size"); return Err(From::from(NetworkError::BadProtocol)); @@ -296,7 +258,7 @@ impl Handshake { } fn read_ack_eip8(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { - trace!(target:"network", "Received EIP8 handshake auth from {:?}", self.connection.socket.peer_addr()); + trace!(target:"network", "Received EIP8 handshake auth from {:?}", self.connection.remote_addr_str()); self.ack_cipher.extend_from_slice(data); let ack = try!(ecies::decrypt(secret, &self.ack_cipher[0..2], &self.ack_cipher[2..])); let rlp = UntrustedRlp::new(&ack); @@ -309,7 +271,7 @@ impl Handshake { /// Sends auth message fn write_auth(&mut self, secret: &Secret, public: &Public) -> Result<(), UtilError> { - trace!(target:"network", "Sending handshake auth to {:?}", self.connection.socket.peer_addr()); + trace!(target:"network", "Sending handshake auth to {:?}", self.connection.remote_addr_str()); let mut data = [0u8; /*Signature::SIZE*/ 65 + /*H256::SIZE*/ 32 + /*Public::SIZE*/ 64 + /*H256::SIZE*/ 32 + 1]; //TODO: use associated constants let len = data.len(); { @@ -336,7 +298,7 @@ impl Handshake { /// Sends ack message fn write_ack(&mut self) -> Result<(), UtilError> { - trace!(target:"network", "Sending handshake ack to {:?}", self.connection.socket.peer_addr()); + trace!(target:"network", "Sending handshake ack to {:?}", self.connection.remote_addr_str()); let mut data = [0u8; 1 + /*Public::SIZE*/ 64 + /*H256::SIZE*/ 32]; //TODO: use associated constants let len = data.len(); { @@ -355,7 +317,7 @@ impl Handshake { /// Sends EIP8 ack message fn write_ack_eip8(&mut self) -> Result<(), UtilError> { - trace!(target:"network", "Sending EIP8 handshake ack to {:?}", self.connection.socket.peer_addr()); + trace!(target:"network", "Sending EIP8 handshake ack to {:?}", self.connection.remote_addr_str()); let mut rlp = RlpStream::new_list(3); rlp.append(self.ecdhe.public()); rlp.append(&self.nonce); diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 13b64eb3c..92a912a40 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -18,6 +18,7 @@ use std::net::{SocketAddr}; use std::collections::{HashMap}; use std::str::{FromStr}; use std::sync::*; +use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use std::ops::*; use std::cmp::min; use std::path::{Path, PathBuf}; @@ -31,7 +32,6 @@ use misc::version; use crypto::*; use sha3::Hashable; use rlp::*; -use network::handshake::Handshake; use network::session::{Session, SessionData}; use error::*; use io::*; @@ -44,8 +44,7 @@ use network::ip_utils::{map_external_address, select_public_address}; type Slab = ::slab::Slab; -const _DEFAULT_PORT: u16 = 30304; -const MAX_SESSIONS: usize = 1024; +const MAX_SESSIONS: usize = 1024 + MAX_HANDSHAKES; const MAX_HANDSHAKES: usize = 80; const MAX_HANDSHAKES_PER_ROUND: usize = 32; const MAINTENANCE_TIMEOUT: u64 = 1000; @@ -115,18 +114,17 @@ impl NetworkConfiguration { } // Tokens -const TCP_ACCEPT: usize = LAST_HANDSHAKE + 1; -const IDLE: usize = LAST_HANDSHAKE + 2; -const DISCOVERY: usize = LAST_HANDSHAKE + 3; -const DISCOVERY_REFRESH: usize = LAST_HANDSHAKE + 4; -const DISCOVERY_ROUND: usize = LAST_HANDSHAKE + 5; -const INIT_PUBLIC: usize = LAST_HANDSHAKE + 6; -const NODE_TABLE: usize = LAST_HANDSHAKE + 7; +const TCP_ACCEPT: usize = SYS_TIMER + 1; +const IDLE: usize = SYS_TIMER + 2; +const DISCOVERY: usize = SYS_TIMER + 3; +const DISCOVERY_REFRESH: usize = SYS_TIMER + 4; +const DISCOVERY_ROUND: usize = SYS_TIMER + 5; +const INIT_PUBLIC: usize = SYS_TIMER + 6; +const NODE_TABLE: usize = SYS_TIMER + 7; const FIRST_SESSION: usize = 0; const LAST_SESSION: usize = FIRST_SESSION + MAX_SESSIONS - 1; -const FIRST_HANDSHAKE: usize = LAST_SESSION + 1; -const LAST_HANDSHAKE: usize = FIRST_HANDSHAKE + MAX_HANDSHAKES - 1; -const USER_TIMER: usize = LAST_HANDSHAKE + 256; +const USER_TIMER: usize = LAST_SESSION + 256; +const SYS_TIMER: usize = LAST_SESSION + 1; /// Protocol handler level packet id pub type PacketId = u8; @@ -306,7 +304,6 @@ impl HostInfo { } type SharedSession = Arc>; -type SharedHandshake = Arc>; #[derive(Copy, Clone)] struct ProtocolTimer { @@ -318,7 +315,6 @@ struct ProtocolTimer { pub struct Host where Message: Send + Sync + Clone { pub info: RwLock, tcp_listener: Mutex, - handshakes: Arc>>, sessions: Arc>>, discovery: Mutex>, nodes: RwLock, @@ -327,6 +323,7 @@ pub struct Host where Message: Send + Sync + Clone { timer_counter: RwLock, stats: Arc, pinned_nodes: Vec, + num_sessions: AtomicUsize, } impl Host where Message: Send + Sync + Clone { @@ -370,7 +367,6 @@ impl Host where Message: Send + Sync + Clone { }), discovery: Mutex::new(None), tcp_listener: Mutex::new(tcp_listener), - handshakes: Arc::new(RwLock::new(Slab::new_starting_at(FIRST_HANDSHAKE, MAX_HANDSHAKES))), sessions: Arc::new(RwLock::new(Slab::new_starting_at(FIRST_SESSION, MAX_SESSIONS))), nodes: RwLock::new(NodeTable::new(path)), handlers: RwLock::new(HashMap::new()), @@ -378,6 +374,7 @@ impl Host where Message: Send + Sync + Clone { timer_counter: RwLock::new(USER_TIMER), stats: Arc::new(NetworkStats::default()), pinned_nodes: Vec::new(), + num_sessions: AtomicUsize::new(0), }; let boot_nodes = host.info.read().unwrap().config.boot_nodes.clone(); @@ -477,19 +474,19 @@ impl Host where Message: Send + Sync + Clone { } fn have_session(&self, id: &NodeId) -> bool { - self.sessions.read().unwrap().iter().any(|e| e.lock().unwrap().info.id.eq(&id)) + self.sessions.read().unwrap().iter().any(|e| e.lock().unwrap().info.id == Some(id.clone())) } fn session_count(&self) -> usize { - self.sessions.read().unwrap().count() + self.num_sessions.load(AtomicOrdering::Relaxed) } fn connecting_to(&self, id: &NodeId) -> bool { - self.handshakes.read().unwrap().iter().any(|e| e.lock().unwrap().id.eq(&id)) + self.sessions.read().unwrap().iter().any(|e| e.lock().unwrap().id() == Some(id)) } fn handshake_count(&self) -> usize { - self.handshakes.read().unwrap().count() + self.sessions.read().unwrap().count() - self.session_count() } fn keep_alive(&self, io: &IoContext>) { @@ -565,21 +562,31 @@ impl Host where Message: Send + Sync + Clone { } } }; - self.create_connection(socket, Some(id), io); + if let Err(e) = self.create_connection(socket, Some(id), io) { + debug!(target: "network", "Can't create connection: {:?}", e); + } } #[cfg_attr(feature="dev", allow(block_in_if_condition_stmt))] - fn create_connection(&self, socket: TcpStream, id: Option<&NodeId>, io: &IoContext>) { + fn create_connection(&self, socket: TcpStream, id: Option<&NodeId>, io: &IoContext>) -> Result<(), UtilError> { let nonce = self.info.write().unwrap().next_nonce(); - let mut handshakes = self.handshakes.write().unwrap(); - if handshakes.insert_with(|token| { - let mut handshake = Handshake::new(token, id, socket, &nonce, self.stats.clone()).expect("Can't create handshake"); - handshake.start(io, &self.info.read().unwrap(), id.is_some()).and_then(|_| io.register_stream(token)).unwrap_or_else (|e| { - debug!(target: "network", "Handshake create error: {:?}", e); - }); - Arc::new(Mutex::new(handshake)) - }).is_none() { - debug!(target: "network", "Max handshakes reached"); + let mut sessions = self.sessions.write().unwrap(); + let token = sessions.insert_with_opt(|token| { + match Session::new(io, socket, token, id, &nonce, self.stats.clone(), &self.info.read().unwrap()) { + Ok(s) => Some(Arc::new(Mutex::new(s))), + Err(e) => { + debug!(target: "network", "Session create error: {:?}", e); + None + } + } + }); + + match token { + Some(t) => io.register_stream(t), + None => { + debug!(target: "network", "Max sessions reached"); + Ok(()) + } } } @@ -594,19 +601,11 @@ impl Host where Message: Send + Sync + Clone { break }, }; - self.create_connection(socket, None, io); - } - io.update_registration(TCP_ACCEPT).expect("Error registering TCP listener"); - } - - fn handshake_writable(&self, token: StreamToken, io: &IoContext>) { - let handshake = { self.handshakes.read().unwrap().get(token).cloned() }; - if let Some(handshake) = handshake { - let mut h = handshake.lock().unwrap(); - if let Err(e) = h.writable(io, &self.info.read().unwrap()) { - trace!(target: "network", "Handshake write error: {}: {:?}", token, e); + if let Err(e) = self.create_connection(socket, None, io) { + debug!(target: "network", "Can't accept connection: {:?}", e); } } + io.update_registration(TCP_ACCEPT).expect("Error registering TCP listener"); } fn session_writable(&self, token: StreamToken, io: &IoContext>) { @@ -629,30 +628,6 @@ impl Host where Message: Send + Sync + Clone { self.kill_connection(token, io, true); } - fn handshake_readable(&self, token: StreamToken, io: &IoContext>) { - let mut create_session = false; - let mut kill = false; - let handshake = { self.handshakes.read().unwrap().get(token).cloned() }; - if let Some(handshake) = handshake { - let mut h = handshake.lock().unwrap(); - if let Err(e) = h.readable(io, &self.info.read().unwrap()) { - debug!(target: "network", "Handshake read error: {}: {:?}", token, e); - kill = true; - } - if h.done() { - create_session = true; - } - } - if kill { - self.kill_connection(token, io, true); - return; - } else if create_session { - self.start_session(token, io); - return; - } - io.update_registration(token).unwrap_or_else(|e| debug!(target: "network", "Token registration error: {:?}", e)); - } - fn session_readable(&self, token: StreamToken, io: &IoContext>) { let mut ready_data: Vec = Vec::new(); let mut packet_data: Option<(ProtocolId, PacketId, Vec)> = None; @@ -662,17 +637,37 @@ impl Host where Message: Send + Sync + Clone { let mut s = session.lock().unwrap(); match s.readable(io, &self.info.read().unwrap()) { Err(e) => { - trace!(target: "network", "Session read error: {}:{} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); + trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); match e { UtilError::Network(NetworkError::Disconnect(DisconnectReason::UselessPeer)) | UtilError::Network(NetworkError::Disconnect(DisconnectReason::IncompatibleProtocol)) => { - self.nodes.write().unwrap().mark_as_useless(s.id()); + if let Some(id) = s.id() { + self.nodes.write().unwrap().mark_as_useless(id); + } } _ => (), } kill = true; }, Ok(SessionData::Ready) => { + if !s.info.originated { + let session_count = self.session_count(); + let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; + if session_count >= ideal_peers as usize { + s.disconnect(DisconnectReason::TooManyPeers); + return; + } + // Add it no node table + if let Ok(address) = s.remote_addr() { + let entry = NodeEntry { id: s.id().unwrap().clone(), endpoint: NodeEndpoint { address: address, udp_port: address.port() } }; + self.nodes.write().unwrap().add_node(Node::new(entry.id.clone(), entry.endpoint.clone())); + let mut discovery = self.discovery.lock().unwrap(); + if let Some(ref mut discovery) = *discovery.deref_mut() { + discovery.add_node(entry); + } + } + } + self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); for (p, _) in self.handlers.read().unwrap().iter() { if s.have_capability(p) { ready_data.push(p); @@ -697,6 +692,7 @@ impl Host where Message: Send + Sync + Clone { } for p in ready_data { let h = self.handlers.read().unwrap().get(p).unwrap().clone(); + self.stats.inc_sessions(); h.connected(&NetworkContext::new(io, p, session.clone(), self.sessions.clone()), &token); } if let Some((p, packet_id, data)) = packet_data { @@ -706,59 +702,6 @@ impl Host where Message: Send + Sync + Clone { io.update_registration(token).unwrap_or_else(|e| debug!(target: "network", "Token registration error: {:?}", e)); } - fn start_session(&self, token: StreamToken, io: &IoContext>) { - let mut handshakes = self.handshakes.write().unwrap(); - if handshakes.get(token).is_none() { - return; - } - - // turn a handshake into a session - let mut sessions = self.sessions.write().unwrap(); - let mut h = handshakes.get_mut(token).unwrap().lock().unwrap(); - if h.expired { - return; - } - io.deregister_stream(token).expect("Error deleting handshake registration"); - h.set_expired(); - let originated = h.originated; - let mut session = match Session::new(&mut h, &self.info.read().unwrap()) { - Ok(s) => s, - Err(e) => { - debug!(target: "network", "Session creation error: {:?}", e); - return; - } - }; - if !originated { - let session_count = sessions.count(); - let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; - if session_count >= ideal_peers as usize { - session.disconnect(DisconnectReason::TooManyPeers); - return; - } - } - let result = sessions.insert_with(move |session_token| { - session.set_token(session_token); - io.register_stream(session_token).expect("Error creating session registration"); - self.stats.inc_sessions(); - trace!(target: "network", "Creating session {} -> {}:{} ({:?})", token, session_token, session.id(), session.remote_addr()); - if !originated { - // Add it no node table - if let Ok(address) = session.remote_addr() { - let entry = NodeEntry { id: session.id().clone(), endpoint: NodeEndpoint { address: address, udp_port: address.port() } }; - self.nodes.write().unwrap().add_node(Node::new(entry.id.clone(), entry.endpoint.clone())); - let mut discovery = self.discovery.lock().unwrap(); - if let Some(ref mut discovery) = *discovery.deref_mut() { - discovery.add_node(entry); - } - } - } - Arc::new(Mutex::new(session)) - }); - if result.is_none() { - warn!("Max sessions reached"); - } - } - fn connection_timeout(&self, token: StreamToken, io: &IoContext>) { trace!(target: "network", "Connection timeout: {}", token); self.kill_connection(token, io, true) @@ -770,17 +713,6 @@ impl Host where Message: Send + Sync + Clone { let mut deregister = false; let mut expired_session = None; match token { - FIRST_HANDSHAKE ... LAST_HANDSHAKE => { - let handshakes = self.handshakes.write().unwrap(); - if let Some(handshake) = handshakes.get(token).cloned() { - let mut handshake = handshake.lock().unwrap(); - if !handshake.expired() { - handshake.set_expired(); - failure_id = Some(handshake.id().clone()); - deregister = true; - } - } - }, FIRST_SESSION ... LAST_SESSION => { let sessions = self.sessions.write().unwrap(); if let Some(session) = sessions.get(token).cloned() { @@ -790,12 +722,13 @@ impl Host where Message: Send + Sync + Clone { if s.is_ready() { for (p, _) in self.handlers.read().unwrap().iter() { if s.have_capability(p) { + self.num_sessions.fetch_sub(1, AtomicOrdering::SeqCst); to_disconnect.push(p); } } } s.set_expired(); - failure_id = Some(s.id().clone()); + failure_id = s.id().cloned(); } deregister = remote || s.done(); } @@ -821,20 +754,11 @@ impl Host where Message: Send + Sync + Clone { fn update_nodes(&self, io: &IoContext>, node_changes: TableUpdates) { let mut to_remove: Vec = Vec::new(); { - { - let handshakes = self.handshakes.write().unwrap(); - for c in handshakes.iter() { - let h = c.lock().unwrap(); - if node_changes.removed.contains(&h.id()) { - to_remove.push(h.token()); - } - } - } - { - let sessions = self.sessions.write().unwrap(); - for c in sessions.iter() { - let s = c.lock().unwrap(); - if node_changes.removed.contains(&s.id()) { + let sessions = self.sessions.write().unwrap(); + for c in sessions.iter() { + let s = c.lock().unwrap(); + if let Some(id) = s.id() { + if node_changes.removed.contains(id) { to_remove.push(s.token()); } } @@ -860,7 +784,6 @@ impl IoHandler> for Host where Messa trace!(target: "network", "Hup: {}", stream); match stream { FIRST_SESSION ... LAST_SESSION => self.connection_closed(stream, io), - FIRST_HANDSHAKE ... LAST_HANDSHAKE => self.connection_closed(stream, io), _ => warn!(target: "network", "Unexpected hup"), }; } @@ -868,7 +791,6 @@ impl IoHandler> for Host where Messa fn stream_readable(&self, io: &IoContext>, stream: StreamToken) { match stream { FIRST_SESSION ... LAST_SESSION => self.session_readable(stream, io), - FIRST_HANDSHAKE ... LAST_HANDSHAKE => self.handshake_readable(stream, io), DISCOVERY => { let node_changes = { self.discovery.lock().unwrap().as_mut().unwrap().readable() }; if let Some(node_changes) = node_changes { @@ -884,7 +806,6 @@ impl IoHandler> for Host where Messa fn stream_writable(&self, io: &IoContext>, stream: StreamToken) { match stream { FIRST_SESSION ... LAST_SESSION => self.session_writable(stream, io), - FIRST_HANDSHAKE ... LAST_HANDSHAKE => self.handshake_writable(stream, io), DISCOVERY => { self.discovery.lock().unwrap().as_mut().unwrap().writable(); io.update_registration(DISCOVERY).expect("Error updating discovery registration"); @@ -899,7 +820,6 @@ impl IoHandler> for Host where Messa INIT_PUBLIC => self.init_public_interface(io).unwrap_or_else(|e| warn!("Error initializing public interface: {:?}", e)), FIRST_SESSION ... LAST_SESSION => self.connection_timeout(token, io), - FIRST_HANDSHAKE ... LAST_HANDSHAKE => self.connection_timeout(token, io), DISCOVERY_REFRESH => { self.discovery.lock().unwrap().as_mut().unwrap().refresh(); io.update_registration(DISCOVERY).expect("Error updating discovery registration"); @@ -966,7 +886,9 @@ impl IoHandler> for Host where Messa let session = { self.sessions.read().unwrap().get(*peer).cloned() }; if let Some(session) = session { session.lock().unwrap().disconnect(DisconnectReason::DisconnectRequested); - self.nodes.write().unwrap().mark_as_useless(session.lock().unwrap().id()); + if let Some(id) = session.lock().unwrap().id() { + self.nodes.write().unwrap().mark_as_useless(id) + } } trace!(target: "network", "Disabling peer {}", peer); self.kill_connection(*peer, io, false); @@ -987,12 +909,6 @@ impl IoHandler> for Host where Messa session.lock().unwrap().register_socket(reg, event_loop).expect("Error registering socket"); } } - FIRST_HANDSHAKE ... LAST_HANDSHAKE => { - let connection = { self.handshakes.read().unwrap().get(stream).cloned() }; - if let Some(connection) = connection { - connection.lock().unwrap().register_socket(reg, event_loop).expect("Error registering socket"); - } - } DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().register_socket(event_loop).expect("Error registering discovery socket"), TCP_ACCEPT => event_loop.register(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error registering stream"), _ => warn!("Unexpected stream registration") @@ -1008,13 +924,6 @@ impl IoHandler> for Host where Messa connections.remove(stream); } } - FIRST_HANDSHAKE ... LAST_HANDSHAKE => { - let mut connections = self.handshakes.write().unwrap(); - if let Some(connection) = connections.get(stream).cloned() { - connection.lock().unwrap().deregister_socket(event_loop).expect("Error deregistering socket"); - connections.remove(stream); - } - } DISCOVERY => (), _ => warn!("Unexpected stream deregistration") } @@ -1028,12 +937,6 @@ impl IoHandler> for Host where Messa connection.lock().unwrap().update_socket(reg, event_loop).expect("Error updating socket"); } } - FIRST_HANDSHAKE ... LAST_HANDSHAKE => { - let connection = { self.handshakes.read().unwrap().get(stream).cloned() }; - if let Some(connection) = connection { - connection.lock().unwrap().update_socket(reg, event_loop).expect("Error updating socket"); - } - } DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().update_registration(event_loop).expect("Error reregistering discovery socket"), TCP_ACCEPT => event_loop.reregister(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error reregistering stream"), _ => warn!("Unexpected stream update") diff --git a/util/src/network/session.rs b/util/src/network/session.rs index 6c0a20a14..7b7f16c18 100644 --- a/util/src/network/session.rs +++ b/util/src/network/session.rs @@ -16,15 +16,19 @@ use std::net::SocketAddr; use std::io; +use std::sync::*; use mio::*; +use mio::tcp::*; use rlp::*; -use network::connection::{EncryptedConnection, Packet}; +use hash::*; +use network::connection::{EncryptedConnection, Packet, Connection}; use network::handshake::Handshake; use error::*; use io::{IoContext, StreamToken}; use network::error::{NetworkError, DisconnectReason}; use network::host::*; use network::node_table::NodeId; +use network::stats::NetworkStats; use time; const PING_TIMEOUT_SEC: u64 = 30; @@ -36,14 +40,18 @@ const PING_INTERVAL_SEC: u64 = 30; pub struct Session { /// Shared session information pub info: SessionInfo, - /// Underlying connection - connection: EncryptedConnection, /// Session ready flag. Set after successfull Hello packet exchange had_hello: bool, /// Session is no longer active flag. expired: bool, ping_time_ns: u64, pong_time_ns: Option, + state: State, +} + +enum State { + Handshake(Handshake), + Session(EncryptedConnection), } /// Structure used to report various session events. @@ -65,7 +73,7 @@ pub enum SessionData { /// Shared session information pub struct SessionInfo { /// Peer public key - pub id: NodeId, + pub id: Option, /// Peer client ID pub client_version: String, /// Peer RLPx protocol version @@ -74,6 +82,8 @@ pub struct SessionInfo { capabilities: Vec, /// Peer ping delay in milliseconds pub ping_ms: Option, + /// True if this session was originated by us. + pub originated: bool, } #[derive(Debug, PartialEq, Eq)] @@ -112,31 +122,52 @@ const PACKET_LAST: u8 = 0x7f; impl Session { /// Create a new session out of comepleted handshake. This clones the handshake connection object /// and leaves the handhsake in limbo to be deregistered from the event loop. - pub fn new(h: &mut Handshake, host: &HostInfo) -> Result { - let id = h.id.clone(); - let connection = try!(EncryptedConnection::new(h)); - let mut session = Session { - connection: connection, + pub fn new(io: &IoContext, socket: TcpStream, token: StreamToken, id: Option<&NodeId>, + nonce: &H256, stats: Arc, host: &HostInfo) -> Result + where Message: Send + Clone { + let originated = id.is_some(); + let mut handshake = Handshake::new(token, id, socket, &nonce, stats).expect("Can't create handshake"); + try!(handshake.start(io, host, originated)); + Ok(Session { + state: State::Handshake(handshake), had_hello: false, info: SessionInfo { - id: id, + id: id.cloned(), client_version: String::new(), protocol_version: 0, capabilities: Vec::new(), ping_ms: None, + originated: originated, }, ping_time_ns: 0, pong_time_ns: None, expired: false, + }) + } + + fn complete_handshake(&mut self, host: &HostInfo) -> Result<(), UtilError> { + let connection = if let State::Handshake(ref mut h) = self.state { + self.info.id = Some(h.id.clone()); + try!(EncryptedConnection::new(h)) + } else { + panic!("Unexpected state"); }; - try!(session.write_hello(host)); - try!(session.send_ping()); - Ok(session) + self.state = State::Session(connection); + try!(self.write_hello(host)); + try!(self.send_ping()); + Ok(()) + } + + fn connection(&self) -> &Connection { + match self.state { + State::Handshake(ref h) => &h.connection, + State::Session(ref s) => &s.connection, + } } /// Get id of the remote peer - pub fn id(&self) -> &NodeId { - &self.info.id + pub fn id(&self) -> Option<&NodeId> { + self.info.id.as_ref() } /// Check if session is ready to send/receive data @@ -151,21 +182,20 @@ impl Session { /// Check if this session is expired. pub fn expired(&self) -> bool { - self.expired + match self.state { + State::Handshake(ref h) => h.expired(), + _ => self.expired, + } } /// Check if this session is over and there is nothing to be sent. pub fn done(&self) -> bool { - self.expired() && !self.connection.is_sending() - } - /// Replace socket token - pub fn set_token(&mut self, token: StreamToken) { - self.connection.set_token(token); + self.expired() && !self.connection().is_sending() } /// Get remote peer address pub fn remote_addr(&self) -> io::Result { - self.connection.remote_addr() + self.connection().remote_addr() } /// Readable IO handler. Returns packet data if available. @@ -173,15 +203,37 @@ impl Session { if self.expired() { return Ok(SessionData::None) } - match try!(self.connection.readable(io)) { - Some(data) => Ok(try!(self.read_packet(data, host))), - None => Ok(SessionData::None) + let mut create_session = false; + let mut packet_data = None; + match self.state { + State::Handshake(ref mut h) => { + try!(h.readable(io, host)); + if h.done() { + create_session = true; + } + } + State::Session(ref mut c) => { + match try!(c.readable(io)) { + data @ Some(_) => packet_data = data, + None => return Ok(SessionData::None) + } + } } + if let Some(data) = packet_data { + return Ok(try!(self.read_packet(data, host))); + } + if create_session { + try!(self.complete_handshake(host)); + } + Ok(SessionData::None) } /// Writable IO handler. Sends pending packets. pub fn writable(&mut self, io: &IoContext, _host: &HostInfo) -> Result<(), UtilError> where Message: Send + Sync + Clone { - self.connection.writable(io) + match self.state { + State::Handshake(ref mut h) => h.writable(io), + State::Session(ref mut s) => s.writable(io), + } } /// Checks if peer supports given capability @@ -194,18 +246,20 @@ impl Session { if self.expired() { return Ok(()); } - try!(self.connection.register_socket(reg, event_loop)); + try!(self.connection().register_socket(reg, event_loop)); Ok(()) } /// Update registration with the event loop. Should be called at the end of the IO handler. pub fn update_socket(&self, reg:Token, event_loop: &mut EventLoop) -> Result<(), UtilError> { - self.connection.update_socket(reg, event_loop) + try!(self.connection().update_socket(reg, event_loop)); + Ok(()) } /// Delete registration pub fn deregister_socket(&self, event_loop: &mut EventLoop) -> Result<(), UtilError> { - self.connection.deregister_socket(event_loop) + try!(self.connection().deregister_socket(event_loop)); + Ok(()) } /// Send a protocol packet to peer. @@ -221,7 +275,7 @@ impl Session { while protocol != self.info.capabilities[i].protocol { i += 1; if i == self.info.capabilities.len() { - debug!(target: "net", "Unknown protocol: {:?}", protocol); + debug!(target: "network", "Unknown protocol: {:?}", protocol); return Ok(()) } } @@ -229,11 +283,14 @@ impl Session { let mut rlp = RlpStream::new(); rlp.append(&(pid as u32)); rlp.append_raw(data, 1); - self.connection.send_packet(&rlp.out()) + self.send(rlp) } /// Keep this session alive. Returns false if ping timeout happened pub fn keep_alive(&mut self, io: &IoContext) -> bool where Message: Send + Sync + Clone { + if let State::Handshake(_) = self.state { + return true; + } let timed_out = if let Some(pong) = self.pong_time_ns { pong - self.ping_time_ns > PING_TIMEOUT_SEC * 1000_000_000 } else { @@ -244,13 +301,13 @@ impl Session { if let Err(e) = self.send_ping() { debug!("Error sending ping message: {:?}", e); } - io.update_registration(self.token()).unwrap_or_else(|e| debug!(target: "net", "Session registration error: {:?}", e)); + io.update_registration(self.token()).unwrap_or_else(|e| debug!(target: "network", "Session registration error: {:?}", e)); } !timed_out } pub fn token(&self) -> StreamToken { - self.connection.token() + self.connection().token() } fn read_packet(&mut self, packet: Packet, host: &HostInfo) -> Result { @@ -288,7 +345,7 @@ impl Session { while packet_id < self.info.capabilities[i].id_offset { i += 1; if i == self.info.capabilities.len() { - debug!(target: "net", "Unknown packet: {:?}", packet_id); + debug!(target: "network", "Unknown packet: {:?}", packet_id); return Ok(SessionData::None) } } @@ -299,7 +356,7 @@ impl Session { Ok(SessionData::Packet { data: packet.data, protocol: protocol, packet_id: pid } ) }, _ => { - debug!(target: "net", "Unknown packet: {:?}", packet_id); + debug!(target: "network", "Unknown packet: {:?}", packet_id); Ok(SessionData::None) } } @@ -314,7 +371,7 @@ impl Session { .append(&host.capabilities) .append(&host.local_endpoint.address.port()) .append(host.id()); - self.connection.send_packet(&rlp.out()) + self.send(rlp) } fn read_hello(&mut self, rlp: &UntrustedRlp, host: &HostInfo) -> Result<(), UtilError> { @@ -384,11 +441,13 @@ impl Session { /// Disconnect this session pub fn disconnect(&mut self, reason: DisconnectReason) -> NetworkError { - let mut rlp = RlpStream::new(); - rlp.append(&(PACKET_DISCONNECT as u32)); - rlp.begin_list(1); - rlp.append(&(reason as u32)); - self.connection.send_packet(&rlp.out()).ok(); + if let State::Session(_) = self.state { + let mut rlp = RlpStream::new(); + rlp.append(&(PACKET_DISCONNECT as u32)); + rlp.begin_list(1); + rlp.append(&(reason as u32)); + self.send(rlp).ok(); + } NetworkError::Disconnect(reason) } @@ -400,7 +459,15 @@ impl Session { } fn send(&mut self, rlp: RlpStream) -> Result<(), UtilError> { - self.connection.send_packet(&rlp.out()) + match self.state { + State::Handshake(_) => { + warn!(target:"network", "Unexpected send request"); + }, + State::Session(ref mut s) => { + try!(s.send_packet(&rlp.out())) + }, + } + Ok(()) } } From 7ad9c73c7523d3183ec4e84ed4b66a9abeac741a Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 2 Jun 2016 11:51:03 +0200 Subject: [PATCH 21/21] devtools helpers extended (#1186) * devtools extensions * some doc effort --- devtools/src/lib.rs | 2 ++ devtools/src/random_path.rs | 12 +++++++++- devtools/src/stop_guard.rs | 45 +++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 devtools/src/stop_guard.rs diff --git a/devtools/src/lib.rs b/devtools/src/lib.rs index 3ab585d93..e37d5c528 100644 --- a/devtools/src/lib.rs +++ b/devtools/src/lib.rs @@ -21,6 +21,8 @@ extern crate rand; pub mod random_path; pub mod test_socket; +pub mod stop_guard; pub use random_path::*; pub use test_socket::*; +pub use stop_guard::*; diff --git a/devtools/src/random_path.rs b/devtools/src/random_path.rs index 990d375e3..09bee7e45 100644 --- a/devtools/src/random_path.rs +++ b/devtools/src/random_path.rs @@ -26,7 +26,11 @@ pub struct RandomTempPath { } pub fn random_filename() -> String { - (0..8).map(|_| ((random::() * 26.0) as u8 + 97) as char).collect() + random_str(8) +} + +pub fn random_str(len: usize) -> String { + (0..len).map(|_| ((random::() * 26.0) as u8 + 97) as char).collect() } impl RandomTempPath { @@ -54,6 +58,12 @@ impl RandomTempPath { pub fn as_str(&self) -> &str { self.path.to_str().unwrap() } + + pub fn new_in(&self, name: &str) -> String { + let mut path = self.path.clone(); + path.push(name); + path.to_str().unwrap().to_owned() + } } impl Drop for RandomTempPath { diff --git a/devtools/src/stop_guard.rs b/devtools/src/stop_guard.rs new file mode 100644 index 000000000..f1db59725 --- /dev/null +++ b/devtools/src/stop_guard.rs @@ -0,0 +1,45 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity 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 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. If not, see . + +//! Stop guard mod + +use std::sync::Arc; +use std::sync::atomic::*; + +/// Stop guard that will set a stop flag on drop +pub struct StopGuard { + flag: Arc, +} + +impl StopGuard { + /// Create a stop guard + pub fn new() -> StopGuard { + StopGuard { + flag: Arc::new(AtomicBool::new(false)) + } + } + + /// Share stop guard between the threads + pub fn share(&self) -> Arc { + self.flag.clone() + } +} + +impl Drop for StopGuard { + fn drop(&mut self) { + self.flag.store(true, Ordering::Relaxed) + } +}