reth_rpc_types_compat/
block.rs1use alloy_consensus::{BlockHeader, Sealable, Sealed, Typed2718};
4use alloy_eips::eip4895::Withdrawals;
5use alloy_primitives::{B256, U256};
6use alloy_rpc_types_eth::{
7 Block, BlockTransactions, BlockTransactionsKind, Header, TransactionInfo,
8};
9use reth_primitives::{transaction::SignedTransactionIntoRecoveredExt, BlockWithSenders};
10use reth_primitives_traits::{Block as BlockTrait, BlockBody, SignedTransaction};
11
12use crate::{transaction::from_recovered_with_block_context, TransactionCompat};
13
14#[expect(clippy::type_complexity)]
19pub fn from_block<T, B>(
20 block: BlockWithSenders<B>,
21 kind: BlockTransactionsKind,
22 block_hash: Option<B256>,
23 tx_resp_builder: &T,
24) -> Result<Block<T::Transaction, Header<B::Header>>, T::Error>
25where
26 T: TransactionCompat<<<B as BlockTrait>::Body as BlockBody>::Transaction>,
27 B: BlockTrait,
28{
29 match kind {
30 BlockTransactionsKind::Hashes => {
31 Ok(from_block_with_tx_hashes::<T::Transaction, B>(block, block_hash))
32 }
33 BlockTransactionsKind::Full => from_block_full::<T, B>(block, block_hash, tx_resp_builder),
34 }
35}
36
37pub fn from_block_with_tx_hashes<T, B>(
43 block: BlockWithSenders<B>,
44 block_hash: Option<B256>,
45) -> Block<T, Header<B::Header>>
46where
47 B: BlockTrait,
48{
49 let block_hash = block_hash.unwrap_or_else(|| block.header().hash_slow());
50 let transactions = block.body().transactions().iter().map(|tx| *tx.tx_hash()).collect();
51
52 from_block_with_transactions(
53 block.length(),
54 block_hash,
55 block.block,
56 BlockTransactions::Hashes(transactions),
57 )
58}
59
60#[expect(clippy::type_complexity)]
66pub fn from_block_full<T, B>(
67 block: BlockWithSenders<B>,
68 block_hash: Option<B256>,
69 tx_resp_builder: &T,
70) -> Result<Block<T::Transaction, Header<B::Header>>, T::Error>
71where
72 T: TransactionCompat<<<B as BlockTrait>::Body as BlockBody>::Transaction>,
73 B: BlockTrait,
74{
75 let block_hash = block_hash.unwrap_or_else(|| block.block.header().hash_slow());
76 let block_number = block.block.header().number();
77 let base_fee_per_gas = block.block.header().base_fee_per_gas();
78
79 let block_length = block.block.length();
82 let transactions = block.block.body().transactions().to_vec();
83 let transactions_with_senders = transactions.into_iter().zip(block.senders);
84 let transactions = transactions_with_senders
85 .enumerate()
86 .map(|(idx, (tx, sender))| {
87 let tx_type = Some(tx.ty() as isize);
88 let tx_hash = *tx.tx_hash();
89 let signed_tx_ec_recovered = tx.with_signer(sender);
90 let tx_info = TransactionInfo {
91 hash: Some(tx_hash),
92 block_hash: Some(block_hash),
93 block_number: Some(block_number),
94 base_fee: base_fee_per_gas.map(u128::from),
95 index: Some(idx as u64),
96 tx_type,
97 };
98
99 from_recovered_with_block_context::<_, T>(
100 signed_tx_ec_recovered,
101 tx_info,
102 tx_resp_builder,
103 )
104 })
105 .collect::<Result<Vec<_>, T::Error>>()?;
106
107 Ok(from_block_with_transactions(
108 block_length,
109 block_hash,
110 block.block,
111 BlockTransactions::Full(transactions),
112 ))
113}
114
115#[inline]
116fn from_block_with_transactions<T, B: BlockTrait>(
117 block_length: usize,
118 block_hash: B256,
119 block: B,
120 transactions: BlockTransactions<T>,
121) -> Block<T, Header<B::Header>> {
122 let withdrawals = block
123 .header()
124 .withdrawals_root()
125 .is_some()
126 .then(|| block.body().withdrawals().cloned().map(Withdrawals::into_inner).map(Into::into))
127 .flatten();
128
129 let uncles = block
130 .body()
131 .ommers()
132 .map(|o| o.iter().map(|h| h.hash_slow()).collect())
133 .unwrap_or_default();
134 let (header, _) = block.split();
135 let header = Header::from_consensus(
136 Sealed::new_unchecked(header, block_hash),
137 None,
138 Some(U256::from(block_length)),
139 );
140
141 Block { header, uncles, transactions, withdrawals }
142}