Fix attestation withdrawals root mismatch (#4249)

## Issue Addressed

Addresses #4234 

## Proposed Changes

- Skip withdrawals processing in an inconsistent state replay. 
- Repurpose `StateRootStrategy`: rename to `StateProcessingStrategy` and always skip withdrawals if using `StateProcessingStrategy::Inconsistent`
- Add a test to reproduce the scenario


Co-authored-by: Jimmy Chen <jimmy@sigmaprime.io>
This commit is contained in:
Jimmy Chen
2023-05-09 10:48:15 +00:00
parent c7c51062ab
commit 8d9c748025
16 changed files with 230 additions and 41 deletions

View File

@@ -29,7 +29,7 @@ pub struct BlockReplayer<
> {
state: BeaconState<Spec>,
spec: &'a ChainSpec,
state_root_strategy: StateRootStrategy,
state_processing_strategy: StateProcessingStrategy,
block_sig_strategy: BlockSignatureStrategy,
verify_block_root: Option<VerifyBlockRoot>,
pre_block_hook: Option<PreBlockHook<'a, Spec, Error>>,
@@ -60,13 +60,13 @@ impl From<BlockProcessingError> for BlockReplayError {
}
}
/// Defines how state roots should be computed during block replay.
#[derive(PartialEq)]
pub enum StateRootStrategy {
/// Defines how state roots should be computed and whether to perform all state transitions during block replay.
#[derive(PartialEq, Clone, Copy)]
pub enum StateProcessingStrategy {
/// Perform all transitions faithfully to the specification.
Accurate,
/// Don't compute state roots, eventually computing an invalid beacon state that can only be
/// used for obtaining shuffling.
/// Don't compute state roots and process withdrawals, eventually computing an invalid beacon
/// state that can only be used for obtaining shuffling.
Inconsistent,
}
@@ -87,7 +87,7 @@ where
Self {
state,
spec,
state_root_strategy: StateRootStrategy::Accurate,
state_processing_strategy: StateProcessingStrategy::Accurate,
block_sig_strategy: BlockSignatureStrategy::VerifyBulk,
verify_block_root: Some(VerifyBlockRoot::True),
pre_block_hook: None,
@@ -100,12 +100,15 @@ where
}
}
/// Set the replayer's state root strategy different from the default.
pub fn state_root_strategy(mut self, state_root_strategy: StateRootStrategy) -> Self {
if state_root_strategy == StateRootStrategy::Inconsistent {
/// Set the replayer's state processing strategy different from the default.
pub fn state_processing_strategy(
mut self,
state_processing_strategy: StateProcessingStrategy,
) -> Self {
if state_processing_strategy == StateProcessingStrategy::Inconsistent {
self.verify_block_root = None;
}
self.state_root_strategy = state_root_strategy;
self.state_processing_strategy = state_processing_strategy;
self
}
@@ -182,7 +185,7 @@ where
i: usize,
) -> Result<Option<Hash256>, Error> {
// If we don't care about state roots then return immediately.
if self.state_root_strategy == StateRootStrategy::Inconsistent {
if self.state_processing_strategy == StateProcessingStrategy::Inconsistent {
return Ok(Some(Hash256::zero()));
}
@@ -249,7 +252,7 @@ where
// If no explicit policy is set, verify only the first 1 or 2 block roots if using
// accurate state roots. Inaccurate state roots require block root verification to
// be off.
if i <= 1 && self.state_root_strategy == StateRootStrategy::Accurate {
if i <= 1 && self.state_processing_strategy == StateProcessingStrategy::Accurate {
VerifyBlockRoot::True
} else {
VerifyBlockRoot::False
@@ -263,6 +266,7 @@ where
&mut self.state,
block,
self.block_sig_strategy,
self.state_processing_strategy,
verify_block_root,
&mut ctxt,
self.spec,

View File

@@ -27,7 +27,7 @@ pub mod state_advance;
pub mod upgrade;
pub mod verify_operation;
pub use block_replayer::{BlockReplayError, BlockReplayer, StateRootStrategy};
pub use block_replayer::{BlockReplayError, BlockReplayer, StateProcessingStrategy};
pub use consensus_context::{ConsensusContext, ContextError};
pub use genesis::{
eth2_genesis_time, initialize_beacon_state_from_eth1, is_valid_genesis_state,

View File

@@ -39,6 +39,7 @@ mod verify_exit;
mod verify_proposer_slashing;
use crate::common::decrease_balance;
use crate::StateProcessingStrategy;
#[cfg(feature = "arbitrary-fuzz")]
use arbitrary::Arbitrary;
@@ -96,6 +97,7 @@ pub fn per_block_processing<T: EthSpec, Payload: AbstractExecPayload<T>>(
state: &mut BeaconState<T>,
signed_block: &SignedBeaconBlock<T, Payload>,
block_signature_strategy: BlockSignatureStrategy,
state_processing_strategy: StateProcessingStrategy,
verify_block_root: VerifyBlockRoot,
ctxt: &mut ConsensusContext<T>,
spec: &ChainSpec,
@@ -160,7 +162,9 @@ pub fn per_block_processing<T: EthSpec, Payload: AbstractExecPayload<T>>(
// previous block.
if is_execution_enabled(state, block.body()) {
let payload = block.body().execution_payload()?;
process_withdrawals::<T, Payload>(state, payload, spec)?;
if state_processing_strategy == StateProcessingStrategy::Accurate {
process_withdrawals::<T, Payload>(state, payload, spec)?;
}
process_execution_payload::<T, Payload>(state, payload, spec)?;
}

View File

@@ -1,11 +1,11 @@
#![cfg(all(test, not(feature = "fake_crypto")))]
use crate::per_block_processing;
use crate::per_block_processing::errors::{
AttestationInvalid, AttesterSlashingInvalid, BlockOperationError, BlockProcessingError,
DepositInvalid, HeaderInvalid, IndexedAttestationInvalid, IntoWithIndex,
ProposerSlashingInvalid,
};
use crate::{per_block_processing, StateProcessingStrategy};
use crate::{
per_block_processing::{process_operations, verify_exit::verify_exit},
BlockSignatureStrategy, ConsensusContext, VerifyBlockRoot, VerifySignatures,
@@ -72,6 +72,7 @@ async fn valid_block_ok() {
&mut state,
&block,
BlockSignatureStrategy::VerifyIndividual,
StateProcessingStrategy::Accurate,
VerifyBlockRoot::True,
&mut ctxt,
&spec,
@@ -97,6 +98,7 @@ async fn invalid_block_header_state_slot() {
&mut state,
&SignedBeaconBlock::from_block(block, signature),
BlockSignatureStrategy::VerifyIndividual,
StateProcessingStrategy::Accurate,
VerifyBlockRoot::True,
&mut ctxt,
&spec,
@@ -129,6 +131,7 @@ async fn invalid_parent_block_root() {
&mut state,
&SignedBeaconBlock::from_block(block, signature),
BlockSignatureStrategy::VerifyIndividual,
StateProcessingStrategy::Accurate,
VerifyBlockRoot::True,
&mut ctxt,
&spec,
@@ -162,6 +165,7 @@ async fn invalid_block_signature() {
&mut state,
&SignedBeaconBlock::from_block(block, Signature::empty()),
BlockSignatureStrategy::VerifyIndividual,
StateProcessingStrategy::Accurate,
VerifyBlockRoot::True,
&mut ctxt,
&spec,
@@ -195,6 +199,7 @@ async fn invalid_randao_reveal_signature() {
&mut state,
&signed_block,
BlockSignatureStrategy::VerifyIndividual,
StateProcessingStrategy::Accurate,
VerifyBlockRoot::True,
&mut ctxt,
&spec,