Skip to main content

reth_rpc_eth_api/helpers/
receipt.rs

1//! Loads a receipt from database. Helper trait for `eth_` block and transaction RPC methods, that
2//! loads receipt data w.r.t. network.
3
4use std::sync::Arc;
5
6use crate::{EthApiTypes, RpcNodeCoreExt, RpcReceipt};
7use alloy_consensus::{transaction::TransactionMeta, TxReceipt};
8use futures::Future;
9use reth_primitives_traits::Recovered;
10use reth_rpc_convert::{transaction::ConvertReceiptInput, RpcConvert};
11use reth_rpc_eth_types::{
12    error::FromEthApiError, utils::calculate_gas_used_and_next_log_index, EthApiError,
13};
14use reth_storage_api::{ProviderReceipt, ProviderTx};
15
16/// Assembles transaction receipt data w.r.t to network.
17///
18/// Behaviour shared by several `eth_` RPC methods, not exclusive to `eth_` receipts RPC methods.
19pub trait LoadReceipt:
20    EthApiTypes<RpcConvert: RpcConvert<Primitives = Self::Primitives>> + RpcNodeCoreExt + Send + Sync
21{
22    /// Helper method for `eth_getBlockReceipts` and `eth_getTransactionReceipt`.
23    ///
24    /// If `all_receipts` is `Some`, skips the cache lookup for receipts entirely.
25    fn build_transaction_receipt(
26        &self,
27        tx: Recovered<ProviderTx<Self::Provider>>,
28        meta: TransactionMeta,
29        receipt: ProviderReceipt<Self::Provider>,
30        all_receipts: Option<Arc<Vec<ProviderReceipt<Self::Provider>>>>,
31    ) -> impl Future<Output = Result<RpcReceipt<Self::NetworkTypes>, Self::Error>> + Send {
32        async move {
33            let hash = meta.block_hash;
34            // Use pre-fetched receipts if available, otherwise fetch from cache.
35            let all_receipts = match all_receipts {
36                Some(receipts) => receipts,
37                None => self
38                    .cache()
39                    .get_receipts(hash)
40                    .await
41                    .map_err(Self::Error::from_eth_err)?
42                    .ok_or(EthApiError::HeaderNotFound(hash.into()))?,
43            };
44
45            let (gas_used, next_log_index) =
46                calculate_gas_used_and_next_log_index(meta.index, &all_receipts);
47
48            Ok(self
49                .converter()
50                .convert_receipts(vec![ConvertReceiptInput {
51                    tx: tx.as_recovered_ref(),
52                    gas_used: receipt.cumulative_gas_used() - gas_used,
53                    receipt,
54                    next_log_index,
55                    meta,
56                }])?
57                .pop()
58                .unwrap())
59        }
60    }
61}