reth_optimism_rpc/eth/
block.rs

1//! Loads and formats OP block RPC response.
2
3use alloy_consensus::{transaction::TransactionMeta, BlockHeader};
4use alloy_rpc_types_eth::BlockId;
5use op_alloy_rpc_types::OpTransactionReceipt;
6use reth_chainspec::ChainSpecProvider;
7use reth_node_api::BlockBody;
8use reth_optimism_chainspec::OpChainSpec;
9use reth_optimism_primitives::{OpReceipt, OpTransactionSigned};
10use reth_primitives_traits::SignedTransaction;
11use reth_provider::{BlockReader, HeaderProvider};
12use reth_rpc_eth_api::{
13    helpers::{EthBlocks, LoadBlock, LoadPendingBlock, LoadReceipt, SpawnBlocking},
14    types::RpcTypes,
15    RpcReceipt,
16};
17
18use crate::{eth::OpNodeCore, OpEthApi, OpEthApiError, OpReceiptBuilder};
19
20impl<N> EthBlocks for OpEthApi<N>
21where
22    Self: LoadBlock<
23        Error = OpEthApiError,
24        NetworkTypes: RpcTypes<Receipt = OpTransactionReceipt>,
25        Provider: BlockReader<Receipt = OpReceipt, Transaction = OpTransactionSigned>,
26    >,
27    N: OpNodeCore<Provider: ChainSpecProvider<ChainSpec = OpChainSpec> + HeaderProvider>,
28{
29    async fn block_receipts(
30        &self,
31        block_id: BlockId,
32    ) -> Result<Option<Vec<RpcReceipt<Self::NetworkTypes>>>, Self::Error>
33    where
34        Self: LoadReceipt,
35    {
36        if let Some((block, receipts)) = self.load_block_and_receipts(block_id).await? {
37            let block_number = block.number();
38            let base_fee = block.base_fee_per_gas();
39            let block_hash = block.hash();
40            let excess_blob_gas = block.excess_blob_gas();
41            let timestamp = block.timestamp();
42
43            let mut l1_block_info = reth_optimism_evm::extract_l1_info(block.body())?;
44
45            return block
46                .body()
47                .transactions()
48                .iter()
49                .zip(receipts.iter())
50                .enumerate()
51                .map(|(idx, (tx, receipt))| -> Result<_, _> {
52                    let meta = TransactionMeta {
53                        tx_hash: *tx.tx_hash(),
54                        index: idx as u64,
55                        block_hash,
56                        block_number,
57                        base_fee,
58                        excess_blob_gas,
59                        timestamp,
60                    };
61
62                    // We must clear this cache as different L2 transactions can have different
63                    // L1 costs. A potential improvement here is to only clear the cache if the
64                    // new transaction input has changed, since otherwise the L1 cost wouldn't.
65                    l1_block_info.clear_tx_l1_cost();
66
67                    Ok(OpReceiptBuilder::new(
68                        &self.inner.eth_api.provider().chain_spec(),
69                        tx,
70                        meta,
71                        receipt,
72                        &receipts,
73                        &mut l1_block_info,
74                    )?
75                    .build())
76                })
77                .collect::<Result<Vec<_>, Self::Error>>()
78                .map(Some)
79        }
80
81        Ok(None)
82    }
83}
84
85impl<N> LoadBlock for OpEthApi<N>
86where
87    Self: LoadPendingBlock + SpawnBlocking,
88    N: OpNodeCore,
89{
90}