chore: add a few tx related helper functions (#5430)

This commit is contained in:
Matthias Seitz
2023-11-15 00:09:07 +01:00
committed by GitHub
parent 6ee481b817
commit 365fbb18c2
4 changed files with 78 additions and 9 deletions

View File

@ -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 alloy_rlp::{RlpDecodable, RlpEncodable};
use reth_codecs::derive_arbitrary; use reth_codecs::derive_arbitrary;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -252,9 +255,38 @@ impl SealedBlockWithSenders {
} }
/// Split Structure to its components /// Split Structure to its components
#[inline]
pub fn into_components(self) -> (SealedBlock, Vec<Address>) { pub fn into_components(self) -> (SealedBlock, Vec<Address>) {
(self.block, self.senders) (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 { impl Deref for SealedBlockWithSenders {

View File

@ -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`] /// Consumes the type, recover signer and return [`TransactionSignedEcRecovered`]
/// ///
/// Returns `None` if the transaction's signature is invalid, see also [Self::recover_signer]. /// 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 /// Create [`TransactionSignedEcRecovered`] from [`TransactionSigned`] and [`Address`] of the
/// signer. /// 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 } Self { signed_transaction, signer }
} }
} }

View File

@ -3,8 +3,8 @@
use crate::bundle_state::BundleStateWithReceipts; use crate::bundle_state::BundleStateWithReceipts;
use reth_interfaces::{executor::BlockExecutionError, RethResult}; use reth_interfaces::{executor::BlockExecutionError, RethResult};
use reth_primitives::{ use reth_primitives::{
BlockHash, BlockNumHash, BlockNumber, ForkBlock, Receipt, SealedBlock, SealedBlockWithSenders, Address, BlockHash, BlockNumHash, BlockNumber, ForkBlock, Receipt, SealedBlock,
SealedHeader, TransactionSigned, TxHash, SealedBlockWithSenders, SealedHeader, TransactionSigned, TransactionSignedEcRecovered, TxHash,
}; };
use std::{borrow::Cow, collections::BTreeMap, fmt}; 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. /// Creates a consuming iterator over all blocks in the chain with increasing block number.
/// ///
/// Note: this always yields at least one block. /// Note: this always yields at least one block.
#[inline]
pub fn into_blocks(self) -> impl Iterator<Item = SealedBlockWithSenders> { pub fn into_blocks(self) -> impl Iterator<Item = SealedBlockWithSenders> {
self.blocks.into_owned().into_values() self.blocks.into_owned().into_values()
} }
/// Creates an iterator over all blocks in the chain with increasing block number. /// Creates an iterator over all blocks in the chain with increasing block number.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (&BlockNumber, &SealedBlockWithSenders)> { pub fn iter(&self) -> impl Iterator<Item = (&BlockNumber, &SealedBlockWithSenders)> {
self.blocks.iter() self.blocks.iter()
} }
@ -290,6 +292,7 @@ impl<'a> ChainBlocks<'a> {
/// # Note /// # Note
/// ///
/// Chains always have at least one block. /// Chains always have at least one block.
#[inline]
pub fn tip(&self) -> &SealedBlockWithSenders { pub fn tip(&self) -> &SealedBlockWithSenders {
self.blocks.last_key_value().expect("Chain should have at least one block").1 self.blocks.last_key_value().expect("Chain should have at least one block").1
} }
@ -299,14 +302,40 @@ impl<'a> ChainBlocks<'a> {
/// # Note /// # Note
/// ///
/// Chains always have at least one block. /// Chains always have at least one block.
#[inline]
pub fn first(&self) -> &SealedBlockWithSenders { pub fn first(&self) -> &SealedBlockWithSenders {
self.blocks.first_key_value().expect("Chain should have at least one block").1 self.blocks.first_key_value().expect("Chain should have at least one block").1
} }
/// Returns an iterator over all transactions in the chain. /// Returns an iterator over all transactions in the chain.
#[inline]
pub fn transactions(&self) -> impl Iterator<Item = &TransactionSigned> + '_ { pub fn transactions(&self) -> impl Iterator<Item = &TransactionSigned> + '_ {
self.blocks.values().flat_map(|block| block.body.iter()) 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> { impl<'a> IntoIterator for ChainBlocks<'a> {

View File

@ -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)); changed_accounts.extend(new_changed_accounts.into_iter().map(|entry| entry.0));
// all transactions mined in the new chain // all transactions mined in the new chain
let new_mined_transactions: HashSet<_> = let new_mined_transactions: HashSet<_> = new_blocks.transaction_hashes().collect();
new_blocks.transactions().map(|tx| tx.hash).collect();
// update the pool then re-inject the pruned transactions // 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 // find all transactions that were mined in the old chain but not in the new chain
let pruned_old_transactions = old_blocks let pruned_old_transactions = old_blocks
.transactions() .transactions_ecrecovered()
.filter(|tx| !new_mined_transactions.contains(&tx.hash)) .filter(|tx| !new_mined_transactions.contains(&tx.hash))
.filter_map(|tx| tx.clone().into_ecrecovered())
.map(<P as TransactionPool>::Transaction::from_recovered_transaction) .map(<P as TransactionPool>::Transaction::from_recovered_transaction)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -359,7 +357,7 @@ pub async fn maintain_transaction_pool<Client, P, St, Tasks>(
changed_accounts.push(acc); 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 // 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 { if first_block.parent_hash != pool_info.last_seen_block_hash {