diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index b2230af7b..893cdae03 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -16,6 +16,7 @@ //! Test client. +use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder}; use util::*; use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action}; use blockchain::TreeRoute; @@ -54,6 +55,8 @@ pub struct TestBlockChainClient { pub execution_result: RwLock>, /// Transaction receipts. pub receipts: RwLock>, + /// Block queue size. + pub queue_size: AtomicUsize, } #[derive(Clone)] @@ -90,6 +93,7 @@ impl TestBlockChainClient { code: RwLock::new(HashMap::new()), execution_result: RwLock::new(None), receipts: RwLock::new(HashMap::new()), + queue_size: AtomicUsize::new(0), }; client.add_blocks(1, EachBlockWith::Nothing); // add genesis block client.genesis_hash = client.last_hash.read().unwrap().clone(); @@ -121,6 +125,11 @@ impl TestBlockChainClient { self.storage.write().unwrap().insert((address, position), value); } + /// Set block queue size for testing + pub fn set_queue_size(&self, size: usize) { + self.queue_size.store(size, AtomicOrder::Relaxed); + } + /// Add blocks to test client. pub fn add_blocks(&self, count: usize, with: EachBlockWith) { let len = self.numbers.read().unwrap().len(); @@ -383,7 +392,7 @@ impl BlockChainClient for TestBlockChainClient { fn queue_info(&self) -> BlockQueueInfo { BlockQueueInfo { - verified_queue_size: 0, + verified_queue_size: self.queue_size.load(AtomicOrder::Relaxed), unverified_queue_size: 0, verifying_queue_size: 0, max_queue_size: 0, diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 508fcffb4..e989fa495 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -165,28 +165,32 @@ impl MinerService for Miner { } fn update_sealing(&self, chain: &BlockChainClient) { - let should_disable_sealing = { + if self.sealing_enabled.load(atomic::Ordering::Relaxed) { let current_no = chain.chain_info().best_block_number; - let last_request = self.sealing_block_last_request.lock().unwrap(); - let is_greater = current_no > *last_request; - is_greater && current_no - *last_request > SEALING_TIMEOUT_IN_BLOCKS - }; + let last_request = *self.sealing_block_last_request.lock().unwrap(); + let should_disable_sealing = current_no > last_request && current_no - last_request > SEALING_TIMEOUT_IN_BLOCKS; - if should_disable_sealing { - self.sealing_enabled.store(false, atomic::Ordering::Relaxed); - *self.sealing_block.lock().unwrap() = None; - } else if self.sealing_enabled.load(atomic::Ordering::Relaxed) { - self.prepare_sealing(chain); + if should_disable_sealing { + trace!(target: "miner", "Miner sleeping (current {}, last {})", current_no, last_request); + self.sealing_enabled.store(false, atomic::Ordering::Relaxed); + *self.sealing_block.lock().unwrap() = None; + } else { + self.prepare_sealing(chain); + } } } fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex> { if self.sealing_block.lock().unwrap().is_none() { self.sealing_enabled.store(true, atomic::Ordering::Relaxed); - self.prepare_sealing(chain); } - *self.sealing_block_last_request.lock().unwrap() = chain.chain_info().best_block_number; + let mut sealing_block_last_request = self.sealing_block_last_request.lock().unwrap(); + let best_number = chain.chain_info().best_block_number; + if *sealing_block_last_request != best_number { + trace!(target: "miner", "Miner received request (was {}, now {}) - waking up.", *sealing_block_last_request, best_number); + *sealing_block_last_request = best_number; + } &self.sealing_block } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index a065392d5..99f6eda3e 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -197,6 +197,8 @@ impl EthClient } } +const MAX_QUEUE_SIZE_TO_MINE_ON: usize = 4; // because uncles go back 6. + impl Eth for EthClient where C: BlockChainClient + 'static, S: SyncProvider + 'static, @@ -398,10 +400,12 @@ impl Eth for EthClient match params { Params::None => { let client = take_weak!(self.client); - // check if we're still syncing and return empty strings int that case + // check if we're still syncing and return empty strings in that case { - let sync = take_weak!(self.sync); - if sync.status().state != SyncState::Idle && client.queue_info().is_empty() { + //TODO: check if initial sync is complete here + //let sync = take_weak!(self.sync); + if /*sync.status().state != SyncState::Idle ||*/ client.queue_info().total_queue_size() > MAX_QUEUE_SIZE_TO_MINE_ON { + trace!(target: "miner", "Syncing. Cannot give any work."); return to_value(&(String::new(), String::new(), String::new())); } } diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 4564076eb..209b95ded 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -476,7 +476,8 @@ fn rpc_eth_compile_serpent() { #[test] fn returns_no_work_if_cant_mine() { - let eth_tester = EthTester::default(); + let mut eth_tester = EthTester::default(); + eth_tester.client.set_queue_size(10); let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":["","",""],"id":1}"#;