Include the seal when populating the header for a new block (#11475)

* debug signer

* Don't panic if empty_steps_transition already happened

Before this the `header_empty_steps_raw` would panic if the chain has already progressed beyond the block number set in `emptyStepsTransition`. As this is a user accessible configuration option I don't think we should panic.

* Cleanup some code in Aura

Nothing really interesting here, renames or removes some methods. Adds some docs and extends a test a bit to clarify the behaviour of the code.

* Include the seal when populating the header for a new block (fixes #11445)

* cleanup

* cleanup2

* Review grumbles

* Update ethcore/engines/authority-round/src/lib.rs

Co-Authored-By: André Silva <andre.beat@gmail.com>

* Update ethcore/engines/authority-round/src/lib.rs

Co-Authored-By: André Silva <andre.beat@gmail.com>

* Update ethcore/src/block.rs

Co-Authored-By: André Silva <andre.beat@gmail.com>

Co-authored-by: André Silva <andre.beat@gmail.com>
This commit is contained in:
David 2020-02-14 19:01:17 +01:00 committed by GitHub
parent ea9322f9c1
commit 856a075588
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 13 deletions

View File

@ -720,17 +720,22 @@ fn header_signature(header: &Header, empty_steps_transition: u64) -> Result<Sign
.as_val::<H520>().map(Into::into) .as_val::<H520>().map(Into::into)
} }
// extracts the raw empty steps vec from the header seal. should only be called when there are 3 fields in the seal // Extracts the RLP bytes of the empty steps from the header seal. Returns data only when there are
// (i.e. header.number() >= self.empty_steps_transition) // 3 fields in the seal. (i.e. header.number() >= self.empty_steps_transition).
fn header_empty_steps_raw(header: &Header) -> &[u8] { fn header_empty_steps_raw(header: &Header) -> Option<&[u8]> {
header.seal().get(2).expect("was checked with verify_block_basic; has 3 fields; qed") header.seal().get(2).map(Vec::as_slice)
} }
// extracts the empty steps from the header seal. should only be called when there are 3 fields in the seal // Extracts the empty steps from the header seal. Returns data only when there are 3 fields in the seal
// (i.e. header.number() >= self.empty_steps_transition). // (i.e. header.number() >= self.empty_steps_transition).
fn header_empty_steps(header: &Header) -> Result<Vec<EmptyStep>, ::rlp::DecoderError> { fn header_empty_steps(header: &Header) -> Result<Vec<EmptyStep>, ::rlp::DecoderError> {
let empty_steps = Rlp::new(header_empty_steps_raw(header)).as_list::<SealedEmptyStep>()?; header_empty_steps_raw(header).map_or(Ok(vec![]), |raw| {
Ok(empty_steps.into_iter().map(|s| EmptyStep::from_sealed(s, header.parent_hash())).collect()) let empty_steps = Rlp::new(raw).as_list::<SealedEmptyStep>()?;
Ok(empty_steps
.into_iter()
.map(|s| EmptyStep::from_sealed(s, header.parent_hash()))
.collect())
})
} }
// gets the signers of empty step messages for the given header, does not include repeated signers // gets the signers of empty step messages for the given header, does not include repeated signers
@ -788,7 +793,7 @@ fn verify_external(header: &Header, validators: &dyn ValidatorSet, empty_steps_t
let correct_proposer = validators.get(header.parent_hash(), header_step as usize); let correct_proposer = validators.get(header.parent_hash(), header_step as usize);
let is_invalid_proposer = *header.author() != correct_proposer || { let is_invalid_proposer = *header.author() != correct_proposer || {
let empty_steps_rlp = if header.number() >= empty_steps_transition { let empty_steps_rlp = if header.number() >= empty_steps_transition {
Some(header_empty_steps_raw(header)) header_empty_steps_raw(header)
} else { } else {
None None
}; };
@ -970,11 +975,15 @@ impl AuthorityRound {
/// Drops all `EmptySteps` less than or equal to the passed `step`, irregardless of the parent hash. /// Drops all `EmptySteps` less than or equal to the passed `step`, irregardless of the parent hash.
fn clear_empty_steps(&self, step: u64) { fn clear_empty_steps(&self, step: u64) {
let mut empty_steps = self.empty_steps.lock(); let mut empty_steps = self.empty_steps.lock();
*empty_steps = empty_steps.split_off(&EmptyStep { if empty_steps.is_empty() {
return;
}
let next_empty_steps = empty_steps.split_off(&EmptyStep {
step: step + 1, step: step + 1,
parent_hash: Default::default(), parent_hash: Default::default(),
signature: Default::default(), signature: Default::default(),
}); });
*empty_steps = next_empty_steps
} }
fn store_empty_step(&self, empty_step: EmptyStep) { fn store_empty_step(&self, empty_step: EmptyStep) {
@ -3013,9 +3022,10 @@ mod tests {
let params = AuthorityRoundParams::from(deserialized.params); let params = AuthorityRoundParams::from(deserialized.params);
for ((block_num1, address1), (block_num2, address2)) in for ((block_num1, address1), (block_num2, address2)) in
params.block_reward_contract_transitions.iter().zip( params.block_reward_contract_transitions.iter().zip(
[(0u64, BlockRewardContract::new_from_address(Address::from_str("2000000000000000000000000000000000000002").unwrap())), [
(7u64, BlockRewardContract::new_from_address(Address::from_str("3000000000000000000000000000000000000003").unwrap())), (0u64, BlockRewardContract::new_from_address(Address::from_str("2000000000000000000000000000000000000002").unwrap())),
(42u64, BlockRewardContract::new_from_address(Address::from_str("4000000000000000000000000000000000000004").unwrap())), (7u64, BlockRewardContract::new_from_address(Address::from_str("3000000000000000000000000000000000000003").unwrap())),
(42u64, BlockRewardContract::new_from_address(Address::from_str("4000000000000000000000000000000000000004").unwrap())),
].iter()) ].iter())
{ {
assert_eq!(block_num1, block_num2); assert_eq!(block_num1, block_num2);

View File

@ -222,6 +222,10 @@ impl<'x> OpenBlock<'x> {
self.block.header.set_timestamp(header.timestamp()); self.block.header.set_timestamp(header.timestamp());
self.block.header.set_uncles_hash(*header.uncles_hash()); self.block.header.set_uncles_hash(*header.uncles_hash());
self.block.header.set_transactions_root(*header.transactions_root()); self.block.header.set_transactions_root(*header.transactions_root());
// For Aura-based chains, the seal may contain EmptySteps which are used to bestow rewards;
// such rewards affect the state and the state root (see
// https://github.com/paritytech/parity-ethereum/pull/11475).
self.block.header.set_seal(header.seal().to_vec());
// TODO: that's horrible. set only for backwards compatibility // TODO: that's horrible. set only for backwards compatibility
if header.extra_data().len() > self.engine.maximum_extra_data_size() { if header.extra_data().len() > self.engine.maximum_extra_data_size() {
warn!("Couldn't set extradata. Ignoring."); warn!("Couldn't set extradata. Ignoring.");
@ -554,7 +558,7 @@ mod tests {
b.close_and_lock() b.close_and_lock()
} }
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block afterwards
fn enact_and_seal( fn enact_and_seal(
block_bytes: Vec<u8>, block_bytes: Vec<u8>,
engine: &dyn Engine, engine: &dyn Engine,

View File

@ -492,6 +492,7 @@ fn execute_impl<Cr, Rr>(
let fetch = fetch::Client::new(FETCH_FULL_NUM_DNS_THREADS).map_err(|e| format!("Error starting fetch client: {:?}", e))?; let fetch = fetch::Client::new(FETCH_FULL_NUM_DNS_THREADS).map_err(|e| format!("Error starting fetch client: {:?}", e))?;
let txpool_size = cmd.miner_options.pool_limits.max_count; let txpool_size = cmd.miner_options.pool_limits.max_count;
// create miner // create miner
let miner = Arc::new(Miner::new( let miner = Arc::new(Miner::new(
cmd.miner_options, cmd.miner_options,
@ -502,6 +503,7 @@ fn execute_impl<Cr, Rr>(
account_utils::miner_local_accounts(account_provider.clone()), account_utils::miner_local_accounts(account_provider.clone()),
) )
)); ));
miner.set_author(miner::Author::External(cmd.miner_extras.author)); miner.set_author(miner::Author::External(cmd.miner_extras.author));
miner.set_gas_range_target(cmd.miner_extras.gas_range_target); miner.set_gas_range_target(cmd.miner_extras.gas_range_target);
miner.set_extra_data(cmd.miner_extras.extra_data); miner.set_extra_data(cmd.miner_extras.extra_data);