1use crate::{
2 frame::EthFrame, instructions::InstructionProvider, Handler, MainnetHandler, PrecompileProvider,
3};
4use context::{
5 result::{
6 EVMError, ExecResultAndState, ExecutionResult, HaltReason, InvalidTransaction,
7 ResultAndState, ResultVecAndState,
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
16pub trait ExecuteEvm {
18 type ExecutionResult;
20 type State;
22 type Error;
24 type Tx: Transaction;
26 type Block: Block;
28
29 fn set_block(&mut self, block: Self::Block);
31
32 fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error>;
49
50 fn finalize(&mut self) -> Self::State;
55
56 #[inline]
64 fn transact(
65 &mut self,
66 tx: Self::Tx,
67 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error> {
68 let output_or_error = self.transact_one(tx);
69 let state = self.finalize();
71 let output = output_or_error?;
72 Ok(ExecResultAndState::new(output, state))
73 }
74
75 #[inline]
86 fn transact_many(
87 &mut self,
88 txs: impl Iterator<Item = Self::Tx>,
89 ) -> Result<Vec<Self::ExecutionResult>, Self::Error> {
90 let mut outputs = Vec::new();
91 for tx in txs {
92 outputs.push(self.transact_one(tx).inspect_err(|_| {
93 let _ = self.finalize();
94 })?);
95 }
96 Ok(outputs)
97 }
98
99 #[inline]
103 fn transact_many_finalize(
104 &mut self,
105 txs: impl Iterator<Item = Self::Tx>,
106 ) -> Result<ResultVecAndState<Self::ExecutionResult, Self::State>, Self::Error> {
107 let result = self.transact_many(txs)?;
109 let state = self.finalize();
110 Ok(ExecResultAndState::new(result, state))
111 }
112
113 fn replay(
115 &mut self,
116 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error>;
117}
118
119pub trait ExecuteCommitEvm: ExecuteEvm {
121 fn commit(&mut self, state: Self::State);
123
124 #[inline]
128 fn commit_inner(&mut self) {
129 let state = self.finalize();
130 self.commit(state);
131 }
132
133 #[inline]
135 fn transact_commit(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
136 let output = self.transact_one(tx)?;
137 self.commit_inner();
138 Ok(output)
139 }
140
141 #[inline]
145 fn transact_many_commit(
146 &mut self,
147 txs: impl Iterator<Item = Self::Tx>,
148 ) -> Result<Vec<Self::ExecutionResult>, Self::Error> {
149 let outputs = self.transact_many(txs)?;
150 self.commit_inner();
151 Ok(outputs)
152 }
153
154 #[inline]
158 fn replay_commit(&mut self) -> Result<Self::ExecutionResult, Self::Error> {
159 let result = self.replay()?;
160 self.commit(result.state);
161 Ok(result.result)
162 }
163}
164
165impl<CTX, INSP, INST, PRECOMPILES> ExecuteEvm
166 for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
167where
168 CTX: ContextTr<Journal: JournalTr<State = EvmState>> + ContextSetters,
169 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
170 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
171{
172 type ExecutionResult = ExecutionResult<HaltReason>;
173 type State = EvmState;
174 type Error = EVMError<<CTX::Db as Database>::Error, InvalidTransaction>;
175 type Tx = <CTX as ContextTr>::Tx;
176 type Block = <CTX as ContextTr>::Block;
177
178 #[inline]
179 fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
180 self.ctx.set_tx(tx);
181 MainnetHandler::default().run(self)
182 }
183
184 #[inline]
185 fn finalize(&mut self) -> Self::State {
186 self.journal_mut().finalize()
187 }
188
189 #[inline]
190 fn set_block(&mut self, block: Self::Block) {
191 self.ctx.set_block(block);
192 }
193
194 #[inline]
195 fn replay(&mut self) -> Result<ResultAndState<HaltReason>, Self::Error> {
196 MainnetHandler::default().run(self).map(|result| {
197 let state = self.finalize();
198 ResultAndState::new(result, state)
199 })
200 }
201}
202
203impl<CTX, INSP, INST, PRECOMPILES> ExecuteCommitEvm
204 for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
205where
206 CTX: ContextTr<Journal: JournalTr<State = EvmState>, Db: DatabaseCommit> + ContextSetters,
207 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
208 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
209{
210 #[inline]
211 fn commit(&mut self, state: Self::State) {
212 self.db_mut().commit(state);
213 }
214}