reth_optimism_primitives/
receipt.rsuse alloy_consensus::{
Eip2718EncodableReceipt, Eip658Value, Receipt, ReceiptWithBloom, RlpDecodableReceipt,
RlpEncodableReceipt, TxReceipt, Typed2718,
};
use alloy_primitives::{Bloom, Log};
use alloy_rlp::{BufMut, Decodable, Header};
use op_alloy_consensus::{OpDepositReceipt, OpTxType};
use reth_primitives_traits::InMemorySize;
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum OpReceipt {
Legacy(Receipt),
Eip2930(Receipt),
Eip1559(Receipt),
Eip7702(Receipt),
Deposit(OpDepositReceipt),
}
impl OpReceipt {
pub const fn tx_type(&self) -> OpTxType {
match self {
Self::Legacy(_) => OpTxType::Legacy,
Self::Eip2930(_) => OpTxType::Eip2930,
Self::Eip1559(_) => OpTxType::Eip1559,
Self::Eip7702(_) => OpTxType::Eip7702,
Self::Deposit(_) => OpTxType::Deposit,
}
}
pub const fn as_receipt(&self) -> &Receipt {
match self {
Self::Legacy(receipt) |
Self::Eip2930(receipt) |
Self::Eip1559(receipt) |
Self::Eip7702(receipt) => receipt,
Self::Deposit(receipt) => &receipt.inner,
}
}
pub fn rlp_encoded_fields_length(&self, bloom: &Bloom) -> usize {
match self {
Self::Legacy(receipt) |
Self::Eip2930(receipt) |
Self::Eip1559(receipt) |
Self::Eip7702(receipt) => receipt.rlp_encoded_fields_length_with_bloom(bloom),
Self::Deposit(receipt) => receipt.rlp_encoded_fields_length_with_bloom(bloom),
}
}
pub fn rlp_encode_fields(&self, bloom: &Bloom, out: &mut dyn BufMut) {
match self {
Self::Legacy(receipt) |
Self::Eip2930(receipt) |
Self::Eip1559(receipt) |
Self::Eip7702(receipt) => receipt.rlp_encode_fields_with_bloom(bloom, out),
Self::Deposit(receipt) => receipt.rlp_encode_fields_with_bloom(bloom, out),
}
}
pub fn rlp_header_inner(&self, bloom: &Bloom) -> Header {
Header { list: true, payload_length: self.rlp_encoded_fields_length(bloom) }
}
pub fn rlp_decode_inner(
buf: &mut &[u8],
tx_type: OpTxType,
) -> alloy_rlp::Result<ReceiptWithBloom<Self>> {
match tx_type {
OpTxType::Legacy => {
let ReceiptWithBloom { receipt, logs_bloom } =
RlpDecodableReceipt::rlp_decode_with_bloom(buf)?;
Ok(ReceiptWithBloom { receipt: Self::Legacy(receipt), logs_bloom })
}
OpTxType::Eip2930 => {
let ReceiptWithBloom { receipt, logs_bloom } =
RlpDecodableReceipt::rlp_decode_with_bloom(buf)?;
Ok(ReceiptWithBloom { receipt: Self::Eip2930(receipt), logs_bloom })
}
OpTxType::Eip1559 => {
let ReceiptWithBloom { receipt, logs_bloom } =
RlpDecodableReceipt::rlp_decode_with_bloom(buf)?;
Ok(ReceiptWithBloom { receipt: Self::Eip1559(receipt), logs_bloom })
}
OpTxType::Eip7702 => {
let ReceiptWithBloom { receipt, logs_bloom } =
RlpDecodableReceipt::rlp_decode_with_bloom(buf)?;
Ok(ReceiptWithBloom { receipt: Self::Eip7702(receipt), logs_bloom })
}
OpTxType::Deposit => {
let ReceiptWithBloom { receipt, logs_bloom } =
RlpDecodableReceipt::rlp_decode_with_bloom(buf)?;
Ok(ReceiptWithBloom { receipt: Self::Deposit(receipt), logs_bloom })
}
}
}
}
impl Eip2718EncodableReceipt for OpReceipt {
fn eip2718_encoded_length_with_bloom(&self, bloom: &Bloom) -> usize {
!self.tx_type().is_legacy() as usize + self.rlp_header_inner(bloom).length_with_payload()
}
fn eip2718_encode_with_bloom(&self, bloom: &Bloom, out: &mut dyn BufMut) {
if !self.tx_type().is_legacy() {
out.put_u8(self.tx_type() as u8);
}
self.rlp_header_inner(bloom).encode(out);
self.rlp_encode_fields(bloom, out);
}
}
impl RlpEncodableReceipt for OpReceipt {
fn rlp_encoded_length_with_bloom(&self, bloom: &Bloom) -> usize {
let mut len = self.eip2718_encoded_length_with_bloom(bloom);
if !self.tx_type().is_legacy() {
len += Header {
list: false,
payload_length: self.eip2718_encoded_length_with_bloom(bloom),
}
.length();
}
len
}
fn rlp_encode_with_bloom(&self, bloom: &Bloom, out: &mut dyn BufMut) {
if !self.tx_type().is_legacy() {
Header { list: false, payload_length: self.eip2718_encoded_length_with_bloom(bloom) }
.encode(out);
}
self.eip2718_encode_with_bloom(bloom, out);
}
}
impl RlpDecodableReceipt for OpReceipt {
fn rlp_decode_with_bloom(buf: &mut &[u8]) -> alloy_rlp::Result<ReceiptWithBloom<Self>> {
let header_buf = &mut &**buf;
let header = Header::decode(header_buf)?;
if header.list {
return Self::rlp_decode_inner(buf, OpTxType::Legacy)
}
*buf = *header_buf;
let remaining = buf.len();
let tx_type = OpTxType::decode(buf)?;
let this = Self::rlp_decode_inner(buf, tx_type)?;
if buf.len() + header.payload_length != remaining {
return Err(alloy_rlp::Error::UnexpectedLength);
}
Ok(this)
}
}
impl TxReceipt for OpReceipt {
type Log = Log;
fn status_or_post_state(&self) -> Eip658Value {
self.as_receipt().status_or_post_state()
}
fn status(&self) -> bool {
self.as_receipt().status()
}
fn bloom(&self) -> Bloom {
self.as_receipt().bloom()
}
fn cumulative_gas_used(&self) -> u128 {
self.as_receipt().cumulative_gas_used()
}
fn logs(&self) -> &[Log] {
self.as_receipt().logs()
}
}
impl Typed2718 for OpReceipt {
fn ty(&self) -> u8 {
self.tx_type().into()
}
}
impl InMemorySize for OpReceipt {
fn size(&self) -> usize {
self.as_receipt().size()
}
}
impl reth_primitives_traits::Receipt for OpReceipt {}
#[cfg(feature = "reth-codec")]
mod compact {
use super::*;
use alloc::borrow::Cow;
use reth_codecs::Compact;
#[derive(reth_codecs::CompactZstd)]
#[reth_zstd(
compressor = reth_zstd_compressors::RECEIPT_COMPRESSOR,
decompressor = reth_zstd_compressors::RECEIPT_DECOMPRESSOR
)]
struct CompactOpReceipt<'a> {
tx_type: OpTxType,
success: bool,
cumulative_gas_used: u64,
logs: Cow<'a, Vec<Log>>,
deposit_nonce: Option<u64>,
deposit_receipt_version: Option<u64>,
}
impl<'a> From<&'a OpReceipt> for CompactOpReceipt<'a> {
fn from(receipt: &'a OpReceipt) -> Self {
Self {
tx_type: receipt.tx_type(),
success: receipt.status(),
cumulative_gas_used: receipt.cumulative_gas_used() as u64,
logs: Cow::Borrowed(&receipt.as_receipt().logs),
deposit_nonce: if let OpReceipt::Deposit(receipt) = receipt {
receipt.deposit_nonce
} else {
None
},
deposit_receipt_version: if let OpReceipt::Deposit(receipt) = receipt {
receipt.deposit_receipt_version
} else {
None
},
}
}
}
impl From<CompactOpReceipt<'_>> for OpReceipt {
fn from(receipt: CompactOpReceipt<'_>) -> Self {
let CompactOpReceipt {
tx_type,
success,
cumulative_gas_used,
logs,
deposit_nonce,
deposit_receipt_version,
} = receipt;
let inner = Receipt {
status: success.into(),
cumulative_gas_used: cumulative_gas_used as u128,
logs: logs.into_owned(),
};
match tx_type {
OpTxType::Legacy => Self::Legacy(inner),
OpTxType::Eip2930 => Self::Eip2930(inner),
OpTxType::Eip1559 => Self::Eip1559(inner),
OpTxType::Eip7702 => Self::Eip7702(inner),
OpTxType::Deposit => Self::Deposit(OpDepositReceipt {
inner,
deposit_nonce,
deposit_receipt_version,
}),
}
}
}
impl Compact for OpReceipt {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
CompactOpReceipt::from(self).to_compact(buf)
}
fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
let (receipt, buf) = CompactOpReceipt::from_compact(buf, len);
(receipt.into(), buf)
}
}
}