move execution pending envelolpe logic to its own file

This commit is contained in:
Eitan Seri- Levi
2026-02-24 12:08:07 -08:00
parent 30241f54c4
commit 2093dc1f39
3 changed files with 146 additions and 134 deletions

View File

@@ -0,0 +1,140 @@
use std::sync::Arc;
use slot_clock::SlotClock;
use state_processing::{
VerifySignatures,
envelope_processing::{VerifyStateRoot, process_execution_payload_envelope},
};
use types::{EthSpec, SignedExecutionPayloadEnvelope};
use crate::{
BeaconChain, BeaconChainError, BeaconChainTypes, NotifyExecutionLayer,
PayloadVerificationOutcome,
block_verification::PayloadVerificationHandle,
payload_envelope_verification::{
EnvelopeError, EnvelopeImportData, MaybeAvailableEnvelope,
gossip_verified_envelope::GossipVerifiedEnvelope, load_snapshot,
payload_notifier::PayloadNotifier,
},
};
pub trait IntoExecutionPendingEnvelope<T: BeaconChainTypes>: Sized {
fn into_execution_pending_envelope(
self,
chain: &Arc<BeaconChain<T>>,
notify_execution_layer: NotifyExecutionLayer,
) -> Result<ExecutionPendingEnvelope<T::EthSpec>, EnvelopeError>;
fn envelope(&self) -> &Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>;
}
pub struct ExecutionPendingEnvelope<E: EthSpec> {
pub signed_envelope: MaybeAvailableEnvelope<E>,
pub import_data: EnvelopeImportData<E>,
pub payload_verification_handle: PayloadVerificationHandle,
}
impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnvelope<T> {
fn into_execution_pending_envelope(
self,
chain: &Arc<BeaconChain<T>>,
notify_execution_layer: NotifyExecutionLayer,
) -> Result<ExecutionPendingEnvelope<T::EthSpec>, EnvelopeError> {
let signed_envelope = self.signed_envelope;
let envelope = &signed_envelope.message;
let payload = &envelope.payload;
// Verify the execution payload is valid
let payload_notifier = PayloadNotifier::new(
chain.clone(),
signed_envelope.clone(),
self.block.clone(),
notify_execution_layer,
)?;
let block_root = envelope.beacon_block_root;
let slot = self.block.slot();
let payload_verification_future = async move {
let chain = payload_notifier.chain.clone();
if let Some(started_execution) = chain.slot_clock.now_duration() {
chain
.envelope_times_cache
.write()
.set_time_started_execution(block_root, slot, started_execution);
}
let payload_verification_status = payload_notifier.notify_new_payload().await?;
Ok(PayloadVerificationOutcome {
payload_verification_status,
// This fork is after the merge so it'll never be the merge transition block
is_valid_merge_transition_block: false,
})
};
// Spawn the payload verification future as a new task, but don't wait for it to complete.
// The `payload_verification_future` will be awaited later to ensure verification completed
// successfully.
let payload_verification_handle = chain
.task_executor
.spawn_handle(
payload_verification_future,
"execution_payload_verification",
)
.ok_or(BeaconChainError::RuntimeShutdown)?;
let snapshot = if let Some(snapshot) = self.snapshot {
*snapshot
} else {
load_snapshot(
signed_envelope.as_ref(),
&chain.canonical_head,
&chain.store,
)?
};
let mut state = snapshot.pre_state;
// All the state modifications are done in envelope_processing
process_execution_payload_envelope(
&mut state,
Some(snapshot.state_root),
&signed_envelope,
// verify signature already done for GossipVerifiedEnvelope
VerifySignatures::False,
VerifyStateRoot::True,
&chain.spec,
)?;
Ok(ExecutionPendingEnvelope {
signed_envelope: MaybeAvailableEnvelope::AvailabilityPending {
block_hash: payload.block_hash,
envelope: signed_envelope,
},
import_data: EnvelopeImportData {
block_root,
block: self.block,
post_state: Box::new(state),
},
payload_verification_handle,
})
}
fn envelope(&self) -> &Arc<SignedExecutionPayloadEnvelope<T::EthSpec>> {
&self.signed_envelope
}
}
impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T>
for Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>
{
fn into_execution_pending_envelope(
self,
chain: &Arc<BeaconChain<T>>,
notify_execution_layer: NotifyExecutionLayer,
) -> Result<ExecutionPendingEnvelope<T::EthSpec>, EnvelopeError> {
GossipVerifiedEnvelope::new(self, &chain.gossip_verification_context())?
.into_execution_pending_envelope(chain, notify_execution_layer)
}
fn envelope(&self) -> &Arc<SignedExecutionPayloadEnvelope<T::EthSpec>> {
self
}
}

View File

@@ -2,11 +2,6 @@ use std::sync::Arc;
use educe::Educe;
use parking_lot::{Mutex, RwLock};
use slot_clock::SlotClock;
use state_processing::{
VerifySignatures,
envelope_processing::{VerifyStateRoot, process_execution_payload_envelope},
};
use store::DatabaseBlock;
use tracing::{Span, debug};
use types::{
@@ -15,14 +10,11 @@ use types::{
};
use crate::{
BeaconChain, BeaconChainError, BeaconChainTypes, BeaconStore, NotifyExecutionLayer,
PayloadVerificationOutcome,
BeaconChain, BeaconChainError, BeaconChainTypes, BeaconStore,
beacon_proposer_cache::{self, BeaconProposerCache},
canonical_head::CanonicalHead,
payload_envelope_verification::{
EnvelopeError, EnvelopeImportData, EnvelopeProcessingSnapshot, ExecutionPendingEnvelope,
IntoExecutionPendingEnvelope, MaybeAvailableEnvelope, load_snapshot,
load_snapshot_from_state_root, payload_notifier::PayloadNotifier,
EnvelopeError, EnvelopeProcessingSnapshot, load_snapshot_from_state_root,
},
validator_pubkey_cache::ValidatorPubkeyCache,
};
@@ -234,94 +226,6 @@ impl<T: BeaconChainTypes> GossipVerifiedEnvelope<T> {
}
}
impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnvelope<T> {
fn into_execution_pending_envelope(
self,
chain: &Arc<BeaconChain<T>>,
notify_execution_layer: NotifyExecutionLayer,
) -> Result<ExecutionPendingEnvelope<T::EthSpec>, EnvelopeError> {
let signed_envelope = self.signed_envelope;
let envelope = &signed_envelope.message;
let payload = &envelope.payload;
// Verify the execution payload is valid
let payload_notifier = PayloadNotifier::new(
chain.clone(),
signed_envelope.clone(),
self.block.clone(),
notify_execution_layer,
)?;
let block_root = envelope.beacon_block_root;
let slot = self.block.slot();
let payload_verification_future = async move {
let chain = payload_notifier.chain.clone();
if let Some(started_execution) = chain.slot_clock.now_duration() {
chain
.envelope_times_cache
.write()
.set_time_started_execution(block_root, slot, started_execution);
}
let payload_verification_status = payload_notifier.notify_new_payload().await?;
Ok(PayloadVerificationOutcome {
payload_verification_status,
// This fork is after the merge so it'll never be the merge transition block
is_valid_merge_transition_block: false,
})
};
// Spawn the payload verification future as a new task, but don't wait for it to complete.
// The `payload_verification_future` will be awaited later to ensure verification completed
// successfully.
let payload_verification_handle = chain
.task_executor
.spawn_handle(
payload_verification_future,
"execution_payload_verification",
)
.ok_or(BeaconChainError::RuntimeShutdown)?;
let snapshot = if let Some(snapshot) = self.snapshot {
*snapshot
} else {
load_snapshot(
signed_envelope.as_ref(),
&chain.canonical_head,
&chain.store,
)?
};
let mut state = snapshot.pre_state;
// All the state modifications are done in envelope_processing
process_execution_payload_envelope(
&mut state,
Some(snapshot.state_root),
&signed_envelope,
// verify signature already done for GossipVerifiedEnvelope
VerifySignatures::False,
VerifyStateRoot::True,
&chain.spec,
)?;
Ok(ExecutionPendingEnvelope {
signed_envelope: MaybeAvailableEnvelope::AvailabilityPending {
block_hash: payload.block_hash,
envelope: signed_envelope,
},
import_data: EnvelopeImportData {
block_root,
block: self.block,
post_state: Box::new(state),
},
payload_verification_handle,
})
}
fn envelope(&self) -> &Arc<SignedExecutionPayloadEnvelope<T::EthSpec>> {
&self.signed_envelope
}
}
impl<T: BeaconChainTypes> BeaconChain<T> {
/// Build a `GossipVerificationContext` from this `BeaconChain`.
pub fn gossip_verification_context(&self) -> GossipVerificationContext<'_, T> {

View File

@@ -39,31 +39,16 @@ use types::{
};
use crate::{
BeaconChain, BeaconChainError, BeaconChainTypes, BeaconStore, BlockError,
ExecutionPayloadError, NotifyExecutionLayer, PayloadVerificationOutcome,
block_verification::PayloadVerificationHandle, canonical_head::CanonicalHead,
payload_envelope_verification::gossip_verified_envelope::GossipVerifiedEnvelope,
BeaconChainError, BeaconChainTypes, BeaconStore, BlockError, ExecutionPayloadError,
PayloadVerificationOutcome, canonical_head::CanonicalHead,
};
pub mod execution_pending_envelope;
pub mod gossip_verified_envelope;
pub mod import;
mod payload_notifier;
pub trait IntoExecutionPendingEnvelope<T: BeaconChainTypes>: Sized {
fn into_execution_pending_envelope(
self,
chain: &Arc<BeaconChain<T>>,
notify_execution_layer: NotifyExecutionLayer,
) -> Result<ExecutionPendingEnvelope<T::EthSpec>, EnvelopeError>;
fn envelope(&self) -> &Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>;
}
pub struct ExecutionPendingEnvelope<E: EthSpec> {
pub signed_envelope: MaybeAvailableEnvelope<E>,
pub import_data: EnvelopeImportData<E>,
pub payload_verification_handle: PayloadVerificationHandle,
}
pub use execution_pending_envelope::{ExecutionPendingEnvelope, IntoExecutionPendingEnvelope};
#[derive(PartialEq)]
pub struct EnvelopeImportData<E: EthSpec> {
@@ -348,20 +333,3 @@ pub(crate) fn load_snapshot<T: BeaconChainTypes>(
load_snapshot_from_state_root::<T>(beacon_block_root, proto_beacon_block.state_root, store)
}
impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T>
for Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>
{
fn into_execution_pending_envelope(
self,
chain: &Arc<BeaconChain<T>>,
notify_execution_layer: NotifyExecutionLayer,
) -> Result<ExecutionPendingEnvelope<T::EthSpec>, EnvelopeError> {
GossipVerifiedEnvelope::new(self, &chain.gossip_verification_context())?
.into_execution_pending_envelope(chain, notify_execution_layer)
}
fn envelope(&self) -> &Arc<SignedExecutionPayloadEnvelope<T::EthSpec>> {
self
}
}