PoA: Wait for transition finality before applying (#5774)
* final engine changes * migration to v13 * adding and removing pending transitions * epoch_transition_for * port snapshot to new engine methods * final validator set interface * fix compiler errors * revert v13/epoch_depth transition * make call on new epoch * rolling finality checker * tests for finality checker * constructing finality proof upon pending transition * fix warnings and finality proof checking * fix compiler warnings in tests * test fixes * don't include genesis in finality checking * change snapshot test chain building logic * minor refactorings * fetch epoch transition based on parent, fix divide-by-zero in SimpleList * fix formatting * fix ABIs and finality checking in snapshot restoration * encode signal number in proof * create more blocks at the end of tests * update gist to accurate contract code * test for epoch_transition_for * fix tests with immediateTransitions parameter * disable force flag after forcing * rename ValidatorsChanged to InitiateChange and finalizeSignal to finalizeChange * a few more validator set tests
This commit is contained in:
committed by
Arkadiy Paronyan
parent
3637c14da5
commit
d069b98b45
@@ -23,7 +23,7 @@ use account_provider::AccountProvider;
|
||||
use block::*;
|
||||
use builtin::Builtin;
|
||||
use spec::CommonParams;
|
||||
use engines::{Engine, EngineError, Seal, Call, EpochChange};
|
||||
use engines::{Engine, Seal, Call, ConstructedVerifier, EngineError};
|
||||
use error::{BlockError, Error};
|
||||
use evm::Schedule;
|
||||
use ethjson;
|
||||
@@ -51,12 +51,10 @@ impl From<ethjson::spec::BasicAuthorityParams> for BasicAuthorityParams {
|
||||
}
|
||||
|
||||
struct EpochVerifier {
|
||||
epoch_number: u64,
|
||||
list: SimpleList,
|
||||
}
|
||||
|
||||
impl super::EpochVerifier for EpochVerifier {
|
||||
fn epoch_number(&self) -> u64 { self.epoch_number.clone() }
|
||||
fn verify_light(&self, header: &Header) -> Result<(), Error> {
|
||||
verify_external(header, &self.list)
|
||||
}
|
||||
@@ -187,26 +185,54 @@ impl Engine for BasicAuthority {
|
||||
verify_external(header, &*self.validators)
|
||||
}
|
||||
|
||||
// the proofs we need just allow us to get the full validator set.
|
||||
fn epoch_proof(&self, header: &Header, caller: &Call) -> Result<Bytes, Error> {
|
||||
self.validators.epoch_proof(header, caller)
|
||||
.map_err(|e| EngineError::InsufficientProof(e).into())
|
||||
fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result<Vec<u8>, String> {
|
||||
self.validators.genesis_epoch_data(header, call)
|
||||
}
|
||||
|
||||
fn is_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> EpochChange
|
||||
#[cfg(not(test))]
|
||||
fn signals_epoch_end(&self, _header: &Header, _block: Option<&[u8]>, _receipts: Option<&[::receipt::Receipt]>)
|
||||
-> super::EpochChange
|
||||
{
|
||||
self.validators.is_epoch_end(header, block, receipts)
|
||||
// don't bother signalling even though a contract might try.
|
||||
super::EpochChange::No
|
||||
}
|
||||
|
||||
fn epoch_verifier(&self, header: &Header, proof: &[u8]) -> Result<Box<super::EpochVerifier>, Error> {
|
||||
// extract a simple list from the proof.
|
||||
let (num, simple_list) = self.validators.epoch_set(header, proof)?;
|
||||
#[cfg(test)]
|
||||
fn signals_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> super::EpochChange
|
||||
{
|
||||
// in test mode, always signal even though they don't be finalized.
|
||||
let first = header.number() == 0;
|
||||
self.validators.signals_epoch_end(first, header, block, receipts)
|
||||
}
|
||||
|
||||
Ok(Box::new(EpochVerifier {
|
||||
epoch_number: num,
|
||||
list: simple_list,
|
||||
}))
|
||||
fn is_epoch_end(
|
||||
&self,
|
||||
chain_head: &Header,
|
||||
_chain: &super::Headers,
|
||||
_transition_store: &super::PendingTransitionStore,
|
||||
) -> Option<Vec<u8>> {
|
||||
let first = chain_head.number() == 0;
|
||||
|
||||
// finality never occurs so only apply immediate transitions.
|
||||
self.validators.is_epoch_end(first, chain_head)
|
||||
}
|
||||
|
||||
fn epoch_verifier<'a>(&self, header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a> {
|
||||
let first = header.number() == 0;
|
||||
|
||||
match self.validators.epoch_set(first, self, header.number(), proof) {
|
||||
Ok((list, finalize)) => {
|
||||
let verifier = Box::new(EpochVerifier { list: list });
|
||||
|
||||
// our epoch verifier will ensure no unverified verifier is ever verified.
|
||||
match finalize {
|
||||
Some(finalize) => ConstructedVerifier::Unconfirmed(verifier, proof, finalize),
|
||||
None => ConstructedVerifier::Trusted(verifier),
|
||||
}
|
||||
}
|
||||
Err(e) => ConstructedVerifier::Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
fn register_client(&self, client: Weak<Client>) {
|
||||
@@ -222,7 +248,7 @@ impl Engine for BasicAuthority {
|
||||
}
|
||||
|
||||
fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> {
|
||||
Some(Box::new(::snapshot::PoaSnapshot))
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +318,7 @@ mod tests {
|
||||
let genesis_header = spec.genesis_header();
|
||||
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false).unwrap();
|
||||
let b = b.close_and_lock();
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b.block()) {
|
||||
assert!(b.try_seal(engine, seal).is_ok());
|
||||
|
||||
Reference in New Issue
Block a user