Skip to content

Commit

Permalink
chore: add a few tx related helper functions (#5430)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored Nov 14, 2023
1 parent 6ee481b commit 365fbb1
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 9 deletions.
34 changes: 33 additions & 1 deletion crates/primitives/src/block.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -252,9 +255,38 @@ impl SealedBlockWithSenders {
}

/// Split Structure to its components
#[inline]
pub fn into_components(self) -> (SealedBlock, Vec<Address>) {
(self.block, self.senders)
}

/// Returns an iterator over all transactions in the block.
#[inline]
pub fn transactions(&self) -> impl Iterator<Item = &TransactionSigned> + '_ {
self.block.body.iter()
}

/// Returns an iterator over all transactions and their sender.
#[inline]
pub fn transactions_with_sender(
&self,
) -> impl Iterator<Item = (&Address, &TransactionSigned)> + '_ {
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<TransactionSigned> {
self.block.body
}

/// Returns an iterator over all transactions in the chain.
#[inline]
pub fn into_transactions_ecrecovered(
self,
) -> impl Iterator<Item = TransactionSignedEcRecovered> {
self.block.body.into_iter().zip(self.senders).map(|(tx, sender)| tx.with_signer(sender))
}
}

impl Deref for SealedBlockWithSenders {
Expand Down
12 changes: 11 additions & 1 deletion crates/primitives/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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].
Expand Down Expand Up @@ -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 }
}
}
Expand Down
33 changes: 31 additions & 2 deletions crates/storage/provider/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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<Item = SealedBlockWithSenders> {
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<Item = (&BlockNumber, &SealedBlockWithSenders)> {
self.blocks.iter()
}
Expand All @@ -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
}
Expand All @@ -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<Item = &TransactionSigned> + '_ {
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<Item = (&Address, &TransactionSigned)> + '_ {
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<Item = TransactionSignedEcRecovered> + '_ {
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<Item = TxHash> + '_ {
self.blocks.values().flat_map(|block| block.transactions().map(|tx| tx.hash))
}
}

impl<'a> IntoIterator for ChainBlocks<'a> {
Expand Down
8 changes: 3 additions & 5 deletions crates/transaction-pool/src/maintain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,15 +279,13 @@ pub async fn maintain_transaction_pool<Client, P, St, Tasks>(
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(<P as TransactionPool>::Transaction::from_recovered_transaction)
.collect::<Vec<_>>();

Expand Down Expand Up @@ -359,7 +357,7 @@ pub async fn maintain_transaction_pool<Client, P, St, Tasks>(
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 {
Expand Down

0 comments on commit 365fbb1

Please sign in to comment.