1use crate::{
2 instructions::InstructionProvider, EthFrame, Handler, MainnetHandler, PrecompileProvider,
3};
4use auto_impl::auto_impl;
5use context::{
6 result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction, ResultAndState},
7 Block, ContextSetters, ContextTr, Database, Evm, JournalOutput, JournalTr, Transaction,
8};
9use database_interface::DatabaseCommit;
10use interpreter::{
11 interpreter::EthInterpreter, Interpreter, InterpreterAction, InterpreterResult,
12 InterpreterTypes,
13};
14
15#[auto_impl(&mut, Box)]
19pub trait EvmTr {
20 type Context: ContextTr;
22 type Instructions: InstructionProvider;
24 type Precompiles: PrecompileProvider<Self::Context>;
26
27 fn run_interpreter(
30 &mut self,
31 interpreter: &mut Interpreter<
32 <Self::Instructions as InstructionProvider>::InterpreterTypes,
33 >,
34 ) -> <<Self::Instructions as InstructionProvider>::InterpreterTypes as InterpreterTypes>::Output;
35
36 fn ctx(&mut self) -> &mut Self::Context;
38
39 fn ctx_ref(&self) -> &Self::Context;
41
42 fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions);
45
46 fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles);
49}
50
51pub trait ExecuteEvm {
53 type Output;
55 type Tx: Transaction;
57 type Block: Block;
59
60 fn set_tx(&mut self, tx: Self::Tx);
62
63 fn set_block(&mut self, block: Self::Block);
65
66 fn replay(&mut self) -> Self::Output;
68
69 fn transact(&mut self, tx: Self::Tx) -> Self::Output {
73 self.set_tx(tx);
74 self.replay()
75 }
76}
77
78pub trait ExecuteCommitEvm: ExecuteEvm {
80 type CommitOutput;
82
83 fn replay_commit(&mut self) -> Self::CommitOutput;
85
86 fn transact_commit(&mut self, tx: Self::Tx) -> Self::CommitOutput {
88 self.set_tx(tx);
89 self.replay_commit()
90 }
91}
92
93impl<CTX, INSP, I, P> EvmTr for Evm<CTX, INSP, I, P>
94where
95 CTX: ContextTr,
96 I: InstructionProvider<
97 Context = CTX,
98 InterpreterTypes: InterpreterTypes<Output = InterpreterAction>,
99 >,
100 P: PrecompileProvider<CTX>,
101{
102 type Context = CTX;
103 type Instructions = I;
104 type Precompiles = P;
105
106 #[inline]
107 fn run_interpreter(
108 &mut self,
109 interpreter: &mut Interpreter<
110 <Self::Instructions as InstructionProvider>::InterpreterTypes,
111 >,
112 ) -> <<Self::Instructions as InstructionProvider>::InterpreterTypes as InterpreterTypes>::Output
113 {
114 let context = &mut self.data.ctx;
115 let instructions = &mut self.instruction;
116 interpreter.run_plain(instructions.instruction_table(), context)
117 }
118 #[inline]
119 fn ctx(&mut self) -> &mut Self::Context {
120 &mut self.data.ctx
121 }
122
123 #[inline]
124 fn ctx_ref(&self) -> &Self::Context {
125 &self.data.ctx
126 }
127
128 #[inline]
129 fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions) {
130 (&mut self.data.ctx, &mut self.instruction)
131 }
132
133 #[inline]
134 fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles) {
135 (&mut self.data.ctx, &mut self.precompiles)
136 }
137}
138
139impl<CTX, INSP, INST, PRECOMPILES> ExecuteEvm for Evm<CTX, INSP, INST, PRECOMPILES>
140where
141 CTX: ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>> + ContextSetters,
142 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
143 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
144{
145 type Output = Result<
146 ResultAndState<HaltReason>,
147 EVMError<<CTX::Db as Database>::Error, InvalidTransaction>,
148 >;
149
150 type Tx = <CTX as ContextTr>::Tx;
151
152 type Block = <CTX as ContextTr>::Block;
153
154 fn replay(&mut self) -> Self::Output {
155 let mut t = MainnetHandler::<_, _, EthFrame<_, _, _>>::default();
156 t.run(self)
157 }
158
159 fn set_tx(&mut self, tx: Self::Tx) {
160 self.data.ctx.set_tx(tx);
161 }
162
163 fn set_block(&mut self, block: Self::Block) {
164 self.data.ctx.set_block(block);
165 }
166}
167
168impl<CTX, INSP, INST, PRECOMPILES> ExecuteCommitEvm for Evm<CTX, INSP, INST, PRECOMPILES>
169where
170 CTX: ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>, Db: DatabaseCommit>
171 + ContextSetters,
172 INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
173 PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
174{
175 type CommitOutput = Result<
176 ExecutionResult<HaltReason>,
177 EVMError<<CTX::Db as Database>::Error, InvalidTransaction>,
178 >;
179
180 fn replay_commit(&mut self) -> Self::CommitOutput {
181 self.replay().map(|r| {
182 self.db().commit(r.state);
183 r.result
184 })
185 }
186}