pub trait ConfigureEvm:
Clone
+ Debug
+ Send
+ Sync
+ Unpin {
type Primitives: NodePrimitives;
type Error: Error + Send + Sync + 'static;
type NextBlockEnvCtx: Debug + Clone;
type BlockExecutorFactory: for<'a> BlockExecutorFactory<Transaction = TxTy<Self::Primitives>, Receipt = ReceiptTy<Self::Primitives>, ExecutionCtx<'a>: Debug + Send, EvmFactory: EvmFactory<Tx: TransactionEnv + FromRecoveredTx<TxTy<Self::Primitives>> + FromTxWithEncoded<TxTy<Self::Primitives>>, Precompiles = PrecompilesMap>>;
type BlockAssembler: BlockAssembler<Self::BlockExecutorFactory, Block = BlockTy<Self::Primitives>>;
Show 17 methods
// Required methods
fn block_executor_factory(&self) -> &Self::BlockExecutorFactory;
fn block_assembler(&self) -> &Self::BlockAssembler;
fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>;
fn next_evm_env(
&self,
parent: &HeaderTy<Self::Primitives>,
attributes: &Self::NextBlockEnvCtx,
) -> Result<EvmEnvFor<Self>, Self::Error>;
fn context_for_block<'a>(
&self,
block: &'a SealedBlock<BlockTy<Self::Primitives>>,
) -> ExecutionCtxFor<'a, Self>;
fn context_for_next_block(
&self,
parent: &SealedHeader<HeaderTy<Self::Primitives>>,
attributes: Self::NextBlockEnvCtx,
) -> ExecutionCtxFor<'_, Self>;
// Provided methods
fn tx_env(
&self,
transaction: impl IntoTxEnv<TxEnvFor<Self>>,
) -> TxEnvFor<Self> { ... }
fn evm_factory(&self) -> &EvmFactoryFor<Self> { ... }
fn evm_with_env<DB: Database>(
&self,
db: DB,
evm_env: EvmEnvFor<Self>,
) -> EvmFor<Self, DB> { ... }
fn evm_for_block<DB: Database>(
&self,
db: DB,
header: &HeaderTy<Self::Primitives>,
) -> EvmFor<Self, DB> { ... }
fn evm_with_env_and_inspector<DB, I>(
&self,
db: DB,
evm_env: EvmEnvFor<Self>,
inspector: I,
) -> EvmFor<Self, DB, I>
where DB: Database,
I: InspectorFor<Self, DB> { ... }
fn create_executor<'a, DB, I>(
&'a self,
evm: EvmFor<Self, &'a mut State<DB>, I>,
ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
where DB: Database,
I: InspectorFor<Self, &'a mut State<DB>> + 'a { ... }
fn executor_for_block<'a, DB: Database>(
&'a self,
db: &'a mut State<DB>,
block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>,
) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB> { ... }
fn create_block_builder<'a, DB, I>(
&'a self,
evm: EvmFor<Self, &'a mut State<DB>, I>,
parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
) -> impl BlockBuilder<Primitives = Self::Primitives, Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>>
where DB: Database,
I: InspectorFor<Self, &'a mut State<DB>> + 'a { ... }
fn builder_for_next_block<'a, DB: Database>(
&'a self,
db: &'a mut State<DB>,
parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>,
attributes: Self::NextBlockEnvCtx,
) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error> { ... }
fn executor<DB: Database>(
&self,
db: DB,
) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> { ... }
fn batch_executor<DB: Database>(
&self,
db: DB,
) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> { ... }
}
Expand description
A complete configuration of EVM for Reth.
This trait encapsulates complete configuration required for transaction execution and block execution/building, providing a unified interface for EVM operations.
§Architecture Overview
The EVM abstraction consists of the following layers:
-
Evm
(produced byEvmFactory
): The core EVM implementation responsible for executing individual transactions and producing outputs including state changes, logs, gas usage, etc. -
BlockExecutor
(produced byBlockExecutorFactory
): A higher-level component that operates on top ofEvm
to execute entire blocks. This involves:- Executing all transactions in sequence
- Building receipts from transaction outputs
- Applying block rewards to the beneficiary
- Executing system calls (e.g., EIP-4788 beacon root updates)
- Managing state changes and bundle accumulation
-
BlockAssembler
: Responsible for assembling valid blocks from executed transactions. It takes the output fromBlockExecutor
along with execution context and produces a complete block ready for inclusion in the chain.
§Usage Patterns
The abstraction supports two primary use cases:
§1. Executing Externally Provided Blocks (e.g., during sync)
use reth_evm::ConfigureEvm;
// Execute a received block
let mut executor = evm_config.executor(state_db);
let output = executor.execute(&block)?;
// Access the execution results
println!("Gas used: {}", output.result.gas_used);
println!("Receipts: {:?}", output.result.receipts);
§2. Building New Blocks (e.g., payload building)
Payload building is slightly different as it doesn’t have the block’s header yet, but rather attributes for the block’s environment, such as timestamp, fee recipient, and randomness value. The block’s header will be the outcome of the block building process.
use reth_evm::{ConfigureEvm, NextBlockEnvAttributes};
// Create attributes for the next block
let attributes = NextBlockEnvAttributes {
timestamp: current_time + 12,
suggested_fee_recipient: beneficiary_address,
prev_randao: randomness_value,
gas_limit: 30_000_000,
withdrawals: Some(withdrawals),
parent_beacon_block_root: Some(beacon_root),
};
// Build a new block on top of parent
let mut builder = evm_config.builder_for_next_block(
&mut state_db,
&parent_header,
attributes
)?;
// Apply pre-execution changes (e.g., beacon root update)
builder.apply_pre_execution_changes()?;
// Execute transactions
for tx in pending_transactions {
match builder.execute_transaction(tx) {
Ok(gas_used) => {
println!("Transaction executed, gas used: {}", gas_used);
}
Err(e) => {
println!("Transaction failed: {:?}", e);
}
}
}
// Finish block building and get the outcome (block)
let outcome = builder.finish(state_provider)?;
let block = outcome.block;
§Key Components
§NextBlockEnvCtx
Contains attributes needed to configure the next block that cannot be derived from the parent block alone. This includes data typically provided by the consensus layer:
timestamp
: Block timestampsuggested_fee_recipient
: Beneficiary addressprev_randao
: Randomness valuegas_limit
: Block gas limitwithdrawals
: Consensus layer withdrawalsparent_beacon_block_root
: EIP-4788 beacon root
§BlockAssembler
Takes the execution output and produces a complete block. It receives:
- Transaction execution results (receipts, gas used)
- Final state root after all executions
- Bundle state with all changes
- Execution context and environment
The assembler is responsible for:
- Setting the correct block header fields
- Including executed transactions
- Setting gas used and receipts root
- Applying any chain-specific rules
Required Associated Types§
Sourcetype Primitives: NodePrimitives
type Primitives: NodePrimitives
The primitives type used by the EVM.
Sourcetype Error: Error + Send + Sync + 'static
type Error: Error + Send + Sync + 'static
The error type that is returned by Self::next_evm_env
.
Sourcetype NextBlockEnvCtx: Debug + Clone
type NextBlockEnvCtx: Debug + Clone
Context required for configuring next block environment.
Contains values that can’t be derived from the parent block.
Sourcetype BlockExecutorFactory: for<'a> BlockExecutorFactory<Transaction = TxTy<Self::Primitives>, Receipt = ReceiptTy<Self::Primitives>, ExecutionCtx<'a>: Debug + Send, EvmFactory: EvmFactory<Tx: TransactionEnv + FromRecoveredTx<TxTy<Self::Primitives>> + FromTxWithEncoded<TxTy<Self::Primitives>>, Precompiles = PrecompilesMap>>
type BlockExecutorFactory: for<'a> BlockExecutorFactory<Transaction = TxTy<Self::Primitives>, Receipt = ReceiptTy<Self::Primitives>, ExecutionCtx<'a>: Debug + Send, EvmFactory: EvmFactory<Tx: TransactionEnv + FromRecoveredTx<TxTy<Self::Primitives>> + FromTxWithEncoded<TxTy<Self::Primitives>>, Precompiles = PrecompilesMap>>
Configured BlockExecutorFactory
, contains EvmFactory
internally.
Sourcetype BlockAssembler: BlockAssembler<Self::BlockExecutorFactory, Block = BlockTy<Self::Primitives>>
type BlockAssembler: BlockAssembler<Self::BlockExecutorFactory, Block = BlockTy<Self::Primitives>>
A type that knows how to build a block.
Required Methods§
Sourcefn block_executor_factory(&self) -> &Self::BlockExecutorFactory
fn block_executor_factory(&self) -> &Self::BlockExecutorFactory
Returns reference to the configured BlockExecutorFactory
.
Sourcefn block_assembler(&self) -> &Self::BlockAssembler
fn block_assembler(&self) -> &Self::BlockAssembler
Returns reference to the configured BlockAssembler
.
Sourcefn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>
fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>
Creates a new EvmEnv
for the given header.
Sourcefn next_evm_env(
&self,
parent: &HeaderTy<Self::Primitives>,
attributes: &Self::NextBlockEnvCtx,
) -> Result<EvmEnvFor<Self>, Self::Error>
fn next_evm_env( &self, parent: &HeaderTy<Self::Primitives>, attributes: &Self::NextBlockEnvCtx, ) -> Result<EvmEnvFor<Self>, Self::Error>
Returns the configured EvmEnv
for parent + 1
block.
This is intended for usage in block building after the merge and requires additional attributes that can’t be derived from the parent block: attributes that are determined by the CL, such as the timestamp, suggested fee recipient, and randomness value.
§Example
let evm_env = evm_config.next_evm_env(&parent_header, &attributes)?;
// evm_env now contains:
// - Correct spec ID based on timestamp and block number
// - Block environment with next block's parameters
// - Configuration like chain ID and blob parameters
Sourcefn context_for_block<'a>(
&self,
block: &'a SealedBlock<BlockTy<Self::Primitives>>,
) -> ExecutionCtxFor<'a, Self>
fn context_for_block<'a>( &self, block: &'a SealedBlock<BlockTy<Self::Primitives>>, ) -> ExecutionCtxFor<'a, Self>
Returns the configured BlockExecutorFactory::ExecutionCtx
for a given block.
Sourcefn context_for_next_block(
&self,
parent: &SealedHeader<HeaderTy<Self::Primitives>>,
attributes: Self::NextBlockEnvCtx,
) -> ExecutionCtxFor<'_, Self>
fn context_for_next_block( &self, parent: &SealedHeader<HeaderTy<Self::Primitives>>, attributes: Self::NextBlockEnvCtx, ) -> ExecutionCtxFor<'_, Self>
Returns the configured BlockExecutorFactory::ExecutionCtx
for parent + 1
block.
Provided Methods§
Sourcefn evm_factory(&self) -> &EvmFactoryFor<Self>
fn evm_factory(&self) -> &EvmFactoryFor<Self>
Provides a reference to EvmFactory
implementation.
Sourcefn evm_with_env<DB: Database>(
&self,
db: DB,
evm_env: EvmEnvFor<Self>,
) -> EvmFor<Self, DB>
fn evm_with_env<DB: Database>( &self, db: DB, evm_env: EvmEnvFor<Self>, ) -> EvmFor<Self, DB>
Returns a new EVM with the given database configured with the given environment settings, including the spec id and transaction environment.
This will preserve any handler modifications
Sourcefn evm_for_block<DB: Database>(
&self,
db: DB,
header: &HeaderTy<Self::Primitives>,
) -> EvmFor<Self, DB>
fn evm_for_block<DB: Database>( &self, db: DB, header: &HeaderTy<Self::Primitives>, ) -> EvmFor<Self, DB>
Returns a new EVM with the given database configured with cfg
and block_env
configuration derived from the given header. Relies on
ConfigureEvm::evm_env
.
§Caution
This does not initialize the tx environment.
Sourcefn evm_with_env_and_inspector<DB, I>(
&self,
db: DB,
evm_env: EvmEnvFor<Self>,
inspector: I,
) -> EvmFor<Self, DB, I>where
DB: Database,
I: InspectorFor<Self, DB>,
fn evm_with_env_and_inspector<DB, I>(
&self,
db: DB,
evm_env: EvmEnvFor<Self>,
inspector: I,
) -> EvmFor<Self, DB, I>where
DB: Database,
I: InspectorFor<Self, DB>,
Returns a new EVM with the given database configured with the given environment settings, including the spec id.
This will use the given external inspector as the EVM external context.
This will preserve any handler modifications
Sourcefn create_executor<'a, DB, I>(
&'a self,
evm: EvmFor<Self, &'a mut State<DB>, I>,
ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
fn create_executor<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
Creates a strategy with given EVM and execution context.
Sourcefn executor_for_block<'a, DB: Database>(
&'a self,
db: &'a mut State<DB>,
block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>,
) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB>
fn executor_for_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB>
Creates a strategy for execution of a given block.
Sourcefn create_block_builder<'a, DB, I>(
&'a self,
evm: EvmFor<Self, &'a mut State<DB>, I>,
parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
) -> impl BlockBuilder<Primitives = Self::Primitives, Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>>
fn create_block_builder<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, parent: &'a SealedHeader<HeaderTy<Self::Primitives>>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockBuilder<Primitives = Self::Primitives, Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>>
Creates a BlockBuilder
. Should be used when building a new block.
Block builder wraps an inner alloy_evm::block::BlockExecutor
and has a similar
interface. Builder collects all of the executed transactions, and once
BlockBuilder::finish
is called, it invokes the configured BlockAssembler
to
create a block.
§Example
// Create a builder with specific EVM configuration
let evm = evm_config.evm_with_env(&mut state_db, evm_env);
let ctx = evm_config.context_for_next_block(&parent, attributes);
let builder = evm_config.create_block_builder(evm, &parent, ctx);
Sourcefn builder_for_next_block<'a, DB: Database>(
&'a self,
db: &'a mut State<DB>,
parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>,
attributes: Self::NextBlockEnvCtx,
) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error>
fn builder_for_next_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>, attributes: Self::NextBlockEnvCtx, ) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error>
Creates a BlockBuilder
for building of a new block. This is a helper to invoke
ConfigureEvm::create_block_builder
.
This is the primary method for building new blocks. It combines:
- Creating the EVM environment for the next block
- Setting up the execution context from attributes
- Initializing the block builder with proper configuration
§Example
// Build a block with specific attributes
let mut builder = evm_config.builder_for_next_block(
&mut state_db,
&parent_header,
attributes
)?;
// Execute system calls (e.g., beacon root update)
builder.apply_pre_execution_changes()?;
// Execute transactions
for tx in transactions {
builder.execute_transaction(tx)?;
}
// Complete block building
let outcome = builder.finish(state_provider)?;
Sourcefn executor<DB: Database>(
&self,
db: DB,
) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError>
fn executor<DB: Database>( &self, db: DB, ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError>
Returns a new Executor
for executing blocks.
The executor processes complete blocks including:
- All transactions in order
- Block rewards and fees
- Block level system calls
- State transitions
§Example
// Create an executor
let mut executor = evm_config.executor(state_db);
// Execute a single block
let output = executor.execute(&block)?;
// Execute multiple blocks
let batch_output = executor.execute_batch(&blocks)?;
Sourcefn batch_executor<DB: Database>(
&self,
db: DB,
) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError>
fn batch_executor<DB: Database>( &self, db: DB, ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError>
Returns a new BasicBlockExecutor
.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.