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]
143 fn transact_commit(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
144 let output = self.transact_one(tx)?;
145 self.commit_inner();
146 Ok(output)
147 }
148
149 #[inline]
153 fn transact_many_commit(
154 &mut self,
155 txs: impl Iterator<Item = Self::Tx>,
156 ) -> Result<Vec<Self::ExecutionResult>, TransactionIndexedError<Self::Error>> {
157 let outputs = self.transact_many(txs)?;
158 self.commit_inner();
159 Ok(outputs)
160 }
161
162 #[inline]
166 fn replay_commit(&mut self) -> Result<Self::ExecutionResult, Self::Error> {
167 let result = self.replay()?;
168 self.commit(result.state);
169 Ok(result.result)
170 }
171}
172
173impl<CTX, INSP, INST, PRECOMPILES> ExecuteEvm
174 for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
175where
176 CTX: ContextTr<Journal: JournalTr<State = EvmState>> + ContextSetters,
177 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
178 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
179{
180 type ExecutionResult = ExecutionResult<HaltReason>;
181 type State = EvmState;
182 type Error = EVMError<<CTX::Db as Database>::Error, InvalidTransaction>;
183 type Tx = <CTX as ContextTr>::Tx;
184 type Block = <CTX as ContextTr>::Block;
185
186 #[inline]
187 fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
188 self.ctx.set_tx(tx);
189 MainnetHandler::default().run(self)
190 }
191
192 #[inline]
193 fn finalize(&mut self) -> Self::State {
194 self.journal_mut().finalize()
195 }
196
197 #[inline]
198 fn set_block(&mut self, block: Self::Block) {
199 self.ctx.set_block(block);
200 }
201
202 #[inline]
203 fn replay(&mut self) -> Result<ResultAndState<HaltReason>, Self::Error> {
204 MainnetHandler::default().run(self).map(|result| {
205 let state = self.finalize();
206 ResultAndState::new(result, state)
207 })
208 }
209}
210
211impl<CTX, INSP, INST, PRECOMPILES> ExecuteCommitEvm
212 for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
213where
214 CTX: ContextTr<Journal: JournalTr<State = EvmState>, Db: DatabaseCommit> + ContextSetters,
215 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
216 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
217{
218 #[inline]
219 fn commit(&mut self, state: Self::State) {
220 self.db_mut().commit(state);
221 }
222}