feat: relax BodyStage bounds (#12539)

This commit is contained in:
Arsenii Kulikov
2024-11-14 19:23:15 +04:00
committed by GitHub
parent 3154a4f66c
commit 77e687c28c
9 changed files with 47 additions and 79 deletions

View File

@ -1,10 +1,8 @@
//! Block body abstraction.
use alloc::{fmt, vec::Vec};
use alloc::fmt;
use alloy_consensus::{BlockHeader, Transaction, TxType};
use alloy_eips::{eip4895::Withdrawal, eip7685::Requests};
use alloy_primitives::{Address, B256};
use alloy_consensus::Transaction;
use crate::InMemorySize;
@ -26,67 +24,8 @@ pub trait BlockBody:
{
/// Ordered list of signed transactions as committed in block.
// todo: requires trait for signed transaction
type SignedTransaction: Transaction;
/// Header type (uncle blocks).
type Header: BlockHeader;
/// Withdrawals in block.
type Withdrawals: Iterator<Item = Withdrawal>;
type Transaction: Transaction;
/// Returns reference to transactions in block.
fn transactions(&self) -> &[Self::SignedTransaction];
/// Returns `Withdrawals` in the block, if any.
// todo: branch out into extension trait
fn withdrawals(&self) -> Option<&Self::Withdrawals>;
/// Returns reference to uncle block headers.
fn ommers(&self) -> &[Self::Header];
/// Returns [`Requests`] in block, if any.
fn requests(&self) -> Option<&Requests>;
/// 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>>;
/// Returns whether or not the block body contains any blob transactions.
fn has_blob_transactions(&self) -> bool {
self.transactions().iter().any(|tx| tx.ty() == TxType::Eip4844 as u8)
}
/// Returns whether or not the block body contains any EIP-7702 transactions.
fn has_eip7702_transactions(&self) -> bool {
self.transactions().iter().any(|tx| tx.ty() == TxType::Eip7702 as u8)
}
/// Returns an iterator over all blob transactions of the block
fn blob_transactions_iter(&self) -> impl Iterator<Item = &Self::SignedTransaction> + '_ {
self.transactions().iter().filter(|tx| tx.ty() == TxType::Eip4844 as u8)
}
/// Returns only the blob transactions, if any, from the block body.
fn blob_transactions(&self) -> Vec<&Self::SignedTransaction> {
self.blob_transactions_iter().collect()
}
/// Returns an iterator over all blob versioned hashes from the block body.
fn blob_versioned_hashes_iter(&self) -> impl Iterator<Item = &B256> + '_;
/// Returns all blob versioned hashes from the block body.
fn blob_versioned_hashes(&self) -> Vec<&B256> {
self.blob_versioned_hashes_iter().collect()
}
fn transactions(&self) -> &[Self::Transaction];
}

View File

@ -24,7 +24,7 @@ impl NodePrimitives for () {
/// Helper trait that sets trait bounds on [`NodePrimitives`].
pub trait FullNodePrimitives: Send + Sync + Unpin + Clone + Default + fmt::Debug {
/// Block primitive.
type Block: FullBlock<Body: BlockBody<SignedTransaction = Self::SignedTx>>;
type Block: FullBlock<Body: BlockBody<Transaction = Self::SignedTx>>;
/// Signed version of the transaction type.
type SignedTx: FullSignedTx;
/// Transaction envelope type ID.

View File

@ -657,6 +657,14 @@ impl InMemorySize for BlockBody {
}
}
impl reth_primitives_traits::BlockBody for BlockBody {
type Transaction = TransactionSigned;
fn transactions(&self) -> &[Self::Transaction] {
&self.transactions
}
}
impl From<Block> for BlockBody {
fn from(block: Block) -> Self {
Self {

View File

@ -1058,6 +1058,22 @@ impl reth_codecs::Compact for TransactionSignedNoHash {
}
}
#[cfg(any(test, feature = "reth-codec"))]
impl reth_codecs::Compact for TransactionSigned {
fn to_compact<B>(&self, buf: &mut B) -> usize
where
B: bytes::BufMut + AsMut<[u8]>,
{
let tx: TransactionSignedNoHash = self.clone().into();
tx.to_compact(buf)
}
fn from_compact(buf: &[u8], len: usize) -> (Self, &[u8]) {
let (tx, buf) = TransactionSignedNoHash::from_compact(buf, len);
(tx.into(), buf)
}
}
impl From<TransactionSignedNoHash> for TransactionSigned {
fn from(tx: TransactionSignedNoHash) -> Self {
tx.with_hash()

View File

@ -4,6 +4,8 @@ use std::{
};
use futures_util::TryStreamExt;
use reth_codecs::Compact;
use reth_primitives_traits::BlockBody;
use tracing::*;
use alloy_primitives::TxNumber;
@ -75,8 +77,8 @@ where
+ StaticFileProviderFactory
+ StatsReader
+ BlockReader
+ BlockWriter,
D: BodyDownloader<Body = reth_primitives::BlockBody>,
+ BlockWriter<Body = D::Body>,
D: BodyDownloader<Body: BlockBody<Transaction: Compact>>,
{
/// Return the id of the stage
fn id(&self) -> StageId {
@ -190,9 +192,9 @@ where
match response {
BlockResponse::Full(block) => {
// Write transactions
for transaction in &block.body.transactions {
let appended_tx_number = static_file_producer
.append_transaction(next_tx_num, &transaction.clone().into())?;
for transaction in block.body.transactions() {
let appended_tx_number =
static_file_producer.append_transaction(next_tx_num, transaction)?;
if appended_tx_number != next_tx_num {
// This scenario indicates a critical error in the logic of adding new
@ -702,9 +704,7 @@ mod tests {
body.tx_num_range().try_for_each(|tx_num| {
let transaction = random_signed_tx(&mut rng);
static_file_producer
.append_transaction(tx_num, &transaction.into())
.map(drop)
static_file_producer.append_transaction(tx_num, &transaction).map(drop)
})?;
if body.tx_count != 0 {

View File

@ -265,7 +265,7 @@ impl TestStageDB {
let res = block.body.transactions.iter().try_for_each(|body_tx| {
if let Some(txs_writer) = &mut txs_writer {
txs_writer.append_transaction(next_tx_num, &body_tx.clone().into())?;
txs_writer.append_transaction(next_tx_num, body_tx)?;
} else {
tx.put::<tables::Transactions>(next_tx_num, body_tx.clone().into())?
}

View File

@ -3110,6 +3110,8 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks> +
impl<TX: DbTxMut + DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks> + 'static> BlockWriter
for DatabaseProvider<TX, N>
{
type Body = BlockBody;
/// Inserts the block into the database, always modifying the following tables:
/// * [`CanonicalHeaders`](tables::CanonicalHeaders)
/// * [`Headers`](tables::Headers)

View File

@ -10,7 +10,7 @@ use reth_db_api::models::CompactU256;
use reth_nippy_jar::{NippyJar, NippyJarError, NippyJarWriter};
use reth_primitives::{
static_file::{SegmentHeader, SegmentRangeInclusive},
Receipt, StaticFileSegment, TransactionSignedNoHash,
Receipt, StaticFileSegment,
};
use reth_storage_errors::provider::{ProviderError, ProviderResult};
use std::{
@ -544,7 +544,7 @@ impl StaticFileProviderRW {
pub fn append_transaction(
&mut self,
tx_num: TxNumber,
tx: &TransactionSignedNoHash,
tx: impl Compact,
) -> ProviderResult<TxNumber> {
let start = Instant::now();
self.ensure_no_queued_prune()?;

View File

@ -1,7 +1,7 @@
use alloy_primitives::BlockNumber;
use reth_db_api::models::StoredBlockBodyIndices;
use reth_execution_types::{Chain, ExecutionOutcome};
use reth_primitives::{BlockBody, SealedBlockWithSenders};
use reth_primitives::SealedBlockWithSenders;
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{updates::TrieUpdates, HashedPostStateSorted};
use std::ops::RangeInclusive;
@ -32,6 +32,9 @@ pub trait StateReader: Send + Sync {
/// Block Writer
#[auto_impl::auto_impl(&, Arc, Box)]
pub trait BlockWriter: Send + Sync {
/// The body this writer can write.
type Body: Send + Sync;
/// Insert full block and make it canonical. Parent tx num and transition id is taken from
/// parent block in database.
///
@ -47,7 +50,7 @@ pub trait BlockWriter: Send + Sync {
/// Bodies are passed as [`Option`]s, if body is `None` the corresponding block is empty.
fn append_block_bodies(
&self,
bodies: impl Iterator<Item = (BlockNumber, Option<BlockBody>)>,
bodies: impl Iterator<Item = (BlockNumber, Option<Self::Body>)>,
) -> ProviderResult<()>;
/// Appends a batch of sealed blocks to the blockchain, including sender information, and