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

Commit

Permalink
PoA: Wait for transition finality before applying (#5774)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
rphmeier authored and arkpar committed Jun 28, 2017
1 parent 3637c14 commit d069b98
Show file tree
Hide file tree
Showing 41 changed files with 1,907 additions and 806 deletions.
2 changes: 1 addition & 1 deletion ethcore/native_contracts/build.rs
Expand Up @@ -28,7 +28,7 @@ const SECRETSTORE_ACL_STORAGE_ABI: &'static str = include_str!("res/secretstore_
const VALIDATOR_SET_ABI: &'static str = include_str!("res/validator_set.json");
const VALIDATOR_REPORT_ABI: &'static str = include_str!("res/validator_report.json");

const TEST_VALIDATOR_SET_ABI: &'static str = r#"[{"constant":true,"inputs":[],"name":"transitionNonce","outputs":[{"name":"n","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newValidators","type":"address[]"}],"name":"setValidators","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"vals","type":"address[]"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_parent_hash","type":"bytes32"},{"indexed":true,"name":"_nonce","type":"uint256"},{"indexed":false,"name":"_new_set","type":"address[]"}],"name":"ValidatorsChanged","type":"event"}]"#;
const TEST_VALIDATOR_SET_ABI: &'static str = include_str!("res/test_validator_set.json");

fn build_file(name: &str, abi: &str, filename: &str) {
let code = ::native_contract_generator::generate_module(name, abi).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion ethcore/native_contracts/generator/src/lib.rs
Expand Up @@ -108,7 +108,7 @@ fn generate_functions(contract: &Contract) -> Result<String, Error> {
/// Outputs: {abi_outputs:?}
pub fn {snake_name}<F, U>(&self, call: F, {params}) -> BoxFuture<{output_type}, String>
where
F: Fn(util::Address, Vec<u8>) -> U,
F: FnOnce(util::Address, Vec<u8>) -> U,
U: IntoFuture<Item=Vec<u8>, Error=String>,
U::Future: Send + 'static
{{
Expand Down
8 changes: 8 additions & 0 deletions ethcore/native_contracts/res/test_validator_set.json
@@ -0,0 +1,8 @@
[
{"constant":false,"inputs":[{"name":"_validators","type":"address[]"}],"name":"setValidators","outputs":[],"payable":false,"type":"function"},
{"constant":false,"inputs":[{"name":"","type":"address"},{"name":"","type":"bytes"}],"name":"reportMalicious","outputs":[],"payable":false,"type":"function"},
{"constant":false,"inputs":[],"name":"finalizeChange","outputs":[],"payable":false,"type":"function"},
{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"_validators","type":"address[]"}],"payable":false,"type":"function"},
{"constant":false,"inputs":[{"name":"","type":"address"}],"name":"reportBenign","outputs":[],"payable":false,"type":"function"},
{"anonymous":false,"inputs":[{"indexed":true,"name":"_parent_hash","type":"bytes32"},{"indexed":false,"name":"_new_set","type":"address[]"}],"name":"InitiateChange","type":"event"}
]
4 changes: 2 additions & 2 deletions ethcore/native_contracts/res/validator_set.json
@@ -1,5 +1,5 @@
[
{"constant":true,"inputs":[],"name":"transitionNonce","outputs":[{"name":"nonce","type":"uint256"}],"payable":false,"type":"function"},
{"constant":false,"inputs":[],"name":"finalizeChange","outputs":[],"payable":false,"type":"function"},
{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"validators","type":"address[]"}],"payable":false,"type":"function"},
{"anonymous":false,"inputs":[{"indexed":true,"name":"_parent_hash","type":"bytes32"},{"indexed":true,"name":"_nonce","type":"uint256"},{"indexed":false,"name":"_new_set","type":"address[]"}],"name":"ValidatorsChanged","type":"event"}
{"anonymous":false,"inputs":[{"indexed":true,"name":"_parent_hash","type":"bytes32"},{"indexed":false,"name":"_new_set","type":"address[]"}],"name":"InitiateChange","type":"event"}
]
3 changes: 2 additions & 1 deletion ethcore/res/authority_round.json
Expand Up @@ -11,7 +11,8 @@
"0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e",
"0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1"
]
}
},
"immediateTransitions": true
}
}
},
Expand Down
3 changes: 2 additions & 1 deletion ethcore/res/validator_contract.json
Expand Up @@ -8,7 +8,8 @@
"startStep": 2,
"validators": {
"contract": "0x0000000000000000000000000000000000000005"
}
},
"immediateTransitions": true
}
}
},
Expand Down
44 changes: 36 additions & 8 deletions ethcore/src/block.rs
Expand Up @@ -260,6 +260,7 @@ impl<'x> OpenBlock<'x> {
author: Address,
gas_range_target: (U256, U256),
extra_data: Bytes,
is_epoch_begin: bool,
) -> Result<Self, Error> {
let number = parent.number() + 1;
let state = State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce(number), factories)?;
Expand All @@ -279,7 +280,8 @@ impl<'x> OpenBlock<'x> {
let gas_floor_target = cmp::max(gas_range_target.0, engine.params().min_gas_limit);
let gas_ceil_target = cmp::max(gas_range_target.1, gas_floor_target);
engine.populate_from_parent(&mut r.block.header, parent, gas_floor_target, gas_ceil_target);
engine.on_new_block(&mut r.block, last_hashes)?;
engine.on_new_block(&mut r.block, last_hashes, is_epoch_begin)?;

Ok(r)
}

Expand Down Expand Up @@ -430,7 +432,7 @@ impl<'x> OpenBlock<'x> {

#[cfg(test)]
/// Return mutable block reference. To be used in tests only.
pub fn block_mut (&mut self) -> &mut ExecutedBlock { &mut self.block }
pub fn block_mut(&mut self) -> &mut ExecutedBlock { &mut self.block }
}

impl<'x> IsBlock for OpenBlock<'x> {
Expand Down Expand Up @@ -554,6 +556,7 @@ pub fn enact(
parent: &Header,
last_hashes: Arc<LastHashes>,
factories: Factories,
is_epoch_begin: bool,
) -> Result<LockedBlock, Error> {
{
if ::log::max_log_level() >= ::log::LogLevel::Trace {
Expand All @@ -563,7 +566,19 @@ pub fn enact(
}
}

let mut b = OpenBlock::new(engine, factories, tracing, db, parent, last_hashes, Address::new(), (3141562.into(), 31415620.into()), vec![])?;
let mut b = OpenBlock::new(
engine,
factories,
tracing,
db,
parent,
last_hashes,
Address::new(),
(3141562.into(), 31415620.into()),
vec![],
is_epoch_begin,
)?;

b.set_difficulty(*header.difficulty());
b.set_gas_limit(*header.gas_limit());
b.set_timestamp(header.timestamp());
Expand Down Expand Up @@ -618,9 +633,22 @@ pub fn enact_verified(
parent: &Header,
last_hashes: Arc<LastHashes>,
factories: Factories,
is_epoch_begin: bool,
) -> Result<LockedBlock, Error> {
let view = BlockView::new(&block.bytes);
enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes, factories)

enact(
&block.header,
&block.transactions,
&view.uncles(),
engine,
tracing,
db,
parent,
last_hashes,
factories,
is_epoch_begin,
)
}

#[cfg(test)]
Expand Down Expand Up @@ -653,7 +681,7 @@ mod tests {
let header = block.header();
let transactions: Result<Vec<_>, Error> = block.transactions().into_iter().map(SignedTransaction::new).collect();
let transactions = transactions?;
enact(&header, &transactions, &block.uncles(), engine, tracing, db, parent, last_hashes, factories)
enact(&header, &transactions, &block.uncles(), engine, tracing, db, parent, last_hashes, factories, false)
}

/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
Expand All @@ -678,7 +706,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(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap();
let b = b.close_and_lock();
let _ = b.seal(&*spec.engine, vec![]);
}
Expand All @@ -692,7 +720,7 @@ mod tests {

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.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap()
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap()
.close_and_lock().seal(engine, vec![]).unwrap();
let orig_bytes = b.rlp_bytes();
let orig_db = b.drain();
Expand All @@ -716,7 +744,7 @@ mod tests {

let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap();
let mut uncle1_header = Header::new();
uncle1_header.set_extra_data(b"uncle1".to_vec());
let mut uncle2_header = Header::new();
Expand Down

0 comments on commit d069b98

Please sign in to comment.