1use crate::{
2 instructions::InstructionProvider, item_or_result::FrameInitOrResult, EthFrame, FrameResult,
3 ItemOrResult, PrecompileProvider,
4};
5use auto_impl::auto_impl;
6use context::{ContextTr, Database, Evm, FrameStack};
7use context_interface::context::ContextError;
8use interpreter::{interpreter::EthInterpreter, interpreter_action::FrameInit, InterpreterResult};
9
10pub type ContextDbError<CTX> = ContextError<ContextTrDbError<CTX>>;
12
13pub type ContextTrDbError<CTX> = <<CTX as ContextTr>::Db as Database>::Error;
15
16pub type FrameInitResult<'a, F> = ItemOrResult<&'a mut F, <F as FrameTr>::FrameResult>;
18
19#[auto_impl(&mut, Box)]
21pub trait FrameTr {
22 type FrameResult: From<FrameResult>;
24 type FrameInit: From<FrameInit>;
26}
27
28#[auto_impl(&mut, Box)]
32pub trait EvmTr {
33 type Context: ContextTr;
35 type Instructions: InstructionProvider;
37 type Precompiles: PrecompileProvider<Self::Context>;
39 type Frame: FrameTr;
41
42 #[allow(clippy::type_complexity)]
44 fn all(
45 &self,
46 ) -> (
47 &Self::Context,
48 &Self::Instructions,
49 &Self::Precompiles,
50 &FrameStack<Self::Frame>,
51 );
52
53 #[allow(clippy::type_complexity)]
55 fn all_mut(
56 &mut self,
57 ) -> (
58 &mut Self::Context,
59 &mut Self::Instructions,
60 &mut Self::Precompiles,
61 &mut FrameStack<Self::Frame>,
62 );
63
64 #[inline]
66 fn ctx(&mut self) -> &mut Self::Context {
67 let (ctx, _, _, _) = self.all_mut();
68 ctx
69 }
70
71 #[inline]
73 fn ctx_mut(&mut self) -> &mut Self::Context {
74 self.ctx()
75 }
76
77 #[inline]
79 fn ctx_ref(&self) -> &Self::Context {
80 let (ctx, _, _, _) = self.all();
81 ctx
82 }
83
84 #[inline]
87 fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions) {
88 let (ctx, instructions, _, _) = self.all_mut();
89 (ctx, instructions)
90 }
91
92 #[inline]
95 fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles) {
96 let (ctx, _, precompiles, _) = self.all_mut();
97 (ctx, precompiles)
98 }
99
100 #[inline]
102 fn frame_stack(&mut self) -> &mut FrameStack<Self::Frame> {
103 let (_, _, _, frame_stack) = self.all_mut();
104 frame_stack
105 }
106
107 fn frame_init(
109 &mut self,
110 frame_input: <Self::Frame as FrameTr>::FrameInit,
111 ) -> Result<FrameInitResult<'_, Self::Frame>, ContextDbError<Self::Context>>;
112
113 fn frame_run(
117 &mut self,
118 ) -> Result<FrameInitOrResult<Self::Frame>, ContextDbError<Self::Context>>;
119
120 fn frame_return_result(
123 &mut self,
124 result: <Self::Frame as FrameTr>::FrameResult,
125 ) -> Result<Option<<Self::Frame as FrameTr>::FrameResult>, ContextDbError<Self::Context>>;
126}
127
128impl<CTX, INSP, I, P> EvmTr for Evm<CTX, INSP, I, P, EthFrame<EthInterpreter>>
129where
130 CTX: ContextTr,
131 I: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
132 P: PrecompileProvider<CTX, Output = InterpreterResult>,
133{
134 type Context = CTX;
135 type Instructions = I;
136 type Precompiles = P;
137 type Frame = EthFrame<EthInterpreter>;
138
139 #[inline]
140 fn all(
141 &self,
142 ) -> (
143 &Self::Context,
144 &Self::Instructions,
145 &Self::Precompiles,
146 &FrameStack<Self::Frame>,
147 ) {
148 let ctx = &self.ctx;
149 let instructions = &self.instruction;
150 let precompiles = &self.precompiles;
151 let frame_stack = &self.frame_stack;
152 (ctx, instructions, precompiles, frame_stack)
153 }
154
155 #[inline]
156 fn all_mut(
157 &mut self,
158 ) -> (
159 &mut Self::Context,
160 &mut Self::Instructions,
161 &mut Self::Precompiles,
162 &mut FrameStack<Self::Frame>,
163 ) {
164 let ctx = &mut self.ctx;
165 let instructions = &mut self.instruction;
166 let precompiles = &mut self.precompiles;
167 let frame_stack = &mut self.frame_stack;
168 (ctx, instructions, precompiles, frame_stack)
169 }
170
171 #[inline]
173 fn frame_init(
174 &mut self,
175 frame_input: <Self::Frame as FrameTr>::FrameInit,
176 ) -> Result<FrameInitResult<'_, Self::Frame>, ContextDbError<CTX>> {
177 let is_first_init = self.frame_stack.index().is_none();
178 let new_frame = if is_first_init {
179 self.frame_stack.start_init()
180 } else {
181 self.frame_stack.get_next()
182 };
183
184 let ctx = &mut self.ctx;
185 let precompiles = &mut self.precompiles;
186 let res = Self::Frame::init_with_context(new_frame, ctx, precompiles, frame_input)?;
187
188 Ok(res.map_frame(|token| {
189 if is_first_init {
190 unsafe { self.frame_stack.end_init(token) };
191 } else {
192 unsafe { self.frame_stack.push(token) };
193 }
194 self.frame_stack.get()
195 }))
196 }
197
198 #[inline]
200 fn frame_run(&mut self) -> Result<FrameInitOrResult<Self::Frame>, ContextDbError<CTX>> {
201 let frame = self.frame_stack.get();
202 let context = &mut self.ctx;
203 let instructions = &mut self.instruction;
204
205 let action = frame
206 .interpreter
207 .run_plain(instructions.instruction_table(), context);
208
209 frame.process_next_action(context, action).inspect(|i| {
210 if i.is_result() {
211 frame.set_finished(true);
212 }
213 })
214 }
215
216 #[inline]
218 fn frame_return_result(
219 &mut self,
220 result: <Self::Frame as FrameTr>::FrameResult,
221 ) -> Result<Option<<Self::Frame as FrameTr>::FrameResult>, ContextDbError<Self::Context>> {
222 if self.frame_stack.get().is_finished() {
223 self.frame_stack.pop();
224 }
225 if self.frame_stack.index().is_none() {
226 return Ok(Some(result));
227 }
228 self.frame_stack
229 .get()
230 .return_result::<_, ContextDbError<Self::Context>>(&mut self.ctx, result)?;
231 Ok(None)
232 }
233}