reth_rpc_eth_types/
pending_block.rs

1//! Helper types for `reth_rpc_eth_api::EthApiServer` implementation.
2//!
3//! Types used in block building.
4
5use std::time::Instant;
6
7use alloy_consensus::BlockHeader;
8use alloy_eips::{BlockId, BlockNumberOrTag};
9use alloy_primitives::B256;
10use derive_more::Constructor;
11use reth_ethereum_primitives::Receipt;
12use reth_evm::EvmEnv;
13use reth_primitives_traits::{Block, RecoveredBlock, SealedHeader};
14
15/// Configured [`EvmEnv`] for a pending block.
16#[derive(Debug, Clone, Constructor)]
17pub struct PendingBlockEnv<B: Block, R, Spec> {
18    /// Configured [`EvmEnv`] for the pending block.
19    pub evm_env: EvmEnv<Spec>,
20    /// Origin block for the config
21    pub origin: PendingBlockEnvOrigin<B, R>,
22}
23
24/// The origin for a configured [`PendingBlockEnv`]
25#[derive(Clone, Debug)]
26pub enum PendingBlockEnvOrigin<B: Block = reth_ethereum_primitives::Block, R = Receipt> {
27    /// The pending block as received from the CL.
28    ActualPending(RecoveredBlock<B>, Vec<R>),
29    /// The _modified_ header of the latest block.
30    ///
31    /// This derives the pending state based on the latest header by modifying:
32    ///  - the timestamp
33    ///  - the block number
34    ///  - fees
35    DerivedFromLatest(SealedHeader<B::Header>),
36}
37
38impl<B: Block, R> PendingBlockEnvOrigin<B, R> {
39    /// Returns true if the origin is the actual pending block as received from the CL.
40    pub const fn is_actual_pending(&self) -> bool {
41        matches!(self, Self::ActualPending(_, _))
42    }
43
44    /// Consumes the type and returns the actual pending block.
45    pub fn into_actual_pending(self) -> Option<RecoveredBlock<B>> {
46        match self {
47            Self::ActualPending(block, _) => Some(block),
48            _ => None,
49        }
50    }
51
52    /// Returns the [`BlockId`] that represents the state of the block.
53    ///
54    /// If this is the actual pending block, the state is the "Pending" tag, otherwise we can safely
55    /// identify the block by its hash (latest block).
56    pub fn state_block_id(&self) -> BlockId {
57        match self {
58            Self::ActualPending(_, _) => BlockNumberOrTag::Pending.into(),
59            Self::DerivedFromLatest(latest) => BlockId::Hash(latest.hash().into()),
60        }
61    }
62
63    /// Returns the hash of the block the pending block should be built on.
64    ///
65    /// For the [`PendingBlockEnvOrigin::ActualPending`] this is the parent hash of the block.
66    /// For the [`PendingBlockEnvOrigin::DerivedFromLatest`] this is the hash of the _latest_
67    /// header.
68    pub fn build_target_hash(&self) -> B256 {
69        match self {
70            Self::ActualPending(block, _) => block.header().parent_hash(),
71            Self::DerivedFromLatest(latest) => latest.hash(),
72        }
73    }
74}
75
76/// Locally built pending block for `pending` tag.
77#[derive(Debug, Constructor)]
78pub struct PendingBlock<B: Block, R> {
79    /// Timestamp when the pending block is considered outdated.
80    pub expires_at: Instant,
81    /// The locally built pending block.
82    pub block: RecoveredBlock<B>,
83    /// The receipts for the pending block
84    pub receipts: Vec<R>,
85}