From d5eb825c4976d16f13f40651b299593386c51df6 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 14 Jun 2024 23:15:35 +0200 Subject: [PATCH] feat: derive serde for header --- crates/consensus/src/header.rs | 55 ++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/crates/consensus/src/header.rs b/crates/consensus/src/header.rs index d6ec497e46b..91f17b797af 100644 --- a/crates/consensus/src/header.rs +++ b/crates/consensus/src/header.rs @@ -22,6 +22,8 @@ pub const EMPTY_ROOT_HASH: B256 = /// Ethereum Block header #[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] pub struct Header { /// The Keccak 256-bit hash of the parent /// block’s header, in its entirety; formally Hp. @@ -42,6 +44,7 @@ pub struct Header { pub receipts_root: B256, /// The Keccak 256-bit hash of the withdrawals list portion of this block. /// + #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))] pub withdrawals_root: Option, /// The Bloom filter composed from indexable information (logger address and log topics) /// contained in each log entry from the receipt of each transaction in the transactions list; @@ -52,13 +55,17 @@ pub struct Header { pub difficulty: U256, /// A scalar value equal to the number of ancestor blocks. The genesis block has a number of /// zero; formally Hi. + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub number: BlockNumber, /// A scalar value equal to the current limit of gas expenditure per block; formally Hl. + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub gas_limit: u128, /// A scalar value equal to the total gas used in transactions in this block; formally Hg. + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub gas_used: u128, /// A scalar value equal to the reasonable output of Unix’s time() at this block’s inception; /// formally Hs. + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] pub timestamp: u64, /// A 256-bit hash which, combined with the /// nonce, proves that a sufficient amount of computation has been carried out on this block; @@ -73,13 +80,37 @@ pub struct Header { /// The algorithm results in the base fee per gas increasing when blocks are /// above the gas target, and decreasing when blocks are below the gas target. The base fee per /// gas is burned. + #[cfg_attr( + feature = "serde", + serde( + default, + with = "alloy_serde::quantity::opt", + skip_serializing_if = "Option::is_none" + ) + )] pub base_fee_per_gas: Option, /// The total amount of blob gas consumed by the transactions within the block, added in /// EIP-4844. + #[cfg_attr( + feature = "serde", + serde( + default, + with = "alloy_serde::quantity::opt", + skip_serializing_if = "Option::is_none" + ) + )] pub blob_gas_used: Option, /// A running total of blob gas consumed in excess of the target, prior to the block. Blocks /// with above-target blob gas consumption increase this value, blocks with below-target blob /// gas consumption decrease it (bounded at 0). This was added in EIP-4844. + #[cfg_attr( + feature = "serde", + serde( + default, + with = "alloy_serde::quantity::opt", + skip_serializing_if = "Option::is_none" + ) + )] pub excess_blob_gas: Option, /// The hash of the parent beacon block's root is included in execution blocks, as proposed by /// EIP-4788. @@ -88,11 +119,13 @@ pub struct Header { /// and more. /// /// The beacon roots contract handles root storage, enhancing Ethereum's functionalities. + #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))] pub parent_beacon_block_root: Option, /// The Keccak 256-bit hash of the root node of the trie structure populated with each /// [EIP-7685] request in the block body. /// /// [EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685 + #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))] pub requests_root: Option, /// An arbitrary byte array containing data relevant to this block. This must be 32 bytes or /// fewer; formally Hx. @@ -492,3 +525,25 @@ impl Decodable for Header { Ok(this) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg(feature = "serde")] + #[test] + fn header_serde() { + let raw = r#"{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","withdrawalsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x0","gasUsed":"0x0","timestamp":"0x0","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1","extraData":"0x"}"#; + let header = Header { + base_fee_per_gas: Some(1), + withdrawals_root: Some(EMPTY_ROOT_HASH), + ..Default::default() + }; + + let json = serde_json::to_string(&header).unwrap(); + assert_eq!(json, raw); + + let decoded: Header = serde_json::from_str(&json).unwrap(); + assert_eq!(decoded, header); + } +}