Flipping sealing_enabled flag after no requests for sealing_block for some time

This commit is contained in:
Tomasz Drwięga 2016-03-18 13:59:11 +01:00
parent cee45e1a8e
commit 0dc1ddef9a
2 changed files with 59 additions and 5 deletions

View File

@ -218,11 +218,11 @@ impl BlockChainClient for TestBlockChainClient {
}
fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec<SignedTransaction>) -> Option<ClosedBlock> {
unimplemented!()
None
}
fn try_seal(&self, _block: ClosedBlock, _seal: Vec<Bytes>) -> Result<SealedBlock, ClosedBlock> {
unimplemented!()
fn try_seal(&self, block: ClosedBlock, _seal: Vec<Bytes>) -> Result<SealedBlock, ClosedBlock> {
Err(block)
}
fn block_header(&self, id: BlockId) -> Option<Bytes> {

View File

@ -34,6 +34,7 @@ pub struct Miner {
// for sealing...
sealing_enabled: AtomicBool,
sealing_block_last_request: Mutex<u64>,
sealing_block: Mutex<Option<ClosedBlock>>,
gas_floor_target: RwLock<U256>,
author: RwLock<Address>,
@ -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<Option<ClosedBlock>> {
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");
}
}