From 0dc1ddef9a3620509a7dde77e0d966226522fc5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 18 Mar 2016 13:59:11 +0100 Subject: [PATCH] Flipping sealing_enabled flag after no requests for sealing_block for some time --- ethcore/src/client/test_client.rs | 6 ++-- miner/src/miner.rs | 58 +++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 83511b1cc..f5c54b705 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -218,11 +218,11 @@ impl BlockChainClient for TestBlockChainClient { } fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> Option { - unimplemented!() + None } - fn try_seal(&self, _block: ClosedBlock, _seal: Vec) -> Result { - unimplemented!() + fn try_seal(&self, block: ClosedBlock, _seal: Vec) -> Result { + Err(block) } fn block_header(&self, id: BlockId) -> Option { diff --git a/miner/src/miner.rs b/miner/src/miner.rs index dc1f9bcff..e90473600 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -34,6 +34,7 @@ pub struct Miner { // for sealing... sealing_enabled: AtomicBool, + sealing_block_last_request: Mutex, sealing_block: Mutex>, gas_floor_target: RwLock, author: RwLock
, @@ -46,6 +47,7 @@ impl Default for Miner { Miner { transaction_queue: Mutex::new(TransactionQueue::new()), sealing_enabled: AtomicBool::new(false), + sealing_block_last_request: Mutex::new(0), sealing_block: Mutex::new(None), gas_floor_target: RwLock::new(U256::zero()), author: RwLock::new(Address::default()), @@ -110,6 +112,8 @@ impl Miner { } } +const SEALING_TIMEOUT_IN_BLOCKS : u64 = 5; + impl MinerService for Miner { fn clear_and_reset(&self, chain: &BlockChainClient) { @@ -139,7 +143,17 @@ impl MinerService for Miner { } fn update_sealing(&self, chain: &BlockChainClient) { - if self.sealing_enabled.load(atomic::Ordering::Relaxed) { + let should_disable_sealing = { + let current_no = chain.chain_info().best_block_number; + let last_request = self.sealing_block_last_request.lock().unwrap(); + + 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); } } @@ -147,9 +161,10 @@ impl MinerService for Miner { fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex> { if self.sealing_block.lock().unwrap().is_none() { self.sealing_enabled.store(true, atomic::Ordering::Relaxed); - // TODO: Above should be on a timer that resets after two blocks have arrived without being asked for. + self.prepare_sealing(chain); } + *self.sealing_block_last_request.lock().unwrap() = chain.chain_info().best_block_number; &self.sealing_block } @@ -228,3 +243,42 @@ impl MinerService for Miner { self.update_sealing(chain); } } + +#[cfg(test)] +mod tests { + + use MinerService; + use super::{Miner}; + use ethcore::client::{TestBlockChainClient, EachBlockWith}; + + // TODO [ToDr] To uncomment client is cleaned from mining stuff. + #[ignore] + #[test] + fn should_prepare_block_to_seal() { + // given + let client = TestBlockChainClient::default(); + let miner = Miner::default(); + + // when + let res = miner.sealing_block(&client); + + // then + assert!(res.lock().unwrap().is_some(), "Expected closed block"); + } + + #[test] + fn should_reset_seal_after_couple_of_blocks() { + // given + let client = TestBlockChainClient::default(); + let miner = Miner::default(); + let res = miner.sealing_block(&client); + // TODO [ToDr] Uncomment after fixing TestBlockChainClient + // assert!(res.lock().unwrap().is_some(), "Expected closed block"); + + // when + client.add_blocks(10, EachBlockWith::Uncle); + + // then + assert!(res.lock().unwrap().is_none(), "Expected to remove sealed block"); + } +}