Fix: Reorder all serde_bincode_compat module definitions (#11435)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Varun Doshi
2024-10-02 21:48:06 +05:30
committed by GitHub
parent e882d00f1a
commit 3bbbade9cf
3 changed files with 507 additions and 507 deletions

View File

@ -507,6 +507,127 @@ pub enum ChainSplit {
},
}
/// Bincode-compatible [`Chain`] serde implementation.
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
pub(super) mod serde_bincode_compat {
use std::collections::BTreeMap;
use alloc::borrow::Cow;
use alloy_primitives::BlockNumber;
use reth_primitives::serde_bincode_compat::SealedBlockWithSenders;
use reth_trie::serde_bincode_compat::updates::TrieUpdates;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_with::{DeserializeAs, SerializeAs};
use crate::ExecutionOutcome;
/// Bincode-compatible [`super::Chain`] serde implementation.
///
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
/// ```rust
/// use reth_execution_types::{serde_bincode_compat, Chain};
/// use serde::{Deserialize, Serialize};
/// use serde_with::serde_as;
///
/// #[serde_as]
/// #[derive(Serialize, Deserialize)]
/// struct Data {
/// #[serde_as(as = "serde_bincode_compat::Chain")]
/// chain: Chain,
/// }
/// ```
#[derive(Debug, Serialize, Deserialize)]
pub struct Chain<'a> {
blocks: BTreeMap<BlockNumber, SealedBlockWithSenders<'a>>,
execution_outcome: Cow<'a, ExecutionOutcome>,
trie_updates: Option<TrieUpdates<'a>>,
}
impl<'a> From<&'a super::Chain> for Chain<'a> {
fn from(value: &'a super::Chain) -> Self {
Self {
blocks: value
.blocks
.iter()
.map(|(block_number, block)| (*block_number, block.into()))
.collect(),
execution_outcome: Cow::Borrowed(&value.execution_outcome),
trie_updates: value.trie_updates.as_ref().map(Into::into),
}
}
}
impl<'a> From<Chain<'a>> for super::Chain {
fn from(value: Chain<'a>) -> Self {
Self {
blocks: value
.blocks
.into_iter()
.map(|(block_number, block)| (block_number, block.into()))
.collect(),
execution_outcome: value.execution_outcome.into_owned(),
trie_updates: value.trie_updates.map(Into::into),
}
}
}
impl<'a> SerializeAs<super::Chain> for Chain<'a> {
fn serialize_as<S>(source: &super::Chain, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
Chain::from(source).serialize(serializer)
}
}
impl<'de> DeserializeAs<'de, super::Chain> for Chain<'de> {
fn deserialize_as<D>(deserializer: D) -> Result<super::Chain, D::Error>
where
D: Deserializer<'de>,
{
Chain::deserialize(deserializer).map(Into::into)
}
}
#[cfg(test)]
mod tests {
use arbitrary::Arbitrary;
use rand::Rng;
use reth_primitives::SealedBlockWithSenders;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use super::super::{serde_bincode_compat, Chain};
#[test]
fn test_chain_bincode_roundtrip() {
#[serde_as]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Data {
#[serde_as(as = "serde_bincode_compat::Chain")]
chain: Chain,
}
let mut bytes = [0u8; 1024];
rand::thread_rng().fill(bytes.as_mut_slice());
let data = Data {
chain: Chain::new(
vec![SealedBlockWithSenders::arbitrary(&mut arbitrary::Unstructured::new(
&bytes,
))
.unwrap()],
Default::default(),
None,
),
};
let encoded = bincode::serialize(&data).unwrap();
let decoded: Data = bincode::deserialize(&encoded).unwrap();
assert_eq!(decoded, data);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -723,124 +844,3 @@ mod tests {
assert_eq!(chain.execution_outcome_at_block(11), Some(execution_outcome));
}
}
/// Bincode-compatible [`Chain`] serde implementation.
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
pub(super) mod serde_bincode_compat {
use std::collections::BTreeMap;
use alloc::borrow::Cow;
use alloy_primitives::BlockNumber;
use reth_primitives::serde_bincode_compat::SealedBlockWithSenders;
use reth_trie::serde_bincode_compat::updates::TrieUpdates;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_with::{DeserializeAs, SerializeAs};
use crate::ExecutionOutcome;
/// Bincode-compatible [`super::Chain`] serde implementation.
///
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
/// ```rust
/// use reth_execution_types::{serde_bincode_compat, Chain};
/// use serde::{Deserialize, Serialize};
/// use serde_with::serde_as;
///
/// #[serde_as]
/// #[derive(Serialize, Deserialize)]
/// struct Data {
/// #[serde_as(as = "serde_bincode_compat::Chain")]
/// chain: Chain,
/// }
/// ```
#[derive(Debug, Serialize, Deserialize)]
pub struct Chain<'a> {
blocks: BTreeMap<BlockNumber, SealedBlockWithSenders<'a>>,
execution_outcome: Cow<'a, ExecutionOutcome>,
trie_updates: Option<TrieUpdates<'a>>,
}
impl<'a> From<&'a super::Chain> for Chain<'a> {
fn from(value: &'a super::Chain) -> Self {
Self {
blocks: value
.blocks
.iter()
.map(|(block_number, block)| (*block_number, block.into()))
.collect(),
execution_outcome: Cow::Borrowed(&value.execution_outcome),
trie_updates: value.trie_updates.as_ref().map(Into::into),
}
}
}
impl<'a> From<Chain<'a>> for super::Chain {
fn from(value: Chain<'a>) -> Self {
Self {
blocks: value
.blocks
.into_iter()
.map(|(block_number, block)| (block_number, block.into()))
.collect(),
execution_outcome: value.execution_outcome.into_owned(),
trie_updates: value.trie_updates.map(Into::into),
}
}
}
impl<'a> SerializeAs<super::Chain> for Chain<'a> {
fn serialize_as<S>(source: &super::Chain, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
Chain::from(source).serialize(serializer)
}
}
impl<'de> DeserializeAs<'de, super::Chain> for Chain<'de> {
fn deserialize_as<D>(deserializer: D) -> Result<super::Chain, D::Error>
where
D: Deserializer<'de>,
{
Chain::deserialize(deserializer).map(Into::into)
}
}
#[cfg(test)]
mod tests {
use arbitrary::Arbitrary;
use rand::Rng;
use reth_primitives::SealedBlockWithSenders;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use super::super::{serde_bincode_compat, Chain};
#[test]
fn test_chain_bincode_roundtrip() {
#[serde_as]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Data {
#[serde_as(as = "serde_bincode_compat::Chain")]
chain: Chain,
}
let mut bytes = [0u8; 1024];
rand::thread_rng().fill(bytes.as_mut_slice());
let data = Data {
chain: Chain::new(
vec![SealedBlockWithSenders::arbitrary(&mut arbitrary::Unstructured::new(
&bytes,
))
.unwrap()],
Default::default(),
None,
),
};
let encoded = bincode::serialize(&data).unwrap();
let decoded: Data = bincode::deserialize(&encoded).unwrap();
assert_eq!(decoded, data);
}
}
}

View File

@ -699,185 +699,6 @@ impl<'a> arbitrary::Arbitrary<'a> for BlockBody {
}
}
#[cfg(test)]
mod tests {
use super::{BlockNumberOrTag::*, *};
use alloy_eips::eip1898::HexStringMissingPrefixError;
use alloy_primitives::hex_literal::hex;
use alloy_rlp::{Decodable, Encodable};
use std::str::FromStr;
/// Check parsing according to EIP-1898.
#[test]
fn can_parse_blockid_u64() {
let num = serde_json::json!(
{"blockNumber": "0xaf"}
);
let id = serde_json::from_value::<BlockId>(num);
assert_eq!(id.unwrap(), BlockId::from(175));
}
#[test]
fn can_parse_block_hash() {
let block_hash =
B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
.unwrap();
let block_hash_json = serde_json::json!(
{ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}
);
let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
assert_eq!(id, BlockId::from(block_hash,));
}
#[test]
fn can_parse_block_hash_with_canonical() {
let block_hash =
B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
.unwrap();
let block_id = BlockId::Hash(RpcBlockHash::from_hash(block_hash, Some(true)));
let block_hash_json = serde_json::json!(
{ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }
);
let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
assert_eq!(id, block_id)
}
#[test]
fn can_parse_blockid_tags() {
let tags =
[("latest", Latest), ("finalized", Finalized), ("safe", Safe), ("pending", Pending)];
for (value, tag) in tags {
let num = serde_json::json!({ "blockNumber": value });
let id = serde_json::from_value::<BlockId>(num);
assert_eq!(id.unwrap(), BlockId::from(tag))
}
}
#[test]
fn repeated_keys_is_err() {
let num = serde_json::json!({"blockNumber": 1, "requireCanonical": true, "requireCanonical": false});
assert!(serde_json::from_value::<BlockId>(num).is_err());
let num =
serde_json::json!({"blockNumber": 1, "requireCanonical": true, "blockNumber": 23});
assert!(serde_json::from_value::<BlockId>(num).is_err());
}
/// Serde tests
#[test]
fn serde_blockid_tags() {
let block_ids = [Latest, Finalized, Safe, Pending].map(BlockId::from);
for block_id in &block_ids {
let serialized = serde_json::to_string(&block_id).unwrap();
let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized, *block_id)
}
}
#[test]
fn serde_blockid_number() {
let block_id = BlockId::from(100u64);
let serialized = serde_json::to_string(&block_id).unwrap();
let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized, block_id)
}
#[test]
fn serde_blockid_hash() {
let block_id = BlockId::from(B256::default());
let serialized = serde_json::to_string(&block_id).unwrap();
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: B256 = 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"}"#;
let value: serde_json::Value = serde_json::from_str(payload).unwrap();
let block_id_param = value.pointer("/params/1").unwrap();
let block_id: BlockId = serde_json::from_value::<BlockId>(block_id_param.clone()).unwrap();
assert_eq!(BlockId::Number(BlockNumberOrTag::Latest), block_id);
}
#[test]
fn serde_rpc_payload_block_object() {
let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}],"id":1,"jsonrpc":"2.0"}"#;
let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
let block_id_param = value.pointer("/params/1").unwrap().to_string();
let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
let hash =
B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
.unwrap();
assert_eq!(BlockId::from(hash), block_id);
let serialized = serde_json::to_string(&BlockId::from(hash)).unwrap();
assert_eq!("{\"blockHash\":\"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3\"}", serialized)
}
#[test]
fn serde_rpc_payload_block_number() {
let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockNumber": "0x0"}],"id":1,"jsonrpc":"2.0"}"#;
let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
let block_id_param = value.pointer("/params/1").unwrap().to_string();
let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
assert_eq!(BlockId::from(0u64), block_id);
let serialized = serde_json::to_string(&BlockId::from(0u64)).unwrap();
assert_eq!("\"0x0\"", serialized)
}
#[test]
#[should_panic]
fn serde_rpc_payload_block_number_duplicate_key() {
let payload = r#"{"blockNumber": "0x132", "blockNumber": "0x133"}"#;
let parsed_block_id = serde_json::from_str::<BlockId>(payload);
parsed_block_id.unwrap();
}
#[test]
fn serde_rpc_payload_block_hash() {
let payload = r#"{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}"#;
let parsed = serde_json::from_str::<BlockId>(payload).unwrap();
let expected = BlockId::from(
B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
.unwrap(),
);
assert_eq!(parsed, expected);
}
#[test]
fn encode_decode_raw_block() {
let bytes = hex!("f90288f90218a0fe21bb173f43067a9f90cfc59bbb6830a7a2929b5de4a61f372a9db28e87f9aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a061effbbcca94f0d3e02e5bd22e986ad57142acabf0cb3d129a6ad8d0f8752e94a0d911c25e97e27898680d242b7780b6faef30995c355a2d5de92e6b9a7212ad3aa0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008003834c4b408252081e80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000842806be9da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421f869f86702842806be9e82520894658bdf435d810c91414ec09147daa6db624063798203e880820a95a040ce7918eeb045ebf8c8b1887ca139d076bda00fa828a07881d442a72626c42da0156576a68e456e295e4c9cf67cf9f53151f329438916e0f24fc69d6bbb7fbacfc0c0");
let bytes_buf = &mut bytes.as_ref();
let block = Block::decode(bytes_buf).unwrap();
let mut encoded_buf = Vec::with_capacity(bytes.len());
block.encode(&mut encoded_buf);
assert_eq!(bytes[..], encoded_buf);
}
#[test]
fn serde_blocknumber_non_0xprefix() {
let s = "\"2\"";
let err = serde_json::from_str::<BlockNumberOrTag>(s).unwrap_err();
assert_eq!(err.to_string(), HexStringMissingPrefixError::default().to_string());
}
#[test]
fn block_with_senders() {
let mut block = Block::default();
let sender = Address::random();
block.body.transactions.push(TransactionSigned::default());
assert_eq!(BlockWithSenders::new(block.clone(), vec![]), None);
assert_eq!(
BlockWithSenders::new(block.clone(), vec![sender]),
Some(BlockWithSenders { block: block.clone(), senders: vec![sender] })
);
let sealed = block.seal_slow();
assert_eq!(SealedBlockWithSenders::new(sealed.clone(), vec![]), None);
assert_eq!(
SealedBlockWithSenders::new(sealed.clone(), vec![sender]),
Some(SealedBlockWithSenders { block: sealed, senders: vec![sender] })
);
}
}
/// Bincode-compatible block type serde implementations.
#[cfg(feature = "serde-bincode-compat")]
pub(super) mod serde_bincode_compat {
@ -1131,3 +952,182 @@ pub(super) mod serde_bincode_compat {
}
}
}
#[cfg(test)]
mod tests {
use super::{BlockNumberOrTag::*, *};
use alloy_eips::eip1898::HexStringMissingPrefixError;
use alloy_primitives::hex_literal::hex;
use alloy_rlp::{Decodable, Encodable};
use std::str::FromStr;
/// Check parsing according to EIP-1898.
#[test]
fn can_parse_blockid_u64() {
let num = serde_json::json!(
{"blockNumber": "0xaf"}
);
let id = serde_json::from_value::<BlockId>(num);
assert_eq!(id.unwrap(), BlockId::from(175));
}
#[test]
fn can_parse_block_hash() {
let block_hash =
B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
.unwrap();
let block_hash_json = serde_json::json!(
{ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}
);
let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
assert_eq!(id, BlockId::from(block_hash,));
}
#[test]
fn can_parse_block_hash_with_canonical() {
let block_hash =
B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
.unwrap();
let block_id = BlockId::Hash(RpcBlockHash::from_hash(block_hash, Some(true)));
let block_hash_json = serde_json::json!(
{ "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true }
);
let id = serde_json::from_value::<BlockId>(block_hash_json).unwrap();
assert_eq!(id, block_id)
}
#[test]
fn can_parse_blockid_tags() {
let tags =
[("latest", Latest), ("finalized", Finalized), ("safe", Safe), ("pending", Pending)];
for (value, tag) in tags {
let num = serde_json::json!({ "blockNumber": value });
let id = serde_json::from_value::<BlockId>(num);
assert_eq!(id.unwrap(), BlockId::from(tag))
}
}
#[test]
fn repeated_keys_is_err() {
let num = serde_json::json!({"blockNumber": 1, "requireCanonical": true, "requireCanonical": false});
assert!(serde_json::from_value::<BlockId>(num).is_err());
let num =
serde_json::json!({"blockNumber": 1, "requireCanonical": true, "blockNumber": 23});
assert!(serde_json::from_value::<BlockId>(num).is_err());
}
/// Serde tests
#[test]
fn serde_blockid_tags() {
let block_ids = [Latest, Finalized, Safe, Pending].map(BlockId::from);
for block_id in &block_ids {
let serialized = serde_json::to_string(&block_id).unwrap();
let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized, *block_id)
}
}
#[test]
fn serde_blockid_number() {
let block_id = BlockId::from(100u64);
let serialized = serde_json::to_string(&block_id).unwrap();
let deserialized: BlockId = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized, block_id)
}
#[test]
fn serde_blockid_hash() {
let block_id = BlockId::from(B256::default());
let serialized = serde_json::to_string(&block_id).unwrap();
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: B256 = 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"}"#;
let value: serde_json::Value = serde_json::from_str(payload).unwrap();
let block_id_param = value.pointer("/params/1").unwrap();
let block_id: BlockId = serde_json::from_value::<BlockId>(block_id_param.clone()).unwrap();
assert_eq!(BlockId::Number(BlockNumberOrTag::Latest), block_id);
}
#[test]
fn serde_rpc_payload_block_object() {
let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}],"id":1,"jsonrpc":"2.0"}"#;
let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
let block_id_param = value.pointer("/params/1").unwrap().to_string();
let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
let hash =
B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
.unwrap();
assert_eq!(BlockId::from(hash), block_id);
let serialized = serde_json::to_string(&BlockId::from(hash)).unwrap();
assert_eq!("{\"blockHash\":\"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3\"}", serialized)
}
#[test]
fn serde_rpc_payload_block_number() {
let example_payload = r#"{"method":"eth_call","params":[{"to":"0xebe8efa441b9302a0d7eaecc277c09d20d684540","data":"0x45848dfc"},{"blockNumber": "0x0"}],"id":1,"jsonrpc":"2.0"}"#;
let value: serde_json::Value = serde_json::from_str(example_payload).unwrap();
let block_id_param = value.pointer("/params/1").unwrap().to_string();
let block_id: BlockId = serde_json::from_str::<BlockId>(&block_id_param).unwrap();
assert_eq!(BlockId::from(0u64), block_id);
let serialized = serde_json::to_string(&BlockId::from(0u64)).unwrap();
assert_eq!("\"0x0\"", serialized)
}
#[test]
#[should_panic]
fn serde_rpc_payload_block_number_duplicate_key() {
let payload = r#"{"blockNumber": "0x132", "blockNumber": "0x133"}"#;
let parsed_block_id = serde_json::from_str::<BlockId>(payload);
parsed_block_id.unwrap();
}
#[test]
fn serde_rpc_payload_block_hash() {
let payload = r#"{"blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"}"#;
let parsed = serde_json::from_str::<BlockId>(payload).unwrap();
let expected = BlockId::from(
B256::from_str("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
.unwrap(),
);
assert_eq!(parsed, expected);
}
#[test]
fn encode_decode_raw_block() {
let bytes = hex!("f90288f90218a0fe21bb173f43067a9f90cfc59bbb6830a7a2929b5de4a61f372a9db28e87f9aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a061effbbcca94f0d3e02e5bd22e986ad57142acabf0cb3d129a6ad8d0f8752e94a0d911c25e97e27898680d242b7780b6faef30995c355a2d5de92e6b9a7212ad3aa0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008003834c4b408252081e80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000842806be9da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421f869f86702842806be9e82520894658bdf435d810c91414ec09147daa6db624063798203e880820a95a040ce7918eeb045ebf8c8b1887ca139d076bda00fa828a07881d442a72626c42da0156576a68e456e295e4c9cf67cf9f53151f329438916e0f24fc69d6bbb7fbacfc0c0");
let bytes_buf = &mut bytes.as_ref();
let block = Block::decode(bytes_buf).unwrap();
let mut encoded_buf = Vec::with_capacity(bytes.len());
block.encode(&mut encoded_buf);
assert_eq!(bytes[..], encoded_buf);
}
#[test]
fn serde_blocknumber_non_0xprefix() {
let s = "\"2\"";
let err = serde_json::from_str::<BlockNumberOrTag>(s).unwrap_err();
assert_eq!(err.to_string(), HexStringMissingPrefixError::default().to_string());
}
#[test]
fn block_with_senders() {
let mut block = Block::default();
let sender = Address::random();
block.body.transactions.push(TransactionSigned::default());
assert_eq!(BlockWithSenders::new(block.clone(), vec![]), None);
assert_eq!(
BlockWithSenders::new(block.clone(), vec![sender]),
Some(BlockWithSenders { block: block.clone(), senders: vec![sender] })
);
let sealed = block.seal_slow();
assert_eq!(SealedBlockWithSenders::new(sealed.clone(), vec![]), None);
assert_eq!(
SealedBlockWithSenders::new(sealed.clone(), vec![sender]),
Some(SealedBlockWithSenders { block: sealed, senders: vec![sender] })
);
}
}

View File

@ -1570,6 +1570,213 @@ impl<T> WithEncoded<Option<T>> {
}
}
/// Bincode-compatible transaction type serde implementations.
#[cfg(feature = "serde-bincode-compat")]
pub mod serde_bincode_compat {
use alloc::borrow::Cow;
use alloy_consensus::{
transaction::serde_bincode_compat::{TxEip1559, TxEip2930, TxEip7702, TxLegacy},
TxEip4844,
};
use alloy_primitives::{Signature, TxHash};
#[cfg(feature = "optimism")]
use op_alloy_consensus::serde_bincode_compat::TxDeposit;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_with::{DeserializeAs, SerializeAs};
/// Bincode-compatible [`super::Transaction`] serde implementation.
///
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
/// ```rust
/// use reth_primitives::{serde_bincode_compat, Transaction};
/// use serde::{Deserialize, Serialize};
/// use serde_with::serde_as;
///
/// #[serde_as]
/// #[derive(Serialize, Deserialize)]
/// struct Data {
/// #[serde_as(as = "serde_bincode_compat::transaction::Transaction")]
/// transaction: Transaction,
/// }
/// ```
#[derive(Debug, Serialize, Deserialize)]
#[allow(missing_docs)]
pub enum Transaction<'a> {
Legacy(TxLegacy<'a>),
Eip2930(TxEip2930<'a>),
Eip1559(TxEip1559<'a>),
Eip4844(Cow<'a, TxEip4844>),
Eip7702(TxEip7702<'a>),
#[cfg(feature = "optimism")]
#[cfg(feature = "optimism")]
Deposit(TxDeposit<'a>),
}
impl<'a> From<&'a super::Transaction> for Transaction<'a> {
fn from(value: &'a super::Transaction) -> Self {
match value {
super::Transaction::Legacy(tx) => Self::Legacy(TxLegacy::from(tx)),
super::Transaction::Eip2930(tx) => Self::Eip2930(TxEip2930::from(tx)),
super::Transaction::Eip1559(tx) => Self::Eip1559(TxEip1559::from(tx)),
super::Transaction::Eip4844(tx) => Self::Eip4844(Cow::Borrowed(tx)),
super::Transaction::Eip7702(tx) => Self::Eip7702(TxEip7702::from(tx)),
#[cfg(feature = "optimism")]
super::Transaction::Deposit(tx) => Self::Deposit(TxDeposit::from(tx)),
}
}
}
impl<'a> From<Transaction<'a>> for super::Transaction {
fn from(value: Transaction<'a>) -> Self {
match value {
Transaction::Legacy(tx) => Self::Legacy(tx.into()),
Transaction::Eip2930(tx) => Self::Eip2930(tx.into()),
Transaction::Eip1559(tx) => Self::Eip1559(tx.into()),
Transaction::Eip4844(tx) => Self::Eip4844(tx.into_owned()),
Transaction::Eip7702(tx) => Self::Eip7702(tx.into()),
#[cfg(feature = "optimism")]
Transaction::Deposit(tx) => Self::Deposit(tx.into()),
}
}
}
impl<'a> SerializeAs<super::Transaction> for Transaction<'a> {
fn serialize_as<S>(source: &super::Transaction, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
Transaction::from(source).serialize(serializer)
}
}
impl<'de> DeserializeAs<'de, super::Transaction> for Transaction<'de> {
fn deserialize_as<D>(deserializer: D) -> Result<super::Transaction, D::Error>
where
D: Deserializer<'de>,
{
Transaction::deserialize(deserializer).map(Into::into)
}
}
/// Bincode-compatible [`super::TransactionSigned`] serde implementation.
///
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
/// ```rust
/// use reth_primitives::{serde_bincode_compat, TransactionSigned};
/// use serde::{Deserialize, Serialize};
/// use serde_with::serde_as;
///
/// #[serde_as]
/// #[derive(Serialize, Deserialize)]
/// struct Data {
/// #[serde_as(as = "serde_bincode_compat::transaction::TransactionSigned")]
/// transaction: TransactionSigned,
/// }
/// ```
#[derive(Debug, Serialize, Deserialize)]
pub struct TransactionSigned<'a> {
hash: TxHash,
signature: Signature,
transaction: Transaction<'a>,
}
impl<'a> From<&'a super::TransactionSigned> for TransactionSigned<'a> {
fn from(value: &'a super::TransactionSigned) -> Self {
Self {
hash: value.hash,
signature: value.signature,
transaction: Transaction::from(&value.transaction),
}
}
}
impl<'a> From<TransactionSigned<'a>> for super::TransactionSigned {
fn from(value: TransactionSigned<'a>) -> Self {
Self {
hash: value.hash,
signature: value.signature,
transaction: value.transaction.into(),
}
}
}
impl<'a> SerializeAs<super::TransactionSigned> for TransactionSigned<'a> {
fn serialize_as<S>(
source: &super::TransactionSigned,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
TransactionSigned::from(source).serialize(serializer)
}
}
impl<'de> DeserializeAs<'de, super::TransactionSigned> for TransactionSigned<'de> {
fn deserialize_as<D>(deserializer: D) -> Result<super::TransactionSigned, D::Error>
where
D: Deserializer<'de>,
{
TransactionSigned::deserialize(deserializer).map(Into::into)
}
}
#[cfg(test)]
mod tests {
use super::super::{serde_bincode_compat, Transaction, TransactionSigned};
use arbitrary::Arbitrary;
use rand::Rng;
use reth_testing_utils::generators;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
#[test]
fn test_transaction_bincode_roundtrip() {
#[serde_as]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Data {
#[serde_as(as = "serde_bincode_compat::Transaction")]
transaction: Transaction,
}
let mut bytes = [0u8; 1024];
generators::rng().fill(bytes.as_mut_slice());
let data = Data {
transaction: Transaction::arbitrary(&mut arbitrary::Unstructured::new(&bytes))
.unwrap(),
};
let encoded = bincode::serialize(&data).unwrap();
let decoded: Data = bincode::deserialize(&encoded).unwrap();
assert_eq!(decoded, data);
}
#[test]
fn test_transaction_signed_bincode_roundtrip() {
#[serde_as]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Data {
#[serde_as(as = "serde_bincode_compat::TransactionSigned")]
transaction: TransactionSigned,
}
let mut bytes = [0u8; 1024];
generators::rng().fill(bytes.as_mut_slice());
let data = Data {
transaction: TransactionSigned::arbitrary(&mut arbitrary::Unstructured::new(
&bytes,
))
.unwrap(),
};
let encoded = bincode::serialize(&data).unwrap();
let decoded: Data = bincode::deserialize(&encoded).unwrap();
assert_eq!(decoded, data);
}
}
}
#[cfg(test)]
mod tests {
use crate::{
@ -1976,210 +2183,3 @@ mod tests {
assert!(res.is_err());
}
}
/// Bincode-compatible transaction type serde implementations.
#[cfg(feature = "serde-bincode-compat")]
pub mod serde_bincode_compat {
use alloc::borrow::Cow;
use alloy_consensus::{
transaction::serde_bincode_compat::{TxEip1559, TxEip2930, TxEip7702, TxLegacy},
TxEip4844,
};
use alloy_primitives::{Signature, TxHash};
#[cfg(feature = "optimism")]
use op_alloy_consensus::serde_bincode_compat::TxDeposit;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_with::{DeserializeAs, SerializeAs};
/// Bincode-compatible [`super::Transaction`] serde implementation.
///
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
/// ```rust
/// use reth_primitives::{serde_bincode_compat, Transaction};
/// use serde::{Deserialize, Serialize};
/// use serde_with::serde_as;
///
/// #[serde_as]
/// #[derive(Serialize, Deserialize)]
/// struct Data {
/// #[serde_as(as = "serde_bincode_compat::transaction::Transaction")]
/// transaction: Transaction,
/// }
/// ```
#[derive(Debug, Serialize, Deserialize)]
#[allow(missing_docs)]
pub enum Transaction<'a> {
Legacy(TxLegacy<'a>),
Eip2930(TxEip2930<'a>),
Eip1559(TxEip1559<'a>),
Eip4844(Cow<'a, TxEip4844>),
Eip7702(TxEip7702<'a>),
#[cfg(feature = "optimism")]
#[cfg(feature = "optimism")]
Deposit(TxDeposit<'a>),
}
impl<'a> From<&'a super::Transaction> for Transaction<'a> {
fn from(value: &'a super::Transaction) -> Self {
match value {
super::Transaction::Legacy(tx) => Self::Legacy(TxLegacy::from(tx)),
super::Transaction::Eip2930(tx) => Self::Eip2930(TxEip2930::from(tx)),
super::Transaction::Eip1559(tx) => Self::Eip1559(TxEip1559::from(tx)),
super::Transaction::Eip4844(tx) => Self::Eip4844(Cow::Borrowed(tx)),
super::Transaction::Eip7702(tx) => Self::Eip7702(TxEip7702::from(tx)),
#[cfg(feature = "optimism")]
super::Transaction::Deposit(tx) => Self::Deposit(TxDeposit::from(tx)),
}
}
}
impl<'a> From<Transaction<'a>> for super::Transaction {
fn from(value: Transaction<'a>) -> Self {
match value {
Transaction::Legacy(tx) => Self::Legacy(tx.into()),
Transaction::Eip2930(tx) => Self::Eip2930(tx.into()),
Transaction::Eip1559(tx) => Self::Eip1559(tx.into()),
Transaction::Eip4844(tx) => Self::Eip4844(tx.into_owned()),
Transaction::Eip7702(tx) => Self::Eip7702(tx.into()),
#[cfg(feature = "optimism")]
Transaction::Deposit(tx) => Self::Deposit(tx.into()),
}
}
}
impl<'a> SerializeAs<super::Transaction> for Transaction<'a> {
fn serialize_as<S>(source: &super::Transaction, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
Transaction::from(source).serialize(serializer)
}
}
impl<'de> DeserializeAs<'de, super::Transaction> for Transaction<'de> {
fn deserialize_as<D>(deserializer: D) -> Result<super::Transaction, D::Error>
where
D: Deserializer<'de>,
{
Transaction::deserialize(deserializer).map(Into::into)
}
}
/// Bincode-compatible [`super::TransactionSigned`] serde implementation.
///
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
/// ```rust
/// use reth_primitives::{serde_bincode_compat, TransactionSigned};
/// use serde::{Deserialize, Serialize};
/// use serde_with::serde_as;
///
/// #[serde_as]
/// #[derive(Serialize, Deserialize)]
/// struct Data {
/// #[serde_as(as = "serde_bincode_compat::transaction::TransactionSigned")]
/// transaction: TransactionSigned,
/// }
/// ```
#[derive(Debug, Serialize, Deserialize)]
pub struct TransactionSigned<'a> {
hash: TxHash,
signature: Signature,
transaction: Transaction<'a>,
}
impl<'a> From<&'a super::TransactionSigned> for TransactionSigned<'a> {
fn from(value: &'a super::TransactionSigned) -> Self {
Self {
hash: value.hash,
signature: value.signature,
transaction: Transaction::from(&value.transaction),
}
}
}
impl<'a> From<TransactionSigned<'a>> for super::TransactionSigned {
fn from(value: TransactionSigned<'a>) -> Self {
Self {
hash: value.hash,
signature: value.signature,
transaction: value.transaction.into(),
}
}
}
impl<'a> SerializeAs<super::TransactionSigned> for TransactionSigned<'a> {
fn serialize_as<S>(
source: &super::TransactionSigned,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
TransactionSigned::from(source).serialize(serializer)
}
}
impl<'de> DeserializeAs<'de, super::TransactionSigned> for TransactionSigned<'de> {
fn deserialize_as<D>(deserializer: D) -> Result<super::TransactionSigned, D::Error>
where
D: Deserializer<'de>,
{
TransactionSigned::deserialize(deserializer).map(Into::into)
}
}
#[cfg(test)]
mod tests {
use super::super::{serde_bincode_compat, Transaction, TransactionSigned};
use arbitrary::Arbitrary;
use rand::Rng;
use reth_testing_utils::generators;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
#[test]
fn test_transaction_bincode_roundtrip() {
#[serde_as]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Data {
#[serde_as(as = "serde_bincode_compat::Transaction")]
transaction: Transaction,
}
let mut bytes = [0u8; 1024];
generators::rng().fill(bytes.as_mut_slice());
let data = Data {
transaction: Transaction::arbitrary(&mut arbitrary::Unstructured::new(&bytes))
.unwrap(),
};
let encoded = bincode::serialize(&data).unwrap();
let decoded: Data = bincode::deserialize(&encoded).unwrap();
assert_eq!(decoded, data);
}
#[test]
fn test_transaction_signed_bincode_roundtrip() {
#[serde_as]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Data {
#[serde_as(as = "serde_bincode_compat::TransactionSigned")]
transaction: TransactionSigned,
}
let mut bytes = [0u8; 1024];
generators::rng().fill(bytes.as_mut_slice());
let data = Data {
transaction: TransactionSigned::arbitrary(&mut arbitrary::Unstructured::new(
&bytes,
))
.unwrap(),
};
let encoded = bincode::serialize(&data).unwrap();
let decoded: Data = bincode::deserialize(&encoded).unwrap();
assert_eq!(decoded, data);
}
}
}