1use crate::{InspectorEvmTr, InspectorFrame};
2use auto_impl::auto_impl;
3use context::{
4 result::ResultAndState, Cfg, ContextTr, Database, JournalEntry, JournaledState, Transaction,
5};
6use handler::{
7 execution, EvmTr, Frame, FrameInitOrResult, FrameOrResult, FrameResult, Handler, ItemOrResult,
8};
9use interpreter::{
10 interpreter::EthInterpreter,
11 interpreter_types::{Jumps, LoopControl},
12 table::InstructionTable,
13 CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, FrameInput, Host,
14 InitialAndFloorGas, InstructionResult, Interpreter, InterpreterAction, InterpreterTypes,
15};
16use primitives::{Address, Log, U256};
17use state::EvmState;
18use std::{vec, vec::Vec};
19
20#[auto_impl(&mut, Box)]
22pub trait Inspector<CTX, INTR: InterpreterTypes = EthInterpreter> {
23 #[inline]
28 fn initialize_interp(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
29 let _ = interp;
30 let _ = context;
31 }
32
33 #[inline]
42 fn step(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
43 let _ = interp;
44 let _ = context;
45 }
46
47 #[inline]
52 fn step_end(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
53 let _ = interp;
54 let _ = context;
55 }
56
57 #[inline]
59 fn log(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX, log: Log) {
60 let _ = interp;
61 let _ = context;
62 let _ = log;
63 }
64
65 #[inline]
69 fn call(&mut self, context: &mut CTX, inputs: &mut CallInputs) -> Option<CallOutcome> {
70 let _ = context;
71 let _ = inputs;
72 None
73 }
74
75 #[inline]
81 fn call_end(&mut self, context: &mut CTX, inputs: &CallInputs, outcome: &mut CallOutcome) {
82 let _ = context;
83 let _ = inputs;
84 let _ = outcome;
85 }
86
87 #[inline]
93 fn create(&mut self, context: &mut CTX, inputs: &mut CreateInputs) -> Option<CreateOutcome> {
94 let _ = context;
95 let _ = inputs;
96 None
97 }
98
99 #[inline]
104 fn create_end(
105 &mut self,
106 context: &mut CTX,
107 inputs: &CreateInputs,
108 outcome: &mut CreateOutcome,
109 ) {
110 let _ = context;
111 let _ = inputs;
112 let _ = outcome;
113 }
114
115 fn eofcreate(
119 &mut self,
120 context: &mut CTX,
121 inputs: &mut EOFCreateInputs,
122 ) -> Option<CreateOutcome> {
123 let _ = context;
124 let _ = inputs;
125 None
126 }
127
128 fn eofcreate_end(
130 &mut self,
131 context: &mut CTX,
132 inputs: &EOFCreateInputs,
133 outcome: &mut CreateOutcome,
134 ) {
135 let _ = context;
136 let _ = inputs;
137 let _ = outcome;
138 }
139
140 #[inline]
142 fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {
143 let _ = contract;
144 let _ = target;
145 let _ = value;
146 }
147}
148
149#[auto_impl(&mut, Box)]
150pub trait JournalExt {
151 fn logs(&self) -> &[Log];
152
153 fn last_journal(&self) -> &[JournalEntry];
154
155 fn evm_state(&self) -> &EvmState;
156
157 fn evm_state_mut(&mut self) -> &mut EvmState;
158}
159
160impl<DB: Database> JournalExt for JournaledState<DB> {
161 #[inline]
162 fn logs(&self) -> &[Log] {
163 &self.logs
164 }
165
166 #[inline]
167 fn last_journal(&self) -> &[JournalEntry] {
168 self.journal.last().expect("Journal is never empty")
169 }
170
171 #[inline]
172 fn evm_state(&self) -> &EvmState {
173 &self.state
174 }
175
176 #[inline]
177 fn evm_state_mut(&mut self) -> &mut EvmState {
178 &mut self.state
179 }
180}
181
182pub trait InspectorHandler: Handler
183where
184 Self::Evm:
185 InspectorEvmTr<Inspector: Inspector<<<Self as Handler>::Evm as EvmTr>::Context, Self::IT>>,
186 Self::Frame: InspectorFrame<IT = Self::IT>,
187{
188 type IT: InterpreterTypes;
189
190 fn inspect_run(
191 &mut self,
192 evm: &mut Self::Evm,
193 ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
194 let init_and_floor_gas = self.validate(evm)?;
195 let eip7702_refund = self.pre_execution(evm)? as i64;
196 let exec_result = self.inspect_execution(evm, &init_and_floor_gas);
197 self.post_execution(evm, exec_result?, init_and_floor_gas, eip7702_refund)
198 }
199
200 fn inspect_execution(
201 &mut self,
202 evm: &mut Self::Evm,
203 init_and_floor_gas: &InitialAndFloorGas,
204 ) -> Result<FrameResult, Self::Error> {
205 let gas_limit = evm.ctx().tx().gas_limit() - init_and_floor_gas.initial_gas;
206
207 let first_frame = self.inspect_create_first_frame(evm, gas_limit)?;
209 let mut frame_result = match first_frame {
210 ItemOrResult::Item(frame) => self.inspect_run_exec_loop(evm, frame)?,
211 ItemOrResult::Result(result) => result,
212 };
213
214 self.last_frame_result(evm, &mut frame_result)?;
215 Ok(frame_result)
216 }
217
218 fn inspect_create_first_frame(
220 &mut self,
221 evm: &mut Self::Evm,
222 gas_limit: u64,
223 ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
224 let ctx = evm.ctx_ref();
225 let init_frame = execution::create_init_frame(ctx.tx(), ctx.cfg().spec().into(), gas_limit);
226 self.inspect_frame_init_first(evm, init_frame)
227 }
228
229 fn inspect_frame_init_first(
232 &mut self,
233 evm: &mut Self::Evm,
234 mut frame_input: <Self::Frame as Frame>::FrameInit,
235 ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
236 let (ctx, inspector) = evm.ctx_inspector();
237 if let Some(output) = frame_start(ctx, inspector, &mut frame_input) {
238 return Ok(ItemOrResult::Result(output));
239 }
240 let mut ret = self.frame_init_first(evm, frame_input.clone());
241
242 if let Ok(ItemOrResult::Item(frame)) = &mut ret {
244 let (context, inspector) = evm.ctx_inspector();
245 inspector.initialize_interp(frame.interpreter(), context);
246 } else if let Ok(ItemOrResult::Result(result)) = &mut ret {
247 let (context, inspector) = evm.ctx_inspector();
248 frame_end(context, inspector, &frame_input, result);
249 }
250 ret
251 }
252
253 #[inline]
254 fn inspect_frame_call(
255 &mut self,
256 frame: &mut Self::Frame,
257 evm: &mut Self::Evm,
258 ) -> Result<FrameInitOrResult<Self::Frame>, Self::Error> {
259 frame.run_inspect(evm)
260 }
261
262 fn inspect_run_exec_loop(
263 &mut self,
264 evm: &mut Self::Evm,
265 frame: Self::Frame,
266 ) -> Result<FrameResult, Self::Error> {
267 let mut frame_stack: Vec<Self::Frame> = vec![frame];
268 loop {
269 let frame = frame_stack.last_mut().unwrap();
270 let call_or_result = self.inspect_frame_call(frame, evm)?;
271
272 let result = match call_or_result {
273 ItemOrResult::Item(mut init) => {
274 let (context, inspector) = evm.ctx_inspector();
275 if let Some(output) = frame_start(context, inspector, &mut init) {
276 output
277 } else {
278 match self.frame_init(frame, evm, init.clone())? {
279 ItemOrResult::Item(mut new_frame) => {
280 let (context, inspector) = evm.ctx_inspector();
282 inspector.initialize_interp(new_frame.interpreter(), context);
283 frame_stack.push(new_frame);
284 continue;
285 }
286 ItemOrResult::Result(mut result) => {
288 let (context, inspector) = evm.ctx_inspector();
289 frame_end(context, inspector, &init, &mut result);
290 result
291 }
292 }
293 }
294 }
295 ItemOrResult::Result(mut result) => {
296 let (context, inspector) = evm.ctx_inspector();
297 frame_end(context, inspector, frame.frame_input(), &mut result);
298
299 frame_stack.pop();
301 result
302 }
303 };
304
305 let Some(frame) = frame_stack.last_mut() else {
306 return Ok(result);
307 };
308
309 self.frame_return_result(frame, evm, result)?;
310 }
311 }
312}
313
314fn frame_start<CTX, INTR: InterpreterTypes>(
315 context: &mut CTX,
316 inspector: &mut impl Inspector<CTX, INTR>,
317 frame_input: &mut FrameInput,
318) -> Option<FrameResult> {
319 match frame_input {
320 FrameInput::Call(i) => {
321 if let Some(output) = inspector.call(context, i) {
322 return Some(FrameResult::Call(output));
323 }
324 }
325 FrameInput::Create(i) => {
326 if let Some(output) = inspector.create(context, i) {
327 return Some(FrameResult::Create(output));
328 }
329 }
330 FrameInput::EOFCreate(i) => {
331 if let Some(output) = inspector.eofcreate(context, i) {
332 return Some(FrameResult::EOFCreate(output));
333 }
334 }
335 }
336 None
337}
338
339fn frame_end<CTX, INTR: InterpreterTypes>(
340 context: &mut CTX,
341 inspector: &mut impl Inspector<CTX, INTR>,
342 frame_input: &FrameInput,
343 frame_output: &mut FrameResult,
344) {
345 match frame_output {
346 FrameResult::Call(outcome) => {
347 let FrameInput::Call(i) = frame_input else {
348 panic!("FrameInput::Call expected");
349 };
350 inspector.call_end(context, i, outcome);
351 }
352 FrameResult::Create(outcome) => {
353 let FrameInput::Create(i) = frame_input else {
354 panic!("FrameInput::Create expected");
355 };
356 inspector.create_end(context, i, outcome);
357 }
358 FrameResult::EOFCreate(outcome) => {
359 let FrameInput::EOFCreate(i) = frame_input else {
360 panic!("FrameInput::EofCreate expected");
361 };
362 inspector.eofcreate_end(context, i, outcome);
363 }
364 }
365}
366
367pub fn inspect_instructions<CTX, IT>(
368 context: &mut CTX,
369 interpreter: &mut Interpreter<IT>,
370 mut inspector: impl Inspector<CTX, IT>,
371 instructions: &InstructionTable<IT, CTX>,
372) -> InterpreterAction
373where
374 CTX: ContextTr<Journal: JournalExt> + Host,
375 IT: InterpreterTypes,
376{
377 interpreter.reset_control();
378
379 let mut log_num = context.journal().logs().len();
380 while interpreter.control.instruction_result().is_continue() {
382 let opcode = interpreter.bytecode.opcode();
384
385 inspector.step(interpreter, context);
387 if interpreter.control.instruction_result() != InstructionResult::Continue {
388 break;
389 }
390
391 interpreter.bytecode.relative_jump(1);
395
396 instructions[opcode as usize](interpreter, context);
398
399 let new_log = context.journal().logs().len();
401 if log_num < new_log {
402 let log = context.journal().logs().last().unwrap().clone();
404 inspector.log(interpreter, context, log);
405 log_num = new_log;
406 }
407
408 inspector.step_end(interpreter, context);
410 }
411
412 let next_action = interpreter.take_next_action();
413
414 if let InterpreterAction::Return { result } = &next_action {
416 if result.result == InstructionResult::SelfDestruct {
417 match context.journal().last_journal().last() {
418 Some(JournalEntry::AccountDestroyed {
419 address,
420 target,
421 had_balance,
422 ..
423 }) => {
424 inspector.selfdestruct(*address, *target, *had_balance);
425 }
426 Some(JournalEntry::BalanceTransfer {
427 from, to, balance, ..
428 }) => {
429 inspector.selfdestruct(*from, *to, *balance);
430 }
431 _ => {}
432 }
433 }
434 }
435
436 next_action
437}