chore(sdk): incorporate block module into reth-primitives-traits (#11835)

This commit is contained in:
Emilia Hane
2024-10-17 15:14:48 +02:00
committed by GitHub
parent 3bc3e71699
commit 52407b18de
4 changed files with 39 additions and 182 deletions

View File

@ -1,99 +0,0 @@
//! Block abstraction.
pub mod body;
use alloc::fmt;
use core::ops;
use alloy_consensus::BlockHeader;
use alloy_primitives::{Address, Sealable, B256};
use crate::{traits::BlockBody, BlockWithSenders, SealedBlock, SealedHeader};
/// Abstraction of block data type.
pub trait Block:
fmt::Debug
+ Clone
+ PartialEq
+ Eq
+ Default
+ serde::Serialize
+ for<'a> serde::Deserialize<'a>
+ From<(Self::Header, Self::Body)>
+ Into<(Self::Header, Self::Body)>
{
/// Header part of the block.
type Header: BlockHeader + Sealable;
/// The block's body contains the transactions in the block.
type Body: BlockBody;
/// A block and block hash.
type SealedBlock<H = Self::Header, B = Self::Body>;
/// A block and addresses of senders of transactions in it.
type BlockWithSenders<T = Self>;
/// Returns reference to [`BlockHeader`] type.
fn header(&self) -> &Self::Header;
/// Returns reference to [`BlockBody`] type.
fn body(&self) -> &Self::Body;
/// Calculate the header hash and seal the block so that it can't be changed.
// todo: can be default impl if sealed block type is made generic over header and body and
// migrated to alloy
fn seal_slow(self) -> Self::SealedBlock;
/// Seal the block with a known hash.
///
/// WARNING: This method does not perform validation whether the hash is correct.
// todo: can be default impl if sealed block type is made generic over header and body and
// migrated to alloy
fn seal(self, hash: B256) -> Self::SealedBlock;
/// Expensive operation that recovers transaction signer. See
/// [`SealedBlockWithSenders`](reth_primitives::SealedBlockWithSenders).
fn senders(&self) -> Option<Vec<Address>> {
self.body().recover_signers()
}
/// Transform into a [`BlockWithSenders`].
///
/// # Panics
///
/// If the number of senders does not match the number of transactions in the block
/// and the signer recovery for one of the transactions fails.
///
/// Note: this is expected to be called with blocks read from disk.
#[track_caller]
fn with_senders_unchecked(self, senders: Vec<Address>) -> Self::BlockWithSenders {
self.try_with_senders_unchecked(senders).expect("stored block is valid")
}
/// Transform into a [`BlockWithSenders`] using the given senders.
///
/// If the number of senders does not match the number of transactions in the block, this falls
/// back to manually recovery, but _without ensuring that the signature has a low `s` value_.
/// See also [`TransactionSigned::recover_signer_unchecked`]
///
/// Returns an error if a signature is invalid.
// todo: can be default impl if block with senders type is made generic over block and migrated
// to alloy
#[track_caller]
fn try_with_senders_unchecked(
self,
senders: Vec<Address>,
) -> Result<Self::BlockWithSenders, Self>;
/// **Expensive**. Transform into a [`BlockWithSenders`] by recovering senders in the contained
/// transactions.
///
/// Returns `None` if a transaction is invalid.
// todo: can be default impl if sealed block type is made generic over header and body and
// migrated to alloy
fn with_recovered_senders(self) -> Option<Self::BlockWithSenders>;
/// Calculates a heuristic for the in-memory size of the [`Block`].
fn size(&self) -> usize;
}

View File

@ -1,11 +1,10 @@
//! Block body abstraction. //! Block body abstraction.
use alloc::fmt; use alloc::{fmt, vec::Vec};
use core::ops;
use alloy_consensus::{BlockHeader,Request, Transaction, TxType}; use alloy_consensus::{BlockHeader, Request, Transaction, TxType};
use alloy_eips::eip4895::Withdrawal;
use alloy_primitives::{Address, B256}; use alloy_primitives::{Address, B256};
use alloy_eips::eip1559::Withdrawal;
use crate::Block; use crate::Block;
@ -37,7 +36,7 @@ pub trait BlockBody:
/// Returns reference to transactions in block. /// Returns reference to transactions in block.
fn transactions(&self) -> &[Self::SignedTransaction]; fn transactions(&self) -> &[Self::SignedTransaction];
/// Returns [`Withdrawals`] in the block, if any. /// Returns `Withdrawals` in the block, if any.
// todo: branch out into extension trait // todo: branch out into extension trait
fn withdrawals(&self) -> Option<&Self::Withdrawals>; fn withdrawals(&self) -> Option<&Self::Withdrawals>;
@ -60,13 +59,13 @@ pub trait BlockBody:
/// Calculate the withdrawals root for the block body, if withdrawals exist. If there are no /// Calculate the withdrawals root for the block body, if withdrawals exist. If there are no
/// withdrawals, this will return `None`. /// withdrawals, this will return `None`.
// todo: can be default impl if `calculate_withdrawals_root` made into a method on // todo: can be default impl if `calculate_withdrawals_root` made into a method on
// `Withdrawals` and `Withdrawals` moved to alloy // `Withdrawals` and `Withdrawals` moved to alloy
fn calculate_withdrawals_root(&self) -> Option<B256>; fn calculate_withdrawals_root(&self) -> Option<B256>;
/// Calculate the requests root for the block body, if requests exist. If there are no /// Calculate the requests root for the block body, if requests exist. If there are no
/// requests, this will return `None`. /// requests, this will return `None`.
// todo: can be default impl if `calculate_requests_root` made into a method on // todo: can be default impl if `calculate_requests_root` made into a method on
// `Requests` and `Requests` moved to alloy // `Requests` and `Requests` moved to alloy
fn calculate_requests_root(&self) -> Option<B256>; fn calculate_requests_root(&self) -> Option<B256>;
@ -75,17 +74,17 @@ pub trait BlockBody:
/// Returns whether or not the block body contains any blob transactions. /// Returns whether or not the block body contains any blob transactions.
fn has_blob_transactions(&self) -> bool { fn has_blob_transactions(&self) -> bool {
self.transactions().iter().any(|tx| tx.ty() as u8 == TxType::Eip4844 as u8) self.transactions().iter().any(|tx| tx.ty() == TxType::Eip4844 as u8)
} }
/// Returns whether or not the block body contains any EIP-7702 transactions. /// Returns whether or not the block body contains any EIP-7702 transactions.
fn has_eip7702_transactions(&self) -> bool { fn has_eip7702_transactions(&self) -> bool {
self.transactions().iter().any(|tx| tx.ty() as u8 == TxType::Eip7702 as u8) self.transactions().iter().any(|tx| tx.ty() == TxType::Eip7702 as u8)
} }
/// Returns an iterator over all blob transactions of the block /// Returns an iterator over all blob transactions of the block
fn blob_transactions_iter(&self) -> impl Iterator<Item = &Self::SignedTransaction> + '_ { fn blob_transactions_iter(&self) -> impl Iterator<Item = &Self::SignedTransaction> + '_ {
self.transactions().iter().filter(|tx| tx.ty() as u8 == TxType::Eip4844 as u8) self.transactions().iter().filter(|tx| tx.ty() == TxType::Eip4844 as u8)
} }
/// Returns only the blob transactions, if any, from the block body. /// Returns only the blob transactions, if any, from the block body.
@ -104,56 +103,3 @@ pub trait BlockBody:
/// Calculates a heuristic for the in-memory size of the [`BlockBody`]. /// Calculates a heuristic for the in-memory size of the [`BlockBody`].
fn size(&self) -> usize; fn size(&self) -> usize;
} }
impl<T> BlockBody for T
where
T: ops::Deref<Target: BlockBody>
+ Clone
+ fmt::Debug
+ PartialEq
+ Eq
+ Default
+ serde::Serialize
+ for<'de> serde::Deserialize<'de>
+ alloy_rlp::Encodable
+ alloy_rlp::Decodable,
{
type Header = <T::Target as BlockBody>::Header;
type SignedTransaction = <T::Target as BlockBody>::SignedTransaction;
fn transactions(&self) -> &Vec<Self::SignedTransaction> {
self.deref().transactions()
}
fn withdrawals(&self) -> Option<&Withdrawals> {
self.deref().withdrawals()
}
fn ommers(&self) -> &Vec<Self::Header> {
self.deref().ommers()
}
fn requests(&self) -> Option<&Requests> {
self.deref().requests()
}
fn calculate_tx_root(&self) -> B256 {
self.deref().calculate_tx_root()
}
fn calculate_ommers_root(&self) -> B256 {
self.deref().calculate_ommers_root()
}
fn recover_signers(&self) -> Option<Vec<Address>> {
self.deref().recover_signers()
}
fn blob_versioned_hashes_iter(&self) -> impl Iterator<Item = &B256> + '_ {
self.deref().blob_versioned_hashes_iter()
}
fn size(&self) -> usize {
self.deref().size()
}
}

View File

@ -2,15 +2,22 @@
pub mod body; pub mod body;
use alloc::fmt; use alloc::{fmt, vec::Vec};
use core::ops;
use alloy_consensus::BlockHeader; use alloy_consensus::BlockHeader;
use alloy_primitives::{Address, Sealable, B256}; use alloy_primitives::{Address, Sealable, B256};
use crate::{traits::BlockBody, BlockWithSenders, SealedBlock, SealedHeader}; use crate::BlockBody;
/// Helper trait, unifies behaviour required of a block header.
pub trait Header: BlockHeader + Sealable {}
impl<T> Header for T where T: BlockHeader + Sealable {}
/// Abstraction of block data type. /// Abstraction of block data type.
// todo: make sealable super-trait, depends on <https://github.com/paradigmxyz/reth/issues/11449>
// todo: make with senders extension trait, so block can be impl by block type already containing
// senders
pub trait Block: pub trait Block:
fmt::Debug fmt::Debug
+ Clone + Clone
@ -23,16 +30,16 @@ pub trait Block:
+ Into<(Self::Header, Self::Body)> + Into<(Self::Header, Self::Body)>
{ {
/// Header part of the block. /// Header part of the block.
type Header: BlockHeader + Sealable; type Header: Header;
/// The block's body contains the transactions in the block. /// The block's body contains the transactions in the block.
type Body: BlockBody; type Body: BlockBody;
/// A block and block hash. /// A block and block hash.
type SealedBlock<H = Self::Header, B = Self::Body>; type SealedBlock<H, B>;
/// A block and addresses of senders of transactions in it. /// A block and addresses of senders of transactions in it.
type BlockWithSenders<T = Self>; type BlockWithSenders<T>;
/// Returns reference to [`BlockHeader`] type. /// Returns reference to [`BlockHeader`] type.
fn header(&self) -> &Self::Header; fn header(&self) -> &Self::Header;
@ -41,24 +48,24 @@ pub trait Block:
fn body(&self) -> &Self::Body; fn body(&self) -> &Self::Body;
/// Calculate the header hash and seal the block so that it can't be changed. /// Calculate the header hash and seal the block so that it can't be changed.
// todo: can be default impl if sealed block type is made generic over header and body and // todo: can be default impl if sealed block type is made generic over header and body and
// migrated to alloy // migrated to alloy
fn seal_slow(self) -> Self::SealedBlock; fn seal_slow(self) -> Self::SealedBlock<Self::Header, Self::Body>;
/// Seal the block with a known hash. /// Seal the block with a known hash.
/// ///
/// WARNING: This method does not perform validation whether the hash is correct. /// WARNING: This method does not perform validation whether the hash is correct.
// todo: can be default impl if sealed block type is made generic over header and body and // todo: can be default impl if sealed block type is made generic over header and body and
// migrated to alloy // migrated to alloy
fn seal(self, hash: B256) -> Self::SealedBlock; fn seal(self, hash: B256) -> Self::SealedBlock<Self::Header, Self::Body>;
/// Expensive operation that recovers transaction signer. See /// Expensive operation that recovers transaction signer. See
/// [`SealedBlockWithSenders`](reth_primitives::SealedBlockWithSenders). /// `SealedBlockWithSenders`.
fn senders(&self) -> Option<Vec<Address>> { fn senders(&self) -> Option<Vec<Address>> {
self.body().recover_signers() self.body().recover_signers()
} }
/// Transform into a [`BlockWithSenders`]. /// Transform into a `BlockWithSenders`.
/// ///
/// # Panics /// # Panics
/// ///
@ -67,32 +74,32 @@ pub trait Block:
/// ///
/// Note: this is expected to be called with blocks read from disk. /// Note: this is expected to be called with blocks read from disk.
#[track_caller] #[track_caller]
fn with_senders_unchecked(self, senders: Vec<Address>) -> Self::BlockWithSenders { fn with_senders_unchecked(self, senders: Vec<Address>) -> Self::BlockWithSenders<Self> {
self.try_with_senders_unchecked(senders).expect("stored block is valid") self.try_with_senders_unchecked(senders).expect("stored block is valid")
} }
/// Transform into a [`BlockWithSenders`] using the given senders. /// Transform into a `BlockWithSenders` using the given senders.
/// ///
/// If the number of senders does not match the number of transactions in the block, this falls /// If the number of senders does not match the number of transactions in the block, this falls
/// back to manually recovery, but _without ensuring that the signature has a low `s` value_. /// back to manually recovery, but _without ensuring that the signature has a low `s` value_.
/// See also [`TransactionSigned::recover_signer_unchecked`] /// See also `SignedTransaction::recover_signer_unchecked`.
/// ///
/// Returns an error if a signature is invalid. /// Returns an error if a signature is invalid.
// todo: can be default impl if block with senders type is made generic over block and migrated // todo: can be default impl if block with senders type is made generic over block and migrated
// to alloy // to alloy
#[track_caller] #[track_caller]
fn try_with_senders_unchecked( fn try_with_senders_unchecked(
self, self,
senders: Vec<Address>, senders: Vec<Address>,
) -> Result<Self::BlockWithSenders, Self>; ) -> Result<Self::BlockWithSenders<Self>, Self>;
/// **Expensive**. Transform into a [`BlockWithSenders`] by recovering senders in the contained /// **Expensive**. Transform into a `BlockWithSenders` by recovering senders in the contained
/// transactions. /// transactions.
/// ///
/// Returns `None` if a transaction is invalid. /// Returns `None` if a transaction is invalid.
// todo: can be default impl if sealed block type is made generic over header and body and // todo: can be default impl if sealed block type is made generic over header and body and
// migrated to alloy // migrated to alloy
fn with_recovered_senders(self) -> Option<Self::BlockWithSenders>; fn with_recovered_senders(self) -> Option<Self::BlockWithSenders<Self>>;
/// Calculates a heuristic for the in-memory size of the [`Block`]. /// Calculates a heuristic for the in-memory size of the [`Block`].
fn size(&self) -> usize; fn size(&self) -> usize;

View File

@ -32,6 +32,9 @@ pub use integer_list::{IntegerList, IntegerListError};
pub mod request; pub mod request;
pub use request::{Request, Requests}; pub use request::{Request, Requests};
pub mod block;
pub use block::{body::BlockBody, Block};
mod withdrawal; mod withdrawal;
pub use withdrawal::{Withdrawal, Withdrawals}; pub use withdrawal::{Withdrawal, Withdrawals};