diff --git a/Cargo.lock b/Cargo.lock index 9f44e710c..541e0f418 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2156,6 +2156,7 @@ dependencies = [ name = "instant-seal" version = "0.1.0" dependencies = [ + "client-traits 0.1.0", "common-types 0.1.0", "engine 0.1.0", "ethcore 1.12.0", diff --git a/ethcore/client-traits/src/lib.rs b/ethcore/client-traits/src/lib.rs index f592ef6cf..3683730b0 100644 --- a/ethcore/client-traits/src/lib.rs +++ b/ethcore/client-traits/src/lib.rs @@ -146,10 +146,18 @@ pub trait TransactionInfo { /// Provides various blockchain information, like block header, chain state etc. pub trait BlockChain: ChainInfo + BlockInfo + TransactionInfo {} +/// Do we want to force update sealing? +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum ForceUpdateSealing { + /// Ideally you want to use `No` at all times as `Yes` skips `reseal_required` checks. + Yes, + /// Don't skip `reseal_required` checks + No +} /// Client facilities used by internally sealing Engines. pub trait EngineClient: Sync + Send + ChainInfo { /// Make a new block and seal it. - fn update_sealing(&self); + fn update_sealing(&self, force: ForceUpdateSealing); /// Submit a seal for a block in the mining queue. fn submit_seal(&self, block_hash: H256, seal: Vec); diff --git a/ethcore/engine/src/engine.rs b/ethcore/engine/src/engine.rs index f5e902343..44f76624a 100644 --- a/ethcore/engine/src/engine.rs +++ b/ethcore/engine/src/engine.rs @@ -188,6 +188,14 @@ pub trait Engine: Sync + Send { /// Returns the engine's current sealing state. fn sealing_state(&self) -> SealingState { SealingState::External } + /// Called in `miner.chain_new_blocks` if the engine wishes to `update_sealing` + /// after a block was recently sealed. + /// + /// returns false by default + fn should_reseal_on_update(&self) -> bool { + false + } + /// Attempt to seal the block internally. /// /// If `Some` is returned, then you get a valid seal. diff --git a/ethcore/engines/authority-round/src/lib.rs b/ethcore/engines/authority-round/src/lib.rs index 54980e4f4..14654bc95 100644 --- a/ethcore/engines/authority-round/src/lib.rs +++ b/ethcore/engines/authority-round/src/lib.rs @@ -40,7 +40,7 @@ use std::sync::{Weak, Arc}; use std::time::{UNIX_EPOCH, Duration}; use std::u64; -use client_traits::EngineClient; +use client_traits::{EngineClient, ForceUpdateSealing}; use engine::{Engine, ConstructedVerifier}; use block_reward::{self, BlockRewardContract, RewardKind}; use ethjson; @@ -1075,7 +1075,7 @@ impl IoHandler<()> for TransitionHandler { self.step.can_propose.store(true, AtomicOrdering::SeqCst); if let Some(ref weak) = *self.client.read() { if let Some(c) = weak.upgrade() { - c.update_sealing(); + c.update_sealing(ForceUpdateSealing::No); } } } @@ -1105,7 +1105,7 @@ impl Engine for AuthorityRound { self.step.can_propose.store(true, AtomicOrdering::SeqCst); if let Some(ref weak) = *self.client.read() { if let Some(c) = weak.upgrade() { - c.update_sealing(); + c.update_sealing(ForceUpdateSealing::No); } } } diff --git a/ethcore/engines/clique/src/lib.rs b/ethcore/engines/clique/src/lib.rs index 50dad03ac..e98cb73c5 100644 --- a/ethcore/engines/clique/src/lib.rs +++ b/ethcore/engines/clique/src/lib.rs @@ -66,7 +66,7 @@ use std::{ time::{self, Instant, Duration, SystemTime, UNIX_EPOCH}, }; -use client_traits::EngineClient; +use client_traits::{EngineClient, ForceUpdateSealing}; use engine::{ Engine, signer::EngineSigner, @@ -780,7 +780,7 @@ impl Engine for Clique { if self.signer.read().is_some() { if let Some(ref weak) = *self.client.read() { if let Some(c) = weak.upgrade() { - c.update_sealing(); + c.update_sealing(ForceUpdateSealing::No); } } } diff --git a/ethcore/engines/instant-seal/Cargo.toml b/ethcore/engines/instant-seal/Cargo.toml index afb56ea52..c3a4eb2b4 100644 --- a/ethcore/engines/instant-seal/Cargo.toml +++ b/ethcore/engines/instant-seal/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" license = "GPL-3.0" [dependencies] +client-traits = { path = "../../client-traits" } common-types = { path = "../../types" } engine = { path = "../../engine" } ethjson = { path = "../../../json" } diff --git a/ethcore/engines/instant-seal/src/lib.rs b/ethcore/engines/instant-seal/src/lib.rs index 9626be86b..368c27819 100644 --- a/ethcore/engines/instant-seal/src/lib.rs +++ b/ethcore/engines/instant-seal/src/lib.rs @@ -74,6 +74,13 @@ impl Engine for InstantSeal { fn sealing_state(&self) -> SealingState { SealingState::Ready } + fn should_reseal_on_update(&self) -> bool { + // We would like for the miner to `update_sealing` if there are local_pending_transactions + // in the pool to prevent transactions sent in parallel from stalling in the transaction + // pool. (see #9660) + true + } + fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal { if !block.transactions.is_empty() { let block_number = block.header.number(); diff --git a/ethcore/engines/validator-set/src/multi.rs b/ethcore/engines/validator-set/src/multi.rs index 76b3e9a1c..9e790cb52 100644 --- a/ethcore/engines/validator-set/src/multi.rs +++ b/ethcore/engines/validator-set/src/multi.rs @@ -161,7 +161,7 @@ mod tests { ids::BlockId, verification::Unverified, }; - use client_traits::{BlockChainClient, BlockInfo, ChainInfo, ImportBlock, EngineClient}; + use client_traits::{BlockChainClient, BlockInfo, ChainInfo, ImportBlock, EngineClient, ForceUpdateSealing}; use engine::EpochChange; use ethcore::{ miner::{self, MinerService}, @@ -191,24 +191,24 @@ mod tests { let signer = Box::new((tap.clone(), v1, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); client.transact_contract(Default::default(), Default::default()).unwrap(); - EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 0); // Right signer for the first block. let signer = Box::new((tap.clone(), v0, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); - EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 1); // This time v0 is wrong. client.transact_contract(Default::default(), Default::default()).unwrap(); - EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 1); let signer = Box::new((tap.clone(), v1, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); - EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 2); // v1 is still good. client.transact_contract(Default::default(), Default::default()).unwrap(); - EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 3); // Check syncing. diff --git a/ethcore/engines/validator-set/src/safe_contract.rs b/ethcore/engines/validator-set/src/safe_contract.rs index cf1a23b1a..bcc6bba63 100644 --- a/ethcore/engines/validator-set/src/safe_contract.rs +++ b/ethcore/engines/validator-set/src/safe_contract.rs @@ -464,7 +464,7 @@ mod tests { transaction::{Transaction, Action}, verification::Unverified, }; - use client_traits::{BlockInfo, ChainInfo, ImportBlock, EngineClient}; + use client_traits::{BlockInfo, ChainInfo, ImportBlock, EngineClient, ForceUpdateSealing}; use engine::{EpochChange, Proof}; use ethcore::{ miner::{self, MinerService}, @@ -513,7 +513,7 @@ mod tests { data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 1); // Add "1" validator back in. let tx = Transaction { @@ -525,14 +525,14 @@ mod tests { data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client, ForceUpdateSealing::No); // The transaction is not yet included so still unable to seal. assert_eq!(client.chain_info().best_block_number, 1); // Switch to the validator that is still there. let signer = Box::new((tap.clone(), v0, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); - EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 2); // Switch back to the added validator, since the state is updated. let signer = Box::new((tap.clone(), v1, "".into())); @@ -546,7 +546,7 @@ mod tests { data: Vec::new(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client, ForceUpdateSealing::No); // Able to seal again. assert_eq!(client.chain_info().best_block_number, 3); diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 0339cfe1b..ce5c50d75 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -48,6 +48,7 @@ use self::header_chain::{AncestryIter, HeaderChain, HardcodedSync}; use cache::Cache; pub use self::service::Service; +use client_traits::ForceUpdateSealing; mod header_chain; mod service; @@ -626,7 +627,7 @@ impl client_traits::ChainInfo for Client { } impl client_traits::EngineClient for Client { - fn update_sealing(&self) { } + fn update_sealing(&self, _force: ForceUpdateSealing) {} fn submit_seal(&self, _block_hash: H256, _seal: Vec>) { } fn broadcast_consensus_message(&self, _message: Vec) { } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 93e5ca2ec..d29c8ac6f 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -78,7 +78,8 @@ use client_traits::{ StateClient, StateOrBlock, Tick, - TransactionInfo + TransactionInfo, + ForceUpdateSealing }; use db::{keys::BlockDetails, Readable, Writable}; use engine::Engine; @@ -2383,7 +2384,9 @@ impl ImportSealedBlock for Client { let raw = block.rlp_bytes(); let header = block.header.clone(); let hash = header.hash(); - self.notify(|n| n.block_pre_import(&raw, &hash, header.difficulty())); + self.notify(|n| { + n.block_pre_import(&raw, &hash, header.difficulty()) + }); let route = { // Do a super duper basic verification to detect potential bugs @@ -2471,19 +2474,22 @@ impl ::miner::TransactionVerifierClient for Client {} impl ::miner::BlockChainClient for Client {} impl client_traits::EngineClient for Client { - fn update_sealing(&self) { - self.importer.miner.update_sealing(self) + fn update_sealing(&self, force: ForceUpdateSealing) { + self.importer.miner.update_sealing(self, force) } fn submit_seal(&self, block_hash: H256, seal: Vec) { - let import = self.importer.miner.submit_seal(block_hash, seal).and_then(|block| self.import_sealed_block(block)); + let import = self.importer.miner.submit_seal(block_hash, seal) + .and_then(|block| self.import_sealed_block(block)); if let Err(err) = import { warn!(target: "poa", "Wrong internal seal submission! {:?}", err); } } fn broadcast_consensus_message(&self, message: Bytes) { - self.notify(|notify| notify.broadcast(ChainMessageType::Consensus(message.clone()))); + self.notify(|notify| { + notify.broadcast(ChainMessageType::Consensus(message.clone())) + }); } fn epoch_transition_for(&self, parent_hash: H256) -> Option { @@ -2622,13 +2628,21 @@ impl ImportExportBlocks for Client { if i % 10000 == 0 { info!("#{}", i); } - let b = self.block(BlockId::Number(i)).ok_or("Error exporting incomplete chain")?.into_inner(); + let b = self.block(BlockId::Number(i)) + .ok_or("Error exporting incomplete chain")? + .into_inner(); match format { DataFormat::Binary => { - out.write(&b).map_err(|e| format!("Couldn't write to stream. Cause: {}", e))?; + out.write(&b) + .map_err(|e| { + format!("Couldn't write to stream. Cause: {}", e) + })?; } DataFormat::Hex => { - out.write_fmt(format_args!("{}\n", b.pretty())).map_err(|e| format!("Couldn't write to stream. Cause: {}", e))?; + out.write_fmt(format_args!("{}\n", b.pretty())) + .map_err(|e| { + format!("Couldn't write to stream. Cause: {}", e) + })?; } } } @@ -2648,7 +2662,10 @@ impl ImportExportBlocks for Client { let format = match format { Some(format) => format, None => { - first_read = source.read(&mut first_bytes).map_err(|_| "Error reading from the file/stream.")?; + first_read = source.read(&mut first_bytes) + .map_err(|_| { + "Error reading from the file/stream." + })?; match first_bytes[0] { 0xf9 => DataFormat::Binary, _ => DataFormat::Hex, @@ -2659,7 +2676,9 @@ impl ImportExportBlocks for Client { let do_import = |bytes: Vec| { let block = Unverified::from_rlp(bytes).map_err(|_| "Invalid block rlp")?; let number = block.header.number(); - while self.queue_info().is_full() { std::thread::sleep(Duration::from_secs(1)); } + while self.queue_info().is_full() { + std::thread::sleep(Duration::from_secs(1)); + } match self.import_block(block) { Err(EthcoreError::Import(ImportError::AlreadyInChain)) => { trace!("Skipping block #{}: already in chain.", number); @@ -2680,33 +2699,45 @@ impl ImportExportBlocks for Client { } else { let mut bytes = vec![0; READAHEAD_BYTES]; let n = source.read(&mut bytes) - .map_err(|err| format!("Error reading from the file/stream: {:?}", err))?; + .map_err(|err| { + format!("Error reading from the file/stream: {:?}", err) + })?; (bytes, n) }; if n == 0 { break; } first_read = 0; let s = PayloadInfo::from(&bytes) - .map_err(|e| format!("Invalid RLP in the file/stream: {:?}", e))?.total(); + .map_err(|e| { + format!("Invalid RLP in the file/stream: {:?}", e) + })?.total(); bytes.resize(s, 0); source.read_exact(&mut bytes[n..]) - .map_err(|err| format!("Error reading from the file/stream: {:?}", err))?; + .map_err(|err| { + format!("Error reading from the file/stream: {:?}", err) + })?; do_import(bytes)?; } } DataFormat::Hex => { for line in BufReader::new(source).lines() { let s = line - .map_err(|err| format!("Error reading from the file/stream: {:?}", err))?; + .map_err(|err| { + format!("Error reading from the file/stream: {:?}", err) + })?; let s = if first_read > 0 { from_utf8(&first_bytes) - .map_err(|err| format!("Invalid UTF-8: {:?}", err))? + .map_err(|err| { + format!("Invalid UTF-8: {:?}", err) + })? .to_owned() + &(s[..]) } else { s }; first_read = 0; let bytes = s.from_hex() - .map_err(|err| format!("Invalid hex in file/stream: {:?}", err))?; + .map_err(|err| { + format!("Invalid hex in file/stream: {:?}", err) + })?; do_import(bytes)?; } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 1671fbffa..fef185e91 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -58,7 +58,7 @@ use using_queue::{UsingQueue, GetAction}; use block::{ClosedBlock, SealedBlock}; use client::{BlockProducer, SealedBlockImporter, Client}; -use client_traits::{BlockChain, ChainInfo, EngineClient, Nonce, TransactionInfo}; +use client_traits::{BlockChain, ChainInfo, Nonce, TransactionInfo, EngineClient, ForceUpdateSealing}; use engine::{Engine, signer::EngineSigner}; use machine::executive::contract_address; use spec::Spec; @@ -294,6 +294,7 @@ impl Miner { let tx_queue_strategy = options.tx_queue_strategy; let nonce_cache_size = cmp::max(4096, limits.max_count / 4); let refuse_service_transactions = options.refuse_service_transactions; + let engine = spec.engine.clone(); Miner { sealing: Mutex::new(SealingWork { @@ -312,7 +313,7 @@ impl Miner { options, transaction_queue: Arc::new(TransactionQueue::new(limits, verifier_options, tx_queue_strategy)), accounts: Arc::new(accounts), - engine: spec.engine.clone(), + engine, io_channel: RwLock::new(None), service_transaction_checker: if refuse_service_transactions { None @@ -865,12 +866,12 @@ impl Miner { match self.engine.sealing_state() { SealingState::Ready => { self.maybe_enable_sealing(); - self.update_sealing(chain) + self.update_sealing(chain, ForceUpdateSealing::No); } SealingState::External => { // this calls `maybe_enable_sealing()` if self.prepare_pending_block(chain) == BlockPreparationStatus::NotPrepared { - self.update_sealing(chain) + self.update_sealing(chain, ForceUpdateSealing::No); } } SealingState::NotReady => { self.maybe_enable_sealing(); }, @@ -1263,14 +1264,16 @@ impl miner::MinerService for Miner { /// Update sealing if required. /// Prepare the block and work if the Engine does not seal internally. - fn update_sealing(&self, chain: &C) where + fn update_sealing(&self, chain: &C, force: ForceUpdateSealing) where C: BlockChain + CallContract + BlockProducer + SealedBlockImporter + Nonce + Sync, { trace!(target: "miner", "update_sealing"); - // Do nothing if reseal is not required, + // Do nothing if we don't want to force update_sealing and reseal is not required. // but note that `requires_reseal` updates internal state. - if !self.requires_reseal(chain.chain_info().best_block_number) { + if force == ForceUpdateSealing::No && + !self.requires_reseal(chain.chain_info().best_block_number) + { return; } @@ -1305,13 +1308,14 @@ impl miner::MinerService for Miner { if self.seal_and_import_block_internally(chain, block) { trace!(target: "miner", "update_sealing: imported internally sealed block"); } + return }, SealingState::NotReady => unreachable!("We returned right after sealing_state was computed. qed."), SealingState::External => { trace!(target: "miner", "update_sealing: engine does not seal internally, preparing work"); - self.prepare_work(block, original_work_hash) + self.prepare_work(block, original_work_hash); }, - } + }; } fn is_currently_sealing(&self) -> bool { @@ -1423,7 +1427,7 @@ impl miner::MinerService for Miner { // | NOTE Code below requires sealing locks. | // | Make sure to release the locks before calling that method. | // -------------------------------------------------------------------------- - self.update_sealing(chain); + self.update_sealing(chain, ForceUpdateSealing::No); } } @@ -1441,7 +1445,6 @@ impl miner::MinerService for Miner { let engine = self.engine.clone(); let accounts = self.accounts.clone(); let service_transaction_checker = self.service_transaction_checker.clone(); - let cull = move |chain: &Client| { let client = PoolClient::new( chain, @@ -1451,8 +1454,9 @@ impl miner::MinerService for Miner { service_transaction_checker.as_ref(), ); queue.cull(client); - if is_internal_import { - chain.update_sealing(); + if engine.should_reseal_on_update() { + // force update_sealing here to skip `reseal_required` checks + chain.update_sealing(ForceUpdateSealing::Yes); } }; @@ -1461,8 +1465,9 @@ impl miner::MinerService for Miner { } } else { self.transaction_queue.cull(client); - if is_internal_import { - self.update_sealing(chain); + if self.engine.should_reseal_on_update() { + // force update_sealing here to skip `reseal_required` checks + self.update_sealing(chain, ForceUpdateSealing::Yes); } } } @@ -1793,7 +1798,7 @@ mod tests { ).pop().unwrap(); assert_eq!(import.unwrap(), ()); - miner.update_sealing(&*client); + miner.update_sealing(&*client, ForceUpdateSealing::No); client.flush_queue(); assert!(miner.pending_block(0).is_none()); assert_eq!(client.chain_info().best_block_number, 3 as BlockNumber); @@ -1803,7 +1808,7 @@ mod tests { PendingTransaction::new(transaction_with_chain_id(spec.chain_id()).into(), None) ).is_ok()); - miner.update_sealing(&*client); + miner.update_sealing(&*client, ForceUpdateSealing::No); client.flush_queue(); assert!(miner.pending_block(0).is_none()); assert_eq!(client.chain_info().best_block_number, 4 as BlockNumber); @@ -1831,7 +1836,7 @@ mod tests { let miner = Miner::new_for_tests(&spec, None); let client = generate_dummy_client(2); - miner.update_sealing(&*client); + miner.update_sealing(&*client, ForceUpdateSealing::No); assert!(miner.is_currently_sealing()); } @@ -1842,7 +1847,7 @@ mod tests { let miner = Miner::new_for_tests(&spec, None); let client = generate_dummy_client(2); - miner.update_sealing(&*client); + miner.update_sealing(&*client, ForceUpdateSealing::No); assert!(!miner.is_currently_sealing()); } @@ -1853,7 +1858,7 @@ mod tests { let miner = Miner::new_for_tests(&spec, None); let client = generate_dummy_client(2); - miner.update_sealing(&*client); + miner.update_sealing(&*client, ForceUpdateSealing::No); assert!(!miner.is_currently_sealing()); } @@ -1872,7 +1877,7 @@ mod tests { miner.add_work_listener(Box::new(DummyNotifyWork)); let client = generate_dummy_client(2); - miner.update_sealing(&*client); + miner.update_sealing(&*client, ForceUpdateSealing::No); assert!(miner.is_currently_sealing()); } diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 04cfd00ca..1fddab4a7 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -47,7 +47,7 @@ use types::{ use call_contract::CallContract; use registrar::RegistrarClient; -use client_traits::{BlockChain, ChainInfo, AccountData, Nonce, ScheduleInfo}; +use client_traits::{BlockChain, ChainInfo, AccountData, Nonce, ScheduleInfo, ForceUpdateSealing}; use account_state::state::StateInfo; use crate::{ @@ -87,7 +87,7 @@ pub trait MinerService : Send + Sync { where C: BlockChain + CallContract + BlockProducer + SealedBlockImporter + Nonce + Sync; /// Update current pending block - fn update_sealing(&self, chain: &C) + fn update_sealing(&self, chain: &C, force: ForceUpdateSealing) where C: BlockChain + CallContract + BlockProducer + SealedBlockImporter + Nonce + Sync; // Notifications diff --git a/ethcore/src/test_helpers/test_client.rs b/ethcore/src/test_helpers/test_client.rs index 683b08dda..403c64c0e 100644 --- a/ethcore/src/test_helpers/test_client.rs +++ b/ethcore/src/test_helpers/test_client.rs @@ -72,7 +72,7 @@ use client::{ use client_traits::{ BlockInfo, Nonce, Balance, ChainInfo, TransactionInfo, BlockChainClient, ImportBlock, AccountData, BlockChain, IoClient, BadBlocks, ScheduleInfo, StateClient, ProvingBlockChainClient, - StateOrBlock + StateOrBlock, ForceUpdateSealing }; use engine::Engine; use machine::executed::Executed; @@ -963,8 +963,8 @@ impl ProvingBlockChainClient for TestBlockChainClient { } impl client_traits::EngineClient for TestBlockChainClient { - fn update_sealing(&self) { - self.miner.update_sealing(self) + fn update_sealing(&self, force: ForceUpdateSealing) { + self.miner.update_sealing(self, force) } fn submit_seal(&self, block_hash: H256, seal: Vec) { diff --git a/miner/src/pool/listener.rs b/miner/src/pool/listener.rs index 998305904..aa3b10a7d 100644 --- a/miner/src/pool/listener.rs +++ b/miner/src/pool/listener.rs @@ -105,11 +105,17 @@ impl TransactionsPoolNotifier { .map(|(hash, _)| hash) .collect() ); - self.pending_listeners.retain(|listener| listener.unbounded_send(to_pending_send.clone()).is_ok()); + self.pending_listeners.retain(|listener| { + listener.unbounded_send(to_pending_send.clone()).is_ok() + }); - let to_full_send = Arc::new(std::mem::replace(&mut self.tx_statuses, Vec::new())); + let to_full_send = Arc::new( + std::mem::replace(&mut self.tx_statuses, Vec::new()) + ); self.full_listeners - .retain(|listener| listener.unbounded_send(to_full_send.clone()).is_ok()); + .retain(|listener| { + listener.unbounded_send(to_full_send.clone()).is_ok() + }); } } diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 7d2edcbbf..be7d83b57 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use std::collections::{BTreeMap, BTreeSet, HashMap}; use bytes::Bytes; -use client_traits::{Nonce, StateClient}; +use client_traits::{Nonce, StateClient, ForceUpdateSealing}; use engine::{Engine, signer::EngineSigner}; use ethcore::block::SealedBlock; use ethcore::client::{PrepareOpenBlock, EngineInfo}; @@ -192,7 +192,7 @@ impl MinerService for TestMinerService { } /// New chain head event. Restart mining operation. - fn update_sealing(&self, _chain: &C) { + fn update_sealing(&self, _chain: &C, _force: ForceUpdateSealing) { unimplemented!(); }