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

@@ -30,7 +30,7 @@ use slog::{debug, error, info, trace, warn, Logger};
use ssz::{Decode, Encode};
use ssz_derive::{Decode, Encode};
use state_processing::{
BlockProcessingError, BlockReplayer, SlotProcessingError, StateRootStrategy,
BlockProcessingError, BlockReplayer, SlotProcessingError, StateProcessingStrategy,
};
use std::cmp::min;
use std::convert::TryInto;
@@ -531,10 +531,10 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
// chain. This way we avoid returning a state that doesn't match `state_root`.
self.load_cold_state(state_root)
} else {
self.load_hot_state(state_root, StateRootStrategy::Accurate)
self.load_hot_state(state_root, StateProcessingStrategy::Accurate)
}
} else {
match self.load_hot_state(state_root, StateRootStrategy::Accurate)? {
match self.load_hot_state(state_root, StateProcessingStrategy::Accurate)? {
Some(state) => Ok(Some(state)),
None => self.load_cold_state(state_root),
}
@@ -572,7 +572,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
}
.into())
} else {
self.load_hot_state(state_root, StateRootStrategy::Inconsistent)
self.load_hot_state(state_root, StateProcessingStrategy::Inconsistent)
}
}
@@ -662,10 +662,13 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
{
// NOTE: minor inefficiency here because we load an unnecessary hot state summary
//
// `StateRootStrategy` should be irrelevant here since we never replay blocks for an epoch
// `StateProcessingStrategy` should be irrelevant here since we never replay blocks for an epoch
// boundary state in the hot DB.
let state = self
.load_hot_state(&epoch_boundary_state_root, StateRootStrategy::Accurate)?
.load_hot_state(
&epoch_boundary_state_root,
StateProcessingStrategy::Accurate,
)?
.ok_or(HotColdDBError::MissingEpochBoundaryState(
epoch_boundary_state_root,
))?;
@@ -834,7 +837,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
pub fn load_hot_state(
&self,
state_root: &Hash256,
state_root_strategy: StateRootStrategy,
state_processing_strategy: StateProcessingStrategy,
) -> Result<Option<BeaconState<E>>, Error> {
metrics::inc_counter(&metrics::BEACON_STATE_HOT_GET_COUNT);
@@ -867,7 +870,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
blocks,
slot,
no_state_root_iter(),
state_root_strategy,
state_processing_strategy,
)?
};
@@ -1038,7 +1041,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
blocks,
slot,
Some(state_root_iter),
StateRootStrategy::Accurate,
StateProcessingStrategy::Accurate,
)?;
// If state is not error, put it in the cache.
@@ -1130,10 +1133,10 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
blocks: Vec<SignedBeaconBlock<E, BlindedPayload<E>>>,
target_slot: Slot,
state_root_iter: Option<impl Iterator<Item = Result<(Hash256, Slot), Error>>>,
state_root_strategy: StateRootStrategy,
state_processing_strategy: StateProcessingStrategy,
) -> Result<BeaconState<E>, Error> {
let mut block_replayer = BlockReplayer::new(state, &self.spec)
.state_root_strategy(state_root_strategy)
.state_processing_strategy(state_processing_strategy)
.no_signature_verification()
.minimal_block_root_verification();

View File

@@ -5,7 +5,7 @@ use itertools::{process_results, Itertools};
use slog::info;
use state_processing::{
per_block_processing, per_slot_processing, BlockSignatureStrategy, ConsensusContext,
VerifyBlockRoot,
StateProcessingStrategy, VerifyBlockRoot,
};
use std::sync::Arc;
use types::{EthSpec, Hash256};
@@ -96,6 +96,7 @@ where
&mut state,
&block,
BlockSignatureStrategy::NoVerification,
StateProcessingStrategy::Accurate,
VerifyBlockRoot::True,
&mut ctxt,
&self.spec,