Skip to content

Commit

Permalink
feat(consensus): bincode compatibility (#131)
Browse files Browse the repository at this point in the history
## Motivation

alloy-rs/alloy#1349

## Solution

Same as alloy-rs/alloy#1397

## PR Checklist

- [x] Added Tests
- [x] Added Documentation
- [ ] Breaking changes
  • Loading branch information
shekhirin authored Sep 30, 2024
1 parent 57beee0 commit daa9438
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 1 deletion.
6 changes: 5 additions & 1 deletion crates/consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ arbitrary = { workspace = true, features = ["derive"], optional = true }
# serde
alloy-serde = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"], optional = true }
serde_with = { version = "3.9", optional = true }

# misc
spin.workspace = true
Expand All @@ -35,8 +36,10 @@ derive_more = { workspace = true, features = ["display"] }
alloy-primitives = { workspace = true, features = ["rand"] }
alloy-signer.workspace = true
arbitrary = { workspace = true, features = ["derive"] }
tokio = { workspace = true, features = ["macros"] }
bincode = "1.3"
rand.workspace = true
serde_json.workspace = true
tokio = { workspace = true, features = ["macros"] }

[features]
default = ["std"]
Expand All @@ -45,3 +48,4 @@ k256 = ["alloy-primitives/k256", "alloy-consensus/k256"]
kzg = ["alloy-eips/kzg", "alloy-consensus/kzg", "std"]
arbitrary = ["std", "dep:arbitrary", "alloy-consensus/arbitrary", "alloy-eips/arbitrary", "alloy-primitives/rand"]
serde = ["dep:serde", "dep:alloy-serde", "alloy-primitives/serde", "alloy-consensus/serde", "alloy-eips/serde"]
serde-bincode-compat = ["serde_with"]
12 changes: 12 additions & 0 deletions crates/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,15 @@ pub use hardforks::Hardforks;

mod block;
pub use block::OpBlock;

/// Bincode-compatible serde implementations for consensus types.
///
/// `bincode` crate doesn't work well with optionally serializable serde fields, but some of the
/// consensus types require optional serialization for RPC compatibility. This module makes so that
/// all fields are serialized.
///
/// Read more: <https://github.com/bincode-org/bincode/issues/326>
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
pub mod serde_bincode_compat {
pub use super::transaction::serde_bincode_compat::TxDeposit;
}
117 changes: 117 additions & 0 deletions crates/consensus/src/transaction/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,3 +356,120 @@ mod tests {
assert!(total_len > len_without_header);
}
}

/// Bincode-compatible [`TxDeposit`] serde implementation.
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
pub(super) mod serde_bincode_compat {
use alloc::borrow::Cow;
use alloy_primitives::{Address, Bytes, TxKind, B256, U256};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_with::{DeserializeAs, SerializeAs};

/// Bincode-compatible [`super::TxDeposit`] serde implementation.
///
/// Intended to use with the [`serde_with::serde_as`] macro in the following way:
/// ```rust
/// use op_alloy_consensus::{serde_bincode_compat, TxDeposit};
/// use serde::{Deserialize, Serialize};
/// use serde_with::serde_as;
///
/// #[serde_as]
/// #[derive(Serialize, Deserialize)]
/// struct Data {
/// #[serde_as(as = "serde_bincode_compat::TxDeposit")]
/// transaction: TxDeposit,
/// }
/// ```
#[derive(Debug, Serialize, Deserialize)]
pub struct TxDeposit<'a> {
source_hash: B256,
from: Address,
#[serde(default)]
to: TxKind,
#[serde(default)]
mint: Option<u128>,
value: U256,
gas_limit: u64,
is_system_transaction: bool,
input: Cow<'a, Bytes>,
}

impl<'a> From<&'a super::TxDeposit> for TxDeposit<'a> {
fn from(value: &'a super::TxDeposit) -> Self {
Self {
source_hash: value.source_hash,
from: value.from,
to: value.to,
mint: value.mint,
value: value.value,
gas_limit: value.gas_limit,
is_system_transaction: value.is_system_transaction,
input: Cow::Borrowed(&value.input),
}
}
}

impl<'a> From<TxDeposit<'a>> for super::TxDeposit {
fn from(value: TxDeposit<'a>) -> Self {
Self {
source_hash: value.source_hash,
from: value.from,
to: value.to,
mint: value.mint,
value: value.value,
gas_limit: value.gas_limit,
is_system_transaction: value.is_system_transaction,
input: value.input.into_owned(),
}
}
}

impl<'a> SerializeAs<super::TxDeposit> for TxDeposit<'a> {
fn serialize_as<S>(source: &super::TxDeposit, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
TxDeposit::from(source).serialize(serializer)
}
}

impl<'de> DeserializeAs<'de, super::TxDeposit> for TxDeposit<'de> {
fn deserialize_as<D>(deserializer: D) -> Result<super::TxDeposit, D::Error>
where
D: Deserializer<'de>,
{
TxDeposit::deserialize(deserializer).map(Into::into)
}
}

#[cfg(test)]
mod tests {
use arbitrary::Arbitrary;
use rand::Rng;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;

use super::super::{serde_bincode_compat, TxDeposit};

#[test]
fn test_tx_deposit_bincode_roundtrip() {
#[serde_as]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Data {
#[serde_as(as = "serde_bincode_compat::TxDeposit")]
transaction: TxDeposit,
}

let mut bytes = [0u8; 1024];
rand::thread_rng().fill(bytes.as_mut_slice());
let data = Data {
transaction: TxDeposit::arbitrary(&mut arbitrary::Unstructured::new(&bytes))
.unwrap(),
};

let encoded = bincode::serialize(&data).unwrap();
let decoded: Data = bincode::deserialize(&encoded).unwrap();
assert_eq!(decoded, data);
}
}
}
6 changes: 6 additions & 0 deletions crates/consensus/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ pub use source::{
DepositSourceDomain, DepositSourceDomainIdentifier, L1InfoDepositSource, UpgradeDepositSource,
UserDepositSource,
};

/// Bincode-compatible serde implementations for transaction types.
#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))]
pub(super) mod serde_bincode_compat {
pub use super::deposit::serde_bincode_compat::TxDeposit;
}

0 comments on commit daa9438

Please sign in to comment.