diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 4685244ccb..722ce553c2 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -24,7 +24,6 @@ mod hardfork; mod header; mod hex_bytes; mod integer_list; -mod jsonu256; mod log; mod net; mod peer; @@ -53,11 +52,11 @@ pub use hardfork::Hardfork; pub use header::{Head, Header, HeadersDirection, SealedHeader}; pub use hex_bytes::Bytes; pub use integer_list::IntegerList; -pub use jsonu256::JsonU256; pub use log::Log; pub use net::NodeRecord; pub use peer::{PeerId, WithPeerId}; pub use receipt::Receipt; +pub use serde_helper::JsonU256; pub use storage::{StorageEntry, StorageTrieEntry}; pub use transaction::{ AccessList, AccessListItem, FromRecoveredTransaction, IntoRecoveredTransaction, Signature, @@ -109,9 +108,7 @@ pub mod utils { } /// Helpers for working with serde -pub mod serde_helper { - pub use crate::jsonu256::deserialize_json_u256; -} +pub mod serde_helper; /// Returns the keccak256 hash for the given data. #[inline] diff --git a/crates/primitives/src/jsonu256.rs b/crates/primitives/src/serde_helper/jsonu256.rs similarity index 100% rename from crates/primitives/src/jsonu256.rs rename to crates/primitives/src/serde_helper/jsonu256.rs diff --git a/crates/primitives/src/serde_helper/mod.rs b/crates/primitives/src/serde_helper/mod.rs new file mode 100644 index 0000000000..7efbed1dac --- /dev/null +++ b/crates/primitives/src/serde_helper/mod.rs @@ -0,0 +1,45 @@ +//! Various serde utilities + +mod jsonu256; +pub use jsonu256::*; + +/// serde functions for handling primitive `u64` as [U64](crate::U64) +pub mod u64_hex { + use crate::U64; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + /// Deserializes an `u64` from [U64] accepting a hex quantity string with optional 0x prefix + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + U64::deserialize(deserializer).map(|val| val.as_u64()) + } + + /// Serializes u64 as hex string + pub fn serialize(value: &u64, s: S) -> Result { + U64::from(*value).serialize(s) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use serde::{Deserialize, Serialize}; + + #[test] + fn test_hex_u64() { + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct Value { + #[serde(with = "u64_hex")] + inner: u64, + } + + let val = Value { inner: 1000 }; + let s = serde_json::to_string(&val).unwrap(); + assert_eq!(s, "{\"inner\":\"0x3e8\"}"); + + let deserialized: Value = serde_json::from_str(&s).unwrap(); + assert_eq!(val, deserialized); + } +} diff --git a/crates/primitives/src/withdrawal.rs b/crates/primitives/src/withdrawal.rs index ae49d3a38d..f94175f8f0 100644 --- a/crates/primitives/src/withdrawal.rs +++ b/crates/primitives/src/withdrawal.rs @@ -1,4 +1,4 @@ -use crate::{constants::GWEI_TO_WEI, Address, U256}; +use crate::{constants::GWEI_TO_WEI, serde_helper::u64_hex, Address, U256}; use reth_codecs::{main_codec, Compact}; use reth_rlp::{RlpDecodable, RlpEncodable}; @@ -7,12 +7,15 @@ use reth_rlp::{RlpDecodable, RlpEncodable}; #[derive(Debug, Clone, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)] pub struct Withdrawal { /// Monotonically increasing identifier issued by consensus layer. + #[serde(with = "u64_hex")] pub index: u64, /// Index of validator associated with withdrawal. + #[serde(with = "u64_hex", rename = "validatorIndex")] pub validator_index: u64, /// Target address for withdrawn ether. pub address: Address, /// Value of the withdrawal in gwei. + #[serde(with = "u64_hex")] pub amount: u64, } @@ -22,3 +25,18 @@ impl Withdrawal { U256::from(self.amount) * U256::from(GWEI_TO_WEI) } } + +#[cfg(test)] +mod tests { + use super::*; + + // + #[test] + fn test_withdrawal_serde_roundtrip() { + let input = r#"[{"index":"0x0","validatorIndex":"0x0","address":"0x0000000000000000000000000000000000001000","amount":"0x1"},{"index":"0x1","validatorIndex":"0x1","address":"0x0000000000000000000000000000000000001001","amount":"0x1"},{"index":"0x2","validatorIndex":"0x2","address":"0x0000000000000000000000000000000000001002","amount":"0x1"},{"index":"0x3","validatorIndex":"0x3","address":"0x0000000000000000000000000000000000001003","amount":"0x1"},{"index":"0x4","validatorIndex":"0x4","address":"0x0000000000000000000000000000000000001004","amount":"0x1"},{"index":"0x5","validatorIndex":"0x5","address":"0x0000000000000000000000000000000000001005","amount":"0x1"},{"index":"0x6","validatorIndex":"0x6","address":"0x0000000000000000000000000000000000001006","amount":"0x1"},{"index":"0x7","validatorIndex":"0x7","address":"0x0000000000000000000000000000000000001007","amount":"0x1"},{"index":"0x8","validatorIndex":"0x8","address":"0x0000000000000000000000000000000000001008","amount":"0x1"},{"index":"0x9","validatorIndex":"0x9","address":"0x0000000000000000000000000000000000001009","amount":"0x1"},{"index":"0xa","validatorIndex":"0xa","address":"0x000000000000000000000000000000000000100a","amount":"0x1"},{"index":"0xb","validatorIndex":"0xb","address":"0x000000000000000000000000000000000000100b","amount":"0x1"},{"index":"0xc","validatorIndex":"0xc","address":"0x000000000000000000000000000000000000100c","amount":"0x1"},{"index":"0xd","validatorIndex":"0xd","address":"0x000000000000000000000000000000000000100d","amount":"0x1"},{"index":"0xe","validatorIndex":"0xe","address":"0x000000000000000000000000000000000000100e","amount":"0x1"},{"index":"0xf","validatorIndex":"0xf","address":"0x000000000000000000000000000000000000100f","amount":"0x1"}]"#; + + let withdrawals: Vec = serde_json::from_str(input).unwrap(); + let s = serde_json::to_string(&withdrawals).unwrap(); + assert_eq!(input, s); + } +}