reth_rpc_eth_api/helpers/
receipt.rs1use 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};
11
12pub fn calculate_gas_used_and_next_log_index(
14 tx_index: u64,
15 all_receipts: &[impl TxReceipt],
16) -> (u64, usize) {
17 let mut gas_used = 0;
18 let mut next_log_index = 0;
19
20 if tx_index > 0 {
21 for receipt in all_receipts.iter().take(tx_index as usize) {
22 gas_used = receipt.cumulative_gas_used();
23 next_log_index += receipt.logs().len();
24 }
25 }
26
27 (gas_used, next_log_index)
28}
29
30pub trait LoadReceipt:
34 EthApiTypes<
35 RpcConvert: RpcConvert<
36 Primitives = Self::Primitives,
37 Error = Self::Error,
38 Network = Self::NetworkTypes,
39 >,
40 Error: FromEthApiError,
41 > + RpcNodeCoreExt
42 + Send
43 + Sync
44{
45 fn build_transaction_receipt(
47 &self,
48 tx: ProviderTx<Self::Provider>,
49 meta: TransactionMeta,
50 receipt: ProviderReceipt<Self::Provider>,
51 ) -> impl Future<Output = Result<RpcReceipt<Self::NetworkTypes>, Self::Error>> + Send {
52 async move {
53 let hash = meta.block_hash;
54 let all_receipts = self
56 .cache()
57 .get_receipts(hash)
58 .await
59 .map_err(Self::Error::from_eth_err)?
60 .ok_or(EthApiError::HeaderNotFound(hash.into()))?;
61
62 let (gas_used, next_log_index) =
63 calculate_gas_used_and_next_log_index(meta.index, &all_receipts);
64
65 Ok(self
66 .tx_resp_builder()
67 .convert_receipts(vec![ConvertReceiptInput {
68 tx: tx
69 .try_into_recovered_unchecked()
70 .map_err(Self::Error::from_eth_err)?
71 .as_recovered_ref(),
72 gas_used: receipt.cumulative_gas_used() - gas_used,
73 receipt,
74 next_log_index,
75 meta,
76 }])?
77 .pop()
78 .unwrap())
79 }
80 }
81}