mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-17 20:02:43 +00:00
Import payload flow
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
use task_executor::JoinHandle;
|
||||
use types::{EthSpec, FullPayload};
|
||||
|
||||
use crate::{
|
||||
BeaconChainTypes, PayloadVerificationOutcome,
|
||||
payload_envelope_verification::{MaybeAvailableEnvelope, PayloadEnvelopeImportData},
|
||||
};
|
||||
|
||||
/// Used to await the result of executing payload with an EE.
|
||||
pub type PayloadVerificationHandle<E: EthSpec> =
|
||||
JoinHandle<Option<Result<PayloadVerificationOutcome, FullPayload<E>>>>;
|
||||
|
||||
/// A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and
|
||||
/// ready to import into the `BeaconChain`. The validation includes:
|
||||
///
|
||||
/// - Parent is known
|
||||
/// - Signatures
|
||||
/// - State root check
|
||||
/// - Block processing
|
||||
///
|
||||
/// Note: a `ExecutionPendingEnvelope` is not _forever_ valid to be imported, it may later become invalid
|
||||
/// due to finality or some other event. A `ExecutionPendingEnvelope` should be imported into the
|
||||
/// `BeaconChain` immediately after it is instantiated.
|
||||
pub struct ExecutionPendingEnvelope<T: BeaconChainTypes> {
|
||||
pub block: MaybeAvailableEnvelope<T::EthSpec>,
|
||||
pub import_data: PayloadEnvelopeImportData<T::EthSpec>,
|
||||
pub payload_verification_handle: PayloadVerificationHandle<T::EthSpec>,
|
||||
}
|
||||
@@ -3,14 +3,14 @@ use std::sync::Arc;
|
||||
use educe::Educe;
|
||||
use slot_clock::SlotClock;
|
||||
use state_processing::{VerifySignatures, envelope_processing::process_execution_payload_envelope};
|
||||
use tracing::debug;
|
||||
use tracing::{Span, debug};
|
||||
use types::{
|
||||
EthSpec, SignedBeaconBlock, SignedExecutionPayloadEnvelope,
|
||||
consts::gloas::BUILDER_INDEX_SELF_BUILD,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
BeaconChain, BeaconChainError, BeaconChainTypes, NotifyExecutionLayer,
|
||||
BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, NotifyExecutionLayer,
|
||||
PayloadVerificationOutcome,
|
||||
payload_envelope_verification::{
|
||||
EnvelopeError, EnvelopeImportData, EnvelopeProcessingSnapshot, ExecutionPendingEnvelope,
|
||||
@@ -181,7 +181,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
||||
self,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingEnvelope<T>, EnvelopeError> {
|
||||
) -> Result<ExecutionPendingEnvelope<T::EthSpec>, BlockError> {
|
||||
let signed_envelope = self.signed_envelope;
|
||||
let envelope = &signed_envelope.message;
|
||||
let payload = &envelope.payload;
|
||||
@@ -255,4 +255,63 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T> for GossipVerifiedEnve
|
||||
payload_verification_handle,
|
||||
})
|
||||
}
|
||||
|
||||
fn envelope(&self) -> &Arc<SignedExecutionPayloadEnvelope<T::EthSpec>> {
|
||||
&self.signed_envelope
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
/// Returns `Ok(GossipVerifiedEnvelope)` if the supplied `envelope` should be forwarded onto the
|
||||
/// gossip network. The envelope is not imported into the chain, it is just partially verified.
|
||||
///
|
||||
/// The returned `GossipVerifiedEnvelope` should be provided to `Self::process_execution_payload_envelope` immediately
|
||||
/// after it is returned, unless some other circumstance decides it should not be imported at
|
||||
/// all.
|
||||
///
|
||||
/// ## Errors
|
||||
///
|
||||
/// Returns an `Err` if the given envelope was invalid, or an error was encountered during
|
||||
pub async fn verify_envelope_for_gossip(
|
||||
self: &Arc<Self>,
|
||||
envelope: Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>,
|
||||
) -> Result<GossipVerifiedEnvelope<T>, EnvelopeError> {
|
||||
let chain = self.clone();
|
||||
let span = Span::current();
|
||||
self.task_executor
|
||||
.clone()
|
||||
.spawn_blocking_handle(
|
||||
move || {
|
||||
let _guard = span.enter();
|
||||
let slot = envelope.slot();
|
||||
let beacon_block_root = envelope.message.beacon_block_root;
|
||||
|
||||
match GossipVerifiedEnvelope::new(envelope, &chain) {
|
||||
Ok(verified) => {
|
||||
debug!(
|
||||
%slot,
|
||||
?beacon_block_root,
|
||||
"Successfully verified gossip envelope"
|
||||
);
|
||||
|
||||
Ok(verified)
|
||||
}
|
||||
Err(e) => {
|
||||
debug!(
|
||||
error = e.to_string(),
|
||||
?beacon_block_root,
|
||||
%slot,
|
||||
"Rejected gossip envelope"
|
||||
);
|
||||
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
"gossip_envelope_verification_handle",
|
||||
)
|
||||
.ok_or(BeaconChainError::RuntimeShutdown)?
|
||||
.await
|
||||
.map_err(BeaconChainError::TokioJoin)?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,17 +34,16 @@ use state_processing::{
|
||||
use tracing::instrument;
|
||||
use types::{
|
||||
BeaconState, BeaconStateError, ChainSpec, DataColumnSidecarList, EthSpec, ExecutionBlockHash,
|
||||
Hash256, SignedBeaconBlock, SignedExecutionPayloadEnvelope, Slot,
|
||||
ExecutionPayloadEnvelope, Hash256, SignedBeaconBlock, SignedExecutionPayloadEnvelope, Slot,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
AvailabilityProcessingStatus, BeaconChain, BeaconChainError, BeaconChainTypes,
|
||||
ExecutionPayloadError, NotifyExecutionLayer, PayloadVerificationOutcome,
|
||||
block_verification::PayloadVerificationHandle, block_verification_types::BlockImportData,
|
||||
BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, ExecutionPayloadError,
|
||||
NotifyExecutionLayer, PayloadVerificationOutcome,
|
||||
block_verification::PayloadVerificationHandle,
|
||||
payload_envelope_verification::gossip_verified_envelope::GossipVerifiedEnvelope,
|
||||
};
|
||||
|
||||
pub mod execution_pending_envelope;
|
||||
pub mod gossip_verified_envelope;
|
||||
mod payload_notifier;
|
||||
mod tests;
|
||||
@@ -54,12 +53,14 @@ pub trait IntoExecutionPendingEnvelope<T: BeaconChainTypes>: Sized {
|
||||
self,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingEnvelope<T>, EnvelopeError>;
|
||||
) -> Result<ExecutionPendingEnvelope<T::EthSpec>, BlockError>;
|
||||
|
||||
fn envelope(&self) -> &Arc<SignedExecutionPayloadEnvelope<T::EthSpec>>;
|
||||
}
|
||||
|
||||
pub struct ExecutionPendingEnvelope<T: BeaconChainTypes> {
|
||||
pub signed_envelope: MaybeAvailableEnvelope<T::EthSpec>,
|
||||
pub import_data: EnvelopeImportData<T::EthSpec>,
|
||||
pub struct ExecutionPendingEnvelope<E: EthSpec> {
|
||||
pub signed_envelope: MaybeAvailableEnvelope<E>,
|
||||
pub import_data: EnvelopeImportData<E>,
|
||||
pub payload_verification_handle: PayloadVerificationHandle,
|
||||
}
|
||||
|
||||
@@ -82,6 +83,25 @@ pub struct AvailableEnvelope<E: EthSpec> {
|
||||
pub spec: Arc<ChainSpec>,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AvailableEnvelope<E> {
|
||||
pub fn message(&self) -> &ExecutionPayloadEnvelope<E> {
|
||||
&self.envelope.message
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn deconstruct(
|
||||
self,
|
||||
) -> (
|
||||
Arc<SignedExecutionPayloadEnvelope<E>>,
|
||||
DataColumnSidecarList<E>,
|
||||
) {
|
||||
let AvailableEnvelope {
|
||||
envelope, columns, ..
|
||||
} = self;
|
||||
(envelope, columns)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MaybeAvailableEnvelope<E: EthSpec> {
|
||||
Available(AvailableEnvelope<E>),
|
||||
AvailabilityPending {
|
||||
@@ -204,6 +224,12 @@ pub enum EnvelopeError {
|
||||
ExecutionPayloadError(ExecutionPayloadError),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for EnvelopeError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BeaconChainError> for EnvelopeError {
|
||||
fn from(e: BeaconChainError) -> Self {
|
||||
EnvelopeError::BeaconChainError(Arc::new(e))
|
||||
@@ -248,7 +274,7 @@ impl From<EnvelopeProcessingError> for EnvelopeError {
|
||||
pub(crate) fn load_snapshot<T: BeaconChainTypes>(
|
||||
envelope: &SignedExecutionPayloadEnvelope<T::EthSpec>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<EnvelopeProcessingSnapshot<T::EthSpec>, EnvelopeError> {
|
||||
) -> Result<EnvelopeProcessingSnapshot<T::EthSpec>, BlockError> {
|
||||
// Reject any block if its block is not known to fork choice.
|
||||
//
|
||||
// A block that is not in fork choice is either:
|
||||
@@ -263,8 +289,8 @@ pub(crate) fn load_snapshot<T: BeaconChainTypes>(
|
||||
let fork_choice_read_lock = chain.canonical_head.fork_choice_read_lock();
|
||||
let beacon_block_root = envelope.beacon_block_root();
|
||||
let Some(proto_beacon_block) = fork_choice_read_lock.get_block(&beacon_block_root) else {
|
||||
return Err(EnvelopeError::BlockRootUnknown {
|
||||
block_root: beacon_block_root,
|
||||
return Err(BlockError::ParentUnknown {
|
||||
parent_root: beacon_block_root,
|
||||
});
|
||||
};
|
||||
drop(fork_choice_read_lock);
|
||||
@@ -278,7 +304,7 @@ pub(crate) fn load_snapshot<T: BeaconChainTypes>(
|
||||
let state = chain
|
||||
.store
|
||||
.get_hot_state(&block_state_root, cache_state)
|
||||
.map_err(|e| EnvelopeError::BeaconChainError(Arc::new(e.into())))?
|
||||
.map_err(|e| BlockError::BeaconChainError(Box::new(e.into())))?
|
||||
.ok_or_else(|| {
|
||||
BeaconChainError::DBInconsistent(format!(
|
||||
"Missing state for envelope block {block_state_root:?}",
|
||||
@@ -299,11 +325,15 @@ impl<T: BeaconChainTypes> IntoExecutionPendingEnvelope<T>
|
||||
self,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingEnvelope<T>, EnvelopeError> {
|
||||
) -> Result<ExecutionPendingEnvelope<T::EthSpec>, BlockError> {
|
||||
// TODO(EIP-7732): figure out how this should be refactored..
|
||||
GossipVerifiedEnvelope::new(self, chain)?
|
||||
.into_execution_pending_envelope(chain, notify_execution_layer)
|
||||
}
|
||||
|
||||
fn envelope(&self) -> &Arc<SignedExecutionPayloadEnvelope<T::EthSpec>> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
||||
@@ -8,7 +8,7 @@ use types::{SignedBeaconBlock, SignedExecutionPayloadEnvelope};
|
||||
|
||||
use crate::{
|
||||
BeaconChain, BeaconChainTypes, BlockError, ExecutionPayloadError, NotifyExecutionLayer,
|
||||
execution_payload::notify_new_payload,
|
||||
execution_payload::notify_new_payload, payload_envelope_verification::EnvelopeError,
|
||||
};
|
||||
|
||||
/// Used to await the result of executing payload with a remote EE.
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{AvailabilityProcessingStatus, BeaconChain, BeaconChainTypes, payload_envelope_verification::{ExecutedEnvelope, ExecutionPendingEnvelope}};
|
||||
use crate::{
|
||||
AvailabilityProcessingStatus, BeaconChain, BeaconChainTypes,
|
||||
payload_envelope_verification::{ExecutedEnvelope, ExecutionPendingEnvelope},
|
||||
};
|
||||
|
||||
async fn import_execution_pending_envelope<T: BeaconChainTypes>(
|
||||
chain: Arc<BeaconChain<T>>,
|
||||
execution_pending_envelope: ExecutionPendingEnvelope<T>,
|
||||
execution_pending_envelope: ExecutionPendingEnvelope<T::EthSpec>,
|
||||
) -> Result<AvailabilityProcessingStatus, String> {
|
||||
match chain
|
||||
.clone()
|
||||
|
||||
Reference in New Issue
Block a user