[stable] Engine backports (#4807)

* calibrate before rejection

* change flag name

* add eip155

* fix build

* make network_id default
This commit is contained in:
keorn 2017-03-08 14:43:54 +01:00 committed by Gav Wood
parent d0b6f2648b
commit 7f5795dee6
2 changed files with 26 additions and 5 deletions

View File

@ -86,6 +86,8 @@ pub struct AuthorityRound {
account_provider: Mutex<Arc<AccountProvider>>, account_provider: Mutex<Arc<AccountProvider>>,
password: RwLock<Option<String>>, password: RwLock<Option<String>>,
validators: Box<ValidatorSet + Send + Sync>, validators: Box<ValidatorSet + Send + Sync>,
/// Is this Engine just for testing (prevents step calibration).
calibrate_step: bool,
} }
fn header_step(header: &Header) -> Result<usize, ::rlp::DecoderError> { fn header_step(header: &Header) -> Result<usize, ::rlp::DecoderError> {
@ -126,6 +128,7 @@ impl AuthorityRound {
account_provider: Mutex::new(Arc::new(AccountProvider::transient_provider())), account_provider: Mutex::new(Arc::new(AccountProvider::transient_provider())),
password: RwLock::new(None), password: RwLock::new(None),
validators: new_validator_set(our_params.validators), validators: new_validator_set(our_params.validators),
calibrate_step: our_params.start_step.is_none(),
}); });
// Do not initialize timeouts for tests. // Do not initialize timeouts for tests.
if should_timeout { if should_timeout {
@ -135,6 +138,12 @@ impl AuthorityRound {
Ok(engine) 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 { fn remaining_step_duration(&self) -> Duration {
let now = unix_now(); let now = unix_now();
let step_end = self.step_duration * (self.step.load(AtomicOrdering::SeqCst) as u32 + 1); let step_end = self.step_duration * (self.step.load(AtomicOrdering::SeqCst) as u32 + 1);
@ -152,6 +161,16 @@ impl AuthorityRound {
fn is_step_proposer(&self, step: usize, address: &Address) -> bool { fn is_step_proposer(&self, step: usize, address: &Address) -> bool {
self.step_proposer(step) == *address self.step_proposer(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 { fn unix_now() -> Duration {
@ -286,7 +305,10 @@ impl Engine for AuthorityRound {
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
let header_step = header_step(header)?; let header_step = header_step(header)?;
// Give one step slack if step is lagging, double vote is still not possible. // Give one step slack if step is lagging, double vote is still not possible.
if header_step <= self.step.load(AtomicOrdering::SeqCst) + 1 { if self.is_future_step(header_step) {
trace!(target: "engine", "verify_block_unordered: block from the future");
Err(BlockError::InvalidSeal)?
} else {
let proposer_signature = header_signature(header)?; let proposer_signature = header_signature(header)?;
let ok_sig = verify_address(&self.step_proposer(header_step), &proposer_signature, &header.bare_hash())?; let ok_sig = verify_address(&self.step_proposer(header_step), &proposer_signature, &header.bare_hash())?;
if ok_sig { if ok_sig {
@ -295,9 +317,6 @@ impl Engine for AuthorityRound {
trace!(target: "poa", "verify_block_unordered: invalid seal signature"); trace!(target: "poa", "verify_block_unordered: invalid seal signature");
Err(BlockError::InvalidSeal)? Err(BlockError::InvalidSeal)?
} }
} else {
trace!(target: "poa", "verify_block_unordered: block from the future");
Err(BlockError::InvalidSeal)?
} }
} }

View File

@ -160,7 +160,9 @@ pub trait Engine : Sync + Send {
fn verify_transaction(&self, _t: &SignedTransaction, _header: &Header) -> Result<(), Error> { Ok(()) } fn verify_transaction(&self, _t: &SignedTransaction, _header: &Header) -> Result<(), Error> { Ok(()) }
/// The network ID that transactions should be signed with. /// The network ID that transactions should be signed with.
fn signing_network_id(&self, _env_info: &EnvInfo) -> Option<u64> { None } fn signing_network_id(&self, _env_info: &EnvInfo) -> Option<u64> {
Some(self.params().chain_id)
}
/// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods /// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods
/// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer /// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer