From 724ec1b5cc4148029181d2d29c4f29e57e6b3878 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Tue, 21 Mar 2023 22:36:06 +0100 Subject: [PATCH] fix: parse 66 blockid str as hash (#1890) --- Cargo.lock | 5 ++-- crates/primitives/src/block.rs | 21 ++++++++++++++++- crates/rpc/rpc-builder/Cargo.toml | 1 + crates/rpc/rpc-builder/tests/it/main.rs | 1 + crates/rpc/rpc-builder/tests/it/serde.rs | 29 ++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 crates/rpc/rpc-builder/tests/it/serde.rs diff --git a/Cargo.lock b/Cargo.lock index cd3fa3789e..ca2fdbe171 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5184,6 +5184,7 @@ dependencies = [ "reth-tracing", "reth-transaction-pool", "serde", + "serde_json", "strum", "thiserror", "tokio", @@ -5836,9 +5837,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ "itoa", "ryu", diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index d2bf7aa6c2..2a17046291 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -328,7 +328,14 @@ impl<'de> Deserialize<'de> for BlockId { where E: serde::de::Error, { - Ok(BlockId::Number(v.parse().map_err(serde::de::Error::custom)?)) + // Since there is no way to clearly distinguish between a DATA parameter and a QUANTITY parameter. A str is therefor deserialized into a Block Number: + // However, since the hex string should be a QUANTITY, we can safely assume that if the len is 66 bytes, it is in fact a hash, ref + if v.len() == 66 { + Ok(BlockId::Hash(v.parse::().map_err(serde::de::Error::custom)?.into())) + } else { + // quantity hex string or tag + Ok(BlockId::Number(v.parse().map_err(serde::de::Error::custom)?)) + } } fn visit_map(self, mut map: A) -> Result @@ -623,6 +630,7 @@ impl BlockBody { #[cfg(test)] mod test { use super::{BlockId, BlockNumberOrTag::*, *}; + /// Check parsing according to EIP-1898. #[test] fn can_parse_blockid_u64() { @@ -684,6 +692,7 @@ mod test { assert_eq!(deserialized, *block_id) } } + #[test] fn serde_blockid_number() { let block_id = BlockId::from(100u64); @@ -691,6 +700,7 @@ mod test { let deserialized: BlockId = serde_json::from_str(&serialized).unwrap(); assert_eq!(deserialized, block_id) } + #[test] fn serde_blockid_hash() { let block_id = BlockId::from(H256::default()); @@ -698,6 +708,15 @@ mod test { let deserialized: BlockId = serde_json::from_str(&serialized).unwrap(); assert_eq!(deserialized, block_id) } + + #[test] + fn serde_blockid_hash_from_str() { + let val = "\"0x898753d8fdd8d92c1907ca21e68c7970abd290c647a202091181deec3f30a0b2\""; + let block_hash: H256 = serde_json::from_str(val).unwrap(); + let block_id: BlockId = serde_json::from_str(val).unwrap(); + assert_eq!(block_id, BlockId::Hash(block_hash.into())); + } + #[test] fn serde_rpc_payload_block_tag() { let payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},"latest"],"id":1,"jsonrpc":"2.0"}"#; diff --git a/crates/rpc/rpc-builder/Cargo.toml b/crates/rpc/rpc-builder/Cargo.toml index 6f9e41a588..465bdc3510 100644 --- a/crates/rpc/rpc-builder/Cargo.toml +++ b/crates/rpc/rpc-builder/Cargo.toml @@ -36,3 +36,4 @@ reth-provider = { path = "../../storage/provider", features = ["test-utils"] } reth-network-api = { path = "../../net/network-api", features = ["test-utils"] } tokio = { version = "1", features = ["rt", "rt-multi-thread"] } +serde_json = "1.0.94" diff --git a/crates/rpc/rpc-builder/tests/it/main.rs b/crates/rpc/rpc-builder/tests/it/main.rs index 9a2b956c07..6d50765815 100644 --- a/crates/rpc/rpc-builder/tests/it/main.rs +++ b/crates/rpc/rpc-builder/tests/it/main.rs @@ -1,4 +1,5 @@ mod http; +mod serde; pub mod utils; fn main() {} diff --git a/crates/rpc/rpc-builder/tests/it/serde.rs b/crates/rpc/rpc-builder/tests/it/serde.rs new file mode 100644 index 0000000000..95babda1b3 --- /dev/null +++ b/crates/rpc/rpc-builder/tests/it/serde.rs @@ -0,0 +1,29 @@ +//! various serde test +use crate::utils::launch_http; +use jsonrpsee::{ + core::{client::ClientT, traits::ToRpcParams, Error}, + types::Request, +}; +use reth_primitives::U256; +use reth_rpc_builder::RethRpcModule; +use serde_json::value::RawValue; + +struct RawRpcParams(Box); + +impl ToRpcParams for RawRpcParams { + fn to_rpc_params(self) -> Result>, Error> { + Ok(Some(self.0)) + } +} + +#[tokio::test(flavor = "multi_thread")] +async fn test_eth_balance_serde() { + let handle = launch_http(vec![RethRpcModule::Eth]).await; + let s = r#"{"jsonrpc":"2.0","id":1,"method":"eth_getBalance","params":["0xaa00000000000000000000000000000000000000","0x898753d8fdd8d92c1907ca21e68c7970abd290c647a202091181deec3f30a0b2"]}"#; + let req: Request = serde_json::from_str(s).unwrap(); + let client = handle.http_client().unwrap(); + + let params = RawRpcParams(RawValue::from_string(req.params.unwrap().to_string()).unwrap()); + + client.request::("eth_getBalance", params).await.unwrap(); +}