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