diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 5a82dc70c5..c985f937a5 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -1135,6 +1135,23 @@ impl BeaconChain { } } + /// Returns the full block at the given root, if it's available in the database. + /// + /// Should always return a full block for pre-merge and post-gloas blocks. + /// An + pub fn get_full_block( + &self, + block_root: &Hash256, + ) -> Result>, Error> { + match self.store.try_get_full_block(block_root)? { + Some(DatabaseBlock::Full(block)) => Ok(Some(block)), + Some(DatabaseBlock::Blinded(_)) => { + Err(Error::ExecutionPayloadMissingFromDatabase(*block_root)) + } + None => Ok(None), + } + } + /// Returns the block at the given root, if any. /// /// ## Errors diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index 691293b200..e4f523c8dd 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -708,7 +708,8 @@ pub struct SignatureVerifiedBlock { } /// Used to await the result of executing payload with an EE. -type PayloadVerificationHandle = JoinHandle>>; +pub type PayloadVerificationHandle = + JoinHandle>>; /// A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and /// ready to import into the `BeaconChain`. The validation includes: diff --git a/beacon_node/beacon_chain/src/envelope_verification.rs b/beacon_node/beacon_chain/src/envelope_verification.rs index 6f927c6387..de40bac602 100644 --- a/beacon_node/beacon_chain/src/envelope_verification.rs +++ b/beacon_node/beacon_chain/src/envelope_verification.rs @@ -4,48 +4,50 @@ //! diagram below). //! //! ```ignore -//! START -//! | -//! ▼ -//! SignedExecutionPayloadEnvelope -//! | -//! |--------------- -//! | | -//! | ▼ -//! | GossipVerifiedEnvelope -//! | | -//! |--------------- -//! | -//! ▼ -//! ExecutionPendingEnvelope -//! | -//! await -//! | -//! ▼ -//! END +//! START +//! | +//! ▼ +//! SignedExecutionPayloadEnvelope +//! | +//! |--------------- +//! | | +//! | ▼ +//! | GossipVerifiedEnvelope +//! | | +//! |--------------- +//! | +//! ▼ +//! SignatureVerifiedEnvelope +//! | +//! ▼ +//! ExecutionPendingEnvelope +//! | +//! await +//! | +//! ▼ +//! END //! //! ``` -use crate::block_verification::{PayloadVerificationHandle, PayloadVerificationOutcome}; -use crate::data_availability_checker::MaybeAvailableEnvelope; -use crate::envelope_verification_types::EnvelopeImportData; -use crate::execution_payload::PayloadNotifier; use crate::NotifyExecutionLayer; +use crate::block_verification::{PayloadVerificationHandle, PayloadVerificationOutcome}; +use crate::envelope_verification_types::{EnvelopeImportData, MaybeAvailableEnvelope}; +use crate::execution_payload::PayloadNotifier; use crate::{BeaconChain, BeaconChainError, BeaconChainTypes}; use derivative::Derivative; use safe_arith::ArithError; use slot_clock::SlotClock; -use state_processing::envelope_processing::{envelope_processing, EnvelopeProcessingError}; +use state_processing::envelope_processing::{EnvelopeProcessingError, envelope_processing}; use state_processing::per_block_processing::compute_timestamp_at_slot; use state_processing::{BlockProcessingError, VerifySignatures}; use std::sync::Arc; use tree_hash::TreeHash; use types::{ - BeaconState, BeaconStateError, EthSpec, ExecutionBlockHash, Hash256, SignedBlindedBeaconBlock, - SignedExecutionPayloadEnvelope, + BeaconState, BeaconStateError, ExecutionBlockHash, Hash256, SignedBeaconBlock, + SignedExecutionPayloadEnvelope, Slot, }; -// TODO(EIP7732): don't use this redefinition.. +// TODO(gloas): don't use this redefinition.. macro_rules! envelope_verify { ($condition: expr, $result: expr) => { if !$condition { @@ -54,7 +56,7 @@ macro_rules! envelope_verify { }; } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum EnvelopeError { /// The envelope's block root is unknown. BlockRootUnknown { @@ -117,11 +119,13 @@ pub enum EnvelopeError { state: Hash256, envelope: Hash256, }, - // The payload was withheld but the block hash - // matched the committed bid - PayloadWithheldBlockHashMismatch, + // The slot doesn't match the parent block + SlotMismatch { + parent_block: Slot, + envelope: Slot, + }, // Some Beacon Chain Error - BeaconChainError(BeaconChainError), + BeaconChainError(Arc), // Some Beacon State error BeaconStateError(BeaconStateError), // Some ArithError @@ -132,7 +136,7 @@ pub enum EnvelopeError { impl From for EnvelopeError { fn from(e: BeaconChainError) -> Self { - EnvelopeError::BeaconChainError(e) + EnvelopeError::BeaconChainError(Arc::new(e)) } } @@ -166,7 +170,7 @@ impl From for EnvelopeError { #[derivative(Debug(bound = "T: BeaconChainTypes"))] pub struct GossipVerifiedEnvelope { pub signed_envelope: Arc>, - pub parent_block: Arc>, + pub parent_block: Arc>, pub pre_state: Box>, } @@ -179,7 +183,7 @@ impl GossipVerifiedEnvelope { let payload = envelope.payload(); let block_root = envelope.beacon_block_root(); - // TODO(EIP7732): this check would fail if the block didn't pass validation right? + // TODO(gloas): this check would fail if the block didn't pass validation right? // check that we've seen the parent block of this envelope let fork_choice_read_lock = chain.canonical_head.fork_choice_read_lock(); @@ -189,7 +193,7 @@ impl GossipVerifiedEnvelope { drop(fork_choice_read_lock); let parent_block = chain - .get_blinded_block(&block_root)? + .get_full_block(&block_root)? .ok_or_else(|| EnvelopeError::from(BeaconChainError::MissingBeaconBlock(block_root))) .map(Arc::new)?; let execution_bid = &parent_block @@ -198,10 +202,17 @@ impl GossipVerifiedEnvelope { .signed_execution_bid()? .message; - // TODO(EIP7732): check we're within the bounds of the slot (probably) + // TODO(gloas): check we're within the bounds of the slot (probably) + // I think a timestamp check like this is on the beacon block but need to check. + if envelope.slot() != parent_block.slot() { + return Err(EnvelopeError::SlotMismatch { + parent_block: parent_block.slot(), + envelope: envelope.slot(), + }); + } - // TODO(EIP7732): check that we haven't seen another valid `SignedExecutionPayloadEnvelope` - // for this block root from this builder + // TODO(gloas): check that we haven't seen another valid `SignedExecutionPayloadEnvelope` + // for this block root from this builder - envelope status table check // builder index matches committed bid if envelope.builder_index() != execution_bid.builder_index { @@ -211,15 +222,21 @@ impl GossipVerifiedEnvelope { }); } - // if payload is withheld, the block hash should not match the committed bid - if !envelope.payload_withheld() && payload.block_hash() == execution_bid.block_hash { - return Err(EnvelopeError::PayloadWithheldBlockHashMismatch); + // the block hash should match the block hash of the execution bid + if payload.block_hash() != execution_bid.block_hash { + return Err(EnvelopeError::BlockHashMismatch { + committed_bid: execution_bid.block_hash, + envelope: payload.block_hash(), + }); } + // TODO(gloas): expensive load here.. check this let parent_state = chain + // TODO(gloas): may need a get_block_state to get the right state here.. .get_state( &parent_block.message().state_root(), Some(parent_block.slot()), + true, )? .ok_or_else(|| { EnvelopeError::from(BeaconChainError::MissingBeaconState( @@ -271,15 +288,24 @@ impl IntoExecutionPendingEnvelope for GossipVerifiedEnve // verify signature already done let mut state = *self.pre_state; - // setting state.latest_block_header happens in envelope_processing + // all state modifications are done in envelope_processing (called at the bottom of this function) + // so here perform the consistency check with the beacon block on a copy of the latest block header + // and let it be modified later in envelope_processing + let previous_state_root = state.canonical_root()?; + if state.latest_block_header().state_root == Hash256::default() { + let mut copy_of_latest_block_header = state.latest_block_header().clone(); + copy_of_latest_block_header.state_root = previous_state_root; - // Verify consistency with the beacon block - if !envelope.tree_hash_root() == state.latest_block_header().tree_hash_root() { - return Err(EnvelopeError::LatestBlockHeaderMismatch { - envelope_root: envelope.tree_hash_root(), - block_header_root: state.latest_block_header().tree_hash_root(), - }); - }; + // Verify consistency with the beacon block + if !envelope.beacon_block_root() == copy_of_latest_block_header.tree_hash_root() { + return Err(EnvelopeError::LatestBlockHeaderMismatch { + envelope_root: envelope.beacon_block_root(), + block_header_root: copy_of_latest_block_header.tree_hash_root(), + }); + }; + } + + // the check about the slots matching is already done in the GossipVerifiedEnvelope // Verify consistency with the committed bid let committed_bid = state.latest_execution_bid()?; @@ -293,79 +319,68 @@ impl IntoExecutionPendingEnvelope for GossipVerifiedEnve }); }; - if !envelope.payload_withheld() { - // Verify the withdrawals root - envelope_verify!( - payload.withdrawals()?.tree_hash_root() == state.latest_withdrawals_root()?, - EnvelopeError::WithdrawalsRootMismatch { - state: state.latest_withdrawals_root()?, - envelope: payload.withdrawals()?.tree_hash_root(), - } - .into() - ); + // Verify the withdrawals root + envelope_verify!( + payload.withdrawals()?.tree_hash_root() == *state.latest_withdrawals_root()?, + EnvelopeError::WithdrawalsRootMismatch { + state: *state.latest_withdrawals_root()?, + envelope: payload.withdrawals()?.tree_hash_root(), + } + .into() + ); - // Verify the gas limit - envelope_verify!( - payload.gas_limit() == committed_bid.gas_limit, - EnvelopeError::GasLimitMismatch { - committed_bid: committed_bid.gas_limit, - envelope: payload.gas_limit(), - } - .into() - ); - // Verify the block hash - envelope_verify!( - committed_bid.block_hash == payload.block_hash(), - EnvelopeError::BlockHashMismatch { - committed_bid: committed_bid.block_hash, - envelope: payload.block_hash(), - } - .into() - ); + // Verify the gas limit + envelope_verify!( + payload.gas_limit() == committed_bid.gas_limit, + EnvelopeError::GasLimitMismatch { + committed_bid: committed_bid.gas_limit, + envelope: payload.gas_limit(), + } + .into() + ); + // Verify the block hash already done in the GossipVerifiedEnvelope - // Verify consistency of the parent hash with respect to the previous execution payload - envelope_verify!( - payload.parent_hash() == state.latest_block_hash()?, - EnvelopeError::ParentHashMismatch { - state: state.latest_block_hash()?, - envelope: payload.parent_hash(), - } - .into() - ); + // Verify consistency of the parent hash with respect to the previous execution payload + envelope_verify!( + payload.parent_hash() == *state.latest_block_hash()?, + EnvelopeError::ParentHashMismatch { + state: *state.latest_block_hash()?, + envelope: payload.parent_hash(), + } + .into() + ); - // Verify prev_randao - envelope_verify!( - payload.prev_randao() == *state.get_randao_mix(state.current_epoch())?, - EnvelopeError::PrevRandaoMismatch { - state: *state.get_randao_mix(state.current_epoch())?, - envelope: payload.prev_randao(), - } - .into() - ); + // Verify prev_randao + envelope_verify!( + payload.prev_randao() == *state.get_randao_mix(state.current_epoch())?, + EnvelopeError::PrevRandaoMismatch { + state: *state.get_randao_mix(state.current_epoch())?, + envelope: payload.prev_randao(), + } + .into() + ); - // Verify the timestamp - let state_timestamp = - compute_timestamp_at_slot(&state, state.slot(), chain.spec.as_ref())?; - envelope_verify!( - payload.timestamp() == state_timestamp, - EnvelopeError::TimestampMismatch { - state: state_timestamp, - envelope: payload.timestamp(), - } - .into() - ); + // Verify the timestamp + let state_timestamp = compute_timestamp_at_slot(&state, state.slot(), chain.spec.as_ref())?; + envelope_verify!( + payload.timestamp() == state_timestamp, + EnvelopeError::TimestampMismatch { + state: state_timestamp, + envelope: payload.timestamp(), + } + .into() + ); - // Verify the commitments are under limit - envelope_verify!( - envelope.blob_kzg_commitments().len() - <= T::EthSpec::max_blob_commitments_per_block(), - EnvelopeError::BlobLimitExceeded { - max: T::EthSpec::max_blob_commitments_per_block(), - envelope: envelope.blob_kzg_commitments().len(), - } - .into() - ); - } + // Verify the commitments are under limit + let max_blobs = chain.spec.max_blobs_per_block(state.current_epoch()) as usize; + envelope_verify!( + envelope.blob_kzg_commitments().len() <= max_blobs, + EnvelopeError::BlobLimitExceeded { + max: max_blobs, + envelope: envelope.blob_kzg_commitments().len(), + } + .into() + ); // Verify the execution payload is valid let payload_notifier = @@ -375,7 +390,7 @@ impl IntoExecutionPendingEnvelope for GossipVerifiedEnve let payload_verification_future = async move { let chain = payload_notifier.chain.clone(); - // TODO:(EIP7732): timing + // TODO:(gloas): timing if let Some(started_execution) = chain.slot_clock.now_duration() { chain.block_times_cache.write().set_time_started_execution( block_root, @@ -410,7 +425,7 @@ impl IntoExecutionPendingEnvelope for GossipVerifiedEnve &chain.spec, )?; - // TODO(EIP7732): if verify + // TODO(gloas): if verify envelope_verify!( state.canonical_root()? == envelope.state_root(), EnvelopeError::InvalidStateRoot { @@ -421,7 +436,7 @@ impl IntoExecutionPendingEnvelope for GossipVerifiedEnve Ok(ExecutionPendingEnvelope { signed_envelope: MaybeAvailableEnvelope::AvailabilityPending { - block_root, + block_hash: payload.block_hash(), envelope: signed_envelope, }, import_data: EnvelopeImportData { @@ -442,8 +457,8 @@ impl IntoExecutionPendingEnvelope chain: &Arc>, notify_execution_layer: NotifyExecutionLayer, ) -> Result, EnvelopeError> { - // TODO(EIP7732): figure out how this should be refactored.. + // TODO(gloas): figure out how this should be refactored.. GossipVerifiedEnvelope::new(self, chain)? .into_execution_pending_envelope(chain, notify_execution_layer) } -} \ No newline at end of file +} diff --git a/beacon_node/beacon_chain/src/envelope_verification_types.rs b/beacon_node/beacon_chain/src/envelope_verification_types.rs index ac58c98582..3d639752ff 100644 --- a/beacon_node/beacon_chain/src/envelope_verification_types.rs +++ b/beacon_node/beacon_chain/src/envelope_verification_types.rs @@ -1,136 +1,30 @@ -use crate::data_availability_checker::{AvailableEnvelope, MaybeAvailableEnvelope}; -use crate::PayloadVerificationOutcome; use std::sync::Arc; use types::{ - BeaconState, BlobIdentifier, EthSpec, Hash256, SignedBlindedBeaconBlock, - SignedExecutionPayloadEnvelope, + BeaconState, ChainSpec, DataColumnSidecarList, EthSpec, ExecutionBlockHash, Hash256, + SignedBeaconBlock, SignedExecutionPayloadEnvelope, }; -/// A block that has completed all pre-deneb block processing checks including verification -/// by an EL client **and** has all requisite blob data to be imported into fork choice. -#[derive(PartialEq)] -pub struct AvailableExecutedEnvelope { - pub envelope: AvailableEnvelope, - pub import_data: EnvelopeImportData, - pub payload_verification_outcome: PayloadVerificationOutcome, -} - -impl AvailableExecutedEnvelope { - pub fn new( - envelope: AvailableEnvelope, - import_data: EnvelopeImportData, - payload_verification_outcome: PayloadVerificationOutcome, - ) -> Self { - Self { - envelope, - import_data, - payload_verification_outcome, - } - } - - pub fn get_all_blob_ids(&self) -> Vec { - let num_blobs_expected = self - .envelope - .envelope() - .message() - .blob_kzg_commitments() - .len(); - let mut blob_ids = Vec::with_capacity(num_blobs_expected); - for i in 0..num_blobs_expected { - blob_ids.push(BlobIdentifier { - block_root: self.import_data.block_root, - index: i as u64, - }); - } - blob_ids - } -} - #[derive(PartialEq)] pub struct EnvelopeImportData { pub block_root: Hash256, - pub parent_block: Arc>, + pub parent_block: Arc>, pub post_state: Box>, } -pub struct AvailabilityPendingExecutedEnvelope { - pub envelope: Arc>, - pub import_data: EnvelopeImportData, - pub payload_verification_outcome: PayloadVerificationOutcome, +#[derive(Debug)] +#[allow(dead_code)] +pub struct AvailableEnvelope { + block_hash: ExecutionBlockHash, + envelope: Arc>, + columns: DataColumnSidecarList, + /// Timestamp at which this block first became available (UNIX timestamp, time since 1970). + columns_available_timestamp: Option, + pub spec: Arc, } - -impl AvailabilityPendingExecutedEnvelope { - pub fn new( +pub enum MaybeAvailableEnvelope { + Available(AvailableEnvelope), + AvailabilityPending { + block_hash: ExecutionBlockHash, envelope: Arc>, - import_data: EnvelopeImportData, - payload_verification_outcome: PayloadVerificationOutcome, - ) -> Self { - Self { - envelope, - import_data, - payload_verification_outcome, - } - } - - pub fn as_envelope(&self) -> &SignedExecutionPayloadEnvelope { - self.envelope.as_ref() - } - - pub fn num_blobs_expected(&self) -> usize { - self.envelope.message().blob_kzg_commitments().len() - } + }, } - -/// An envelope that has gone through all envelope processing checks including envelope processing -/// and execution by an EL client. This block hasn't necessarily completed data availability checks. -/// -/// -/// It contains 2 variants: -/// 1. `Available`: This envelope has been executed and also contains all data to consider it a -/// fully available envelope. -/// 2. `AvailabilityPending`: This envelope hasn't received all required blobs to consider it a -/// fully available envelope. -pub enum ExecutedEnvelope { - Available(AvailableExecutedEnvelope), - AvailabilityPending(AvailabilityPendingExecutedEnvelope), -} - -impl ExecutedEnvelope { - pub fn new( - envelope: MaybeAvailableEnvelope, - import_data: EnvelopeImportData, - payload_verification_outcome: PayloadVerificationOutcome, - ) -> Self { - match envelope { - MaybeAvailableEnvelope::Available(available_envelope) => { - Self::Available(AvailableExecutedEnvelope::new( - available_envelope, - import_data, - payload_verification_outcome, - )) - } - MaybeAvailableEnvelope::AvailabilityPending { - block_root: _, - envelope, - } => Self::AvailabilityPending(AvailabilityPendingExecutedEnvelope::new( - envelope, - import_data, - payload_verification_outcome, - )), - } - } - - pub fn as_envelope(&self) -> &SignedExecutionPayloadEnvelope { - match self { - Self::Available(available) => available.envelope.envelope(), - Self::AvailabilityPending(pending) => pending.envelope.as_ref(), - } - } - - pub fn block_root(&self) -> Hash256 { - match self { - Self::Available(available) => available.import_data.block_root, - Self::AvailabilityPending(pending) => pending.import_data.block_root, - } - } -} \ No newline at end of file diff --git a/beacon_node/beacon_chain/src/errors.rs b/beacon_node/beacon_chain/src/errors.rs index d4eba2b0ea..9523c1ec6c 100644 --- a/beacon_node/beacon_chain/src/errors.rs +++ b/beacon_node/beacon_chain/src/errors.rs @@ -148,6 +148,7 @@ pub enum BeaconChainError { EngineGetCapabilititesFailed(Box), ExecutionLayerGetBlockByNumberFailed(Box), ExecutionLayerGetBlockByHashFailed(Box), + ExecutionPayloadMissingFromDatabase(Hash256), BlockHashMissingFromExecutionLayer(ExecutionBlockHash), InconsistentPayloadReconstructed { slot: Slot, diff --git a/beacon_node/beacon_chain/src/execution_payload.rs b/beacon_node/beacon_chain/src/execution_payload.rs index f0cab06ca3..7cad2104eb 100644 --- a/beacon_node/beacon_chain/src/execution_payload.rs +++ b/beacon_node/beacon_chain/src/execution_payload.rs @@ -9,7 +9,7 @@ use crate::{ BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, BlockProductionError, - ExecutionPayloadError, + EnvelopeError, ExecutionPayloadError, }; use execution_layer::{ BlockProposalContents, BlockProposalContentsType, BuilderParams, NewPayloadRequest, @@ -108,6 +108,16 @@ impl PayloadNotifier { }) } + pub fn from_envelope( + _chain: Arc>, + _envelope: ExecutionPayloadEnvelopeRef, + _notify_execution_layer: NotifyExecutionLayer, + ) -> Result { + todo!( + "this isn't a real method but something like this will be needed after refactoring this a bit" + ); + } + pub async fn notify_new_payload(self) -> Result { if let Some(precomputed_status) = self.payload_verification_status { Ok(precomputed_status) diff --git a/beacon_node/beacon_chain/src/lib.rs b/beacon_node/beacon_chain/src/lib.rs index 8df88532c2..37e8945a25 100644 --- a/beacon_node/beacon_chain/src/lib.rs +++ b/beacon_node/beacon_chain/src/lib.rs @@ -87,6 +87,7 @@ pub use block_verification_types::AvailabilityPendingExecutedBlock; pub use block_verification_types::ExecutedBlock; pub use canonical_head::{CachedHead, CanonicalHead, CanonicalHeadRwLock}; pub use custody_context::CustodyContext; +pub use envelope_verification::{EnvelopeError, GossipVerifiedEnvelope}; pub use events::ServerSentEventHandler; pub use execution_layer::EngineState; pub use execution_payload::NotifyExecutionLayer; diff --git a/consensus/state_processing/src/envelope_processing.rs b/consensus/state_processing/src/envelope_processing.rs index aafc6bb3e8..01f49c1438 100644 --- a/consensus/state_processing/src/envelope_processing.rs +++ b/consensus/state_processing/src/envelope_processing.rs @@ -1,9 +1,11 @@ +use crate::BlockProcessingError; +use crate::VerifySignatures; use crate::per_block_processing::process_operations::{ process_consolidation_requests, process_deposit_requests, process_withdrawal_requests, }; -use crate::BlockProcessingError; -use crate::VerifySignatures; -use types::{BeaconState, BeaconStateError, ChainSpec, EthSpec, Hash256, SignedExecutionPayloadEnvelope}; +use types::{ + BeaconState, BeaconStateError, ChainSpec, EthSpec, Hash256, SignedExecutionPayloadEnvelope, +}; #[derive(Debug)] pub enum EnvelopeProcessingError { @@ -47,8 +49,6 @@ pub fn envelope_processing( state.latest_block_header_mut().state_root = previous_state_root; } - // Verify consistency with the beacon block - // process electra operations let envelope = signed_envelope.message(); let payload = envelope.payload(); @@ -62,4 +62,4 @@ pub fn envelope_processing( todo!("the rest of process_execution_payload()"); //Ok(()) -} \ No newline at end of file +} diff --git a/consensus/state_processing/src/per_block_processing/signature_sets.rs b/consensus/state_processing/src/per_block_processing/signature_sets.rs index af1b75a00f..1dc53ce1a8 100644 --- a/consensus/state_processing/src/per_block_processing/signature_sets.rs +++ b/consensus/state_processing/src/per_block_processing/signature_sets.rs @@ -11,8 +11,9 @@ use types::{ BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256, InconsistentFork, IndexedAttestation, IndexedAttestationRef, ProposerSlashing, PublicKey, PublicKeyBytes, Signature, SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader, - SignedBlsToExecutionChange, SignedContributionAndProof, SignedRoot, SignedVoluntaryExit, - SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData, Unsigned, SignedExecutionPayloadEnvelope, + SignedBlsToExecutionChange, SignedContributionAndProof, SignedExecutionPayloadEnvelope, + SignedRoot, SignedVoluntaryExit, SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData, + Unsigned, }; pub type Result = std::result::Result;