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::{Account, AccountInfo, Bundle, Index, StateContext};
7use alloy_rpc_types_trace::geth::{
8 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#[rpc(server, namespace = "debug")]
15pub trait DebugApi<TxReq: RpcObject> {
16 /// Returns an RLP-encoded header.
17 #[method(name = "getRawHeader")]
18 async fn raw_header(&self, block_id: BlockId) -> RpcResult<Bytes>;
19
20 /// Returns an RLP-encoded block.
21 #[method(name = "getRawBlock")]
22 async fn raw_block(&self, block_id: BlockId) -> RpcResult<Bytes>;
23
24 /// Returns the RLP-encoded EIP-7928 block access list.
25 #[method(name = "getRawBlockAccessList")]
26 async fn raw_block_access_list(&self, block_id: BlockId) -> RpcResult<Bytes>;
27
28 /// Returns an EIP-2718 binary-encoded transaction.
29 ///
30 /// If this is a pooled EIP-4844 transaction, the blob sidecar is included.
31 #[method(name = "getRawTransaction")]
32 async fn raw_transaction(&self, hash: B256) -> RpcResult<Option<Bytes>>;
33
34 /// Returns an array of EIP-2718 binary-encoded transactions for the given [`BlockId`].
35 #[method(name = "getRawTransactions")]
36 async fn raw_transactions(&self, block_id: BlockId) -> RpcResult<Vec<Bytes>>;
37
38 /// Returns an array of EIP-2718 binary-encoded receipts.
39 #[method(name = "getRawReceipts")]
40 async fn raw_receipts(&self, block_id: BlockId) -> RpcResult<Vec<Bytes>>;
41
42 /// Returns an array of recent bad blocks that the client has seen on the network.
43 #[method(name = "getBadBlocks")]
44 async fn bad_blocks(&self) -> RpcResult<Vec<serde_json::Value>>;
45
46 /// Clears all transactions from the transaction pool.
47 #[method(name = "clearTxpool")]
48 async fn debug_clear_txpool(&self) -> RpcResult<()>;
49
50 /// Subscribes to structured logs created during EVM execution between two blocks, excluding
51 /// the start block and including the end block.
52 #[subscription(
53 name = "subscribe" => "subscription",
54 unsubscribe = "unsubscribe",
55 item = alloy_rpc_types_trace::geth::ChainBlockTraceResult
56 )]
57 async fn debug_subscribe(
58 &self,
59 subscription: String,
60 start_exclusive: BlockNumberOrTag,
61 end_inclusive: BlockNumberOrTag,
62 opts: Option<GethDebugTracingOptions>,
63 ) -> jsonrpsee::core::SubscriptionResult;
64
65 /// The `debug_traceBlock` method will return a full stack trace of all invoked opcodes of all
66 /// transaction that were included in this block.
67 ///
68 /// This expects an rlp encoded block
69 ///
70 /// Note, the parent of this block must be present, or it will fail. For the second parameter
71 /// see [`GethDebugTracingOptions`] reference.
72 #[method(name = "traceBlock")]
73 async fn debug_trace_block(
74 &self,
75 rlp_block: Bytes,
76 opts: Option<GethDebugTracingOptions>,
77 ) -> RpcResult<Vec<TraceResult>>;
78
79 /// Similar to `debug_traceBlock`, `debug_traceBlockByHash` accepts a block hash and will replay
80 /// the block that is already present in the database. For the second parameter see
81 /// [`GethDebugTracingOptions`].
82 #[method(name = "traceBlockByHash")]
83 async fn debug_trace_block_by_hash(
84 &self,
85 block: B256,
86 opts: Option<GethDebugTracingOptions>,
87 ) -> RpcResult<Vec<TraceResult>>;
88
89 /// Similar to `debug_traceBlockByHash`, `debug_traceBlockByNumber` accepts a block number
90 /// [`BlockNumberOrTag`] and will replay the block that is already present in the database.
91 /// For the second parameter see [`GethDebugTracingOptions`].
92 #[method(name = "traceBlockByNumber")]
93 async fn debug_trace_block_by_number(
94 &self,
95 block: BlockNumberOrTag,
96 opts: Option<GethDebugTracingOptions>,
97 ) -> RpcResult<Vec<TraceResult>>;
98
99 /// The `debug_traceTransaction` debugging method will attempt to run the transaction in the
100 /// exact same manner as it was executed on the network. It will replay any transaction that
101 /// may have been executed prior to this one before it will finally attempt to execute the
102 /// transaction that corresponds to the given hash.
103 #[method(name = "traceTransaction")]
104 async fn debug_trace_transaction(
105 &self,
106 tx_hash: B256,
107 opts: Option<GethDebugTracingOptions>,
108 ) -> RpcResult<GethTrace>;
109
110 /// The `debug_traceCall` method lets you run an `eth_call` within the context of the given
111 /// block execution using the final state of parent block as the base.
112 ///
113 /// The first argument (just as in `eth_call`) is a transaction request.
114 /// The block can optionally be specified either by hash or by number as
115 /// the second argument.
116 /// The trace can be configured similar to `debug_traceTransaction`,
117 /// see [`GethDebugTracingOptions`]. The method returns the same output as
118 /// `debug_traceTransaction`.
119 #[method(name = "traceCall")]
120 async fn debug_trace_call(
121 &self,
122 request: TxReq,
123 block_id: Option<BlockId>,
124 opts: Option<GethDebugTracingCallOptions>,
125 ) -> RpcResult<GethTrace>;
126
127 /// The `debug_traceCallMany` method lets you run an `eth_callMany` within the context of the
128 /// given block execution using the final state of parent block as the base followed by n
129 /// transactions.
130 ///
131 /// The first argument is a list of bundles. Each bundle can overwrite the block headers. This
132 /// will affect all transaction in that bundle.
133 /// `BlockNumber` and `transaction_index` are optional. `Transaction_index`
134 /// specifies the number of tx in the block to replay and -1 means all transactions should be
135 /// replayed.
136 /// The trace can be configured similar to `debug_traceTransaction`.
137 /// State override apply to all bundles.
138 ///
139 /// This methods is similar to many `eth_callMany`, hence this returns nested lists of traces.
140 /// Where the length of the outer list is the number of bundles and the length of the inner list
141 /// (`Vec<GethTrace>`) is the number of transactions in the bundle.
142 #[method(name = "traceCallMany")]
143 async fn debug_trace_call_many(
144 &self,
145 bundles: Vec<Bundle<TxReq>>,
146 state_context: Option<StateContext>,
147 opts: Option<GethDebugTracingCallOptions>,
148 ) -> RpcResult<Vec<Vec<GethTrace>>>;
149
150 /// The `debug_executionWitness` method allows for re-execution of a block with the purpose of
151 /// generating an execution witness. The witness comprises of a map of all hashed trie nodes
152 /// to their preimages that were required during the execution of the block, including during
153 /// state root recomputation.
154 ///
155 /// The first argument is the block identifier. The optional second argument selects the
156 /// witness generation mode and defaults to `legacy`.
157 #[method(name = "executionWitness")]
158 async fn debug_execution_witness(
159 &self,
160 block: BlockId,
161 mode: Option<ExecutionWitnessMode>,
162 ) -> RpcResult<ExecutionWitness>;
163
164 /// The `debug_executionWitnessByBlockHash` method allows for re-execution of a block with the
165 /// purpose of generating an execution witness. The witness comprises of a map of all hashed
166 /// trie nodes to their preimages that were required during the execution of the block,
167 /// including during state root recomputation.
168 ///
169 /// The first argument is the block hash. The optional second argument selects the witness
170 /// generation mode and defaults to `legacy`.
171 #[method(name = "executionWitnessByBlockHash")]
172 async fn debug_execution_witness_by_block_hash(
173 &self,
174 hash: B256,
175 mode: Option<ExecutionWitnessMode>,
176 ) -> RpcResult<ExecutionWitness>;
177
178 /// Returns account information, including the storage root, at the state after executing the
179 /// transaction with the given index in the block.
180 #[method(name = "accountAt")]
181 async fn debug_account_at(
182 &self,
183 block_id: BlockId,
184 tx_index: Index,
185 address: Address,
186 ) -> RpcResult<Option<Account>>;
187
188 /// Returns account information at the state after executing the transaction with the given
189 /// index in the block.
190 #[method(name = "accountInfoAt")]
191 async fn debug_account_info_at(
192 &self,
193 block_id: BlockId,
194 tx_index: Index,
195 address: Address,
196 ) -> RpcResult<Option<AccountInfo>>;
197
198 /// Enumerates all accounts at a given block with paging capability. `maxResults` are returned
199 /// in the page and the items have keys that come after the `start` key (hashed address).
200 ///
201 /// If incompletes is false, then accounts for which the key preimage (i.e: the address) doesn't
202 /// exist in db are skipped. NB: geth by default does not store preimages.
203 #[method(name = "accountRange")]
204 async fn debug_account_range(
205 &self,
206 block_number: BlockNumberOrTag,
207 start: Bytes,
208 max_results: u64,
209 nocode: bool,
210 nostorage: bool,
211 incompletes: bool,
212 ) -> RpcResult<()>;
213
214 /// Flattens the entire key-value database into a single level, removing all unused slots and
215 /// merging all keys.
216 #[method(name = "chaindbCompact")]
217 async fn debug_chaindb_compact(&self) -> RpcResult<()>;
218
219 /// Returns the current chain config.
220 #[method(name = "chainConfig")]
221 async fn debug_chain_config(&self) -> RpcResult<ChainConfig>;
222
223 /// Returns leveldb properties of the key-value database.
224 #[method(name = "chaindbProperty")]
225 async fn debug_chaindb_property(&self, property: String) -> RpcResult<()>;
226
227 /// Returns the code associated with a given hash at the specified block ID.
228 /// If no block ID is provided, it defaults to the latest block.
229 #[method(name = "codeByHash")]
230 async fn debug_code_by_hash(
231 &self,
232 hash: B256,
233 block_id: Option<BlockId>,
234 ) -> RpcResult<Option<Bytes>>;
235
236 /// Retrieves an ancient binary blob from the freezer. The freezer is a collection of
237 /// append-only immutable files. The first argument `kind` specifies which table to look up data
238 /// from. The list of all table kinds are as follows:
239 #[method(name = "dbAncient")]
240 async fn debug_db_ancient(&self, kind: String, number: u64) -> RpcResult<()>;
241
242 /// Returns the number of ancient items in the ancient store.
243 #[method(name = "dbAncients")]
244 async fn debug_db_ancients(&self) -> RpcResult<()>;
245
246 /// Returns the raw value of a key stored in the database.
247 #[method(name = "dbGet")]
248 async fn debug_db_get(&self, key: String) -> RpcResult<Option<Bytes>>;
249
250 /// Retrieves the state that corresponds to the block number and returns a list of accounts
251 /// (including storage and code).
252 #[method(name = "dumpBlock")]
253 async fn debug_dump_block(&self, number: BlockId) -> RpcResult<()>;
254
255 /// Forces garbage collection.
256 #[method(name = "freeOSMemory")]
257 async fn debug_free_os_memory(&self) -> RpcResult<()>;
258
259 /// Returns garbage collection statistics.
260 #[method(name = "gcStats")]
261 async fn debug_gc_stats(&self) -> RpcResult<()>;
262
263 /// Returns the first number where the node has accessible state on disk. This is the
264 /// post-state of that block and the pre-state of the next block. The (from, to) parameters
265 /// are the sequence of blocks to search, which can go either forwards or backwards.
266 ///
267 /// Note: to get the last state pass in the range of blocks in reverse, i.e. (last, first).
268 #[method(name = "getAccessibleState")]
269 async fn debug_get_accessible_state(
270 &self,
271 from: BlockNumberOrTag,
272 to: BlockNumberOrTag,
273 ) -> RpcResult<()>;
274
275 /// Returns all accounts that have changed between the two blocks specified. A change is defined
276 /// as a difference in nonce, balance, code hash, or storage hash. With one parameter, returns
277 /// the list of accounts modified in the specified block.
278 #[method(name = "getModifiedAccountsByHash")]
279 async fn debug_get_modified_accounts_by_hash(
280 &self,
281 start_hash: B256,
282 end_hash: B256,
283 ) -> RpcResult<()>;
284
285 /// Returns all accounts that have changed between the two blocks specified. A change is defined
286 /// as a difference in nonce, balance, code hash or storage hash.
287 #[method(name = "getModifiedAccountsByNumber")]
288 async fn debug_get_modified_accounts_by_number(
289 &self,
290 start_number: u64,
291 end_number: u64,
292 ) -> RpcResult<()>;
293
294 /// Executes a canonical or bad block, and returns a list of intermediate roots: the stateroot
295 /// after each transaction up to the first invalid one.
296 #[method(name = "intermediateRoots")]
297 async fn debug_intermediate_roots(
298 &self,
299 block_hash: B256,
300 opts: Option<GethDebugTracingCallOptions>,
301 ) -> RpcResult<Vec<B256>>;
302
303 /// Returns detailed runtime memory statistics.
304 #[method(name = "memStats")]
305 async fn debug_mem_stats(&self) -> RpcResult<()>;
306
307 /// Returns the preimage for a sha3 hash, if known.
308 #[method(name = "preimage")]
309 async fn debug_preimage(&self, hash: B256) -> RpcResult<()>;
310
311 /// Retrieves a block and returns its pretty printed form.
312 #[method(name = "printBlock")]
313 async fn debug_print_block(&self, number: u64) -> RpcResult<()>;
314
315 /// Fetches and retrieves the seed hash of the block by number.
316 #[method(name = "seedHash")]
317 async fn debug_seed_hash(&self, number: u64) -> RpcResult<B256>;
318
319 /// Sets the garbage collection target percentage. A negative value disables garbage collection.
320 #[method(name = "setGCPercent")]
321 async fn debug_set_gc_percent(&self, v: i32) -> RpcResult<()>;
322
323 /// Sets the current head of the local chain by block number. Note, this is a destructive action
324 /// and may severely damage your chain. Use with extreme caution.
325 #[method(name = "setHead")]
326 async fn debug_set_head(&self, number: U64) -> RpcResult<()>;
327
328 /// Configures how often in-memory state tries are persisted to disk. The interval needs to be
329 /// in a format parsable by a time.Duration. Note that the interval is not wall-clock time.
330 /// Rather it is accumulated block processing time after which the state should be flushed.
331 #[method(name = "setTrieFlushInterval")]
332 async fn debug_set_trie_flush_interval(&self, interval: String) -> RpcResult<()>;
333
334 /// Used to obtain info about a block.
335 #[method(name = "standardTraceBadBlockToFile")]
336 async fn debug_standard_trace_bad_block_to_file(
337 &self,
338 block: BlockNumberOrTag,
339 opts: Option<GethDebugTracingCallOptions>,
340 ) -> RpcResult<()>;
341
342 /// This method is similar to `debug_standardTraceBlockToFile`, but can be used to obtain info
343 /// about a block which has been rejected as invalid (for some reason).
344 #[method(name = "standardTraceBlockToFile")]
345 async fn debug_standard_trace_block_to_file(
346 &self,
347 block: BlockNumberOrTag,
348 opts: Option<GethDebugTracingCallOptions>,
349 ) -> RpcResult<()>;
350
351 /// Returns the state root of the `HashedPostState` on top of the state for the given block with
352 /// trie updates.
353 #[method(name = "stateRootWithUpdates")]
354 async fn debug_state_root_with_updates(
355 &self,
356 hashed_state: HashedPostState,
357 block_id: Option<BlockId>,
358 ) -> RpcResult<(B256, TrieUpdates)>;
359
360 /// Returns the storage at the given block height and transaction index. The result can be
361 /// paged by providing a `maxResult` to cap the number of storage slots returned as well as
362 /// specifying the offset via `keyStart` (hash of storage key).
363 #[method(name = "storageRangeAt")]
364 async fn debug_storage_range_at(
365 &self,
366 block_hash: B256,
367 tx_idx: usize,
368 contract_address: Address,
369 key_start: B256,
370 max_result: u64,
371 ) -> RpcResult<()>;
372
373 /// Returns the structured logs created during the execution of EVM against a block pulled
374 /// from the pool of bad ones and returns them as a JSON object. For the second parameter see
375 /// `TraceConfig` reference.
376 #[method(name = "traceBadBlock")]
377 async fn debug_trace_bad_block(
378 &self,
379 block_hash: B256,
380 opts: Option<GethDebugTracingCallOptions>,
381 ) -> RpcResult<Vec<TraceResult>>;
382}