Skip to main content

reth_rpc_api/
debug.rs

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