reth_optimism_rpc/eth/
pending_block.rs

1//! Loads OP pending block for a RPC response.
2
3use crate::OpEthApi;
4use alloy_consensus::BlockHeader;
5use alloy_eips::BlockNumberOrTag;
6use alloy_primitives::B256;
7use reth_chainspec::EthChainSpec;
8use reth_evm::execute::BlockExecutionStrategyFactory;
9use reth_node_api::NodePrimitives;
10use reth_optimism_evm::OpNextBlockEnvAttributes;
11use reth_optimism_forks::OpHardforks;
12use reth_optimism_primitives::{OpBlock, OpReceipt, OpTransactionSigned};
13use reth_primitives::{RecoveredBlock, SealedHeader};
14use reth_provider::{
15    BlockReader, BlockReaderIdExt, ChainSpecProvider, ProviderBlock, ProviderHeader,
16    ProviderReceipt, ProviderTx, ReceiptProvider, StateProviderFactory,
17};
18use reth_rpc_eth_api::{
19    helpers::{LoadPendingBlock, SpawnBlocking},
20    types::RpcTypes,
21    EthApiTypes, FromEthApiError, FromEvmError, RpcNodeCore,
22};
23use reth_rpc_eth_types::{EthApiError, PendingBlock};
24use reth_transaction_pool::{PoolTransaction, TransactionPool};
25
26impl<N> LoadPendingBlock for OpEthApi<N>
27where
28    Self: SpawnBlocking
29        + EthApiTypes<
30            NetworkTypes: RpcTypes<
31                Header = alloy_rpc_types_eth::Header<ProviderHeader<Self::Provider>>,
32            >,
33            Error: FromEvmError<Self::Evm>,
34        >,
35    N: RpcNodeCore<
36        Provider: BlockReaderIdExt<
37            Transaction = OpTransactionSigned,
38            Block = OpBlock,
39            Receipt = OpReceipt,
40            Header = reth_primitives::Header,
41        > + ChainSpecProvider<ChainSpec: EthChainSpec + OpHardforks>
42                      + StateProviderFactory,
43        Pool: TransactionPool<Transaction: PoolTransaction<Consensus = ProviderTx<N::Provider>>>,
44        Evm: BlockExecutionStrategyFactory<
45            Primitives: NodePrimitives<
46                SignedTx = ProviderTx<Self::Provider>,
47                BlockHeader = ProviderHeader<Self::Provider>,
48                Receipt = ProviderReceipt<Self::Provider>,
49                Block = ProviderBlock<Self::Provider>,
50            >,
51            NextBlockEnvCtx = OpNextBlockEnvAttributes,
52        >,
53    >,
54{
55    #[inline]
56    fn pending_block(
57        &self,
58    ) -> &tokio::sync::Mutex<
59        Option<PendingBlock<ProviderBlock<Self::Provider>, ProviderReceipt<Self::Provider>>>,
60    > {
61        self.inner.eth_api.pending_block()
62    }
63
64    fn next_env_attributes(
65        &self,
66        parent: &SealedHeader<ProviderHeader<Self::Provider>>,
67    ) -> Result<<Self::Evm as reth_evm::ConfigureEvmEnv>::NextBlockEnvCtx, Self::Error> {
68        Ok(OpNextBlockEnvAttributes {
69            timestamp: parent.timestamp().saturating_add(12),
70            suggested_fee_recipient: parent.beneficiary(),
71            prev_randao: B256::random(),
72            gas_limit: parent.gas_limit(),
73            parent_beacon_block_root: parent.parent_beacon_block_root(),
74            extra_data: parent.extra_data.clone(),
75        })
76    }
77
78    /// Returns the locally built pending block
79    async fn local_pending_block(
80        &self,
81    ) -> Result<
82        Option<(
83            RecoveredBlock<ProviderBlock<Self::Provider>>,
84            Vec<ProviderReceipt<Self::Provider>>,
85        )>,
86        Self::Error,
87    > {
88        // See: <https://github.com/ethereum-optimism/op-geth/blob/f2e69450c6eec9c35d56af91389a1c47737206ca/miner/worker.go#L367-L375>
89        let latest = self
90            .provider()
91            .latest_header()
92            .map_err(Self::Error::from_eth_err)?
93            .ok_or(EthApiError::HeaderNotFound(BlockNumberOrTag::Latest.into()))?;
94        let block_id = latest.hash().into();
95        let block = self
96            .provider()
97            .block_with_senders(block_id, Default::default())
98            .map_err(Self::Error::from_eth_err)?
99            .ok_or(EthApiError::HeaderNotFound(block_id.into()))?;
100
101        let receipts = self
102            .provider()
103            .receipts_by_block(block_id)
104            .map_err(Self::Error::from_eth_err)?
105            .ok_or(EthApiError::ReceiptsNotFound(block_id.into()))?;
106
107        Ok(Some((block, receipts)))
108    }
109}