revm_inspector/
traits.rs

1use context::ContextTr;
2use handler::{
3    evm::{ContextDbError, FrameInitResult, FrameTr},
4    instructions::InstructionProvider,
5    EthFrame, EvmTr, FrameInitOrResult, ItemOrResult,
6};
7use interpreter::{interpreter::EthInterpreter, FrameInput, Interpreter, InterpreterTypes};
8
9use crate::{
10    handler::{frame_end, frame_start},
11    inspect_instructions, Inspector, JournalExt,
12};
13
14/// Inspector EVM trait. Extends the [`EvmTr`] trait with inspector related methods.
15///
16/// It contains execution of interpreter with [`crate::Inspector`] calls [`crate::Inspector::step`] and [`crate::Inspector::step_end`] calls.
17///
18/// It is used inside [`crate::InspectorHandler`] to extend evm with support for inspection.
19pub trait InspectorEvmTr:
20    EvmTr<
21    Frame = EthFrame<EthInterpreter>,
22    Instructions: InstructionProvider<InterpreterTypes = EthInterpreter, Context = Self::Context>,
23    Context: ContextTr<Journal: JournalExt>,
24>
25{
26    /// The inspector type used for EVM execution inspection.
27    type Inspector: Inspector<Self::Context, EthInterpreter>;
28
29    /// Returns a mutable reference to the inspector.
30    fn inspector(&mut self) -> &mut Self::Inspector;
31
32    /// Returns a tuple of mutable references to the context and the inspector.
33    ///
34    /// Useful when you want to allow inspector to modify the context.
35    fn ctx_inspector(&mut self) -> (&mut Self::Context, &mut Self::Inspector);
36
37    /// Returns a tuple of mutable references to the context, the inspector and the frame.
38    ///
39    /// Useful when you want to allow inspector to modify the context and the frame.
40    fn ctx_inspector_frame(
41        &mut self,
42    ) -> (&mut Self::Context, &mut Self::Inspector, &mut Self::Frame);
43
44    /// Returns a tuple of mutable references to the context, the inspector, the frame and the instructions.
45    fn ctx_inspector_frame_instructions(
46        &mut self,
47    ) -> (
48        &mut Self::Context,
49        &mut Self::Inspector,
50        &mut Self::Frame,
51        &mut Self::Instructions,
52    );
53
54    /// Initializes the frame for the given frame input. Frame is pushed to the frame stack.
55    #[inline]
56    fn inspect_frame_init(
57        &mut self,
58        mut frame_init: <Self::Frame as FrameTr>::FrameInit,
59    ) -> Result<FrameInitResult<'_, Self::Frame>, ContextDbError<Self::Context>> {
60        let (ctx, inspector) = self.ctx_inspector();
61        if let Some(mut output) = frame_start(ctx, inspector, &mut frame_init.frame_input) {
62            frame_end(ctx, inspector, &frame_init.frame_input, &mut output);
63            return Ok(ItemOrResult::Result(output));
64        }
65
66        let frame_input = frame_init.frame_input.clone();
67        if let ItemOrResult::Result(mut output) = self.frame_init(frame_init)? {
68            let (ctx, inspector) = self.ctx_inspector();
69            frame_end(ctx, inspector, &frame_input, &mut output);
70            return Ok(ItemOrResult::Result(output));
71        }
72
73        // if it is new frame, initialize the interpreter.
74        let (ctx, inspector, frame) = self.ctx_inspector_frame();
75        let interp = frame.interpreter();
76        inspector.initialize_interp(interp, ctx);
77        Ok(ItemOrResult::Item(frame))
78    }
79
80    /// Run the frame from the top of the stack. Returns the frame init or result.
81    ///
82    /// If frame has returned result it would mark it as finished.
83    #[inline]
84    fn inspect_frame_run(
85        &mut self,
86    ) -> Result<FrameInitOrResult<Self::Frame>, ContextDbError<Self::Context>> {
87        let (ctx, inspector, frame, instructions) = self.ctx_inspector_frame_instructions();
88
89        let next_action = inspect_instructions(
90            ctx,
91            frame.interpreter(),
92            inspector,
93            instructions.instruction_table(),
94        );
95        let mut result = frame.process_next_action(ctx, next_action);
96
97        if let Ok(ItemOrResult::Result(frame_result)) = &mut result {
98            let (ctx, inspector, frame) = self.ctx_inspector_frame();
99            frame_end(ctx, inspector, frame.frame_input(), frame_result);
100            frame.set_finished(true);
101        };
102        result
103    }
104}
105
106/// Trait that extends the [`FrameTr`] trait with additional functionality that is needed for inspection.
107pub trait InspectorFrame: FrameTr {
108    /// The interpreter types used by this frame.
109    type IT: InterpreterTypes;
110
111    /// Returns a mutable reference to the interpreter.
112    fn interpreter(&mut self) -> &mut Interpreter<Self::IT>;
113
114    /// Returns a reference to the frame input. Frame input is needed for call/create/eofcreate [`crate::Inspector`] methods
115    fn frame_input(&self) -> &FrameInput;
116}
117
118/// Impl InspectorFrame for EthFrame.
119impl InspectorFrame for EthFrame<EthInterpreter> {
120    type IT = EthInterpreter;
121
122    fn interpreter(&mut self) -> &mut Interpreter<Self::IT> {
123        &mut self.interpreter
124    }
125
126    fn frame_input(&self) -> &FrameInput {
127        &self.input
128    }
129}