reth_primitives_traits/block/
mod.rs
1pub(crate) mod sealed;
4pub use sealed::SealedBlock;
5
6pub(crate) mod recovered;
7pub use recovered::RecoveredBlock;
8
9pub mod body;
10pub mod error;
11pub mod header;
12
13use alloc::{fmt, vec::Vec};
14use alloy_primitives::{Address, B256};
15use alloy_rlp::{Decodable, Encodable};
16
17use crate::{
18 block::error::BlockRecoveryError, transaction::signed::RecoveryError, BlockBody, BlockHeader,
19 FullBlockBody, FullBlockHeader, InMemorySize, MaybeSerde, SealedHeader, SignedTransaction,
20};
21
22#[cfg(feature = "serde-bincode-compat")]
24pub mod serde_bincode_compat {
25 pub use super::{
26 recovered::serde_bincode_compat::RecoveredBlock, sealed::serde_bincode_compat::SealedBlock,
27 };
28}
29
30pub trait FullBlock:
32 Block<Header: FullBlockHeader, Body: FullBlockBody> + alloy_rlp::Encodable + alloy_rlp::Decodable
33{
34}
35
36impl<T> FullBlock for T where
37 T: Block<Header: FullBlockHeader, Body: FullBlockBody>
38 + alloy_rlp::Encodable
39 + alloy_rlp::Decodable
40{
41}
42
43pub type BlockTx<B> = <<B as Block>::Body as BlockBody>::Transaction;
45
46pub trait Block:
52 Send
53 + Sync
54 + Unpin
55 + Clone
56 + Default
57 + fmt::Debug
58 + PartialEq
59 + Eq
60 + InMemorySize
61 + MaybeSerde
62 + Encodable
63 + Decodable
64{
65 type Header: BlockHeader;
67
68 type Body: BlockBody<OmmerHeader = Self::Header>;
71
72 fn new(header: Self::Header, body: Self::Body) -> Self;
74
75 fn new_sealed(header: SealedHeader<Self::Header>, body: Self::Body) -> SealedBlock<Self> {
77 SealedBlock::from_sealed_parts(header, body)
78 }
79
80 fn seal_unchecked(self, hash: B256) -> SealedBlock<Self> {
84 SealedBlock::new_unchecked(self, hash)
85 }
86
87 fn seal(self) -> SealedBlock<Self> {
89 SealedBlock::new_unhashed(self)
90 }
91
92 fn seal_slow(self) -> SealedBlock<Self> {
94 SealedBlock::seal_slow(self)
95 }
96
97 fn header(&self) -> &Self::Header;
99
100 fn body(&self) -> &Self::Body;
102
103 fn split(self) -> (Self::Header, Self::Body);
105
106 fn split_ref(&self) -> (&Self::Header, &Self::Body) {
108 (self.header(), self.body())
109 }
110
111 fn into_header(self) -> Self::Header {
113 self.split().0
114 }
115
116 fn into_body(self) -> Self::Body {
118 self.split().1
119 }
120
121 fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize;
123
124 fn recover_signers(&self) -> Result<Vec<Address>, RecoveryError>
126 where
127 <Self::Body as BlockBody>::Transaction: SignedTransaction,
128 {
129 self.body().recover_signers()
130 }
131
132 fn try_into_recovered_unchecked(
139 self,
140 senders: Vec<Address>,
141 ) -> Result<RecoveredBlock<Self>, BlockRecoveryError<Self>>
142 where
143 <Self::Body as BlockBody>::Transaction: SignedTransaction,
144 {
145 let senders = if self.body().transactions().len() == senders.len() {
146 senders
147 } else {
148 let Ok(senders) = self.body().recover_signers_unchecked() else {
150 return Err(BlockRecoveryError::new(self))
151 };
152 senders
153 };
154 Ok(RecoveredBlock::new_unhashed(self, senders))
155 }
156
157 fn into_recovered_with_signers(self, signers: Vec<Address>) -> RecoveredBlock<Self>
161 where
162 <Self::Body as BlockBody>::Transaction: SignedTransaction,
163 {
164 RecoveredBlock::new_unhashed(self, signers)
165 }
166
167 fn try_into_recovered(self) -> Result<RecoveredBlock<Self>, BlockRecoveryError<Self>>
172 where
173 <Self::Body as BlockBody>::Transaction: SignedTransaction,
174 {
175 let Ok(signers) = self.body().recover_signers() else {
176 return Err(BlockRecoveryError::new(self))
177 };
178 Ok(RecoveredBlock::new_unhashed(self, signers))
179 }
180
181 fn into_ethereum_block(
196 self,
197 ) -> alloy_consensus::Block<<Self::Body as BlockBody>::Transaction, Self::Header> {
198 let (header, body) = self.split();
199 alloy_consensus::Block::new(header, body.into_ethereum_body())
200 }
201}
202
203impl<T, H> Block for alloy_consensus::Block<T, H>
204where
205 T: SignedTransaction,
206 H: BlockHeader,
207{
208 type Header = H;
209 type Body = alloy_consensus::BlockBody<T, H>;
210
211 fn new(header: Self::Header, body: Self::Body) -> Self {
212 Self { header, body }
213 }
214
215 fn header(&self) -> &Self::Header {
216 &self.header
217 }
218
219 fn body(&self) -> &Self::Body {
220 &self.body
221 }
222
223 fn split(self) -> (Self::Header, Self::Body) {
224 (self.header, self.body)
225 }
226
227 fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize {
228 Self::rlp_length_for(header, body)
229 }
230
231 fn into_ethereum_block(self) -> Self {
232 self
233 }
234}
235
236#[cfg(any(test, feature = "test-utils"))]
240pub trait TestBlock: Block<Header: crate::test_utils::TestHeader> {
241 fn body_mut(&mut self) -> &mut Self::Body;
243
244 fn header_mut(&mut self) -> &mut Self::Header;
246
247 fn set_header(&mut self, header: Self::Header);
249
250 fn set_parent_hash(&mut self, hash: alloy_primitives::BlockHash) {
252 crate::header::test_utils::TestHeader::set_parent_hash(self.header_mut(), hash);
253 }
254
255 fn set_block_number(&mut self, number: alloy_primitives::BlockNumber) {
257 crate::header::test_utils::TestHeader::set_block_number(self.header_mut(), number);
258 }
259
260 fn set_state_root(&mut self, state_root: alloy_primitives::B256) {
262 crate::header::test_utils::TestHeader::set_state_root(self.header_mut(), state_root);
263 }
264
265 fn set_difficulty(&mut self, difficulty: alloy_primitives::U256) {
267 crate::header::test_utils::TestHeader::set_difficulty(self.header_mut(), difficulty);
268 }
269}
270
271#[cfg(any(test, feature = "test-utils"))]
272impl<T, H> TestBlock for alloy_consensus::Block<T, H>
273where
274 T: SignedTransaction,
275 H: crate::test_utils::TestHeader,
276{
277 fn body_mut(&mut self) -> &mut Self::Body {
278 &mut self.body
279 }
280
281 fn header_mut(&mut self) -> &mut Self::Header {
282 &mut self.header
283 }
284
285 fn set_header(&mut self, header: Self::Header) {
286 self.header = header
287 }
288}