reth_storage_api/
transactions.rs

1use crate::{BlockNumReader, BlockReader};
2use alloc::vec::Vec;
3use alloy_consensus::transaction::TransactionMeta;
4use alloy_eips::BlockHashOrNumber;
5use alloy_primitives::{Address, BlockNumber, TxHash, TxNumber};
6use core::ops::{Range, RangeBounds, RangeInclusive};
7use reth_primitives_traits::SignedTransaction;
8use reth_storage_errors::provider::{ProviderError, ProviderResult};
9
10/// Enum to control transaction hash inclusion.
11///
12/// This serves as a hint to the provider to include or omit exclude hashes because hashes are
13/// stored separately and are not always needed.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
15pub enum TransactionVariant {
16    /// Indicates that transactions should be processed without including their hashes.
17    NoHash,
18    /// Indicates that transactions should be processed along with their hashes.
19    #[default]
20    WithHash,
21}
22
23///  Client trait for fetching transactions related data.
24#[auto_impl::auto_impl(&, Arc)]
25pub trait TransactionsProvider: BlockNumReader + Send + Sync {
26    /// The transaction type this provider reads.
27    type Transaction: Send + Sync + SignedTransaction;
28
29    /// Get internal transaction identifier by transaction hash.
30    ///
31    /// This is the inverse of [TransactionsProvider::transaction_by_id].
32    /// Returns None if the transaction is not found.
33    fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult<Option<TxNumber>>;
34
35    /// Get transaction by id, computes hash every time so more expensive.
36    fn transaction_by_id(&self, id: TxNumber) -> ProviderResult<Option<Self::Transaction>>;
37
38    /// Get transaction by id without computing the hash.
39    fn transaction_by_id_unhashed(&self, id: TxNumber)
40        -> ProviderResult<Option<Self::Transaction>>;
41
42    /// Get transaction by transaction hash.
43    fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Transaction>>;
44
45    /// Get transaction by transaction hash and additional metadata of the block the transaction was
46    /// mined in
47    fn transaction_by_hash_with_meta(
48        &self,
49        hash: TxHash,
50    ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>>;
51
52    /// Get transaction block number
53    fn transaction_block(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>>;
54
55    /// Get transactions by block id.
56    fn transactions_by_block(
57        &self,
58        block: BlockHashOrNumber,
59    ) -> ProviderResult<Option<Vec<Self::Transaction>>>;
60
61    /// Get transactions by block range.
62    fn transactions_by_block_range(
63        &self,
64        range: impl RangeBounds<BlockNumber>,
65    ) -> ProviderResult<Vec<Vec<Self::Transaction>>>;
66
67    /// Get transactions by tx range.
68    fn transactions_by_tx_range(
69        &self,
70        range: impl RangeBounds<TxNumber>,
71    ) -> ProviderResult<Vec<Self::Transaction>>;
72
73    /// Get Senders from a tx range.
74    fn senders_by_tx_range(
75        &self,
76        range: impl RangeBounds<TxNumber>,
77    ) -> ProviderResult<Vec<Address>>;
78
79    /// Get transaction sender.
80    ///
81    /// Returns None if the transaction is not found.
82    fn transaction_sender(&self, id: TxNumber) -> ProviderResult<Option<Address>>;
83}
84
85/// A helper type alias to access [`TransactionsProvider::Transaction`].
86pub type ProviderTx<P> = <P as TransactionsProvider>::Transaction;
87
88///  Client trait for fetching additional transactions related data.
89#[auto_impl::auto_impl(&, Arc)]
90pub trait TransactionsProviderExt: BlockReader {
91    /// Get transactions range by block range.
92    fn transaction_range_by_block_range(
93        &self,
94        block_range: RangeInclusive<BlockNumber>,
95    ) -> ProviderResult<RangeInclusive<TxNumber>> {
96        let from = self
97            .block_body_indices(*block_range.start())?
98            .ok_or_else(|| ProviderError::BlockBodyIndicesNotFound(*block_range.start()))?
99            .first_tx_num();
100
101        let to = self
102            .block_body_indices(*block_range.end())?
103            .ok_or_else(|| ProviderError::BlockBodyIndicesNotFound(*block_range.end()))?
104            .last_tx_num();
105
106        Ok(from..=to)
107    }
108
109    /// Get transaction hashes from a transaction range.
110    fn transaction_hashes_by_range(
111        &self,
112        tx_range: Range<TxNumber>,
113    ) -> ProviderResult<Vec<(TxHash, TxNumber)>>;
114}