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