Skip to main content

ethrex_vm/
tracing.rs

1use crate::backends::levm::LEVM;
2use ethrex_common::H256;
3use ethrex_common::tracing::{CallTrace, OpcodeTraceResult, PrestateResult};
4use ethrex_common::types::{Block, BlockHeader, GenericTransaction};
5pub use ethrex_levm::tracing::OpcodeTracerConfig;
6
7use crate::{Evm, EvmError};
8
9impl Evm {
10    /// Runs a single tx with the call tracer and outputs its trace.
11    /// Assumes that the received state already contains changes from previous blocks and other
12    /// transactions within its block.
13    /// Wraps LEVM::trace_tx_calls depending on the feature.
14    pub fn trace_tx_calls(
15        &mut self,
16        block: &Block,
17        tx_index: usize,
18        only_top_call: bool,
19        with_log: bool,
20        log_index_base: u64,
21    ) -> Result<CallTrace, EvmError> {
22        let tx = block
23            .body
24            .transactions
25            .get(tx_index)
26            .ok_or(EvmError::Custom(
27                "Missing Transaction for Trace".to_string(),
28            ))?;
29
30        LEVM::trace_tx_calls(
31            &mut self.db,
32            &block.header,
33            tx,
34            only_top_call,
35            with_log,
36            log_index_base,
37            self.vm_type,
38            self.crypto.as_ref(),
39            self.stateless_validator.as_deref(),
40        )
41    }
42
43    /// Executes a single tx and captures the pre/post account state (prestateTracer).
44    /// Assumes that the received state already contains changes from previous transactions.
45    pub fn trace_tx_prestate(
46        &mut self,
47        block: &Block,
48        tx_index: usize,
49        diff_mode: bool,
50        include_empty: bool,
51    ) -> Result<PrestateResult, EvmError> {
52        let tx = block
53            .body
54            .transactions
55            .get(tx_index)
56            .ok_or(EvmError::Custom(
57                "Missing Transaction for Trace".to_string(),
58            ))?;
59
60        LEVM::trace_tx_prestate(
61            &mut self.db,
62            &block.header,
63            tx,
64            diff_mode,
65            include_empty,
66            self.vm_type,
67            self.crypto.as_ref(),
68        )
69    }
70
71    /// Executes a single tx and captures the per-opcode (EIP-3155) trace.
72    /// Assumes that the received state already contains changes from previous transactions.
73    pub fn trace_tx_opcodes(
74        &mut self,
75        block: &Block,
76        tx_index: usize,
77        cfg: OpcodeTracerConfig,
78    ) -> Result<OpcodeTraceResult, EvmError> {
79        let tx = block
80            .body
81            .transactions
82            .get(tx_index)
83            .ok_or(EvmError::Custom(
84                "Missing Transaction for Trace".to_string(),
85            ))?;
86
87        LEVM::trace_tx_opcodes(
88            &mut self.db,
89            &block.header,
90            tx,
91            cfg,
92            self.vm_type,
93            self.crypto.as_ref(),
94        )
95    }
96
97    /// Traces a synthetic `eth_call`-shaped request with the callTracer (`debug_traceCall`).
98    /// Assumes `db` already reflects the target block/tx state to call against.
99    pub fn trace_call_calls(
100        &mut self,
101        block_header: &BlockHeader,
102        tx: &GenericTransaction,
103        only_top_call: bool,
104        with_log: bool,
105        log_index_base: u64,
106    ) -> Result<CallTrace, EvmError> {
107        LEVM::trace_call_calls(
108            &mut self.db,
109            block_header,
110            tx,
111            only_top_call,
112            with_log,
113            log_index_base,
114            self.vm_type,
115            self.crypto.as_ref(),
116        )
117    }
118
119    /// Traces a synthetic `eth_call`-shaped request with the prestateTracer (`debug_traceCall`).
120    pub fn trace_call_prestate(
121        &mut self,
122        block_header: &BlockHeader,
123        tx: &GenericTransaction,
124        diff_mode: bool,
125        include_empty: bool,
126    ) -> Result<PrestateResult, EvmError> {
127        LEVM::trace_call_prestate(
128            &mut self.db,
129            block_header,
130            tx,
131            diff_mode,
132            include_empty,
133            self.vm_type,
134            self.crypto.as_ref(),
135        )
136    }
137
138    /// Traces a synthetic `eth_call`-shaped request with the opcode (EIP-3155) tracer
139    /// (`debug_traceCall`).
140    pub fn trace_call_opcodes(
141        &mut self,
142        block_header: &BlockHeader,
143        tx: &GenericTransaction,
144        cfg: OpcodeTracerConfig,
145    ) -> Result<OpcodeTraceResult, EvmError> {
146        LEVM::trace_call_opcodes(
147            &mut self.db,
148            block_header,
149            tx,
150            cfg,
151            self.vm_type,
152            self.crypto.as_ref(),
153        )
154    }
155
156    /// Traces every transaction in `block` with the callTracer. Assumes `self`'s state is
157    /// the block's parent state. Runs the whole block in a single pass, reusing the
158    /// block-invariant EVM config across transactions.
159    pub fn trace_block_calls(
160        &mut self,
161        block: &Block,
162        only_top_call: bool,
163        with_log: bool,
164    ) -> Result<Vec<(H256, CallTrace)>, EvmError> {
165        LEVM::trace_block_calls(
166            &mut self.db,
167            block,
168            only_top_call,
169            with_log,
170            self.vm_type,
171            self.crypto.as_ref(),
172        )
173    }
174
175    /// Traces every transaction in `block` with the prestateTracer. See
176    /// [`Self::trace_block_calls`].
177    pub fn trace_block_prestate(
178        &mut self,
179        block: &Block,
180        diff_mode: bool,
181        include_empty: bool,
182    ) -> Result<Vec<(H256, PrestateResult)>, EvmError> {
183        LEVM::trace_block_prestate(
184            &mut self.db,
185            block,
186            diff_mode,
187            include_empty,
188            self.vm_type,
189            self.crypto.as_ref(),
190        )
191    }
192
193    /// Traces every transaction in `block` with the opcode (EIP-3155) tracer. See
194    /// [`Self::trace_block_calls`].
195    pub fn trace_block_opcodes(
196        &mut self,
197        block: &Block,
198        cfg: OpcodeTracerConfig,
199    ) -> Result<Vec<(H256, OpcodeTraceResult)>, EvmError> {
200        LEVM::trace_block_opcodes(&mut self.db, block, cfg, self.vm_type, self.crypto.as_ref())
201    }
202
203    /// Reruns the given block, saving the changes on the state, doesn't output any results or receipts.
204    /// If the optional argument `stop_index` is set, the run will stop just before executing the transaction at that index
205    /// and won't process the withdrawals afterwards.
206    /// WrapsLEVM::rerun_block depending on the feature.
207    pub fn rerun_block(
208        &mut self,
209        block: &Block,
210        stop_index: Option<usize>,
211    ) -> Result<(), EvmError> {
212        LEVM::rerun_block(
213            &mut self.db,
214            block,
215            stop_index,
216            self.vm_type,
217            self.crypto.as_ref(),
218            self.stateless_validator.as_deref(),
219        )
220    }
221}