mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-08 03:01:12 -04:00
feat(rpc): impl debug_traceCall (#2090)
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use reth_rpc_types::trace::geth::GethDefaultTracingOptions;
|
||||
|
||||
/// Gives guidance to the [TracingInspector](crate::tracing::TracingInspector).
|
||||
///
|
||||
/// Use [TracingInspectorConfig::default_parity] or [TracingInspectorConfig::default_geth] to get
|
||||
@@ -49,6 +51,16 @@ impl TracingInspectorConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a config for geth style traces based on the given [GethDefaultTracingOptions].
|
||||
pub fn from_geth_config(config: &GethDefaultTracingOptions) -> Self {
|
||||
Self {
|
||||
record_memory_snapshots: config.enable_memory.unwrap_or_default(),
|
||||
record_stack_snapshots: !config.disable_stack.unwrap_or_default(),
|
||||
record_state_diff: !config.disable_storage.unwrap_or_default(),
|
||||
..Self::default_geth()
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure whether individual opcode level steps should be recorded
|
||||
pub fn set_steps(mut self, record_steps: bool) -> Self {
|
||||
self.record_steps = record_steps;
|
||||
|
||||
@@ -16,6 +16,7 @@ use reth_revm::{
|
||||
env::tx_env_with_recovered,
|
||||
tracing::{TracingInspector, TracingInspectorConfig},
|
||||
};
|
||||
use reth_rlp::Encodable;
|
||||
use reth_rpc_api::DebugApiServer;
|
||||
use reth_rpc_types::{
|
||||
trace::geth::{
|
||||
@@ -107,10 +108,7 @@ where
|
||||
}
|
||||
|
||||
// default structlog tracer
|
||||
let inspector_config = TracingInspectorConfig::default_geth()
|
||||
.set_memory_snapshots(config.enable_memory.unwrap_or_default())
|
||||
.set_stack_snapshots(!config.disable_stack.unwrap_or_default())
|
||||
.set_state_diffs(!config.disable_storage.unwrap_or_default());
|
||||
let inspector_config = TracingInspectorConfig::from_geth_config(&config);
|
||||
|
||||
let mut inspector = TracingInspector::new(inspector_config);
|
||||
|
||||
@@ -122,9 +120,33 @@ where
|
||||
Ok(frame.into())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
use reth_rlp::Encodable;
|
||||
/// 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.
|
||||
pub async fn debug_trace_call(
|
||||
&self,
|
||||
call: CallRequest,
|
||||
block_id: Option<BlockId>,
|
||||
opts: GethDebugTracingOptions,
|
||||
) -> EthResult<GethTraceFrame> {
|
||||
let at = block_id.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest));
|
||||
|
||||
let GethDebugTracingOptions { config, .. } = opts;
|
||||
// TODO(mattsse) support non default tracers
|
||||
|
||||
// default structlog tracer
|
||||
let inspector_config = TracingInspectorConfig::from_geth_config(&config);
|
||||
|
||||
let mut inspector = TracingInspector::new(inspector_config);
|
||||
|
||||
let (res, _) = self.eth_api.inspect_call_at(call, at, None, &mut inspector).await?;
|
||||
let gas_used = res.result.gas_used();
|
||||
|
||||
let frame = inspector.into_geth_builder().geth_traces(U256::from(gas_used), config);
|
||||
|
||||
Ok(frame.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<Client, Eth> DebugApiServer for DebugApi<Client, Eth>
|
||||
@@ -250,11 +272,11 @@ where
|
||||
/// Handler for `debug_traceCall`
|
||||
async fn debug_trace_call(
|
||||
&self,
|
||||
_request: CallRequest,
|
||||
_block_number: Option<BlockId>,
|
||||
_opts: GethDebugTracingOptions,
|
||||
request: CallRequest,
|
||||
block_number: Option<BlockId>,
|
||||
opts: GethDebugTracingOptions,
|
||||
) -> RpcResult<GethTraceFrame> {
|
||||
Err(internal_rpc_err("unimplemented"))
|
||||
Ok(DebugApi::debug_trace_call(self, request, block_number, opts).await?)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ pub trait EthTransactions: Send + Sync {
|
||||
fn state_at(&self, at: BlockId) -> EthResult<StateProviderBox<'_>>;
|
||||
|
||||
/// Executes the closure with the state that corresponds to the given [BlockId].
|
||||
fn with_state_at<F, T>(&self, _at: BlockId, _f: F) -> EthResult<T>
|
||||
fn with_state_at<F, T>(&self, at: BlockId, f: F) -> EthResult<T>
|
||||
where
|
||||
F: FnOnce(StateProviderBox<'_>) -> EthResult<T>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user