mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: optimism-specific receipt (#13317)
Co-authored-by: Emilia Hane <elsaemiliaevahane@gmail.com>
This commit is contained in:
30
Cargo.lock
generated
30
Cargo.lock
generated
@ -5411,9 +5411,9 @@ checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-alloy-consensus"
|
name = "op-alloy-consensus"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f9d95d0ec6457ad4d3d7fc0ad41db490b219587ed837ada87a26b28e535db15f"
|
checksum = "e5085cc8be65a2da9c04e9a904eccfe38eb69ecc3bc6c6485ce0f1af879f3abe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-consensus",
|
"alloy-consensus",
|
||||||
"alloy-eips",
|
"alloy-eips",
|
||||||
@ -5429,9 +5429,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-alloy-genesis"
|
name = "op-alloy-genesis"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8692a934265dd0fc68f02e2a1d644a80b76ae07dbc59552aa51d6df06953e9d"
|
checksum = "64f5aa1201d83af3b0ebffbfc28fdc7e772d7e44f4dea9e41c51162f84412edf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-consensus",
|
"alloy-consensus",
|
||||||
"alloy-eips",
|
"alloy-eips",
|
||||||
@ -5444,9 +5444,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-alloy-network"
|
name = "op-alloy-network"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f973f9e396dc53138ef89501875991bb1728ec34bbd9c0e1ab30caa5518abfa3"
|
checksum = "9d12eafaad5b89792de75f1344d42634dd5271945fd36256e4e5d766cf32107e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-consensus",
|
"alloy-consensus",
|
||||||
"alloy-network",
|
"alloy-network",
|
||||||
@ -5459,9 +5459,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-alloy-protocol"
|
name = "op-alloy-protocol"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29cb147e6f39d34bd8284b1107bcbca2e4c14e95b5bc49e5498ca6c0068a94c2"
|
checksum = "2cf8c05e1b7ed20c4af6f72a54cc389225d2c6af6fcf932ef6481cfdfcb540ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
"alloy-consensus",
|
"alloy-consensus",
|
||||||
@ -5483,9 +5483,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-alloy-rpc-jsonrpsee"
|
name = "op-alloy-rpc-jsonrpsee"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d7e394ccd907c63acc8213c24ebfb1be24f184b75af89cbaa92178b11de34a8"
|
checksum = "3b6edd6fb56f23ab45c704ad0c598641086e07b3a55d74890acaa01226ffc3e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-eips",
|
"alloy-eips",
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
@ -5496,9 +5496,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-alloy-rpc-types"
|
name = "op-alloy-rpc-types"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eba1b44e2035ec04cc61762cb9b5457d0ecd29d9af631e1a1c107ef571ce2318"
|
checksum = "b44194f44faef3db1edd17fc8e0b1309d377c6c7a4ba74a02d78c13d5f2ed90d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-consensus",
|
"alloy-consensus",
|
||||||
"alloy-eips",
|
"alloy-eips",
|
||||||
@ -5515,9 +5515,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "op-alloy-rpc-types-engine"
|
name = "op-alloy-rpc-types-engine"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00bcf8a51980231bbcd250a686c9ef41501c9e7aaa348ffe5808aa61dfe14151"
|
checksum = "c005d0a4431fbd9cd16eb0c2f67306de4245f76f311fa1628a68b79e7ea5aa0e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-eips",
|
"alloy-eips",
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
@ -8583,6 +8583,7 @@ dependencies = [
|
|||||||
"arbitrary",
|
"arbitrary",
|
||||||
"bytes",
|
"bytes",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
|
"modular-bitfield",
|
||||||
"op-alloy-consensus",
|
"op-alloy-consensus",
|
||||||
"proptest",
|
"proptest",
|
||||||
"proptest-arbitrary-interop",
|
"proptest-arbitrary-interop",
|
||||||
@ -8590,6 +8591,7 @@ dependencies = [
|
|||||||
"reth-codecs",
|
"reth-codecs",
|
||||||
"reth-primitives",
|
"reth-primitives",
|
||||||
"reth-primitives-traits",
|
"reth-primitives-traits",
|
||||||
|
"reth-zstd-compressors",
|
||||||
"revm-primitives",
|
"revm-primitives",
|
||||||
"rstest",
|
"rstest",
|
||||||
"secp256k1",
|
"secp256k1",
|
||||||
|
|||||||
10
Cargo.toml
10
Cargo.toml
@ -477,11 +477,11 @@ alloy-transport-ipc = { version = "0.8.0", default-features = false }
|
|||||||
alloy-transport-ws = { version = "0.8.0", default-features = false }
|
alloy-transport-ws = { version = "0.8.0", default-features = false }
|
||||||
|
|
||||||
# op
|
# op
|
||||||
op-alloy-rpc-types = "0.8.0"
|
op-alloy-rpc-types = "0.8.1"
|
||||||
op-alloy-rpc-types-engine = "0.8.0"
|
op-alloy-rpc-types-engine = "0.8.1"
|
||||||
op-alloy-rpc-jsonrpsee = "0.8.0"
|
op-alloy-rpc-jsonrpsee = "0.8.1"
|
||||||
op-alloy-network = "0.8.0"
|
op-alloy-network = "0.8.1"
|
||||||
op-alloy-consensus = "0.8.0"
|
op-alloy-consensus = "0.8.1"
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
aquamarine = "0.6"
|
aquamarine = "0.6"
|
||||||
|
|||||||
@ -16,6 +16,7 @@ workspace = true
|
|||||||
reth-primitives.workspace = true
|
reth-primitives.workspace = true
|
||||||
reth-primitives-traits = { workspace = true, features = ["op"] }
|
reth-primitives-traits = { workspace = true, features = ["op"] }
|
||||||
reth-codecs = { workspace = true, optional = true, features = ["op"] }
|
reth-codecs = { workspace = true, optional = true, features = ["op"] }
|
||||||
|
reth-zstd-compressors = { workspace = true, optional = true }
|
||||||
|
|
||||||
# ethereum
|
# ethereum
|
||||||
alloy-primitives.workspace = true
|
alloy-primitives.workspace = true
|
||||||
@ -30,6 +31,7 @@ op-alloy-consensus.workspace = true
|
|||||||
|
|
||||||
# codec
|
# codec
|
||||||
bytes = { workspace = true, optional = true }
|
bytes = { workspace = true, optional = true }
|
||||||
|
modular-bitfield = { workspace = true, optional = true }
|
||||||
serde = { workspace = true, optional = true }
|
serde = { workspace = true, optional = true }
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
@ -59,9 +61,10 @@ std = [
|
|||||||
"serde?/std",
|
"serde?/std",
|
||||||
"bytes?/std",
|
"bytes?/std",
|
||||||
"derive_more/std",
|
"derive_more/std",
|
||||||
"revm-primitives/std",
|
"revm-primitives/std",
|
||||||
"secp256k1?/std",
|
"secp256k1?/std",
|
||||||
"alloy-rlp/std",
|
"alloy-rlp/std",
|
||||||
|
"reth-zstd-compressors?/std"
|
||||||
]
|
]
|
||||||
reth-codec = [
|
reth-codec = [
|
||||||
"dep:reth-codecs",
|
"dep:reth-codecs",
|
||||||
@ -74,6 +77,8 @@ reth-codec = [
|
|||||||
"reth-codecs?/op",
|
"reth-codecs?/op",
|
||||||
"reth-primitives/reth-codec",
|
"reth-primitives/reth-codec",
|
||||||
"dep:bytes",
|
"dep:bytes",
|
||||||
|
"dep:modular-bitfield",
|
||||||
|
"dep:reth-zstd-compressors"
|
||||||
]
|
]
|
||||||
serde = [
|
serde = [
|
||||||
"dep:serde",
|
"dep:serde",
|
||||||
|
|||||||
@ -18,6 +18,9 @@ pub mod transaction;
|
|||||||
|
|
||||||
pub use transaction::{signed::OpTransactionSigned, tx_type::OpTxType, OpTransaction};
|
pub use transaction::{signed::OpTransactionSigned, tx_type::OpTxType, OpTransaction};
|
||||||
|
|
||||||
|
mod receipt;
|
||||||
|
pub use receipt::OpReceipt;
|
||||||
|
|
||||||
/// Optimism primitive types.
|
/// Optimism primitive types.
|
||||||
pub type OpPrimitives = reth_primitives::EthPrimitives;
|
pub type OpPrimitives = reth_primitives::EthPrimitives;
|
||||||
|
|
||||||
|
|||||||
299
crates/optimism/primitives/src/receipt.rs
Normal file
299
crates/optimism/primitives/src/receipt.rs
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
use 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;
|
||||||
|
|
||||||
|
/// Typed ethereum transaction receipt.
|
||||||
|
/// Receipt containing result of transaction execution.
|
||||||
|
#[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
|
||||||
|
Legacy(Receipt),
|
||||||
|
/// EIP-2930 receipt
|
||||||
|
Eip2930(Receipt),
|
||||||
|
/// EIP-1559 receipt
|
||||||
|
Eip1559(Receipt),
|
||||||
|
/// EIP-7702 receipt
|
||||||
|
Eip7702(Receipt),
|
||||||
|
/// Deposit receipt
|
||||||
|
Deposit(OpDepositReceipt),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpReceipt {
|
||||||
|
/// Returns [`OpTxType`] of the receipt.
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns inner [`Receipt`],
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns length of RLP-encoded receipt fields with the given [`Bloom`] without an RLP header.
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RLP-encodes receipt fields with the given [`Bloom`] without an RLP header.
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns RLP header for inner encoding.
|
||||||
|
pub fn rlp_header_inner(&self, bloom: &Bloom) -> Header {
|
||||||
|
Header { list: true, payload_length: self.rlp_encoded_fields_length(bloom) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RLP-decodes the receipt from the provided buffer. This does not expect a type byte or
|
||||||
|
/// network header.
|
||||||
|
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)?;
|
||||||
|
|
||||||
|
// Legacy receipt, reuse initial buffer without advancing
|
||||||
|
if header.list {
|
||||||
|
return Self::rlp_decode_inner(buf, OpTxType::Legacy)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, advance the buffer and try decoding type flag followed by receipt
|
||||||
|
*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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -40,7 +40,7 @@ use std::sync::OnceLock;
|
|||||||
#[derive(Debug, Clone, Eq, AsRef, Deref)]
|
#[derive(Debug, Clone, Eq, AsRef, Deref)]
|
||||||
pub struct OpTransactionSigned {
|
pub struct OpTransactionSigned {
|
||||||
/// Transaction hash
|
/// Transaction hash
|
||||||
#[serde(skip)]
|
#[cfg_attr(feature = "serde", serde(skip))]
|
||||||
pub hash: OnceLock<TxHash>,
|
pub hash: OnceLock<TxHash>,
|
||||||
/// The transaction signature values
|
/// The transaction signature values
|
||||||
pub signature: Signature,
|
pub signature: Signature,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use alloy_consensus::{Header, TxEip1559, TxEip2930, TxEip4844, TxEip7702, TxLegacy, TxType};
|
use alloy_consensus::{Header, TxEip1559, TxEip2930, TxEip4844, TxEip7702, TxLegacy, TxType};
|
||||||
use alloy_primitives::{PrimitiveSignature as Signature, TxHash};
|
use alloy_primitives::{PrimitiveSignature as Signature, TxHash};
|
||||||
|
use revm_primitives::Log;
|
||||||
|
|
||||||
/// Trait for calculating a heuristic for the in-memory size of a struct.
|
/// Trait for calculating a heuristic for the in-memory size of a struct.
|
||||||
#[auto_impl::auto_impl(&, Arc, Box)]
|
#[auto_impl::auto_impl(&, Arc, Box)]
|
||||||
@ -49,6 +50,25 @@ impl_in_mem_size!(Header, TxLegacy, TxEip2930, TxEip1559, TxEip7702, TxEip4844);
|
|||||||
#[cfg(feature = "op")]
|
#[cfg(feature = "op")]
|
||||||
impl_in_mem_size_size_of!(op_alloy_consensus::OpTxType);
|
impl_in_mem_size_size_of!(op_alloy_consensus::OpTxType);
|
||||||
|
|
||||||
|
impl InMemorySize for alloy_consensus::Receipt {
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
let Self { status, cumulative_gas_used, logs } = self;
|
||||||
|
core::mem::size_of_val(status) +
|
||||||
|
core::mem::size_of_val(cumulative_gas_used) +
|
||||||
|
logs.capacity() * core::mem::size_of::<Log>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "op")]
|
||||||
|
impl InMemorySize for op_alloy_consensus::OpDepositReceipt {
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
let Self { inner, deposit_nonce, deposit_receipt_version } = self;
|
||||||
|
inner.size() +
|
||||||
|
core::mem::size_of_val(deposit_nonce) +
|
||||||
|
core::mem::size_of_val(deposit_receipt_version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@ -21,7 +21,6 @@ pub use reth_primitives_traits::receipt::gas_spent_by_transactions;
|
|||||||
Clone, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable, Serialize, Deserialize,
|
Clone, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable, Serialize, Deserialize,
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(any(test, feature = "reth-codec"), derive(reth_codecs::CompactZstd))]
|
#[cfg_attr(any(test, feature = "reth-codec"), derive(reth_codecs::CompactZstd))]
|
||||||
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests)]
|
|
||||||
#[cfg_attr(any(test, feature = "reth-codec"), reth_zstd(
|
#[cfg_attr(any(test, feature = "reth-codec"), reth_zstd(
|
||||||
compressor = reth_zstd_compressors::RECEIPT_COMPRESSOR,
|
compressor = reth_zstd_compressors::RECEIPT_COMPRESSOR,
|
||||||
decompressor = reth_zstd_compressors::RECEIPT_DECOMPRESSOR
|
decompressor = reth_zstd_compressors::RECEIPT_DECOMPRESSOR
|
||||||
|
|||||||
@ -126,7 +126,9 @@ fn build_struct_field_flags(
|
|||||||
let mut total_bits = 0;
|
let mut total_bits = 0;
|
||||||
|
|
||||||
// Find out the adequate bit size for the length of each field, if applicable.
|
// Find out the adequate bit size for the length of each field, if applicable.
|
||||||
for (name, ftype, is_compact, _) in fields {
|
for field in fields {
|
||||||
|
let StructFieldDescriptor { name, ftype, is_compact, use_alt_impl: _, is_reference: _ } =
|
||||||
|
field;
|
||||||
// This happens when dealing with a wrapper struct eg. Struct(pub U256).
|
// This happens when dealing with a wrapper struct eg. Struct(pub U256).
|
||||||
let name = if name.is_empty() { "placeholder" } else { name };
|
let name = if name.is_empty() { "placeholder" } else { name };
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,15 @@ pub fn generate_from_to(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let fn_from_compact = if has_lifetime {
|
let has_ref_fields = fields.iter().any(|field| {
|
||||||
|
if let FieldTypes::StructField(field) = field {
|
||||||
|
field.is_reference
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let fn_from_compact = if has_ref_fields {
|
||||||
quote! { unimplemented!("from_compact not supported with ref structs") }
|
quote! { unimplemented!("from_compact not supported with ref structs") }
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
@ -100,7 +108,7 @@ fn generate_from_compact(
|
|||||||
) -> TokenStream2 {
|
) -> TokenStream2 {
|
||||||
let mut lines = vec![];
|
let mut lines = vec![];
|
||||||
let mut known_types =
|
let mut known_types =
|
||||||
vec!["B256", "Address", "Bloom", "Vec", "TxHash", "BlockHash", "FixedBytes"];
|
vec!["B256", "Address", "Bloom", "Vec", "TxHash", "BlockHash", "FixedBytes", "Cow"];
|
||||||
|
|
||||||
// Only types without `Bytes` should be added here. It's currently manually added, since
|
// Only types without `Bytes` should be added here. It's currently manually added, since
|
||||||
// it's hard to figure out with derive_macro which types have Bytes fields.
|
// it's hard to figure out with derive_macro which types have Bytes fields.
|
||||||
@ -132,8 +140,8 @@ fn generate_from_compact(
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let fields = fields.iter().filter_map(|field| {
|
let fields = fields.iter().filter_map(|field| {
|
||||||
if let FieldTypes::StructField((name, _, _, _)) = field {
|
if let FieldTypes::StructField(field) = field {
|
||||||
let ident = format_ident!("{name}");
|
let ident = format_ident!("{}", field.name);
|
||||||
return Some(quote! {
|
return Some(quote! {
|
||||||
#ident: #ident,
|
#ident: #ident,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -17,10 +17,6 @@ use structs::*;
|
|||||||
|
|
||||||
use crate::ZstdConfig;
|
use crate::ZstdConfig;
|
||||||
|
|
||||||
// Helper Alias type
|
|
||||||
type IsCompact = bool;
|
|
||||||
// Helper Alias type
|
|
||||||
type FieldName = String;
|
|
||||||
// Helper Alias type
|
// Helper Alias type
|
||||||
type FieldType = String;
|
type FieldType = String;
|
||||||
/// `Compact` has alternative functions that can be used as a workaround for type
|
/// `Compact` has alternative functions that can be used as a workaround for type
|
||||||
@ -30,7 +26,14 @@ type FieldType = String;
|
|||||||
/// require the len of the element, while the latter one does.
|
/// require the len of the element, while the latter one does.
|
||||||
type UseAlternative = bool;
|
type UseAlternative = bool;
|
||||||
// Helper Alias type
|
// Helper Alias type
|
||||||
type StructFieldDescriptor = (FieldName, FieldType, IsCompact, UseAlternative);
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub struct StructFieldDescriptor {
|
||||||
|
name: String,
|
||||||
|
ftype: String,
|
||||||
|
is_compact: bool,
|
||||||
|
use_alt_impl: bool,
|
||||||
|
is_reference: bool,
|
||||||
|
}
|
||||||
// Helper Alias type
|
// Helper Alias type
|
||||||
type FieldList = Vec<FieldTypes>;
|
type FieldList = Vec<FieldTypes>;
|
||||||
|
|
||||||
@ -150,12 +153,13 @@ fn load_field_from_segments(
|
|||||||
attr.path().segments.iter().any(|path| path.ident == "maybe_zero")
|
attr.path().segments.iter().any(|path| path.ident == "maybe_zero")
|
||||||
});
|
});
|
||||||
|
|
||||||
fields.push(FieldTypes::StructField((
|
fields.push(FieldTypes::StructField(StructFieldDescriptor {
|
||||||
field.ident.as_ref().map(|i| i.to_string()).unwrap_or_default(),
|
name: field.ident.as_ref().map(|i| i.to_string()).unwrap_or_default(),
|
||||||
ftype,
|
ftype,
|
||||||
should_compact,
|
is_compact: should_compact,
|
||||||
use_alt_impl,
|
use_alt_impl,
|
||||||
)));
|
is_reference: matches!(field.ty, syn::Type::Reference(_)),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,7 +200,7 @@ fn should_use_alt_impl(ftype: &str, segment: &syn::PathSegment) -> bool {
|
|||||||
pub fn get_bit_size(ftype: &str) -> u8 {
|
pub fn get_bit_size(ftype: &str) -> u8 {
|
||||||
match ftype {
|
match ftype {
|
||||||
"TransactionKind" | "TxKind" | "bool" | "Option" | "Signature" => 1,
|
"TransactionKind" | "TxKind" | "bool" | "Option" | "Signature" => 1,
|
||||||
"TxType" => 2,
|
"TxType" | "OpTxType" => 2,
|
||||||
"u64" | "BlockNumber" | "TxNumber" | "ChainId" | "NumTransactions" => 4,
|
"u64" | "BlockNumber" | "TxNumber" | "ChainId" | "NumTransactions" => 4,
|
||||||
"u128" => 5,
|
"u128" => 5,
|
||||||
"U256" => 6,
|
"U256" => 6,
|
||||||
|
|||||||
@ -44,7 +44,8 @@ impl<'a> StructHandler<'a> {
|
|||||||
|
|
||||||
/// Generates `to_compact` code for a struct field.
|
/// Generates `to_compact` code for a struct field.
|
||||||
fn to(&mut self, field_descriptor: &StructFieldDescriptor) {
|
fn to(&mut self, field_descriptor: &StructFieldDescriptor) {
|
||||||
let (name, ftype, is_compact, use_alt_impl) = field_descriptor;
|
let StructFieldDescriptor { name, ftype, is_compact, use_alt_impl, is_reference: _ } =
|
||||||
|
field_descriptor;
|
||||||
|
|
||||||
let to_compact_ident = if *use_alt_impl {
|
let to_compact_ident = if *use_alt_impl {
|
||||||
format_ident!("specialized_to_compact")
|
format_ident!("specialized_to_compact")
|
||||||
@ -97,7 +98,7 @@ impl<'a> StructHandler<'a> {
|
|||||||
|
|
||||||
/// Generates `from_compact` code for a struct field.
|
/// Generates `from_compact` code for a struct field.
|
||||||
fn from(&mut self, field_descriptor: &StructFieldDescriptor, known_types: &[&str]) {
|
fn from(&mut self, field_descriptor: &StructFieldDescriptor, known_types: &[&str]) {
|
||||||
let (name, ftype, is_compact, use_alt_impl) = field_descriptor;
|
let StructFieldDescriptor { name, ftype, is_compact, use_alt_impl, .. } = field_descriptor;
|
||||||
|
|
||||||
let (name, len) = if name.is_empty() {
|
let (name, len) = if name.is_empty() {
|
||||||
self.is_wrapper = true;
|
self.is_wrapper = true;
|
||||||
|
|||||||
@ -25,7 +25,10 @@ use serde as _;
|
|||||||
use alloy_primitives::{Address, Bloom, Bytes, FixedBytes, U256};
|
use alloy_primitives::{Address, Bloom, Bytes, FixedBytes, U256};
|
||||||
use bytes::{Buf, BufMut};
|
use bytes::{Buf, BufMut};
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::{
|
||||||
|
borrow::{Cow, ToOwned},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "test-utils")]
|
#[cfg(feature = "test-utils")]
|
||||||
pub mod alloy;
|
pub mod alloy;
|
||||||
@ -343,6 +346,32 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Compact + ToOwned<Owned = T>> Compact for Cow<'_, T> {
|
||||||
|
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||||
|
where
|
||||||
|
B: bytes::BufMut + AsMut<[u8]>,
|
||||||
|
{
|
||||||
|
self.as_ref().to_compact(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
|
||||||
|
let (element, buf) = T::from_compact(buf, len);
|
||||||
|
(Cow::Owned(element), buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn specialized_to_compact<B>(&self, buf: &mut B) -> usize
|
||||||
|
where
|
||||||
|
B: bytes::BufMut + AsMut<[u8]>,
|
||||||
|
{
|
||||||
|
self.as_ref().specialized_to_compact(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn specialized_from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
|
||||||
|
let (element, buf) = T::specialized_from_compact(buf, len);
|
||||||
|
(Cow::Owned(element), buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Compact for U256 {
|
impl Compact for U256 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_compact<B>(&self, buf: &mut B) -> usize
|
fn to_compact<B>(&self, buf: &mut B) -> usize
|
||||||
|
|||||||
Reference in New Issue
Block a user