mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-29 09:08:05 -05:00
fix: use serde json value for tracer config (#3154)
This commit is contained in:
@@ -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(),
|
||||
|
||||
@@ -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 <https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers> and <https://geth.ethereum.org/docs/developers/evm-tracing/custom-tracer>
|
||||
@@ -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<CallConfig> {
|
||||
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<serde_json::Value> {
|
||||
match self {
|
||||
GethDebugTracerConfig::JsTracer(cfg) => Some(cfg),
|
||||
_ => None,
|
||||
}
|
||||
/// Consumes the config and tries to deserialize it into the given type.
|
||||
pub fn from_value<T: DeserializeOwned>(self) -> Result<T, serde_json::Error> {
|
||||
serde_json::from_value(self.0)
|
||||
}
|
||||
|
||||
/// Returns the [CallConfig] if it is a call config.
|
||||
pub fn into_call_config(self) -> Result<CallConfig, serde_json::Error> {
|
||||
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<PreStateConfig> {
|
||||
match self {
|
||||
GethDebugTracerConfig::BuiltInTracer(GethDebugBuiltInTracerConfig::PreStateTracer(
|
||||
cfg,
|
||||
)) => Some(cfg),
|
||||
_ => None,
|
||||
}
|
||||
pub fn into_pre_state_config(self) -> Result<PreStateConfig, serde_json::Error> {
|
||||
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<serde_json::Value> 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<GethDebugTracerType>,
|
||||
/// 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 <https://github.com/ethereum/go-ethereum/issues/26513>
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub tracer_config: Option<GethDebugTracerConfig>,
|
||||
///
|
||||
/// 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")]
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user