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/SeismicSystems/seismic-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::{
23 eip2718::{EIP2930_TX_TYPE_ID, LEGACY_TX_TYPE_ID},
24 eip2930::AccessList,
25 eip4895::Withdrawals,
26};
27use alloy_evm::block::{BlockExecutorFactory, BlockExecutorFor};
28use alloy_primitives::{Address, B256};
29use core::{error::Error, fmt::Debug};
30use execute::{BasicBlockExecutor, BlockAssembler, BlockBuilder};
31use reth_primitives_traits::{
32 BlockTy, HeaderTy, NodePrimitives, ReceiptTy, SealedBlock, SealedHeader, TxTy,
33};
34use revm::{context::TxEnv, database::State};
35
36pub mod either;
37pub mod execute;
39
40mod aliases;
41pub use aliases::*;
42
43#[cfg(feature = "metrics")]
44pub mod metrics;
45pub mod noop;
46#[cfg(any(test, feature = "test-utils"))]
47pub mod test_utils;
49
50pub use alloy_evm::{
51 block::{state_changes, system_calls, OnStateHook},
52 *,
53};
54
55pub use alloy_evm::block::state_changes as state_change;
56
57#[auto_impl::auto_impl(&, Arc)]
96pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
97 type Primitives: NodePrimitives;
99
100 type Error: Error + Send + Sync + 'static;
102
103 type NextBlockEnvCtx: Debug + Clone;
107
108 type BlockExecutorFactory: BlockExecutorFactory<
110 Transaction = TxTy<Self::Primitives>,
111 Receipt = ReceiptTy<Self::Primitives>,
112 EvmFactory: EvmFactory<
113 Tx: TransactionEnv
114 + FromRecoveredTx<TxTy<Self::Primitives>>
115 + FromTxWithEncoded<TxTy<Self::Primitives>>,
116 >,
118 >;
119
120 type BlockAssembler: BlockAssembler<
122 Self::BlockExecutorFactory,
123 Block = BlockTy<Self::Primitives>,
124 >;
125
126 fn block_executor_factory(&self) -> &Self::BlockExecutorFactory;
128
129 fn block_assembler(&self) -> &Self::BlockAssembler;
131
132 fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>;
134
135 fn next_evm_env(
141 &self,
142 parent: &HeaderTy<Self::Primitives>,
143 attributes: &Self::NextBlockEnvCtx,
144 ) -> Result<EvmEnvFor<Self>, Self::Error>;
145
146 fn context_for_block<'a>(
148 &self,
149 block: &'a SealedBlock<BlockTy<Self::Primitives>>,
150 ) -> ExecutionCtxFor<'a, Self>;
151
152 fn context_for_next_block(
155 &self,
156 parent: &SealedHeader<HeaderTy<Self::Primitives>>,
157 attributes: Self::NextBlockEnvCtx,
158 ) -> ExecutionCtxFor<'_, Self>;
159
160 fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self> {
162 transaction.into_tx_env()
163 }
164
165 fn evm_factory(&self) -> &EvmFactoryFor<Self> {
167 self.block_executor_factory().evm_factory()
168 }
169
170 fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnvFor<Self>) -> EvmFor<Self, DB> {
175 self.evm_factory().create_evm(db, evm_env)
176 }
177
178 fn evm_for_block<DB: Database>(
186 &self,
187 db: DB,
188 header: &HeaderTy<Self::Primitives>,
189 ) -> EvmFor<Self, DB> {
190 let evm_env = self.evm_env(header);
191 self.evm_with_env(db, evm_env)
192 }
193
194 fn evm_with_env_and_inspector<DB, I>(
201 &self,
202 db: DB,
203 evm_env: EvmEnvFor<Self>,
204 inspector: I,
205 ) -> EvmFor<Self, DB, I>
206 where
207 DB: Database,
208 I: InspectorFor<Self, DB>,
209 {
210 self.evm_factory().create_evm_with_inspector(db, evm_env, inspector)
211 }
212
213 fn create_executor<'a, DB, I>(
215 &'a self,
216 evm: EvmFor<Self, &'a mut State<DB>, I>,
217 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
218 ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
219 where
220 DB: Database,
221 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
222 {
223 self.block_executor_factory().create_executor(evm, ctx)
224 }
225
226 fn executor_for_block<'a, DB: Database>(
228 &'a self,
229 db: &'a mut State<DB>,
230 block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>,
231 ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB> {
232 let evm = self.evm_for_block(db, block.header());
233 let ctx = self.context_for_block(block);
234 self.create_executor(evm, ctx)
235 }
236
237 fn create_block_builder<'a, DB, I>(
244 &'a self,
245 evm: EvmFor<Self, &'a mut State<DB>, I>,
246 parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
247 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
248 ) -> impl BlockBuilder<
249 Primitives = Self::Primitives,
250 Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>,
251 >
252 where
253 DB: Database,
254 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
255 {
256 BasicBlockBuilder {
257 executor: self.create_executor(evm, ctx.clone()),
258 ctx,
259 assembler: self.block_assembler(),
260 parent,
261 transactions: Vec::new(),
262 }
263 }
264
265 fn builder_for_next_block<'a, DB: Database>(
268 &'a self,
269 db: &'a mut State<DB>,
270 parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>,
271 attributes: Self::NextBlockEnvCtx,
272 ) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error> {
273 let evm_env = self.next_evm_env(parent, &attributes)?;
274 let evm = self.evm_with_env(db, evm_env);
275 let ctx = self.context_for_next_block(parent, attributes);
276 Ok(self.create_block_builder(evm, parent, ctx))
277 }
278
279 #[auto_impl(keep_default_for(&, Arc))]
281 fn executor<DB: Database>(&self, db: DB) -> BasicBlockExecutor<&Self, DB> {
282 BasicBlockExecutor::new(self, db)
283 }
284
285 #[auto_impl(keep_default_for(&, Arc))]
287 fn batch_executor<DB: Database>(&self, db: DB) -> BasicBlockExecutor<&Self, DB> {
288 BasicBlockExecutor::new(self, db)
289 }
290}
291
292#[derive(Debug, Clone, PartialEq, Eq)]
297pub struct NextBlockEnvAttributes {
298 pub timestamp: u64,
300 pub suggested_fee_recipient: Address,
302 pub prev_randao: B256,
304 pub gas_limit: u64,
306 pub parent_beacon_block_root: Option<B256>,
308 pub withdrawals: Option<Withdrawals>,
310}
311
312pub trait TransactionEnv:
314 revm::context_interface::Transaction + Debug + Clone + Send + Sync + 'static
315{
316 fn set_gas_limit(&mut self, gas_limit: u64);
318
319 fn with_gas_limit(mut self, gas_limit: u64) -> Self {
321 self.set_gas_limit(gas_limit);
322 self
323 }
324
325 fn nonce(&self) -> u64;
327
328 fn set_nonce(&mut self, nonce: u64);
330
331 fn with_nonce(mut self, nonce: u64) -> Self {
333 self.set_nonce(nonce);
334 self
335 }
336
337 fn set_access_list(&mut self, access_list: AccessList);
339
340 fn with_access_list(mut self, access_list: AccessList) -> Self {
342 self.set_access_list(access_list);
343 self
344 }
345}
346
347impl TransactionEnv for TxEnv {
348 fn set_gas_limit(&mut self, gas_limit: u64) {
349 self.gas_limit = gas_limit;
350 }
351
352 fn nonce(&self) -> u64 {
353 self.nonce
354 }
355
356 fn set_nonce(&mut self, nonce: u64) {
357 self.nonce = nonce;
358 }
359
360 fn set_access_list(&mut self, access_list: AccessList) {
361 self.access_list = access_list;
362
363 if self.tx_type == LEGACY_TX_TYPE_ID {
364 self.tx_type = EIP2930_TX_TYPE_ID;
367 }
368 }
369}
370
371#[cfg(feature = "op")]
372impl<T: TransactionEnv> TransactionEnv for op_revm::OpTransaction<T> {
373 fn set_gas_limit(&mut self, gas_limit: u64) {
374 self.base.set_gas_limit(gas_limit);
375 }
376
377 fn nonce(&self) -> u64 {
378 TransactionEnv::nonce(&self.base)
379 }
380
381 fn set_nonce(&mut self, nonce: u64) {
382 self.base.set_nonce(nonce);
383 }
384
385 fn set_access_list(&mut self, access_list: AccessList) {
386 self.base.set_access_list(access_list);
387 }
388}
389
390impl<T: TransactionEnv> TransactionEnv for seismic_revm::SeismicTransaction<T> {
391 fn set_gas_limit(&mut self, gas_limit: u64) {
392 self.base.set_gas_limit(gas_limit);
393 }
394
395 fn nonce(&self) -> u64 {
396 TransactionEnv::nonce(&self.base)
397 }
398
399 fn set_nonce(&mut self, nonce: u64) {
400 self.base.set_nonce(nonce);
401 }
402
403 fn set_access_list(&mut self, access_list: AccessList) {
404 self.base.set_access_list(access_list);
405 }
406}