1use crate::{
4 execute::{
5 BasicBatchExecutor, BasicBlockExecutor, BatchExecutor, BlockExecutionInput,
6 BlockExecutionOutput, BlockExecutionStrategy, BlockExecutorProvider, Executor,
7 },
8 provider::EvmEnvProvider,
9 system_calls::OnStateHook,
10 ConfigureEvmEnv,
11};
12use alloy_eips::eip7685::Requests;
13use alloy_primitives::{BlockNumber, U256};
14use parking_lot::Mutex;
15use reth_execution_errors::BlockExecutionError;
16use reth_execution_types::ExecutionOutcome;
17use reth_primitives::{BlockWithSenders, EthPrimitives, NodePrimitives, Receipt, Receipts};
18use reth_prune_types::PruneModes;
19use reth_storage_errors::provider::{ProviderError, ProviderResult};
20use revm::State;
21use revm_primitives::{db::Database, BlockEnv, CfgEnvWithHandlerCfg};
22use std::{fmt::Display, sync::Arc};
23
24impl<C: Send + Sync, N: NodePrimitives> EvmEnvProvider<N::BlockHeader>
25 for reth_storage_api::noop::NoopProvider<C, N>
26{
27 fn env_with_header<EvmConfig>(
28 &self,
29 header: &N::BlockHeader,
30 evm_config: EvmConfig,
31 ) -> ProviderResult<(CfgEnvWithHandlerCfg, BlockEnv)>
32 where
33 EvmConfig: ConfigureEvmEnv<Header = N::BlockHeader>,
34 {
35 Ok(evm_config.cfg_and_block_env(header, U256::MAX))
36 }
37}
38
39#[derive(Clone, Debug, Default)]
41pub struct MockExecutorProvider {
42 exec_results: Arc<Mutex<Vec<ExecutionOutcome>>>,
43}
44
45impl MockExecutorProvider {
46 pub fn extend(&self, results: impl IntoIterator<Item = impl Into<ExecutionOutcome>>) {
48 self.exec_results.lock().extend(results.into_iter().map(Into::into));
49 }
50}
51
52impl BlockExecutorProvider for MockExecutorProvider {
53 type Primitives = EthPrimitives;
54
55 type Executor<DB: Database<Error: Into<ProviderError> + Display>> = Self;
56
57 type BatchExecutor<DB: Database<Error: Into<ProviderError> + Display>> = Self;
58
59 fn executor<DB>(&self, _: DB) -> Self::Executor<DB>
60 where
61 DB: Database<Error: Into<ProviderError> + Display>,
62 {
63 self.clone()
64 }
65
66 fn batch_executor<DB>(&self, _: DB) -> Self::BatchExecutor<DB>
67 where
68 DB: Database<Error: Into<ProviderError> + Display>,
69 {
70 self.clone()
71 }
72}
73
74impl<DB> Executor<DB> for MockExecutorProvider {
75 type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
76 type Output = BlockExecutionOutput<Receipt>;
77 type Error = BlockExecutionError;
78
79 fn execute(self, _: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
80 let ExecutionOutcome { bundle, receipts, requests, first_block: _ } =
81 self.exec_results.lock().pop().unwrap();
82 Ok(BlockExecutionOutput {
83 state: bundle,
84 receipts: receipts.into_iter().flatten().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 fn execute_with_state_closure<F>(
94 self,
95 input: Self::Input<'_>,
96 _: F,
97 ) -> Result<Self::Output, Self::Error>
98 where
99 F: FnMut(&State<DB>),
100 {
101 <Self as Executor<DB>>::execute(self, input)
102 }
103
104 fn execute_with_state_hook<F>(
105 self,
106 input: Self::Input<'_>,
107 _: F,
108 ) -> Result<Self::Output, Self::Error>
109 where
110 F: OnStateHook,
111 {
112 <Self as Executor<DB>>::execute(self, input)
113 }
114}
115
116impl<DB> BatchExecutor<DB> for MockExecutorProvider {
117 type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
118 type Output = ExecutionOutcome;
119 type Error = BlockExecutionError;
120
121 fn execute_and_verify_one(&mut self, _: Self::Input<'_>) -> Result<(), Self::Error> {
122 Ok(())
123 }
124
125 fn finalize(self) -> Self::Output {
126 self.exec_results.lock().pop().unwrap()
127 }
128
129 fn set_tip(&mut self, _: BlockNumber) {}
130
131 fn set_prune_modes(&mut self, _: PruneModes) {}
132
133 fn size_hint(&self) -> Option<usize> {
134 None
135 }
136}
137
138impl<S> BasicBlockExecutor<S>
139where
140 S: BlockExecutionStrategy,
141{
142 pub fn with_state<F, R>(&self, f: F) -> R
144 where
145 F: FnOnce(&State<S::DB>) -> R,
146 {
147 f(self.strategy.state_ref())
148 }
149
150 pub fn with_state_mut<F, R>(&mut self, f: F) -> R
152 where
153 F: FnOnce(&mut State<S::DB>) -> R,
154 {
155 f(self.strategy.state_mut())
156 }
157}
158
159impl<S> BasicBatchExecutor<S>
160where
161 S: BlockExecutionStrategy,
162{
163 pub fn with_state<F, R>(&self, f: F) -> R
165 where
166 F: FnOnce(&State<S::DB>) -> R,
167 {
168 f(self.strategy.state_ref())
169 }
170
171 pub fn with_state_mut<F, R>(&mut self, f: F) -> R
173 where
174 F: FnOnce(&mut State<S::DB>) -> R,
175 {
176 f(self.strategy.state_mut())
177 }
178
179 pub const fn receipts(&self) -> &Receipts<<S::Primitives as NodePrimitives>::Receipt> {
181 self.batch_record.receipts()
182 }
183}