reth_storage_api/
transactions.rs

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