Skip to main content

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}