1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
use reth_primitives::{Address, BlockId, BlockNumberOrTag, Bytes, B256};
use reth_rpc_types::{
    trace::geth::{
        BlockTraceResult, GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace,
        TraceResult,
    },
    Bundle, RichBlock, StateContext, TransactionRequest,
};

/// Debug rpc interface.
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "debug"))]
#[cfg_attr(feature = "client", rpc(server, client, namespace = "debug"))]
pub trait DebugApi {
    /// Returns an RLP-encoded header.
    #[method(name = "getRawHeader")]
    async fn raw_header(&self, block_id: BlockId) -> RpcResult<Bytes>;

    /// Returns an RLP-encoded block.
    #[method(name = "getRawBlock")]
    async fn raw_block(&self, block_id: BlockId) -> RpcResult<Bytes>;

    /// Returns a EIP-2718 binary-encoded transaction.
    ///
    /// If this is a pooled EIP-4844 transaction, the blob sidecar is included.
    #[method(name = "getRawTransaction")]
    async fn raw_transaction(&self, hash: B256) -> RpcResult<Option<Bytes>>;

    /// Returns an array of EIP-2718 binary-encoded transactions for the given [`BlockId`].
    #[method(name = "getRawTransactions")]
    async fn raw_transactions(&self, block_id: BlockId) -> RpcResult<Vec<Bytes>>;

    /// Returns an array of EIP-2718 binary-encoded receipts.
    #[method(name = "getRawReceipts")]
    async fn raw_receipts(&self, block_id: BlockId) -> RpcResult<Vec<Bytes>>;

    /// Returns an array of recent bad blocks that the client has seen on the network.
    #[method(name = "getBadBlocks")]
    async fn bad_blocks(&self) -> RpcResult<Vec<RichBlock>>;

    /// Returns the structured logs created during the execution of EVM between two blocks
    /// (excluding start) as a JSON object.
    #[method(name = "traceChain")]
    async fn debug_trace_chain(
        &self,
        start_exclusive: BlockNumberOrTag,
        end_inclusive: BlockNumberOrTag,
    ) -> RpcResult<Vec<BlockTraceResult>>;

    /// The `debug_traceBlock` method will return a full stack trace of all invoked opcodes of all
    /// transaction that were included in this block.
    ///
    /// This expects an rlp encoded block
    ///
    /// Note, the parent of this block must be present, or it will fail. For the second parameter
    /// see [GethDebugTracingOptions] reference.
    #[method(name = "traceBlock")]
    async fn debug_trace_block(
        &self,
        rlp_block: Bytes,
        opts: Option<GethDebugTracingOptions>,
    ) -> RpcResult<Vec<TraceResult>>;

    /// Similar to `debug_traceBlock`, `debug_traceBlockByHash` accepts a block hash and will replay
    /// the block that is already present in the database. For the second parameter see
    /// [GethDebugTracingOptions].
    #[method(name = "traceBlockByHash")]
    async fn debug_trace_block_by_hash(
        &self,
        block: B256,
        opts: Option<GethDebugTracingOptions>,
    ) -> RpcResult<Vec<TraceResult>>;

    /// Similar to `debug_traceBlockByHash`, `debug_traceBlockByNumber` accepts a block number
    /// [BlockNumberOrTag] and will replay the block that is already present in the database.
    /// For the second parameter see [GethDebugTracingOptions].
    #[method(name = "traceBlockByNumber")]
    async fn debug_trace_block_by_number(
        &self,
        block: BlockNumberOrTag,
        opts: Option<GethDebugTracingOptions>,
    ) -> RpcResult<Vec<TraceResult>>;

    /// The `debug_traceTransaction` debugging method will attempt to run the transaction in the
    /// exact same manner as it was executed on the network. It will replay any transaction that
    /// may have been executed prior to this one before it will finally attempt to execute the
    /// transaction that corresponds to the given hash.
    #[method(name = "traceTransaction")]
    async fn debug_trace_transaction(
        &self,
        tx_hash: B256,
        opts: Option<GethDebugTracingOptions>,
    ) -> RpcResult<GethTrace>;

    /// The `debug_traceCall` method lets you run an `eth_call` within the context of the given
    /// block execution using the final state of parent block as the base.
    ///
    /// The first argument (just as in `eth_call`) is a transaction request.
    /// The block can optionally be specified either by hash or by number as
    /// the second argument.
    /// The trace can be configured similar to `debug_traceTransaction`,
    /// see [GethDebugTracingOptions]. The method returns the same output as
    /// `debug_traceTransaction`.
    #[method(name = "traceCall")]
    async fn debug_trace_call(
        &self,
        request: TransactionRequest,
        block_number: Option<BlockId>,
        opts: Option<GethDebugTracingCallOptions>,
    ) -> RpcResult<GethTrace>;

    /// The `debug_traceCallMany` method lets you run an `eth_callMany` within the context of the
    /// given block execution using the final state of parent block as the base followed by n
    /// transactions.
    ///
    /// The first argument is a list of bundles. Each bundle can overwrite the block headers. This
    /// will affect all transaction in that bundle.
    /// BlockNumber and transaction_index are optional. Transaction_index
    /// specifies the number of tx in the block to replay and -1 means all transactions should be
    /// replayed.
    /// The trace can be configured similar to `debug_traceTransaction`.
    /// State override apply to all bundles.
    ///
    /// This methods is similar to many `eth_callMany`, hence this returns nested lists of traces.
    /// Where the length of the outer list is the number of bundles and the length of the inner list
    /// (`Vec<GethTrace>`) is the number of transactions in the bundle.
    #[method(name = "traceCallMany")]
    async fn debug_trace_call_many(
        &self,
        bundles: Vec<Bundle>,
        state_context: Option<StateContext>,
        opts: Option<GethDebugTracingCallOptions>,
    ) -> RpcResult<Vec<Vec<GethTrace>>>;

    /// Sets the logging backtrace location. When a backtrace location is set and a log message is
    /// emitted at that location, the stack of the goroutine executing the log statement will
    /// be printed to stderr.
    #[method(name = "backtraceAt")]
    async fn debug_backtrace_at(&self, location: &str) -> RpcResult<()>;

    /// Enumerates all accounts at a given block with paging capability. `maxResults` are returned
    /// in the page and the items have keys that come after the `start` key (hashed address).
    ///
    /// If incompletes is false, then accounts for which the key preimage (i.e: the address) doesn't
    /// exist in db are skipped. NB: geth by default does not store preimages.
    #[method(name = "accountRange")]
    async fn debug_account_range(
        &self,
        block_number: BlockNumberOrTag,
        start: Bytes,
        max_results: u64,
        nocode: bool,
        nostorage: bool,
        incompletes: bool,
    ) -> RpcResult<()>;

    /// Turns on block profiling for the given duration and writes profile data to disk. It uses a
    /// profile rate of 1 for most accurate information. If a different rate is desired, set the
    /// rate and write the profile manually using `debug_writeBlockProfile`.
    #[method(name = "blockProfile")]
    async fn debug_block_profile(&self, file: String, seconds: u64) -> RpcResult<()>;

    /// Flattens the entire key-value database into a single level, removing all unused slots and
    /// merging all keys.
    #[method(name = "chaindbCompact")]
    async fn debug_chaindb_compact(&self) -> RpcResult<()>;

    /// Returns leveldb properties of the key-value database.
    #[method(name = "chaindbProperty")]
    async fn debug_chaindb_property(&self, property: String) -> RpcResult<()>;

    /// Turns on CPU profiling for the given duration and writes profile data to disk.
    #[method(name = "cpuProfile")]
    async fn debug_cpu_profile(&self, file: String, seconds: u64) -> RpcResult<()>;

    /// Retrieves an ancient binary blob from the freezer. The freezer is a collection of
    /// append-only immutable files. The first argument `kind` specifies which table to look up data
    /// from. The list of all table kinds are as follows:
    #[method(name = "dbAncient")]
    async fn debug_db_ancient(&self, kind: String, number: u64) -> RpcResult<()>;

    /// Returns the number of ancient items in the ancient store.
    #[method(name = "dbAncients")]
    async fn debug_db_ancients(&self) -> RpcResult<()>;

    /// Returns the raw value of a key stored in the database.
    #[method(name = "dbGet")]
    async fn debug_db_get(&self, key: String) -> RpcResult<()>;

    /// Retrieves the state that corresponds to the block number and returns a list of accounts
    /// (including storage and code).
    #[method(name = "dumpBlock")]
    async fn debug_dump_block(&self, number: BlockId) -> RpcResult<()>;

    /// Forces garbage collection.
    #[method(name = "freeOSMemory")]
    async fn debug_free_os_memory(&self) -> RpcResult<()>;

    /// Forces a temporary client freeze, normally when the server is overloaded.
    #[method(name = "freezeClient")]
    async fn debug_freeze_client(&self, node: String) -> RpcResult<()>;

    /// Returns garbage collection statistics.
    #[method(name = "gcStats")]
    async fn debug_gc_stats(&self) -> RpcResult<()>;

    /// Returns the first number where the node has accessible state on disk. This is the
    /// post-state of that block and the pre-state of the next block. The (from, to) parameters
    /// are the sequence of blocks to search, which can go either forwards or backwards.
    ///
    /// Note: to get the last state pass in the range of blocks in reverse, i.e. (last, first).
    #[method(name = "getAccessibleState")]
    async fn debug_get_accessible_state(
        &self,
        from: BlockNumberOrTag,
        to: BlockNumberOrTag,
    ) -> RpcResult<()>;

    /// Returns all accounts that have changed between the two blocks specified. A change is defined
    /// as a difference in nonce, balance, code hash, or storage hash. With one parameter, returns
    /// the list of accounts modified in the specified block.
    #[method(name = "getModifiedAccountsByHash")]
    async fn debug_get_modified_accounts_by_hash(
        &self,
        start_hash: B256,
        end_hash: B256,
    ) -> RpcResult<()>;

    /// Returns all accounts that have changed between the two blocks specified. A change is defined
    /// as a difference in nonce, balance, code hash or storage hash.
    #[method(name = "getModifiedAccountsByNumber")]
    async fn debug_get_modified_accounts_by_number(
        &self,
        start_number: u64,
        end_number: u64,
    ) -> RpcResult<()>;

    /// Turns on Go runtime tracing for the given duration and writes trace data to disk.
    #[method(name = "goTrace")]
    async fn debug_go_trace(&self, file: String, seconds: u64) -> RpcResult<()>;

    /// Executes a block (bad- or canon- or side-), and returns a list of intermediate roots: the
    /// stateroot after each transaction.
    #[method(name = "intermediateRoots")]
    async fn debug_intermediate_roots(
        &self,
        block_hash: B256,
        opts: Option<GethDebugTracingCallOptions>,
    ) -> RpcResult<()>;

    /// Returns detailed runtime memory statistics.
    #[method(name = "memStats")]
    async fn debug_mem_stats(&self) -> RpcResult<()>;

    /// Turns on mutex profiling for `nsec` seconds and writes profile data to file. It uses a
    /// profile rate of 1 for most accurate information. If a different rate is desired, set the
    /// rate and write the profile manually.
    #[method(name = "mutexProfile")]
    async fn debug_mutex_profile(&self, file: String, nsec: u64) -> RpcResult<()>;

    /// Returns the preimage for a sha3 hash, if known.
    #[method(name = "preimage")]
    async fn debug_preimage(&self, hash: B256) -> RpcResult<()>;

    /// Retrieves a block and returns its pretty printed form.
    #[method(name = "printBlock")]
    async fn debug_print_block(&self, number: u64) -> RpcResult<()>;

    /// Fetches and retrieves the seed hash of the block by number.
    #[method(name = "seedHash")]
    async fn debug_seed_hash(&self, number: u64) -> RpcResult<B256>;

    /// Sets the rate (in samples/sec) of goroutine block profile data collection. A non-zero rate
    /// enables block profiling, setting it to zero stops the profile. Collected profile data can be
    /// written using `debug_writeBlockProfile`.
    #[method(name = "setBlockProfileRate")]
    async fn debug_set_block_profile_rate(&self, rate: u64) -> RpcResult<()>;

    /// Sets the garbage collection target percentage. A negative value disables garbage collection.
    #[method(name = "setGCPercent")]
    async fn debug_set_gc_percent(&self, v: i32) -> RpcResult<()>;

    /// Sets the current head of the local chain by block number. Note, this is a destructive action
    /// and may severely damage your chain. Use with extreme caution.
    #[method(name = "setHead")]
    async fn debug_set_head(&self, number: u64) -> RpcResult<()>;

    /// Sets the rate of mutex profiling.
    #[method(name = "setMutexProfileFraction")]
    async fn debug_set_mutex_profile_fraction(&self, rate: i32) -> RpcResult<()>;

    /// Configures how often in-memory state tries are persisted to disk. The interval needs to be
    /// in a format parsable by a time.Duration. Note that the interval is not wall-clock time.
    /// Rather it is accumulated block processing time after which the state should be flushed.
    #[method(name = "setTrieFlushInterval")]
    async fn debug_set_trie_flush_interval(&self, interval: String) -> RpcResult<()>;

    /// Returns a printed representation of the stacks of all goroutines.
    #[method(name = "stacks")]
    async fn debug_stacks(&self) -> RpcResult<()>;

    /// Used to obtain info about a block.
    #[method(name = "standardTraceBadBlockToFile")]
    async fn debug_standard_trace_bad_block_to_file(
        &self,
        block: BlockNumberOrTag,
        opts: Option<GethDebugTracingCallOptions>,
    ) -> RpcResult<()>;

    /// This method is similar to `debug_standardTraceBlockToFile`, but can be used to obtain info
    /// about a block which has been rejected as invalid (for some reason).
    #[method(name = "standardTraceBlockToFile")]
    async fn debug_standard_trace_block_to_file(
        &self,
        block: BlockNumberOrTag,
        opts: Option<GethDebugTracingCallOptions>,
    ) -> RpcResult<()>;

    /// Turns on CPU profiling indefinitely, writing to the given file.
    #[method(name = "startCPUProfile")]
    async fn debug_start_cpu_profile(&self, file: String) -> RpcResult<()>;

    /// Starts writing a Go runtime trace to the given file.
    #[method(name = "startGoTrace")]
    async fn debug_start_go_trace(&self, file: String) -> RpcResult<()>;

    /// Stops an ongoing CPU profile.
    #[method(name = "stopCPUProfile")]
    async fn debug_stop_cpu_profile(&self) -> RpcResult<()>;

    /// Stops writing the Go runtime trace.
    #[method(name = "stopGoTrace")]
    async fn debug_stop_go_trace(&self) -> RpcResult<()>;

    /// Returns the storage at the given block height and transaction index. The result can be
    /// paged by providing a `maxResult` to cap the number of storage slots returned as well as
    /// specifying the offset via `keyStart` (hash of storage key).
    #[method(name = "storageRangeAt")]
    async fn debug_storage_range_at(
        &self,
        block_hash: B256,
        tx_idx: usize,
        contract_address: Address,
        key_start: B256,
        max_result: u64,
    ) -> RpcResult<()>;

    /// Returns the structured logs created during the execution of EVM against a block pulled
    /// from the pool of bad ones and returns them as a JSON object. For the second parameter see
    /// TraceConfig reference.
    #[method(name = "traceBadBlock")]
    async fn debug_trace_bad_block(
        &self,
        block_hash: B256,
        opts: Option<GethDebugTracingCallOptions>,
    ) -> RpcResult<()>;

    /// Sets the logging verbosity ceiling. Log messages with level up to and including the given
    /// level will be printed.
    #[method(name = "verbosity")]
    async fn debug_verbosity(&self, level: usize) -> RpcResult<()>;

    /// Sets the logging verbosity pattern.
    #[method(name = "vmodule")]
    async fn debug_vmodule(&self, pattern: String) -> RpcResult<()>;

    /// Writes a goroutine blocking profile to the given file.
    #[method(name = "writeBlockProfile")]
    async fn debug_write_block_profile(&self, file: String) -> RpcResult<()>;

    /// Writes an allocation profile to the given file.
    #[method(name = "writeMemProfile")]
    async fn debug_write_mem_profile(&self, file: String) -> RpcResult<()>;

    /// Writes a goroutine blocking profile to the given file.
    #[method(name = "writeMutexProfile")]
    async fn debug_write_mutex_profile(&self, file: String) -> RpcResult<()>;
}