Skip to main content

revm_inspector/
inspector.rs

1use auto_impl::auto_impl;
2use context::{Database, Journal, JournalEntry};
3use handler::FrameResult;
4use interpreter::{
5    interpreter::EthInterpreter, CallInputs, CallOutcome, CreateInputs, CreateOutcome, FrameInput,
6    Interpreter, InterpreterTypes,
7};
8use primitives::{Address, Log, U256};
9use state::EvmState;
10
11/// EVM hooks into execution.
12///
13/// This trait is used to enabled tracing of the EVM execution.
14///
15/// Object that is implemented this trait is used in `InspectorHandler` to trace the EVM execution.
16/// And API that allow calling the inspector can be found in [`crate::InspectEvm`] and [`crate::InspectCommitEvm`].
17#[auto_impl(&mut, Box)]
18pub trait Inspector<CTX, INTR: InterpreterTypes = EthInterpreter, FI = FrameInput, FR = FrameResult>
19{
20    /// Called before the interpreter is initialized.
21    ///
22    /// If `interp.bytecode.set_action` is set the execution of the interpreter is skipped.
23    #[inline]
24    fn initialize_interp(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
25        let _ = interp;
26        let _ = context;
27    }
28
29    /// Called on each step of the interpreter.
30    ///
31    /// Information about the current execution, including the memory, stack and more is available
32    /// on `interp` (see [Interpreter]).
33    ///
34    /// # Example
35    ///
36    /// To get the current opcode, use `interp.bytecode.opcode()`.
37    #[inline]
38    fn step(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
39        let _ = interp;
40        let _ = context;
41    }
42
43    /// Called after `step` when the instruction has been executed.
44    ///
45    /// Setting `interp.bytecode.set_action` will result in stopping the execution of the interpreter.
46    #[inline]
47    fn step_end(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
48        let _ = interp;
49        let _ = context;
50    }
51
52    /// Called when a log is emitted, called on every new log.
53    /// If there is a needs for Interpreter context, use [`Inspector::log_full`] instead.
54    #[inline]
55    fn log(&mut self, context: &mut CTX, log: Log) {
56        let _ = context;
57        let _ = log;
58    }
59
60    /// Called when a log is emitted with the interpreter context.
61    ///
62    /// This will not happen only if custom precompiles where logs will be
63    /// gethered after precompile call.
64    fn log_full(&mut self, interpreter: &mut Interpreter<INTR>, context: &mut CTX, log: Log) {
65        let _ = interpreter;
66        self.log(context, log);
67    }
68
69    /// Called before call/create dispatch. Called with a mutable reference to
70    /// the frame input, allowing mutations of the input before the variant-specific
71    /// hooks (`call`/`create`) are called.
72    ///
73    /// Returning `Some(FrameResult)` will skip execution of the frame entirely,
74    /// and also skips calling `call()`/`create()`. `frame_end` will still be called.
75    #[inline]
76    fn frame_start(&mut self, context: &mut CTX, frame_input: &mut FI) -> Option<FR> {
77        let _ = context;
78        let _ = frame_input;
79        None
80    }
81
82    /// Called after `call_end()`/`create_end()` variant-specific hooks complete.
83    ///
84    /// Allows transformation of the final result regardless of frame kind.
85    #[inline]
86    fn frame_end(&mut self, context: &mut CTX, frame_input: &FI, frame_result: &mut FR) {
87        let _ = context;
88        let _ = frame_input;
89        let _ = frame_result;
90    }
91
92    /// Called whenever a call to a contract is about to start.
93    ///
94    /// Returning `CallOutcome` will override the result of the call.
95    #[inline]
96    fn call(&mut self, context: &mut CTX, inputs: &mut CallInputs) -> Option<CallOutcome> {
97        let _ = context;
98        let _ = inputs;
99        None
100    }
101
102    /// Called when a call to a contract has concluded.
103    ///
104    /// The returned [CallOutcome] is used as the result of the call.
105    ///
106    /// This allows the inspector to modify the given `result` before returning it.
107    #[inline]
108    fn call_end(&mut self, context: &mut CTX, inputs: &CallInputs, outcome: &mut CallOutcome) {
109        let _ = context;
110        let _ = inputs;
111        let _ = outcome;
112    }
113
114    /// Called when a contract is about to be created.
115    ///
116    /// If this returns `Some` then the [CreateOutcome] is used to override the result of the creation.
117    ///
118    /// If this returns `None` then the creation proceeds as normal.
119    #[inline]
120    fn create(&mut self, context: &mut CTX, inputs: &mut CreateInputs) -> Option<CreateOutcome> {
121        let _ = context;
122        let _ = inputs;
123        None
124    }
125
126    /// Called when a contract has been created.
127    ///
128    /// Modifying the outcome will alter the result of the create operation.
129    #[inline]
130    fn create_end(
131        &mut self,
132        context: &mut CTX,
133        inputs: &CreateInputs,
134        outcome: &mut CreateOutcome,
135    ) {
136        let _ = context;
137        let _ = inputs;
138        let _ = outcome;
139    }
140
141    /// Called when a contract has been self-destructed with funds transferred to target.
142    #[inline]
143    fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {
144        let _ = contract;
145        let _ = target;
146        let _ = value;
147    }
148}
149
150impl<CTX, INTR: InterpreterTypes, FI, FR, L, R> Inspector<CTX, INTR, FI, FR> for (L, R)
151where
152    L: Inspector<CTX, INTR, FI, FR>,
153    R: Inspector<CTX, INTR, FI, FR>,
154{
155    fn initialize_interp(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
156        self.0.initialize_interp(interp, context);
157        self.1.initialize_interp(interp, context);
158    }
159
160    fn step(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
161        self.0.step(interp, context);
162        self.1.step(interp, context);
163    }
164
165    fn step_end(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
166        self.0.step_end(interp, context);
167        self.1.step_end(interp, context);
168    }
169
170    fn log(&mut self, context: &mut CTX, log: Log) {
171        self.0.log(context, log.clone());
172        self.1.log(context, log);
173    }
174
175    fn log_full(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX, log: Log) {
176        self.0.log_full(interp, context, log.clone());
177        self.1.log_full(interp, context, log);
178    }
179
180    fn frame_start(&mut self, context: &mut CTX, frame_input: &mut FI) -> Option<FR> {
181        let first = self.0.frame_start(context, frame_input);
182        let second = self.1.frame_start(context, frame_input);
183        first.or(second)
184    }
185
186    fn frame_end(&mut self, context: &mut CTX, frame_input: &FI, frame_result: &mut FR) {
187        self.0.frame_end(context, frame_input, frame_result);
188        self.1.frame_end(context, frame_input, frame_result);
189    }
190
191    fn call(&mut self, context: &mut CTX, inputs: &mut CallInputs) -> Option<CallOutcome> {
192        let first = self.0.call(context, inputs);
193        let second = self.1.call(context, inputs);
194        first.or(second)
195    }
196
197    fn call_end(&mut self, context: &mut CTX, inputs: &CallInputs, outcome: &mut CallOutcome) {
198        self.0.call_end(context, inputs, outcome);
199        self.1.call_end(context, inputs, outcome);
200    }
201
202    fn create(&mut self, context: &mut CTX, inputs: &mut CreateInputs) -> Option<CreateOutcome> {
203        let first = self.0.create(context, inputs);
204        let second = self.1.create(context, inputs);
205        first.or(second)
206    }
207
208    fn create_end(
209        &mut self,
210        context: &mut CTX,
211        inputs: &CreateInputs,
212        outcome: &mut CreateOutcome,
213    ) {
214        self.0.create_end(context, inputs, outcome);
215        self.1.create_end(context, inputs, outcome);
216    }
217
218    fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {
219        self.0.selfdestruct(contract, target, value);
220        self.1.selfdestruct(contract, target, value);
221    }
222}
223
224/// Extends the journal with additional methods that are used by the inspector.
225#[auto_impl(&mut, Box)]
226pub trait JournalExt {
227    /// Get the journal entries that are created from last checkpoint.
228    /// new checkpoint is created when sub call is made.
229    fn journal(&self) -> &[JournalEntry];
230
231    /// Return the current Journaled state.
232    fn evm_state(&self) -> &EvmState;
233
234    /// Return the mutable current Journaled state.
235    fn evm_state_mut(&mut self) -> &mut EvmState;
236}
237
238impl<DB: Database> JournalExt for Journal<DB> {
239    #[inline]
240    fn journal(&self) -> &[JournalEntry] {
241        &self.journal
242    }
243
244    #[inline]
245    fn evm_state(&self) -> &EvmState {
246        &self.state
247    }
248
249    #[inline]
250    fn evm_state_mut(&mut self) -> &mut EvmState {
251        &mut self.state
252    }
253}