feat: feature gate reth-codec impl (#9492)

This commit is contained in:
Matthias Seitz
2024-07-16 16:39:31 +02:00
committed by GitHub
parent a322a7c83e
commit bc31f5da58
11 changed files with 51 additions and 141 deletions

View File

@@ -14,12 +14,12 @@ workspace = true
[dependencies]
# reth
reth-primitives-traits.workspace = true
reth-codecs.workspace = true
reth-ethereum-forks.workspace = true
reth-static-file-types.workspace = true
reth-trie-common.workspace = true
revm-primitives = { workspace = true, features = ["serde"] }
reth-chainspec = { workspace = true, optional = true }
reth-codecs = { workspace = true, optional = true }
# ethereum
alloy-primitives = { workspace = true, features = ["rand", "rlp"] }
@@ -58,6 +58,7 @@ proptest = { workspace = true, optional = true }
reth-primitives-traits = { workspace = true, features = ["arbitrary"] }
revm-primitives = { workspace = true, features = ["arbitrary"] }
reth-chainspec.workspace = true
reth-codecs.workspace = true
nybbles = { workspace = true, features = ["arbitrary"] }
alloy-trie = { workspace = true, features = ["arbitrary"] }
alloy-eips = { workspace = true, features = ["arbitrary"] }
@@ -84,7 +85,8 @@ pprof = { workspace = true, features = [
secp256k1.workspace = true
[features]
default = ["c-kzg", "zstd-codec", "alloy-compat", "std"]
default = ["c-kzg", "alloy-compat", "std", "reth-codec"]
reth-codec = ["dep:reth-codecs", "dep:zstd"]
asm-keccak = ["alloy-primitives/asm-keccak"]
arbitrary = [
"reth-primitives-traits/arbitrary",
@@ -96,10 +98,9 @@ arbitrary = [
"alloy-eips/arbitrary",
"dep:arbitrary",
"dep:proptest",
"zstd-codec",
"reth-codec",
]
c-kzg = ["dep:c-kzg", "revm-primitives/c-kzg", "dep:tempfile", "alloy-eips/kzg"]
zstd-codec = ["dep:zstd"]
optimism = [
"reth-chainspec/optimism",
"reth-ethereum-forks/optimism",

View File

@@ -7,6 +7,8 @@
//! - `alloy-compat`: Adds compatibility conversions for certain alloy types.
//! - `arbitrary`: Adds `proptest` and `arbitrary` support for primitive types.
//! - `test-utils`: Export utilities for testing
//! - `reth-codec`: Enables db codec support for reth types including zstd compression for certain
//! types.
#![doc(
html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
@@ -24,7 +26,7 @@ extern crate alloc;
mod alloy_compat;
pub mod basefee;
mod block;
#[cfg(feature = "zstd-codec")]
#[cfg(feature = "reth-codec")]
mod compression;
pub mod constants;
pub mod eip4844;
@@ -40,7 +42,7 @@ pub use block::{
Block, BlockBody, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag, BlockWithSenders,
ForkBlock, RpcBlockHash, SealedBlock, SealedBlockWithSenders,
};
#[cfg(feature = "zstd-codec")]
#[cfg(feature = "reth-codec")]
pub use compression::*;
pub use constants::{
DEV_GENESIS_HASH, EMPTY_OMMER_ROOT_HASH, HOLESKY_GENESIS_HASH, KECCAK_EMPTY,

View File

@@ -1,4 +1,4 @@
#[cfg(feature = "zstd-codec")]
#[cfg(feature = "reth-codec")]
use crate::compression::{RECEIPT_COMPRESSOR, RECEIPT_DECOMPRESSOR};
use crate::{logs_bloom, Bloom, Bytes, TxType, B256};
use alloy_primitives::Log;
@@ -6,18 +6,16 @@ use alloy_rlp::{length_of_length, Decodable, Encodable, RlpDecodable, RlpEncodab
use bytes::{Buf, BufMut};
use core::{cmp::Ordering, ops::Deref};
use derive_more::{Deref, DerefMut, From, IntoIterator};
#[cfg(feature = "zstd-codec")]
use reth_codecs::CompactZstd;
use reth_codecs::{add_arbitrary_tests, reth_codec, Compact};
#[cfg(feature = "reth-codec")]
use reth_codecs::{Compact, CompactZstd};
use serde::{Deserialize, Serialize};
#[cfg(not(feature = "std"))]
use alloc::{vec, vec::Vec};
/// Receipt containing result of transaction execution.
#[cfg_attr(feature = "zstd-codec", reth_codec(no_arbitrary, zstd))]
#[cfg_attr(not(feature = "zstd-codec"), reth_codec(no_arbitrary))]
#[add_arbitrary_tests]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::reth_codec(no_arbitrary, zstd))]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests)]
#[derive(Clone, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)]
#[rlp(trailing)]
pub struct Receipt {
@@ -142,7 +140,7 @@ impl From<Receipt> for ReceiptWithBloom {
}
/// [`Receipt`] with calculated bloom filter.
#[reth_codec]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::reth_codec)]
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct ReceiptWithBloom {
/// Bloom filter build from logs.

View File

@@ -2,13 +2,13 @@ use super::access_list::AccessList;
use crate::{keccak256, Bytes, ChainId, Signature, TxKind, TxType, B256, U256};
use alloy_rlp::{length_of_length, Decodable, Encodable, Header};
use core::mem;
use reth_codecs::{reth_codec, Compact};
use reth_codecs::Compact;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
/// A transaction with a priority fee ([EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)).
#[reth_codec]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::reth_codec)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct TxEip1559 {
/// Added as EIP-155: Simple replay attack protection

View File

@@ -2,13 +2,13 @@ use super::access_list::AccessList;
use crate::{keccak256, Bytes, ChainId, Signature, TxKind, TxType, B256, U256};
use alloy_rlp::{length_of_length, Decodable, Encodable, Header};
use core::mem;
use reth_codecs::{reth_codec, Compact};
use reth_codecs::Compact;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
/// Transaction with an [`AccessList`] ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930)).
#[reth_codec]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::reth_codec)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct TxEip2930 {
/// Added as EIP-155: Simple replay attack protection

View File

@@ -5,7 +5,7 @@ use crate::{
};
use alloy_rlp::{length_of_length, Decodable, Encodable, Header};
use core::mem;
use reth_codecs::{reth_codec, Compact, CompactPlaceholder};
use reth_codecs::{Compact, CompactPlaceholder};
#[cfg(feature = "c-kzg")]
use crate::kzg::KzgSettings;
@@ -16,7 +16,7 @@ use alloc::vec::Vec;
/// [EIP-4844 Blob Transaction](https://eips.ethereum.org/EIPS/eip-4844#blob-transaction)
///
/// A transaction with blob hashes and max blob fee
#[reth_codec]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::reth_codec)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct TxEip4844 {
/// Added as EIP-155: Simple replay attack protection

View File

@@ -7,7 +7,7 @@ use reth_codecs::{reth_codec, Compact};
use alloc::vec::Vec;
/// Legacy transaction.
#[reth_codec]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codec)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct TxLegacy {
/// Added as EIP-155: Simple replay attack protection

View File

@@ -1,7 +1,5 @@
//! Transaction types.
#[cfg(any(feature = "arbitrary", feature = "zstd-codec"))]
use crate::compression::{TRANSACTION_COMPRESSOR, TRANSACTION_DECOMPRESSOR};
use crate::{
eip7702::SignedAuthorization, keccak256, Address, BlockHashOrNumber, Bytes, TxHash, TxKind,
B256, U256,
@@ -15,7 +13,6 @@ use core::mem;
use derive_more::{AsRef, Deref};
use once_cell::sync::Lazy;
use rayon::prelude::{IntoParallelIterator, ParallelIterator};
use reth_codecs::{add_arbitrary_tests, derive_arbitrary, Compact};
use serde::{Deserialize, Serialize};
pub use access_list::{AccessList, AccessListItem};
@@ -68,6 +65,9 @@ pub use optimism::TxDeposit;
#[cfg(feature = "optimism")]
pub use tx_type::DEPOSIT_TX_TYPE_ID;
#[cfg(test)]
use reth_codecs::Compact;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
@@ -86,7 +86,7 @@ pub(crate) static PARALLEL_SENDER_RECOVERY_THRESHOLD: Lazy<usize> =
/// A raw transaction.
///
/// Transaction types were introduced in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718).
#[derive_arbitrary(compact)]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::derive_arbitrary(compact))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Transaction {
/// Legacy transaction (type `0x0`).
@@ -679,7 +679,8 @@ impl From<TxEip7702> for Transaction {
}
}
impl Compact for Transaction {
#[cfg(any(test, feature = "reth-codec"))]
impl reth_codecs::Compact for Transaction {
// Serializes the TxType to the buffer if necessary, returning 2 bits of the type as an
// identifier instead of the length.
fn to_compact<B>(self, buf: &mut B) -> usize
@@ -811,7 +812,7 @@ impl Encodable for Transaction {
/// Signed transaction without its Hash. Used type for inserting into the DB.
///
/// This can by converted to [`TransactionSigned`] by calling [`TransactionSignedNoHash::hash`].
#[derive_arbitrary(compact)]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::derive_arbitrary(compact))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, AsRef, Deref, Default, Serialize, Deserialize)]
pub struct TransactionSignedNoHash {
/// The transaction signature values
@@ -909,8 +910,8 @@ impl TransactionSignedNoHash {
}
}
#[cfg(feature = "zstd-codec")]
impl Compact for TransactionSignedNoHash {
#[cfg(any(test, feature = "reth-codec"))]
impl reth_codecs::Compact for TransactionSignedNoHash {
fn to_compact<B>(self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
@@ -925,7 +926,7 @@ impl Compact for TransactionSignedNoHash {
let zstd_bit = self.transaction.input().len() >= 32;
let tx_bits = if zstd_bit {
TRANSACTION_COMPRESSOR.with(|compressor| {
crate::compression::TRANSACTION_COMPRESSOR.with(|compressor| {
let mut compressor = compressor.borrow_mut();
let mut tmp = Vec::with_capacity(256);
let tx_bits = self.transaction.to_compact(&mut tmp);
@@ -953,7 +954,7 @@ impl Compact for TransactionSignedNoHash {
let zstd_bit = bitflags >> 3;
let (transaction, buf) = if zstd_bit != 0 {
TRANSACTION_DECOMPRESSOR.with(|decompressor| {
crate::compression::TRANSACTION_DECOMPRESSOR.with(|decompressor| {
let mut decompressor = decompressor.borrow_mut();
// TODO: enforce that zstd is only present at a "top" level type
@@ -973,63 +974,6 @@ impl Compact for TransactionSignedNoHash {
}
}
#[cfg(not(feature = "zstd-codec"))]
impl Compact for TransactionSignedNoHash {
fn to_compact<B>(self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
to_compact_ztd_unaware(self, buf)
}
fn from_compact(buf: &[u8], _len: usize) -> (Self, &[u8]) {
from_compact_zstd_unaware(buf, _len)
}
}
// Allowing dead code, as this function is extracted from behind feature, so it can be tested
#[allow(dead_code)]
fn to_compact_ztd_unaware<B>(transaction: TransactionSignedNoHash, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
let start = buf.as_mut().len();
// Placeholder for bitflags.
// The first byte uses 4 bits as flags: IsCompressed[1bit], TxType[2bits], Signature[1bit]
buf.put_u8(0);
let sig_bit = transaction.signature.to_compact(buf) as u8;
let zstd_bit = false;
let tx_bits = transaction.transaction.to_compact(buf) as u8;
// Replace bitflags with the actual values
buf.as_mut()[start] = sig_bit | (tx_bits << 1) | ((zstd_bit as u8) << 3);
buf.as_mut().len() - start
}
// Allowing dead code, as this function is extracted from behind feature, so it can be tested
#[allow(dead_code)]
fn from_compact_zstd_unaware(mut buf: &[u8], _len: usize) -> (TransactionSignedNoHash, &[u8]) {
// The first byte uses 4 bits as flags: IsCompressed[1], TxType[2], Signature[1]
let bitflags = buf.get_u8() as usize;
let sig_bit = bitflags & 1;
let (signature, buf) = Signature::from_compact(buf, sig_bit);
let zstd_bit = bitflags >> 3;
assert_eq!(
zstd_bit, 0,
"zstd-codec feature is not enabled, cannot decode `TransactionSignedNoHash` with zstd flag"
);
let transaction_type = bitflags >> 1;
let (transaction, buf) = Transaction::from_compact(buf, transaction_type);
(TransactionSignedNoHash { signature, transaction }, buf)
}
impl From<TransactionSignedNoHash> for TransactionSigned {
fn from(tx: TransactionSignedNoHash) -> Self {
tx.with_hash()
@@ -1043,7 +987,7 @@ impl From<TransactionSigned> for TransactionSignedNoHash {
}
/// Signed transaction.
#[add_arbitrary_tests(rlp)]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(rlp))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, AsRef, Deref, Default, Serialize, Deserialize)]
pub struct TransactionSigned {
/// Transaction hash
@@ -1754,8 +1698,7 @@ mod tests {
use crate::{
hex, sign_message,
transaction::{
from_compact_zstd_unaware, signature::Signature, to_compact_ztd_unaware, TxEip1559,
TxKind, TxLegacy, PARALLEL_SENDER_RECOVERY_THRESHOLD,
signature::Signature, TxEip1559, TxKind, TxLegacy, PARALLEL_SENDER_RECOVERY_THRESHOLD,
},
Address, Bytes, Transaction, TransactionSigned, TransactionSignedEcRecovered,
TransactionSignedNoHash, B256, U256,
@@ -2145,46 +2088,6 @@ mod tests {
let written_bytes = tx_signed_no_hash.clone().to_compact(&mut buff);
let (decoded, _) = TransactionSignedNoHash::from_compact(&buff, written_bytes);
assert_eq!(tx_signed_no_hash, decoded);
// zstd unaware `to_compact`/`from_compact`
let mut buff: Vec<u8> = Vec::new();
let written_bytes = to_compact_ztd_unaware(tx_signed_no_hash.clone(), &mut buff);
let (decoded_no_zstd, _something) = from_compact_zstd_unaware(&buff, written_bytes);
assert_eq!(tx_signed_no_hash, decoded_no_zstd);
// zstd unaware `to_compact`, but decode with zstd awareness
let mut buff: Vec<u8> = Vec::new();
let written_bytes = to_compact_ztd_unaware(tx_signed_no_hash.clone(), &mut buff);
let (decoded, _) = TransactionSignedNoHash::from_compact(&buff, written_bytes);
assert_eq!(tx_signed_no_hash, decoded);
}
#[test]
#[should_panic(
expected = "zstd-codec feature is not enabled, cannot decode `TransactionSignedNoHash` with zstd flag"
)]
fn transaction_signed_zstd_encoded_no_zstd_decode() {
let signature = Signature {
odd_y_parity: false,
r: U256::from_str("0xeb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5ae")
.unwrap(),
s: U256::from_str("0x3a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca18")
.unwrap(),
};
let transaction = Transaction::Legacy(TxLegacy {
chain_id: Some(4u64),
nonce: 2,
gas_price: 1000000000,
gas_limit: 100000,
to: Address::from_str("d3e8763675e4c425df46cc3b5c0f6cbdac396046").unwrap().into(),
value: U256::from(1000000000000000u64),
input: Bytes::from(vec![3u8; 64]),
});
let tx_signed_no_hash = TransactionSignedNoHash { signature, transaction };
let mut buff: Vec<u8> = Vec::new();
let written_bytes = tx_signed_no_hash.to_compact(&mut buff);
from_compact_zstd_unaware(&buff, written_bytes);
}
#[test]

View File

@@ -7,7 +7,7 @@ use reth_codecs::{reth_codec, Compact};
use std::mem;
/// Deposit transactions, also known as deposits are initiated on L1, and executed on L2.
#[reth_codec]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codec)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct TxDeposit {
/// Hash that uniquely identifies the source of the deposit.

View File

@@ -2,9 +2,11 @@ use crate::{transaction::util::secp256k1, Address, B256, U256};
use alloy_primitives::Bytes;
use alloy_rlp::{Decodable, Encodable, Error as RlpError};
use bytes::Buf;
use reth_codecs::{derive_arbitrary, Compact};
use serde::{Deserialize, Serialize};
#[cfg(test)]
use reth_codecs::Compact;
/// The order of the secp256k1 curve, divided by two. Signatures that should be checked according
/// to EIP-2 should have an S value less than or equal to this.
///
@@ -17,7 +19,7 @@ const SECP256K1N_HALF: U256 = U256::from_be_bytes([
/// r, s: Values corresponding to the signature of the
/// transaction and used to determine the sender of
/// the transaction; formally Tr and Ts. This is expanded in Appendix F of yellow paper.
#[derive_arbitrary(compact)]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::derive_arbitrary(compact))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
pub struct Signature {
/// The R field of the signature; the point on the curve.
@@ -40,7 +42,8 @@ impl Signature {
}
}
impl Compact for Signature {
#[cfg(any(test, feature = "reth-codec"))]
impl reth_codecs::Compact for Signature {
fn to_compact<B>(self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,

View File

@@ -1,9 +1,11 @@
use crate::{U64, U8};
use alloy_rlp::{Decodable, Encodable};
use bytes::Buf;
use reth_codecs::{derive_arbitrary, Compact};
use serde::{Deserialize, Serialize};
#[cfg(test)]
use reth_codecs::Compact;
/// For backwards compatibility purposes only 2 bits of the type are encoded in the identifier
/// parameter. In the case of a 3, the full transaction type is read from the buffer as a
/// single byte.
@@ -31,12 +33,12 @@ pub const DEPOSIT_TX_TYPE_ID: u8 = 126;
/// Transaction Type
///
/// Currently being used as 2-bit type when encoding it to [`Compact`] on
/// Currently being used as 2-bit type when encoding it to `reth_codecs::Compact` on
/// [`crate::TransactionSignedNoHash`]. Adding more transaction types will break the codec and
/// database format.
///
/// Other required changes when adding a new type can be seen on [PR#3953](https://github.com/paradigmxyz/reth/pull/3953/files).
#[derive_arbitrary(compact)]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::derive_arbitrary(compact))]
#[derive(
Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize, Hash,
)]
@@ -134,7 +136,8 @@ impl TryFrom<U64> for TxType {
}
}
impl Compact for TxType {
#[cfg(any(test, feature = "reth-codec"))]
impl reth_codecs::Compact for TxType {
fn to_compact<B>(self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
@@ -217,9 +220,9 @@ impl Decodable for TxType {
#[cfg(test)]
mod tests {
use rand::Rng;
use crate::hex;
use rand::Rng;
use reth_codecs::Compact;
use super::*;