revm_inspector/
traits.rs

1use context::{ContextTr, FrameStack};
2use handler::{
3    evm::{ContextDbError, FrameInitResult, FrameTr},
4    instructions::InstructionProvider,
5    EthFrame, EvmTr, FrameInitOrResult, FrameResult, ItemOrResult,
6};
7use interpreter::{interpreter::EthInterpreter, interpreter_action::FrameInit, 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: InspectorFrame<IT = 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 tuple of mutable references to the context, the inspector, the frame and the instructions.
30    ///
31    /// This is one of two functions that need to be implemented for Evm. Second one is `all_mut`.
32    #[allow(clippy::type_complexity)]
33    fn all_inspector(
34        &self,
35    ) -> (
36        &Self::Context,
37        &Self::Instructions,
38        &Self::Precompiles,
39        &FrameStack<Self::Frame>,
40        &Self::Inspector,
41    );
42
43    /// Returns a tuple of mutable references to the context, the inspector, the frame and the instructions.
44    ///
45    /// This is one of two functions that need to be implemented for Evm. Second one is `all`.
46    #[allow(clippy::type_complexity)]
47    fn all_mut_inspector(
48        &mut self,
49    ) -> (
50        &mut Self::Context,
51        &mut Self::Instructions,
52        &mut Self::Precompiles,
53        &mut FrameStack<Self::Frame>,
54        &mut Self::Inspector,
55    );
56
57    /// Returns a mutable reference to the inspector.
58    fn inspector(&mut self) -> &mut Self::Inspector {
59        let (_, _, _, _, inspector) = self.all_mut_inspector();
60        inspector
61    }
62
63    /// Returns a tuple of mutable references to the context and the inspector.
64    ///
65    /// Useful when you want to allow inspector to modify the context.
66    fn ctx_inspector(&mut self) -> (&mut Self::Context, &mut Self::Inspector) {
67        let (ctx, _, _, _, inspector) = self.all_mut_inspector();
68        (ctx, inspector)
69    }
70
71    /// Returns a tuple of mutable references to the context, the inspector and the frame.
72    ///
73    /// Useful when you want to allow inspector to modify the context and the frame.
74    fn ctx_inspector_frame(
75        &mut self,
76    ) -> (&mut Self::Context, &mut Self::Inspector, &mut Self::Frame) {
77        let (ctx, _, _, frame, inspector) = self.all_mut_inspector();
78        (ctx, inspector, frame.get())
79    }
80
81    /// Returns a tuple of mutable references to the context, the inspector, the frame and the instructions.
82    fn ctx_inspector_frame_instructions(
83        &mut self,
84    ) -> (
85        &mut Self::Context,
86        &mut Self::Inspector,
87        &mut Self::Frame,
88        &mut Self::Instructions,
89    ) {
90        let (ctx, instructions, _, frame, inspector) = self.all_mut_inspector();
91        (ctx, inspector, frame.get(), instructions)
92    }
93
94    /// Initializes the frame for the given frame input. Frame is pushed to the frame stack.
95    #[inline]
96    fn inspect_frame_init(
97        &mut self,
98        mut frame_init: <Self::Frame as FrameTr>::FrameInit,
99    ) -> Result<FrameInitResult<'_, Self::Frame>, ContextDbError<Self::Context>> {
100        let (ctx, inspector) = self.ctx_inspector();
101        if let Some(mut output) = frame_start(ctx, inspector, &mut frame_init.frame_input) {
102            frame_end(ctx, inspector, &frame_init.frame_input, &mut output);
103            return Ok(ItemOrResult::Result(output));
104        }
105
106        let frame_input = frame_init.frame_input.clone();
107        if let ItemOrResult::Result(mut output) = self.frame_init(frame_init)? {
108            let (ctx, inspector) = self.ctx_inspector();
109            frame_end(ctx, inspector, &frame_input, &mut output);
110            return Ok(ItemOrResult::Result(output));
111        }
112
113        // if it is new frame, initialize the interpreter.
114        let (ctx, inspector, frame) = self.ctx_inspector_frame();
115        if let Some(frame) = frame.eth_frame() {
116            let interp = &mut frame.interpreter;
117            inspector.initialize_interp(interp, ctx);
118        };
119        Ok(ItemOrResult::Item(frame))
120    }
121
122    /// Run the frame from the top of the stack. Returns the frame init or result.
123    ///
124    /// If frame has returned result it would mark it as finished.
125    #[inline]
126    fn inspect_frame_run(
127        &mut self,
128    ) -> Result<FrameInitOrResult<Self::Frame>, ContextDbError<Self::Context>> {
129        let (ctx, inspector, frame, instructions) = self.ctx_inspector_frame_instructions();
130
131        let Some(frame) = frame.eth_frame() else {
132            return self.frame_run();
133        };
134
135        let next_action = inspect_instructions(
136            ctx,
137            &mut frame.interpreter,
138            inspector,
139            instructions.instruction_table(),
140        );
141        let mut result = frame.process_next_action(ctx, next_action);
142
143        if let Ok(ItemOrResult::Result(frame_result)) = &mut result {
144            let (ctx, inspector, frame) = self.ctx_inspector_frame();
145            // TODO When all_mut fn is added we can fetch inspector at the top of the function.s
146            if let Some(frame) = frame.eth_frame() {
147                frame_end(ctx, inspector, &frame.input, frame_result);
148                frame.set_finished(true);
149            }
150        };
151        result
152    }
153}
154
155/// Trait that extends the [`FrameTr`] trait with additional functionality that is needed for inspection.
156pub trait InspectorFrame: FrameTr<FrameResult = FrameResult, FrameInit = FrameInit> {
157    /// The interpreter types used by this frame.
158    type IT: InterpreterTypes;
159
160    /// Returns a mutable reference to the EthFrame.
161    ///
162    /// If this frame does not have support for tracing (does not contain
163    /// the EthFrame) Inspector calls for this frame will be skipped.
164    fn eth_frame(&mut self) -> Option<&mut EthFrame<EthInterpreter>>;
165}
166
167/// Impl InspectorFrame for EthFrame.
168impl InspectorFrame for EthFrame<EthInterpreter> {
169    type IT = EthInterpreter;
170
171    fn eth_frame(&mut self) -> Option<&mut EthFrame<EthInterpreter>> {
172        Some(self)
173    }
174}