feat(rpc): impl debug_traceCall (#2090)

This commit is contained in:
Matthias Seitz
2023-04-03 17:47:22 +02:00
committed by GitHub
parent 72c66e4cb8
commit 60f392b6a7
3 changed files with 45 additions and 11 deletions

View File

@@ -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;

View File

@@ -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?)
}
}

View File

@@ -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>;