reth_evm/
test_utils.rs
1use crate::{
4 execute::{BasicBlockExecutor, BlockExecutionOutput, BlockExecutorProvider, Executor},
5 Database, OnStateHook,
6};
7use alloc::{sync::Arc, vec::Vec};
8use alloy_eips::eip7685::Requests;
9use parking_lot::Mutex;
10use reth_ethereum_primitives::EthPrimitives;
11use reth_execution_errors::BlockExecutionError;
12use reth_execution_types::{BlockExecutionResult, ExecutionOutcome};
13use reth_primitives_traits::{NodePrimitives, RecoveredBlock};
14use revm::database::State;
15
16#[derive(Clone, Debug, Default)]
18pub struct MockExecutorProvider {
19 exec_results: Arc<Mutex<Vec<ExecutionOutcome>>>,
20}
21
22impl MockExecutorProvider {
23 pub fn extend(&self, results: impl IntoIterator<Item = impl Into<ExecutionOutcome>>) {
25 self.exec_results.lock().extend(results.into_iter().map(Into::into));
26 }
27}
28
29impl BlockExecutorProvider for MockExecutorProvider {
30 type Primitives = EthPrimitives;
31
32 type Executor<DB: Database> = Self;
33
34 fn executor<DB>(&self, _: DB) -> Self::Executor<DB>
35 where
36 DB: Database,
37 {
38 self.clone()
39 }
40}
41
42impl<DB: Database> Executor<DB> for MockExecutorProvider {
43 type Primitives = EthPrimitives;
44 type Error = BlockExecutionError;
45
46 fn execute_one(
47 &mut self,
48 _block: &RecoveredBlock<<Self::Primitives as NodePrimitives>::Block>,
49 ) -> Result<BlockExecutionResult<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
50 {
51 let ExecutionOutcome { bundle: _, receipts, requests, first_block: _ } =
52 self.exec_results.lock().pop().unwrap();
53 Ok(BlockExecutionResult {
54 receipts: receipts.into_iter().flatten().collect(),
55 requests: requests.into_iter().fold(Requests::default(), |mut reqs, req| {
56 reqs.extend(req);
57 reqs
58 }),
59 gas_used: 0,
60 })
61 }
62
63 fn execute_one_with_state_hook<F>(
64 &mut self,
65 block: &RecoveredBlock<<Self::Primitives as NodePrimitives>::Block>,
66 _state_hook: F,
67 ) -> Result<BlockExecutionResult<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
68 where
69 F: OnStateHook + 'static,
70 {
71 <Self as Executor<DB>>::execute_one(self, block)
72 }
73
74 fn execute(
75 self,
76 _block: &RecoveredBlock<<Self::Primitives as NodePrimitives>::Block>,
77 ) -> Result<BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
78 {
79 let ExecutionOutcome { bundle, receipts, requests, first_block: _ } =
80 self.exec_results.lock().pop().unwrap();
81 Ok(BlockExecutionOutput {
82 state: bundle,
83 result: BlockExecutionResult {
84 receipts: receipts.into_iter().flatten().collect(),
85 requests: requests.into_iter().fold(Requests::default(), |mut reqs, req| {
86 reqs.extend(req);
87 reqs
88 }),
89 gas_used: 0,
90 },
91 })
92 }
93
94 fn execute_with_state_closure<F>(
95 self,
96 block: &RecoveredBlock<<Self::Primitives as NodePrimitives>::Block>,
97 _f: F,
98 ) -> Result<BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
99 where
100 F: FnMut(&revm::database::State<DB>),
101 {
102 <Self as Executor<DB>>::execute(self, block)
103 }
104
105 fn execute_with_state_hook<F>(
106 self,
107 block: &RecoveredBlock<<Self::Primitives as NodePrimitives>::Block>,
108 _state_hook: F,
109 ) -> Result<BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
110 where
111 F: OnStateHook + 'static,
112 {
113 <Self as Executor<DB>>::execute(self, block)
114 }
115
116 fn into_state(self) -> revm::database::State<DB> {
117 unreachable!()
118 }
119
120 fn size_hint(&self) -> usize {
121 0
122 }
123}
124
125impl<Factory, DB> BasicBlockExecutor<Factory, DB> {
126 pub fn with_state<F, R>(&self, f: F) -> R
128 where
129 F: FnOnce(&State<DB>) -> R,
130 {
131 f(&self.db)
132 }
133
134 pub fn with_state_mut<F, R>(&mut self, f: F) -> R
136 where
137 F: FnOnce(&mut State<DB>) -> R,
138 {
139 f(&mut self.db)
140 }
141}