chore(sdk): Define helper trait MaybeCompact (#12683)

This commit is contained in:
Emilia Hane
2024-11-21 17:10:06 +01:00
committed by GitHub
parent 96f7572404
commit ad7885b48c
19 changed files with 134 additions and 87 deletions

View File

@ -528,6 +528,7 @@ tracing = "0.1.0"
tracing-appender = "0.2"
url = "2.3"
zstd = "0.13"
byteorder = "1"
# metrics
metrics = "0.24.0"

View File

@ -13,7 +13,7 @@ workspace = true
[dependencies]
# reth
reth-codecs.workspace = true
reth-codecs = { workspace = true, optional = true }
# ethereum
alloy-consensus.workspace = true
@ -24,16 +24,16 @@ alloy-rlp.workspace = true
revm-primitives.workspace = true
# misc
byteorder = "1"
byteorder = { workspace = true, optional = true }
bytes.workspace = true
derive_more.workspace = true
roaring = "0.10.2"
serde_with = { workspace = true, optional = true }
auto_impl.workspace = true
# required by reth-codecs
bytes.workspace = true
modular-bitfield.workspace = true
serde.workspace = true
modular-bitfield = { workspace = true, optional = true }
serde = { workspace = true, optional = true}
# arbitrary utils
arbitrary = { workspace = true, features = ["derive"], optional = true }
@ -50,6 +50,8 @@ proptest.workspace = true
rand.workspace = true
serde_json.workspace = true
test-fuzz.workspace = true
modular-bitfield.workspace = true
serde.workspace = true
[features]
default = ["std"]
@ -59,11 +61,11 @@ std = [
"alloy-genesis/std",
"alloy-primitives/std",
"revm-primitives/std",
"serde/std"
"serde?/std"
]
test-utils = [
"arbitrary",
"reth-codecs/test-utils"
"reth-codecs?/test-utils"
]
arbitrary = [
"std",
@ -74,7 +76,7 @@ arbitrary = [
"dep:proptest-arbitrary-interop",
"alloy-eips/arbitrary",
"revm-primitives/arbitrary",
"reth-codecs/arbitrary"
"reth-codecs?/arbitrary"
]
serde-bincode-compat = [
"serde",
@ -83,13 +85,19 @@ serde-bincode-compat = [
"alloy-eips/serde-bincode-compat"
]
serde = [
"dep:serde",
"alloy-consensus/serde",
"alloy-eips/serde",
"alloy-primitives/serde",
"bytes/serde",
"rand/serde",
"reth-codecs/serde",
"reth-codecs?/serde",
"revm-primitives/serde",
"roaring/serde",
"revm-primitives/serde",
]
reth-codec = [
"dep:reth-codecs",
"dep:modular-bitfield",
"dep:byteorder",
]

View File

@ -1,32 +1,34 @@
use alloy_consensus::constants::KECCAK_EMPTY;
use alloy_genesis::GenesisAccount;
use alloy_primitives::{keccak256, Bytes, B256, U256};
use byteorder::{BigEndian, ReadBytesExt};
use bytes::Buf;
use derive_more::Deref;
use reth_codecs::{add_arbitrary_tests, Compact};
use revm_primitives::{AccountInfo, Bytecode as RevmBytecode, BytecodeDecodeError, JumpTable};
use revm_primitives::{AccountInfo, Bytecode as RevmBytecode, BytecodeDecodeError};
/// Identifier for [`LegacyRaw`](RevmBytecode::LegacyRaw).
const LEGACY_RAW_BYTECODE_ID: u8 = 0;
#[cfg(any(test, feature = "reth-codec"))]
/// Identifiers used in [`Compact`](reth_codecs::Compact) encoding of [`Bytecode`].
pub mod compact_ids {
/// Identifier for [`LegacyRaw`](revm_primitives::Bytecode::LegacyRaw).
pub const LEGACY_RAW_BYTECODE_ID: u8 = 0;
/// Identifier for removed bytecode variant.
const REMOVED_BYTECODE_ID: u8 = 1;
pub const REMOVED_BYTECODE_ID: u8 = 1;
/// Identifier for [`LegacyAnalyzed`](RevmBytecode::LegacyAnalyzed).
const LEGACY_ANALYZED_BYTECODE_ID: u8 = 2;
/// Identifier for [`LegacyAnalyzed`](revm_primitives::Bytecode::LegacyAnalyzed).
pub const LEGACY_ANALYZED_BYTECODE_ID: u8 = 2;
/// Identifier for [`Eof`](RevmBytecode::Eof).
const EOF_BYTECODE_ID: u8 = 3;
/// Identifier for [`Eof`](revm_primitives::Bytecode::Eof).
pub const EOF_BYTECODE_ID: u8 = 3;
/// Identifier for [`Eip7702`](RevmBytecode::Eip7702).
const EIP7702_BYTECODE_ID: u8 = 4;
/// Identifier for [`Eip7702`](revm_primitives::Bytecode::Eip7702).
pub const EIP7702_BYTECODE_ID: u8 = 4;
}
/// An Ethereum account.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Compact)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[add_arbitrary_tests(compact)]
#[cfg_attr(any(test, feature = "reth-codec"), derive(reth_codecs::Compact))]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
pub struct Account {
/// Account nonce.
pub nonce: u64,
@ -85,11 +87,17 @@ impl Bytecode {
}
}
impl Compact for Bytecode {
#[cfg(any(test, feature = "reth-codec"))]
impl reth_codecs::Compact for Bytecode {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
use compact_ids::{
EIP7702_BYTECODE_ID, EOF_BYTECODE_ID, LEGACY_ANALYZED_BYTECODE_ID,
LEGACY_RAW_BYTECODE_ID,
};
let bytecode = match &self.0 {
RevmBytecode::LegacyRaw(bytes) => bytes,
RevmBytecode::LegacyAnalyzed(analyzed) => analyzed.bytecode(),
@ -128,7 +136,12 @@ impl Compact for Bytecode {
// A panic will be triggered if a bytecode variant of 1 or greater than 2 is passed from the
// database.
fn from_compact(mut buf: &[u8], _: usize) -> (Self, &[u8]) {
let len = buf.read_u32::<BigEndian>().expect("could not read bytecode length");
use byteorder::ReadBytesExt;
use bytes::Buf;
use compact_ids::*;
let len = buf.read_u32::<byteorder::BigEndian>().expect("could not read bytecode length");
let bytes = Bytes::from(buf.copy_to_bytes(len as usize));
let variant = buf.read_u8().expect("could not read bytecode variant");
let decoded = match variant {
@ -139,8 +152,8 @@ impl Compact for Bytecode {
LEGACY_ANALYZED_BYTECODE_ID => Self(unsafe {
RevmBytecode::new_analyzed(
bytes,
buf.read_u64::<BigEndian>().unwrap() as usize,
JumpTable::from_slice(buf),
buf.read_u64::<byteorder::BigEndian>().unwrap() as usize,
revm_primitives::JumpTable::from_slice(buf),
)
}),
EOF_BYTECODE_ID | EIP7702_BYTECODE_ID => {
@ -187,9 +200,11 @@ impl From<Account> for AccountInfo {
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::{hex_literal::hex, B256, U256};
use revm_primitives::LegacyAnalyzedBytecode;
use reth_codecs::Compact;
use revm_primitives::{JumpTable, LegacyAnalyzedBytecode};
use super::*;
#[test]
fn test_account() {

View File

@ -28,7 +28,6 @@ pub trait BlockBody:
+ MaybeSerde
{
/// Ordered list of signed transactions as committed in block.
// todo: requires trait for signed transaction
type Transaction: Transaction;
/// Returns reference to transactions in block.

View File

@ -3,15 +3,14 @@
use core::fmt;
use alloy_primitives::Sealable;
use reth_codecs::Compact;
use crate::{InMemorySize, MaybeSerde};
use crate::{InMemorySize, MaybeCompact, MaybeSerde};
/// Helper trait that unifies all behaviour required by block header to support full node
/// operations.
pub trait FullBlockHeader: BlockHeader + Compact {}
pub trait FullBlockHeader: BlockHeader + MaybeCompact {}
impl<T> FullBlockHeader for T where T: BlockHeader + Compact {}
impl<T> FullBlockHeader for T where T: BlockHeader + MaybeCompact {}
/// Abstraction of a block header.
pub trait BlockHeader:

View File

@ -5,18 +5,18 @@ pub mod header;
use alloc::fmt;
use alloy_rlp::{Decodable, Encodable};
use crate::{BlockHeader, FullBlockBody, FullBlockHeader, InMemorySize, MaybeSerde};
/// Helper trait that unifies all behaviour required by block to support full node operations.
pub trait FullBlock:
Block<Header: FullBlockHeader, Body: FullBlockBody> + Encodable + Decodable
Block<Header: FullBlockHeader, Body: FullBlockBody> + alloy_rlp::Encodable + alloy_rlp::Decodable
{
}
impl<T> FullBlock for T where
T: Block<Header: FullBlockHeader, Body: FullBlockBody> + Encodable + Decodable
T: Block<Header: FullBlockHeader, Body: FullBlockBody>
+ alloy_rlp::Encodable
+ alloy_rlp::Decodable
{
}

View File

@ -1,17 +1,19 @@
use crate::InMemorySize;
pub use alloy_consensus::Header;
use core::mem;
use alloy_consensus::Sealed;
use alloy_eips::BlockNumHash;
use alloy_primitives::{keccak256, BlockHash, Sealable, B256};
use alloy_rlp::{Decodable, Encodable};
use bytes::BufMut;
use core::mem;
use derive_more::{AsRef, Deref};
use reth_codecs::add_arbitrary_tests;
use serde::{Deserialize, Serialize};
use crate::InMemorySize;
/// A helper struct to store the block number/hash and its parent hash.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BlockWithParent {
/// Parent hash.
pub parent: B256,
@ -21,8 +23,9 @@ pub struct BlockWithParent {
/// A [`Header`] that is sealed at a precalculated hash, use [`SealedHeader::unseal()`] if you want
/// to modify header.
#[derive(Debug, Clone, PartialEq, Eq, Hash, AsRef, Deref, Serialize, Deserialize)]
#[add_arbitrary_tests(rlp)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, AsRef, Deref)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(rlp))]
pub struct SealedHeader<H = Header> {
/// Locked Header hash.
hash: BlockHash,

View File

@ -1,13 +1,9 @@
use alloc::vec::Vec;
use bytes::BufMut;
use core::fmt;
use bytes::BufMut;
use derive_more::Deref;
use roaring::RoaringTreemap;
use serde::{
de::{SeqAccess, Visitor},
ser::SerializeSeq,
Deserialize, Deserializer, Serialize, Serializer,
};
/// A data structure that uses Roaring Bitmaps to efficiently store a list of integers.
///
@ -90,11 +86,14 @@ impl IntegerList {
}
}
impl Serialize for IntegerList {
#[cfg(feature = "serde")]
impl serde::Serialize for IntegerList {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
S: serde::Serializer,
{
use serde::ser::SerializeSeq;
let mut seq = serializer.serialize_seq(Some(self.len() as usize))?;
for e in &self.0 {
seq.serialize_element(&e)?;
@ -103,8 +102,11 @@ impl Serialize for IntegerList {
}
}
#[cfg(feature = "serde")]
struct IntegerListVisitor;
impl<'de> Visitor<'de> for IntegerListVisitor {
#[cfg(feature = "serde")]
impl<'de> serde::de::Visitor<'de> for IntegerListVisitor {
type Value = IntegerList;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -113,7 +115,7 @@ impl<'de> Visitor<'de> for IntegerListVisitor {
fn visit_seq<E>(self, mut seq: E) -> Result<Self::Value, E::Error>
where
E: SeqAccess<'de>,
E: serde::de::SeqAccess<'de>,
{
let mut list = IntegerList::empty();
while let Some(item) = seq.next_element()? {
@ -123,10 +125,11 @@ impl<'de> Visitor<'de> for IntegerListVisitor {
}
}
impl<'de> Deserialize<'de> for IntegerList {
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for IntegerList {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
D: serde::Deserializer<'de>,
{
deserializer.deserialize_byte_buf(IntegerListVisitor)
}

View File

@ -103,3 +103,17 @@ pub trait MaybeSerde {}
impl<T> MaybeSerde for T where T: serde::Serialize + for<'de> serde::Deserialize<'de> {}
#[cfg(not(feature = "serde"))]
impl<T> MaybeSerde for T {}
/// Helper trait that requires database encoding implementation since `reth-codec` feature is
/// enabled.
#[cfg(feature = "reth-codec")]
pub trait MaybeCompact: reth_codecs::Compact {}
/// Noop. Helper trait that would require database encoding implementation if `reth-codec` feature
/// were enabled.
#[cfg(not(feature = "reth-codec"))]
pub trait MaybeCompact {}
#[cfg(feature = "reth-codec")]
impl<T> MaybeCompact for T where T: reth_codecs::Compact {}
#[cfg(not(feature = "reth-codec"))]
impl<T> MaybeCompact for T {}

View File

@ -1,16 +1,17 @@
//! Receipt abstraction
use crate::{InMemorySize, MaybeSerde};
use core::fmt;
use alloc::vec::Vec;
use alloy_consensus::TxReceipt;
use alloy_primitives::B256;
use core::fmt;
use reth_codecs::Compact;
use crate::{InMemorySize, MaybeCompact, MaybeSerde};
/// Helper trait that unifies all behaviour required by receipt to support full node operations.
pub trait FullReceipt: Receipt + Compact {}
pub trait FullReceipt: Receipt + MaybeCompact {}
impl<T> FullReceipt for T where T: ReceiptExt + Compact {}
impl<T> FullReceipt for T where T: ReceiptExt + MaybeCompact {}
/// Abstraction of a receipt.
#[auto_impl::auto_impl(&, Arc)]

View File

@ -1,13 +1,12 @@
use alloy_primitives::{B256, U256};
use reth_codecs::{add_arbitrary_tests, Compact};
use serde::{Deserialize, Serialize};
/// Account storage entry.
///
/// `key` is the subkey when used as a value in the `StorageChangeSets` table.
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[add_arbitrary_tests(compact)]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
pub struct StorageEntry {
/// Storage key.
pub key: B256,
@ -31,7 +30,8 @@ impl From<(B256, U256)> for StorageEntry {
// NOTE: Removing reth_codec and manually encode subkey
// and compress second part of the value. If we have compression
// over whole value (Even SubKey) that would mess up fetching of values with seek_by_key_subkey
impl Compact for StorageEntry {
#[cfg(any(test, feature = "reth-codec"))]
impl reth_codecs::Compact for StorageEntry {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,

View File

@ -7,14 +7,13 @@ pub mod tx_type;
use core::{fmt, hash::Hash};
use alloy_primitives::B256;
use reth_codecs::Compact;
use crate::{FullTxType, InMemorySize, MaybeArbitrary, MaybeSerde, TxType};
use crate::{FullTxType, InMemorySize, MaybeArbitrary, MaybeCompact, MaybeSerde, TxType};
/// Helper trait that unifies all behaviour required by transaction to support full node operations.
pub trait FullTransaction: Transaction<Type: FullTxType> + Compact {}
pub trait FullTransaction: Transaction<Type: FullTxType> + MaybeCompact {}
impl<T> FullTransaction for T where T: Transaction<Type: FullTxType> + Compact {}
impl<T> FullTransaction for T where T: Transaction<Type: FullTxType> + MaybeCompact {}
/// Abstraction of a transaction.
pub trait Transaction:

View File

@ -5,18 +5,19 @@ use core::hash::Hash;
use alloy_eips::eip2718::{Decodable2718, Encodable2718};
use alloy_primitives::{keccak256, Address, PrimitiveSignature, TxHash, B256};
use reth_codecs::Compact;
use crate::{FillTxEnv, FullTransaction, InMemorySize, MaybeArbitrary, MaybeSerde, Transaction};
use crate::{
FillTxEnv, FullTransaction, InMemorySize, MaybeArbitrary, MaybeCompact, MaybeSerde, Transaction,
};
/// Helper trait that unifies all behaviour required by block to support full node operations.
pub trait FullSignedTx:
SignedTransaction<Transaction: FullTransaction> + FillTxEnv + Compact
SignedTransaction<Transaction: FullTransaction> + FillTxEnv + MaybeCompact
{
}
impl<T> FullSignedTx for T where
T: SignedTransaction<Transaction: FullTransaction> + FillTxEnv + Compact
T: SignedTransaction<Transaction: FullTransaction> + FillTxEnv + MaybeCompact
{
}
@ -41,7 +42,7 @@ pub trait SignedTransaction:
+ MaybeArbitrary
+ InMemorySize
{
/// Transaction type that is signed.
/// Unsigned transaction type.
type Transaction: Transaction;
/// Returns reference to transaction hash.

View File

@ -3,15 +3,14 @@
use core::fmt;
use alloy_primitives::{U64, U8};
use reth_codecs::Compact;
use crate::InMemorySize;
use crate::{InMemorySize, MaybeCompact};
/// Helper trait that unifies all behaviour required by transaction type ID to support full node
/// operations.
pub trait FullTxType: TxType + Compact {}
pub trait FullTxType: TxType + MaybeCompact {}
impl<T> FullTxType for T where T: TxType + Compact {}
impl<T> FullTxType for T where T: TxType + MaybeCompact {}
/// Trait representing the behavior of a transaction type.
pub trait TxType:

View File

@ -105,7 +105,12 @@ std = [
"serde/std",
"alloy-trie/std"
]
reth-codec = ["dep:reth-codecs", "dep:zstd", "dep:modular-bitfield", "std"]
reth-codec = [
"dep:reth-codecs",
"dep:zstd",
"dep:modular-bitfield", "std",
"reth-primitives-traits/reth-codec",
]
asm-keccak = ["alloy-primitives/asm-keccak", "revm-primitives/asm-keccak"]
arbitrary = [
"dep:arbitrary",

View File

@ -16,7 +16,7 @@ workspace = true
reth-codecs.workspace = true
reth-db-models.workspace = true
reth-primitives = { workspace = true, features = ["reth-codec"] }
reth-primitives-traits = { workspace = true, features = ["serde"] }
reth-primitives-traits = { workspace = true, features = ["serde", "reth-codec"] }
reth-prune-types.workspace = true
reth-stages-types.workspace = true
reth-storage-errors.workspace = true

View File

@ -14,7 +14,7 @@ workspace = true
[dependencies]
# reth
reth-codecs.workspace = true
reth-primitives-traits = { workspace = true, features = ["serde"] }
reth-primitives-traits = { workspace = true, features = ["serde", "reth-codec"] }
# ethereum
alloy-primitives.workspace = true

View File

@ -15,7 +15,7 @@ workspace = true
# reth
reth-db-api.workspace = true
reth-primitives = { workspace = true, features = ["reth-codec"] }
reth-primitives-traits = { workspace = true, features = ["serde"] }
reth-primitives-traits = { workspace = true, features = ["serde", "reth-codec"] }
reth-fs-util.workspace = true
reth-storage-errors.workspace = true
reth-nippy-jar.workspace = true

View File

@ -17,7 +17,7 @@ reth-chainspec.workspace = true
reth-blockchain-tree-api.workspace = true
reth-execution-types.workspace = true
reth-primitives = { workspace = true, features = ["reth-codec", "secp256k1"] }
reth-primitives-traits.workspace = true
reth-primitives-traits = { workspace = true, features = ["reth-codec"] }
reth-fs-util.workspace = true
reth-errors.workspace = true
reth-storage-errors.workspace = true