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: modifiy ReceiptWithBloom and associated impls to use with Reth #1672

Merged
merged 15 commits into from
Nov 25, 2024
54 changes: 27 additions & 27 deletions crates/consensus-any/src/receipt/envelope.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use alloy_consensus::{Eip658Value, ReceiptWithBloom, TxReceipt};
use alloy_consensus::{Eip658Value, Receipt, ReceiptWithBloom, RlpReceipt, TxReceipt};
use alloy_eips::eip2718::{Decodable2718, Eip2718Result, Encodable2718};
use alloy_primitives::{bytes::BufMut, Bloom, Log};
use alloy_rlp::{Decodable, Encodable};
use core::fmt;

/// Receipt envelope, as defined in [EIP-2718].
///
Expand All @@ -17,7 +16,7 @@ use core::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[doc(alias = "AnyTransactionReceiptEnvelope", alias = "AnyTxReceiptEnvelope")]
pub struct AnyReceiptEnvelope<T = Log> {
pub struct AnyReceiptEnvelope<T = Receipt<Log>> {
/// The receipt envelope.
#[cfg_attr(feature = "serde", serde(flatten))]
pub inner: ReceiptWithBloom<T>,
Expand All @@ -26,10 +25,14 @@ pub struct AnyReceiptEnvelope<T = Log> {
pub r#type: u8,
}

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

impl<R: RlpReceipt> AnyReceiptEnvelope<R> {
/// Calculate the length of the rlp payload of the network encoded receipt.
pub fn rlp_payload_length(&self) -> usize {
let length = self.inner.length();
Expand All @@ -41,12 +44,7 @@ where
}
}

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

impl<R: TxReceipt> AnyReceiptEnvelope<R> {
/// Return true if the transaction was successful.
///
/// ## Note
Expand All @@ -55,7 +53,7 @@ impl<T> AnyReceiptEnvelope<T> {
/// for transactions before [EIP-658].
///
/// [EIP-658]: https://eips.ethereum.org/EIPS/eip-658
pub const fn is_success(&self) -> bool {
pub fn is_success(&self) -> bool {
self.status()
}

Expand All @@ -67,8 +65,8 @@ impl<T> AnyReceiptEnvelope<T> {
/// for transactions before [EIP-658].
///
/// [EIP-658]: https://eips.ethereum.org/EIPS/eip-658
pub const fn status(&self) -> bool {
matches!(self.inner.receipt.status, Eip658Value::Eip658(true) | Eip658Value::PostState(_))
pub fn status(&self) -> bool {
self.inner.receipt.status()
}

/// Return the receipt's bloom.
Expand All @@ -77,38 +75,40 @@ impl<T> AnyReceiptEnvelope<T> {
}

/// Returns the cumulative gas used at this receipt.
pub const fn cumulative_gas_used(&self) -> u128 {
self.inner.receipt.cumulative_gas_used
pub fn cumulative_gas_used(&self) -> u128 {
self.inner.receipt.cumulative_gas_used()
}

/// Return the receipt logs.
pub fn logs(&self) -> &[T] {
&self.inner.receipt.logs
pub fn logs(&self) -> &[R::Log] {
self.inner.receipt.logs()
}
}

impl<T> TxReceipt<T> for AnyReceiptEnvelope<T>
impl<R> TxReceipt for AnyReceiptEnvelope<R>
where
T: Clone + fmt::Debug + PartialEq + Eq + Send + Sync,
R: TxReceipt,
{
type Log = R::Log;

fn status_or_post_state(&self) -> Eip658Value {
self.inner.status_or_post_state()
self.inner.receipt.status_or_post_state()
}

fn status(&self) -> bool {
self.inner.status()
self.inner.receipt.status()
}

fn bloom(&self) -> Bloom {
self.inner.logs_bloom
}

fn cumulative_gas_used(&self) -> u128 {
self.inner.receipt.cumulative_gas_used
self.inner.receipt.cumulative_gas_used()
}

fn logs(&self) -> &[T] {
&self.inner.receipt.logs
fn logs(&self) -> &[Self::Log] {
self.inner.receipt.logs()
}
}

Expand Down
4 changes: 3 additions & 1 deletion crates/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ pub mod constants;
pub use constants::{EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH};

mod receipt;
pub use receipt::{Eip658Value, Receipt, ReceiptEnvelope, ReceiptWithBloom, Receipts, TxReceipt};
pub use receipt::{
Eip658Value, Receipt, ReceiptEnvelope, ReceiptWithBloom, Receipts, RlpReceipt, TxReceipt,
};

pub mod proofs;

Expand Down
27 changes: 16 additions & 11 deletions crates/consensus/src/receipt/envelope.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use core::fmt;

use crate::{Eip658Value, Receipt, ReceiptWithBloom, TxReceipt, TxType};
use alloy_eips::eip2718::{Decodable2718, Eip2718Error, Eip2718Result, Encodable2718};
use alloy_primitives::{Bloom, Log};
use alloy_rlp::{BufMut, Decodable, Encodable};
use core::fmt;

/// Receipt envelope, as defined in [EIP-2718].
///
Expand All @@ -22,27 +23,27 @@ use core::fmt;
pub enum ReceiptEnvelope<T = Log> {
/// Receipt envelope with no type flag.
#[cfg_attr(feature = "serde", serde(rename = "0x0", alias = "0x00"))]
Legacy(ReceiptWithBloom<T>),
Legacy(ReceiptWithBloom<Receipt<T>>),
/// Receipt envelope with type flag 1, containing a [EIP-2930] receipt.
///
/// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930
#[cfg_attr(feature = "serde", serde(rename = "0x1", alias = "0x01"))]
Eip2930(ReceiptWithBloom<T>),
Eip2930(ReceiptWithBloom<Receipt<T>>),
/// Receipt envelope with type flag 2, containing a [EIP-1559] receipt.
///
/// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
#[cfg_attr(feature = "serde", serde(rename = "0x2", alias = "0x02"))]
Eip1559(ReceiptWithBloom<T>),
Eip1559(ReceiptWithBloom<Receipt<T>>),
/// Receipt envelope with type flag 2, containing a [EIP-4844] receipt.
///
/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844
#[cfg_attr(feature = "serde", serde(rename = "0x3", alias = "0x03"))]
Eip4844(ReceiptWithBloom<T>),
Eip4844(ReceiptWithBloom<Receipt<T>>),
/// Receipt envelope with type flag 4, containing a [EIP-7702] receipt.
///
/// [EIP-7702]: https://eips.ethereum.org/EIPS/eip-7702
#[cfg_attr(feature = "serde", serde(rename = "0x4", alias = "0x04"))]
Eip7702(ReceiptWithBloom<T>),
Eip7702(ReceiptWithBloom<Receipt<T>>),
}

impl<T> ReceiptEnvelope<T> {
Expand Down Expand Up @@ -85,7 +86,7 @@ impl<T> ReceiptEnvelope<T> {

/// Return the inner receipt with bloom. Currently this is infallible,
/// however, future receipt types may be added.
pub const fn as_receipt_with_bloom(&self) -> Option<&ReceiptWithBloom<T>> {
pub const fn as_receipt_with_bloom(&self) -> Option<&ReceiptWithBloom<Receipt<T>>> {
match self {
Self::Legacy(t)
| Self::Eip2930(t)
Expand All @@ -108,10 +109,12 @@ impl<T> ReceiptEnvelope<T> {
}
}

impl<T> TxReceipt<T> for ReceiptEnvelope<T>
impl<T> TxReceipt for ReceiptEnvelope<T>
where
T: Clone + fmt::Debug + PartialEq + Eq + Send + Sync,
{
type Log = T;

fn status_or_post_state(&self) -> Eip658Value {
self.as_receipt().unwrap().status
}
Expand Down Expand Up @@ -220,7 +223,7 @@ where
T: arbitrary::Arbitrary<'a>,
{
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let receipt = ReceiptWithBloom::<T>::arbitrary(u)?;
let receipt = ReceiptWithBloom::<Receipt<T>>::arbitrary(u)?;

match u.int_in_range(0..=3)? {
0 => Ok(Self::Legacy(receipt)),
Expand All @@ -240,7 +243,9 @@ mod test {
fn deser_pre658_receipt_envelope() {
use alloy_primitives::b256;

let receipt = super::ReceiptWithBloom::<()> {
use crate::Receipt;

let receipt = super::ReceiptWithBloom::<Receipt<()>> {
receipt: super::Receipt {
status: super::Eip658Value::PostState(b256!(
"284d35bf53b82ef480ab4208527325477439c64fb90ef518450f05ee151c8e10"
Expand All @@ -255,7 +260,7 @@ mod test {

println!("Serialized {}", json);

let receipt: super::ReceiptWithBloom<()> = serde_json::from_str(&json).unwrap();
let receipt: super::ReceiptWithBloom<Receipt<()>> = serde_json::from_str(&json).unwrap();

assert_eq!(
receipt.receipt.status,
Expand Down
67 changes: 63 additions & 4 deletions crates/consensus/src/receipt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use alloy_primitives::{Bloom, Log};
use alloy_primitives::Bloom;
use alloy_rlp::{BufMut, Header};
use core::fmt;

mod envelope;
Expand All @@ -13,7 +14,10 @@ pub use status::Eip658Value;
/// Receipt is the result of a transaction execution.
#[doc(alias = "TransactionReceipt")]
#[auto_impl::auto_impl(&, Arc)]
pub trait TxReceipt<T = Log>: Clone + fmt::Debug + PartialEq + Eq + Send + Sync {
pub trait TxReceipt: Clone + fmt::Debug + PartialEq + Eq + Send + Sync {
/// The associated log type.
type Log;

/// Returns the status or post state of the transaction.
///
/// ## Note
Expand Down Expand Up @@ -54,14 +58,69 @@ pub trait TxReceipt<T = Log>: Clone + fmt::Debug + PartialEq + Eq + Send + Sync
fn cumulative_gas_used(&self) -> u128;

/// Returns the logs emitted by this transaction.
fn logs(&self) -> &[T];
fn logs(&self) -> &[Self::Log];
}

/// Receipt type that knows how to encode and decode itself with a [`Bloom`] value.
pub trait RlpReceipt: Sized {
/// Returns the length of the RLP encoded receipt fields with the provided bloom filter, without
/// RLP header.
fn rlp_encoded_fields_length_with_bloom(&self, bloom: Bloom) -> usize;

/// RLP encodes the receipt fields with the provided bloom filter, without RLP header.
fn rlp_encode_fields_with_bloom(&self, bloom: Bloom, out: &mut dyn BufMut);

/// Returns the RLP header for the receipt payload with the provided bloom filter.
fn rlp_header_with_bloom(&self, bloom: Bloom) -> alloy_rlp::Header {
alloy_rlp::Header {
list: true,
payload_length: self.rlp_encoded_fields_length_with_bloom(bloom),
}
}

/// Returns the length of the receipt payload with the provided bloom filter.
fn rlp_encoded_length_with_bloom(&self, bloom: Bloom) -> usize {
self.rlp_header_with_bloom(bloom).length_with_payload()
}

/// RLP encodes the receipt with the provided bloom filter.
fn rlp_encode_with_bloom(&self, bloom: Bloom, out: &mut dyn BufMut) {
self.rlp_header_with_bloom(bloom).encode(out);
self.rlp_encode_fields_with_bloom(bloom, out);
}

/// RLP decodes receipt's fields and [`Bloom`] into [`ReceiptWithBloom`] instance.
///
/// Note: this should not decode an RLP header.
fn rlp_decode_fields_with_bloom(buf: &mut &[u8]) -> alloy_rlp::Result<ReceiptWithBloom<Self>>;

/// RLP decodes receipt and [`Bloom`] into [`ReceiptWithBloom`] instance.
fn rlp_decode_with_bloom(buf: &mut &[u8]) -> alloy_rlp::Result<ReceiptWithBloom<Self>> {
let header = Header::decode(buf)?;
if !header.list {
return Err(alloy_rlp::Error::UnexpectedString);
}
let remaining = buf.len();

if header.payload_length > remaining {
return Err(alloy_rlp::Error::InputTooShort);
}

let this = Self::rlp_decode_fields_with_bloom(buf)?;

if buf.len() + header.payload_length != remaining {
return Err(alloy_rlp::Error::UnexpectedLength);
}

Ok(this)
}
}

#[cfg(test)]
mod tests {
use super::*;
use alloy_eips::eip2718::Encodable2718;
use alloy_primitives::{address, b256, bytes, hex, LogData};
use alloy_primitives::{address, b256, bytes, hex, Log, LogData};
use alloy_rlp::{Decodable, Encodable};

// Test vector from: https://eips.ethereum.org/EIPS/eip-2481
Expand Down
Loading