From be21671c1c01af248460ff442076af832d6d6c9e Mon Sep 17 00:00:00 2001 From: keorn Date: Wed, 8 Mar 2017 17:25:50 +0100 Subject: [PATCH] Calibrate step before rejection (#4800) * calibrate before rejection * change flag name * fix merge --- ethcore/src/engines/authority_round.rs | 30 ++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/ethcore/src/engines/authority_round.rs b/ethcore/src/engines/authority_round.rs index 45be4a491..03b5d785f 100644 --- a/ethcore/src/engines/authority_round.rs +++ b/ethcore/src/engines/authority_round.rs @@ -83,6 +83,8 @@ pub struct AuthorityRound { client: RwLock>>, signer: EngineSigner, validators: Box, + /// Is this Engine just for testing (prevents step calibration). + calibrate_step: bool, } fn header_step(header: &Header) -> Result { @@ -122,6 +124,7 @@ impl AuthorityRound { client: RwLock::new(None), signer: Default::default(), validators: new_validator_set(our_params.validators), + calibrate_step: our_params.start_step.is_none(), }); // Do not initialize timeouts for tests. if should_timeout { @@ -131,6 +134,12 @@ impl AuthorityRound { Ok(engine) } + fn calibrate_step(&self) { + if self.calibrate_step { + self.step.store((unix_now().as_secs() / self.step_duration.as_secs()) as usize, AtomicOrdering::SeqCst); + } + } + fn remaining_step_duration(&self) -> Duration { let now = unix_now(); let step_end = self.step_duration * (self.step.load(AtomicOrdering::SeqCst) as u32 + 1); @@ -148,6 +157,16 @@ impl AuthorityRound { fn is_step_proposer(&self, bh: &H256, step: usize, address: &Address) -> bool { self.step_proposer(bh, step) == *address } + + fn is_future_step(&self, step: usize) -> bool { + if step > self.step.load(AtomicOrdering::SeqCst) + 1 { + // Make absolutely sure that the step is correct. + self.calibrate_step(); + step > self.step.load(AtomicOrdering::SeqCst) + 1 + } else { + false + } + } } fn unix_now() -> Duration { @@ -289,18 +308,17 @@ impl Engine for AuthorityRound { fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> { let step = header_step(header)?; // Give one step slack if step is lagging, double vote is still not possible. - if step <= self.step.load(AtomicOrdering::SeqCst) + 1 { - // Check if the signature belongs to a validator, can depend on parent state. + if self.is_future_step(step) { + trace!(target: "engine", "verify_block_unordered: block from the future"); + self.validators.report_benign(header.author()); + Err(BlockError::InvalidSeal)? + } else { let proposer_signature = header_signature(header)?; let correct_proposer = self.step_proposer(header.parent_hash(), step); if !verify_address(&correct_proposer, &proposer_signature, &header.bare_hash())? { trace!(target: "engine", "verify_block_unordered: bad proposer for step: {}", step); Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: header.author().clone() }))? } - } else { - trace!(target: "engine", "verify_block_unordered: block from the future"); - self.validators.report_benign(header.author()); - Err(BlockError::InvalidSeal)? } // Do not calculate difficulty for genesis blocks.