reth_evm/lib.rs
1//! Traits for configuring an EVM specifics.
2//!
3//! # Revm features
4//!
5//! This crate does __not__ enforce specific revm features such as `blst` or `c-kzg`, which are
6//! critical for revm's evm internals, it is the responsibility of the implementer to ensure the
7//! proper features are selected.
8
9#![doc(
10 html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
11 html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
12 issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
13)]
14#![cfg_attr(not(test), warn(unused_crate_dependencies))]
15#![cfg_attr(docsrs, feature(doc_cfg))]
16#![cfg_attr(not(feature = "std"), no_std)]
17
18extern crate alloc;
19
20use crate::execute::{BasicBlockBuilder, Executor};
21use alloc::vec::Vec;
22use alloy_eips::{
23 eip2718::{EIP2930_TX_TYPE_ID, LEGACY_TX_TYPE_ID},
24 eip2930::AccessList,
25 eip4895::Withdrawals,
26};
27use alloy_evm::{
28 block::{BlockExecutorFactory, BlockExecutorFor},
29 precompiles::PrecompilesMap,
30};
31use alloy_primitives::{Address, B256};
32use core::{error::Error, fmt::Debug};
33use execute::{BasicBlockExecutor, BlockAssembler, BlockBuilder};
34use reth_execution_errors::BlockExecutionError;
35use reth_primitives_traits::{
36 BlockTy, HeaderTy, NodePrimitives, ReceiptTy, SealedBlock, SealedHeader, TxTy,
37};
38use revm::{context::TxEnv, database::State};
39
40pub mod either;
41/// EVM environment configuration.
42pub mod execute;
43
44mod aliases;
45pub use aliases::*;
46
47mod engine;
48pub use engine::{ConfigureEngineEvm, ExecutableTxIterator};
49
50#[cfg(feature = "metrics")]
51pub mod metrics;
52pub mod noop;
53#[cfg(any(test, feature = "test-utils"))]
54/// test helpers for mocking executor
55pub mod test_utils;
56
57pub use alloy_evm::{
58 block::{state_changes, system_calls, OnStateHook},
59 *,
60};
61
62pub use alloy_evm::block::state_changes as state_change;
63
64/// A complete configuration of EVM for Reth.
65///
66/// This trait encapsulates complete configuration required for transaction execution and block
67/// execution/building, providing a unified interface for EVM operations.
68///
69/// # Architecture Overview
70///
71/// The EVM abstraction consists of the following layers:
72///
73/// 1. **[`Evm`] (produced by [`EvmFactory`])**: The core EVM implementation responsible for
74/// executing individual transactions and producing outputs including state changes, logs, gas
75/// usage, etc.
76///
77/// 2. **[`BlockExecutor`] (produced by [`BlockExecutorFactory`])**: A higher-level component that
78/// operates on top of [`Evm`] to execute entire blocks. This involves:
79/// - Executing all transactions in sequence
80/// - Building receipts from transaction outputs
81/// - Applying block rewards to the beneficiary
82/// - Executing system calls (e.g., EIP-4788 beacon root updates)
83/// - Managing state changes and bundle accumulation
84///
85/// 3. **[`BlockAssembler`]**: Responsible for assembling valid blocks from executed transactions.
86/// It takes the output from [`BlockExecutor`] along with execution context and produces a
87/// complete block ready for inclusion in the chain.
88///
89/// # Usage Patterns
90///
91/// The abstraction supports two primary use cases:
92///
93/// ## 1. Executing Externally Provided Blocks (e.g., during sync)
94///
95/// ```rust,ignore
96/// use reth_evm::ConfigureEvm;
97///
98/// // Execute a received block
99/// let mut executor = evm_config.executor(state_db);
100/// let output = executor.execute(&block)?;
101///
102/// // Access the execution results
103/// println!("Gas used: {}", output.result.gas_used);
104/// println!("Receipts: {:?}", output.result.receipts);
105/// ```
106///
107/// ## 2. Building New Blocks (e.g., payload building)
108///
109/// Payload building is slightly different as it doesn't have the block's header yet, but rather
110/// attributes for the block's environment, such as timestamp, fee recipient, and randomness value.
111/// The block's header will be the outcome of the block building process.
112///
113/// ```rust,ignore
114/// use reth_evm::{ConfigureEvm, NextBlockEnvAttributes};
115///
116/// // Create attributes for the next block
117/// let attributes = NextBlockEnvAttributes {
118/// timestamp: current_time + 12,
119/// suggested_fee_recipient: beneficiary_address,
120/// prev_randao: randomness_value,
121/// gas_limit: 30_000_000,
122/// withdrawals: Some(withdrawals),
123/// parent_beacon_block_root: Some(beacon_root),
124/// };
125///
126/// // Build a new block on top of parent
127/// let mut builder = evm_config.builder_for_next_block(
128/// &mut state_db,
129/// &parent_header,
130/// attributes
131/// )?;
132///
133/// // Apply pre-execution changes (e.g., beacon root update)
134/// builder.apply_pre_execution_changes()?;
135///
136/// // Execute transactions
137/// for tx in pending_transactions {
138/// match builder.execute_transaction(tx) {
139/// Ok(gas_used) => {
140/// println!("Transaction executed, gas used: {}", gas_used);
141/// }
142/// Err(e) => {
143/// println!("Transaction failed: {:?}", e);
144/// }
145/// }
146/// }
147///
148/// // Finish block building and get the outcome (block)
149/// let outcome = builder.finish(state_provider)?;
150/// let block = outcome.block;
151/// ```
152///
153/// # Key Components
154///
155/// ## [`NextBlockEnvCtx`]
156///
157/// Contains attributes needed to configure the next block that cannot be derived from the
158/// parent block alone. This includes data typically provided by the consensus layer:
159/// - `timestamp`: Block timestamp
160/// - `suggested_fee_recipient`: Beneficiary address
161/// - `prev_randao`: Randomness value
162/// - `gas_limit`: Block gas limit
163/// - `withdrawals`: Consensus layer withdrawals
164/// - `parent_beacon_block_root`: EIP-4788 beacon root
165///
166/// ## [`BlockAssembler`]
167///
168/// Takes the execution output and produces a complete block. It receives:
169/// - Transaction execution results (receipts, gas used)
170/// - Final state root after all executions
171/// - Bundle state with all changes
172/// - Execution context and environment
173///
174/// The assembler is responsible for:
175/// - Setting the correct block header fields
176/// - Including executed transactions
177/// - Setting gas used and receipts root
178/// - Applying any chain-specific rules
179///
180/// [`ExecutionCtx`]: BlockExecutorFactory::ExecutionCtx
181/// [`NextBlockEnvCtx`]: ConfigureEvm::NextBlockEnvCtx
182/// [`BlockExecutor`]: alloy_evm::block::BlockExecutor
183#[auto_impl::auto_impl(&, Arc)]
184pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
185 /// The primitives type used by the EVM.
186 type Primitives: NodePrimitives;
187
188 /// The error type that is returned by [`Self::next_evm_env`].
189 type Error: Error + Send + Sync + 'static;
190
191 /// Context required for configuring next block environment.
192 ///
193 /// Contains values that can't be derived from the parent block.
194 type NextBlockEnvCtx: Debug + Clone;
195
196 /// Configured [`BlockExecutorFactory`], contains [`EvmFactory`] internally.
197 type BlockExecutorFactory: for<'a> BlockExecutorFactory<
198 Transaction = TxTy<Self::Primitives>,
199 Receipt = ReceiptTy<Self::Primitives>,
200 ExecutionCtx<'a>: Debug + Send,
201 EvmFactory: EvmFactory<
202 Tx: TransactionEnv
203 + FromRecoveredTx<TxTy<Self::Primitives>>
204 + FromTxWithEncoded<TxTy<Self::Primitives>>,
205 Precompiles = PrecompilesMap,
206 >,
207 >;
208
209 /// A type that knows how to build a block.
210 type BlockAssembler: BlockAssembler<
211 Self::BlockExecutorFactory,
212 Block = BlockTy<Self::Primitives>,
213 >;
214
215 /// Returns reference to the configured [`BlockExecutorFactory`].
216 fn block_executor_factory(&self) -> &Self::BlockExecutorFactory;
217
218 /// Returns reference to the configured [`BlockAssembler`].
219 fn block_assembler(&self) -> &Self::BlockAssembler;
220
221 /// Creates a new [`EvmEnv`] for the given header.
222 fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> Result<EvmEnvFor<Self>, Self::Error>;
223
224 /// Returns the configured [`EvmEnv`] for `parent + 1` block.
225 ///
226 /// This is intended for usage in block building after the merge and requires additional
227 /// attributes that can't be derived from the parent block: attributes that are determined by
228 /// the CL, such as the timestamp, suggested fee recipient, and randomness value.
229 ///
230 /// # Example
231 ///
232 /// ```rust,ignore
233 /// let evm_env = evm_config.next_evm_env(&parent_header, &attributes)?;
234 /// // evm_env now contains:
235 /// // - Correct spec ID based on timestamp and block number
236 /// // - Block environment with next block's parameters
237 /// // - Configuration like chain ID and blob parameters
238 /// ```
239 fn next_evm_env(
240 &self,
241 parent: &HeaderTy<Self::Primitives>,
242 attributes: &Self::NextBlockEnvCtx,
243 ) -> Result<EvmEnvFor<Self>, Self::Error>;
244
245 /// Returns the configured [`BlockExecutorFactory::ExecutionCtx`] for a given block.
246 fn context_for_block<'a>(
247 &self,
248 block: &'a SealedBlock<BlockTy<Self::Primitives>>,
249 ) -> Result<ExecutionCtxFor<'a, Self>, Self::Error>;
250
251 /// Returns the configured [`BlockExecutorFactory::ExecutionCtx`] for `parent + 1`
252 /// block.
253 fn context_for_next_block(
254 &self,
255 parent: &SealedHeader<HeaderTy<Self::Primitives>>,
256 attributes: Self::NextBlockEnvCtx,
257 ) -> Result<ExecutionCtxFor<'_, Self>, Self::Error>;
258
259 /// Returns a [`TxEnv`] from a transaction and [`Address`].
260 fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self> {
261 transaction.into_tx_env()
262 }
263
264 /// Provides a reference to [`EvmFactory`] implementation.
265 fn evm_factory(&self) -> &EvmFactoryFor<Self> {
266 self.block_executor_factory().evm_factory()
267 }
268
269 /// Returns a new EVM with the given database configured with the given environment settings,
270 /// including the spec id and transaction environment.
271 ///
272 /// This will preserve any handler modifications
273 fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnvFor<Self>) -> EvmFor<Self, DB> {
274 self.evm_factory().create_evm(db, evm_env)
275 }
276
277 /// Returns a new EVM with the given database configured with `cfg` and `block_env`
278 /// configuration derived from the given header. Relies on
279 /// [`ConfigureEvm::evm_env`].
280 ///
281 /// # Caution
282 ///
283 /// This does not initialize the tx environment.
284 fn evm_for_block<DB: Database>(
285 &self,
286 db: DB,
287 header: &HeaderTy<Self::Primitives>,
288 ) -> Result<EvmFor<Self, DB>, Self::Error> {
289 let evm_env = self.evm_env(header)?;
290 Ok(self.evm_with_env(db, evm_env))
291 }
292
293 /// Returns a new EVM with the given database configured with the given environment settings,
294 /// including the spec id.
295 ///
296 /// This will use the given external inspector as the EVM external context.
297 ///
298 /// This will preserve any handler modifications
299 fn evm_with_env_and_inspector<DB, I>(
300 &self,
301 db: DB,
302 evm_env: EvmEnvFor<Self>,
303 inspector: I,
304 ) -> EvmFor<Self, DB, I>
305 where
306 DB: Database,
307 I: InspectorFor<Self, DB>,
308 {
309 self.evm_factory().create_evm_with_inspector(db, evm_env, inspector)
310 }
311
312 /// Creates a strategy with given EVM and execution context.
313 fn create_executor<'a, DB, I>(
314 &'a self,
315 evm: EvmFor<Self, &'a mut State<DB>, I>,
316 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
317 ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
318 where
319 DB: Database,
320 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
321 {
322 self.block_executor_factory().create_executor(evm, ctx)
323 }
324
325 /// Creates a strategy for execution of a given block.
326 fn executor_for_block<'a, DB: Database>(
327 &'a self,
328 db: &'a mut State<DB>,
329 block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>,
330 ) -> Result<impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB>, Self::Error> {
331 let evm = self.evm_for_block(db, block.header())?;
332 let ctx = self.context_for_block(block)?;
333 Ok(self.create_executor(evm, ctx))
334 }
335
336 /// Creates a [`BlockBuilder`]. Should be used when building a new block.
337 ///
338 /// Block builder wraps an inner [`alloy_evm::block::BlockExecutor`] and has a similar
339 /// interface. Builder collects all of the executed transactions, and once
340 /// [`BlockBuilder::finish`] is called, it invokes the configured [`BlockAssembler`] to
341 /// create a block.
342 ///
343 /// # Example
344 ///
345 /// ```rust,ignore
346 /// // Create a builder with specific EVM configuration
347 /// let evm = evm_config.evm_with_env(&mut state_db, evm_env);
348 /// let ctx = evm_config.context_for_next_block(&parent, attributes);
349 /// let builder = evm_config.create_block_builder(evm, &parent, ctx);
350 /// ```
351 fn create_block_builder<'a, DB, I>(
352 &'a self,
353 evm: EvmFor<Self, &'a mut State<DB>, I>,
354 parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
355 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
356 ) -> impl BlockBuilder<
357 Primitives = Self::Primitives,
358 Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>,
359 >
360 where
361 DB: Database,
362 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
363 {
364 BasicBlockBuilder {
365 executor: self.create_executor(evm, ctx.clone()),
366 ctx,
367 assembler: self.block_assembler(),
368 parent,
369 transactions: Vec::new(),
370 }
371 }
372
373 /// Creates a [`BlockBuilder`] for building of a new block. This is a helper to invoke
374 /// [`ConfigureEvm::create_block_builder`].
375 ///
376 /// This is the primary method for building new blocks. It combines:
377 /// 1. Creating the EVM environment for the next block
378 /// 2. Setting up the execution context from attributes
379 /// 3. Initializing the block builder with proper configuration
380 ///
381 /// # Example
382 ///
383 /// ```rust,ignore
384 /// // Build a block with specific attributes
385 /// let mut builder = evm_config.builder_for_next_block(
386 /// &mut state_db,
387 /// &parent_header,
388 /// attributes
389 /// )?;
390 ///
391 /// // Execute system calls (e.g., beacon root update)
392 /// builder.apply_pre_execution_changes()?;
393 ///
394 /// // Execute transactions
395 /// for tx in transactions {
396 /// builder.execute_transaction(tx)?;
397 /// }
398 ///
399 /// // Complete block building
400 /// let outcome = builder.finish(state_provider)?;
401 /// ```
402 fn builder_for_next_block<'a, DB: Database>(
403 &'a self,
404 db: &'a mut State<DB>,
405 parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>,
406 attributes: Self::NextBlockEnvCtx,
407 ) -> Result<
408 impl BlockBuilder<
409 Primitives = Self::Primitives,
410 Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB>,
411 >,
412 Self::Error,
413 > {
414 let evm_env = self.next_evm_env(parent, &attributes)?;
415 let evm = self.evm_with_env(db, evm_env);
416 let ctx = self.context_for_next_block(parent, attributes)?;
417 Ok(self.create_block_builder(evm, parent, ctx))
418 }
419
420 /// Returns a new [`Executor`] for executing blocks.
421 ///
422 /// The executor processes complete blocks including:
423 /// - All transactions in order
424 /// - Block rewards and fees
425 /// - Block level system calls
426 /// - State transitions
427 ///
428 /// # Example
429 ///
430 /// ```rust,ignore
431 /// // Create an executor
432 /// let mut executor = evm_config.executor(state_db);
433 ///
434 /// // Execute a single block
435 /// let output = executor.execute(&block)?;
436 ///
437 /// // Execute multiple blocks
438 /// let batch_output = executor.execute_batch(&blocks)?;
439 /// ```
440 #[auto_impl(keep_default_for(&, Arc))]
441 fn executor<DB: Database>(
442 &self,
443 db: DB,
444 ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> {
445 BasicBlockExecutor::new(self, db)
446 }
447
448 /// Returns a new [`BasicBlockExecutor`].
449 #[auto_impl(keep_default_for(&, Arc))]
450 fn batch_executor<DB: Database>(
451 &self,
452 db: DB,
453 ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> {
454 BasicBlockExecutor::new(self, db)
455 }
456}
457
458/// Represents additional attributes required to configure the next block.
459///
460/// This struct contains all the information needed to build a new block that cannot be
461/// derived from the parent block header alone. These attributes are typically provided
462/// by the consensus layer (CL) through the Engine API during payload building.
463///
464/// # Relationship with [`ConfigureEvm`] and [`BlockAssembler`]
465///
466/// The flow for building a new block involves:
467///
468/// 1. **Receive attributes** from the consensus layer containing:
469/// - Timestamp for the new block
470/// - Fee recipient (coinbase/beneficiary)
471/// - Randomness value (prevRandao)
472/// - Withdrawals to process
473/// - Parent beacon block root for EIP-4788
474///
475/// 2. **Configure EVM environment** using these attributes: ```rust,ignore let evm_env =
476/// evm_config.next_evm_env(&parent, &attributes)?; ```
477///
478/// 3. **Build the block** with transactions: ```rust,ignore let mut builder =
479/// evm_config.builder_for_next_block( &mut state, &parent, attributes )?; ```
480///
481/// 4. **Assemble the final block** using [`BlockAssembler`] which takes:
482/// - Execution results from all transactions
483/// - The attributes used during execution
484/// - Final state root after all changes
485///
486/// This design cleanly separates:
487/// - **Configuration** (what parameters to use) - handled by `NextBlockEnvAttributes`
488/// - **Execution** (running transactions) - handled by `BlockExecutor`
489/// - **Assembly** (creating the final block) - handled by `BlockAssembler`
490#[derive(Debug, Clone, PartialEq, Eq)]
491pub struct NextBlockEnvAttributes {
492 /// The timestamp of the next block.
493 pub timestamp: u64,
494 /// The suggested fee recipient for the next block.
495 pub suggested_fee_recipient: Address,
496 /// The randomness value for the next block.
497 pub prev_randao: B256,
498 /// Block gas limit.
499 pub gas_limit: u64,
500 /// The parent beacon block root.
501 pub parent_beacon_block_root: Option<B256>,
502 /// Withdrawals
503 pub withdrawals: Option<Withdrawals>,
504}
505
506/// Abstraction over transaction environment.
507pub trait TransactionEnv:
508 revm::context_interface::Transaction + Debug + Clone + Send + Sync + 'static
509{
510 /// Set the gas limit.
511 fn set_gas_limit(&mut self, gas_limit: u64);
512
513 /// Set the gas limit.
514 fn with_gas_limit(mut self, gas_limit: u64) -> Self {
515 self.set_gas_limit(gas_limit);
516 self
517 }
518
519 /// Returns the configured nonce.
520 fn nonce(&self) -> u64;
521
522 /// Sets the nonce.
523 fn set_nonce(&mut self, nonce: u64);
524
525 /// Sets the nonce.
526 fn with_nonce(mut self, nonce: u64) -> Self {
527 self.set_nonce(nonce);
528 self
529 }
530
531 /// Set access list.
532 fn set_access_list(&mut self, access_list: AccessList);
533
534 /// Set access list.
535 fn with_access_list(mut self, access_list: AccessList) -> Self {
536 self.set_access_list(access_list);
537 self
538 }
539}
540
541impl TransactionEnv for TxEnv {
542 fn set_gas_limit(&mut self, gas_limit: u64) {
543 self.gas_limit = gas_limit;
544 }
545
546 fn nonce(&self) -> u64 {
547 self.nonce
548 }
549
550 fn set_nonce(&mut self, nonce: u64) {
551 self.nonce = nonce;
552 }
553
554 fn set_access_list(&mut self, access_list: AccessList) {
555 self.access_list = access_list;
556
557 if self.tx_type == LEGACY_TX_TYPE_ID {
558 // if this was previously marked as legacy tx, this must be upgraded to eip2930 with an
559 // accesslist
560 self.tx_type = EIP2930_TX_TYPE_ID;
561 }
562 }
563}
564
565#[cfg(feature = "op")]
566impl<T: TransactionEnv> TransactionEnv for op_revm::OpTransaction<T> {
567 fn set_gas_limit(&mut self, gas_limit: u64) {
568 self.base.set_gas_limit(gas_limit);
569 }
570
571 fn nonce(&self) -> u64 {
572 TransactionEnv::nonce(&self.base)
573 }
574
575 fn set_nonce(&mut self, nonce: u64) {
576 self.base.set_nonce(nonce);
577 }
578
579 fn set_access_list(&mut self, access_list: AccessList) {
580 self.base.set_access_list(access_list);
581 }
582}