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 crate::{EthApiTypes, RpcNodeCoreExt, RpcReceipt};
5use alloy_consensus::{transaction::TransactionMeta, TxReceipt};
6use futures::Future;
7use reth_primitives_traits::SignerRecoverable;
8use reth_rpc_convert::{transaction::ConvertReceiptInput, RpcConvert};
9use reth_rpc_eth_types::{error::FromEthApiError, EthApiError};
10use reth_storage_api::{ProviderReceipt, ProviderTx};
11use std::borrow::Cow;
12
13/// Assembles transaction receipt data w.r.t to network.
14///
15/// Behaviour shared by several `eth_` RPC methods, not exclusive to `eth_` receipts RPC methods.
16pub trait LoadReceipt:
17    EthApiTypes<
18        RpcConvert: RpcConvert<
19            Primitives = Self::Primitives,
20            Error = Self::Error,
21            Network = Self::NetworkTypes,
22        >,
23        Error: FromEthApiError,
24    > + RpcNodeCoreExt
25    + Send
26    + Sync
27{
28    /// Helper method for `eth_getBlockReceipts` and `eth_getTransactionReceipt`.
29    fn build_transaction_receipt(
30        &self,
31        tx: ProviderTx<Self::Provider>,
32        meta: TransactionMeta,
33        receipt: ProviderReceipt<Self::Provider>,
34    ) -> impl Future<Output = Result<RpcReceipt<Self::NetworkTypes>, Self::Error>> + Send {
35        async move {
36            let hash = meta.block_hash;
37            // get all receipts for the block
38            let all_receipts = self
39                .cache()
40                .get_receipts(hash)
41                .await
42                .map_err(Self::Error::from_eth_err)?
43                .ok_or(EthApiError::HeaderNotFound(hash.into()))?;
44
45            let mut gas_used = 0;
46            let mut next_log_index = 0;
47
48            if meta.index > 0 {
49                for receipt in all_receipts.iter().take(meta.index as usize) {
50                    gas_used = receipt.cumulative_gas_used();
51                    next_log_index += receipt.logs().len();
52                }
53            }
54
55            Ok(self
56                .tx_resp_builder()
57                .convert_receipts(vec![ConvertReceiptInput {
58                    tx: tx
59                        .try_into_recovered_unchecked()
60                        .map_err(Self::Error::from_eth_err)?
61                        .as_recovered_ref(),
62                    gas_used: receipt.cumulative_gas_used() - gas_used,
63                    receipt: Cow::Owned(receipt),
64                    next_log_index,
65                    meta,
66                }])?
67                .pop()
68                .unwrap())
69        }
70    }
71}