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}