reth_rpc_eth_types/
pending_block.rs1use std::{sync::Arc, time::Instant};
6
7use alloy_consensus::BlockHeader;
8use alloy_eips::{BlockId, BlockNumberOrTag};
9use alloy_primitives::{BlockHash, B256};
10use derive_more::Constructor;
11use reth_chain_state::{
12 BlockState, ExecutedBlock, ExecutedBlockWithTrieUpdates, ExecutedTrieUpdates,
13};
14use reth_ethereum_primitives::Receipt;
15use reth_evm::EvmEnv;
16use reth_primitives_traits::{Block, NodePrimitives, RecoveredBlock, SealedHeader};
17
18#[derive(Debug, Clone, Constructor)]
20pub struct PendingBlockEnv<B: Block, R, Spec> {
21 pub evm_env: EvmEnv<Spec>,
23 pub origin: PendingBlockEnvOrigin<B, R>,
25}
26
27#[derive(Clone, Debug)]
29pub enum PendingBlockEnvOrigin<B: Block = reth_ethereum_primitives::Block, R = Receipt> {
30 ActualPending(Arc<RecoveredBlock<B>>, Arc<Vec<R>>),
32 DerivedFromLatest(SealedHeader<B::Header>),
39}
40
41impl<B: Block, R> PendingBlockEnvOrigin<B, R> {
42 pub const fn is_actual_pending(&self) -> bool {
44 matches!(self, Self::ActualPending(_, _))
45 }
46
47 pub fn into_actual_pending(self) -> Option<Arc<RecoveredBlock<B>>> {
49 match self {
50 Self::ActualPending(block, _) => Some(block),
51 _ => None,
52 }
53 }
54
55 pub fn state_block_id(&self) -> BlockId {
60 match self {
61 Self::ActualPending(_, _) => BlockNumberOrTag::Pending.into(),
62 Self::DerivedFromLatest(latest) => BlockId::Hash(latest.hash().into()),
63 }
64 }
65
66 pub fn build_target_hash(&self) -> B256 {
72 match self {
73 Self::ActualPending(block, _) => block.header().parent_hash(),
74 Self::DerivedFromLatest(latest) => latest.hash(),
75 }
76 }
77}
78
79pub type PendingRecoveredBlock<N> = Arc<RecoveredBlock<<N as NodePrimitives>::Block>>;
81
82pub type PendingBlockReceipts<N> = Arc<Vec<<N as NodePrimitives>::Receipt>>;
84
85pub type PendingBlockAndReceipts<N> = (PendingRecoveredBlock<N>, PendingBlockReceipts<N>);
88
89#[derive(Debug, Clone, Constructor)]
91pub struct PendingBlock<N: NodePrimitives> {
92 pub expires_at: Instant,
94 pub receipts: PendingBlockReceipts<N>,
96 pub executed_block: ExecutedBlock<N>,
98}
99
100impl<N: NodePrimitives> PendingBlock<N> {
101 pub fn with_executed_block(expires_at: Instant, executed_block: ExecutedBlock<N>) -> Self {
104 Self {
105 expires_at,
106 receipts: Arc::new(
107 executed_block.execution_output.receipts.iter().flatten().cloned().collect(),
108 ),
109 executed_block,
110 }
111 }
112
113 pub const fn block(&self) -> &PendingRecoveredBlock<N> {
115 &self.executed_block.recovered_block
116 }
117
118 pub fn into_block_and_receipts(self) -> PendingBlockAndReceipts<N> {
121 (self.executed_block.recovered_block, self.receipts)
122 }
123
124 pub fn to_block_and_receipts(&self) -> PendingBlockAndReceipts<N> {
127 (self.executed_block.recovered_block.clone(), self.receipts.clone())
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}