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, 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 a 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.
144 #[method(name = "executionWitness")]
145 async fn debug_execution_witness(&self, block: BlockNumberOrTag)
146 -> RpcResult<ExecutionWitness>;
147
148 /// The `debug_executionWitnessByBlockHash` method allows for re-execution of a block with the
149 /// purpose of generating an execution witness. The witness comprises of a map of all hashed
150 /// trie nodes to their preimages that were required during the execution of the block,
151 /// including during state root recomputation.
152 ///
153 /// The first argument is the block hash.
154 #[method(name = "executionWitnessByBlockHash")]
155 async fn debug_execution_witness_by_block_hash(
156 &self,
157 hash: B256,
158 ) -> RpcResult<ExecutionWitness>;
159
160 /// Re-executes a block and returns the Block Access List (BAL) as defined in EIP-7928.
161 #[method(name = "getBlockAccessList")]
162 async fn debug_get_block_access_list(&self, block_id: BlockId) -> RpcResult<BlockAccessList>;
163
164 /// Sets the logging backtrace location. When a backtrace location is set and a log message is
165 /// emitted at that location, the stack of the goroutine executing the log statement will
166 /// be printed to stderr.
167 #[method(name = "backtraceAt")]
168 async fn debug_backtrace_at(&self, location: &str) -> RpcResult<()>;
169
170 /// Enumerates all accounts at a given block with paging capability. `maxResults` are returned
171 /// in the page and the items have keys that come after the `start` key (hashed address).
172 ///
173 /// If incompletes is false, then accounts for which the key preimage (i.e: the address) doesn't
174 /// exist in db are skipped. NB: geth by default does not store preimages.
175 #[method(name = "accountRange")]
176 async fn debug_account_range(
177 &self,
178 block_number: BlockNumberOrTag,
179 start: Bytes,
180 max_results: u64,
181 nocode: bool,
182 nostorage: bool,
183 incompletes: bool,
184 ) -> RpcResult<()>;
185
186 /// Turns on block profiling for the given duration and writes profile data to disk. It uses a
187 /// profile rate of 1 for most accurate information. If a different rate is desired, set the
188 /// rate and write the profile manually using `debug_writeBlockProfile`.
189 #[method(name = "blockProfile")]
190 async fn debug_block_profile(&self, file: String, seconds: u64) -> RpcResult<()>;
191
192 /// Flattens the entire key-value database into a single level, removing all unused slots and
193 /// merging all keys.
194 #[method(name = "chaindbCompact")]
195 async fn debug_chaindb_compact(&self) -> RpcResult<()>;
196
197 /// Returns the current chain config.
198 #[method(name = "chainConfig")]
199 async fn debug_chain_config(&self) -> RpcResult<ChainConfig>;
200
201 /// Returns leveldb properties of the key-value database.
202 #[method(name = "chaindbProperty")]
203 async fn debug_chaindb_property(&self, property: String) -> RpcResult<()>;
204
205 /// Returns the code associated with a given hash at the specified block ID.
206 /// If no block ID is provided, it defaults to the latest block.
207 #[method(name = "codeByHash")]
208 async fn debug_code_by_hash(
209 &self,
210 hash: B256,
211 block_id: Option<BlockId>,
212 ) -> RpcResult<Option<Bytes>>;
213
214 /// Turns on CPU profiling for the given duration and writes profile data to disk.
215 #[method(name = "cpuProfile")]
216 async fn debug_cpu_profile(&self, file: String, seconds: u64) -> RpcResult<()>;
217
218 /// Retrieves an ancient binary blob from the freezer. The freezer is a collection of
219 /// append-only immutable files. The first argument `kind` specifies which table to look up data
220 /// from. The list of all table kinds are as follows:
221 #[method(name = "dbAncient")]
222 async fn debug_db_ancient(&self, kind: String, number: u64) -> RpcResult<()>;
223
224 /// Returns the number of ancient items in the ancient store.
225 #[method(name = "dbAncients")]
226 async fn debug_db_ancients(&self) -> RpcResult<()>;
227
228 /// Returns the raw value of a key stored in the database.
229 #[method(name = "dbGet")]
230 async fn debug_db_get(&self, key: String) -> RpcResult<Option<Bytes>>;
231
232 /// Retrieves the state that corresponds to the block number and returns a list of accounts
233 /// (including storage and code).
234 #[method(name = "dumpBlock")]
235 async fn debug_dump_block(&self, number: BlockId) -> RpcResult<()>;
236
237 /// Forces garbage collection.
238 #[method(name = "freeOSMemory")]
239 async fn debug_free_os_memory(&self) -> RpcResult<()>;
240
241 /// Forces a temporary client freeze, normally when the server is overloaded.
242 #[method(name = "freezeClient")]
243 async fn debug_freeze_client(&self, node: String) -> RpcResult<()>;
244
245 /// Returns garbage collection statistics.
246 #[method(name = "gcStats")]
247 async fn debug_gc_stats(&self) -> RpcResult<()>;
248
249 /// Returns the first number where the node has accessible state on disk. This is the
250 /// post-state of that block and the pre-state of the next block. The (from, to) parameters
251 /// are the sequence of blocks to search, which can go either forwards or backwards.
252 ///
253 /// Note: to get the last state pass in the range of blocks in reverse, i.e. (last, first).
254 #[method(name = "getAccessibleState")]
255 async fn debug_get_accessible_state(
256 &self,
257 from: BlockNumberOrTag,
258 to: BlockNumberOrTag,
259 ) -> RpcResult<()>;
260
261 /// Returns all accounts that have changed between the two blocks specified. A change is defined
262 /// as a difference in nonce, balance, code hash, or storage hash. With one parameter, returns
263 /// the list of accounts modified in the specified block.
264 #[method(name = "getModifiedAccountsByHash")]
265 async fn debug_get_modified_accounts_by_hash(
266 &self,
267 start_hash: B256,
268 end_hash: B256,
269 ) -> RpcResult<()>;
270
271 /// Returns all accounts that have changed between the two blocks specified. A change is defined
272 /// as a difference in nonce, balance, code hash or storage hash.
273 #[method(name = "getModifiedAccountsByNumber")]
274 async fn debug_get_modified_accounts_by_number(
275 &self,
276 start_number: u64,
277 end_number: u64,
278 ) -> RpcResult<()>;
279
280 /// Turns on Go runtime tracing for the given duration and writes trace data to disk.
281 #[method(name = "goTrace")]
282 async fn debug_go_trace(&self, file: String, seconds: u64) -> RpcResult<()>;
283
284 /// Executes a block (bad- or canon- or side-), and returns a list of intermediate roots: the
285 /// stateroot after each transaction.
286 #[method(name = "intermediateRoots")]
287 async fn debug_intermediate_roots(
288 &self,
289 block_hash: B256,
290 opts: Option<GethDebugTracingCallOptions>,
291 ) -> RpcResult<()>;
292
293 /// Returns detailed runtime memory statistics.
294 #[method(name = "memStats")]
295 async fn debug_mem_stats(&self) -> RpcResult<()>;
296
297 /// Turns on mutex profiling for `nsec` seconds and writes profile data to file. It uses a
298 /// profile rate of 1 for most accurate information. If a different rate is desired, set the
299 /// rate and write the profile manually.
300 #[method(name = "mutexProfile")]
301 async fn debug_mutex_profile(&self, file: String, nsec: u64) -> RpcResult<()>;
302
303 /// Returns the preimage for a sha3 hash, if known.
304 #[method(name = "preimage")]
305 async fn debug_preimage(&self, hash: B256) -> RpcResult<()>;
306
307 /// Retrieves a block and returns its pretty printed form.
308 #[method(name = "printBlock")]
309 async fn debug_print_block(&self, number: u64) -> RpcResult<()>;
310
311 /// Fetches and retrieves the seed hash of the block by number.
312 #[method(name = "seedHash")]
313 async fn debug_seed_hash(&self, number: u64) -> RpcResult<B256>;
314
315 /// Sets the rate (in samples/sec) of goroutine block profile data collection. A non-zero rate
316 /// enables block profiling, setting it to zero stops the profile. Collected profile data can be
317 /// written using `debug_writeBlockProfile`.
318 #[method(name = "setBlockProfileRate")]
319 async fn debug_set_block_profile_rate(&self, rate: u64) -> RpcResult<()>;
320
321 /// Sets the garbage collection target percentage. A negative value disables garbage collection.
322 #[method(name = "setGCPercent")]
323 async fn debug_set_gc_percent(&self, v: i32) -> RpcResult<()>;
324
325 /// Sets the current head of the local chain by block number. Note, this is a destructive action
326 /// and may severely damage your chain. Use with extreme caution.
327 #[method(name = "setHead")]
328 async fn debug_set_head(&self, number: U64) -> RpcResult<()>;
329
330 /// Sets the rate of mutex profiling.
331 #[method(name = "setMutexProfileFraction")]
332 async fn debug_set_mutex_profile_fraction(&self, rate: i32) -> RpcResult<()>;
333
334 /// Configures how often in-memory state tries are persisted to disk. The interval needs to be
335 /// in a format parsable by a time.Duration. Note that the interval is not wall-clock time.
336 /// Rather it is accumulated block processing time after which the state should be flushed.
337 #[method(name = "setTrieFlushInterval")]
338 async fn debug_set_trie_flush_interval(&self, interval: String) -> RpcResult<()>;
339
340 /// Returns a printed representation of the stacks of all goroutines.
341 #[method(name = "stacks")]
342 async fn debug_stacks(&self) -> RpcResult<()>;
343
344 /// Used to obtain info about a block.
345 #[method(name = "standardTraceBadBlockToFile")]
346 async fn debug_standard_trace_bad_block_to_file(
347 &self,
348 block: BlockNumberOrTag,
349 opts: Option<GethDebugTracingCallOptions>,
350 ) -> RpcResult<()>;
351
352 /// This method is similar to `debug_standardTraceBlockToFile`, but can be used to obtain info
353 /// about a block which has been rejected as invalid (for some reason).
354 #[method(name = "standardTraceBlockToFile")]
355 async fn debug_standard_trace_block_to_file(
356 &self,
357 block: BlockNumberOrTag,
358 opts: Option<GethDebugTracingCallOptions>,
359 ) -> RpcResult<()>;
360
361 /// Turns on CPU profiling indefinitely, writing to the given file.
362 #[method(name = "startCPUProfile")]
363 async fn debug_start_cpu_profile(&self, file: String) -> RpcResult<()>;
364
365 /// Starts writing a Go runtime trace to the given file.
366 #[method(name = "startGoTrace")]
367 async fn debug_start_go_trace(&self, file: String) -> RpcResult<()>;
368
369 /// Returns the state root of the `HashedPostState` on top of the state for the given block with
370 /// trie updates.
371 #[method(name = "stateRootWithUpdates")]
372 async fn debug_state_root_with_updates(
373 &self,
374 hashed_state: HashedPostState,
375 block_id: Option<BlockId>,
376 ) -> RpcResult<(B256, TrieUpdates)>;
377
378 /// Stops an ongoing CPU profile.
379 #[method(name = "stopCPUProfile")]
380 async fn debug_stop_cpu_profile(&self) -> RpcResult<()>;
381
382 /// Stops writing the Go runtime trace.
383 #[method(name = "stopGoTrace")]
384 async fn debug_stop_go_trace(&self) -> RpcResult<()>;
385
386 /// Returns the storage at the given block height and transaction index. The result can be
387 /// paged by providing a `maxResult` to cap the number of storage slots returned as well as
388 /// specifying the offset via `keyStart` (hash of storage key).
389 #[method(name = "storageRangeAt")]
390 async fn debug_storage_range_at(
391 &self,
392 block_hash: B256,
393 tx_idx: usize,
394 contract_address: Address,
395 key_start: B256,
396 max_result: u64,
397 ) -> RpcResult<()>;
398
399 /// Returns the structured logs created during the execution of EVM against a block pulled
400 /// from the pool of bad ones and returns them as a JSON object. For the second parameter see
401 /// `TraceConfig` reference.
402 #[method(name = "traceBadBlock")]
403 async fn debug_trace_bad_block(
404 &self,
405 block_hash: B256,
406 opts: Option<GethDebugTracingCallOptions>,
407 ) -> RpcResult<()>;
408
409 /// Sets the logging verbosity ceiling. Log messages with level up to and including the given
410 /// level will be printed.
411 #[method(name = "verbosity")]
412 async fn debug_verbosity(&self, level: usize) -> RpcResult<()>;
413
414 /// Sets the logging verbosity pattern.
415 #[method(name = "vmodule")]
416 async fn debug_vmodule(&self, pattern: String) -> RpcResult<()>;
417
418 /// Writes a goroutine blocking profile to the given file.
419 #[method(name = "writeBlockProfile")]
420 async fn debug_write_block_profile(&self, file: String) -> RpcResult<()>;
421
422 /// Writes an allocation profile to the given file.
423 #[method(name = "writeMemProfile")]
424 async fn debug_write_mem_profile(&self, file: String) -> RpcResult<()>;
425
426 /// Writes a goroutine blocking profile to the given file.
427 #[method(name = "writeMutexProfile")]
428 async fn debug_write_mutex_profile(&self, file: String) -> RpcResult<()>;
429}
430
431/// An extension to the `debug_` namespace that provides additional methods for retrieving
432/// witnesses.
433///
434/// This is separate from the regular `debug_` api, because this depends on the network specific
435/// params. For optimism this will expect the optimism specific payload attributes
436#[cfg_attr(not(feature = "client"), rpc(server, namespace = "debug"))]
437#[cfg_attr(feature = "client", rpc(server, client, namespace = "debug"))]
438pub trait DebugExecutionWitnessApi<Attributes> {
439 /// The `debug_executePayload` method allows for re-execution of a group of transactions with
440 /// the purpose of generating an execution witness. The witness comprises of a map of all
441 /// hashed trie nodes to their preimages that were required during the execution of the block,
442 /// including during state root recomputation.
443 ///
444 /// The first argument is the parent block hash. The second argument is the payload
445 /// attributes for the new block.
446 #[method(name = "executePayload")]
447 async fn execute_payload(
448 &self,
449 parent_block_hash: B256,
450 attributes: Attributes,
451 ) -> RpcResult<ExecutionWitness>;
452}