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: Block<Header: FullBlockHeader, Body: FullBlockBody> {}
54
55impl<T> FullBlock for T where T: Block<Header: FullBlockHeader, Body: FullBlockBody> {}
56
57pub type BlockTx<B> = <<B as Block>::Body as BlockBody>::Transaction;
59
60pub trait Block:
66 Send
67 + Sync
68 + Unpin
69 + Clone
70 + Default
71 + fmt::Debug
72 + PartialEq
73 + Eq
74 + InMemorySize
75 + MaybeSerde
76 + Encodable
77 + Decodable
78{
79 type Header: BlockHeader;
81
82 type Body: BlockBody<OmmerHeader = Self::Header>;
85
86 fn new(header: Self::Header, body: Self::Body) -> Self;
88
89 fn new_sealed(header: SealedHeader<Self::Header>, body: Self::Body) -> SealedBlock<Self> {
91 SealedBlock::from_sealed_parts(header, body)
92 }
93
94 fn seal_unchecked(self, hash: B256) -> SealedBlock<Self> {
98 SealedBlock::new_unchecked(self, hash)
99 }
100
101 fn seal(self) -> SealedBlock<Self> {
103 SealedBlock::new_unhashed(self)
104 }
105
106 fn seal_slow(self) -> SealedBlock<Self> {
108 SealedBlock::seal_slow(self)
109 }
110
111 fn header(&self) -> &Self::Header;
113
114 fn body(&self) -> &Self::Body;
116
117 fn split(self) -> (Self::Header, Self::Body);
119
120 fn split_ref(&self) -> (&Self::Header, &Self::Body) {
122 (self.header(), self.body())
123 }
124
125 fn into_header(self) -> Self::Header {
127 self.split().0
128 }
129
130 fn into_body(self) -> Self::Body {
132 self.split().1
133 }
134
135 fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize;
137
138 fn recover_signers(&self) -> Result<Vec<Address>, RecoveryError>
140 where
141 <Self::Body as BlockBody>::Transaction: SignedTransaction,
142 {
143 self.body().recover_signers()
144 }
145
146 fn try_into_recovered_unchecked(
153 self,
154 senders: Vec<Address>,
155 ) -> Result<RecoveredBlock<Self>, BlockRecoveryError<Self>>
156 where
157 <Self::Body as BlockBody>::Transaction: SignedTransaction,
158 {
159 let senders = if self.body().transactions().len() == senders.len() {
160 senders
161 } else {
162 let Ok(senders) = self.body().recover_signers_unchecked() else {
164 return Err(BlockRecoveryError::new(self))
165 };
166 senders
167 };
168 Ok(RecoveredBlock::new_unhashed(self, senders))
169 }
170
171 fn into_recovered_with_signers(self, signers: Vec<Address>) -> RecoveredBlock<Self>
175 where
176 <Self::Body as BlockBody>::Transaction: SignedTransaction,
177 {
178 RecoveredBlock::new_unhashed(self, signers)
179 }
180
181 fn try_into_recovered(self) -> Result<RecoveredBlock<Self>, BlockRecoveryError<Self>> {
186 let Ok(signers) = self.body().recover_signers() else {
187 return Err(BlockRecoveryError::new(self))
188 };
189 Ok(RecoveredBlock::new_unhashed(self, signers))
190 }
191
192 fn into_ethereum_block(
207 self,
208 ) -> alloy_consensus::Block<<Self::Body as BlockBody>::Transaction, Self::Header> {
209 let (header, body) = self.split();
210 alloy_consensus::Block::new(header, body.into_ethereum_body())
211 }
212}
213
214impl<T, H> Block for alloy_consensus::Block<T, H>
215where
216 T: SignedTransaction,
217 H: BlockHeader,
218{
219 type Header = H;
220 type Body = alloy_consensus::BlockBody<T, H>;
221
222 fn new(header: Self::Header, body: Self::Body) -> Self {
223 Self { header, body }
224 }
225
226 fn header(&self) -> &Self::Header {
227 &self.header
228 }
229
230 fn body(&self) -> &Self::Body {
231 &self.body
232 }
233
234 fn split(self) -> (Self::Header, Self::Body) {
235 (self.header, self.body)
236 }
237
238 fn rlp_length(header: &Self::Header, body: &Self::Body) -> usize {
239 Self::rlp_length_for(header, body)
240 }
241
242 fn into_ethereum_block(self) -> Self {
243 self
244 }
245}
246
247#[cfg(any(test, feature = "test-utils"))]
251pub trait TestBlock: Block<Header: crate::test_utils::TestHeader> {
252 fn body_mut(&mut self) -> &mut Self::Body;
254
255 fn header_mut(&mut self) -> &mut Self::Header;
257
258 fn set_header(&mut self, header: Self::Header);
260
261 fn set_parent_hash(&mut self, hash: alloy_primitives::BlockHash) {
263 crate::header::test_utils::TestHeader::set_parent_hash(self.header_mut(), hash);
264 }
265
266 fn set_block_number(&mut self, number: alloy_primitives::BlockNumber) {
268 crate::header::test_utils::TestHeader::set_block_number(self.header_mut(), number);
269 }
270
271 fn set_state_root(&mut self, state_root: alloy_primitives::B256) {
273 crate::header::test_utils::TestHeader::set_state_root(self.header_mut(), state_root);
274 }
275
276 fn set_difficulty(&mut self, difficulty: alloy_primitives::U256) {
278 crate::header::test_utils::TestHeader::set_difficulty(self.header_mut(), difficulty);
279 }
280}
281
282#[cfg(any(test, feature = "test-utils"))]
283impl<T, H> TestBlock for alloy_consensus::Block<T, H>
284where
285 T: SignedTransaction,
286 H: crate::test_utils::TestHeader,
287{
288 fn body_mut(&mut self) -> &mut Self::Body {
289 &mut self.body
290 }
291
292 fn header_mut(&mut self) -> &mut Self::Header {
293 &mut self.header
294 }
295
296 fn set_header(&mut self, header: Self::Header) {
297 self.header = header
298 }
299}