reth_primitives_traits/block/
mod.rs1pub(crate) mod sealed;
26pub use sealed::SealedBlock;
27
28pub(crate) mod recovered;
29pub use recovered::RecoveredBlock;
30
31pub mod body;
32pub mod error;
33pub mod header;
34
35use alloc::{fmt, vec::Vec};
36use alloy_primitives::{Address, B256};
37use alloy_rlp::{Decodable, Encodable};
38
39use crate::{
40 block::error::BlockRecoveryError, transaction::signed::RecoveryError, BlockBody, BlockHeader,
41 FullBlockBody, FullBlockHeader, InMemorySize, MaybeSerde, SealedHeader, SignedTransaction,
42};
43
44#[cfg(feature = "serde-bincode-compat")]
46pub mod serde_bincode_compat {
47 pub use super::{
48 recovered::serde_bincode_compat::RecoveredBlock, sealed::serde_bincode_compat::SealedBlock,
49 };
50}
51
52pub trait FullBlock:
54 Block<Header: FullBlockHeader, Body: FullBlockBody> + alloy_rlp::Encodable + alloy_rlp::Decodable
55{
56}
57
58impl<T> FullBlock for T where
59 T: Block<Header: FullBlockHeader, Body: FullBlockBody>
60 + alloy_rlp::Encodable
61 + alloy_rlp::Decodable
62{
63}
64
65pub type BlockTx<B> = <<B as Block>::Body as BlockBody>::Transaction;
67
68pub trait Block:
74 Send
75 + Sync
76 + Unpin
77 + Clone
78 + Default
79 + fmt::Debug
80 + PartialEq
81 + Eq
82 + InMemorySize
83 + MaybeSerde
84 + Encodable
85 + Decodable
86{
87 type Header: BlockHeader;
89
90 type Body: BlockBody<OmmerHeader = Self::Header>;
93
94 fn new(header: Self::Header, body: Self::Body) -> Self;
96
97 fn new_sealed(header: SealedHeader<Self::Header>, body: Self::Body) -> SealedBlock<Self> {
99 SealedBlock::from_sealed_parts(header, body)
100 }
101
102 fn seal_unchecked(self, hash: B256) -> SealedBlock<Self> {
106 SealedBlock::new_unchecked(self, hash)
107 }
108
109 fn seal(self) -> SealedBlock<Self> {
111 SealedBlock::new_unhashed(self)
112 }
113
114 fn seal_slow(self) -> SealedBlock<Self> {
116 SealedBlock::seal_slow(self)
117 }
118
119 fn header(&self) -> &Self::Header;
121
122 fn body(&self) -> &Self::Body;
124
125 fn split(self) -> (Self::Header, Self::Body);
127
128 fn split_ref(&self) -> (&Self::Header, &Self::Body) {
130 (self.header(), self.body())
131 }
132
133 fn into_header(self) -> Self::Header {
135 self.split().0
136 }
137
138 fn into_body(self) -> Self::Body {
140 self.split().1
141 }
142
143 fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize;
145
146 fn recover_signers(&self) -> Result<Vec<Address>, RecoveryError>
148 where
149 <Self::Body as BlockBody>::Transaction: SignedTransaction,
150 {
151 self.body().recover_signers()
152 }
153
154 fn try_into_recovered_unchecked(
161 self,
162 senders: Vec<Address>,
163 ) -> Result<RecoveredBlock<Self>, BlockRecoveryError<Self>>
164 where
165 <Self::Body as BlockBody>::Transaction: SignedTransaction,
166 {
167 let senders = if self.body().transactions().len() == senders.len() {
168 senders
169 } else {
170 let Ok(senders) = self.body().recover_signers_unchecked() else {
172 return Err(BlockRecoveryError::new(self))
173 };
174 senders
175 };
176 Ok(RecoveredBlock::new_unhashed(self, senders))
177 }
178
179 fn into_recovered_with_signers(self, signers: Vec<Address>) -> RecoveredBlock<Self>
183 where
184 <Self::Body as BlockBody>::Transaction: SignedTransaction,
185 {
186 RecoveredBlock::new_unhashed(self, signers)
187 }
188
189 fn try_into_recovered(self) -> Result<RecoveredBlock<Self>, BlockRecoveryError<Self>>
194 where
195 <Self::Body as BlockBody>::Transaction: SignedTransaction,
196 {
197 let Ok(signers) = self.body().recover_signers() else {
198 return Err(BlockRecoveryError::new(self))
199 };
200 Ok(RecoveredBlock::new_unhashed(self, signers))
201 }
202
203 fn into_ethereum_block(
218 self,
219 ) -> alloy_consensus::Block<<Self::Body as BlockBody>::Transaction, Self::Header> {
220 let (header, body) = self.split();
221 alloy_consensus::Block::new(header, body.into_ethereum_body())
222 }
223}
224
225impl<T, H> Block for alloy_consensus::Block<T, H>
226where
227 T: SignedTransaction,
228 H: BlockHeader,
229{
230 type Header = H;
231 type Body = alloy_consensus::BlockBody<T, H>;
232
233 fn new(header: Self::Header, body: Self::Body) -> Self {
234 Self { header, body }
235 }
236
237 fn header(&self) -> &Self::Header {
238 &self.header
239 }
240
241 fn body(&self) -> &Self::Body {
242 &self.body
243 }
244
245 fn split(self) -> (Self::Header, Self::Body) {
246 (self.header, self.body)
247 }
248
249 fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize {
250 Self::rlp_length_for(header, body)
251 }
252
253 fn into_ethereum_block(self) -> Self {
254 self
255 }
256}
257
258#[cfg(any(test, feature = "test-utils"))]
262pub trait TestBlock: Block<Header: crate::test_utils::TestHeader> {
263 fn body_mut(&mut self) -> &mut Self::Body;
265
266 fn header_mut(&mut self) -> &mut Self::Header;
268
269 fn set_header(&mut self, header: Self::Header);
271
272 fn set_parent_hash(&mut self, hash: alloy_primitives::BlockHash) {
274 crate::header::test_utils::TestHeader::set_parent_hash(self.header_mut(), hash);
275 }
276
277 fn set_block_number(&mut self, number: alloy_primitives::BlockNumber) {
279 crate::header::test_utils::TestHeader::set_block_number(self.header_mut(), number);
280 }
281
282 fn set_state_root(&mut self, state_root: alloy_primitives::B256) {
284 crate::header::test_utils::TestHeader::set_state_root(self.header_mut(), state_root);
285 }
286
287 fn set_difficulty(&mut self, difficulty: alloy_primitives::U256) {
289 crate::header::test_utils::TestHeader::set_difficulty(self.header_mut(), difficulty);
290 }
291}
292
293#[cfg(any(test, feature = "test-utils"))]
294impl<T, H> TestBlock for alloy_consensus::Block<T, H>
295where
296 T: SignedTransaction,
297 H: crate::test_utils::TestHeader,
298{
299 fn body_mut(&mut self) -> &mut Self::Body {
300 &mut self.body
301 }
302
303 fn header_mut(&mut self) -> &mut Self::Header {
304 &mut self.header
305 }
306
307 fn set_header(&mut self, header: Self::Header) {
308 self.header = header
309 }
310}