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.
51    #[inline]
52    fn log(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX, log: Log) {
53        let _ = interp;
54        let _ = context;
55        let _ = log;
56    }
57
58    /// Called whenever a call to a contract is about to start.
59    ///
60    /// Returning `CallOutcome` will override the result of the call.
61    #[inline]
62    fn call(&mut self, context: &mut CTX, inputs: &mut CallInputs) -> Option<CallOutcome> {
63        let _ = context;
64        let _ = inputs;
65        None
66    }
67
68    /// Called when a call to a contract has concluded.
69    ///
70    /// The returned [CallOutcome] is used as the result of the call.
71    ///
72    /// This allows the inspector to modify the given `result` before returning it.
73    #[inline]
74    fn call_end(&mut self, context: &mut CTX, inputs: &CallInputs, outcome: &mut CallOutcome) {
75        let _ = context;
76        let _ = inputs;
77        let _ = outcome;
78    }
79
80    /// Called when a contract is about to be created.
81    ///
82    /// If this returns `Some` then the [CreateOutcome] is used to override the result of the creation.
83    ///
84    /// If this returns `None` then the creation proceeds as normal.
85    #[inline]
86    fn create(&mut self, context: &mut CTX, inputs: &mut CreateInputs) -> Option<CreateOutcome> {
87        let _ = context;
88        let _ = inputs;
89        None
90    }
91
92    /// Called when a contract has been created.
93    ///
94    /// Modifying the outcome will alter the result of the create operation.
95    #[inline]
96    fn create_end(
97        &mut self,
98        context: &mut CTX,
99        inputs: &CreateInputs,
100        outcome: &mut CreateOutcome,
101    ) {
102        let _ = context;
103        let _ = inputs;
104        let _ = outcome;
105    }
106
107    /// Called when a contract has been self-destructed with funds transferred to target.
108    #[inline]
109    fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {
110        let _ = contract;
111        let _ = target;
112        let _ = value;
113    }
114}
115
116impl<CTX, INTR: InterpreterTypes, L, R> Inspector<CTX, INTR> for (L, R)
117where
118    L: Inspector<CTX, INTR>,
119    R: Inspector<CTX, INTR>,
120{
121    fn initialize_interp(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
122        self.0.initialize_interp(interp, context);
123        self.1.initialize_interp(interp, context);
124    }
125
126    fn step(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
127        self.0.step(interp, context);
128        self.1.step(interp, context);
129    }
130
131    fn step_end(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX) {
132        self.0.step_end(interp, context);
133        self.1.step_end(interp, context);
134    }
135
136    fn log(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX, log: Log) {
137        self.0.log(interp, context, log.clone());
138        self.1.log(interp, context, log);
139    }
140
141    fn call(&mut self, context: &mut CTX, inputs: &mut CallInputs) -> Option<CallOutcome> {
142        self.0
143            .call(context, inputs)
144            .or_else(|| self.1.call(context, inputs))
145    }
146
147    fn call_end(&mut self, context: &mut CTX, inputs: &CallInputs, outcome: &mut CallOutcome) {
148        self.0.call_end(context, inputs, outcome);
149        self.1.call_end(context, inputs, outcome);
150    }
151
152    fn create(&mut self, context: &mut CTX, inputs: &mut CreateInputs) -> Option<CreateOutcome> {
153        self.0
154            .create(context, inputs)
155            .or_else(|| self.1.create(context, inputs))
156    }
157
158    fn create_end(
159        &mut self,
160        context: &mut CTX,
161        inputs: &CreateInputs,
162        outcome: &mut CreateOutcome,
163    ) {
164        self.0.create_end(context, inputs, outcome);
165        self.1.create_end(context, inputs, outcome);
166    }
167
168    fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {
169        self.0.selfdestruct(contract, target, value);
170        self.1.selfdestruct(contract, target, value);
171    }
172}
173
174/// Extends the journal with additional methods that are used by the inspector.
175#[auto_impl(&mut, Box)]
176pub trait JournalExt {
177    /// Get all logs from the journal.
178    fn logs(&self) -> &[Log];
179
180    /// Get the journal entries that are created from last checkpoint.
181    /// new checkpoint is created when sub call is made.
182    fn journal(&self) -> &[JournalEntry];
183
184    /// Return the current Journaled state.
185    fn evm_state(&self) -> &EvmState;
186
187    /// Return the mutable current Journaled state.
188    fn evm_state_mut(&mut self) -> &mut EvmState;
189}
190
191impl<DB: Database> JournalExt for Journal<DB> {
192    #[inline]
193    fn logs(&self) -> &[Log] {
194        &self.logs
195    }
196
197    #[inline]
198    fn journal(&self) -> &[JournalEntry] {
199        &self.journal
200    }
201
202    #[inline]
203    fn evm_state(&self) -> &EvmState {
204        &self.state
205    }
206
207    #[inline]
208    fn evm_state_mut(&mut self) -> &mut EvmState {
209        &mut self.state
210    }
211}