Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add AnyReceiptEnvelope #446

Merged
merged 2 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod header;
pub use header::{Header, EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH};

mod receipt;
pub use receipt::{Receipt, ReceiptEnvelope, ReceiptWithBloom, TxReceipt};
pub use receipt::{AnyReceiptEnvelope, Receipt, ReceiptEnvelope, ReceiptWithBloom, TxReceipt};

mod transaction;
pub use transaction::{
Expand Down
74 changes: 74 additions & 0 deletions crates/consensus/src/receipt/any.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use crate::ReceiptWithBloom;
use alloy_eips::eip2718::{Decodable2718, Encodable2718};
use alloy_primitives::{bytes::BufMut, Log};
use alloy_rlp::{Decodable, Encodable};

/// Receipt envelope, as defined in [EIP-2718].
///
/// This enum distinguishes between tagged and untagged legacy receipts, as the
/// in-protocol merkle tree may commit to EITHER 0-prefixed or raw. Therefore
/// we must ensure that encoding returns the precise byte-array that was
/// decoded, preserving the presence or absence of the `TransactionType` flag.
///
/// Transaction receipt payloads are specified in their respective EIPs.
///
/// [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AnyReceiptEnvelope<T = Log> {
/// The receipt envelope.
#[cfg_attr(feature = "serde", serde(flatten))]
pub inner: ReceiptWithBloom<T>,
/// The transaction type.
#[cfg_attr(feature = "serde", serde(with = "alloy_serde::num::u8_hex"))]
pub r#type: u8,
}

impl AnyReceiptEnvelope {
/// Returns whether this is a legacy receipt (type 0)
pub const fn is_legacy(&self) -> bool {
self.r#type == 0
}

/// Calculate the length of the rlp payload of the network encoded receipt.
pub fn rlp_payload_length(&self) -> usize {
let length = self.inner.length();
if self.is_legacy() {
length
} else {
length + 1
}
}
}

impl Encodable2718 for AnyReceiptEnvelope {
fn type_flag(&self) -> Option<u8> {
match self.r#type {
0 => None,
ty => Some(ty),
}
}

fn encode_2718_len(&self) -> usize {
self.inner.length() + !self.is_legacy() as usize
}

fn encode_2718(&self, out: &mut dyn BufMut) {
match self.type_flag() {
None => {}
Some(ty) => out.put_u8(ty),
}
self.inner.encode(out);
}
}

impl Decodable2718 for AnyReceiptEnvelope {
fn typed_decode(ty: u8, buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
let receipt = Decodable::decode(buf)?;
Ok(Self { inner: receipt, r#type: ty })
}

fn fallback_decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
Self::typed_decode(0, buf)
}
}
3 changes: 3 additions & 0 deletions crates/consensus/src/receipt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use alloy_primitives::{Bloom, Log};

mod any;
pub use any::AnyReceiptEnvelope;

mod envelope;
pub use envelope::ReceiptEnvelope;

Expand Down
47 changes: 44 additions & 3 deletions crates/serde/src/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,47 @@ impl<'de> Deserialize<'de> for U64HexOrNumber {
}
}

/// serde functions for handling `u8` as [U8](alloy_primitives::U8)
pub mod u8_hex {
use alloy_primitives::U8;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// Deserializes an `u8` from [U8] accepting a hex quantity string with optional 0x prefix
pub fn deserialize<'de, D>(deserializer: D) -> Result<u8, D::Error>
where
D: Deserializer<'de>,
{
U8::deserialize(deserializer).map(|val| val.to())
}

/// Serializes u64 as hex string
pub fn serialize<S: Serializer>(value: &u8, s: S) -> Result<S::Ok, S::Error> {
U8::from(*value).serialize(s)
}
}

/// serde functions for handling `Option<u8>` as [U8](alloy_primitives::U8)
pub mod u8_hex_opt {
use alloy_primitives::U8;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// Serializes u64 as hex string
pub fn serialize<S: Serializer>(value: &Option<u8>, s: S) -> Result<S::Ok, S::Error> {
match value {
Some(val) => U8::from(*val).serialize(s),
None => s.serialize_none(),
}
}

/// Deserializes an `Option` from [U8] accepting a hex quantity string with optional 0x prefix
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<u8>, D::Error>
where
D: Deserializer<'de>,
{
Ok(U8::deserialize(deserializer).map_or(None, |v| Some(u8::from_be_bytes(v.to_be_bytes()))))
}
}

/// serde functions for handling `u64` as [U64]
pub mod u64_hex {
use alloy_primitives::U64;
Expand Down Expand Up @@ -203,12 +244,12 @@ where
NumberOrHexU256::deserialize(deserializer)?.try_into_u256()
}

/// serde functions for handling primitive `u64` as [U64]
/// serde functions for handling primitive `u128` as [U128](alloy_primitives::U128)
pub mod u128_hex_or_decimal {
use alloy_primitives::U128;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// Deserializes an `u64` accepting a hex quantity string with optional 0x prefix or
/// Deserializes an `u128` accepting a hex quantity string with optional 0x prefix or
/// a number
pub fn deserialize<'de, D>(deserializer: D) -> Result<u128, D::Error>
where
Expand All @@ -217,7 +258,7 @@ pub mod u128_hex_or_decimal {
U128::deserialize(deserializer).map(|val| val.to())
}

/// Serializes u64 as hex string
/// Serializes u128 as hex string
pub fn serialize<S: Serializer>(value: &u128, s: S) -> Result<S::Ok, S::Error> {
U128::from(*value).serialize(s)
}
Expand Down
Loading