revm_inspector/
inspector.rs

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