diff --git a/crates/primitives-traits/src/block/body.rs b/crates/primitives-traits/src/block/body.rs index 6ec184a21546..c5f15aefea6f 100644 --- a/crates/primitives-traits/src/block/body.rs +++ b/crates/primitives-traits/src/block/body.rs @@ -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; + 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; - - /// Recover signer addresses for all transactions in the block body. - fn recover_signers(&self) -> Option>; - - /// 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 + '_ { - 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 + '_; - - /// 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]; } diff --git a/crates/primitives-traits/src/node.rs b/crates/primitives-traits/src/node.rs index cebbbe202e85..9ca692748314 100644 --- a/crates/primitives-traits/src/node.rs +++ b/crates/primitives-traits/src/node.rs @@ -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>; + type Block: FullBlock>; /// Signed version of the transaction type. type SignedTx: FullSignedTx; /// Transaction envelope type ID. diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index 703f9d331696..0f96a9d5842b 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -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 for BlockBody { fn from(block: Block) -> Self { Self { diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index d1a95b09be24..e5e4517d9dde 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -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(&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 for TransactionSigned { fn from(tx: TransactionSignedNoHash) -> Self { tx.with_hash() diff --git a/crates/stages/stages/src/stages/bodies.rs b/crates/stages/stages/src/stages/bodies.rs index c4676b2728cc..640bae866594 100644 --- a/crates/stages/stages/src/stages/bodies.rs +++ b/crates/stages/stages/src/stages/bodies.rs @@ -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, + + BlockWriter, + D: BodyDownloader>, { /// 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 { diff --git a/crates/stages/stages/src/test_utils/test_db.rs b/crates/stages/stages/src/test_utils/test_db.rs index 4c43d4cdcd1d..52983cb6f69a 100644 --- a/crates/stages/stages/src/test_utils/test_db.rs +++ b/crates/stages/stages/src/test_utils/test_db.rs @@ -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::(next_tx_num, body_tx.clone().into())? } diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 20d01932a152..62a44c175b0e 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -3110,6 +3110,8 @@ impl + impl + 'static> BlockWriter for DatabaseProvider { + type Body = BlockBody; + /// Inserts the block into the database, always modifying the following tables: /// * [`CanonicalHeaders`](tables::CanonicalHeaders) /// * [`Headers`](tables::Headers) diff --git a/crates/storage/provider/src/providers/static_file/writer.rs b/crates/storage/provider/src/providers/static_file/writer.rs index ed1a51068c30..2e54fb943a7a 100644 --- a/crates/storage/provider/src/providers/static_file/writer.rs +++ b/crates/storage/provider/src/providers/static_file/writer.rs @@ -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 { let start = Instant::now(); self.ensure_no_queued_prune()?; diff --git a/crates/storage/provider/src/traits/block.rs b/crates/storage/provider/src/traits/block.rs index 5cb60c2f42a9..50fb032923d8 100644 --- a/crates/storage/provider/src/traits/block.rs +++ b/crates/storage/provider/src/traits/block.rs @@ -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)>, + bodies: impl Iterator)>, ) -> ProviderResult<()>; /// Appends a batch of sealed blocks to the blockchain, including sender information, and