Fix replayer

This commit is contained in:
Pawan Dhananjay
2026-03-30 15:36:17 -07:00
parent 93d3343482
commit aa5292df99

View File

@@ -9,6 +9,7 @@ use crate::{
per_slot_processing, per_slot_processing,
}; };
use itertools::Itertools; use itertools::Itertools;
use std::collections::HashMap;
use std::iter::Peekable; use std::iter::Peekable;
use std::marker::PhantomData; use std::marker::PhantomData;
use types::{ use types::{
@@ -288,17 +289,11 @@ where
payload_envelopes: Vec<SignedExecutionPayloadEnvelope<E>>, payload_envelopes: Vec<SignedExecutionPayloadEnvelope<E>>,
target_slot: Option<Slot>, target_slot: Option<Slot>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let mut envelopes_iter = payload_envelopes.into_iter(); let mut envelopes_by_slot: HashMap<Slot, SignedExecutionPayloadEnvelope<E>> =
payload_envelopes
let mut next_envelope_at_slot = |slot| { .into_iter()
if let Some(envelope) = envelopes_iter.next() .map(|e| (e.message.slot, e))
&& envelope.message.slot == slot .collect();
{
Ok(envelope)
} else {
Err(BlockReplayError::MissingPayloadEnvelope { slot })
}
};
for (i, block) in blocks.iter().enumerate() { for (i, block) in blocks.iter().enumerate() {
// Allow one additional block at the start which is only used for its state root. // Allow one additional block at the start which is only used for its state root.
@@ -313,24 +308,41 @@ where
// indicates that the parent is full (and it hasn't already been applied). // indicates that the parent is full (and it hasn't already been applied).
state_root = if block.fork_name_unchecked().gloas_enabled() state_root = if block.fork_name_unchecked().gloas_enabled()
&& self.state.slot() == self.state.latest_block_header().slot && self.state.slot() == self.state.latest_block_header().slot
&& self.state.payload_status() == StatePayloadStatus::Pending
{ {
let latest_bid_block_hash = self if self.state.payload_status() == StatePayloadStatus::Pending {
.state let latest_bid_block_hash = self
.latest_execution_payload_bid() .state
.map_err(BlockReplayError::from)? .latest_execution_payload_bid()
.block_hash; .map_err(BlockReplayError::from)?
.block_hash;
// Similar to `is_parent_block_full`, but reading the block hash from the // Similar to `is_parent_block_full`, but reading the block hash from the
// not-yet-applied `block`. The slot 0 case covers genesis (no block replay reqd). // not-yet-applied `block`. The slot 0 case covers genesis (no block replay
if self.state.slot() != 0 && block.is_parent_block_full(latest_bid_block_hash) { // reqd).
let envelope = next_envelope_at_slot(self.state.slot())?; if self.state.slot() != 0
// State root for the next slot processing is now the envelope's state root. && block.is_parent_block_full(latest_bid_block_hash)
self.apply_payload_envelope(&envelope, state_root)? {
let envelope = envelopes_by_slot.remove(&self.state.slot()).ok_or(
BlockReplayError::MissingPayloadEnvelope {
slot: self.state.slot(),
},
)?;
// State root for the next slot processing is now the envelope's
// state root.
self.apply_payload_envelope(&envelope, state_root)?
} else {
// Empty payload at this slot, the state root is unchanged from
// when the beacon block was applied.
state_root
}
} else { } else {
// Empty payload at this slot, the state root is unchanged from when the // Full: the envelope was already applied. Use its state_root so
// beacon block was applied. // per_slot_processing stores the correct post-envelope root
state_root // (not the pre-envelope block state root).
envelopes_by_slot
.get(&self.state.slot())
.map(|e| e.message.state_root)
.unwrap_or(state_root)
} }
} else { } else {
// Pre-Gloas or at skipped slots post-Gloas, the state root of the parent state // Pre-Gloas or at skipped slots post-Gloas, the state root of the parent state
@@ -384,7 +396,11 @@ where
let mut opt_state_root = if let StatePayloadStatus::Full = self.desired_state_payload_status let mut opt_state_root = if let StatePayloadStatus::Full = self.desired_state_payload_status
&& let Some(last_block) = blocks.last() && let Some(last_block) = blocks.last()
{ {
let envelope = next_envelope_at_slot(self.state.slot())?; let envelope = envelopes_by_slot.remove(&self.state.slot()).ok_or(
BlockReplayError::MissingPayloadEnvelope {
slot: self.state.slot(),
},
)?;
Some(self.apply_payload_envelope(&envelope, last_block.state_root())?) Some(self.apply_payload_envelope(&envelope, last_block.state_root())?)
} else { } else {
None None