Skip to main content

reth_rpc_api/
debug.rs

1use alloy_eips::{BlockId, BlockNumberOrTag};
2use alloy_genesis::ChainConfig;
3use alloy_json_rpc::RpcObject;
4use alloy_primitives::{Address, Bytes, B256, U64};
5use alloy_rpc_types_debug::ExecutionWitness;
6use alloy_rpc_types_eth::{Bundle, StateContext};
7use alloy_rpc_types_trace::geth::{
8    BlockTraceResult, GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, TraceResult,
9};
10use jsonrpsee::{core::RpcResult, proc_macros::rpc};
11use reth_trie_common::{updates::TrieUpdates, ExecutionWitnessMode, HashedPostState};
12
13/// Debug rpc interface.
14#[cfg_attr(not(feature = "client"), rpc(server, namespace = "debug"))]
15#[cfg_attr(feature = "client", rpc(server, client, namespace = "debug"))]
16pub trait DebugApi<TxReq: RpcObject> {
17    /// Returns an RLP-encoded header.
18    #[method(name = "getRawHeader")]
19    async fn raw_header(&self, block_id: BlockId) -> RpcResult<Bytes>;
20
21    /// Returns an RLP-encoded block.
22    #[method(name = "getRawBlock")]
23    async fn raw_block(&self, block_id: BlockId) -> RpcResult<Bytes>;
24
25    /// Returns an EIP-2718 binary-encoded transaction.
26    ///
27    /// If this is a pooled EIP-4844 transaction, the blob sidecar is included.
28    #[method(name = "getRawTransaction")]
29    async fn raw_transaction(&self, hash: B256) -> RpcResult<Option<Bytes>>;
30
31    /// Returns an array of EIP-2718 binary-encoded transactions for the given [`BlockId`].
32    #[method(name = "getRawTransactions")]
33    async fn raw_transactions(&self, block_id: BlockId) -> RpcResult<Vec<Bytes>>;
34
35    /// Returns an array of EIP-2718 binary-encoded receipts.
36    #[method(name = "getRawReceipts")]
37    async fn raw_receipts(&self, block_id: BlockId) -> RpcResult<Vec<Bytes>>;
38
39    /// Returns an array of recent bad blocks that the client has seen on the network.
40    #[method(name = "getBadBlocks")]
41    async fn bad_blocks(&self) -> RpcResult<Vec<serde_json::Value>>;
42
43    /// Returns the structured logs created during the execution of EVM between two blocks
44    /// (excluding start) as a JSON object.
45    #[method(name = "traceChain")]
46    async fn debug_trace_chain(
47        &self,
48        start_exclusive: BlockNumberOrTag,
49        end_inclusive: BlockNumberOrTag,
50    ) -> RpcResult<Vec<BlockTraceResult>>;
51
52    /// The `debug_traceBlock` method will return a full stack trace of all invoked opcodes of all
53    /// transaction that were included in this block.
54    ///
55    /// This expects an rlp encoded block
56    ///
57    /// Note, the parent of this block must be present, or it will fail. For the second parameter
58    /// see [`GethDebugTracingOptions`] reference.
59    #[method(name = "traceBlock")]
60    async fn debug_trace_block(
61        &self,
62        rlp_block: Bytes,
63        opts: Option<GethDebugTracingOptions>,
64    ) -> RpcResult<Vec<TraceResult>>;
65
66    /// Similar to `debug_traceBlock`, `debug_traceBlockByHash` accepts a block hash and will replay
67    /// the block that is already present in the database. For the second parameter see
68    /// [`GethDebugTracingOptions`].
69    #[method(name = "traceBlockByHash")]
70    async fn debug_trace_block_by_hash(
71        &self,
72        block: B256,
73        opts: Option<GethDebugTracingOptions>,
74    ) -> RpcResult<Vec<TraceResult>>;
75
76    /// Similar to `debug_traceBlockByHash`, `debug_traceBlockByNumber` accepts a block number
77    /// [`BlockNumberOrTag`] and will replay the block that is already present in the database.
78    /// For the second parameter see [`GethDebugTracingOptions`].
79    #[method(name = "traceBlockByNumber")]
80    async fn debug_trace_block_by_number(
81        &self,
82        block: BlockNumberOrTag,
83        opts: Option<GethDebugTracingOptions>,
84    ) -> RpcResult<Vec<TraceResult>>;
85
86    /// The `debug_traceTransaction` debugging method will attempt to run the transaction in the
87    /// exact same manner as it was executed on the network. It will replay any transaction that
88    /// may have been executed prior to this one before it will finally attempt to execute the
89    /// transaction that corresponds to the given hash.
90    #[method(name = "traceTransaction")]
91    async fn debug_trace_transaction(
92        &self,
93        tx_hash: B256,
94        opts: Option<GethDebugTracingOptions>,
95    ) -> RpcResult<GethTrace>;
96
97    /// The `debug_traceCall` method lets you run an `eth_call` within the context of the given
98    /// block execution using the final state of parent block as the base.
99    ///
100    /// The first argument (just as in `eth_call`) is a transaction request.
101    /// The block can optionally be specified either by hash or by number as
102    /// the second argument.
103    /// The trace can be configured similar to `debug_traceTransaction`,
104    /// see [`GethDebugTracingOptions`]. The method returns the same output as
105    /// `debug_traceTransaction`.
106    #[method(name = "traceCall")]
107    async fn debug_trace_call(
108        &self,
109        request: TxReq,
110        block_id: Option<BlockId>,
111        opts: Option<GethDebugTracingCallOptions>,
112    ) -> RpcResult<GethTrace>;
113
114    /// The `debug_traceCallMany` method lets you run an `eth_callMany` within the context of the
115    /// given block execution using the final state of parent block as the base followed by n
116    /// transactions.
117    ///
118    /// The first argument is a list of bundles. Each bundle can overwrite the block headers. This
119    /// will affect all transaction in that bundle.
120    /// `BlockNumber` and `transaction_index` are optional. `Transaction_index`
121    /// specifies the number of tx in the block to replay and -1 means all transactions should be
122    /// replayed.
123    /// The trace can be configured similar to `debug_traceTransaction`.
124    /// State override apply to all bundles.
125    ///
126    /// This methods is similar to many `eth_callMany`, hence this returns nested lists of traces.
127    /// Where the length of the outer list is the number of bundles and the length of the inner list
128    /// (`Vec<GethTrace>`) is the number of transactions in the bundle.
129    #[method(name = "traceCallMany")]
130    async fn debug_trace_call_many(
131        &self,
132        bundles: Vec<Bundle<TxReq>>,
133        state_context: Option<StateContext>,
134        opts: Option<GethDebugTracingCallOptions>,
135    ) -> RpcResult<Vec<Vec<GethTrace>>>;
136
137    /// The `debug_executionWitness` method allows for re-execution of a block with the purpose of
138    /// generating an execution witness. The witness comprises of a map of all hashed trie nodes
139    /// to their preimages that were required during the execution of the block, including during
140    /// state root recomputation.
141    ///
142    /// The first argument is the block number or tag. The optional second argument selects the
143    /// witness generation mode and defaults to `legacy`.
144    #[method(name = "executionWitness")]
145    async fn debug_execution_witness(
146        &self,
147        block: BlockNumberOrTag,
148        mode: Option<ExecutionWitnessMode>,
149    ) -> RpcResult<ExecutionWitness>;
150
151    /// The `debug_executionWitnessByBlockHash` method allows for re-execution of a block with the
152    /// purpose of generating an execution witness. The witness comprises of a map of all hashed
153    /// trie nodes to their preimages that were required during the execution of the block,
154    /// including during state root recomputation.
155    ///
156    /// The first argument is the block hash. The optional second argument selects the witness
157    /// generation mode and defaults to `legacy`.
158    #[method(name = "executionWitnessByBlockHash")]
159    async fn debug_execution_witness_by_block_hash(
160        &self,
161        hash: B256,
162        mode: Option<ExecutionWitnessMode>,
163    ) -> RpcResult<ExecutionWitness>;
164
165    /// Sets the logging backtrace location. When a backtrace location is set and a log message is
166    /// emitted at that location, the stack of the goroutine executing the log statement will
167    /// be printed to stderr.
168    #[method(name = "backtraceAt")]
169    async fn debug_backtrace_at(&self, location: &str) -> RpcResult<()>;
170
171    /// Enumerates all accounts at a given block with paging capability. `maxResults` are returned
172    /// in the page and the items have keys that come after the `start` key (hashed address).
173    ///
174    /// If incompletes is false, then accounts for which the key preimage (i.e: the address) doesn't
175    /// exist in db are skipped. NB: geth by default does not store preimages.
176    #[method(name = "accountRange")]
177    async fn debug_account_range(
178        &self,
179        block_number: BlockNumberOrTag,
180        start: Bytes,
181        max_results: u64,
182        nocode: bool,
183        nostorage: bool,
184        incompletes: bool,
185    ) -> RpcResult<()>;
186
187    /// Turns on block profiling for the given duration and writes profile data to disk. It uses a
188    /// profile rate of 1 for most accurate information. If a different rate is desired, set the
189    /// rate and write the profile manually using `debug_writeBlockProfile`.
190    #[method(name = "blockProfile")]
191    async fn debug_block_profile(&self, file: String, seconds: u64) -> RpcResult<()>;
192
193    /// Flattens the entire key-value database into a single level, removing all unused slots and
194    /// merging all keys.
195    #[method(name = "chaindbCompact")]
196    async fn debug_chaindb_compact(&self) -> RpcResult<()>;
197
198    /// Returns the current chain config.
199    #[method(name = "chainConfig")]
200    async fn debug_chain_config(&self) -> RpcResult<ChainConfig>;
201
202    /// Returns leveldb properties of the key-value database.
203    #[method(name = "chaindbProperty")]
204    async fn debug_chaindb_property(&self, property: String) -> RpcResult<()>;
205
206    /// Returns the code associated with a given hash at the specified block ID.
207    /// If no block ID is provided, it defaults to the latest block.
208    #[method(name = "codeByHash")]
209    async fn debug_code_by_hash(
210        &self,
211        hash: B256,
212        block_id: Option<BlockId>,
213    ) -> RpcResult<Option<Bytes>>;
214
215    /// Turns on CPU profiling for the given duration and writes profile data to disk.
216    #[method(name = "cpuProfile")]
217    async fn debug_cpu_profile(&self, file: String, seconds: u64) -> RpcResult<()>;
218
219    /// Retrieves an ancient binary blob from the freezer. The freezer is a collection of
220    /// append-only immutable files. The first argument `kind` specifies which table to look up data
221    /// from. The list of all table kinds are as follows:
222    #[method(name = "dbAncient")]
223    async fn debug_db_ancient(&self, kind: String, number: u64) -> RpcResult<()>;
224
225    /// Returns the number of ancient items in the ancient store.
226    #[method(name = "dbAncients")]
227    async fn debug_db_ancients(&self) -> RpcResult<()>;
228
229    /// Returns the raw value of a key stored in the database.
230    #[method(name = "dbGet")]
231    async fn debug_db_get(&self, key: String) -> RpcResult<Option<Bytes>>;
232
233    /// Retrieves the state that corresponds to the block number and returns a list of accounts
234    /// (including storage and code).
235    #[method(name = "dumpBlock")]
236    async fn debug_dump_block(&self, number: BlockId) -> RpcResult<()>;
237
238    /// Forces garbage collection.
239    #[method(name = "freeOSMemory")]
240    async fn debug_free_os_memory(&self) -> RpcResult<()>;
241
242    /// Forces a temporary client freeze, normally when the server is overloaded.
243    #[method(name = "freezeClient")]
244    async fn debug_freeze_client(&self, node: String) -> RpcResult<()>;
245
246    /// Returns garbage collection statistics.
247    #[method(name = "gcStats")]
248    async fn debug_gc_stats(&self) -> RpcResult<()>;
249
250    /// Returns the first number where the node has accessible state on disk. This is the
251    /// post-state of that block and the pre-state of the next block. The (from, to) parameters
252    /// are the sequence of blocks to search, which can go either forwards or backwards.
253    ///
254    /// Note: to get the last state pass in the range of blocks in reverse, i.e. (last, first).
255    #[method(name = "getAccessibleState")]
256    async fn debug_get_accessible_state(
257        &self,
258        from: BlockNumberOrTag,
259        to: BlockNumberOrTag,
260    ) -> RpcResult<()>;
261
262    /// Returns all accounts that have changed between the two blocks specified. A change is defined
263    /// as a difference in nonce, balance, code hash, or storage hash. With one parameter, returns
264    /// the list of accounts modified in the specified block.
265    #[method(name = "getModifiedAccountsByHash")]
266    async fn debug_get_modified_accounts_by_hash(
267        &self,
268        start_hash: B256,
269        end_hash: B256,
270    ) -> RpcResult<()>;
271
272    /// Returns all accounts that have changed between the two blocks specified. A change is defined
273    /// as a difference in nonce, balance, code hash or storage hash.
274    #[method(name = "getModifiedAccountsByNumber")]
275    async fn debug_get_modified_accounts_by_number(
276        &self,
277        start_number: u64,
278        end_number: u64,
279    ) -> RpcResult<()>;
280
281    /// Turns on Go runtime tracing for the given duration and writes trace data to disk.
282    #[method(name = "goTrace")]
283    async fn debug_go_trace(&self, file: String, seconds: u64) -> RpcResult<()>;
284
285    /// Executes a block (bad- or canon- or side-), and returns a list of intermediate roots: the
286    /// stateroot after each transaction.
287    #[method(name = "intermediateRoots")]
288    async fn debug_intermediate_roots(
289        &self,
290        block_hash: B256,
291        opts: Option<GethDebugTracingCallOptions>,
292    ) -> RpcResult<Vec<B256>>;
293
294    /// Returns detailed runtime memory statistics.
295    #[method(name = "memStats")]
296    async fn debug_mem_stats(&self) -> RpcResult<()>;
297
298    /// Turns on mutex profiling for `nsec` seconds and writes profile data to file. It uses a
299    /// profile rate of 1 for most accurate information. If a different rate is desired, set the
300    /// rate and write the profile manually.
301    #[method(name = "mutexProfile")]
302    async fn debug_mutex_profile(&self, file: String, nsec: u64) -> RpcResult<()>;
303
304    /// Returns the preimage for a sha3 hash, if known.
305    #[method(name = "preimage")]
306    async fn debug_preimage(&self, hash: B256) -> RpcResult<()>;
307
308    /// Retrieves a block and returns its pretty printed form.
309    #[method(name = "printBlock")]
310    async fn debug_print_block(&self, number: u64) -> RpcResult<()>;
311
312    /// Fetches and retrieves the seed hash of the block by number.
313    #[method(name = "seedHash")]
314    async fn debug_seed_hash(&self, number: u64) -> RpcResult<B256>;
315
316    /// Sets the rate (in samples/sec) of goroutine block profile data collection. A non-zero rate
317    /// enables block profiling, setting it to zero stops the profile. Collected profile data can be
318    /// written using `debug_writeBlockProfile`.
319    #[method(name = "setBlockProfileRate")]
320    async fn debug_set_block_profile_rate(&self, rate: u64) -> RpcResult<()>;
321
322    /// Sets the garbage collection target percentage. A negative value disables garbage collection.
323    #[method(name = "setGCPercent")]
324    async fn debug_set_gc_percent(&self, v: i32) -> RpcResult<()>;
325
326    /// Sets the current head of the local chain by block number. Note, this is a destructive action
327    /// and may severely damage your chain. Use with extreme caution.
328    #[method(name = "setHead")]
329    async fn debug_set_head(&self, number: U64) -> RpcResult<()>;
330
331    /// Sets the rate of mutex profiling.
332    #[method(name = "setMutexProfileFraction")]
333    async fn debug_set_mutex_profile_fraction(&self, rate: i32) -> RpcResult<()>;
334
335    /// Configures how often in-memory state tries are persisted to disk. The interval needs to be
336    /// in a format parsable by a time.Duration. Note that the interval is not wall-clock time.
337    /// Rather it is accumulated block processing time after which the state should be flushed.
338    #[method(name = "setTrieFlushInterval")]
339    async fn debug_set_trie_flush_interval(&self, interval: String) -> RpcResult<()>;
340
341    /// Returns a printed representation of the stacks of all goroutines.
342    #[method(name = "stacks")]
343    async fn debug_stacks(&self) -> RpcResult<()>;
344
345    /// Used to obtain info about a block.
346    #[method(name = "standardTraceBadBlockToFile")]
347    async fn debug_standard_trace_bad_block_to_file(
348        &self,
349        block: BlockNumberOrTag,
350        opts: Option<GethDebugTracingCallOptions>,
351    ) -> RpcResult<()>;
352
353    /// This method is similar to `debug_standardTraceBlockToFile`, but can be used to obtain info
354    /// about a block which has been rejected as invalid (for some reason).
355    #[method(name = "standardTraceBlockToFile")]
356    async fn debug_standard_trace_block_to_file(
357        &self,
358        block: BlockNumberOrTag,
359        opts: Option<GethDebugTracingCallOptions>,
360    ) -> RpcResult<()>;
361
362    /// Turns on CPU profiling indefinitely, writing to the given file.
363    #[method(name = "startCPUProfile")]
364    async fn debug_start_cpu_profile(&self, file: String) -> RpcResult<()>;
365
366    /// Starts writing a Go runtime trace to the given file.
367    #[method(name = "startGoTrace")]
368    async fn debug_start_go_trace(&self, file: String) -> RpcResult<()>;
369
370    /// Returns the state root of the `HashedPostState` on top of the state for the given block with
371    /// trie updates.
372    #[method(name = "stateRootWithUpdates")]
373    async fn debug_state_root_with_updates(
374        &self,
375        hashed_state: HashedPostState,
376        block_id: Option<BlockId>,
377    ) -> RpcResult<(B256, TrieUpdates)>;
378
379    /// Stops an ongoing CPU profile.
380    #[method(name = "stopCPUProfile")]
381    async fn debug_stop_cpu_profile(&self) -> RpcResult<()>;
382
383    /// Stops writing the Go runtime trace.
384    #[method(name = "stopGoTrace")]
385    async fn debug_stop_go_trace(&self) -> RpcResult<()>;
386
387    /// Returns the storage at the given block height and transaction index. The result can be
388    /// paged by providing a `maxResult` to cap the number of storage slots returned as well as
389    /// specifying the offset via `keyStart` (hash of storage key).
390    #[method(name = "storageRangeAt")]
391    async fn debug_storage_range_at(
392        &self,
393        block_hash: B256,
394        tx_idx: usize,
395        contract_address: Address,
396        key_start: B256,
397        max_result: u64,
398    ) -> RpcResult<()>;
399
400    /// Returns the structured logs created during the execution of EVM against a block pulled
401    /// from the pool of bad ones and returns them as a JSON object. For the second parameter see
402    /// `TraceConfig` reference.
403    #[method(name = "traceBadBlock")]
404    async fn debug_trace_bad_block(
405        &self,
406        block_hash: B256,
407        opts: Option<GethDebugTracingCallOptions>,
408    ) -> RpcResult<Vec<TraceResult>>;
409
410    /// Sets the logging verbosity ceiling. Log messages with level up to and including the given
411    /// level will be printed.
412    #[method(name = "verbosity")]
413    async fn debug_verbosity(&self, level: usize) -> RpcResult<()>;
414
415    /// Sets the logging verbosity pattern.
416    #[method(name = "vmodule")]
417    async fn debug_vmodule(&self, pattern: String) -> RpcResult<()>;
418
419    /// Writes a goroutine blocking profile to the given file.
420    #[method(name = "writeBlockProfile")]
421    async fn debug_write_block_profile(&self, file: String) -> RpcResult<()>;
422
423    /// Writes an allocation profile to the given file.
424    #[method(name = "writeMemProfile")]
425    async fn debug_write_mem_profile(&self, file: String) -> RpcResult<()>;
426
427    /// Writes a goroutine blocking profile to the given file.
428    #[method(name = "writeMutexProfile")]
429    async fn debug_write_mutex_profile(&self, file: String) -> RpcResult<()>;
430}
431
432/// An extension to the `debug_` namespace that provides additional methods for retrieving
433/// witnesses.
434///
435/// This is separate from the regular `debug_` api, because this depends on the network specific
436/// params. For optimism this will expect the optimism specific payload attributes
437#[cfg_attr(not(feature = "client"), rpc(server, namespace = "debug"))]
438#[cfg_attr(feature = "client", rpc(server, client, namespace = "debug"))]
439pub trait DebugExecutionWitnessApi<Attributes> {
440    /// The `debug_executePayload` method allows for re-execution of a group of transactions with
441    /// the purpose of generating an execution witness. The witness comprises of a map of all
442    /// hashed trie nodes to their preimages that were required during the execution of the block,
443    /// including during state root recomputation.
444    ///
445    /// The first argument is the parent block hash. The second argument is the payload
446    /// attributes for the new block.
447    #[method(name = "executePayload")]
448    async fn execute_payload(
449        &self,
450        parent_block_hash: B256,
451        attributes: Attributes,
452    ) -> RpcResult<ExecutionWitness>;
453}