reth_primitives_traits/block/
body.rs1use crate::{
4 transaction::signed::RecoveryError, BlockHeader, FullSignedTx, InMemorySize, MaybeSerde,
5 MaybeSerdeBincodeCompat, SignedTransaction,
6};
7use alloc::{fmt, vec::Vec};
8use alloy_consensus::{
9 transaction::{Recovered, TxHashRef},
10 Transaction, Typed2718,
11};
12use alloy_eips::{eip2718::Encodable2718, eip4895::Withdrawals};
13use alloy_primitives::{Address, Bytes, B256};
14
15pub trait FullBlockBody: BlockBody<Transaction: FullSignedTx> + MaybeSerdeBincodeCompat {}
17
18impl<T> FullBlockBody for T where T: BlockBody<Transaction: FullSignedTx> + MaybeSerdeBincodeCompat {}
19
20pub trait BlockBody:
25 Send
26 + Sync
27 + Unpin
28 + Clone
29 + Default
30 + fmt::Debug
31 + PartialEq
32 + Eq
33 + alloy_rlp::Encodable
34 + alloy_rlp::Decodable
35 + InMemorySize
36 + MaybeSerde
37 + 'static
38{
39 type Transaction: SignedTransaction;
41
42 type OmmerHeader: BlockHeader;
44
45 fn transactions(&self) -> &[Self::Transaction];
47
48 fn into_ethereum_body(self)
59 -> alloy_consensus::BlockBody<Self::Transaction, Self::OmmerHeader>;
60
61 fn transactions_iter(&self) -> impl Iterator<Item = &Self::Transaction> + '_ {
63 self.transactions().iter()
64 }
65
66 fn transaction_by_hash(&self, hash: &B256) -> Option<&Self::Transaction> {
70 self.transactions_iter().find(|tx| tx.tx_hash() == hash)
71 }
72
73 fn contains_transaction(&self, hash: &B256) -> bool {
77 self.transaction_by_hash(hash).is_some()
78 }
79
80 fn clone_transactions(&self) -> Vec<Self::Transaction> {
84 self.transactions().to_vec()
85 }
86
87 fn transaction_hashes_iter(&self) -> impl Iterator<Item = &B256> + '_ {
89 self.transactions_iter().map(|tx| tx.tx_hash())
90 }
91
92 fn transaction_count(&self) -> usize {
94 self.transactions().len()
95 }
96
97 fn into_transactions(self) -> Vec<Self::Transaction>;
99
100 fn contains_transaction_type(&self, tx_type: u8) -> bool {
102 self.transactions_iter().any(|tx| tx.is_type(tx_type))
103 }
104
105 fn calculate_tx_root(&self) -> B256 {
107 alloy_consensus::proofs::calculate_transaction_root(self.transactions())
108 }
109
110 fn withdrawals(&self) -> Option<&Withdrawals>;
112
113 fn calculate_withdrawals_root(&self) -> Option<B256> {
117 self.withdrawals().map(|withdrawals| {
118 alloy_consensus::proofs::calculate_withdrawals_root(withdrawals.as_slice())
119 })
120 }
121
122 fn ommers(&self) -> Option<&[Self::OmmerHeader]>;
124
125 fn calculate_ommers_root(&self) -> Option<B256> {
129 self.ommers().map(alloy_consensus::proofs::calculate_ommers_root)
130 }
131
132 fn blob_gas_used(&self) -> u64 {
134 self.transactions_iter().filter_map(|tx| tx.blob_gas_used()).sum()
135 }
136
137 fn blob_versioned_hashes_iter(&self) -> impl Iterator<Item = &B256> + '_ {
139 self.transactions_iter().filter_map(|tx| tx.blob_versioned_hashes()).flatten()
140 }
141
142 #[doc(alias = "raw_transactions_iter")]
148 fn encoded_2718_transactions_iter(&self) -> impl Iterator<Item = Vec<u8>> + '_ {
149 self.transactions_iter().map(|tx| tx.encoded_2718())
150 }
151
152 #[doc(alias = "raw_transactions")]
158 fn encoded_2718_transactions(&self) -> Vec<Bytes> {
159 self.encoded_2718_transactions_iter().map(Into::into).collect()
160 }
161
162 fn recover_signers(&self) -> Result<Vec<Address>, RecoveryError> {
164 crate::transaction::recover::recover_signers(self.transactions())
165 }
166
167 fn try_recover_signers(&self) -> Result<Vec<Address>, RecoveryError> {
171 self.recover_signers()
172 }
173
174 fn recover_signers_unchecked(&self) -> Result<Vec<Address>, RecoveryError> {
179 crate::transaction::recover::recover_signers_unchecked(self.transactions())
180 }
181
182 fn try_recover_signers_unchecked(&self) -> Result<Vec<Address>, RecoveryError> {
187 self.recover_signers_unchecked()
188 }
189
190 fn recover_transactions(&self) -> Result<Vec<Recovered<Self::Transaction>>, RecoveryError> {
193 self.recover_signers().map(|signers| {
194 self.transactions()
195 .iter()
196 .zip(signers)
197 .map(|(tx, signer)| tx.clone().with_signer(signer))
198 .collect()
199 })
200 }
201}
202
203impl<T, H> BlockBody for alloy_consensus::BlockBody<T, H>
204where
205 T: SignedTransaction,
206 H: BlockHeader,
207{
208 type Transaction = T;
209 type OmmerHeader = H;
210
211 fn transactions(&self) -> &[Self::Transaction] {
212 &self.transactions
213 }
214
215 fn into_ethereum_body(self) -> Self {
216 self
217 }
218
219 fn into_transactions(self) -> Vec<Self::Transaction> {
220 self.transactions
221 }
222
223 fn withdrawals(&self) -> Option<&Withdrawals> {
224 self.withdrawals.as_ref()
225 }
226
227 fn ommers(&self) -> Option<&[Self::OmmerHeader]> {
228 Some(&self.ommers)
229 }
230}
231
232pub type BodyTx<N> = <N as BlockBody>::Transaction;
235
236pub type BodyOmmer<N> = <N as BlockBody>::OmmerHeader;