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 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 transactions by block id.
53    fn transactions_by_block(
54        &self,
55        block: BlockHashOrNumber,
56    ) -> ProviderResult<Option<Vec<Self::Transaction>>>;
57
58    /// Get transactions by block range.
59    fn transactions_by_block_range(
60        &self,
61        range: impl RangeBounds<BlockNumber>,
62    ) -> ProviderResult<Vec<Vec<Self::Transaction>>>;
63
64    /// Get transactions by tx range.
65    fn transactions_by_tx_range(
66        &self,
67        range: impl RangeBounds<TxNumber>,
68    ) -> ProviderResult<Vec<Self::Transaction>>;
69
70    /// Get Senders from a tx range.
71    fn senders_by_tx_range(
72        &self,
73        range: impl RangeBounds<TxNumber>,
74    ) -> ProviderResult<Vec<Address>>;
75
76    /// Get transaction sender.
77    ///
78    /// Returns None if the transaction is not found.
79    fn transaction_sender(&self, id: TxNumber) -> ProviderResult<Option<Address>>;
80}
81
82/// A helper type alias to access [`TransactionsProvider::Transaction`].
83pub type ProviderTx<P> = <P as TransactionsProvider>::Transaction;
84
85///  Client trait for fetching additional transactions related data.
86#[auto_impl::auto_impl(&, Arc)]
87pub trait TransactionsProviderExt: BlockReader {
88    /// Get transactions range by block range.
89    fn transaction_range_by_block_range(
90        &self,
91        block_range: RangeInclusive<BlockNumber>,
92    ) -> ProviderResult<RangeInclusive<TxNumber>> {
93        let from = self
94            .block_body_indices(*block_range.start())?
95            .ok_or_else(|| ProviderError::BlockBodyIndicesNotFound(*block_range.start()))?
96            .first_tx_num();
97
98        let to = self
99            .block_body_indices(*block_range.end())?
100            .ok_or_else(|| ProviderError::BlockBodyIndicesNotFound(*block_range.end()))?
101            .last_tx_num();
102
103        Ok(from..=to)
104    }
105
106    /// Get transaction hashes from a transaction range.
107    fn transaction_hashes_by_range(
108        &self,
109        tx_range: Range<TxNumber>,
110    ) -> ProviderResult<Vec<(TxHash, TxNumber)>>;
111}