diff --git a/crates/rpc/rpc-types/src/eth/trace/geth/call.rs b/crates/rpc/rpc-types/src/eth/trace/geth/call.rs index b38737b145..8af626d115 100644 --- a/crates/rpc/rpc-types/src/eth/trace/geth/call.rs +++ b/crates/rpc/rpc-types/src/eth/trace/geth/call.rs @@ -68,9 +68,9 @@ mod tests { opts.tracing_options.tracer = Some(GethDebugTracerType::BuiltInTracer(GethDebugBuiltInTracerType::CallTracer)); opts.tracing_options.tracer_config = - Some(GethDebugTracerConfig::BuiltInTracer(GethDebugBuiltInTracerConfig::CallTracer( - CallConfig { only_top_call: Some(true), with_log: Some(true) }, - ))); + serde_json::to_value(CallConfig { only_top_call: Some(true), with_log: Some(true) }) + .unwrap() + .into(); assert_eq!( serde_json::to_string(&opts).unwrap(), diff --git a/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs b/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs index 05c6e1d9f9..526c9dc1fc 100644 --- a/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs +++ b/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs @@ -3,7 +3,7 @@ use crate::{state::StateOverride, BlockOverrides}; use reth_primitives::{Bytes, H256, U256}; -use serde::{ser::SerializeMap, Deserialize, Serialize, Serializer}; +use serde::{de::DeserializeOwned, ser::SerializeMap, Deserialize, Serialize, Serializer}; use std::collections::BTreeMap; // re-exports @@ -183,30 +183,6 @@ pub enum GethDebugBuiltInTracerType { NoopTracer, } -/// Configuration for the builtin tracer -#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] -#[serde(untagged)] -pub enum GethDebugBuiltInTracerConfig { - CallTracer(CallConfig), - PreStateTracer(PreStateConfig), -} - -// === impl GethDebugBuiltInTracerConfig === - -impl GethDebugBuiltInTracerConfig { - /// Returns true if the config matches the given tracer - pub fn matches_tracer(&self, tracer: &GethDebugBuiltInTracerType) -> bool { - matches!( - (self, tracer), - (GethDebugBuiltInTracerConfig::CallTracer(_), GethDebugBuiltInTracerType::CallTracer,) | - ( - GethDebugBuiltInTracerConfig::PreStateTracer(_), - GethDebugBuiltInTracerType::PreStateTracer, - ) - ) - } -} - /// Available tracers /// /// See and @@ -220,61 +196,45 @@ pub enum GethDebugTracerType { } /// Configuration of the tracer -#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] -#[serde(untagged)] -pub enum GethDebugTracerConfig { - /// built-in tracer - BuiltInTracer(GethDebugBuiltInTracerConfig), - /// custom JS tracer - JsTracer(serde_json::Value), -} +/// +/// This is a simple wrapper around serde_json::Value. +/// with helpers for deserializing tracer configs. +#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)] +#[serde(transparent)] +pub struct GethDebugTracerConfig(pub serde_json::Value); // === impl GethDebugTracerConfig === impl GethDebugTracerConfig { - /// Returns the [CallConfig] if it is a call config. - pub fn into_call_config(self) -> Option { - match self { - GethDebugTracerConfig::BuiltInTracer(GethDebugBuiltInTracerConfig::CallTracer(cfg)) => { - Some(cfg) - } - _ => None, - } + /// Returns if this is a null object + pub fn is_null(&self) -> bool { + self.0.is_null() } - /// Returns the json config if this config is a JS tracer. - pub fn into_js_config(self) -> Option { - match self { - GethDebugTracerConfig::JsTracer(cfg) => Some(cfg), - _ => None, - } + /// Consumes the config and tries to deserialize it into the given type. + pub fn from_value(self) -> Result { + serde_json::from_value(self.0) + } + + /// Returns the [CallConfig] if it is a call config. + pub fn into_call_config(self) -> Result { + self.from_value() + } + + /// Returns the raw json value + pub fn into_json(self) -> serde_json::Value { + self.0 } /// Returns the [PreStateConfig] if it is a call config. - pub fn into_pre_state_config(self) -> Option { - match self { - GethDebugTracerConfig::BuiltInTracer(GethDebugBuiltInTracerConfig::PreStateTracer( - cfg, - )) => Some(cfg), - _ => None, - } + pub fn into_pre_state_config(self) -> Result { + self.from_value() } +} - /// Returns true if the config matches the given tracer - pub fn matches_tracer(&self, tracer: &GethDebugTracerType) -> bool { - match (self, tracer) { - (_, GethDebugTracerType::BuiltInTracer(tracer)) => self.matches_builtin_tracer(tracer), - (GethDebugTracerConfig::JsTracer(_), GethDebugTracerType::JsTracer(_)) => true, - _ => false, - } - } - - /// Returns true if the config matches the given tracer - pub fn matches_builtin_tracer(&self, tracer: &GethDebugBuiltInTracerType) -> bool { - match (self, tracer) { - (GethDebugTracerConfig::BuiltInTracer(config), tracer) => config.matches_tracer(tracer), - (GethDebugTracerConfig::JsTracer(_), _) => false, - } +impl From for GethDebugTracerConfig { + fn from(value: serde_json::Value) -> Self { + GethDebugTracerConfig(value) } } @@ -291,10 +251,16 @@ pub struct GethDebugTracingOptions { /// If `None` then the default structlog tracer is used. #[serde(default, skip_serializing_if = "Option::is_none")] pub tracer: Option, + /// Config specific to given `tracer`. + /// + /// Note default struct logger config are historically embedded in main object. + /// /// tracerConfig is slated for Geth v1.11.0 /// See - #[serde(default, skip_serializing_if = "Option::is_none")] - pub tracer_config: Option, + /// + /// This could be [CallConfig] or [PreStateConfig] depending on the tracer. + #[serde(default, skip_serializing_if = "GethDebugTracerConfig::is_null")] + pub tracer_config: GethDebugTracerConfig, /// A string of decimal integers that overrides the JavaScript-based tracing calls default /// timeout of 5 seconds. #[serde(default, skip_serializing_if = "Option::is_none")] diff --git a/crates/rpc/rpc-types/src/eth/trace/geth/pre_state.rs b/crates/rpc/rpc-types/src/eth/trace/geth/pre_state.rs index e8bde9fbd8..fc53ecfa7b 100644 --- a/crates/rpc/rpc-types/src/eth/trace/geth/pre_state.rs +++ b/crates/rpc/rpc-types/src/eth/trace/geth/pre_state.rs @@ -62,9 +62,8 @@ mod tests { opts.tracing_options.config.disable_storage = Some(false); opts.tracing_options.tracer = Some(GethDebugTracerType::BuiltInTracer(GethDebugBuiltInTracerType::PreStateTracer)); - opts.tracing_options.tracer_config = Some(GethDebugTracerConfig::BuiltInTracer( - GethDebugBuiltInTracerConfig::PreStateTracer(PreStateConfig { diff_mode: Some(true) }), - )); + opts.tracing_options.tracer_config = + serde_json::to_value(PreStateConfig { diff_mode: Some(true) }).unwrap().into(); assert_eq!( serde_json::to_string(&opts).unwrap(), diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 76911cb6f7..8a44d16984 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -268,13 +268,6 @@ where let GethDebugTracingOptions { config, tracer, tracer_config, .. } = tracing_options; if let Some(tracer) = tracer { - // valid matching config - if let Some(ref config) = tracer_config { - if !config.matches_tracer(&tracer) { - return Err(EthApiError::InvalidTracerConfig) - } - } - return match tracer { GethDebugTracerType::BuiltInTracer(tracer) => match tracer { GethDebugBuiltInTracerType::FourByteTracer => { @@ -287,9 +280,9 @@ where return Ok(FourByteFrame::from(inspector).into()) } GethDebugBuiltInTracerType::CallTracer => { - // we validated the config above - let call_config = - tracer_config.and_then(|c| c.into_call_config()).unwrap_or_default(); + let call_config = tracer_config + .into_call_config() + .map_err(|_| EthApiError::InvalidTracerConfig)?; let mut inspector = TracingInspector::new( TracingInspectorConfig::from_geth_config(&config), @@ -311,7 +304,7 @@ where GethDebugBuiltInTracerType::NoopTracer => Ok(NoopFrame::default().into()), }, GethDebugTracerType::JsTracer(code) => { - let config = tracer_config.and_then(|c| c.into_js_config()).unwrap_or_default(); + let config = tracer_config.into_json(); // for JS tracing we need to setup all async work before we can start tracing // because JSTracer and all JS types are not Send @@ -360,13 +353,6 @@ where let GethDebugTracingOptions { config, tracer, tracer_config, .. } = opts; if let Some(tracer) = tracer { - // valid matching config - if let Some(ref config) = tracer_config { - if !config.matches_tracer(&tracer) { - return Err(EthApiError::InvalidTracerConfig) - } - } - return match tracer { GethDebugTracerType::BuiltInTracer(tracer) => match tracer { GethDebugBuiltInTracerType::FourByteTracer => { @@ -375,9 +361,9 @@ where return Ok((FourByteFrame::from(inspector).into(), res.state)) } GethDebugBuiltInTracerType::CallTracer => { - // we validated the config above - let call_config = - tracer_config.and_then(|c| c.into_call_config()).unwrap_or_default(); + let call_config = tracer_config + .into_call_config() + .map_err(|_| EthApiError::InvalidTracerConfig)?; let mut inspector = TracingInspector::new( TracingInspectorConfig::from_geth_config(&config), @@ -397,7 +383,7 @@ where } }, GethDebugTracerType::JsTracer(code) => { - let config = tracer_config.and_then(|c| c.into_js_config()).unwrap_or_default(); + let config = tracer_config.into_json(); // we spawn the database service that will be used by the JS tracer // TODO(mattsse) this is not quite accurate when tracing a block inside a