From fa109e3a41bc84ca0721a218003ff3c45dcbc36e Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 3 Jan 2025 22:15:01 +0100 Subject: [PATCH] feat: add additional conversion fn (#1883) --- crates/rpc-types-engine/src/payload.rs | 44 +++++++++++++++++++++++++- crates/rpc-types-engine/src/sidecar.rs | 27 ++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/crates/rpc-types-engine/src/payload.rs b/crates/rpc-types-engine/src/payload.rs index 937b6836537..94b5a0c6f02 100644 --- a/crates/rpc-types-engine/src/payload.rs +++ b/crates/rpc-types-engine/src/payload.rs @@ -6,7 +6,7 @@ use alloc::{ vec::Vec, }; use alloy_consensus::{ - constants::MAXIMUM_EXTRA_DATA_SIZE, Blob, Block, BlockBody, Bytes48, Header, + constants::MAXIMUM_EXTRA_DATA_SIZE, Blob, Block, BlockBody, Bytes48, Header, Transaction, EMPTY_OMMER_ROOT_HASH, }; use alloy_eips::{ @@ -770,6 +770,48 @@ pub enum ExecutionPayload { } impl ExecutionPayload { + /// Converts [`alloy_consensus::Block`] to [`ExecutionPayload`] and also returns the + /// [`ExecutionPayloadSidecar`] extracted from the block. + /// + /// See also [`ExecutionPayloadV3::from_block_unchecked`]. + /// See also [`ExecutionPayloadSidecar::from_block`]. + /// + /// Note: This re-calculates the block hash. + pub fn from_block_slow(block: &Block) -> (Self, ExecutionPayloadSidecar) + where + T: Encodable2718 + Transaction, + { + Self::from_block_unchecked(block.hash_slow(), block) + } + + /// Converts [`alloy_consensus::Block`] to [`ExecutionPayload`] and also returns the + /// [`ExecutionPayloadSidecar`] extracted from the block. + /// + /// See also [`ExecutionPayloadV3::from_block_unchecked`]. + /// See also [`ExecutionPayloadSidecar::from_block`]. + pub fn from_block_unchecked( + block_hash: B256, + block: &Block, + ) -> (Self, ExecutionPayloadSidecar) + where + T: Encodable2718 + Transaction, + { + let sidecar = ExecutionPayloadSidecar::from_block(block); + + let execution_payload = if block.header.parent_beacon_block_root.is_some() { + // block with parent beacon block root: V3 + Self::V3(ExecutionPayloadV3::from_block_unchecked(block_hash, block)) + } else if block.body.withdrawals.is_some() { + // block with withdrawals: V2 + Self::V2(ExecutionPayloadV2::from_block_unchecked(block_hash, block)) + } else { + // otherwise V1 + Self::V1(ExecutionPayloadV1::from_block_unchecked(block_hash, block)) + }; + + (execution_payload, sidecar) + } + /// Tries to create a new unsealed block from the given payload and payload sidecar. /// /// Performs additional validation of `extra_data` and `base_fee_per_gas` fields. diff --git a/crates/rpc-types-engine/src/sidecar.rs b/crates/rpc-types-engine/src/sidecar.rs index 79db14d3644..c7262d593fb 100644 --- a/crates/rpc-types-engine/src/sidecar.rs +++ b/crates/rpc-types-engine/src/sidecar.rs @@ -4,6 +4,7 @@ use crate::{ CancunPayloadFields, MaybeCancunPayloadFields, MaybePraguePayloadFields, PraguePayloadFields, }; use alloc::vec::Vec; +use alloy_consensus::{Block, Transaction}; use alloy_eips::eip7685::Requests; use alloy_primitives::B256; @@ -21,6 +22,32 @@ pub struct ExecutionPayloadSidecar { } impl ExecutionPayloadSidecar { + /// Extracts the [`ExecutionPayloadSidecar`] from the given [`alloy_consensus::Block`]. + /// + /// Returns [`ExecutionPayloadSidecar::none`] if the block does not contain any sidecar fields + /// (pre-cancun): `requests_hash`, `parent_beacon_block_root`, `blob_versioned_hashes`. + /// + /// Note: This returns [`RequestOrHash::Hash`](alloy_eips::eip7685::RequestsOrHash::Hash) for + /// the EIP-7685 requests. + pub fn from_block(block: &Block) -> Self + where + T: Transaction, + { + let cancun = + block.parent_beacon_block_root.map(|parent_beacon_block_root| CancunPayloadFields { + parent_beacon_block_root, + versioned_hashes: block.body.blob_versioned_hashes_iter().copied().collect(), + }); + + let prague = block.requests_hash.map(PraguePayloadFields::new); + + match (cancun, prague) { + (Some(cancun), Some(prague)) => Self::v4(cancun, prague), + (Some(cancun), None) => Self::v3(cancun), + _ => Self::none(), + } + } + /// Returns a new empty instance (pre-cancun, v1, v2) pub const fn none() -> Self { Self { cancun: MaybeCancunPayloadFields::none(), prague: MaybePraguePayloadFields::none() }