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(
117 &mut self,
118 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error>;
119}
120
121pub trait ExecuteCommitEvm: ExecuteEvm {
123 fn commit(&mut self, state: Self::State);
125
126 #[inline]
130 fn commit_inner(&mut self) {
131 let state = self.finalize();
132 self.commit(state);
133 }
134
135 #[inline]
137 fn transact_commit(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
138 let output = self.transact_one(tx)?;
139 self.commit_inner();
140 Ok(output)
141 }
142
143 #[inline]
147 fn transact_many_commit(
148 &mut self,
149 txs: impl Iterator<Item = Self::Tx>,
150 ) -> Result<Vec<Self::ExecutionResult>, Self::Error> {
151 let outputs = self.transact_many(txs)?;
152 self.commit_inner();
153 Ok(outputs)
154 }
155
156 #[inline]
160 fn replay_commit(&mut self) -> Result<Self::ExecutionResult, Self::Error> {
161 let result = self.replay()?;
162 self.commit(result.state);
163 Ok(result.result)
164 }
165}
166
167impl<CTX, INSP, INST, PRECOMPILES> ExecuteEvm
168 for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
169where
170 CTX: ContextTr<Journal: JournalTr<State = EvmState>> + ContextSetters,
171 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
172 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
173{
174 type ExecutionResult = ExecutionResult<HaltReason>;
175 type State = EvmState;
176 type Error = EVMError<<CTX::Db as Database>::Error, InvalidTransaction>;
177 type Tx = <CTX as ContextTr>::Tx;
178 type Block = <CTX as ContextTr>::Block;
179
180 #[inline]
181 fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
182 self.ctx.set_tx(tx);
183 MainnetHandler::default().run(self)
184 }
185
186 #[inline]
187 fn finalize(&mut self) -> Self::State {
188 self.journal_mut().finalize()
189 }
190
191 #[inline]
192 fn set_block(&mut self, block: Self::Block) {
193 self.ctx.set_block(block);
194 }
195
196 #[inline]
197 fn replay(&mut self) -> Result<ResultAndState<HaltReason>, Self::Error> {
198 MainnetHandler::default().run(self).map(|result| {
199 let state = self.finalize();
200 ResultAndState::new(result, state)
201 })
202 }
203}
204
205impl<CTX, INSP, INST, PRECOMPILES> ExecuteCommitEvm
206 for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
207where
208 CTX: ContextTr<Journal: JournalTr<State = EvmState>, Db: DatabaseCommit> + ContextSetters,
209 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
210 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
211{
212 #[inline]
213 fn commit(&mut self, state: Self::State) {
214 self.db_mut().commit(state);
215 }
216}