1use crate::{
2 frame::EthFrame, instructions::InstructionProvider, Handler, MainnetHandler, PrecompileProvider,
3};
4use context::{
5 result::{
6 EVMError, ExecResultAndState, ExecutionResult, HaltReason, InvalidTransaction,
7 ResultAndState, ResultVecAndState, TransactionIndexedError,
8 },
9 Block, ContextSetters, ContextTr, Database, Evm, JournalTr, Transaction,
10};
11use database_interface::DatabaseCommit;
12use interpreter::{interpreter::EthInterpreter, InterpreterResult};
13use state::EvmState;
14use std::vec::Vec;
15
16type TransactManyFinalizeResult<ExecutionResult, State, Error> =
18 Result<ResultVecAndState<ExecutionResult, State>, TransactionIndexedError<Error>>;
19
20pub trait ExecuteEvm {
22 type ExecutionResult;
24 type State;
26 type Error;
28 type Tx: Transaction;
30 type Block: Block;
32
33 fn set_block(&mut self, block: Self::Block);
35
36 fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error>;
53
54 fn finalize(&mut self) -> Self::State;
59
60 #[inline]
68 fn transact(
69 &mut self,
70 tx: Self::Tx,
71 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error> {
72 let output_or_error = self.transact_one(tx);
73 let state = self.finalize();
75 let output = output_or_error?;
76 Ok(ExecResultAndState::new(output, state))
77 }
78
79 #[inline]
89 fn transact_many(
90 &mut self,
91 txs: impl Iterator<Item = Self::Tx>,
92 ) -> Result<Vec<Self::ExecutionResult>, TransactionIndexedError<Self::Error>> {
93 let (lower, _) = txs.size_hint();
94 let mut outputs = Vec::with_capacity(lower);
95 for (index, tx) in txs.enumerate() {
96 outputs.push(
97 self.transact_one(tx)
98 .inspect_err(|_| {
99 let _ = self.finalize();
100 })
101 .map_err(|error| TransactionIndexedError::new(error, index))?,
102 );
103 }
104 Ok(outputs)
105 }
106
107 #[inline]
111 fn transact_many_finalize(
112 &mut self,
113 txs: impl Iterator<Item = Self::Tx>,
114 ) -> TransactManyFinalizeResult<Self::ExecutionResult, Self::State, Self::Error> {
115 let result = self.transact_many(txs)?;
117 let state = self.finalize();
118 Ok(ExecResultAndState::new(result, state))
119 }
120
121 fn replay(
123 &mut self,
124 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error>;
125}
126
127pub trait ExecuteCommitEvm: ExecuteEvm {
129 fn commit(&mut self, state: Self::State);
131
132 #[inline]
136 fn commit_inner(&mut self) {
137 let state = self.finalize();
138 self.commit(state);
139 }
140
141 #[inline]
148 fn transact_commit(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
149 let output = self.transact_one(tx).inspect_err(|_| {
150 let _ = self.finalize();
152 })?;
153 self.commit_inner();
154 Ok(output)
155 }
156
157 #[inline]
161 fn transact_many_commit(
162 &mut self,
163 txs: impl Iterator<Item = Self::Tx>,
164 ) -> Result<Vec<Self::ExecutionResult>, TransactionIndexedError<Self::Error>> {
165 let outputs = self.transact_many(txs)?;
166 self.commit_inner();
167 Ok(outputs)
168 }
169
170 #[inline]
174 fn replay_commit(&mut self) -> Result<Self::ExecutionResult, Self::Error> {
175 let result = self.replay()?;
176 self.commit(result.state);
177 Ok(result.result)
178 }
179}
180
181impl<CTX, INSP, INST, PRECOMPILES> ExecuteEvm
182 for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
183where
184 CTX: ContextTr<Journal: JournalTr<State = EvmState>> + ContextSetters,
185 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
186 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
187{
188 type ExecutionResult = ExecutionResult<HaltReason>;
189 type State = EvmState;
190 type Error = EVMError<<CTX::Db as Database>::Error, InvalidTransaction>;
191 type Tx = <CTX as ContextTr>::Tx;
192 type Block = <CTX as ContextTr>::Block;
193
194 #[inline]
195 fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
196 self.ctx.set_tx(tx);
197 MainnetHandler::default().run(self)
198 }
199
200 #[inline]
201 fn finalize(&mut self) -> Self::State {
202 self.journal_mut().finalize()
203 }
204
205 #[inline]
206 fn set_block(&mut self, block: Self::Block) {
207 self.ctx.set_block(block);
208 }
209
210 #[inline]
211 fn replay(&mut self) -> Result<ResultAndState<HaltReason>, Self::Error> {
212 MainnetHandler::default()
213 .run(self)
214 .inspect_err(|_| {
217 let _ = self.finalize();
218 })
219 .map(|result| {
220 let state = self.finalize();
221 ResultAndState::new(result, state)
222 })
223 }
224}
225
226impl<CTX, INSP, INST, PRECOMPILES> ExecuteCommitEvm
227 for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
228where
229 CTX: ContextTr<Journal: JournalTr<State = EvmState>, Db: DatabaseCommit> + ContextSetters,
230 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
231 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
232{
233 #[inline]
234 fn commit(&mut self, state: Self::State) {
235 self.db_mut().commit(state);
236 }
237}