Skip to content

Commit

Permalink
Blanket impl BlockBody for Block types
Browse files Browse the repository at this point in the history
  • Loading branch information
emhane committed Nov 24, 2024
1 parent 0d6ebec commit cde76d6
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 39 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 15 additions & 8 deletions crates/primitives-traits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
description = "Common types in reth."
description = "Reth abstraction of EVM data primitives."

[lints]
workspace = true
Expand All @@ -23,19 +23,25 @@ alloy-primitives.workspace = true
alloy-rlp.workspace = true
revm-primitives.workspace = true

# misc
# async
once_cell.workspace = true

# io
rayon.workspace = true

# codec
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
modular-bitfield = { workspace = true, optional = true }
serde = { workspace = true, optional = true}

# arbitrary utils
# misc
derive_more.workspace = true
auto_impl.workspace = true

# test-utils
arbitrary = { workspace = true, features = ["derive"], optional = true }
proptest = { workspace = true, optional = true }
proptest-arbitrary-interop = { workspace = true, optional = true }
Expand All @@ -61,7 +67,8 @@ std = [
"alloy-genesis/std",
"alloy-primitives/std",
"revm-primitives/std",
"serde?/std"
"serde?/std",
"once_cell/std",
]
test-utils = [
"arbitrary",
Expand Down
208 changes: 200 additions & 8 deletions crates/primitives-traits/src/block/body.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
//! Block body abstraction.
use alloc::fmt;
use alloc::vec::Vec;
use core::fmt;
#[cfg(feature = "std")]
use std::sync::LazyLock;

use alloy_consensus::Transaction;
use alloy_eips::eip4895::Withdrawal;
use alloy_primitives::{Address, B256};
use once_cell as _;
#[cfg(not(feature = "std"))]
use once_cell::sync::Lazy as LazyLock;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};

use crate::{FullSignedTx, InMemorySize, MaybeArbitrary, MaybeSerde};
use crate::{
Block, FullSignedTx, InMemorySize, MaybeArbitrary, MaybeSerde, SignedTransaction, TxType,
};

/// Helper trait that unifies all behaviour required by transaction to support full node operations.
/// Expected number of transactions where we can expect a speed-up by recovering the senders in
/// parallel.
pub static PARALLEL_SENDER_RECOVERY_THRESHOLD: LazyLock<usize> =
LazyLock::new(|| match rayon::current_num_threads() {
0..=1 => usize::MAX,
2..=8 => 10,
_ => 5,
});

/// Helper trait that unifies all behaviour required by block to support full node operations.
pub trait FullBlockBody: BlockBody<Transaction: FullSignedTx> {}

impl<T> FullBlockBody for T where T: BlockBody<Transaction: FullSignedTx> {}

/// Abstraction for block's body.
/// Abstraction of block's body.
#[auto_impl::auto_impl(&, Arc)]
pub trait BlockBody:
Send
Expand All @@ -28,9 +47,182 @@ pub trait BlockBody:
+ MaybeSerde
+ MaybeArbitrary
{
/// Ordered list of signed transactions as committed in block.
type Transaction: Transaction;
/// Signed transaction.
type Transaction: SignedTransaction + 'static;

// todo
// /// Header type (uncle blocks).
// type Header: BlockHeader + 'static;

/// Withdrawals in block.
type Withdrawals: IntoIterator<Item = Withdrawal> + 'static;

/// Returns reference to transactions in block.
fn transactions(&self) -> &[Self::Transaction];
fn transactions(&self) -> &Vec<Self::Transaction>;

// todo
// /// Returns reference to uncle block headers.
// fn ommers(&self) -> &[Self::Header];

/// Returns `Withdrawals` in the block, if any.
// todo: branch out into extension trait
fn withdrawals(&self) -> Option<&Self::Withdrawals>;

/// Calculate the transaction root for the block body.
fn calculate_tx_root(&self) -> B256;

/// Calculate the ommers root for the block body.
fn calculate_ommers_root(&self) -> B256;

/// Calculate the withdrawals root for the block body, if withdrawals exist. If there are no
/// withdrawals, this will return `None`.
// todo: can be default impl if `calculate_withdrawals_root` made into a method on
// `Withdrawals` and `Withdrawals` moved to alloy
fn calculate_withdrawals_root(&self) -> Option<B256>;

/// Recover signer addresses for all transactions in the block body.
fn recover_signers(&self) -> Option<Vec<Address>> {
if self.transactions().len() < *PARALLEL_SENDER_RECOVERY_THRESHOLD {
self.transactions().iter().map(|tx| tx.recover_signer()).collect()
} else {
self.transactions().par_iter().map(|tx| tx.recover_signer()).collect()
}
}

/// Returns whether or not the block body contains any blob transactions.
fn has_blob_transactions(&self) -> bool {
self.transactions().iter().any(|tx| tx.tx_type().is_eip4844())
}

/// Returns whether or not the block body contains any EIP-7702 transactions.
fn has_eip7702_transactions(&self) -> bool {
self.transactions().iter().any(|tx| tx.tx_type().is_eip7702())
}

/// Returns an iterator over all blob transactions of the block
fn blob_transactions_iter(&self) -> impl Iterator<Item = &Self::Transaction> {
self.transactions().iter().filter(|tx| tx.tx_type().is_eip4844())
}

/// Returns only the blob transactions, if any, from the block body.
fn blob_transactions(&self) -> Vec<&Self::Transaction> {
self.blob_transactions_iter().collect()
}

/// Returns references to all blob versioned hashes from the block body.
fn blob_versioned_hashes(&self) -> Vec<&B256>;

/// Returns all blob versioned hashes from the block body.
fn blob_versioned_hashes_copied(&self) -> Vec<B256>;
}

/// Helper trait to implement [`BlockBody`] functionality for [`Block`](crate::Block) types.
pub trait Body<Header: 'static, SignedTx: SignedTransaction + 'static, Withdrawals: 'static> {
/// See [`BlockBody`].
fn transactions(&self) -> &[SignedTx];

/// See [`BlockBody`].
fn withdrawals(&self) -> Option<&Withdrawals>;

// todo
// /// See [`BlockBody`].
//fn ommers(&self) -> &[Header];

/// See [`BlockBody`].
fn calculate_tx_root(&self) -> B256;

/// See [`BlockBody`].
fn calculate_ommers_root(&self) -> B256;

/// See [`BlockBody`].
fn calculate_withdrawals_root(&self) -> Option<B256>;

/// See [`BlockBody`].
fn recover_signers(&self) -> Option<Vec<Address>> {
if self.transactions().len() < *PARALLEL_SENDER_RECOVERY_THRESHOLD {
self.transactions().iter().map(|tx| tx.recover_signer()).collect()
} else {
self.transactions().par_iter().map(|tx| tx.recover_signer()).collect()
}
}

/// See [`BlockBody`].
fn has_blob_transactions(&self) -> bool {
self.transactions().iter().any(|tx| tx.tx_type().is_eip4844())
}

/// See [`BlockBody`].
fn has_eip7702_transactions(&self) -> bool {
self.transactions().iter().any(|tx| tx.tx_type().is_eip7702())
}

/// See [`BlockBody`].
fn blob_transactions_iter<'a>(&'a self) -> impl Iterator<Item = &'a SignedTx> + 'a
where
SignedTx: 'a,
{
self.transactions().iter().filter(|tx| tx.tx_type().is_eip4844())
}

/// See [`BlockBody`].
fn blob_transactions(&self) -> Vec<&SignedTx> {
self.blob_transactions_iter().collect()
}

/// See [`BlockBody`].
fn blob_versioned_hashes(&self) -> Vec<&B256>;

/// See [`BlockBody`].
fn blob_versioned_hashes_copied(&self) -> Vec<B256>;
}

impl<T: Block>
Body<T::Header, <T::Body as BlockBody>::Transaction, <T::Body as BlockBody>::Withdrawals>
for T
{
#[inline]
fn transactions(&self) -> &[<T::Body as BlockBody>::Transaction] {
self.body().transactions()
}

#[inline]
fn withdrawals(&self) -> Option<&<T::Body as BlockBody>::Withdrawals> {
self.body().withdrawals()
}

// todo
//#[inline]
// fn ommers(&self) -> &[T::Header] {
// self.body().ommers()
//}

#[inline]
fn calculate_tx_root(&self) -> B256 {
self.body().calculate_tx_root()
}

#[inline]
fn calculate_ommers_root(&self) -> B256 {
self.body().calculate_ommers_root()
}

#[inline]
fn calculate_withdrawals_root(&self) -> Option<B256> {
self.body().calculate_withdrawals_root()
}

#[inline]
fn recover_signers(&self) -> Option<Vec<Address>> {
self.body().recover_signers()
}

#[inline]
fn blob_versioned_hashes(&self) -> Vec<&B256> {
self.body().blob_versioned_hashes()
}

#[inline]
fn blob_versioned_hashes_copied(&self) -> Vec<B256> {
self.body().blob_versioned_hashes_copied()
}
}
7 changes: 4 additions & 3 deletions crates/primitives-traits/src/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
pub mod body;
pub mod header;

use alloc::fmt;
use core::fmt;

use crate::{
BlockHeader, FullBlockBody, FullBlockHeader, InMemorySize, MaybeArbitrary, MaybeSerde,
BlockBody, BlockHeader, FullBlockBody, FullBlockHeader, InMemorySize, MaybeArbitrary,
MaybeSerde,
};

/// Helper trait that unifies all behaviour required by block to support full node operations.
Expand Down Expand Up @@ -44,7 +45,7 @@ pub trait Block:
type Header: BlockHeader + 'static;

/// The block's body contains the transactions in the block.
type Body: Send + Sync + Unpin + 'static;
type Body: BlockBody + 'static;

/// Returns reference to block header.
fn header(&self) -> &Self::Header;
Expand Down
7 changes: 6 additions & 1 deletion crates/primitives-traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
#[macro_use]
extern crate alloc;

/// Helper traits for calling block header and body methods directly on block type.
pub mod block_prelude {
pub use crate::{block::body::Body as _, Block};
}

/// Common constants.
pub mod constants;
pub use constants::gas_units::{format_gas, format_gas_throughput};
Expand All @@ -36,7 +41,7 @@ pub use integer_list::{IntegerList, IntegerListError};

pub mod block;
pub use block::{
body::{BlockBody, FullBlockBody},
body::{BlockBody, FullBlockBody, PARALLEL_SENDER_RECOVERY_THRESHOLD},
header::{BlockHeader, FullBlockHeader},
Block, FullBlock,
};
Expand Down
35 changes: 17 additions & 18 deletions crates/primitives-traits/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,24 +77,23 @@ impl NodePrimitives for () {
}

/// Helper trait that sets trait bounds on [`NodePrimitives`].
pub trait FullNodePrimitives
where
Self: NodePrimitives<
Block: FullBlock<Header = Self::BlockHeader, Body = Self::BlockBody>,
BlockHeader: FullBlockHeader,
BlockBody: FullBlockBody<Transaction = Self::SignedTx>,
SignedTx: FullSignedTx,
TxType: FullTxType,
Receipt: FullReceipt,
> + Send
+ Sync
+ Unpin
+ Clone
+ Default
+ fmt::Debug
+ PartialEq
+ Eq
+ 'static,
pub trait FullNodePrimitives:
NodePrimitives<
Block: FullBlock<Header = Self::BlockHeader, Body = Self::BlockBody>,
BlockHeader: FullBlockHeader,
BlockBody: FullBlockBody<Transaction = Self::SignedTx>,
SignedTx: FullSignedTx,
TxType: FullTxType,
Receipt: FullReceipt,
> + Send
+ Sync
+ Unpin
+ Clone
+ Default
+ fmt::Debug
+ PartialEq
+ Eq
+ 'static
{
}

Expand Down
Loading

0 comments on commit cde76d6

Please sign in to comment.