Skip to content
22 changes: 22 additions & 0 deletions crates/rpc/src/config/rpc_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ pub struct StorageRpcConfig {
/// Default: `25`.
pub max_tracing_requests: usize,

/// Maximum block range for `trace_filter` queries.
///
/// Default: `100`.
pub max_trace_filter_blocks: u64,

/// Time-to-live for stale filters and subscriptions.
///
/// Default: `5 minutes`.
Expand Down Expand Up @@ -136,6 +141,7 @@ impl Default for StorageRpcConfig {
max_logs_per_response: 20_000,
max_log_query_deadline: Duration::from_secs(10),
max_tracing_requests: 25,
max_trace_filter_blocks: 100,
stale_filter_ttl: Duration::from_secs(5 * 60),
gas_oracle_block_count: 20,
gas_oracle_percentile: 60.0,
Expand Down Expand Up @@ -188,6 +194,12 @@ impl StorageRpcConfigBuilder {
self
}

/// Set the max block range for trace_filter.
pub const fn max_trace_filter_blocks(mut self, max: u64) -> Self {
self.inner.max_trace_filter_blocks = max;
self
}

/// Set the time-to-live for stale filters and subscriptions.
pub const fn stale_filter_ttl(mut self, ttl: Duration) -> Self {
self.inner.stale_filter_ttl = ttl;
Expand Down Expand Up @@ -298,6 +310,13 @@ pub struct StorageRpcConfigEnv {
optional
)]
max_tracing_requests: Option<u64>,
/// Maximum block range for trace_filter queries.
#[from_env(
var = "SIGNET_RPC_MAX_TRACE_FILTER_BLOCKS",
desc = "Maximum block range for trace_filter queries",
optional
)]
max_trace_filter_blocks: Option<u64>,
/// Filter TTL in seconds.
#[from_env(
var = "SIGNET_RPC_STALE_FILTER_TTL_SECS",
Expand Down Expand Up @@ -385,6 +404,9 @@ impl From<StorageRpcConfigEnv> for StorageRpcConfig {
max_tracing_requests: env
.max_tracing_requests
.map_or(defaults.max_tracing_requests, |v| v as usize),
max_trace_filter_blocks: env
.max_trace_filter_blocks
.unwrap_or(defaults.max_trace_filter_blocks),
stale_filter_ttl: env
.stale_filter_ttl_secs
.map_or(defaults.stale_filter_ttl, Duration::from_secs),
Expand Down
77 changes: 72 additions & 5 deletions crates/rpc/src/debug/tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
//! Largely adapted from reth: `crates/rpc/rpc/src/debug.rs`.

use crate::debug::DebugError;
use alloy::rpc::types::{
TransactionInfo,
trace::geth::{
FourByteFrame, GethDebugBuiltInTracerType, GethDebugTracerConfig, GethDebugTracerType,
GethDebugTracingOptions, GethTrace, NoopFrame,
use alloy::{
primitives::map::HashSet,
rpc::types::{
TransactionInfo,
trace::{
geth::{
FourByteFrame, GethDebugBuiltInTracerType, GethDebugTracerConfig,
GethDebugTracerType, GethDebugTracingOptions, GethTrace, NoopFrame,
},
parity::{LocalizedTransactionTrace, TraceResults, TraceType},
},
},
};
use revm_inspectors::tracing::{
Expand Down Expand Up @@ -197,6 +203,67 @@ where
Ok((frame.into(), trevm))
}

/// Trace a transaction and return Parity-format localized traces.
///
/// Used by `trace_block`, `trace_transaction`, `trace_get`, and
/// `trace_filter`.
pub(crate) fn trace_parity_localized<Db, Insp>(
trevm: EvmReady<Db, Insp>,
tx_info: TransactionInfo,
) -> Result<(Vec<LocalizedTransactionTrace>, EvmNeedsTx<Db, Insp>), DebugError>
where
Db: Database + DatabaseCommit + DatabaseRef,
Insp: Inspector<Ctx<Db>>,
{
let gas_limit = trevm.gas_limit();
let mut inspector = TracingInspector::new(TracingInspectorConfig::default_parity());
let trevm = trevm
.try_with_inspector(&mut inspector, |trevm| trevm.run())
.map_err(|err| DebugError::EvmHalt { reason: err.into_error().to_string() })?;

let traces = inspector
.with_transaction_gas_limit(gas_limit)
.into_parity_builder()
.into_localized_transaction_traces(tx_info);

Ok((traces, trevm.accept_state()))
}

/// Trace a transaction and return Parity-format [`TraceResults`].
///
/// When [`TraceType::StateDiff`] is in `trace_types`, the state diff is
/// enriched with pre-transaction balance/nonce from the database.
///
/// Used by `trace_replayBlockTransactions`, `trace_call`,
/// `trace_callMany`, and `trace_rawTransaction`.
pub(crate) fn trace_parity_replay<Db, Insp>(
trevm: EvmReady<Db, Insp>,
trace_types: &HashSet<TraceType>,
) -> Result<(TraceResults, EvmNeedsTx<Db, Insp>), DebugError>
where
Db: Database + DatabaseCommit + DatabaseRef,
<Db as DatabaseRef>::Error: std::fmt::Debug,
Insp: Inspector<Ctx<Db>>,
{
let mut inspector =
TracingInspector::new(TracingInspectorConfig::from_parity_config(trace_types));
let trevm = trevm
.try_with_inspector(&mut inspector, |trevm| trevm.run())
.map_err(|err| DebugError::EvmHalt { reason: err.into_error().to_string() })?;

let (result, mut trevm) = trevm.take_result_and_state();

let trace_res = inspector
.into_parity_builder()
.into_trace_results_with_state(&result, trace_types, trevm.inner_mut_unchecked().db_mut())
.map_err(|e| DebugError::EvmHalt { reason: format!("state diff: {e:?}") })?;

// Equivalent to `trevm.accept_state()`.
trevm.inner_mut_unchecked().db_mut().commit(result.state);

Ok((trace_res, trevm))
}

// Some code in this file has been copied and modified from reth
// <https://github.com/paradigmxyz/reth>
// The original license is included below:
Expand Down
8 changes: 6 additions & 2 deletions crates/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub use interest::{ChainEvent, NewBlockNotification, RemovedBlock, ReorgNotifica
mod debug;
pub use debug::DebugError;

mod trace;
pub use trace::TraceError;

mod signet;
pub use signet::error::SignetError;

Expand All @@ -34,8 +37,8 @@ mod web3;
pub mod serve;
pub use serve::{RpcServerGuard, ServeConfig, ServeConfigEnv, ServeError};

/// Instantiate a combined router with `eth`, `debug`, `signet`, `web3`, and
/// `net` namespaces.
/// Instantiate a combined router with `eth`, `debug`, `trace`, `signet`,
/// `web3`, and `net` namespaces.
pub fn router<H>() -> ajj::Router<StorageRpcCtx<H>>
where
H: signet_hot::HotKv + Send + Sync + 'static,
Expand All @@ -44,6 +47,7 @@ where
ajj::Router::new()
.nest("eth", eth::eth())
.nest("debug", debug::debug())
.nest("trace", trace::trace())
.nest("signet", signet::signet())
.nest("web3", web3::web3())
.nest("net", net::net())
Expand Down
Loading