From 45af6dc504005aafc0165a9aa1ce71811d78b9a5 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Tue, 6 Jun 2023 13:41:08 +0200 Subject: [PATCH] fix: serialize storage map without prefix (#3016) --- Cargo.lock | 52 ++++++++++++++++++- crates/rpc/rpc-types/Cargo.toml | 1 + .../rpc/rpc-types/src/eth/trace/geth/mod.rs | 37 ++++++++++++- 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 98d991ff2..3626c5bbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -500,6 +500,17 @@ dependencies = [ "sha2 0.9.9", ] +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", +] + [[package]] name = "bstr" version = "1.3.0" @@ -847,6 +858,18 @@ dependencies = [ "toml 0.5.11", ] +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "const-oid" version = "0.9.2" @@ -1607,6 +1630,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.32" @@ -2309,7 +2338,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick 0.7.20", - "bstr", + "bstr 1.3.0", "fnv", "log", "regex", @@ -5363,6 +5392,7 @@ dependencies = [ "reth-rlp", "serde", "serde_json", + "similar-asserts", "thiserror", "tokio", ] @@ -6243,6 +6273,26 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "similar" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" +dependencies = [ + "bstr 0.2.17", + "unicode-segmentation", +] + +[[package]] +name = "similar-asserts" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf644ad016b75129f01a34a355dcb8d66a5bc803e417c7a77cc5d5ee9fa0f18" +dependencies = [ + "console", + "similar", +] + [[package]] name = "simple_asn1" version = "0.6.2" diff --git a/crates/rpc/rpc-types/Cargo.toml b/crates/rpc/rpc-types/Cargo.toml index 5bb82d2e8..a4c7f9446 100644 --- a/crates/rpc/rpc-types/Cargo.toml +++ b/crates/rpc/rpc-types/Cargo.toml @@ -34,3 +34,4 @@ reth-interfaces = { path = "../../interfaces", features = ["test-utils"] } # misc rand = "0.8" assert_matches = "1.5" +similar-asserts = "1.4" 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 fe59d1742..4ed006a78 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::{Deserialize, Serialize}; +use serde::{ser::SerializeMap, Deserialize, Serialize, Serializer}; use std::collections::BTreeMap; // re-exports @@ -74,7 +74,11 @@ pub struct StructLog { pub return_data: Option, /// Storage slots of current contract read from and written to. Only emitted for SLOAD and /// SSTORE. Disabled via disableStorage - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde( + default, + skip_serializing_if = "Option::is_none", + serialize_with = "serialize_string_storage_map_opt" + )] pub storage: Option>, /// Current call depth pub depth: u64, @@ -327,6 +331,26 @@ pub struct GethDebugTracingCallOptions { pub block_overrides: Option, } +/// Serializes a storage map as a list of key-value pairs _without_ 0x-prefix +fn serialize_string_storage_map_opt( + storage: &Option>, + s: S, +) -> Result { + match storage { + None => s.serialize_none(), + Some(storage) => { + let mut m = s.serialize_map(Some(storage.len()))?; + for (key, val) in storage.iter() { + let key = format!("{:?}", key); + let val = format!("{:?}", val); + // skip the 0x prefix + m.serialize_entry(&key.as_str()[2..], &val.as_str()[2..])?; + } + m.end() + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -337,4 +361,13 @@ mod tests { let input = include_str!("../../../../test_data/default/structlogs_01.json"); let _frame: DefaultFrame = serde_json::from_str(input).unwrap(); } + + #[test] + fn test_serialize_storage_map() { + let s = r#"{"pc":3349,"op":"SLOAD","gas":23959,"gasCost":2100,"depth":1,"stack":[],"memory":[],"storage":{"6693dabf5ec7ab1a0d1c5bc58451f85d5e44d504c9ffeb75799bfdb61aa2997a":"0000000000000000000000000000000000000000000000000000000000000000"}}"#; + let log: StructLog = serde_json::from_str(s).unwrap(); + let val = serde_json::to_value(&log).unwrap(); + let input = serde_json::from_str::(s).unwrap(); + similar_asserts::assert_eq!(input, val); + } }