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