diff --git a/beacon_node/beacon_chain/src/data_availability_checker.rs b/beacon_node/beacon_chain/src/data_availability_checker.rs index 1e6e1bb4b5..8762b73e1c 100644 --- a/beacon_node/beacon_chain/src/data_availability_checker.rs +++ b/beacon_node/beacon_chain/src/data_availability_checker.rs @@ -11,7 +11,6 @@ use kzg::Kzg; use slog::{debug, error}; use slot_clock::SlotClock; use ssz_types::{Error, FixedVector, VariableList}; -use state_processing::per_block_processing::deneb::deneb::verify_kzg_commitments_against_transactions; use std::collections::HashSet; use std::sync::Arc; use strum::IntoStaticStr; @@ -21,7 +20,7 @@ use types::blob_sidecar::{BlobIdentifier, BlobSidecar, FixedBlobSidecarList}; use types::consts::deneb::MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS; use types::ssz_tagged_signed_beacon_block; use types::{ - BeaconBlockRef, BlobSidecarList, ChainSpec, Epoch, EthSpec, ExecPayload, FullPayload, Hash256, + BeaconBlockRef, BlobSidecarList, ChainSpec, Epoch, EthSpec, FullPayload, Hash256, SignedBeaconBlock, SignedBeaconBlockHeader, Slot, }; @@ -291,35 +290,20 @@ impl DataAvailabilityChecker { &self, block: &Arc>>, ) -> Result { - let verified_blobs = if let (Ok(block_kzg_commitments), Ok(payload)) = ( - block.message().body().blob_kzg_commitments(), - block.message().body().execution_payload(), - ) { - if let Some(transactions) = payload.transactions() { - let verified = verify_kzg_commitments_against_transactions::( - transactions, - block_kzg_commitments, - ) - .map_err(|e| AvailabilityCheckError::TxKzgCommitmentMismatch(format!("{e:?}")))?; - if !verified { - return Err(AvailabilityCheckError::TxKzgCommitmentMismatch( - "a commitment and version didn't match".to_string(), - )); - } - } - - if self.da_check_required(block.epoch()) { - if block_kzg_commitments.is_empty() { - BlobRequirements::EmptyBlobs + let verified_blobs = + if let Ok(block_kzg_commitments) = block.message().body().blob_kzg_commitments() { + if self.da_check_required(block.epoch()) { + if block_kzg_commitments.is_empty() { + BlobRequirements::EmptyBlobs + } else { + BlobRequirements::Required + } } else { - BlobRequirements::Required + BlobRequirements::NotRequired } } else { - BlobRequirements::NotRequired - } - } else { - BlobRequirements::PreDeneb - }; + BlobRequirements::PreDeneb + }; Ok(verified_blobs) } diff --git a/beacon_node/beacon_chain/src/execution_payload.rs b/beacon_node/beacon_chain/src/execution_payload.rs index 51c7ec2990..1166de1e56 100644 --- a/beacon_node/beacon_chain/src/execution_payload.rs +++ b/beacon_node/beacon_chain/src/execution_payload.rs @@ -18,7 +18,7 @@ use proto_array::{Block as ProtoBlock, ExecutionStatus}; use slog::{debug, warn}; use slot_clock::SlotClock; use state_processing::per_block_processing::{ - compute_timestamp_at_slot, get_expected_withdrawals, is_execution_enabled, + self, compute_timestamp_at_slot, get_expected_withdrawals, is_execution_enabled, is_merge_transition_complete, partially_verify_execution_payload, }; use std::sync::Arc; @@ -68,15 +68,16 @@ impl PayloadNotifier { // the block as optimistically imported. This is particularly relevant in the case // where we do not send the block to the EL at all. let block_message = block.message(); - let payload = block_message.execution_payload()?; partially_verify_execution_payload::<_, FullPayload<_>>( state, block.slot(), - payload, + block_message.body(), &chain.spec, ) .map_err(BlockError::PerBlockProcessingError)?; + let payload = block_message.execution_payload()?; + match notify_execution_layer { NotifyExecutionLayer::No if chain.config.optimistic_finalized_sync => { // Verify the block hash here in Lighthouse and immediately mark the block as @@ -139,6 +140,14 @@ async fn notify_new_payload<'a, T: BeaconChainTypes>( block: BeaconBlockRef<'a, T::EthSpec>, ) -> Result> { let execution_payload = block.execution_payload()?; + let versioned_hashes = block.body().blob_kzg_commitments().ok().map(|commitments| { + commitments + .into_iter() + .map(|commitment| { + per_block_processing::deneb::deneb::kzg_commitment_to_versioned_hash(commitment) + }) + .collect::>() + }); let execution_layer = chain .execution_layer @@ -146,7 +155,7 @@ async fn notify_new_payload<'a, T: BeaconChainTypes>( .ok_or(ExecutionPayloadError::NoExecutionConnection)?; let new_payload_response = execution_layer - .notify_new_payload(&execution_payload.into()) + .notify_new_payload(&execution_payload.into(), versioned_hashes) .await; match new_payload_response { diff --git a/beacon_node/execution_layer/src/engine_api/http.rs b/beacon_node/execution_layer/src/engine_api/http.rs index 8e403b2bea..0ae4a82ecc 100644 --- a/beacon_node/execution_layer/src/engine_api/http.rs +++ b/beacon_node/execution_layer/src/engine_api/http.rs @@ -11,7 +11,7 @@ use std::collections::HashSet; use tokio::sync::Mutex; use std::time::{Duration, Instant}; -use types::EthSpec; +use types::{EthSpec, VersionedHash}; pub use deposit_log::{DepositLog, Log}; pub use reqwest::Client; @@ -808,8 +808,12 @@ impl HttpJsonRpc { pub async fn new_payload_v3( &self, execution_payload: ExecutionPayload, + versioned_hashes: Vec, ) -> Result { - let params = json!([JsonExecutionPayload::from(execution_payload)]); + let params = json!([ + JsonExecutionPayload::from(execution_payload), + versioned_hashes + ]); let response: JsonPayloadStatusV1 = self .rpc_request( @@ -1099,10 +1103,15 @@ impl HttpJsonRpc { pub async fn new_payload( &self, execution_payload: ExecutionPayload, + versioned_hashes_opt: Option>, ) -> Result { let engine_capabilities = self.get_engine_capabilities(None).await?; if engine_capabilities.new_payload_v3 { - self.new_payload_v3(execution_payload).await + let Some(versioned_hashes) = versioned_hashes_opt else { + return Err(Error::IncorrectStateVariant); + }; + self.new_payload_v3(execution_payload, versioned_hashes) + .await } else if engine_capabilities.new_payload_v2 { self.new_payload_v2(execution_payload).await } else if engine_capabilities.new_payload_v1 { diff --git a/beacon_node/execution_layer/src/lib.rs b/beacon_node/execution_layer/src/lib.rs index a02cb78a32..b32bc2780c 100644 --- a/beacon_node/execution_layer/src/lib.rs +++ b/beacon_node/execution_layer/src/lib.rs @@ -1210,6 +1210,7 @@ impl ExecutionLayer { pub async fn notify_new_payload( &self, execution_payload: &ExecutionPayload, + versioned_hashes: Option>, ) -> Result { let _timer = metrics::start_timer_vec( &metrics::EXECUTION_LAYER_REQUEST_TIMES, @@ -1226,7 +1227,11 @@ impl ExecutionLayer { let result = self .engine() - .request(|engine| engine.api.new_payload(execution_payload.clone())) + .request(|engine| { + engine + .api + .new_payload(execution_payload.clone(), versioned_hashes) + }) .await; if let Ok(status) = &result { @@ -1237,6 +1242,8 @@ impl ExecutionLayer { } *self.inner.last_new_payload_errored.write().await = result.is_err(); + //TODO(sean) process notify commitments updatE? + process_payload_status(execution_payload.block_hash(), result, self.log()) .map_err(Box::new) .map_err(Error::EngineError) diff --git a/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs b/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs index 0c6f5ce666..5d9b63f1ab 100644 --- a/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs +++ b/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs @@ -204,7 +204,7 @@ impl MockExecutionLayer { Some(payload.clone()) ); - let status = self.el.notify_new_payload(&payload).await.unwrap(); + let status = self.el.notify_new_payload(&payload, None).await.unwrap(); assert_eq!(status, PayloadStatus::Valid); // Use junk values for slot/head-root to ensure there is no payload supplied. diff --git a/consensus/state_processing/src/per_block_processing.rs b/consensus/state_processing/src/per_block_processing.rs index 53bfbe3069..4d50175ff9 100644 --- a/consensus/state_processing/src/per_block_processing.rs +++ b/consensus/state_processing/src/per_block_processing.rs @@ -13,7 +13,6 @@ pub use self::verify_attester_slashing::{ pub use self::verify_proposer_slashing::verify_proposer_slashing; pub use altair::sync_committee::process_sync_aggregate; pub use block_signature_verifier::{BlockSignatureVerifier, ParallelSignatureSets}; -pub use deneb::deneb::process_blob_kzg_commitments; pub use is_valid_indexed_attestation::is_valid_indexed_attestation; pub use process_operations::process_operations; pub use verify_attestation::{ @@ -163,11 +162,11 @@ pub fn per_block_processing>( // `process_randao` as the former depends on the `randao_mix` computed with the reveal of the // previous block. if is_execution_enabled(state, block.body()) { - let payload = block.body().execution_payload()?; + let body = block.body(); if state_processing_strategy == StateProcessingStrategy::Accurate { - process_withdrawals::(state, payload, spec)?; + process_withdrawals::(state, body.execution_payload()?, spec)?; } - process_execution_payload::(state, payload, spec)?; + process_execution_payload::(state, body, spec)?; } process_randao(state, block, verify_randao, ctxt, spec)?; @@ -184,8 +183,6 @@ pub fn per_block_processing>( )?; } - process_blob_kzg_commitments(block.body(), ctxt)?; - Ok(()) } @@ -350,9 +347,10 @@ pub fn get_new_eth1_data( pub fn partially_verify_execution_payload>( state: &BeaconState, block_slot: Slot, - payload: Payload::Ref<'_>, + body: BeaconBlockBodyRef, spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { + let payload = body.execution_payload()?; if is_merge_transition_complete(state) { block_verify!( payload.parent_hash() == state.latest_execution_payload_header()?.block_hash(), @@ -379,6 +377,17 @@ pub fn partially_verify_execution_payload>( state: &mut BeaconState, - payload: Payload::Ref<'_>, + body: BeaconBlockBodyRef, spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { - partially_verify_execution_payload::(state, state.slot(), payload, spec)?; - + partially_verify_execution_payload::(state, state.slot(), body, spec)?; + let payload = body.execution_payload()?; match state.latest_execution_payload_header_mut()? { ExecutionPayloadHeaderRefMut::Merge(header_mut) => { match payload.to_execution_payload_header() { diff --git a/consensus/state_processing/src/per_block_processing/deneb/deneb.rs b/consensus/state_processing/src/per_block_processing/deneb/deneb.rs index aacb6b83ff..8f7cb0514f 100644 --- a/consensus/state_processing/src/per_block_processing/deneb/deneb.rs +++ b/consensus/state_processing/src/per_block_processing/deneb/deneb.rs @@ -1,125 +1,8 @@ -use crate::{BlockProcessingError, ConsensusContext}; use ethereum_hashing::hash_fixed; -use itertools::{EitherOrBoth, Itertools}; -use safe_arith::SafeArith; -use ssz::Decode; -use types::consts::deneb::{BLOB_TX_TYPE, VERSIONED_HASH_VERSION_KZG}; -use types::{ - AbstractExecPayload, BeaconBlockBodyRef, EthSpec, ExecPayload, KzgCommitment, Transaction, - Transactions, VersionedHash, -}; +use types::consts::deneb::VERSIONED_HASH_VERSION_KZG; +use types::{KzgCommitment, VersionedHash}; -pub fn process_blob_kzg_commitments>( - block_body: BeaconBlockBodyRef, - ctxt: &mut ConsensusContext, -) -> Result<(), BlockProcessingError> { - // Return early if this check has already been run. - if ctxt.kzg_commitments_consistent() { - return Ok(()); - } - if let (Ok(payload), Ok(kzg_commitments)) = ( - block_body.execution_payload(), - block_body.blob_kzg_commitments(), - ) { - if let Some(transactions) = payload.transactions() { - if !verify_kzg_commitments_against_transactions::(transactions, kzg_commitments)? { - return Err(BlockProcessingError::BlobVersionHashMismatch); - } - } - } - - Ok(()) -} - -pub fn verify_kzg_commitments_against_transactions( - transactions: &Transactions, - kzg_commitments: &[KzgCommitment], -) -> Result { - let nested_iter = transactions - .into_iter() - .filter(|tx| { - tx.first() - .map(|tx_type| *tx_type == BLOB_TX_TYPE) - .unwrap_or(false) - }) - .map(|tx| tx_peek_versioned_hashes::(tx)); - - itertools::process_results(nested_iter, |iter| { - let zipped_iter = iter - .flatten() - // Need to use `itertools::zip_longest` here because just zipping hides if one iter is shorter - // and `itertools::zip_eq` panics. - .zip_longest(kzg_commitments.iter()) - .enumerate() - .map(|(index, next)| match next { - EitherOrBoth::Both(hash, commitment) => Ok((hash?, commitment)), - // The number of versioned hashes from the blob transactions exceeds the number of - // commitments in the block. - EitherOrBoth::Left(_) => Err(BlockProcessingError::BlobNumCommitmentsMismatch { - commitments_processed_in_block: index, - commitments_processed_in_transactions: index.safe_add(1)?, - }), - // The number of commitments in the block exceeds the number of versioned hashes - // in the blob transactions. - EitherOrBoth::Right(_) => Err(BlockProcessingError::BlobNumCommitmentsMismatch { - commitments_processed_in_block: index.safe_add(1)?, - commitments_processed_in_transactions: index, - }), - }); - - itertools::process_results(zipped_iter, |mut iter| { - iter.all(|(tx_versioned_hash, commitment)| { - tx_versioned_hash == kzg_commitment_to_versioned_hash(commitment) - }) - }) - })? -} - -/// Only transactions of type `BLOB_TX_TYPE` should be passed into this function. -fn tx_peek_versioned_hashes( - opaque_tx: &Transaction, -) -> Result< - impl IntoIterator> + '_, - BlockProcessingError, -> { - let tx_len = opaque_tx.len(); - let message_offset = 1.safe_add(u32::from_ssz_bytes(opaque_tx.get(1..5).ok_or( - BlockProcessingError::BlobVersionHashIndexOutOfBounds { - length: tx_len, - index: 5, - }, - )?)?)?; - - let message_offset_usize = message_offset as usize; - - // field offset: 32 + 8 + 32 + 32 + 8 + 4 + 32 + 4 + 4 + 32 = 188 - let versioned_hashes_offset = message_offset.safe_add(u32::from_ssz_bytes( - opaque_tx - .get(message_offset_usize.safe_add(188)?..message_offset_usize.safe_add(192)?) - .ok_or(BlockProcessingError::BlobVersionHashIndexOutOfBounds { - length: tx_len, - index: message_offset_usize.safe_add(192)?, - })?, - )?)?; - - let num_hashes = tx_len - .safe_sub(versioned_hashes_offset as usize)? - .safe_div(32)?; - - Ok((0..num_hashes).map(move |i| { - let next_version_hash_index = - (versioned_hashes_offset as usize).safe_add(i.safe_mul(32)?)?; - let bytes = opaque_tx - .get(next_version_hash_index..next_version_hash_index.safe_add(32)?) - .ok_or(BlockProcessingError::BlobVersionHashIndexOutOfBounds { - length: tx_len, - index: (next_version_hash_index).safe_add(32)?, - })?; - Ok(VersionedHash::from_slice(bytes)) - })) -} - -fn kzg_commitment_to_versioned_hash(kzg_commitment: &KzgCommitment) -> VersionedHash { +pub fn kzg_commitment_to_versioned_hash(kzg_commitment: &KzgCommitment) -> VersionedHash { let mut hashed_commitment = hash_fixed(&kzg_commitment.0); hashed_commitment[0] = VERSIONED_HASH_VERSION_KZG; VersionedHash::from(hashed_commitment) diff --git a/consensus/state_processing/src/per_block_processing/errors.rs b/consensus/state_processing/src/per_block_processing/errors.rs index 5c34afd593..ab6db7e47d 100644 --- a/consensus/state_processing/src/per_block_processing/errors.rs +++ b/consensus/state_processing/src/per_block_processing/errors.rs @@ -76,6 +76,10 @@ pub enum BlockProcessingError { expected: u64, found: u64, }, + ExecutionInvalidBlobsLen { + max: usize, + actual: usize, + }, ExecutionInvalid, ConsensusContext(ContextError), WithdrawalsRootMismatch { diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index 46c5c2a4ce..fc2c466394 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -73,12 +73,12 @@ pub mod validator_subscription; pub mod voluntary_exit; #[macro_use] pub mod slot_epoch_macros; +pub mod body; pub mod config_and_preset; pub mod execution_block_header; pub mod fork_context; pub mod participation_flags; pub mod participation_list; -pub mod payload; pub mod preset; pub mod slot_epoch; pub mod subnet_id; @@ -121,6 +121,11 @@ pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee}; pub use crate::beacon_state::{BeaconTreeHashCache, Error as BeaconStateError, *}; pub use crate::blob_sidecar::{BlobSidecar, BlobSidecarList}; pub use crate::bls_to_execution_change::BlsToExecutionChange; +pub use crate::body::{ + AbstractExecPayload, BlindedPayload, BlindedPayloadCapella, BlindedPayloadDeneb, + BlindedPayloadMerge, BlindedPayloadRef, BlockType, ExecPayload, FullPayload, + FullPayloadCapella, FullPayloadDeneb, FullPayloadMerge, FullPayloadRef, OwnedExecPayload, +}; pub use crate::chain_spec::{ChainSpec, Config, Domain}; pub use crate::checkpoint::Checkpoint; pub use crate::config_and_preset::{ @@ -156,11 +161,6 @@ pub use crate::light_client_finality_update::LightClientFinalityUpdate; pub use crate::light_client_optimistic_update::LightClientOptimisticUpdate; pub use crate::participation_flags::ParticipationFlags; pub use crate::participation_list::ParticipationList; -pub use crate::payload::{ - AbstractExecPayload, BlindedPayload, BlindedPayloadCapella, BlindedPayloadDeneb, - BlindedPayloadMerge, BlindedPayloadRef, BlockType, ExecPayload, FullPayload, - FullPayloadCapella, FullPayloadDeneb, FullPayloadMerge, FullPayloadRef, OwnedExecPayload, -}; pub use crate::pending_attestation::PendingAttestation; pub use crate::preset::{AltairPreset, BasePreset, BellatrixPreset, CapellaPreset}; pub use crate::proposer_preparation_data::ProposerPreparationData; diff --git a/consensus/types/src/payload.rs b/consensus/types/src/payload.rs deleted file mode 100644 index fd15bb5d5d..0000000000 --- a/consensus/types/src/payload.rs +++ /dev/null @@ -1,957 +0,0 @@ -use crate::{test_utils::TestRandom, *}; -use derivative::Derivative; -use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; -use ssz::{Decode, Encode}; -use ssz_derive::{Decode, Encode}; -use std::borrow::Cow; -use std::convert::TryFrom; -use std::fmt::Debug; -use std::hash::Hash; -use test_random_derive::TestRandom; -use tree_hash::TreeHash; -use tree_hash_derive::TreeHash; - -#[derive(Debug, PartialEq)] -pub enum BlockType { - Blinded, - Full, -} - -/// A trait representing behavior of an `ExecutionPayload` that either has a full list of transactions -/// or a transaction hash in it's place. -pub trait ExecPayload: Debug + Clone + PartialEq + Hash + TreeHash + Send { - fn block_type() -> BlockType; - - /// Convert the payload into a payload header. - fn to_execution_payload_header(&self) -> ExecutionPayloadHeader; - - /// We provide a subset of field accessors, for the fields used in `consensus`. - /// - /// More fields can be added here if you wish. - fn parent_hash(&self) -> ExecutionBlockHash; - fn prev_randao(&self) -> Hash256; - fn block_number(&self) -> u64; - fn timestamp(&self) -> u64; - fn block_hash(&self) -> ExecutionBlockHash; - fn fee_recipient(&self) -> Address; - fn gas_limit(&self) -> u64; - fn transactions(&self) -> Option<&Transactions>; - /// fork-specific fields - fn withdrawals_root(&self) -> Result; - - /// Is this a default payload with 0x0 roots for transactions and withdrawals? - fn is_default_with_zero_roots(&self) -> bool; - - /// Is this a default payload with the hash of the empty list for transactions and withdrawals? - fn is_default_with_empty_roots(&self) -> bool; -} - -/// `ExecPayload` functionality the requires ownership. -pub trait OwnedExecPayload: - ExecPayload - + Default - + Serialize - + DeserializeOwned - + Encode - + Decode - + TestRandom - + for<'a> arbitrary::Arbitrary<'a> - + 'static -{ -} - -impl OwnedExecPayload for P where - P: ExecPayload - + Default - + Serialize - + DeserializeOwned - + Encode - + Decode - + TestRandom - + for<'a> arbitrary::Arbitrary<'a> - + 'static -{ -} - -pub trait AbstractExecPayload: - ExecPayload - + Sized - + From> - + TryFrom> - + TryInto - + TryInto - + TryInto -{ - type Ref<'a>: ExecPayload - + Copy - + From<&'a Self::Merge> - + From<&'a Self::Capella> - + From<&'a Self::Deneb>; - - type Merge: OwnedExecPayload - + Into - + for<'a> From>> - + TryFrom>; - type Capella: OwnedExecPayload - + Into - + for<'a> From>> - + TryFrom>; - type Deneb: OwnedExecPayload - + Into - + for<'a> From>> - + TryFrom>; - - fn default_at_fork(fork_name: ForkName) -> Result; -} - -#[superstruct( - variants(Merge, Capella, Deneb), - variant_attributes( - derive( - Debug, - Clone, - Serialize, - Deserialize, - Encode, - Decode, - TestRandom, - TreeHash, - Derivative, - arbitrary::Arbitrary, - ), - derivative(PartialEq, Hash(bound = "T: EthSpec")), - serde(bound = "T: EthSpec", deny_unknown_fields), - arbitrary(bound = "T: EthSpec"), - ssz(struct_behaviour = "transparent"), - ), - ref_attributes( - derive(Debug, Derivative, TreeHash), - derivative(PartialEq, Hash(bound = "T: EthSpec")), - tree_hash(enum_behaviour = "transparent"), - ), - map_into(ExecutionPayload), - map_ref_into(ExecutionPayloadRef), - cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"), - partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant") -)] -#[derive(Debug, Clone, Serialize, Deserialize, TreeHash, Derivative, arbitrary::Arbitrary)] -#[derivative(PartialEq, Hash(bound = "T: EthSpec"))] -#[serde(bound = "T: EthSpec")] -#[arbitrary(bound = "T: EthSpec")] -#[tree_hash(enum_behaviour = "transparent")] -pub struct FullPayload { - #[superstruct(only(Merge), partial_getter(rename = "execution_payload_merge"))] - pub execution_payload: ExecutionPayloadMerge, - #[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))] - pub execution_payload: ExecutionPayloadCapella, - #[superstruct(only(Deneb), partial_getter(rename = "execution_payload_deneb"))] - pub execution_payload: ExecutionPayloadDeneb, -} - -impl From> for ExecutionPayload { - fn from(full_payload: FullPayload) -> Self { - map_full_payload_into_execution_payload!(full_payload, move |payload, cons| { - cons(payload.execution_payload) - }) - } -} - -impl<'a, T: EthSpec> From> for ExecutionPayload { - fn from(full_payload_ref: FullPayloadRef<'a, T>) -> Self { - map_full_payload_ref!(&'a _, full_payload_ref, move |payload, cons| { - cons(payload); - payload.execution_payload.clone().into() - }) - } -} - -impl<'a, T: EthSpec> From> for FullPayload { - fn from(full_payload_ref: FullPayloadRef<'a, T>) -> Self { - map_full_payload_ref!(&'a _, full_payload_ref, move |payload, cons| { - cons(payload); - payload.clone().into() - }) - } -} - -impl ExecPayload for FullPayload { - fn block_type() -> BlockType { - BlockType::Full - } - - fn to_execution_payload_header<'a>(&'a self) -> ExecutionPayloadHeader { - map_full_payload_ref!(&'a _, self.to_ref(), move |inner, cons| { - cons(inner); - let exec_payload_ref: ExecutionPayloadRef<'a, T> = From::from(&inner.execution_payload); - ExecutionPayloadHeader::from(exec_payload_ref) - }) - } - - fn parent_hash<'a>(&'a self) -> ExecutionBlockHash { - map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload.parent_hash - }) - } - - fn prev_randao<'a>(&'a self) -> Hash256 { - map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload.prev_randao - }) - } - - fn block_number<'a>(&'a self) -> u64 { - map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload.block_number - }) - } - - fn timestamp<'a>(&'a self) -> u64 { - map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload.timestamp - }) - } - - fn block_hash<'a>(&'a self) -> ExecutionBlockHash { - map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload.block_hash - }) - } - - fn fee_recipient<'a>(&'a self) -> Address { - map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload.fee_recipient - }) - } - - fn gas_limit<'a>(&'a self) -> u64 { - map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload.gas_limit - }) - } - - fn transactions<'a>(&'a self) -> Option<&'a Transactions> { - map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - Some(&payload.execution_payload.transactions) - }) - } - - fn withdrawals_root(&self) -> Result { - match self { - FullPayload::Merge(_) => Err(Error::IncorrectStateVariant), - FullPayload::Capella(ref inner) => { - Ok(inner.execution_payload.withdrawals.tree_hash_root()) - } - FullPayload::Deneb(ref inner) => { - Ok(inner.execution_payload.withdrawals.tree_hash_root()) - } - } - } - - fn is_default_with_zero_roots<'a>(&'a self) -> bool { - map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload == <_>::default() - }) - } - - fn is_default_with_empty_roots(&self) -> bool { - // For full payloads the empty/zero distinction does not exist. - self.is_default_with_zero_roots() - } -} - -impl FullPayload { - pub fn execution_payload(self) -> ExecutionPayload { - map_full_payload_into_execution_payload!(self, |inner, cons| { - cons(inner.execution_payload) - }) - } -} - -impl<'a, T: EthSpec> FullPayloadRef<'a, T> { - pub fn execution_payload_ref(self) -> ExecutionPayloadRef<'a, T> { - map_full_payload_ref_into_execution_payload_ref!(&'a _, self, |inner, cons| { - cons(&inner.execution_payload) - }) - } -} - -impl<'b, T: EthSpec> ExecPayload for FullPayloadRef<'b, T> { - fn block_type() -> BlockType { - BlockType::Full - } - - fn to_execution_payload_header<'a>(&'a self) -> ExecutionPayloadHeader { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.to_execution_payload_header() - }) - } - - fn parent_hash<'a>(&'a self) -> ExecutionBlockHash { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload.parent_hash - }) - } - - fn prev_randao<'a>(&'a self) -> Hash256 { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload.prev_randao - }) - } - - fn block_number<'a>(&'a self) -> u64 { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload.block_number - }) - } - - fn timestamp<'a>(&'a self) -> u64 { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload.timestamp - }) - } - - fn block_hash<'a>(&'a self) -> ExecutionBlockHash { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload.block_hash - }) - } - - fn fee_recipient<'a>(&'a self) -> Address { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload.fee_recipient - }) - } - - fn gas_limit<'a>(&'a self) -> u64 { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload.gas_limit - }) - } - - fn transactions<'a>(&'a self) -> Option<&'a Transactions> { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - Some(&payload.execution_payload.transactions) - }) - } - - fn withdrawals_root(&self) -> Result { - match self { - FullPayloadRef::Merge(_) => Err(Error::IncorrectStateVariant), - FullPayloadRef::Capella(inner) => { - Ok(inner.execution_payload.withdrawals.tree_hash_root()) - } - FullPayloadRef::Deneb(inner) => { - Ok(inner.execution_payload.withdrawals.tree_hash_root()) - } - } - } - - fn is_default_with_zero_roots<'a>(&'a self) -> bool { - map_full_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload == <_>::default() - }) - } - - fn is_default_with_empty_roots(&self) -> bool { - // For full payloads the empty/zero distinction does not exist. - self.is_default_with_zero_roots() - } -} - -impl AbstractExecPayload for FullPayload { - type Ref<'a> = FullPayloadRef<'a, T>; - type Merge = FullPayloadMerge; - type Capella = FullPayloadCapella; - type Deneb = FullPayloadDeneb; - - fn default_at_fork(fork_name: ForkName) -> Result { - match fork_name { - ForkName::Base | ForkName::Altair => Err(Error::IncorrectStateVariant), - ForkName::Merge => Ok(FullPayloadMerge::default().into()), - ForkName::Capella => Ok(FullPayloadCapella::default().into()), - ForkName::Deneb => Ok(FullPayloadDeneb::default().into()), - } - } -} - -impl From> for FullPayload { - fn from(execution_payload: ExecutionPayload) -> Self { - map_execution_payload_into_full_payload!(execution_payload, |inner, cons| { - cons(inner.into()) - }) - } -} - -impl TryFrom> for FullPayload { - type Error = (); - fn try_from(_: ExecutionPayloadHeader) -> Result { - Err(()) - } -} - -#[superstruct( - variants(Merge, Capella, Deneb), - variant_attributes( - derive( - Debug, - Clone, - Serialize, - Deserialize, - Encode, - Decode, - TestRandom, - TreeHash, - Derivative, - arbitrary::Arbitrary - ), - derivative(PartialEq, Hash(bound = "T: EthSpec")), - serde(bound = "T: EthSpec", deny_unknown_fields), - arbitrary(bound = "T: EthSpec"), - ssz(struct_behaviour = "transparent"), - ), - ref_attributes( - derive(Debug, Derivative, TreeHash), - derivative(PartialEq, Hash(bound = "T: EthSpec")), - tree_hash(enum_behaviour = "transparent"), - ), - map_into(ExecutionPayloadHeader), - cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"), - partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant") -)] -#[derive(Debug, Clone, Serialize, Deserialize, TreeHash, Derivative, arbitrary::Arbitrary)] -#[derivative(PartialEq, Hash(bound = "T: EthSpec"))] -#[serde(bound = "T: EthSpec")] -#[arbitrary(bound = "T: EthSpec")] -#[tree_hash(enum_behaviour = "transparent")] -pub struct BlindedPayload { - #[superstruct(only(Merge), partial_getter(rename = "execution_payload_merge"))] - pub execution_payload_header: ExecutionPayloadHeaderMerge, - #[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))] - pub execution_payload_header: ExecutionPayloadHeaderCapella, - #[superstruct(only(Deneb), partial_getter(rename = "execution_payload_deneb"))] - pub execution_payload_header: ExecutionPayloadHeaderDeneb, -} - -impl<'a, T: EthSpec> From> for BlindedPayload { - fn from(blinded_payload_ref: BlindedPayloadRef<'a, T>) -> Self { - map_blinded_payload_ref!(&'a _, blinded_payload_ref, move |payload, cons| { - cons(payload); - payload.clone().into() - }) - } -} - -impl ExecPayload for BlindedPayload { - fn block_type() -> BlockType { - BlockType::Blinded - } - - fn to_execution_payload_header(&self) -> ExecutionPayloadHeader { - map_blinded_payload_into_execution_payload_header!(self.clone(), |inner, cons| { - cons(inner.execution_payload_header) - }) - } - - fn parent_hash<'a>(&'a self) -> ExecutionBlockHash { - map_blinded_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload_header.parent_hash - }) - } - - fn prev_randao<'a>(&'a self) -> Hash256 { - map_blinded_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload_header.prev_randao - }) - } - - fn block_number<'a>(&'a self) -> u64 { - map_blinded_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload_header.block_number - }) - } - - fn timestamp<'a>(&'a self) -> u64 { - map_blinded_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload_header.timestamp - }) - } - - fn block_hash<'a>(&'a self) -> ExecutionBlockHash { - map_blinded_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload_header.block_hash - }) - } - - fn fee_recipient<'a>(&'a self) -> Address { - map_blinded_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload_header.fee_recipient - }) - } - - fn gas_limit<'a>(&'a self) -> u64 { - map_blinded_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { - cons(payload); - payload.execution_payload_header.gas_limit - }) - } - - fn transactions(&self) -> Option<&Transactions> { - None - } - - fn withdrawals_root(&self) -> Result { - match self { - BlindedPayload::Merge(_) => Err(Error::IncorrectStateVariant), - BlindedPayload::Capella(ref inner) => { - Ok(inner.execution_payload_header.withdrawals_root) - } - BlindedPayload::Deneb(ref inner) => Ok(inner.execution_payload_header.withdrawals_root), - } - } - - fn is_default_with_zero_roots(&self) -> bool { - self.to_ref().is_default_with_zero_roots() - } - - // For blinded payloads we must check "defaultness" against the default `ExecutionPayload` - // which has been blinded into an `ExecutionPayloadHeader`, NOT against the default - // `ExecutionPayloadHeader` which has a zeroed out `transactions_root`. The transactions root - // should be the root of the empty list. - fn is_default_with_empty_roots(&self) -> bool { - self.to_ref().is_default_with_empty_roots() - } -} - -impl<'b, T: EthSpec> ExecPayload for BlindedPayloadRef<'b, T> { - fn block_type() -> BlockType { - BlockType::Blinded - } - - fn to_execution_payload_header<'a>(&'a self) -> ExecutionPayloadHeader { - map_blinded_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.to_execution_payload_header() - }) - } - - fn parent_hash<'a>(&'a self) -> ExecutionBlockHash { - map_blinded_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload_header.parent_hash - }) - } - - fn prev_randao<'a>(&'a self) -> Hash256 { - map_blinded_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload_header.prev_randao - }) - } - - fn block_number<'a>(&'a self) -> u64 { - map_blinded_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload_header.block_number - }) - } - - fn timestamp<'a>(&'a self) -> u64 { - map_blinded_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload_header.timestamp - }) - } - - fn block_hash<'a>(&'a self) -> ExecutionBlockHash { - map_blinded_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload_header.block_hash - }) - } - - fn fee_recipient<'a>(&'a self) -> Address { - map_blinded_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload_header.fee_recipient - }) - } - - fn gas_limit<'a>(&'a self) -> u64 { - map_blinded_payload_ref!(&'a _, self, move |payload, cons| { - cons(payload); - payload.execution_payload_header.gas_limit - }) - } - - fn transactions(&self) -> Option<&Transactions> { - None - } - - fn withdrawals_root(&self) -> Result { - match self { - BlindedPayloadRef::Merge(_) => Err(Error::IncorrectStateVariant), - BlindedPayloadRef::Capella(inner) => { - Ok(inner.execution_payload_header.withdrawals_root) - } - BlindedPayloadRef::Deneb(inner) => Ok(inner.execution_payload_header.withdrawals_root), - } - } - - fn is_default_with_zero_roots<'a>(&'a self) -> bool { - map_blinded_payload_ref!(&'b _, self, move |payload, cons| { - cons(payload); - payload.execution_payload_header == <_>::default() - }) - } - - fn is_default_with_empty_roots<'a>(&'a self) -> bool { - map_blinded_payload_ref!(&'b _, self, move |payload, cons| { - cons(payload); - payload.is_default_with_empty_roots() - }) - } -} - -macro_rules! impl_exec_payload_common { - ($wrapper_type:ident, // BlindedPayloadMerge | FullPayloadMerge - $wrapped_type:ident, // ExecutionPayloadHeaderMerge | ExecutionPayloadMerge - $wrapped_type_full:ident, // ExecutionPayloadMerge | ExecutionPayloadMerge - $wrapped_type_header:ident, // ExecutionPayloadHeaderMerge | ExecutionPayloadHeaderMerge - $wrapped_field:ident, // execution_payload_header | execution_payload - $fork_variant:ident, // Merge | Merge - $block_type_variant:ident, // Blinded | Full - $is_default_with_empty_roots:block, - $f:block, - $g:block) => { - impl ExecPayload for $wrapper_type { - fn block_type() -> BlockType { - BlockType::$block_type_variant - } - - fn to_execution_payload_header(&self) -> ExecutionPayloadHeader { - ExecutionPayloadHeader::$fork_variant($wrapped_type_header::from( - &self.$wrapped_field, - )) - } - - fn parent_hash(&self) -> ExecutionBlockHash { - self.$wrapped_field.parent_hash - } - - fn prev_randao(&self) -> Hash256 { - self.$wrapped_field.prev_randao - } - - fn block_number(&self) -> u64 { - self.$wrapped_field.block_number - } - - fn timestamp(&self) -> u64 { - self.$wrapped_field.timestamp - } - - fn block_hash(&self) -> ExecutionBlockHash { - self.$wrapped_field.block_hash - } - - fn fee_recipient(&self) -> Address { - self.$wrapped_field.fee_recipient - } - - fn gas_limit(&self) -> u64 { - self.$wrapped_field.gas_limit - } - - fn is_default_with_zero_roots(&self) -> bool { - self.$wrapped_field == $wrapped_type::default() - } - - fn is_default_with_empty_roots(&self) -> bool { - let f = $is_default_with_empty_roots; - f(self) - } - - fn transactions(&self) -> Option<&Transactions> { - let f = $f; - f(self) - } - - fn withdrawals_root(&self) -> Result { - let g = $g; - g(self) - } - } - - impl From<$wrapped_type> for $wrapper_type { - fn from($wrapped_field: $wrapped_type) -> Self { - Self { $wrapped_field } - } - } - }; -} - -macro_rules! impl_exec_payload_for_fork { - // BlindedPayloadMerge, FullPayloadMerge, ExecutionPayloadHeaderMerge, ExecutionPayloadMerge, Merge - ($wrapper_type_header:ident, $wrapper_type_full:ident, $wrapped_type_header:ident, $wrapped_type_full:ident, $fork_variant:ident) => { - //*************** Blinded payload implementations ******************// - - impl_exec_payload_common!( - $wrapper_type_header, // BlindedPayloadMerge - $wrapped_type_header, // ExecutionPayloadHeaderMerge - $wrapped_type_full, // ExecutionPayloadMerge - $wrapped_type_header, // ExecutionPayloadHeaderMerge - execution_payload_header, - $fork_variant, // Merge - Blinded, - { - |wrapper: &$wrapper_type_header| { - wrapper.execution_payload_header - == $wrapped_type_header::from(&$wrapped_type_full::default()) - } - }, - { |_| { None } }, - { - let c: for<'a> fn(&'a $wrapper_type_header) -> Result = - |payload: &$wrapper_type_header| { - let wrapper_ref_type = BlindedPayloadRef::$fork_variant(&payload); - wrapper_ref_type.withdrawals_root() - }; - c - } - ); - - impl TryInto<$wrapper_type_header> for BlindedPayload { - type Error = Error; - - fn try_into(self) -> Result<$wrapper_type_header, Self::Error> { - match self { - BlindedPayload::$fork_variant(payload) => Ok(payload), - _ => Err(Error::IncorrectStateVariant), - } - } - } - - // NOTE: the `Default` implementation for `BlindedPayload` needs to be different from the `Default` - // implementation for `ExecutionPayloadHeader` because payloads are checked for equality against the - // default payload in `is_merge_transition_block` to determine whether the merge has occurred. - // - // The default `BlindedPayload` is therefore the payload header that results from blinding the - // default `ExecutionPayload`, which differs from the default `ExecutionPayloadHeader` in that - // its `transactions_root` is the hash of the empty list rather than 0x0. - impl Default for $wrapper_type_header { - fn default() -> Self { - Self { - execution_payload_header: $wrapped_type_header::from( - &$wrapped_type_full::default(), - ), - } - } - } - - impl TryFrom> for $wrapper_type_header { - type Error = Error; - fn try_from(header: ExecutionPayloadHeader) -> Result { - match header { - ExecutionPayloadHeader::$fork_variant(execution_payload_header) => { - Ok(execution_payload_header.into()) - } - _ => Err(Error::PayloadConversionLogicFlaw), - } - } - } - - // BlindedPayload* from CoW reference to ExecutionPayload* (hopefully just a reference). - impl<'a, T: EthSpec> From>> for $wrapper_type_header { - fn from(execution_payload: Cow<'a, $wrapped_type_full>) -> Self { - Self { - execution_payload_header: $wrapped_type_header::from(&*execution_payload), - } - } - } - - //*************** Full payload implementations ******************// - - impl_exec_payload_common!( - $wrapper_type_full, // FullPayloadMerge - $wrapped_type_full, // ExecutionPayloadMerge - $wrapped_type_full, // ExecutionPayloadMerge - $wrapped_type_header, // ExecutionPayloadHeaderMerge - execution_payload, - $fork_variant, // Merge - Full, - { - |wrapper: &$wrapper_type_full| { - wrapper.execution_payload == $wrapped_type_full::default() - } - }, - { - let c: for<'a> fn(&'a $wrapper_type_full) -> Option<&'a Transactions> = - |payload: &$wrapper_type_full| Some(&payload.execution_payload.transactions); - c - }, - { - let c: for<'a> fn(&'a $wrapper_type_full) -> Result = - |payload: &$wrapper_type_full| { - let wrapper_ref_type = FullPayloadRef::$fork_variant(&payload); - wrapper_ref_type.withdrawals_root() - }; - c - } - ); - - impl Default for $wrapper_type_full { - fn default() -> Self { - Self { - execution_payload: $wrapped_type_full::default(), - } - } - } - - // FullPayload * from CoW reference to ExecutionPayload* (hopefully already owned). - impl<'a, T: EthSpec> From>> for $wrapper_type_full { - fn from(execution_payload: Cow<'a, $wrapped_type_full>) -> Self { - Self { - execution_payload: $wrapped_type_full::from(execution_payload.into_owned()), - } - } - } - - impl TryFrom> for $wrapper_type_full { - type Error = Error; - fn try_from(_: ExecutionPayloadHeader) -> Result { - Err(Error::PayloadConversionLogicFlaw) - } - } - - impl TryFrom<$wrapped_type_header> for $wrapper_type_full { - type Error = Error; - fn try_from(_: $wrapped_type_header) -> Result { - Err(Error::PayloadConversionLogicFlaw) - } - } - - impl TryInto<$wrapper_type_full> for FullPayload { - type Error = Error; - - fn try_into(self) -> Result<$wrapper_type_full, Self::Error> { - match self { - FullPayload::$fork_variant(payload) => Ok(payload), - _ => Err(Error::PayloadConversionLogicFlaw), - } - } - } - }; -} - -impl_exec_payload_for_fork!( - BlindedPayloadMerge, - FullPayloadMerge, - ExecutionPayloadHeaderMerge, - ExecutionPayloadMerge, - Merge -); -impl_exec_payload_for_fork!( - BlindedPayloadCapella, - FullPayloadCapella, - ExecutionPayloadHeaderCapella, - ExecutionPayloadCapella, - Capella -); -impl_exec_payload_for_fork!( - BlindedPayloadDeneb, - FullPayloadDeneb, - ExecutionPayloadHeaderDeneb, - ExecutionPayloadDeneb, - Deneb -); - -impl AbstractExecPayload for BlindedPayload { - type Ref<'a> = BlindedPayloadRef<'a, T>; - type Merge = BlindedPayloadMerge; - type Capella = BlindedPayloadCapella; - type Deneb = BlindedPayloadDeneb; - - fn default_at_fork(fork_name: ForkName) -> Result { - match fork_name { - ForkName::Base | ForkName::Altair => Err(Error::IncorrectStateVariant), - ForkName::Merge => Ok(BlindedPayloadMerge::default().into()), - ForkName::Capella => Ok(BlindedPayloadCapella::default().into()), - ForkName::Deneb => Ok(BlindedPayloadDeneb::default().into()), - } - } -} - -impl From> for BlindedPayload { - fn from(payload: ExecutionPayload) -> Self { - // This implementation is a bit wasteful in that it discards the payload body. - // Required by the top-level constraint on AbstractExecPayload but could maybe be loosened - // in future. - map_execution_payload_into_blinded_payload!(payload, |inner, cons| cons(From::from( - Cow::Owned(inner) - ))) - } -} - -impl From> for BlindedPayload { - fn from(execution_payload_header: ExecutionPayloadHeader) -> Self { - match execution_payload_header { - ExecutionPayloadHeader::Merge(execution_payload_header) => { - Self::Merge(BlindedPayloadMerge { - execution_payload_header, - }) - } - ExecutionPayloadHeader::Capella(execution_payload_header) => { - Self::Capella(BlindedPayloadCapella { - execution_payload_header, - }) - } - ExecutionPayloadHeader::Deneb(execution_payload_header) => { - Self::Deneb(BlindedPayloadDeneb { - execution_payload_header, - }) - } - } - } -} - -impl From> for ExecutionPayloadHeader { - fn from(blinded: BlindedPayload) -> Self { - match blinded { - BlindedPayload::Merge(blinded_payload) => { - ExecutionPayloadHeader::Merge(blinded_payload.execution_payload_header) - } - BlindedPayload::Capella(blinded_payload) => { - ExecutionPayloadHeader::Capella(blinded_payload.execution_payload_header) - } - BlindedPayload::Deneb(blinded_payload) => { - ExecutionPayloadHeader::Deneb(blinded_payload.execution_payload_header) - } - } - } -} diff --git a/testing/ef_tests/src/cases/operations.rs b/testing/ef_tests/src/cases/operations.rs index 2f27b43a1d..abd511ede7 100644 --- a/testing/ef_tests/src/cases/operations.rs +++ b/testing/ef_tests/src/cases/operations.rs @@ -4,6 +4,7 @@ use crate::case_result::compare_beacon_state_results_without_caches; use crate::decode::{ssz_decode_file, ssz_decode_file_with, ssz_decode_state, yaml_decode_file}; use crate::testing_spec; use serde_derive::Deserialize; +use ssz::Decode; use state_processing::{ per_block_processing::{ errors::BlockProcessingError, @@ -19,9 +20,9 @@ use state_processing::{ use std::fmt::Debug; use std::path::Path; use types::{ - Attestation, AttesterSlashing, BeaconBlock, BeaconState, BlindedPayload, ChainSpec, Deposit, - EthSpec, ExecutionPayload, ForkName, FullPayload, ProposerSlashing, SignedBlsToExecutionChange, - SignedVoluntaryExit, SyncAggregate, + map_fork_name, map_fork_name_with, Attestation, AttesterSlashing, BeaconBlock, BeaconBlockBody, + BeaconState, BlindedPayload, ChainSpec, Deposit, EthSpec, ExecutionPayload, ForkName, + FullPayload, ProposerSlashing, SignedBlsToExecutionChange, SignedVoluntaryExit, SyncAggregate, }; #[derive(Debug, Clone, Default, Deserialize)] @@ -259,13 +260,13 @@ impl Operation for SyncAggregate { } } -impl Operation for FullPayload { +impl Operation for BeaconBlockBody> { fn handler_name() -> String { "execution_payload".into() } fn filename() -> String { - "execution_payload.ssz_snappy".into() + "body.ssz_snappy".into() } fn is_enabled_for_fork(fork_name: ForkName) -> bool { @@ -274,9 +275,8 @@ impl Operation for FullPayload { fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result { ssz_decode_file_with(path, |bytes| { - ExecutionPayload::from_ssz_bytes(bytes, fork_name) + Ok(map_fork_name!(fork_name, Self, <_>::from_ssz_bytes(bytes)?)) }) - .map(Into::into) } fn apply_to( @@ -296,13 +296,13 @@ impl Operation for FullPayload { } } } -impl Operation for BlindedPayload { +impl Operation for BeaconBlockBody> { fn handler_name() -> String { "execution_payload".into() } fn filename() -> String { - "execution_payload.ssz_snappy".into() + "body.ssz_snappy".into() } fn is_enabled_for_fork(fork_name: ForkName) -> bool { @@ -311,9 +311,8 @@ impl Operation for BlindedPayload { fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result { ssz_decode_file_with(path, |bytes| { - ExecutionPayload::from_ssz_bytes(bytes, fork_name) + Ok(map_fork_name!(fork_name, Self, <_>::from_ssz_bytes(bytes)?)) }) - .map(Into::into) } fn apply_to( diff --git a/testing/execution_engine_integration/src/test_rig.rs b/testing/execution_engine_integration/src/test_rig.rs index 726019a848..57fd7a55b3 100644 --- a/testing/execution_engine_integration/src/test_rig.rs +++ b/testing/execution_engine_integration/src/test_rig.rs @@ -371,7 +371,7 @@ impl TestRig { let status = self .ee_a .execution_layer - .notify_new_payload(&valid_payload) + .notify_new_payload(&valid_payload, None) .await .unwrap(); assert_eq!(status, PayloadStatus::Valid); @@ -424,7 +424,7 @@ impl TestRig { let status = self .ee_a .execution_layer - .notify_new_payload(&invalid_payload) + .notify_new_payload(&invalid_payload, None) .await .unwrap(); assert!(matches!( @@ -486,7 +486,7 @@ impl TestRig { let status = self .ee_a .execution_layer - .notify_new_payload(&second_payload) + .notify_new_payload(&second_payload, None) .await .unwrap(); assert_eq!(status, PayloadStatus::Valid); @@ -533,7 +533,7 @@ impl TestRig { let status = self .ee_b .execution_layer - .notify_new_payload(&second_payload) + .notify_new_payload(&second_payload, None) .await .unwrap(); // TODO: we should remove the `Accepted` status here once Geth fixes it @@ -574,7 +574,7 @@ impl TestRig { let status = self .ee_b .execution_layer - .notify_new_payload(&valid_payload) + .notify_new_payload(&valid_payload, None) .await .unwrap(); assert_eq!(status, PayloadStatus::Valid); @@ -588,7 +588,7 @@ impl TestRig { let status = self .ee_b .execution_layer - .notify_new_payload(&second_payload) + .notify_new_payload(&second_payload, None) .await .unwrap(); assert_eq!(status, PayloadStatus::Valid);