1#![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, doc_auto_cfg))]
16#![cfg_attr(not(feature = "std"), no_std)]
17
18extern crate alloc;
19
20use crate::execute::BasicBlockBuilder;
21use alloc::vec::Vec;
22use alloy_eips::{eip2930::AccessList, eip4895::Withdrawals};
23use alloy_evm::block::{BlockExecutorFactory, BlockExecutorFor};
24use alloy_primitives::{Address, B256};
25use core::{error::Error, fmt::Debug};
26use execute::{BlockAssembler, BlockBuilder};
27use reth_primitives_traits::{
28 BlockTy, HeaderTy, NodePrimitives, ReceiptTy, SealedBlock, SealedHeader, TxTy,
29};
30use revm::{context::TxEnv, database::State};
31
32pub mod either;
33pub mod execute;
35
36mod aliases;
37pub use aliases::*;
38
39#[cfg(feature = "metrics")]
40pub mod metrics;
41pub mod noop;
42#[cfg(any(test, feature = "test-utils"))]
43pub mod test_utils;
45
46pub use alloy_evm::{
47 block::{state_changes, system_calls, OnStateHook},
48 *,
49};
50
51pub use alloy_evm::block::state_changes as state_change;
52
53#[auto_impl::auto_impl(&, Arc)]
92pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
93 type Primitives: NodePrimitives;
95
96 type Error: Error + Send + Sync + 'static;
98
99 type NextBlockEnvCtx: Debug + Clone;
103
104 type BlockExecutorFactory: BlockExecutorFactory<
106 Transaction = TxTy<Self::Primitives>,
107 Receipt = ReceiptTy<Self::Primitives>,
108 EvmFactory: EvmFactory<
109 Tx: TransactionEnv
110 + FromRecoveredTx<TxTy<Self::Primitives>>
111 + FromTxWithEncoded<TxTy<Self::Primitives>>,
112 >,
113 >;
114
115 type BlockAssembler: BlockAssembler<
117 Self::BlockExecutorFactory,
118 Block = BlockTy<Self::Primitives>,
119 >;
120
121 fn block_executor_factory(&self) -> &Self::BlockExecutorFactory;
123
124 fn block_assembler(&self) -> &Self::BlockAssembler;
126
127 fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>;
129
130 fn next_evm_env(
136 &self,
137 parent: &HeaderTy<Self::Primitives>,
138 attributes: &Self::NextBlockEnvCtx,
139 ) -> Result<EvmEnvFor<Self>, Self::Error>;
140
141 fn context_for_block<'a>(
143 &self,
144 block: &'a SealedBlock<BlockTy<Self::Primitives>>,
145 ) -> ExecutionCtxFor<'a, Self>;
146
147 fn context_for_next_block(
150 &self,
151 parent: &SealedHeader<HeaderTy<Self::Primitives>>,
152 attributes: Self::NextBlockEnvCtx,
153 ) -> ExecutionCtxFor<'_, Self>;
154
155 fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self> {
157 transaction.into_tx_env()
158 }
159
160 fn evm_factory(&self) -> &EvmFactoryFor<Self> {
162 self.block_executor_factory().evm_factory()
163 }
164
165 fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnvFor<Self>) -> EvmFor<Self, DB> {
170 self.evm_factory().create_evm(db, evm_env)
171 }
172
173 fn evm_for_block<DB: Database>(
181 &self,
182 db: DB,
183 header: &HeaderTy<Self::Primitives>,
184 ) -> EvmFor<Self, DB> {
185 let evm_env = self.evm_env(header);
186 self.evm_with_env(db, evm_env)
187 }
188
189 fn evm_with_env_and_inspector<DB, I>(
196 &self,
197 db: DB,
198 evm_env: EvmEnvFor<Self>,
199 inspector: I,
200 ) -> EvmFor<Self, DB, I>
201 where
202 DB: Database,
203 I: InspectorFor<Self, DB>,
204 {
205 self.evm_factory().create_evm_with_inspector(db, evm_env, inspector)
206 }
207
208 fn create_executor<'a, DB, I>(
210 &'a self,
211 evm: EvmFor<Self, &'a mut State<DB>, I>,
212 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
213 ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
214 where
215 DB: Database,
216 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
217 {
218 self.block_executor_factory().create_executor(evm, ctx)
219 }
220
221 fn executor_for_block<'a, DB: Database>(
223 &'a self,
224 db: &'a mut State<DB>,
225 block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>,
226 ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB> {
227 let evm = self.evm_for_block(db, block.header());
228 let ctx = self.context_for_block(block);
229 self.create_executor(evm, ctx)
230 }
231
232 fn create_block_builder<'a, DB, I>(
239 &'a self,
240 evm: EvmFor<Self, &'a mut State<DB>, I>,
241 parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
242 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
243 ) -> impl BlockBuilder<
244 Primitives = Self::Primitives,
245 Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>,
246 >
247 where
248 DB: Database,
249 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
250 {
251 BasicBlockBuilder {
252 executor: self.create_executor(evm, ctx.clone()),
253 ctx,
254 assembler: self.block_assembler(),
255 parent,
256 transactions: Vec::new(),
257 }
258 }
259
260 fn builder_for_next_block<'a, DB: Database>(
263 &'a self,
264 db: &'a mut State<DB>,
265 parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>,
266 attributes: Self::NextBlockEnvCtx,
267 ) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error> {
268 let evm_env = self.next_evm_env(parent, &attributes)?;
269 let evm = self.evm_with_env(db, evm_env);
270 let ctx = self.context_for_next_block(parent, attributes);
271 Ok(self.create_block_builder(evm, parent, ctx))
272 }
273}
274
275#[derive(Debug, Clone, PartialEq, Eq)]
280pub struct NextBlockEnvAttributes {
281 pub timestamp: u64,
283 pub suggested_fee_recipient: Address,
285 pub prev_randao: B256,
287 pub gas_limit: u64,
289 pub parent_beacon_block_root: Option<B256>,
291 pub withdrawals: Option<Withdrawals>,
293}
294
295pub trait TransactionEnv:
297 revm::context_interface::Transaction + Debug + Clone + Send + Sync + 'static
298{
299 fn set_gas_limit(&mut self, gas_limit: u64);
301
302 fn with_gas_limit(mut self, gas_limit: u64) -> Self {
304 self.set_gas_limit(gas_limit);
305 self
306 }
307
308 fn nonce(&self) -> u64;
310
311 fn set_nonce(&mut self, nonce: u64);
313
314 fn with_nonce(mut self, nonce: u64) -> Self {
316 self.set_nonce(nonce);
317 self
318 }
319
320 fn set_access_list(&mut self, access_list: AccessList);
322
323 fn with_access_list(mut self, access_list: AccessList) -> Self {
325 self.set_access_list(access_list);
326 self
327 }
328}
329
330impl TransactionEnv for TxEnv {
331 fn set_gas_limit(&mut self, gas_limit: u64) {
332 self.gas_limit = gas_limit;
333 }
334
335 fn nonce(&self) -> u64 {
336 self.nonce
337 }
338
339 fn set_nonce(&mut self, nonce: u64) {
340 self.nonce = nonce;
341 }
342
343 fn set_access_list(&mut self, access_list: AccessList) {
344 self.access_list = access_list;
345 }
346}
347
348#[cfg(feature = "op")]
349impl<T: TransactionEnv> TransactionEnv for op_revm::OpTransaction<T> {
350 fn set_gas_limit(&mut self, gas_limit: u64) {
351 self.base.set_gas_limit(gas_limit);
352 }
353
354 fn nonce(&self) -> u64 {
355 TransactionEnv::nonce(&self.base)
356 }
357
358 fn set_nonce(&mut self, nonce: u64) {
359 self.base.set_nonce(nonce);
360 }
361
362 fn set_access_list(&mut self, access_list: AccessList) {
363 self.base.set_access_list(access_list);
364 }
365}