reth_rpc_eth_types/
pending_block.rs1use std::{sync::Arc, time::Instant};
6
7use crate::block::BlockAndReceipts;
8use alloy_consensus::BlockHeader;
9use alloy_eips::{BlockId, BlockNumberOrTag};
10use alloy_primitives::{BlockHash, B256};
11use derive_more::Constructor;
12use reth_chain_state::{
13 BlockState, ExecutedBlock, ExecutedBlockWithTrieUpdates, ExecutedTrieUpdates,
14};
15use reth_ethereum_primitives::Receipt;
16use reth_evm::EvmEnv;
17use reth_primitives_traits::{
18 Block, BlockTy, NodePrimitives, ReceiptTy, RecoveredBlock, SealedHeader,
19};
20
21#[derive(Debug, Clone, Constructor)]
23pub struct PendingBlockEnv<B: Block, R, Spec> {
24 pub evm_env: EvmEnv<Spec>,
26 pub origin: PendingBlockEnvOrigin<B, R>,
28}
29
30#[derive(Clone, Debug)]
32pub enum PendingBlockEnvOrigin<B: Block = reth_ethereum_primitives::Block, R = Receipt> {
33 ActualPending(Arc<RecoveredBlock<B>>, Arc<Vec<R>>),
35 DerivedFromLatest(SealedHeader<B::Header>),
42}
43
44impl<B: Block, R> PendingBlockEnvOrigin<B, R> {
45 pub const fn is_actual_pending(&self) -> bool {
47 matches!(self, Self::ActualPending(_, _))
48 }
49
50 pub fn into_actual_pending(self) -> Option<Arc<RecoveredBlock<B>>> {
52 match self {
53 Self::ActualPending(block, _) => Some(block),
54 _ => None,
55 }
56 }
57
58 pub fn state_block_id(&self) -> BlockId {
63 match self {
64 Self::ActualPending(_, _) => BlockNumberOrTag::Pending.into(),
65 Self::DerivedFromLatest(latest) => BlockId::Hash(latest.hash().into()),
66 }
67 }
68
69 pub fn build_target_hash(&self) -> B256 {
75 match self {
76 Self::ActualPending(block, _) => block.header().parent_hash(),
77 Self::DerivedFromLatest(latest) => latest.hash(),
78 }
79 }
80}
81
82pub type PendingBlockAndReceipts<N> = BlockAndReceipts<N>;
85
86#[derive(Debug, Clone, Constructor)]
88pub struct PendingBlock<N: NodePrimitives> {
89 pub expires_at: Instant,
91 pub receipts: Arc<Vec<ReceiptTy<N>>>,
93 pub executed_block: ExecutedBlock<N>,
95}
96
97impl<N: NodePrimitives> PendingBlock<N> {
98 pub fn with_executed_block(expires_at: Instant, executed_block: ExecutedBlock<N>) -> Self {
101 Self {
102 expires_at,
103 receipts: Arc::new(
104 executed_block.execution_output.receipts.iter().flatten().cloned().collect(),
105 ),
106 executed_block,
107 }
108 }
109
110 pub const fn block(&self) -> &Arc<RecoveredBlock<BlockTy<N>>> {
112 &self.executed_block.recovered_block
113 }
114
115 pub fn into_block_and_receipts(self) -> PendingBlockAndReceipts<N> {
118 BlockAndReceipts { block: self.executed_block.recovered_block, receipts: self.receipts }
119 }
120
121 pub fn to_block_and_receipts(&self) -> PendingBlockAndReceipts<N> {
124 BlockAndReceipts {
125 block: self.executed_block.recovered_block.clone(),
126 receipts: self.receipts.clone(),
127 }
128 }
129
130 pub fn parent_hash(&self) -> BlockHash {
132 self.executed_block.recovered_block().parent_hash()
133 }
134}
135
136impl<N: NodePrimitives> From<PendingBlock<N>> for BlockState<N> {
137 fn from(pending_block: PendingBlock<N>) -> Self {
138 Self::new(ExecutedBlockWithTrieUpdates::<N>::new(
139 pending_block.executed_block.recovered_block,
140 pending_block.executed_block.execution_output,
141 pending_block.executed_block.hashed_state,
142 ExecutedTrieUpdates::Missing,
143 ))
144 }
145}