diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 8205ae2ab3b..ee42e6829d5 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -18,7 +18,7 @@ use std::sync::{Weak, Arc}; -use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage}; +use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage, traits::ForceUpdateSealing}; use ethcore::engines::{epoch, EthEngine, EpochChange, EpochTransition, Proof}; use ethcore::machine::EthereumMachine; use ethcore::error::{Error, EthcoreResult}; @@ -620,7 +620,7 @@ impl ::ethcore::client::ChainInfo for Client { } impl ::ethcore::client::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 bd872d798cb..43cf42bbd6d 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -62,7 +62,7 @@ use client::{ BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient, TraceFilter, CallAnalytics, Mode, ChainNotify, NewBlocks, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType, - IoClient, BadBlocks, + IoClient, BadBlocks, traits::ForceUpdateSealing }; use client::bad_blocks; use engines::{MAX_UNCLE_AGE, EthEngine, EpochTransition, ForkChoice, EngineError}; @@ -2424,7 +2424,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 @@ -2512,19 +2514,22 @@ impl ::miner::TransactionVerifierClient for Client {} impl ::miner::BlockChainClient for Client {} impl super::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<::engines::EpochTransition> { @@ -2598,13 +2603,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) + })?; } } } @@ -2624,7 +2637,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, @@ -2635,7 +2651,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(Error(EthcoreErrorKind::Import(ImportErrorKind::AlreadyInChain), _)) => { trace!("Skipping block #{}: already in chain.", number); @@ -2656,33 +2674,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/client/test_client.rs b/ethcore/src/client/test_client.rs index 94baa855202..e3ccc71fb00 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -56,7 +56,7 @@ use client::{ TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics, ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock, Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, IoClient, - BadBlocks, + BadBlocks, traits::ForceUpdateSealing }; use engines::EthEngine; use error::{Error, EthcoreResult}; @@ -931,8 +931,8 @@ impl ProvingBlockChainClient for TestBlockChainClient { } impl super::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/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 8515cab0ad3..16c185e6910 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -423,10 +423,19 @@ pub trait BroadcastProposalBlock { /// Provides methods to import sealed block and broadcast a block proposal pub trait SealedBlockImporter: ImportSealedBlock + BroadcastProposalBlock {} +/// 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/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 312b58e61ce..3350498e9ec 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -25,7 +25,7 @@ use std::sync::{Weak, Arc}; use std::time::{UNIX_EPOCH, Duration}; use block::*; -use client::EngineClient; +use client::{EngineClient, traits::ForceUpdateSealing}; use engines::{Engine, Seal, EngineError, ConstructedVerifier}; use engines::block_reward; use engines::block_reward::{BlockRewardContract, RewardKind}; @@ -908,7 +908,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); } } } @@ -936,7 +936,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/src/engines/clique/mod.rs b/ethcore/src/engines/clique/mod.rs index 133e66b968b..65d56fa28bf 100644 --- a/ethcore/src/engines/clique/mod.rs +++ b/ethcore/src/engines/clique/mod.rs @@ -68,7 +68,7 @@ use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH}; use block::ExecutedBlock; use bytes::Bytes; -use client::{BlockId, EngineClient}; +use client::{BlockId, EngineClient, traits::ForceUpdateSealing}; use engines::clique::util::{extract_signers, recover_creator}; use engines::{Engine, EngineError, Seal}; use error::{BlockError, Error}; @@ -749,7 +749,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/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index ec6f42bc7dc..677a8abc193 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -63,6 +63,13 @@ impl Engine for InstantSeal { fn seals_internally(&self) -> Option { Some(true) } + 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/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 8b67c5d48a9..56e7b5d178f 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -307,6 +307,14 @@ pub trait Engine: Sync + Send { /// Some(false) means that the node might seal internally but is not qualified now. fn seals_internally(&self) -> Option { None } + /// 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/src/engines/validator_set/multi.rs b/ethcore/src/engines/validator_set/multi.rs index b9ef6774784..c1ca3c3ed19 100644 --- a/ethcore/src/engines/validator_set/multi.rs +++ b/ethcore/src/engines/validator_set/multi.rs @@ -151,7 +151,7 @@ mod tests { use std::collections::BTreeMap; use hash::keccak; use accounts::AccountProvider; - use client::{BlockChainClient, ChainInfo, BlockInfo, ImportBlock}; + use client::{BlockChainClient, ChainInfo, BlockInfo, ImportBlock, traits::ForceUpdateSealing}; use engines::EpochChange; use engines::validator_set::ValidatorSet; use ethkey::Secret; @@ -181,24 +181,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(); - ::client::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)); - ::client::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(); - ::client::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)); - ::client::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(); - ::client::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/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index 49d539df3f3..3596ff4b298 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -447,7 +447,7 @@ mod tests { use spec::Spec; use accounts::AccountProvider; use types::transaction::{Transaction, Action}; - use client::{ChainInfo, BlockInfo, ImportBlock}; + use client::{ChainInfo, BlockInfo, ImportBlock, traits::{ForceUpdateSealing, EngineClient}}; use ethkey::Secret; use miner::{self, MinerService}; use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data}; @@ -488,7 +488,7 @@ mod tests { data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - ::client::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 { @@ -500,14 +500,14 @@ mod tests { data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - ::client::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)); - ::client::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())); @@ -521,7 +521,7 @@ mod tests { data: Vec::new(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - ::client::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/src/miner/miner.rs b/ethcore/src/miner/miner.rs index c86550083e3..1da323e30cd 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -52,7 +52,7 @@ use client::{ BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId }; use client::{BlockId, ClientIoMessage}; -use client::traits::EngineClient; +use client::traits::{EngineClient, ForceUpdateSealing}; use engines::{EthEngine, Seal, EngineSigner}; use error::{Error, ErrorKind}; use executed::ExecutionError; @@ -276,6 +276,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 { @@ -294,7 +295,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 @@ -829,7 +830,7 @@ impl Miner { preparation_status } - /// Prepare pending block, check whether sealing is needed, and then update sealing. +/// Prepare pending block, check whether sealing is needed, and then update sealing. fn prepare_and_update_sealing(&self, chain: &C) { // Make sure to do it after transaction is imported and lock is dropped. @@ -838,7 +839,7 @@ impl Miner { // If new block has not been prepared (means we already had one) // or Engine might be able to seal internally, // we need to update sealing. - self.update_sealing(chain); + self.update_sealing(chain, ForceUpdateSealing::No); } } } @@ -1136,14 +1137,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; } @@ -1173,6 +1176,7 @@ impl miner::MinerService for Miner { if self.seal_and_import_block_internally(chain, block) { trace!(target: "miner", "update_sealing: imported internally sealed block"); } + return }, Some(false) => { trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now"); @@ -1181,9 +1185,9 @@ impl miner::MinerService for Miner { }, None => { 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 { @@ -1284,7 +1288,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); } } @@ -1312,8 +1316,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); } }; @@ -1322,8 +1327,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); } } } @@ -1643,14 +1649,14 @@ mod tests { let import = miner.import_external_transactions(&*client, vec![transaction_with_chain_id(spec.chain_id()).into()]).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); assert!(miner.import_own_transaction(&*client, 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); @@ -1678,7 +1684,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()); } @@ -1689,7 +1695,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()); } @@ -1700,7 +1706,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()); } @@ -1719,7 +1725,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 fd7ab96513c..12658192aa3 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -46,7 +46,7 @@ use call_contract::{CallContract, RegistryInfo}; use client::{ ScheduleInfo, BlockChain, BlockProducer, SealedBlockImporter, ChainInfo, - AccountData, Nonce, + AccountData, Nonce, traits::ForceUpdateSealing }; use error::Error; use state::StateInfo; @@ -83,7 +83,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/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 8f000418480..86239be1a62 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -21,7 +21,7 @@ use std::collections::{BTreeMap, BTreeSet, HashMap}; use bytes::Bytes; use ethcore::block::SealedBlock; -use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo}; +use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo, traits::ForceUpdateSealing}; use ethcore::engines::{EthEngine, signer::EngineSigner}; use ethcore::error::Error; use ethcore::miner::{self, MinerService, AuthoringParams}; @@ -186,7 +186,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!(); }