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;
31use revm_database::State;
32
33pub mod either;
34pub mod execute;
36
37mod aliases;
38pub use aliases::*;
39
40#[cfg(feature = "metrics")]
41pub mod metrics;
42pub mod noop;
43#[cfg(any(test, feature = "test-utils"))]
44pub mod test_utils;
46
47pub use alloy_evm::{
48 block::{state_changes, system_calls, OnStateHook},
49 *,
50};
51
52pub use alloy_evm::block::state_changes as state_change;
53
54#[auto_impl::auto_impl(&, Arc)]
93pub trait ConfigureEvm: Send + Sync + Unpin + Clone {
94 type Primitives: NodePrimitives;
96
97 type Error: Error + Send + Sync + 'static;
99
100 type NextBlockEnvCtx: Debug + Clone;
104
105 type BlockExecutorFactory: BlockExecutorFactory<
107 Transaction = TxTy<Self::Primitives>,
108 Receipt = ReceiptTy<Self::Primitives>,
109 EvmFactory: EvmFactory<Tx: TransactionEnv + FromRecoveredTx<TxTy<Self::Primitives>>>,
110 >;
111
112 type BlockAssembler: BlockAssembler<
114 Self::BlockExecutorFactory,
115 Block = BlockTy<Self::Primitives>,
116 >;
117
118 fn block_executor_factory(&self) -> &Self::BlockExecutorFactory;
120
121 fn block_assembler(&self) -> &Self::BlockAssembler;
123
124 fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>;
126
127 fn next_evm_env(
133 &self,
134 parent: &HeaderTy<Self::Primitives>,
135 attributes: &Self::NextBlockEnvCtx,
136 ) -> Result<EvmEnvFor<Self>, Self::Error>;
137
138 fn context_for_block<'a>(
140 &self,
141 block: &'a SealedBlock<BlockTy<Self::Primitives>>,
142 ) -> ExecutionCtxFor<'a, Self>;
143
144 fn context_for_next_block(
147 &self,
148 parent: &SealedHeader<HeaderTy<Self::Primitives>>,
149 attributes: Self::NextBlockEnvCtx,
150 ) -> ExecutionCtxFor<'_, Self>;
151
152 fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self> {
154 transaction.into_tx_env()
155 }
156
157 fn evm_factory(&self) -> &EvmFactoryFor<Self> {
159 self.block_executor_factory().evm_factory()
160 }
161
162 fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnvFor<Self>) -> EvmFor<Self, DB> {
167 self.evm_factory().create_evm(db, evm_env)
168 }
169
170 fn evm_for_block<DB: Database>(
178 &self,
179 db: DB,
180 header: &HeaderTy<Self::Primitives>,
181 ) -> EvmFor<Self, DB> {
182 let evm_env = self.evm_env(header);
183 self.evm_with_env(db, evm_env)
184 }
185
186 fn evm_with_env_and_inspector<DB, I>(
193 &self,
194 db: DB,
195 evm_env: EvmEnvFor<Self>,
196 inspector: I,
197 ) -> EvmFor<Self, DB, I>
198 where
199 DB: Database,
200 I: InspectorFor<Self, DB>,
201 {
202 self.evm_factory().create_evm_with_inspector(db, evm_env, inspector)
203 }
204
205 fn create_executor<'a, DB, I>(
207 &'a self,
208 evm: EvmFor<Self, &'a mut State<DB>, I>,
209 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
210 ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
211 where
212 DB: Database,
213 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
214 {
215 self.block_executor_factory().create_executor(evm, ctx)
216 }
217
218 fn executor_for_block<'a, DB: Database>(
220 &'a self,
221 db: &'a mut State<DB>,
222 block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>,
223 ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB> {
224 let evm = self.evm_for_block(db, block.header());
225 let ctx = self.context_for_block(block);
226 self.create_executor(evm, ctx)
227 }
228
229 fn create_block_builder<'a, DB, I>(
236 &'a self,
237 evm: EvmFor<Self, &'a mut State<DB>, I>,
238 parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
239 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
240 ) -> impl BlockBuilder<
241 Primitives = Self::Primitives,
242 Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>,
243 >
244 where
245 DB: Database,
246 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
247 {
248 BasicBlockBuilder {
249 executor: self.create_executor(evm, ctx.clone()),
250 ctx,
251 assembler: self.block_assembler(),
252 parent,
253 transactions: Vec::new(),
254 }
255 }
256
257 fn builder_for_next_block<'a, DB: Database>(
260 &'a self,
261 db: &'a mut State<DB>,
262 parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>,
263 attributes: Self::NextBlockEnvCtx,
264 ) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error> {
265 let evm_env = self.next_evm_env(parent, &attributes)?;
266 let evm = self.evm_with_env(db, evm_env);
267 let ctx = self.context_for_next_block(parent, attributes);
268 Ok(self.create_block_builder(evm, parent, ctx))
269 }
270}
271
272#[derive(Debug, Clone, PartialEq, Eq)]
277pub struct NextBlockEnvAttributes {
278 pub timestamp: u64,
280 pub suggested_fee_recipient: Address,
282 pub prev_randao: B256,
284 pub gas_limit: u64,
286 pub parent_beacon_block_root: Option<B256>,
288 pub withdrawals: Option<Withdrawals>,
290}
291
292pub trait TransactionEnv:
294 revm::context_interface::Transaction + Debug + Clone + Send + Sync + 'static
295{
296 fn set_gas_limit(&mut self, gas_limit: u64);
298
299 fn with_gas_limit(mut self, gas_limit: u64) -> Self {
301 self.set_gas_limit(gas_limit);
302 self
303 }
304
305 fn nonce(&self) -> u64;
307
308 fn set_nonce(&mut self, nonce: u64);
310
311 fn with_nonce(mut self, nonce: u64) -> Self {
313 self.set_nonce(nonce);
314 self
315 }
316
317 fn set_access_list(&mut self, access_list: AccessList);
319
320 fn with_access_list(mut self, access_list: AccessList) -> Self {
322 self.set_access_list(access_list);
323 self
324 }
325}
326
327impl TransactionEnv for TxEnv {
328 fn set_gas_limit(&mut self, gas_limit: u64) {
329 self.gas_limit = gas_limit;
330 }
331
332 fn nonce(&self) -> u64 {
333 self.nonce
334 }
335
336 fn set_nonce(&mut self, nonce: u64) {
337 self.nonce = nonce;
338 }
339
340 fn set_access_list(&mut self, access_list: AccessList) {
341 self.access_list = access_list;
342 }
343}
344
345#[cfg(feature = "op")]
346impl<T: TransactionEnv> TransactionEnv for op_revm::OpTransaction<T> {
347 fn set_gas_limit(&mut self, gas_limit: u64) {
348 self.base.set_gas_limit(gas_limit);
349 }
350
351 fn nonce(&self) -> u64 {
352 TransactionEnv::nonce(&self.base)
353 }
354
355 fn set_nonce(&mut self, nonce: u64) {
356 self.base.set_nonce(nonce);
357 }
358
359 fn set_access_list(&mut self, access_list: AccessList) {
360 self.base.set_access_list(access_list);
361 }
362}