Skip to content

Commit

Permalink
chore(sdk): Define helper trait MaybeCompact (paradigmxyz#12683)
Browse files Browse the repository at this point in the history
  • Loading branch information
emhane authored Nov 21, 2024
1 parent 96f7572 commit ad7885b
Show file tree
Hide file tree
Showing 19 changed files with 134 additions and 87 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
26 changes: 17 additions & 9 deletions crates/primitives-traits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ workspace = true

[dependencies]
# reth
reth-codecs.workspace = true
reth-codecs = { workspace = true, optional = true }

# ethereum
alloy-consensus.workspace = true
Expand All @@ -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 }
Expand All @@ -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"]
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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",
]
59 changes: 37 additions & 22 deletions crates/primitives-traits/src/account.rs
Original file line number Diff line number Diff line change
@@ -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;
/// Identifier for removed bytecode variant.
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,
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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 {
Expand All @@ -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 => {
Expand Down Expand Up @@ -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() {
Expand Down
1 change: 0 additions & 1 deletion crates/primitives-traits/src/block/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 3 additions & 4 deletions crates/primitives-traits/src/block/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions crates/primitives-traits/src/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
}

Expand Down
17 changes: 10 additions & 7 deletions crates/primitives-traits/src/header/sealed.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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,
Expand Down
27 changes: 15 additions & 12 deletions crates/primitives-traits/src/integer_list.rs
Original file line number Diff line number Diff line change
@@ -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.
///
Expand Down Expand Up @@ -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)?;
Expand All @@ -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 {
Expand All @@ -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()? {
Expand All @@ -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)
}
Expand Down
14 changes: 14 additions & 0 deletions crates/primitives-traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
11 changes: 6 additions & 5 deletions crates/primitives-traits/src/receipt.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down
Loading

0 comments on commit ad7885b

Please sign in to comment.