diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index 7f94a4d501..2d820734d5 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -1,4 +1,7 @@ -use crate::{Address, Header, SealedHeader, TransactionSigned, Withdrawal, B256}; +use crate::{ + Address, Header, SealedHeader, TransactionSigned, TransactionSignedEcRecovered, Withdrawal, + B256, +}; use alloy_rlp::{RlpDecodable, RlpEncodable}; use reth_codecs::derive_arbitrary; use serde::{Deserialize, Serialize}; @@ -252,9 +255,38 @@ impl SealedBlockWithSenders { } /// Split Structure to its components + #[inline] pub fn into_components(self) -> (SealedBlock, Vec
) { (self.block, self.senders) } + + /// Returns an iterator over all transactions in the block. + #[inline] + pub fn transactions(&self) -> impl Iterator + '_ { + self.block.body.iter() + } + + /// Returns an iterator over all transactions and their sender. + #[inline] + pub fn transactions_with_sender( + &self, + ) -> impl Iterator + '_ { + self.senders.iter().zip(self.block.body.iter()) + } + + /// Consumes the block and returns the transactions of the block. + #[inline] + pub fn into_transactions(self) -> Vec { + self.block.body + } + + /// Returns an iterator over all transactions in the chain. + #[inline] + pub fn into_transactions_ecrecovered( + self, + ) -> impl Iterator { + self.block.body.into_iter().zip(self.senders).map(|(tx, sender)| tx.with_signer(sender)) + } } impl Deref for SealedBlockWithSenders { diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index 40b37085f6..2d539b1f36 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -1006,6 +1006,12 @@ impl TransactionSigned { } } + /// Returns the [TransactionSignedEcRecovered] transaction with the given sender. + #[inline] + pub const fn with_signer(self, signer: Address) -> TransactionSignedEcRecovered { + TransactionSignedEcRecovered::from_signed_transaction(self, signer) + } + /// Consumes the type, recover signer and return [`TransactionSignedEcRecovered`] /// /// Returns `None` if the transaction's signature is invalid, see also [Self::recover_signer]. @@ -1424,7 +1430,11 @@ impl TransactionSignedEcRecovered { /// Create [`TransactionSignedEcRecovered`] from [`TransactionSigned`] and [`Address`] of the /// signer. - pub fn from_signed_transaction(signed_transaction: TransactionSigned, signer: Address) -> Self { + #[inline] + pub const fn from_signed_transaction( + signed_transaction: TransactionSigned, + signer: Address, + ) -> Self { Self { signed_transaction, signer } } } diff --git a/crates/storage/provider/src/chain.rs b/crates/storage/provider/src/chain.rs index ab269b680a..53bc31a941 100644 --- a/crates/storage/provider/src/chain.rs +++ b/crates/storage/provider/src/chain.rs @@ -3,8 +3,8 @@ use crate::bundle_state::BundleStateWithReceipts; use reth_interfaces::{executor::BlockExecutionError, RethResult}; use reth_primitives::{ - BlockHash, BlockNumHash, BlockNumber, ForkBlock, Receipt, SealedBlock, SealedBlockWithSenders, - SealedHeader, TransactionSigned, TxHash, + Address, BlockHash, BlockNumHash, BlockNumber, ForkBlock, Receipt, SealedBlock, + SealedBlockWithSenders, SealedHeader, TransactionSigned, TransactionSignedEcRecovered, TxHash, }; use std::{borrow::Cow, collections::BTreeMap, fmt}; @@ -276,11 +276,13 @@ impl<'a> ChainBlocks<'a> { /// Creates a consuming iterator over all blocks in the chain with increasing block number. /// /// Note: this always yields at least one block. + #[inline] pub fn into_blocks(self) -> impl Iterator { self.blocks.into_owned().into_values() } /// Creates an iterator over all blocks in the chain with increasing block number. + #[inline] pub fn iter(&self) -> impl Iterator { self.blocks.iter() } @@ -290,6 +292,7 @@ impl<'a> ChainBlocks<'a> { /// # Note /// /// Chains always have at least one block. + #[inline] pub fn tip(&self) -> &SealedBlockWithSenders { self.blocks.last_key_value().expect("Chain should have at least one block").1 } @@ -299,14 +302,40 @@ impl<'a> ChainBlocks<'a> { /// # Note /// /// Chains always have at least one block. + #[inline] pub fn first(&self) -> &SealedBlockWithSenders { self.blocks.first_key_value().expect("Chain should have at least one block").1 } /// Returns an iterator over all transactions in the chain. + #[inline] pub fn transactions(&self) -> impl Iterator + '_ { self.blocks.values().flat_map(|block| block.body.iter()) } + + /// Returns an iterator over all transactions and their senders. + #[inline] + pub fn transactions_with_sender( + &self, + ) -> impl Iterator + '_ { + self.blocks.values().flat_map(|block| block.transactions_with_sender()) + } + + /// Returns an iterator over all [TransactionSignedEcRecovered] in the blocks + /// + /// Note: This clones the transactions since it is assumed this is part of a shared [Chain]. + #[inline] + pub fn transactions_ecrecovered( + &self, + ) -> impl Iterator + '_ { + self.transactions_with_sender().map(|(signer, tx)| tx.clone().with_signer(*signer)) + } + + /// Returns an iterator over all transaction hashes in the block + #[inline] + pub fn transaction_hashes(&self) -> impl Iterator + '_ { + self.blocks.values().flat_map(|block| block.transactions().map(|tx| tx.hash)) + } } impl<'a> IntoIterator for ChainBlocks<'a> { diff --git a/crates/transaction-pool/src/maintain.rs b/crates/transaction-pool/src/maintain.rs index 8c48601c47..4da9987b72 100644 --- a/crates/transaction-pool/src/maintain.rs +++ b/crates/transaction-pool/src/maintain.rs @@ -279,15 +279,13 @@ pub async fn maintain_transaction_pool( changed_accounts.extend(new_changed_accounts.into_iter().map(|entry| entry.0)); // all transactions mined in the new chain - let new_mined_transactions: HashSet<_> = - new_blocks.transactions().map(|tx| tx.hash).collect(); + let new_mined_transactions: HashSet<_> = new_blocks.transaction_hashes().collect(); // update the pool then re-inject the pruned transactions // find all transactions that were mined in the old chain but not in the new chain let pruned_old_transactions = old_blocks - .transactions() + .transactions_ecrecovered() .filter(|tx| !new_mined_transactions.contains(&tx.hash)) - .filter_map(|tx| tx.clone().into_ecrecovered()) .map(

::Transaction::from_recovered_transaction) .collect::>(); @@ -359,7 +357,7 @@ pub async fn maintain_transaction_pool( changed_accounts.push(acc); } - let mined_transactions = blocks.transactions().map(|tx| tx.hash).collect(); + let mined_transactions = blocks.transaction_hashes().collect(); // check if the range of the commit is canonical with the pool's block if first_block.parent_hash != pool_info.last_seen_block_hash {