1use crate::{Inspector, InspectorEvmTr, InspectorFrame, JournalExt};
2use context::{result::ExecutionResult, ContextTr, JournalEntry, Transaction};
3use handler::{EvmTr, Frame, FrameInitOrResult, FrameOrResult, FrameResult, Handler, ItemOrResult};
4use interpreter::{
5 instructions::InstructionTable,
6 interpreter_types::{Jumps, LoopControl},
7 FrameInput, Host, InitialAndFloorGas, InstructionContext, InstructionResult, Interpreter,
8 InterpreterAction, InterpreterTypes,
9};
10
11use std::{vec, vec::Vec};
12
13pub trait InspectorHandler: Handler
30where
31 Self::Evm:
32 InspectorEvmTr<Inspector: Inspector<<<Self as Handler>::Evm as EvmTr>::Context, Self::IT>>,
33 Self::Frame: InspectorFrame<IT = Self::IT>,
34{
35 type IT: InterpreterTypes;
36
37 fn inspect_run(
41 &mut self,
42 evm: &mut Self::Evm,
43 ) -> Result<ExecutionResult<Self::HaltReason>, Self::Error> {
44 match self.inspect_run_without_catch_error(evm) {
45 Ok(output) => Ok(output),
46 Err(e) => self.catch_error(evm, e),
47 }
48 }
49
50 fn inspect_run_without_catch_error(
54 &mut self,
55 evm: &mut Self::Evm,
56 ) -> Result<ExecutionResult<Self::HaltReason>, Self::Error> {
57 let init_and_floor_gas = self.validate(evm)?;
58 let eip7702_refund = self.pre_execution(evm)? as i64;
59 let mut frame_result = self.inspect_execution(evm, &init_and_floor_gas)?;
60 self.post_execution(evm, &mut frame_result, init_and_floor_gas, eip7702_refund)?;
61 self.execution_result(evm, frame_result)
62 }
63
64 fn inspect_execution(
68 &mut self,
69 evm: &mut Self::Evm,
70 init_and_floor_gas: &InitialAndFloorGas,
71 ) -> Result<FrameResult, Self::Error> {
72 let gas_limit = evm.ctx().tx().gas_limit() - init_and_floor_gas.initial_gas;
73
74 let first_frame_input = self.first_frame_input(evm, gas_limit)?;
76 let first_frame = self.inspect_first_frame_init(evm, first_frame_input)?;
77
78 let mut frame_result = match first_frame {
79 ItemOrResult::Item(frame) => self.inspect_run_exec_loop(evm, frame)?,
80 ItemOrResult::Result(result) => result,
81 };
82
83 self.last_frame_result(evm, &mut frame_result)?;
84 Ok(frame_result)
85 }
86
87 fn inspect_first_frame_init(
98 &mut self,
99 evm: &mut Self::Evm,
100 mut frame_input: <Self::Frame as Frame>::FrameInit,
101 ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
102 let (ctx, inspector) = evm.ctx_inspector();
103 if let Some(mut output) = frame_start(ctx, inspector, &mut frame_input) {
104 frame_end(ctx, inspector, &frame_input, &mut output);
105 return Ok(ItemOrResult::Result(output));
106 }
107 let mut ret = self.first_frame_init(evm, frame_input.clone());
108
109 if let Ok(ItemOrResult::Item(frame)) = &mut ret {
111 let (context, inspector) = evm.ctx_inspector();
112 inspector.initialize_interp(frame.interpreter(), context);
113 } else if let Ok(ItemOrResult::Result(result)) = &mut ret {
114 let (context, inspector) = evm.ctx_inspector();
115 frame_end(context, inspector, &frame_input, result);
116 }
117 ret
118 }
119
120 #[inline]
127 fn inspect_frame_call(
128 &mut self,
129 frame: &mut Self::Frame,
130 evm: &mut Self::Evm,
131 ) -> Result<FrameInitOrResult<Self::Frame>, Self::Error> {
132 frame.run_inspect(evm)
133 }
134
135 fn inspect_run_exec_loop(
145 &mut self,
146 evm: &mut Self::Evm,
147 frame: Self::Frame,
148 ) -> Result<FrameResult, Self::Error> {
149 let mut frame_stack: Vec<Self::Frame> = vec![frame];
150 loop {
151 let frame = frame_stack.last_mut().unwrap();
152 let call_or_result = self.inspect_frame_call(frame, evm)?;
153
154 let result = match call_or_result {
155 ItemOrResult::Item(mut init) => {
156 let (context, inspector) = evm.ctx_inspector();
157 if let Some(mut output) = frame_start(context, inspector, &mut init) {
158 frame_end(context, inspector, &init, &mut output);
159 output
160 } else {
161 match self.frame_init(frame, evm, init.clone())? {
162 ItemOrResult::Item(mut new_frame) => {
163 let (context, inspector) = evm.ctx_inspector();
165 inspector.initialize_interp(new_frame.interpreter(), context);
166 frame_stack.push(new_frame);
167 continue;
168 }
169 ItemOrResult::Result(mut result) => {
171 let (context, inspector) = evm.ctx_inspector();
172 frame_end(context, inspector, &init, &mut result);
173 result
174 }
175 }
176 }
177 }
178 ItemOrResult::Result(mut result) => {
179 let (context, inspector) = evm.ctx_inspector();
180 frame_end(context, inspector, frame.frame_input(), &mut result);
181
182 frame_stack.pop();
184 result
185 }
186 };
187
188 let Some(frame) = frame_stack.last_mut() else {
189 return Ok(result);
190 };
191
192 self.frame_return_result(frame, evm, result)?;
193 }
194 }
195}
196
197pub fn frame_start<CTX, INTR: InterpreterTypes>(
198 context: &mut CTX,
199 inspector: &mut impl Inspector<CTX, INTR>,
200 frame_input: &mut FrameInput,
201) -> Option<FrameResult> {
202 match frame_input {
203 FrameInput::Call(i) => {
204 if let Some(output) = inspector.call(context, i) {
205 return Some(FrameResult::Call(output));
206 }
207 }
208 FrameInput::Create(i) => {
209 if let Some(output) = inspector.create(context, i) {
210 return Some(FrameResult::Create(output));
211 }
212 }
213 FrameInput::EOFCreate(i) => {
214 if let Some(output) = inspector.eofcreate(context, i) {
215 return Some(FrameResult::EOFCreate(output));
216 }
217 }
218 }
219 None
220}
221
222pub fn frame_end<CTX, INTR: InterpreterTypes>(
223 context: &mut CTX,
224 inspector: &mut impl Inspector<CTX, INTR>,
225 frame_input: &FrameInput,
226 frame_output: &mut FrameResult,
227) {
228 match frame_output {
229 FrameResult::Call(outcome) => {
230 let FrameInput::Call(i) = frame_input else {
231 panic!("FrameInput::Call expected");
232 };
233 inspector.call_end(context, i, outcome);
234 }
235 FrameResult::Create(outcome) => {
236 let FrameInput::Create(i) = frame_input else {
237 panic!("FrameInput::Create expected");
238 };
239 inspector.create_end(context, i, outcome);
240 }
241 FrameResult::EOFCreate(outcome) => {
242 let FrameInput::EOFCreate(i) = frame_input else {
243 panic!("FrameInput::EofCreate expected");
244 };
245 inspector.eofcreate_end(context, i, outcome);
246 }
247 }
248}
249
250pub fn inspect_instructions<CTX, IT>(
256 context: &mut CTX,
257 interpreter: &mut Interpreter<IT>,
258 mut inspector: impl Inspector<CTX, IT>,
259 instructions: &InstructionTable<IT, CTX>,
260) -> InterpreterAction
261where
262 CTX: ContextTr<Journal: JournalExt> + Host,
263 IT: InterpreterTypes,
264{
265 let mut log_num = context.journal_mut().logs().len();
266 while interpreter.bytecode.is_not_end() {
268 let opcode = interpreter.bytecode.opcode();
270
271 inspector.step(interpreter, context);
273 if interpreter.bytecode.is_end() {
274 break;
275 }
276
277 interpreter.bytecode.relative_jump(1);
281
282 let instruction_context = InstructionContext {
284 interpreter,
285 host: context,
286 };
287 instructions[opcode as usize](instruction_context);
288
289 let new_log = context.journal_mut().logs().len();
291 if log_num < new_log {
292 let log = context.journal_mut().logs().last().unwrap().clone();
294 inspector.log(interpreter, context, log);
295 log_num = new_log;
296 }
297
298 inspector.step_end(interpreter, context);
300 }
301
302 interpreter.bytecode.revert_to_previous_pointer();
303
304 let next_action = interpreter.take_next_action();
305
306 if let InterpreterAction::Return(result) = &next_action {
308 if result.result == InstructionResult::SelfDestruct {
309 match context.journal_mut().journal().last() {
310 Some(JournalEntry::AccountDestroyed {
311 address,
312 target,
313 had_balance,
314 ..
315 }) => {
316 inspector.selfdestruct(*address, *target, *had_balance);
317 }
318 Some(JournalEntry::BalanceTransfer {
319 from, to, balance, ..
320 }) => {
321 inspector.selfdestruct(*from, *to, *balance);
322 }
323 _ => {}
324 }
325 }
326 }
327
328 next_action
329}