All tests bar invalid_message passing, changes might be dubious

This commit is contained in:
Michael Sproul
2026-05-13 09:26:27 +10:00
parent e9ae5babc8
commit 715d6bfa0c
6 changed files with 230 additions and 103 deletions

View File

@@ -48,6 +48,9 @@
// returned alongside.
#![allow(clippy::result_large_err)]
use crate::attestation_verification::{
Error as AttestationVerificationError, obtain_indexed_attestation_and_committees_per_slot,
};
use crate::beacon_snapshot::PreProcessingSnapshot;
use crate::blob_verification::GossipBlobError;
use crate::block_verification_types::{AsBlock, BlockImportData, LookupBlock, RangeSyncBlock};
@@ -1648,6 +1651,18 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
* free real estate.
*/
let current_slot = chain.slot()?;
let mut indexed_attestations = vec![];
for attestation in block.message().body().attestations() {
match obtain_indexed_attestation_and_committees_per_slot(chain, attestation) {
Ok((indexed_attestation, _)) => indexed_attestations.push(indexed_attestation),
Err(AttestationVerificationError::BeaconChainError(e)) => {
return Err(BlockError::BeaconChainError(e));
}
// Ignore invalid attestations whilst importing attestations from a block. The
// block might be very old and therefore the attestations useless to fork choice.
Err(_) => {}
}
}
let mut fork_choice = chain.canonical_head.fork_choice_write_lock();
// Register each attester slashing in the block with fork choice.
@@ -1656,14 +1671,10 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
}
// Register each attestation in the block with fork choice.
for (i, attestation) in block.message().body().attestations().enumerate() {
let indexed_attestation = consensus_context
.get_indexed_attestation(&state, attestation)
.map_err(|e| BlockError::PerBlockProcessingError(e.into_with_index(i)))?;
for indexed_attestation in indexed_attestations {
match fork_choice.on_attestation(
current_slot,
indexed_attestation,
indexed_attestation.to_ref(),
AttestationFromBlock::True,
&chain.spec,
) {

View File

@@ -8,12 +8,10 @@ use bls::AggregateSignature;
use educe::Educe;
use eth2::types::{EventKind, ForkVersionedResponse};
use parking_lot::RwLock;
use safe_arith::SafeArith;
use slot_clock::SlotClock;
use state_processing::per_block_processing::signature_sets::indexed_payload_attestation_signature_set;
use state_processing::state_advance::partial_state_advance;
use std::borrow::Cow;
use types::{ChainSpec, EthSpec, IndexedPayloadAttestation, PTC, PayloadAttestationMessage, Slot};
use types::{ChainSpec, IndexedPayloadAttestation, PTC, PayloadAttestationMessage, Slot};
pub struct GossipVerificationContext<'a, T: BeaconChainTypes> {
pub slot_clock: &'a T::SlotClock,
@@ -67,62 +65,26 @@ impl<T: BeaconChainTypes> VerifiedPayloadAttestationMessage<T> {
// 2. Blocks we've seen that are invalid (REJECT).
// Presently both cases return IGNORE.
let beacon_block_root = payload_attestation_message.data.beacon_block_root;
if ctx
let Some(block) = ctx
.canonical_head
.fork_choice_read_lock()
.get_block(&beacon_block_root)
.is_none()
{
else {
return Err(Error::UnknownHeadBlock { beacon_block_root });
}
// Get head state for PTC computation. If the cached head state is too stale
// (e.g. during liveness failures with many skipped slots), fall back to loading
// a more recent state from the store and advancing it if necessary.
let head = ctx.canonical_head.cached_head();
let head_state = &head.snapshot.beacon_state;
let message_epoch = slot.epoch(T::EthSpec::slots_per_epoch());
let state_epoch = head_state.current_epoch();
// get_ptc can serve epochs in [state_epoch - 1, state_epoch + min_seed_lookahead].
// If the message epoch is beyond that range, the head state is stale.
let advanced_state = if message_epoch
> state_epoch
.safe_add(ctx.spec.min_seed_lookahead)
.map_err(BeaconChainError::from)?
{
let head_block_root = head.head_block_root();
let target_slot = message_epoch.start_slot(T::EthSpec::slots_per_epoch());
let (state_root, mut state) = ctx
.store
.get_advanced_hot_state(
head_block_root,
target_slot,
head.snapshot.beacon_state_root(),
)
.map_err(BeaconChainError::from)?
.ok_or(BeaconChainError::MissingBeaconState(
head.snapshot.beacon_state_root(),
))?;
if state
.current_epoch()
.safe_add(ctx.spec.min_seed_lookahead)
.map_err(BeaconChainError::from)?
< message_epoch
{
partial_state_advance(&mut state, Some(state_root), target_slot, ctx.spec)
.map_err(BeaconChainError::from)?;
}
Some(state)
} else {
None
};
let state = advanced_state.as_ref().unwrap_or(head_state);
// Spec: use `store.block_states[data.beacon_block_root]` to derive the PTC for this
// payload attestation. The canonical head can be on a different branch.
let state = ctx
.store
.get_hot_state(&block.state_root, true)
.map_err(BeaconChainError::from)?
.ok_or_else(|| {
BeaconChainError::DBInconsistent(format!(
"Missing state for payload attestation block {:?}",
block.state_root
))
})?;
// [REJECT] `validator_index` is within `get_ptc(state, data.slot)`.
let ptc = state.get_ptc(slot, ctx.spec)?;
@@ -146,7 +108,7 @@ impl<T: BeaconChainTypes> VerifiedPayloadAttestationMessage<T> {
// [REJECT] The signature is valid with respect to the `validator_index`.
let pubkey_cache = ctx.validator_pubkey_cache.read();
let signature_set = indexed_payload_attestation_signature_set(
state,
&state,
|validator_index| pubkey_cache.get(validator_index).map(Cow::Borrowed),
&indexed_payload_attestation.signature,
&indexed_payload_attestation,