diff --git a/crates/rpc/rpc-api/src/debug.rs b/crates/rpc/rpc-api/src/debug.rs index 4a78a635a6..dc594e0275 100644 --- a/crates/rpc/rpc-api/src/debug.rs +++ b/crates/rpc/rpc-api/src/debug.rs @@ -1,6 +1,9 @@ use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; -use reth_primitives::{BlockId, Bytes, H256}; -use reth_rpc_types::RichBlock; +use reth_primitives::{BlockId, BlockNumberOrTag, Bytes, H256}; +use reth_rpc_types::{ + trace::geth::{BlockTraceResult, GethDebugTracingOptions, GethTraceFrame, TraceResult}, + CallRequest, RichBlock, +}; /// Debug rpc interface. #[cfg_attr(not(feature = "client"), rpc(server))] @@ -25,4 +28,75 @@ pub trait DebugApi { /// Returns an array of recent bad blocks that the client has seen on the network. #[method(name = "debug_getBadBlocks")] async fn bad_blocks(&self) -> Result>; + + /// Returns the structured logs created during the execution of EVM between two blocks + /// (excluding start) as a JSON object. + #[method(name = "debug_traceChain")] + async fn debug_trace_chain( + &self, + start_exclusive: BlockNumberOrTag, + end_inclusive: BlockNumberOrTag, + ) -> Result>; + + /// 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 = "debug_traceBlock")] + async fn debug_trace_block( + &self, + rlp_block: Bytes, + opts: GethDebugTracingOptions, + ) -> Result>; + + /// 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 = "debug_traceBlockByHash")] + async fn debug_trace_block_by_hash( + &self, + block: H256, + opts: GethDebugTracingOptions, + ) -> Result>; + + /// Similar to `debug_traceBlockByNumber`, `debug_traceBlockByHash` 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 = "debug_traceBlockByNumber")] + async fn debug_trace_block_by_number( + &self, + block: BlockNumberOrTag, + opts: GethDebugTracingOptions, + ) -> Result>; + + /// 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 = "debug_traceTransaction")] + async fn debug_trace_transaction( + &self, + tx_hash: H256, + opts: GethDebugTracingOptions, + ) -> Result; + + /// 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 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 = "debug_traceCall")] + async fn debug_trace_call( + &self, + request: CallRequest, + block_number: Option, + opts: GethDebugTracingOptions, + ) -> Result; } diff --git a/crates/rpc/rpc-types/src/eth/trace/common.rs b/crates/rpc/rpc-types/src/eth/trace/common.rs new file mode 100644 index 0000000000..78ee088ce2 --- /dev/null +++ b/crates/rpc/rpc-types/src/eth/trace/common.rs @@ -0,0 +1,14 @@ +//! Types used by tracing backends + +use serde::{Deserialize, Serialize}; + +/// The result of a single transaction trace. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +#[allow(missing_docs)] +pub enum TraceResult { + /// Untagged success variant + Success { result: Ok }, + /// Untagged error variant + Error { error: Err }, +} diff --git a/crates/rpc/rpc-types/src/eth/trace/geth.rs b/crates/rpc/rpc-types/src/eth/trace/geth.rs new file mode 100644 index 0000000000..6e38ba81f3 --- /dev/null +++ b/crates/rpc/rpc-types/src/eth/trace/geth.rs @@ -0,0 +1,59 @@ +#![allow(missing_docs)] +/// Geth tracing types +use reth_primitives::{Bytes, JsonU256, H256, U256}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +// re-exported for geth tracing types +pub use ethers_core::types::{GethDebugTracingOptions, GethTraceFrame}; + +/// Result type for geth style transaction trace +pub type TraceResult = crate::trace::common::TraceResult; + +/// blockTraceResult represents the results of tracing a single block when an entire chain is being +/// traced. ref +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct BlockTraceResult { + /// Block number corresponding to the trace task + pub block: U256, + /// Block hash corresponding to the trace task + pub hash: H256, + /// Trace results produced by the trace task + pub traces: Vec, +} + +/// Geth Default trace frame +/// +/// +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct DefaultFrame { + pub failed: bool, + pub gas: JsonU256, + pub return_value: Bytes, + pub struct_logs: Vec, +} + +/// Represents a struct log entry in a trace +/// +/// +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct StructLog { + pub depth: u64, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub error: Option, + pub gas: u64, + #[serde(rename = "gasCost")] + pub gas_cost: u64, + /// ref + #[serde(default, skip_serializing_if = "Option::is_none")] + pub memory: Option>, + pub op: String, + pub pc: u64, + #[serde(default, rename = "refund", skip_serializing_if = "Option::is_none")] + pub refund_counter: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub stack: Option>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub storage: Option>, +} diff --git a/crates/rpc/rpc-types/src/eth/trace/mod.rs b/crates/rpc/rpc-types/src/eth/trace/mod.rs index cc07e21cb3..d4ec6960f0 100644 --- a/crates/rpc/rpc-types/src/eth/trace/mod.rs +++ b/crates/rpc/rpc-types/src/eth/trace/mod.rs @@ -1,52 +1,6 @@ //! Types for tracing +pub mod common; pub mod filter; +pub mod geth; pub mod parity; - -/// Geth tracing types -pub mod geth { - #![allow(missing_docs)] - - use reth_primitives::{Bytes, JsonU256, H256, U256}; - use serde::{Deserialize, Serialize}; - use std::collections::BTreeMap; - - // re-exported for geth tracing types - pub use ethers_core::types::GethDebugTracingOptions; - - /// Geth Default trace frame - /// - /// - #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] - #[serde(rename_all = "camelCase")] - pub struct DefaultFrame { - pub failed: bool, - pub gas: JsonU256, - pub return_value: Bytes, - pub struct_logs: Vec, - } - - /// Represents a struct log entry in a trace - /// - /// - #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] - pub struct StructLog { - pub depth: u64, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub error: Option, - pub gas: u64, - #[serde(rename = "gasCost")] - pub gas_cost: u64, - /// ref - #[serde(default, skip_serializing_if = "Option::is_none")] - pub memory: Option>, - pub op: String, - pub pc: u64, - #[serde(default, rename = "refund", skip_serializing_if = "Option::is_none")] - pub refund_counter: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub stack: Option>, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub storage: Option>, - } -} diff --git a/crates/rpc/rpc-types/src/eth/trace/parity.rs b/crates/rpc/rpc-types/src/eth/trace/parity.rs index 174f1f13d7..14df580898 100644 --- a/crates/rpc/rpc-types/src/eth/trace/parity.rs +++ b/crates/rpc/rpc-types/src/eth/trace/parity.rs @@ -7,6 +7,9 @@ use reth_primitives::{Address, Bytes, H256, U256, U64}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; +/// Result type for parity style transaction trace +pub type TraceResult = crate::trace::common::TraceResult; + #[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub enum TraceType { @@ -171,13 +174,6 @@ pub enum TraceOutput { Create(CreateOutput), } -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -pub enum TraceResult { - Success { result: TraceOutput }, - Error { error: String }, -} - #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TransactionTrace { diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index de3d11398c..3fc9c23c46 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -1,9 +1,12 @@ use crate::{result::internal_rpc_err, EthApiSpec}; use async_trait::async_trait; -use jsonrpsee::core::RpcResult as Result; -use reth_primitives::{BlockId, Bytes, H256}; +use jsonrpsee::core::RpcResult; +use reth_primitives::{BlockId, BlockNumberOrTag, Bytes, H256}; use reth_rpc_api::DebugApiServer; -use reth_rpc_types::RichBlock; +use reth_rpc_types::{ + trace::geth::{BlockTraceResult, GethDebugTracingOptions, GethTraceFrame, TraceResult}, + CallRequest, RichBlock, +}; /// `debug` API implementation. /// @@ -28,24 +31,79 @@ impl DebugApiServer for DebugApi where Eth: EthApiSpec + 'static, { - async fn raw_header(&self, _block_id: BlockId) -> Result { + async fn raw_header(&self, _block_id: BlockId) -> RpcResult { Err(internal_rpc_err("unimplemented")) } - async fn raw_block(&self, _block_id: BlockId) -> Result { + async fn raw_block(&self, _block_id: BlockId) -> RpcResult { Err(internal_rpc_err("unimplemented")) } /// Returns the bytes of the transaction for the given hash. - async fn raw_transaction(&self, _hash: H256) -> Result { + async fn raw_transaction(&self, _hash: H256) -> RpcResult { Err(internal_rpc_err("unimplemented")) } - async fn raw_receipts(&self, _block_id: BlockId) -> Result> { + async fn raw_receipts(&self, _block_id: BlockId) -> RpcResult> { Err(internal_rpc_err("unimplemented")) } - async fn bad_blocks(&self) -> Result> { + async fn bad_blocks(&self) -> RpcResult> { + Err(internal_rpc_err("unimplemented")) + } + + /// Handler for `debug_traceChain` + async fn debug_trace_chain( + &self, + _start_exclusive: BlockNumberOrTag, + _end_inclusive: BlockNumberOrTag, + ) -> RpcResult> { + Err(internal_rpc_err("unimplemented")) + } + + /// Handler for `debug_traceBlock` + async fn debug_trace_block( + &self, + _rlp_block: Bytes, + _opts: GethDebugTracingOptions, + ) -> RpcResult> { + Err(internal_rpc_err("unimplemented")) + } + + /// Handler for `debug_traceBlockByHash` + async fn debug_trace_block_by_hash( + &self, + _block: H256, + _opts: GethDebugTracingOptions, + ) -> RpcResult> { + Err(internal_rpc_err("unimplemented")) + } + + /// Handler for `debug_traceBlockByNumber` + async fn debug_trace_block_by_number( + &self, + _block: BlockNumberOrTag, + _opts: GethDebugTracingOptions, + ) -> RpcResult> { + Err(internal_rpc_err("unimplemented")) + } + + /// Handler for `debug_traceTransaction` + async fn debug_trace_transaction( + &self, + _tx_hash: H256, + _opts: GethDebugTracingOptions, + ) -> RpcResult { + Err(internal_rpc_err("unimplemented")) + } + + /// Handler for `debug_traceCall` + async fn debug_trace_call( + &self, + _request: CallRequest, + _block_number: Option, + _opts: GethDebugTracingOptions, + ) -> RpcResult { Err(internal_rpc_err("unimplemented")) } }