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