revm_inspector/inspect.rs
1use context::result::ExecResultAndState;
2use handler::{system_call::SYSTEM_ADDRESS, ExecuteCommitEvm, ExecuteEvm, SystemCallEvm};
3use primitives::{Address, Bytes};
4
5/// InspectEvm is a API that allows inspecting the EVM.
6///
7/// It extends the `ExecuteEvm` trait and enabled setting inspector
8///
9pub trait InspectEvm: ExecuteEvm {
10 /// The inspector type used for inspecting EVM execution.
11 type Inspector;
12
13 /// Set the inspector for the EVM.
14 ///
15 /// this function is used to change inspector during execution.
16 /// This function can't change Inspector type, changing inspector type can be done in
17 /// `Evm` with `with_inspector` function.
18 fn set_inspector(&mut self, inspector: Self::Inspector);
19
20 /// Inspect the EVM with the given transaction.
21 fn inspect_one_tx(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error>;
22
23 /// Inspect the EVM and finalize the state.
24 ///
25 /// # Outcome of Error
26 ///
27 /// If the transaction fails, the journal is finalized (cleared) so that the
28 /// next transaction starts from a clean state. This mirrors [`ExecuteEvm::transact`].
29 fn inspect_tx(
30 &mut self,
31 tx: Self::Tx,
32 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error> {
33 // finalize the journal unconditionally, even on error, so the
34 // EIP-2929 warm set and state do not leak into the next transaction.
35 let output_or_error = self.inspect_one_tx(tx);
36 let state = self.finalize();
37 let output = output_or_error?;
38 Ok(ExecResultAndState::new(output, state))
39 }
40
41 /// Inspect the EVM with the given inspector and transaction, and finalize the state.
42 ///
43 /// # Outcome of Error
44 ///
45 /// Same as [`InspectEvm::inspect_tx`]: the journal is finalized on error.
46 fn inspect(
47 &mut self,
48 tx: Self::Tx,
49 inspector: Self::Inspector,
50 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error> {
51 let output_or_error = self.inspect_one(tx, inspector);
52 let state = self.finalize();
53 let output = output_or_error?;
54 Ok(ExecResultAndState::new(output, state))
55 }
56
57 /// Inspect the EVM with the given inspector and transaction.
58 fn inspect_one(
59 &mut self,
60 tx: Self::Tx,
61 inspector: Self::Inspector,
62 ) -> Result<Self::ExecutionResult, Self::Error> {
63 self.set_inspector(inspector);
64 self.inspect_one_tx(tx)
65 }
66}
67
68/// InspectCommitEvm is a API that allows inspecting similar to `InspectEvm` but it has
69/// functions that commit the state diff to the database.
70///
71/// Functions return CommitOutput from [`ExecuteCommitEvm`] trait.
72pub trait InspectCommitEvm: InspectEvm + ExecuteCommitEvm {
73 /// Inspect the EVM with the current inspector and previous transaction by replaying, similar to [`InspectEvm::inspect_tx`]
74 /// and commit the state diff to the database.
75 ///
76 /// # Outcome of Error
77 ///
78 /// If the transaction fails, the journal is finalized (not committed) so it
79 /// does not leak into the next transaction.
80 fn inspect_tx_commit(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
81 let output = self.inspect_one_tx(tx).inspect_err(|_| {
82 // finalize (clear) the journal on error; do not commit it.
83 let _ = self.finalize();
84 })?;
85 self.commit_inner();
86 Ok(output)
87 }
88
89 /// Inspect the EVM with the given transaction and inspector similar to [`InspectEvm::inspect`]
90 /// and commit the state diff to the database.
91 ///
92 /// # Outcome of Error
93 ///
94 /// Same as [`InspectCommitEvm::inspect_tx_commit`]: the journal is finalized on error.
95 fn inspect_commit(
96 &mut self,
97 tx: Self::Tx,
98 inspector: Self::Inspector,
99 ) -> Result<Self::ExecutionResult, Self::Error> {
100 let output = self.inspect_one(tx, inspector).inspect_err(|_| {
101 let _ = self.finalize();
102 })?;
103 self.commit_inner();
104 Ok(output)
105 }
106}
107
108/// InspectSystemCallEvm is an API that allows inspecting system calls in the EVM.
109///
110/// It extends [`InspectEvm`] and [`SystemCallEvm`] traits to provide inspection
111/// capabilities for system transactions, enabling tracing and debugging of
112/// system calls similar to regular transactions.
113pub trait InspectSystemCallEvm: InspectEvm + SystemCallEvm {
114 /// Inspect a system call with the current inspector.
115 ///
116 /// Similar to [`InspectEvm::inspect_one_tx`] but for system calls.
117 /// Uses [`SYSTEM_ADDRESS`] as the caller.
118 fn inspect_one_system_call(
119 &mut self,
120 system_contract_address: Address,
121 data: Bytes,
122 ) -> Result<Self::ExecutionResult, Self::Error> {
123 self.inspect_one_system_call_with_caller(SYSTEM_ADDRESS, system_contract_address, data)
124 }
125
126 /// Inspect a system call with the current inspector and a custom caller.
127 ///
128 /// Similar to [`InspectEvm::inspect_one_tx`] but for system calls with a custom caller.
129 fn inspect_one_system_call_with_caller(
130 &mut self,
131 caller: Address,
132 system_contract_address: Address,
133 data: Bytes,
134 ) -> Result<Self::ExecutionResult, Self::Error>;
135
136 /// Inspect a system call and finalize the state.
137 ///
138 /// Similar to [`InspectEvm::inspect_tx`] but for system calls.
139 ///
140 /// # Outcome of Error
141 ///
142 /// Same as [`InspectEvm::inspect_tx`]: the journal is finalized on error.
143 fn inspect_system_call(
144 &mut self,
145 system_contract_address: Address,
146 data: Bytes,
147 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error> {
148 let output_or_error = self.inspect_one_system_call(system_contract_address, data);
149 let state = self.finalize();
150 let output = output_or_error?;
151 Ok(ExecResultAndState::new(output, state))
152 }
153
154 /// Inspect a system call with a custom caller and finalize the state.
155 ///
156 /// Similar to [`InspectEvm::inspect_tx`] but for system calls with a custom caller.
157 ///
158 /// # Outcome of Error
159 ///
160 /// Same as [`InspectEvm::inspect_tx`]: the journal is finalized on error.
161 fn inspect_system_call_with_caller(
162 &mut self,
163 caller: Address,
164 system_contract_address: Address,
165 data: Bytes,
166 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error> {
167 let output_or_error =
168 self.inspect_one_system_call_with_caller(caller, system_contract_address, data);
169 let state = self.finalize();
170 let output = output_or_error?;
171 Ok(ExecResultAndState::new(output, state))
172 }
173
174 /// Inspect a system call with a given inspector.
175 ///
176 /// Similar to [`InspectEvm::inspect_one`] but for system calls.
177 fn inspect_one_system_call_with_inspector(
178 &mut self,
179 system_contract_address: Address,
180 data: Bytes,
181 inspector: Self::Inspector,
182 ) -> Result<Self::ExecutionResult, Self::Error> {
183 self.set_inspector(inspector);
184 self.inspect_one_system_call(system_contract_address, data)
185 }
186
187 /// Inspect a system call with a given inspector and finalize the state.
188 ///
189 /// Similar to [`InspectEvm::inspect`] but for system calls.
190 ///
191 /// # Outcome of Error
192 ///
193 /// Same as [`InspectEvm::inspect_tx`]: the journal is finalized on error.
194 fn inspect_system_call_with_inspector(
195 &mut self,
196 system_contract_address: Address,
197 data: Bytes,
198 inspector: Self::Inspector,
199 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error> {
200 let output_or_error =
201 self.inspect_one_system_call_with_inspector(system_contract_address, data, inspector);
202 let state = self.finalize();
203 let output = output_or_error?;
204 Ok(ExecResultAndState::new(output, state))
205 }
206
207 /// Inspect a system call with a given inspector and caller.
208 ///
209 /// Similar to [`InspectEvm::inspect_one`] but for system calls.
210 fn inspect_one_system_call_with_inspector_and_caller(
211 &mut self,
212 caller: Address,
213 system_contract_address: Address,
214 data: Bytes,
215 inspector: Self::Inspector,
216 ) -> Result<Self::ExecutionResult, Self::Error> {
217 self.set_inspector(inspector);
218 self.inspect_one_system_call_with_caller(caller, system_contract_address, data)
219 }
220
221 /// Inspect a system call with a given inspector and finalize the state.
222 ///
223 /// Similar to [`InspectEvm::inspect`] but for system calls.
224 ///
225 /// # Outcome of Error
226 ///
227 /// Same as [`InspectEvm::inspect_tx`]: the journal is finalized on error.
228 fn inspect_system_call_with_inspector_and_caller(
229 &mut self,
230 caller: Address,
231 system_contract_address: Address,
232 data: Bytes,
233 inspector: Self::Inspector,
234 ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error> {
235 let output_or_error = self.inspect_one_system_call_with_inspector_and_caller(
236 caller,
237 system_contract_address,
238 data,
239 inspector,
240 );
241 let state = self.finalize();
242 let output = output_or_error?;
243 Ok(ExecResultAndState::new(output, state))
244 }
245}