From c2436a955f40457fd1888fbacebaeee35af9e60f Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Thu, 24 Aug 2023 15:14:51 +0200 Subject: [PATCH] feat(rpc): add missing `DebugApi` methods (#4321) --- crates/rpc/rpc-api/src/debug.rs | 240 +++++++++++++++++++++++++++++++- crates/rpc/rpc/src/debug.rs | 211 +++++++++++++++++++++++++++- 2 files changed, 449 insertions(+), 2 deletions(-) diff --git a/crates/rpc/rpc-api/src/debug.rs b/crates/rpc/rpc-api/src/debug.rs index 880fa82c10..8422a17535 100644 --- a/crates/rpc/rpc-api/src/debug.rs +++ b/crates/rpc/rpc-api/src/debug.rs @@ -1,5 +1,5 @@ use jsonrpsee::{core::RpcResult, proc_macros::rpc}; -use reth_primitives::{BlockId, BlockNumberOrTag, Bytes, H256}; +use reth_primitives::{BlockId, BlockNumberOrTag, Bytes, H160, H256}; use reth_rpc_types::{ trace::geth::{ BlockTraceResult, GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, @@ -127,4 +127,242 @@ pub trait DebugApi { /// 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: H256, + end_hash: H256, + ) -> 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: H256, + opts: Option, + ) -> 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: H256) -> 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; + + /// 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, + ) -> 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, + ) -> 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: H256, + tx_idx: usize, + contract_address: H160, + key_start: H256, + 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: H256, + opts: Option, + ) -> 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<()>; } diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 7e987ca9c7..a18a5cf6ff 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -12,7 +12,9 @@ use crate::{ }; use async_trait::async_trait; use jsonrpsee::core::RpcResult; -use reth_primitives::{Account, Block, BlockId, BlockNumberOrTag, Bytes, TransactionSigned, H256}; +use reth_primitives::{ + Account, Block, BlockId, BlockNumberOrTag, Bytes, TransactionSigned, H160, H256, +}; use reth_provider::{BlockReaderIdExt, HeaderProvider, StateProviderBox}; use reth_revm::{ database::{State, SubState}, @@ -653,6 +655,213 @@ where Ok(()) } + async fn debug_account_range( + &self, + _block_number: BlockNumberOrTag, + _start: Bytes, + _max_results: u64, + _nocode: bool, + _nostorage: bool, + _incompletes: bool, + ) -> RpcResult<()> { + Ok(()) + } + + async fn debug_block_profile(&self, _file: String, _seconds: u64) -> RpcResult<()> { + Ok(()) + } + + async fn debug_chaindb_compact(&self) -> RpcResult<()> { + Ok(()) + } + + async fn debug_chaindb_property(&self, _property: String) -> RpcResult<()> { + Ok(()) + } + + async fn debug_cpu_profile(&self, _file: String, _seconds: u64) -> RpcResult<()> { + Ok(()) + } + + async fn debug_db_ancient(&self, _kind: String, _number: u64) -> RpcResult<()> { + Ok(()) + } + + async fn debug_db_ancients(&self) -> RpcResult<()> { + Ok(()) + } + + async fn debug_db_get(&self, _key: String) -> RpcResult<()> { + Ok(()) + } + + async fn debug_dump_block(&self, _number: BlockId) -> RpcResult<()> { + Ok(()) + } + + async fn debug_free_os_memory(&self) -> RpcResult<()> { + Ok(()) + } + + async fn debug_freeze_client(&self, _node: String) -> RpcResult<()> { + Ok(()) + } + + async fn debug_gc_stats(&self) -> RpcResult<()> { + Ok(()) + } + + async fn debug_get_accessible_state( + &self, + _from: BlockNumberOrTag, + _to: BlockNumberOrTag, + ) -> RpcResult<()> { + Ok(()) + } + + async fn debug_get_modified_accounts_by_hash( + &self, + _start_hash: H256, + _end_hash: H256, + ) -> RpcResult<()> { + Ok(()) + } + + async fn debug_get_modified_accounts_by_number( + &self, + _start_number: u64, + _end_number: u64, + ) -> RpcResult<()> { + Ok(()) + } + + async fn debug_go_trace(&self, _file: String, _seconds: u64) -> RpcResult<()> { + Ok(()) + } + + async fn debug_intermediate_roots( + &self, + _block_hash: H256, + _opts: Option, + ) -> RpcResult<()> { + Ok(()) + } + + async fn debug_mem_stats(&self) -> RpcResult<()> { + Ok(()) + } + + async fn debug_mutex_profile(&self, _file: String, _nsec: u64) -> RpcResult<()> { + Ok(()) + } + + async fn debug_preimage(&self, _hash: H256) -> RpcResult<()> { + Ok(()) + } + + async fn debug_print_block(&self, _number: u64) -> RpcResult<()> { + Ok(()) + } + + async fn debug_seed_hash(&self, _number: u64) -> RpcResult { + Ok(Default::default()) + } + + async fn debug_set_block_profile_rate(&self, _rate: u64) -> RpcResult<()> { + Ok(()) + } + + async fn debug_set_gc_percent(&self, _v: i32) -> RpcResult<()> { + Ok(()) + } + + async fn debug_set_head(&self, _number: u64) -> RpcResult<()> { + Ok(()) + } + + async fn debug_set_mutex_profile_fraction(&self, _rate: i32) -> RpcResult<()> { + Ok(()) + } + + async fn debug_set_trie_flush_interval(&self, _interval: String) -> RpcResult<()> { + Ok(()) + } + + async fn debug_stacks(&self) -> RpcResult<()> { + Ok(()) + } + + async fn debug_standard_trace_bad_block_to_file( + &self, + _block: BlockNumberOrTag, + _opts: Option, + ) -> RpcResult<()> { + Ok(()) + } + + async fn debug_standard_trace_block_to_file( + &self, + _block: BlockNumberOrTag, + _opts: Option, + ) -> RpcResult<()> { + Ok(()) + } + + async fn debug_start_cpu_profile(&self, _file: String) -> RpcResult<()> { + Ok(()) + } + + async fn debug_start_go_trace(&self, _file: String) -> RpcResult<()> { + Ok(()) + } + + async fn debug_stop_cpu_profile(&self) -> RpcResult<()> { + Ok(()) + } + + async fn debug_stop_go_trace(&self) -> RpcResult<()> { + Ok(()) + } + + async fn debug_storage_range_at( + &self, + _block_hash: H256, + _tx_idx: usize, + _contract_address: H160, + _key_start: H256, + _max_result: u64, + ) -> RpcResult<()> { + Ok(()) + } + + async fn debug_trace_bad_block( + &self, + _block_hash: H256, + _opts: Option, + ) -> RpcResult<()> { + Ok(()) + } + + async fn debug_verbosity(&self, _level: usize) -> RpcResult<()> { + Ok(()) + } + + async fn debug_vmodule(&self, _pattern: String) -> RpcResult<()> { + Ok(()) + } + + async fn debug_write_block_profile(&self, _file: String) -> RpcResult<()> { + Ok(()) + } + + async fn debug_write_mem_profile(&self, _file: String) -> RpcResult<()> { + Ok(()) + } + + async fn debug_write_mutex_profile(&self, _file: String) -> RpcResult<()> { + Ok(()) + } + /// Handler for `debug_getRawBlock` async fn raw_block(&self, block_id: BlockId) -> RpcResult { let block = self.inner.provider.block_by_id(block_id).to_rpc_result()?;