Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit b5c7df8

Browse files
committed
Make InstantSeal Instant again (#11186)
* Make InstantSeal Instant again * update_sealing if there are transactions in pool after impoerting a block, some line formatting * Apply suggestions from code review Co-Authored-By: Tomasz Drwięga <[email protected]> * InstantSeal specific behaviour * introduce engine.should_reseal_on_update, remove InstantSealService * remove unused code * add force param to update_sealing * better docc * even better docs * revert code changes, doc corrections, sort dep * code optimization * fix test * fix bench
1 parent 6891ad9 commit b5c7df8

File tree

13 files changed

+123
-63
lines changed

13 files changed

+123
-63
lines changed

ethcore/light/src/client/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
1919
use std::sync::{Weak, Arc};
2020

21-
use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage};
21+
use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage, traits::ForceUpdateSealing};
2222
use ethcore::engines::{epoch, EthEngine, EpochChange, EpochTransition, Proof};
2323
use ethcore::machine::EthereumMachine;
2424
use ethcore::error::{Error, EthcoreResult};
@@ -620,7 +620,7 @@ impl<T: ChainDataFetcher> ::ethcore::client::ChainInfo for Client<T> {
620620
}
621621

622622
impl<T: ChainDataFetcher> ::ethcore::client::EngineClient for Client<T> {
623-
fn update_sealing(&self) { }
623+
fn update_sealing(&self, _force: ForceUpdateSealing) {}
624624
fn submit_seal(&self, _block_hash: H256, _seal: Vec<Vec<u8>>) { }
625625
fn broadcast_consensus_message(&self, _message: Vec<u8>) { }
626626

ethcore/src/client/client.rs

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ use client::{
6262
BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient,
6363
TraceFilter, CallAnalytics, Mode,
6464
ChainNotify, NewBlocks, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType,
65-
IoClient, BadBlocks,
65+
IoClient, BadBlocks, traits::ForceUpdateSealing
6666
};
6767
use client::bad_blocks;
6868
use engines::{MAX_UNCLE_AGE, EthEngine, EpochTransition, ForkChoice, EngineError};
@@ -2424,7 +2424,9 @@ impl ImportSealedBlock for Client {
24242424
let raw = block.rlp_bytes();
24252425
let header = block.header.clone();
24262426
let hash = header.hash();
2427-
self.notify(|n| n.block_pre_import(&raw, &hash, header.difficulty()));
2427+
self.notify(|n| {
2428+
n.block_pre_import(&raw, &hash, header.difficulty())
2429+
});
24282430

24292431
let route = {
24302432
// Do a super duper basic verification to detect potential bugs
@@ -2512,19 +2514,22 @@ impl ::miner::TransactionVerifierClient for Client {}
25122514
impl ::miner::BlockChainClient for Client {}
25132515

25142516
impl super::traits::EngineClient for Client {
2515-
fn update_sealing(&self) {
2516-
self.importer.miner.update_sealing(self)
2517+
fn update_sealing(&self, force: ForceUpdateSealing) {
2518+
self.importer.miner.update_sealing(self, force)
25172519
}
25182520

25192521
fn submit_seal(&self, block_hash: H256, seal: Vec<Bytes>) {
2520-
let import = self.importer.miner.submit_seal(block_hash, seal).and_then(|block| self.import_sealed_block(block));
2522+
let import = self.importer.miner.submit_seal(block_hash, seal)
2523+
.and_then(|block| self.import_sealed_block(block));
25212524
if let Err(err) = import {
25222525
warn!(target: "poa", "Wrong internal seal submission! {:?}", err);
25232526
}
25242527
}
25252528

25262529
fn broadcast_consensus_message(&self, message: Bytes) {
2527-
self.notify(|notify| notify.broadcast(ChainMessageType::Consensus(message.clone())));
2530+
self.notify(|notify| {
2531+
notify.broadcast(ChainMessageType::Consensus(message.clone()))
2532+
});
25282533
}
25292534

25302535
fn epoch_transition_for(&self, parent_hash: H256) -> Option<::engines::EpochTransition> {
@@ -2598,13 +2603,21 @@ impl ImportExportBlocks for Client {
25982603
if i % 10000 == 0 {
25992604
info!("#{}", i);
26002605
}
2601-
let b = self.block(BlockId::Number(i)).ok_or("Error exporting incomplete chain")?.into_inner();
2606+
let b = self.block(BlockId::Number(i))
2607+
.ok_or("Error exporting incomplete chain")?
2608+
.into_inner();
26022609
match format {
26032610
DataFormat::Binary => {
2604-
out.write(&b).map_err(|e| format!("Couldn't write to stream. Cause: {}", e))?;
2611+
out.write(&b)
2612+
.map_err(|e| {
2613+
format!("Couldn't write to stream. Cause: {}", e)
2614+
})?;
26052615
}
26062616
DataFormat::Hex => {
2607-
out.write_fmt(format_args!("{}\n", b.pretty())).map_err(|e| format!("Couldn't write to stream. Cause: {}", e))?;
2617+
out.write_fmt(format_args!("{}\n", b.pretty()))
2618+
.map_err(|e| {
2619+
format!("Couldn't write to stream. Cause: {}", e)
2620+
})?;
26082621
}
26092622
}
26102623
}
@@ -2624,7 +2637,10 @@ impl ImportExportBlocks for Client {
26242637
let format = match format {
26252638
Some(format) => format,
26262639
None => {
2627-
first_read = source.read(&mut first_bytes).map_err(|_| "Error reading from the file/stream.")?;
2640+
first_read = source.read(&mut first_bytes)
2641+
.map_err(|_| {
2642+
"Error reading from the file/stream."
2643+
})?;
26282644
match first_bytes[0] {
26292645
0xf9 => DataFormat::Binary,
26302646
_ => DataFormat::Hex,
@@ -2635,7 +2651,9 @@ impl ImportExportBlocks for Client {
26352651
let do_import = |bytes: Vec<u8>| {
26362652
let block = Unverified::from_rlp(bytes).map_err(|_| "Invalid block rlp")?;
26372653
let number = block.header.number();
2638-
while self.queue_info().is_full() { std::thread::sleep(Duration::from_secs(1)); }
2654+
while self.queue_info().is_full() {
2655+
std::thread::sleep(Duration::from_secs(1));
2656+
}
26392657
match self.import_block(block) {
26402658
Err(Error(EthcoreErrorKind::Import(ImportErrorKind::AlreadyInChain), _)) => {
26412659
trace!("Skipping block #{}: already in chain.", number);
@@ -2656,33 +2674,45 @@ impl ImportExportBlocks for Client {
26562674
} else {
26572675
let mut bytes = vec![0; READAHEAD_BYTES];
26582676
let n = source.read(&mut bytes)
2659-
.map_err(|err| format!("Error reading from the file/stream: {:?}", err))?;
2677+
.map_err(|err| {
2678+
format!("Error reading from the file/stream: {:?}", err)
2679+
})?;
26602680
(bytes, n)
26612681
};
26622682
if n == 0 { break; }
26632683
first_read = 0;
26642684
let s = PayloadInfo::from(&bytes)
2665-
.map_err(|e| format!("Invalid RLP in the file/stream: {:?}", e))?.total();
2685+
.map_err(|e| {
2686+
format!("Invalid RLP in the file/stream: {:?}", e)
2687+
})?.total();
26662688
bytes.resize(s, 0);
26672689
source.read_exact(&mut bytes[n..])
2668-
.map_err(|err| format!("Error reading from the file/stream: {:?}", err))?;
2690+
.map_err(|err| {
2691+
format!("Error reading from the file/stream: {:?}", err)
2692+
})?;
26692693
do_import(bytes)?;
26702694
}
26712695
}
26722696
DataFormat::Hex => {
26732697
for line in BufReader::new(source).lines() {
26742698
let s = line
2675-
.map_err(|err| format!("Error reading from the file/stream: {:?}", err))?;
2699+
.map_err(|err| {
2700+
format!("Error reading from the file/stream: {:?}", err)
2701+
})?;
26762702
let s = if first_read > 0 {
26772703
from_utf8(&first_bytes)
2678-
.map_err(|err| format!("Invalid UTF-8: {:?}", err))?
2704+
.map_err(|err| {
2705+
format!("Invalid UTF-8: {:?}", err)
2706+
})?
26792707
.to_owned() + &(s[..])
26802708
} else {
26812709
s
26822710
};
26832711
first_read = 0;
26842712
let bytes = s.from_hex()
2685-
.map_err(|err| format!("Invalid hex in file/stream: {:?}", err))?;
2713+
.map_err(|err| {
2714+
format!("Invalid hex in file/stream: {:?}", err)
2715+
})?;
26862716
do_import(bytes)?;
26872717
}
26882718
}

ethcore/src/client/test_client.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ use client::{
5656
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics,
5757
ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock,
5858
Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, IoClient,
59-
BadBlocks,
59+
BadBlocks, traits::ForceUpdateSealing
6060
};
6161
use engines::EthEngine;
6262
use error::{Error, EthcoreResult};
@@ -931,8 +931,8 @@ impl ProvingBlockChainClient for TestBlockChainClient {
931931
}
932932

933933
impl super::traits::EngineClient for TestBlockChainClient {
934-
fn update_sealing(&self) {
935-
self.miner.update_sealing(self)
934+
fn update_sealing(&self, force: ForceUpdateSealing) {
935+
self.miner.update_sealing(self, force)
936936
}
937937

938938
fn submit_seal(&self, block_hash: H256, seal: Vec<Bytes>) {

ethcore/src/client/traits.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,10 +423,19 @@ pub trait BroadcastProposalBlock {
423423
/// Provides methods to import sealed block and broadcast a block proposal
424424
pub trait SealedBlockImporter: ImportSealedBlock + BroadcastProposalBlock {}
425425

426+
/// Do we want to force update sealing?
427+
#[derive(Debug, Copy, Clone, PartialEq)]
428+
pub enum ForceUpdateSealing {
429+
/// Ideally you want to use `No` at all times as `Yes` skips `reseal_required` checks.
430+
Yes,
431+
/// Don't skip `reseal_required` checks
432+
No
433+
}
434+
426435
/// Client facilities used by internally sealing Engines.
427436
pub trait EngineClient: Sync + Send + ChainInfo {
428437
/// Make a new block and seal it.
429-
fn update_sealing(&self);
438+
fn update_sealing(&self, force: ForceUpdateSealing);
430439

431440
/// Submit a seal for a block in the mining queue.
432441
fn submit_seal(&self, block_hash: H256, seal: Vec<Bytes>);

ethcore/src/engines/authority_round/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use std::sync::{Weak, Arc};
2525
use std::time::{UNIX_EPOCH, Duration};
2626

2727
use block::*;
28-
use client::EngineClient;
28+
use client::{EngineClient, traits::ForceUpdateSealing};
2929
use engines::{Engine, Seal, EngineError, ConstructedVerifier};
3030
use engines::block_reward;
3131
use engines::block_reward::{BlockRewardContract, RewardKind};
@@ -908,7 +908,7 @@ impl IoHandler<()> for TransitionHandler {
908908
self.step.can_propose.store(true, AtomicOrdering::SeqCst);
909909
if let Some(ref weak) = *self.client.read() {
910910
if let Some(c) = weak.upgrade() {
911-
c.update_sealing();
911+
c.update_sealing(ForceUpdateSealing::No);
912912
}
913913
}
914914
}
@@ -936,7 +936,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
936936
self.step.can_propose.store(true, AtomicOrdering::SeqCst);
937937
if let Some(ref weak) = *self.client.read() {
938938
if let Some(c) = weak.upgrade() {
939-
c.update_sealing();
939+
c.update_sealing(ForceUpdateSealing::No);
940940
}
941941
}
942942
}

ethcore/src/engines/clique/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH};
6868

6969
use block::ExecutedBlock;
7070
use bytes::Bytes;
71-
use client::{BlockId, EngineClient};
71+
use client::{BlockId, EngineClient, traits::ForceUpdateSealing};
7272
use engines::clique::util::{extract_signers, recover_creator};
7373
use engines::{Engine, EngineError, Seal};
7474
use error::{BlockError, Error};
@@ -749,7 +749,7 @@ impl Engine<EthereumMachine> for Clique {
749749
if self.signer.read().is_some() {
750750
if let Some(ref weak) = *self.client.read() {
751751
if let Some(c) = weak.upgrade() {
752-
c.update_sealing();
752+
c.update_sealing(ForceUpdateSealing::No);
753753
}
754754
}
755755
}

ethcore/src/engines/instant_seal.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ impl<M: Machine> Engine<M> for InstantSeal<M> {
6363

6464
fn seals_internally(&self) -> Option<bool> { Some(true) }
6565

66+
fn should_reseal_on_update(&self) -> bool {
67+
// We would like for the miner to `update_sealing` if there are local_pending_transactions
68+
// in the pool to prevent transactions sent in parallel from stalling in the transaction
69+
// pool. (see #9660)
70+
true
71+
}
72+
6673
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
6774
if !block.transactions.is_empty() {
6875
let block_number = block.header.number();

ethcore/src/engines/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,14 @@ pub trait Engine<M: Machine>: Sync + Send {
307307
/// Some(false) means that the node might seal internally but is not qualified now.
308308
fn seals_internally(&self) -> Option<bool> { None }
309309

310+
/// Called in `miner.chain_new_blocks` if the engine wishes to `update_sealing`
311+
/// after a block was recently sealed.
312+
///
313+
/// returns false by default
314+
fn should_reseal_on_update(&self) -> bool {
315+
false
316+
}
317+
310318
/// Attempt to seal the block internally.
311319
///
312320
/// If `Some` is returned, then you get a valid seal.

ethcore/src/engines/validator_set/multi.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ mod tests {
151151
use std::collections::BTreeMap;
152152
use hash::keccak;
153153
use accounts::AccountProvider;
154-
use client::{BlockChainClient, ChainInfo, BlockInfo, ImportBlock};
154+
use client::{BlockChainClient, ChainInfo, BlockInfo, ImportBlock, traits::ForceUpdateSealing};
155155
use engines::EpochChange;
156156
use engines::validator_set::ValidatorSet;
157157
use ethkey::Secret;
@@ -181,24 +181,24 @@ mod tests {
181181
let signer = Box::new((tap.clone(), v1, "".into()));
182182
client.miner().set_author(miner::Author::Sealer(signer));
183183
client.transact_contract(Default::default(), Default::default()).unwrap();
184-
::client::EngineClient::update_sealing(&*client);
184+
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
185185
assert_eq!(client.chain_info().best_block_number, 0);
186186
// Right signer for the first block.
187187
let signer = Box::new((tap.clone(), v0, "".into()));
188188
client.miner().set_author(miner::Author::Sealer(signer));
189-
::client::EngineClient::update_sealing(&*client);
189+
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
190190
assert_eq!(client.chain_info().best_block_number, 1);
191191
// This time v0 is wrong.
192192
client.transact_contract(Default::default(), Default::default()).unwrap();
193-
::client::EngineClient::update_sealing(&*client);
193+
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
194194
assert_eq!(client.chain_info().best_block_number, 1);
195195
let signer = Box::new((tap.clone(), v1, "".into()));
196196
client.miner().set_author(miner::Author::Sealer(signer));
197-
::client::EngineClient::update_sealing(&*client);
197+
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
198198
assert_eq!(client.chain_info().best_block_number, 2);
199199
// v1 is still good.
200200
client.transact_contract(Default::default(), Default::default()).unwrap();
201-
::client::EngineClient::update_sealing(&*client);
201+
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
202202
assert_eq!(client.chain_info().best_block_number, 3);
203203

204204
// Check syncing.

ethcore/src/engines/validator_set/safe_contract.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ mod tests {
447447
use spec::Spec;
448448
use accounts::AccountProvider;
449449
use types::transaction::{Transaction, Action};
450-
use client::{ChainInfo, BlockInfo, ImportBlock};
450+
use client::{ChainInfo, BlockInfo, ImportBlock, traits::ForceUpdateSealing};
451451
use ethkey::Secret;
452452
use miner::{self, MinerService};
453453
use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data};
@@ -488,7 +488,7 @@ mod tests {
488488
data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
489489
}.sign(&s0, Some(chain_id));
490490
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
491-
::client::EngineClient::update_sealing(&*client);
491+
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
492492
assert_eq!(client.chain_info().best_block_number, 1);
493493
// Add "1" validator back in.
494494
let tx = Transaction {
@@ -500,14 +500,14 @@ mod tests {
500500
data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
501501
}.sign(&s0, Some(chain_id));
502502
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
503-
::client::EngineClient::update_sealing(&*client);
503+
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
504504
// The transaction is not yet included so still unable to seal.
505505
assert_eq!(client.chain_info().best_block_number, 1);
506506

507507
// Switch to the validator that is still there.
508508
let signer = Box::new((tap.clone(), v0, "".into()));
509509
client.miner().set_author(miner::Author::Sealer(signer));
510-
::client::EngineClient::update_sealing(&*client);
510+
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
511511
assert_eq!(client.chain_info().best_block_number, 2);
512512
// Switch back to the added validator, since the state is updated.
513513
let signer = Box::new((tap.clone(), v1, "".into()));
@@ -521,7 +521,7 @@ mod tests {
521521
data: Vec::new(),
522522
}.sign(&s0, Some(chain_id));
523523
client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
524-
::client::EngineClient::update_sealing(&*client);
524+
EngineClient::update_sealing(&*client, ForceUpdateSealing::No);
525525
// Able to seal again.
526526
assert_eq!(client.chain_info().best_block_number, 3);
527527

0 commit comments

Comments
 (0)