From 7413f11aa2fe54dffaa30b9680ee54b67e0e14fb Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Mon, 3 Mar 2025 21:11:57 +0400 Subject: [PATCH] feat: `ConfigureEvm::NextBlockEnvCtx` (#14801) --- crates/ethereum/evm/src/execute.rs | 21 +++++++------- crates/ethereum/evm/src/lib.rs | 3 +- crates/ethereum/node/src/node.rs | 6 ++-- crates/ethereum/payload/src/lib.rs | 12 ++++++-- crates/evm/src/execute.rs | 17 +++++------ crates/evm/src/lib.rs | 13 ++++++--- crates/optimism/evm/src/config.rs | 18 ++++++++++++ crates/optimism/evm/src/execute.rs | 8 ++--- crates/optimism/evm/src/lib.rs | 7 +++-- crates/optimism/node/src/node.rs | 12 ++++++-- crates/optimism/payload/src/builder.rs | 29 +++++++++++++------ crates/optimism/rpc/src/eth/pending_block.rs | 18 +++++++++++- crates/optimism/rpc/src/witness.rs | 6 +++- crates/rpc/rpc-eth-api/src/helpers/call.rs | 2 +- .../rpc-eth-api/src/helpers/pending_block.rs | 17 +++-------- .../rpc/rpc/src/eth/helpers/pending_block.rs | 19 ++++++++++-- .../custom-beacon-withdrawals/src/main.rs | 21 +++++++------- 17 files changed, 150 insertions(+), 79 deletions(-) diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index ba16a29cba..aa15b60d11 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -4,7 +4,7 @@ use crate::{ dao_fork::{DAO_HARDFORK_ACCOUNTS, DAO_HARDFORK_BENEFICIARY}, EthEvmConfig, }; -use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec}; use alloy_consensus::{Header, Transaction}; use alloy_eips::{eip4895::Withdrawals, eip6110, eip7685::Requests}; use alloy_evm::FromRecoveredTx; @@ -17,8 +17,7 @@ use reth_evm::{ }, state_change::post_block_balance_increments, system_calls::{OnStateHook, StateChangePostBlockSource, StateChangeSource, SystemCaller}, - Database, Evm, EvmEnv, EvmFactory, EvmFor, InspectorFor, NextBlockEnvAttributes, - TransactionEnv, + Database, Evm, EvmEnv, EvmFactory, EvmFor, InspectorFor, TransactionEnv, }; use reth_execution_types::BlockExecutionResult; use reth_primitives::{ @@ -48,20 +47,20 @@ where parent_hash: block.header().parent_hash, parent_beacon_block_root: block.header().parent_beacon_block_root, ommers: &block.body().ommers, - withdrawals: block.body().withdrawals.as_ref(), + withdrawals: block.body().withdrawals.as_ref().map(Cow::Borrowed), } } - fn context_for_next_block<'a>( + fn context_for_next_block( &self, parent: &SealedHeader, - attributes: NextBlockEnvAttributes<'a>, - ) -> Self::ExecutionCtx<'a> { + attributes: Self::NextBlockEnvCtx, + ) -> Self::ExecutionCtx<'_> { EthBlockExecutionCtx { parent_hash: parent.hash(), parent_beacon_block_root: attributes.parent_beacon_block_root, ommers: &[], - withdrawals: attributes.withdrawals, + withdrawals: attributes.withdrawals.map(Cow::Owned), } } @@ -79,7 +78,7 @@ where } /// Context for Ethereum block execution. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct EthBlockExecutionCtx<'a> { /// Parent block hash. pub parent_hash: B256, @@ -88,7 +87,7 @@ pub struct EthBlockExecutionCtx<'a> { /// Block ommers pub ommers: &'a [Header], /// Block withdrawals. - pub withdrawals: Option<&'a Withdrawals>, + pub withdrawals: Option>, } /// Block execution strategy for Ethereum. @@ -216,7 +215,7 @@ where self.chain_spec, self.evm.block(), self.ctx.ommers, - self.ctx.withdrawals, + self.ctx.withdrawals.as_deref(), ); // Irregular state change at Ethereum DAO hardfork diff --git a/crates/ethereum/evm/src/lib.rs b/crates/ethereum/evm/src/lib.rs index 6993b379dc..f9541b8cf1 100644 --- a/crates/ethereum/evm/src/lib.rs +++ b/crates/ethereum/evm/src/lib.rs @@ -96,6 +96,7 @@ where type Error = Infallible; type TxEnv = EvmF::Tx; type Spec = SpecId; + type NextBlockEnvCtx = NextBlockEnvAttributes; fn evm_env(&self, header: &Self::Header) -> EvmEnv { let spec = config::revm_spec(self.chain_spec(), header); @@ -123,7 +124,7 @@ where fn next_evm_env( &self, parent: &Self::Header, - attributes: NextBlockEnvAttributes<'_>, + attributes: &NextBlockEnvAttributes, ) -> Result { // ensure we're not missing any timestamp based hardforks let spec_id = revm_spec_by_timestamp_and_block_number( diff --git a/crates/ethereum/node/src/node.rs b/crates/ethereum/node/src/node.rs index 48c8889755..1b09a5c6c6 100644 --- a/crates/ethereum/node/src/node.rs +++ b/crates/ethereum/node/src/node.rs @@ -9,7 +9,7 @@ use reth_ethereum_engine_primitives::{ EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes, }; use reth_ethereum_primitives::{EthPrimitives, PooledTransaction}; -use reth_evm::{execute::BasicBlockExecutorProvider, ConfigureEvm}; +use reth_evm::{execute::BasicBlockExecutorProvider, ConfigureEvm, NextBlockEnvAttributes}; use reth_network::{EthNetworkPrimitives, NetworkHandle, PeersInfo}; use reth_node_api::{AddOnsContext, BlockTy, FullNodeComponents, NodeAddOns, ReceiptTy, TxTy}; use reth_node_builder::{ @@ -178,7 +178,7 @@ where Primitives = EthPrimitives, Engine = EthEngineTypes, >, - Evm: ConfigureEvm, + Evm: ConfigureEvm, >, EthApiError: FromEvmError, { @@ -218,7 +218,7 @@ where Primitives = EthPrimitives, Engine = EthEngineTypes, >, - Evm: ConfigureEvm, + Evm: ConfigureEvm, >, EthApiError: FromEvmError, { diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index c39e2a0b45..2920f58dca 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -84,7 +84,10 @@ impl EthereumPayloadBuilder { // Default implementation of [PayloadBuilder] for unit type impl PayloadBuilder for EthereumPayloadBuilder where - EvmConfig: BlockExecutionStrategyFactory, + EvmConfig: BlockExecutionStrategyFactory< + Primitives = EthPrimitives, + NextBlockEnvCtx = NextBlockEnvAttributes, + >, Client: StateProviderFactory + ChainSpecProvider + Clone, Pool: TransactionPool>, { @@ -139,7 +142,10 @@ pub fn default_ethereum_payload( best_txs: F, ) -> Result, PayloadBuilderError> where - EvmConfig: BlockExecutionStrategyFactory, + EvmConfig: BlockExecutionStrategyFactory< + Primitives = EthPrimitives, + NextBlockEnvCtx = NextBlockEnvAttributes, + >, Client: StateProviderFactory + ChainSpecProvider, Pool: TransactionPool>, F: FnOnce(BestTransactionsAttributes) -> BestTransactionsIter, @@ -158,7 +164,7 @@ where prev_randao: attributes.prev_randao(), gas_limit: builder_config.gas_limit(parent_header.gas_limit), parent_beacon_block_root: attributes.parent_beacon_block_root(), - withdrawals: Some(attributes.withdrawals()), + withdrawals: Some(attributes.withdrawals().clone()), }; let mut strategy = evm_config diff --git a/crates/evm/src/execute.rs b/crates/evm/src/execute.rs index 13c3d0b28f..4785856215 100644 --- a/crates/evm/src/execute.rs +++ b/crates/evm/src/execute.rs @@ -3,10 +3,7 @@ use alloy_consensus::BlockHeader; use alloy_evm::Evm; // Re-export execution types -use crate::{ - system_calls::OnStateHook, ConfigureEvmFor, Database, EvmFor, InspectorFor, - NextBlockEnvAttributes, -}; +use crate::{system_calls::OnStateHook, ConfigureEvmFor, Database, EvmFor, InspectorFor}; use alloc::{boxed::Box, vec::Vec}; use alloy_primitives::{ map::{DefaultHashBuilder, HashMap}, @@ -235,7 +232,7 @@ pub trait BlockExecutionStrategy { /// /// Strategy is required to provide a way to obtain [`ExecutionCtx`] from either a complete /// [`SealedBlock`] (in case of execution of an externally obtained block), or from a parent header -/// along with [`NextBlockEnvAttributes`] (in the case of block building). +/// along with [`crate::ConfigureEvmEnv::NextBlockEnvCtx`] (in the case of block building). /// /// For more context on the strategy design, see the documentation for [`BlockExecutionStrategy`]. /// @@ -265,11 +262,11 @@ pub trait BlockExecutionStrategyFactory: ConfigureEvmFor + 'st /// Returns the configured [`BlockExecutionStrategyFactory::ExecutionCtx`] for `parent + 1` /// block. - fn context_for_next_block<'a>( + fn context_for_next_block( &self, parent: &SealedHeader<::BlockHeader>, - attributes: NextBlockEnvAttributes<'a>, - ) -> Self::ExecutionCtx<'a>; + attributes: Self::NextBlockEnvCtx, + ) -> Self::ExecutionCtx<'_>; /// Creates a strategy with given EVM and execution context. fn create_strategy<'a, DB, I>( @@ -297,9 +294,9 @@ pub trait BlockExecutionStrategyFactory: ConfigureEvmFor + 'st &'a self, db: &'a mut State, parent: &'a SealedHeader<::BlockHeader>, - attributes: NextBlockEnvAttributes<'a>, + attributes: Self::NextBlockEnvCtx, ) -> Result, Self::Error> { - let evm_env = self.next_evm_env(parent, attributes)?; + let evm_env = self.next_evm_env(parent, &attributes)?; let evm = self.evm_with_env(db, evm_env); let ctx = self.context_for_next_block(parent, attributes); Ok(self.create_strategy(evm, ctx)) diff --git a/crates/evm/src/lib.rs b/crates/evm/src/lib.rs index c45ea8f84c..6775b7951e 100644 --- a/crates/evm/src/lib.rs +++ b/crates/evm/src/lib.rs @@ -161,6 +161,11 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone { /// Identifier of the EVM specification. type Spec: Debug + Copy + Send + Sync + 'static; + /// Context required for configuring next block environment. + /// + /// Contains values that can't be derived from the parent block. + type NextBlockEnvCtx: Debug + Clone; + /// Returns a [`TxEnv`] from a transaction and [`Address`]. fn tx_env(&self, transaction: impl IntoTxEnv) -> Self::TxEnv { transaction.into_tx_env() @@ -177,7 +182,7 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone { fn next_evm_env( &self, parent: &Self::Header, - attributes: NextBlockEnvAttributes<'_>, + attributes: &Self::NextBlockEnvCtx, ) -> Result, Self::Error>; } @@ -185,8 +190,8 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone { /// This is used to configure the next block's environment /// [`ConfigureEvmEnv::next_evm_env`] and contains fields that can't be derived from the /// parent header alone (attributes that are determined by the CL.) -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct NextBlockEnvAttributes<'a> { +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct NextBlockEnvAttributes { /// The timestamp of the next block. pub timestamp: u64, /// The suggested fee recipient for the next block. @@ -198,7 +203,7 @@ pub struct NextBlockEnvAttributes<'a> { /// The parent beacon block root. pub parent_beacon_block_root: Option, /// Withdrawals - pub withdrawals: Option<&'a Withdrawals>, + pub withdrawals: Option, } /// Abstraction over transaction environment. diff --git a/crates/optimism/evm/src/config.rs b/crates/optimism/evm/src/config.rs index 2007110971..83612faf63 100644 --- a/crates/optimism/evm/src/config.rs +++ b/crates/optimism/evm/src/config.rs @@ -1,6 +1,24 @@ use alloy_consensus::BlockHeader; use reth_optimism_forks::OpHardforks; use revm_optimism::OpSpecId; +use revm_primitives::{Address, Bytes, B256}; + +/// Context relevant for execution of a next block w.r.t OP. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct OpNextBlockEnvAttributes { + /// The timestamp of the next block. + pub timestamp: u64, + /// The suggested fee recipient for the next block. + pub suggested_fee_recipient: Address, + /// The randomness value for the next block. + pub prev_randao: B256, + /// Block gas limit. + pub gas_limit: u64, + /// The parent beacon block root. + pub parent_beacon_block_root: Option, + /// Encoded EIP-1559 parameters to include into block's `extra_data` field. + pub extra_data: Bytes, +} /// Map the latest active hardfork at the given header to a revm [`OpSpecId`]. pub fn revm_spec(chain_spec: impl OpHardforks, header: impl BlockHeader) -> OpSpecId { diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index 9e3d6a374c..4cd4dace09 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -18,7 +18,7 @@ use reth_evm::{ }, state_change::post_block_balance_increments, system_calls::{OnStateHook, StateChangePostBlockSource, StateChangeSource, SystemCaller}, - Database, Evm, EvmFor, InspectorFor, NextBlockEnvAttributes, + Database, Evm, EvmFor, InspectorFor, }; use reth_execution_types::BlockExecutionResult; use reth_optimism_chainspec::OpChainSpec; @@ -48,11 +48,11 @@ where } } - fn context_for_next_block<'a>( + fn context_for_next_block( &self, parent: &SealedHeader, - attributes: NextBlockEnvAttributes<'a>, - ) -> Self::ExecutionCtx<'a> { + attributes: Self::NextBlockEnvCtx, + ) -> Self::ExecutionCtx<'_> { OpBlockExecutionCtx { parent_hash: parent.hash(), parent_beacon_block_root: attributes.parent_beacon_block_root, diff --git a/crates/optimism/evm/src/lib.rs b/crates/optimism/evm/src/lib.rs index c7519a8af6..4527e5930e 100644 --- a/crates/optimism/evm/src/lib.rs +++ b/crates/optimism/evm/src/lib.rs @@ -18,7 +18,7 @@ use alloy_primitives::U256; use core::fmt::Debug; use op_alloy_consensus::EIP1559ParamError; use reth_chainspec::EthChainSpec; -use reth_evm::{ConfigureEvm, ConfigureEvmEnv, EvmEnv, NextBlockEnvAttributes}; +use reth_evm::{ConfigureEvm, ConfigureEvmEnv, EvmEnv}; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_consensus::next_block_base_fee; use reth_optimism_forks::OpHardforks; @@ -32,7 +32,7 @@ use revm::{ use revm_optimism::{OpHaltReason, OpSpecId, OpTransaction}; mod config; -pub use config::{revm_spec, revm_spec_by_timestamp_after_bedrock}; +pub use config::{revm_spec, revm_spec_by_timestamp_after_bedrock, OpNextBlockEnvAttributes}; mod execute; pub use execute::*; pub mod l1; @@ -98,6 +98,7 @@ where type Error = EIP1559ParamError; type TxEnv = OpTransaction; type Spec = OpSpecId; + type NextBlockEnvCtx = OpNextBlockEnvAttributes; fn evm_env(&self, header: &Self::Header) -> EvmEnv { let spec = config::revm_spec(self.chain_spec(), header); @@ -132,7 +133,7 @@ where fn next_evm_env( &self, parent: &Self::Header, - attributes: NextBlockEnvAttributes<'_>, + attributes: &Self::NextBlockEnvCtx, ) -> Result, Self::Error> { // ensure we're not missing any timestamp based hardforks let spec_id = revm_spec_by_timestamp_after_bedrock(&self.chain_spec, attributes.timestamp); diff --git a/crates/optimism/node/src/node.rs b/crates/optimism/node/src/node.rs index 1ef57c223b..25a3fc6a23 100644 --- a/crates/optimism/node/src/node.rs +++ b/crates/optimism/node/src/node.rs @@ -29,7 +29,7 @@ use reth_node_builder::{ }; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_consensus::OpBeaconConsensus; -use reth_optimism_evm::{BasicOpReceiptBuilder, OpEvmConfig}; +use reth_optimism_evm::{BasicOpReceiptBuilder, OpEvmConfig, OpNextBlockEnvAttributes}; use reth_optimism_forks::OpHardforks; use reth_optimism_payload_builder::{ builder::OpPayloadTransactions, @@ -279,7 +279,10 @@ where Storage = OpStorage, Engine = OpEngineTypes, >, - Evm: ConfigureEvmEnv>, + Evm: ConfigureEvmEnv< + TxEnv = revm_optimism::OpTransaction, + NextBlockEnvCtx = OpNextBlockEnvAttributes, + >, >, OpEthApiError: FromEvmError, <::Pool as TransactionPool>::Transaction: MaybeConditionalTransaction, @@ -351,7 +354,10 @@ where Storage = OpStorage, Engine = OpEngineTypes, >, - Evm: ConfigureEvm>, + Evm: ConfigureEvm< + TxEnv = revm_optimism::OpTransaction, + NextBlockEnvCtx = OpNextBlockEnvAttributes, + >, >, OpEthApiError: FromEvmError, <::Pool as TransactionPool>::Transaction: MaybeConditionalTransaction, diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index f72a19d005..80ff7a3ea4 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -23,11 +23,11 @@ use reth_evm::{ BlockExecutionError, BlockExecutionStrategy, BlockExecutionStrategyFactory, BlockValidationError, }, - ConfigureEvm, ConfigureEvmFor, Database, Evm, HaltReasonFor, NextBlockEnvAttributes, + ConfigureEvm, ConfigureEvmFor, Database, Evm, HaltReasonFor, }; use reth_execution_types::ExecutionOutcome; use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism; -use reth_optimism_evm::OpReceiptBuilder; +use reth_optimism_evm::{OpNextBlockEnvAttributes, OpReceiptBuilder}; use reth_optimism_forks::OpHardforks; use reth_optimism_primitives::transaction::signed::OpTransaction; use reth_optimism_storage::predeploys; @@ -163,7 +163,8 @@ where Pool: TransactionPool>, Client: StateProviderFactory + ChainSpecProvider, N: OpPayloadPrimitives, - EvmConfig: BlockExecutionStrategyFactory, + EvmConfig: + BlockExecutionStrategyFactory, { /// Constructs an Optimism payload from the transactions sent via the /// Payload attributes by the sequencer. If the `no_tx_pool` argument is passed in @@ -248,7 +249,8 @@ where Client: StateProviderFactory + ChainSpecProvider + Clone, N: OpPayloadPrimitives, Pool: TransactionPool>, - EvmConfig: BlockExecutionStrategyFactory, + EvmConfig: + BlockExecutionStrategyFactory, Txs: OpPayloadTransactions, { type Attributes = OpPayloadBuilderAttributes; @@ -327,7 +329,10 @@ impl OpBuilder<'_, Txs> { where N: OpPayloadPrimitives, Txs: PayloadTransactions>, - EvmConfig: BlockExecutionStrategyFactory, + EvmConfig: BlockExecutionStrategyFactory< + Primitives = N, + NextBlockEnvCtx = OpNextBlockEnvAttributes, + >, ChainSpec: EthChainSpec + OpHardforks, DB: Database + AsRef

, P: StorageRootProvider, @@ -340,13 +345,13 @@ impl OpBuilder<'_, Txs> { .strategy_for_next_block( &mut *state, ctx.parent(), - NextBlockEnvAttributes { + OpNextBlockEnvAttributes { timestamp: ctx.attributes().timestamp(), suggested_fee_recipient: ctx.attributes().suggested_fee_recipient(), prev_randao: ctx.attributes().prev_randao(), gas_limit: ctx.attributes().gas_limit.unwrap_or(ctx.parent().gas_limit), parent_beacon_block_root: ctx.attributes().parent_beacon_block_root(), - withdrawals: None, + extra_data: ctx.extra_data()?, }, ) .map_err(PayloadBuilderError::other)?; @@ -406,7 +411,10 @@ impl OpBuilder<'_, Txs> { ctx: OpPayloadBuilderCtx, ) -> Result>, PayloadBuilderError> where - EvmConfig: BlockExecutionStrategyFactory, + EvmConfig: BlockExecutionStrategyFactory< + Primitives = N, + NextBlockEnvCtx = OpNextBlockEnvAttributes, + >, ChainSpec: EthChainSpec + OpHardforks, N: OpPayloadPrimitives, Txs: PayloadTransactions>, @@ -529,7 +537,10 @@ impl OpBuilder<'_, Txs> { ctx: &OpPayloadBuilderCtx, ) -> Result where - EvmConfig: BlockExecutionStrategyFactory, + EvmConfig: BlockExecutionStrategyFactory< + Primitives = N, + NextBlockEnvCtx = OpNextBlockEnvAttributes, + >, ChainSpec: EthChainSpec + OpHardforks, N: OpPayloadPrimitives, Txs: PayloadTransactions>, diff --git a/crates/optimism/rpc/src/eth/pending_block.rs b/crates/optimism/rpc/src/eth/pending_block.rs index 117fc3ea8c..d24c9582ac 100644 --- a/crates/optimism/rpc/src/eth/pending_block.rs +++ b/crates/optimism/rpc/src/eth/pending_block.rs @@ -3,7 +3,7 @@ use crate::OpEthApi; use alloy_consensus::{ constants::EMPTY_WITHDRAWALS, proofs::calculate_transaction_root, transaction::Recovered, - Header, Transaction as _, TxReceipt, EMPTY_OMMER_ROOT_HASH, + BlockHeader, Header, Transaction as _, TxReceipt, EMPTY_OMMER_ROOT_HASH, }; use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE, BlockNumberOrTag}; use alloy_primitives::{B256, U256}; @@ -11,6 +11,7 @@ use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_evm::execute::BlockExecutionStrategyFactory; use reth_node_api::NodePrimitives; use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism; +use reth_optimism_evm::OpNextBlockEnvAttributes; use reth_optimism_forks::OpHardforks; use reth_optimism_primitives::{OpBlock, OpReceipt, OpTransactionSigned}; use reth_primitives::{logs_bloom, BlockBody, RecoveredBlock, SealedHeader}; @@ -51,6 +52,7 @@ where BlockHeader = ProviderHeader, Receipt = ProviderReceipt, >, + NextBlockEnvCtx = OpNextBlockEnvAttributes, >, >, { @@ -63,6 +65,20 @@ where self.inner.eth_api.pending_block() } + fn next_env_attributes( + &self, + parent: &SealedHeader>, + ) -> Result<::NextBlockEnvCtx, Self::Error> { + Ok(OpNextBlockEnvAttributes { + timestamp: parent.timestamp().saturating_add(12), + suggested_fee_recipient: parent.beneficiary(), + prev_randao: B256::random(), + gas_limit: parent.gas_limit(), + parent_beacon_block_root: parent.parent_beacon_block_root(), + extra_data: parent.extra_data.clone(), + }) + } + /// Returns the locally built pending block async fn local_pending_block( &self, diff --git a/crates/optimism/rpc/src/witness.rs b/crates/optimism/rpc/src/witness.rs index 79f25905d0..12fcaccb8a 100644 --- a/crates/optimism/rpc/src/witness.rs +++ b/crates/optimism/rpc/src/witness.rs @@ -8,6 +8,7 @@ use reth_chainspec::ChainSpecProvider; use reth_evm::{execute::BlockExecutionStrategyFactory, ConfigureEvm}; use reth_node_api::NodePrimitives; use reth_optimism_chainspec::OpChainSpec; +use reth_optimism_evm::OpNextBlockEnvAttributes; use reth_optimism_payload_builder::{OpPayloadBuilder, OpPayloadPrimitives}; use reth_primitives::SealedHeader; use reth_provider::{ @@ -69,7 +70,10 @@ where + ChainSpecProvider + Clone + 'static, - EvmConfig: BlockExecutionStrategyFactory + 'static, + EvmConfig: BlockExecutionStrategyFactory< + Primitives = Provider::Primitives, + NextBlockEnvCtx = OpNextBlockEnvAttributes, + > + 'static, { async fn execute_payload( &self, diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index 9d2698ab1b..1e5f8cbd31 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -107,7 +107,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA for block in block_state_calls { let mut evm_env = this .evm_config() - .next_evm_env(&parent, this.next_env_attributes(&parent)?) + .next_evm_env(&parent, &this.next_env_attributes(&parent)?) .map_err(RethError::other) .map_err(Self::Error::from_eth_err)?; diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index 09230ffecf..7a3a22bec3 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -12,7 +12,7 @@ use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_errors::{BlockExecutionError, BlockValidationError, RethError}; use reth_evm::{ execute::{BlockExecutionStrategy, BlockExecutionStrategyFactory}, - ConfigureEvmEnv, Evm, NextBlockEnvAttributes, + ConfigureEvmEnv, Evm, }; use reth_node_api::NodePrimitives; use reth_primitives::{InvalidTransactionError, RecoveredBlock, SealedHeader}; @@ -111,27 +111,18 @@ pub trait LoadPendingBlock: let evm_env = self .evm_config() - .next_evm_env(&latest, self.next_env_attributes(&latest)?) + .next_evm_env(&latest, &self.next_env_attributes(&latest)?) .map_err(RethError::other) .map_err(Self::Error::from_eth_err)?; Ok(PendingBlockEnv::new(evm_env, PendingBlockEnvOrigin::DerivedFromLatest(latest))) } - /// Returns [`NextBlockEnvAttributes`] for building a local pending block. + /// Returns [`ConfigureEvmEnv::NextBlockEnvCtx`] for building a local pending block. fn next_env_attributes( &self, parent: &SealedHeader>, - ) -> Result, Self::Error> { - Ok(NextBlockEnvAttributes { - timestamp: parent.timestamp().saturating_add(12), - suggested_fee_recipient: parent.beneficiary(), - prev_randao: B256::random(), - gas_limit: parent.gas_limit(), - parent_beacon_block_root: parent.parent_beacon_block_root(), - withdrawals: None, - }) - } + ) -> Result<::NextBlockEnvCtx, Self::Error>; /// Returns the locally built pending block #[expect(clippy::type_complexity)] diff --git a/crates/rpc/rpc/src/eth/helpers/pending_block.rs b/crates/rpc/rpc/src/eth/helpers/pending_block.rs index 52b25e3b2d..64477018b8 100644 --- a/crates/rpc/rpc/src/eth/helpers/pending_block.rs +++ b/crates/rpc/rpc/src/eth/helpers/pending_block.rs @@ -1,13 +1,13 @@ //! Support for building a pending block with transactions from local view of mempool. use alloy_consensus::{ - constants::EMPTY_WITHDRAWALS, transaction::Recovered, Header, Transaction, + constants::EMPTY_WITHDRAWALS, transaction::Recovered, BlockHeader, Header, Transaction, EMPTY_OMMER_ROOT_HASH, }; use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE}; use alloy_primitives::U256; use reth_chainspec::{EthChainSpec, EthereumHardforks}; -use reth_evm::execute::BlockExecutionStrategyFactory; +use reth_evm::{execute::BlockExecutionStrategyFactory, NextBlockEnvAttributes}; use reth_node_api::NodePrimitives; use reth_primitives::{logs_bloom, BlockBody, Receipt, SealedHeader}; use reth_primitives_traits::proofs::calculate_transaction_root; @@ -50,6 +50,7 @@ where SignedTx = ProviderTx, Receipt = ProviderReceipt, >, + NextBlockEnvCtx = NextBlockEnvAttributes, >, >, Provider: BlockReader, @@ -63,6 +64,20 @@ where self.inner.pending_block() } + fn next_env_attributes( + &self, + parent: &SealedHeader>, + ) -> Result<::NextBlockEnvCtx, Self::Error> { + Ok(NextBlockEnvAttributes { + timestamp: parent.timestamp().saturating_add(12), + suggested_fee_recipient: parent.beneficiary(), + prev_randao: B256::random(), + gas_limit: parent.gas_limit(), + parent_beacon_block_root: parent.parent_beacon_block_root(), + withdrawals: None, + }) + } + fn assemble_block( &self, block_env: &BlockEnv, diff --git a/examples/custom-beacon-withdrawals/src/main.rs b/examples/custom-beacon-withdrawals/src/main.rs index 446e6787ed..646208109b 100644 --- a/examples/custom-beacon-withdrawals/src/main.rs +++ b/examples/custom-beacon-withdrawals/src/main.rs @@ -31,7 +31,7 @@ use reth_node_ethereum::{node::EthereumAddOns, BasicBlockExecutorProvider, Ether use reth_primitives::{ EthPrimitives, Receipt, Recovered, SealedBlock, SealedHeader, TransactionSigned, }; -use std::fmt::Display; +use std::{borrow::Cow, fmt::Display}; pub const SYSTEM_ADDRESS: Address = address!("fffffffffffffffffffffffffffffffffffffffe"); pub const WITHDRAWALS_ADDRESS: Address = address!("4200000000000000000000000000000000000000"); @@ -91,6 +91,7 @@ impl ConfigureEvmEnv for CustomEvmConfig { type Spec = ::Spec; type Transaction = ::Transaction; type TxEnv = ::TxEnv; + type NextBlockEnvCtx = NextBlockEnvAttributes; fn evm_env(&self, header: &Self::Header) -> EvmEnv { self.inner.evm_env(header) @@ -99,7 +100,7 @@ impl ConfigureEvmEnv for CustomEvmConfig { fn next_evm_env( &self, parent: &Self::Header, - attributes: NextBlockEnvAttributes, + attributes: &NextBlockEnvAttributes, ) -> Result, Self::Error> { self.inner.next_evm_env(parent, attributes) } @@ -114,7 +115,7 @@ impl ConfigureEvm for CustomEvmConfig { } pub struct CustomExecutionCtx<'a> { - withdrawals: Option<&'a Withdrawals>, + withdrawals: Option>, } impl BlockExecutionStrategyFactory for CustomEvmConfig { @@ -124,15 +125,15 @@ impl BlockExecutionStrategyFactory for CustomEvmConfig { CustomExecutorStrategy<'a, EvmFor, I>>; fn context_for_block<'a>(&self, block: &'a SealedBlock) -> Self::ExecutionCtx<'a> { - CustomExecutionCtx { withdrawals: block.body().withdrawals.as_ref() } + CustomExecutionCtx { withdrawals: block.body().withdrawals.as_ref().map(Cow::Borrowed) } } - fn context_for_next_block<'a>( + fn context_for_next_block( &self, _parent: &SealedHeader, - attributes: NextBlockEnvAttributes<'a>, - ) -> Self::ExecutionCtx<'a> { - CustomExecutionCtx { withdrawals: attributes.withdrawals } + attributes: Self::NextBlockEnvCtx, + ) -> Self::ExecutionCtx<'_> { + CustomExecutionCtx { withdrawals: attributes.withdrawals.map(Cow::Owned) } } fn create_strategy<'a, DB, I>( @@ -158,7 +159,7 @@ pub struct CustomExecutorStrategy<'a, Evm> { /// EVM used for execution. evm: Evm, /// Block withdrawals. - withdrawals: Option<&'a Withdrawals>, + withdrawals: Option>, } impl<'db, DB, E> BlockExecutionStrategy for CustomExecutorStrategy<'_, E> @@ -191,7 +192,7 @@ where mut self, ) -> Result, Self::Error> { if let Some(withdrawals) = self.withdrawals { - apply_withdrawals_contract_call(withdrawals, &mut self.evm)?; + apply_withdrawals_contract_call(withdrawals.as_ref(), &mut self.evm)?; } Ok(Default::default())