diff --git a/crates/evm/execution-types/src/chain.rs b/crates/evm/execution-types/src/chain.rs index 1767a7f43..20bf5c6d2 100644 --- a/crates/evm/execution-types/src/chain.rs +++ b/crates/evm/execution-types/src/chain.rs @@ -525,7 +525,9 @@ pub(super) mod serde_bincode_compat { use crate::ExecutionOutcome; use alloc::borrow::Cow; use alloy_primitives::BlockNumber; - use reth_primitives::serde_bincode_compat::SealedBlockWithSenders; + use reth_primitives::{ + serde_bincode_compat::SealedBlockWithSenders, EthPrimitives, NodePrimitives, + }; use reth_trie_common::serde_bincode_compat::updates::TrieUpdates; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; use serde_with::{DeserializeAs, SerializeAs}; @@ -547,18 +549,24 @@ pub(super) mod serde_bincode_compat { /// } /// ``` #[derive(Debug, Serialize, Deserialize)] - pub struct Chain<'a> { - blocks: SealedBlocksWithSenders<'a>, - execution_outcome: Cow<'a, ExecutionOutcome>, + pub struct Chain<'a, N = EthPrimitives> + where + N: NodePrimitives, + { + blocks: SealedBlocksWithSenders<'a, N::Block>, + execution_outcome: Cow<'a, ExecutionOutcome>, trie_updates: Option>, } #[derive(Debug)] - struct SealedBlocksWithSenders<'a>( - Cow<'a, BTreeMap>, + struct SealedBlocksWithSenders<'a, B: reth_primitives_traits::Block>( + Cow<'a, BTreeMap>>, ); - impl Serialize for SealedBlocksWithSenders<'_> { + impl Serialize for SealedBlocksWithSenders<'_, B> + where + B: reth_primitives_traits::Block, + { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -573,20 +581,26 @@ pub(super) mod serde_bincode_compat { } } - impl<'de> Deserialize<'de> for SealedBlocksWithSenders<'_> { + impl<'de, B> Deserialize<'de> for SealedBlocksWithSenders<'_, B> + where + B: reth_primitives_traits::Block, + { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Ok(Self(Cow::Owned( - BTreeMap::>::deserialize(deserializer) + BTreeMap::>::deserialize(deserializer) .map(|blocks| blocks.into_iter().map(|(n, b)| (n, b.into())).collect())?, ))) } } - impl<'a> From<&'a super::Chain> for Chain<'a> { - fn from(value: &'a super::Chain) -> Self { + impl<'a, N> From<&'a super::Chain> for Chain<'a, N> + where + N: NodePrimitives, + { + fn from(value: &'a super::Chain) -> Self { Self { blocks: SealedBlocksWithSenders(Cow::Borrowed(&value.blocks)), execution_outcome: Cow::Borrowed(&value.execution_outcome), @@ -595,8 +609,11 @@ pub(super) mod serde_bincode_compat { } } - impl<'a> From> for super::Chain { - fn from(value: Chain<'a>) -> Self { + impl<'a, N> From> for super::Chain + where + N: NodePrimitives, + { + fn from(value: Chain<'a, N>) -> Self { Self { blocks: value.blocks.0.into_owned(), execution_outcome: value.execution_outcome.into_owned(), diff --git a/crates/exex/types/Cargo.toml b/crates/exex/types/Cargo.toml index 3b67fd5aa..4d99bd7e6 100644 --- a/crates/exex/types/Cargo.toml +++ b/crates/exex/types/Cargo.toml @@ -15,6 +15,7 @@ workspace = true # reth reth-chain-state.workspace = true reth-execution-types.workspace = true +reth-primitives.workspace = true reth-primitives-traits.workspace = true # reth diff --git a/crates/exex/types/src/notification.rs b/crates/exex/types/src/notification.rs index fb0762f04..5ded40d06 100644 --- a/crates/exex/types/src/notification.rs +++ b/crates/exex/types/src/notification.rs @@ -76,6 +76,7 @@ pub(super) mod serde_bincode_compat { use std::sync::Arc; use reth_execution_types::serde_bincode_compat::Chain; + use reth_primitives::{EthPrimitives, NodePrimitives}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_with::{DeserializeAs, SerializeAs}; @@ -96,14 +97,21 @@ pub(super) mod serde_bincode_compat { /// ``` #[derive(Debug, Serialize, Deserialize)] #[allow(missing_docs)] - pub enum ExExNotification<'a> { - ChainCommitted { new: Chain<'a> }, - ChainReorged { old: Chain<'a>, new: Chain<'a> }, - ChainReverted { old: Chain<'a> }, + #[serde(bound = "")] + pub enum ExExNotification<'a, N = EthPrimitives> + where + N: NodePrimitives, + { + ChainCommitted { new: Chain<'a, N> }, + ChainReorged { old: Chain<'a, N>, new: Chain<'a, N> }, + ChainReverted { old: Chain<'a, N> }, } - impl<'a> From<&'a super::ExExNotification> for ExExNotification<'a> { - fn from(value: &'a super::ExExNotification) -> Self { + impl<'a, N> From<&'a super::ExExNotification> for ExExNotification<'a, N> + where + N: NodePrimitives, + { + fn from(value: &'a super::ExExNotification) -> Self { match value { super::ExExNotification::ChainCommitted { new } => { ExExNotification::ChainCommitted { new: Chain::from(new.as_ref()) } @@ -121,8 +129,11 @@ pub(super) mod serde_bincode_compat { } } - impl<'a> From> for super::ExExNotification { - fn from(value: ExExNotification<'a>) -> Self { + impl<'a, N> From> for super::ExExNotification + where + N: NodePrimitives, + { + fn from(value: ExExNotification<'a, N>) -> Self { match value { ExExNotification::ChainCommitted { new } => { Self::ChainCommitted { new: Arc::new(new.into()) } diff --git a/crates/primitives-traits/src/block/body.rs b/crates/primitives-traits/src/block/body.rs index 76bf916ad..7491c75fa 100644 --- a/crates/primitives-traits/src/block/body.rs +++ b/crates/primitives-traits/src/block/body.rs @@ -4,7 +4,10 @@ use alloc::{fmt, vec::Vec}; use alloy_eips::eip4895::Withdrawals; -use crate::{FullSignedTx, InMemorySize, MaybeArbitrary, MaybeSerde, SignedTransaction}; +use crate::{ + FullSignedTx, InMemorySize, MaybeArbitrary, MaybeSerde, MaybeSerdeBincodeCompat, + SignedTransaction, +}; /// Helper trait that unifies all behaviour required by transaction to support full node operations. pub trait FullBlockBody: BlockBody {} @@ -26,6 +29,7 @@ pub trait BlockBody: + InMemorySize + MaybeSerde + MaybeArbitrary + + MaybeSerdeBincodeCompat { /// Ordered list of signed transactions as committed in block. type Transaction: SignedTransaction; diff --git a/crates/primitives-traits/src/block/header.rs b/crates/primitives-traits/src/block/header.rs index 268068085..e03535dd3 100644 --- a/crates/primitives-traits/src/block/header.rs +++ b/crates/primitives-traits/src/block/header.rs @@ -4,7 +4,7 @@ use core::fmt; use alloy_primitives::Sealable; -use crate::{InMemorySize, MaybeArbitrary, MaybeCompact, MaybeSerde}; +use crate::{InMemorySize, MaybeArbitrary, MaybeCompact, MaybeSerde, MaybeSerdeBincodeCompat}; /// Helper trait that unifies all behaviour required by block header to support full node /// operations. @@ -29,6 +29,7 @@ pub trait BlockHeader: + InMemorySize + MaybeSerde + MaybeArbitrary + + MaybeSerdeBincodeCompat { } @@ -48,5 +49,6 @@ impl BlockHeader for T where + InMemorySize + MaybeSerde + MaybeArbitrary + + MaybeSerdeBincodeCompat { } diff --git a/crates/primitives-traits/src/header/sealed.rs b/crates/primitives-traits/src/header/sealed.rs index 08add0ac3..f167ffbf2 100644 --- a/crates/primitives-traits/src/header/sealed.rs +++ b/crates/primitives-traits/src/header/sealed.rs @@ -173,11 +173,12 @@ where /// Bincode-compatible [`SealedHeader`] serde implementation. #[cfg(feature = "serde-bincode-compat")] pub(super) mod serde_bincode_compat { - use alloy_consensus::serde_bincode_compat::Header; use alloy_primitives::BlockHash; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_with::{DeserializeAs, SerializeAs}; + use crate::serde_bincode_compat::SerdeBincodeCompat; + /// Bincode-compatible [`super::SealedHeader`] serde implementation. /// /// Intended to use with the [`serde_with::serde_as`] macro in the following way: @@ -193,20 +194,21 @@ pub(super) mod serde_bincode_compat { /// header: SealedHeader, /// } /// ``` - #[derive(Debug, Serialize, Deserialize)] - pub struct SealedHeader<'a> { + #[derive(derive_more::Debug, Serialize, Deserialize)] + #[debug(bound(H::BincodeRepr<'a>: core::fmt::Debug))] + pub struct SealedHeader<'a, H: SerdeBincodeCompat = super::Header> { hash: BlockHash, - header: Header<'a>, + header: H::BincodeRepr<'a>, } - impl<'a> From<&'a super::SealedHeader> for SealedHeader<'a> { - fn from(value: &'a super::SealedHeader) -> Self { - Self { hash: value.hash, header: Header::from(&value.header) } + impl<'a, H: SerdeBincodeCompat> From<&'a super::SealedHeader> for SealedHeader<'a, H> { + fn from(value: &'a super::SealedHeader) -> Self { + Self { hash: value.hash, header: (&value.header).into() } } } - impl<'a> From> for super::SealedHeader { - fn from(value: SealedHeader<'a>) -> Self { + impl<'a, H: SerdeBincodeCompat> From> for super::SealedHeader { + fn from(value: SealedHeader<'a, H>) -> Self { Self { hash: value.hash, header: value.header.into() } } } @@ -229,6 +231,9 @@ pub(super) mod serde_bincode_compat { } } + impl SerdeBincodeCompat for super::SealedHeader { + type BincodeRepr<'a> = SealedHeader<'a, H>; + } #[cfg(test)] mod tests { use super::super::{serde_bincode_compat, SealedHeader}; diff --git a/crates/primitives-traits/src/lib.rs b/crates/primitives-traits/src/lib.rs index 338f8f621..5bdfd01eb 100644 --- a/crates/primitives-traits/src/lib.rs +++ b/crates/primitives-traits/src/lib.rs @@ -68,9 +68,7 @@ pub use header::{BlockWithParent, Header, HeaderError, SealedHeader}; /// /// Read more: #[cfg(feature = "serde-bincode-compat")] -pub mod serde_bincode_compat { - pub use super::header::{serde_bincode_compat as header, serde_bincode_compat::*}; -} +pub mod serde_bincode_compat; /// Heuristic size trait pub mod size; @@ -118,3 +116,16 @@ pub trait MaybeCompact {} impl MaybeCompact for T where T: reth_codecs::Compact {} #[cfg(not(feature = "reth-codec"))] impl MaybeCompact for T {} + +/// Helper trait that requires serde bincode compatibility implementation. +#[cfg(feature = "serde-bincode-compat")] +pub trait MaybeSerdeBincodeCompat: crate::serde_bincode_compat::SerdeBincodeCompat {} +/// Noop. Helper trait that would require serde bincode compatibility implementation if +/// `serde-bincode-compat` feature were enabled. +#[cfg(not(feature = "serde-bincode-compat"))] +pub trait MaybeSerdeBincodeCompat {} + +#[cfg(feature = "serde-bincode-compat")] +impl MaybeSerdeBincodeCompat for T where T: crate::serde_bincode_compat::SerdeBincodeCompat {} +#[cfg(not(feature = "serde-bincode-compat"))] +impl MaybeSerdeBincodeCompat for T {} diff --git a/crates/primitives-traits/src/serde_bincode_compat.rs b/crates/primitives-traits/src/serde_bincode_compat.rs new file mode 100644 index 000000000..a1f7d4256 --- /dev/null +++ b/crates/primitives-traits/src/serde_bincode_compat.rs @@ -0,0 +1,14 @@ +use core::fmt::Debug; + +pub use super::header::{serde_bincode_compat as header, serde_bincode_compat::*}; +use serde::{de::DeserializeOwned, Serialize}; + +/// Trait for types that can be serialized and deserialized using bincode. +pub trait SerdeBincodeCompat: Sized + 'static { + /// Serde representation of the type for bincode serialization. + type BincodeRepr<'a>: Debug + Serialize + DeserializeOwned + From<&'a Self> + Into; +} + +impl SerdeBincodeCompat for alloy_consensus::Header { + type BincodeRepr<'a> = alloy_consensus::serde_bincode_compat::Header<'a>; +} diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index 5618d81bd..c4905458c 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -744,7 +744,7 @@ pub(super) mod serde_bincode_compat { use alloy_consensus::serde_bincode_compat::Header; use alloy_eips::eip4895::Withdrawals; use alloy_primitives::Address; - use reth_primitives_traits::serde_bincode_compat::SealedHeader; + use reth_primitives_traits::serde_bincode_compat::{SealedHeader, SerdeBincodeCompat}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_with::{DeserializeAs, SerializeAs}; @@ -810,6 +810,10 @@ pub(super) mod serde_bincode_compat { } } + impl SerdeBincodeCompat for super::BlockBody { + type BincodeRepr<'a> = BlockBody<'a>; + } + /// Bincode-compatible [`super::SealedBlock`] serde implementation. /// /// Intended to use with the [`serde_with::serde_as`] macro in the following way: @@ -826,19 +830,34 @@ pub(super) mod serde_bincode_compat { /// } /// ``` #[derive(Debug, Serialize, Deserialize)] - pub struct SealedBlock<'a> { - header: SealedHeader<'a>, - body: BlockBody<'a>, + pub struct SealedBlock<'a, H = super::Header, B = super::BlockBody> + where + H: SerdeBincodeCompat, + B: SerdeBincodeCompat, + { + header: SealedHeader<'a, H>, + body: B::BincodeRepr<'a>, } - impl<'a> From<&'a super::SealedBlock> for SealedBlock<'a> { - fn from(value: &'a super::SealedBlock) -> Self { - Self { header: SealedHeader::from(&value.header), body: BlockBody::from(&value.body) } + impl<'a, H, B> From<&'a super::SealedBlock> for SealedBlock<'a, H, B> + where + H: SerdeBincodeCompat, + B: SerdeBincodeCompat, + { + fn from(value: &'a super::SealedBlock) -> Self { + Self { + header: SealedHeader::from(&value.header), + body: B::BincodeRepr::from(&value.body), + } } } - impl<'a> From> for super::SealedBlock { - fn from(value: SealedBlock<'a>) -> Self { + impl<'a, H, B> From> for super::SealedBlock + where + H: SerdeBincodeCompat, + B: SerdeBincodeCompat, + { + fn from(value: SealedBlock<'a, H, B>) -> Self { Self { header: value.header.into(), body: value.body.into() } } } @@ -877,19 +896,28 @@ pub(super) mod serde_bincode_compat { /// } /// ``` #[derive(Debug, Serialize, Deserialize)] - pub struct SealedBlockWithSenders<'a> { - block: SealedBlock<'a>, + pub struct SealedBlockWithSenders<'a, B = super::Block> + where + B: reth_primitives_traits::Block, + { + block: SealedBlock<'a, B::Header, B::Body>, senders: Cow<'a, Vec
>, } - impl<'a> From<&'a super::SealedBlockWithSenders> for SealedBlockWithSenders<'a> { - fn from(value: &'a super::SealedBlockWithSenders) -> Self { + impl<'a, B> From<&'a super::SealedBlockWithSenders> for SealedBlockWithSenders<'a, B> + where + B: reth_primitives_traits::Block, + { + fn from(value: &'a super::SealedBlockWithSenders) -> Self { Self { block: SealedBlock::from(&value.block), senders: Cow::Borrowed(&value.senders) } } } - impl<'a> From> for super::SealedBlockWithSenders { - fn from(value: SealedBlockWithSenders<'a>) -> Self { + impl<'a, B> From> for super::SealedBlockWithSenders + where + B: reth_primitives_traits::Block, + { + fn from(value: SealedBlockWithSenders<'a, B>) -> Self { Self { block: value.block.into(), senders: value.senders.into_owned() } } }