1use crate::block::body::owned::{
4 GenericOwnedBlockBody, OwnedBeaconChainBody, OwnedBeaconChainBodyError,
5 OwnedIntermediateShardBody, OwnedIntermediateShardBodyError, OwnedLeafShardBlockBodyBuilder,
6 OwnedLeafShardBody, OwnedLeafShardBodyError, WritableBodyTransaction,
7};
8use crate::block::body::{BlockBody, IntermediateShardBlockInfo, LeafShardBlockInfo};
9use crate::block::header::owned::{
10 GenericOwnedBlockHeader, OwnedBeaconChainHeader, OwnedBeaconChainHeaderError,
11 OwnedBeaconChainHeaderUnsealed, OwnedIntermediateShardHeader,
12 OwnedIntermediateShardHeaderError, OwnedIntermediateShardHeaderUnsealed, OwnedLeafShardHeader,
13 OwnedLeafShardHeaderUnsealed,
14};
15use crate::block::header::{
16 BlockHeader, BlockHeaderBeaconChainInfo, BlockHeaderConsensusInfo,
17 BlockHeaderConsensusParameters, BlockHeaderPrefix, BlockHeaderResult, BlockHeaderSeal,
18};
19use crate::block::{BeaconChainBlock, Block, GenericBlock, IntermediateShardBlock, LeafShardBlock};
20use crate::hashes::Blake3Hash;
21use crate::pot::PotCheckpoints;
22use crate::segments::SegmentRoot;
23use crate::shard::ShardKind;
24use ab_aligned_buffer::SharedAlignedBuffer;
25use alloc::vec::Vec;
26use core::fmt;
27use core::iter::TrustedLen;
28use derive_more::From;
29
30pub trait GenericOwnedBlock: Clone + fmt::Debug + 'static {
32 type Header: GenericOwnedBlockHeader;
34 type Body: GenericOwnedBlockBody;
36 type Block<'a>: GenericBlock<'a>
38 where
39 Self: 'a;
40
41 fn header(&self) -> &Self::Header;
43
44 fn body(&self) -> &Self::Body;
46
47 fn block(&self) -> Self::Block<'_>;
49}
50
51#[derive(Debug, Clone)]
56#[non_exhaustive]
58pub struct OwnedBeaconChainBlock {
59 pub header: OwnedBeaconChainHeader,
61 pub body: OwnedBeaconChainBody,
63}
64
65impl GenericOwnedBlock for OwnedBeaconChainBlock {
66 type Header = OwnedBeaconChainHeader;
67 type Body = OwnedBeaconChainBody;
68 type Block<'a> = BeaconChainBlock<'a>;
69
70 #[inline(always)]
71 fn header(&self) -> &Self::Header {
72 &self.header
73 }
74
75 #[inline(always)]
76 fn body(&self) -> &Self::Body {
77 &self.body
78 }
79
80 #[inline(always)]
81 fn block(&self) -> Self::Block<'_> {
82 self.block()
83 }
84}
85
86impl OwnedBeaconChainBlock {
87 pub fn init<'a, OSR, ISB>(
89 own_segment_roots: OSR,
90 intermediate_shard_blocks: ISB,
91 pot_checkpoints: &[PotCheckpoints],
92 ) -> Result<OwnedBeaconChainBlockBuilder, OwnedBeaconChainBodyError>
93 where
94 OSR: TrustedLen<Item = SegmentRoot>,
95 ISB: TrustedLen<Item = IntermediateShardBlockInfo<'a>> + Clone + 'a,
96 {
97 Ok(OwnedBeaconChainBlockBuilder {
98 body: OwnedBeaconChainBody::new(
99 own_segment_roots,
100 intermediate_shard_blocks,
101 pot_checkpoints,
102 )?,
103 })
104 }
105
106 #[inline]
108 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
109 let block = Self {
110 header: OwnedBeaconChainHeader::from_buffer(header).ok()?,
111 body: OwnedBeaconChainBody::from_buffer(body).ok()?,
112 };
113
114 if !block.block().is_internally_consistent() {
116 return None;
117 }
118
119 Some(block)
120 }
121
122 pub fn block(&self) -> BeaconChainBlock<'_> {
124 BeaconChainBlock {
125 header: self.header.header().clone(),
126 body: *self.body.body(),
127 }
128 }
129}
130
131#[derive(Debug, Clone)]
133pub struct OwnedBeaconChainBlockBuilder {
134 body: OwnedBeaconChainBody,
135}
136
137impl OwnedBeaconChainBlockBuilder {
138 pub fn with_header(
140 self,
141 prefix: &BlockHeaderPrefix,
142 state_root: Blake3Hash,
143 consensus_info: &BlockHeaderConsensusInfo,
144 consensus_parameters: BlockHeaderConsensusParameters<'_>,
145 ) -> Result<OwnedBeaconChainBlockUnsealed, OwnedBeaconChainHeaderError> {
146 let body = self.body;
147 let header = OwnedBeaconChainHeader::from_parts(
148 prefix,
149 &BlockHeaderResult {
150 body_root: body.body().root(),
151 state_root,
152 },
153 consensus_info,
154 &body
155 .body()
156 .intermediate_shard_blocks()
157 .iter()
158 .map(|block| *block.header.root())
159 .collect::<Vec<_>>(),
160 consensus_parameters,
161 )?;
162
163 Ok(OwnedBeaconChainBlockUnsealed { body, header })
164 }
165}
166
167#[derive(Debug, Clone)]
169pub struct OwnedBeaconChainBlockUnsealed {
170 body: OwnedBeaconChainBody,
171 header: OwnedBeaconChainHeaderUnsealed,
172}
173
174impl OwnedBeaconChainBlockUnsealed {
175 #[inline(always)]
177 pub fn pre_seal_hash(&self) -> Blake3Hash {
178 self.header.pre_seal_hash()
179 }
180
181 pub fn with_seal(self, seal: BlockHeaderSeal<'_>) -> OwnedBeaconChainBlock {
183 let header = self.header.with_seal(seal);
184
185 OwnedBeaconChainBlock {
186 header,
187 body: self.body,
188 }
189 }
190}
191
192#[derive(Debug, thiserror::Error)]
194pub enum OwnedIntermediateShardBlockError {
195 #[error("Intermediate shard block header error: {0}")]
197 Header(#[from] OwnedIntermediateShardHeaderError),
198 #[error("Intermediate shard block body error: {0}")]
200 Body(#[from] OwnedIntermediateShardBodyError),
201}
202
203#[derive(Debug, Clone)]
208#[non_exhaustive]
210pub struct OwnedIntermediateShardBlock {
211 pub header: OwnedIntermediateShardHeader,
213 pub body: OwnedIntermediateShardBody,
215}
216
217impl GenericOwnedBlock for OwnedIntermediateShardBlock {
218 type Header = OwnedIntermediateShardHeader;
219 type Body = OwnedIntermediateShardBody;
220 type Block<'a> = IntermediateShardBlock<'a>;
221
222 #[inline(always)]
223 fn header(&self) -> &Self::Header {
224 &self.header
225 }
226
227 #[inline(always)]
228 fn body(&self) -> &Self::Body {
229 &self.body
230 }
231
232 #[inline(always)]
233 fn block(&self) -> Self::Block<'_> {
234 self.block()
235 }
236}
237
238impl OwnedIntermediateShardBlock {
239 pub fn init<'a, OSR, LSB>(
241 own_segment_roots: OSR,
242 leaf_shard_blocks: LSB,
243 ) -> Result<OwnedIntermediateShardBlockBuilder, OwnedIntermediateShardBodyError>
244 where
245 OSR: TrustedLen<Item = SegmentRoot>,
246 LSB: TrustedLen<Item = LeafShardBlockInfo<'a>> + Clone + 'a,
247 {
248 Ok(OwnedIntermediateShardBlockBuilder {
249 body: OwnedIntermediateShardBody::new(own_segment_roots, leaf_shard_blocks)?,
250 })
251 }
252
253 #[inline]
255 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
256 let block = Self {
257 header: OwnedIntermediateShardHeader::from_buffer(header).ok()?,
258 body: OwnedIntermediateShardBody::from_buffer(body).ok()?,
259 };
260
261 if !block.block().is_internally_consistent() {
263 return None;
264 }
265
266 Some(block)
267 }
268
269 pub fn block(&self) -> IntermediateShardBlock<'_> {
271 IntermediateShardBlock {
272 header: self.header.header().clone(),
273 body: *self.body.body(),
274 }
275 }
276}
277
278#[derive(Debug, Clone)]
280pub struct OwnedIntermediateShardBlockBuilder {
281 body: OwnedIntermediateShardBody,
282}
283
284impl OwnedIntermediateShardBlockBuilder {
285 pub fn with_header(
287 self,
288 prefix: &BlockHeaderPrefix,
289 state_root: Blake3Hash,
290 consensus_info: &BlockHeaderConsensusInfo,
291 beacon_chain_info: &BlockHeaderBeaconChainInfo,
292 ) -> Result<OwnedIntermediateShardBlockUnsealed, OwnedIntermediateShardHeaderError> {
293 let body = self.body;
294 let header = OwnedIntermediateShardHeader::from_parts(
295 prefix,
296 &BlockHeaderResult {
297 body_root: body.body().root(),
298 state_root,
299 },
300 consensus_info,
301 beacon_chain_info,
302 &body
303 .body()
304 .leaf_shard_blocks()
305 .iter()
306 .map(|block| *block.header.root())
307 .collect::<Vec<_>>(),
308 )?;
309
310 Ok(OwnedIntermediateShardBlockUnsealed { body, header })
311 }
312}
313
314#[derive(Debug, Clone)]
316pub struct OwnedIntermediateShardBlockUnsealed {
317 body: OwnedIntermediateShardBody,
318 header: OwnedIntermediateShardHeaderUnsealed,
319}
320
321impl OwnedIntermediateShardBlockUnsealed {
322 #[inline(always)]
324 pub fn pre_seal_hash(&self) -> Blake3Hash {
325 self.header.pre_seal_hash()
326 }
327
328 pub fn with_seal(self, seal: BlockHeaderSeal<'_>) -> OwnedIntermediateShardBlock {
330 let header = self.header.with_seal(seal);
331
332 OwnedIntermediateShardBlock {
333 header,
334 body: self.body,
335 }
336 }
337}
338
339#[derive(Debug, Clone)]
344#[non_exhaustive]
346pub struct OwnedLeafShardBlock {
347 pub header: OwnedLeafShardHeader,
349 pub body: OwnedLeafShardBody,
351}
352
353impl GenericOwnedBlock for OwnedLeafShardBlock {
354 type Header = OwnedLeafShardHeader;
355 type Body = OwnedLeafShardBody;
356 type Block<'a> = LeafShardBlock<'a>;
357
358 #[inline(always)]
359 fn header(&self) -> &Self::Header {
360 &self.header
361 }
362
363 #[inline(always)]
364 fn body(&self) -> &Self::Body {
365 &self.body
366 }
367
368 #[inline(always)]
369 fn block(&self) -> Self::Block<'_> {
370 self.block()
371 }
372}
373
374impl OwnedLeafShardBlock {
375 pub fn init<OSR>(
377 own_segment_roots: OSR,
378 ) -> Result<OwnedLeafShardBlockBuilder, OwnedLeafShardBodyError>
379 where
380 OSR: TrustedLen<Item = SegmentRoot>,
381 {
382 Ok(OwnedLeafShardBlockBuilder {
383 body_builder: OwnedLeafShardBody::init(own_segment_roots)?,
384 })
385 }
386
387 #[inline]
389 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
390 let block = Self {
391 header: OwnedLeafShardHeader::from_buffer(header).ok()?,
392 body: OwnedLeafShardBody::from_buffer(body).ok()?,
393 };
394
395 if !block.block().is_internally_consistent() {
397 return None;
398 }
399
400 Some(block)
401 }
402
403 pub fn block(&self) -> LeafShardBlock<'_> {
405 LeafShardBlock {
406 header: self.header.header().clone(),
407 body: *self.body.body(),
408 }
409 }
410}
411
412#[derive(Debug, Clone)]
414pub struct OwnedLeafShardBlockBuilder {
415 body_builder: OwnedLeafShardBlockBodyBuilder,
416}
417
418impl OwnedLeafShardBlockBuilder {
419 #[inline(always)]
421 pub fn add_transaction<T>(&mut self, transaction: T) -> Result<(), OwnedLeafShardBodyError>
422 where
423 T: WritableBodyTransaction,
424 {
425 self.body_builder.add_transaction(transaction)?;
426
427 Ok(())
428 }
429
430 pub fn with_header(
432 self,
433 prefix: &BlockHeaderPrefix,
434 state_root: Blake3Hash,
435 consensus_info: &BlockHeaderConsensusInfo,
436 beacon_chain_info: &BlockHeaderBeaconChainInfo,
437 ) -> OwnedLeafShardBlockUnsealed {
438 let body = self.body_builder.finish();
439 let header = OwnedLeafShardHeader::from_parts(
440 prefix,
441 &BlockHeaderResult {
442 body_root: body.body().root(),
443 state_root,
444 },
445 consensus_info,
446 beacon_chain_info,
447 );
448 OwnedLeafShardBlockUnsealed { body, header }
449 }
450}
451
452#[derive(Debug, Clone)]
454pub struct OwnedLeafShardBlockUnsealed {
455 body: OwnedLeafShardBody,
456 header: OwnedLeafShardHeaderUnsealed,
457}
458
459impl OwnedLeafShardBlockUnsealed {
460 #[inline(always)]
462 pub fn pre_seal_hash(&self) -> Blake3Hash {
463 self.header.pre_seal_hash()
464 }
465
466 pub fn with_seal(self, seal: BlockHeaderSeal<'_>) -> OwnedLeafShardBlock {
468 let header = self.header.with_seal(seal);
469
470 OwnedLeafShardBlock {
471 header,
472 body: self.body,
473 }
474 }
475}
476
477#[derive(Debug, Clone, From)]
483pub enum OwnedBlock {
484 BeaconChain(OwnedBeaconChainBlock),
486 IntermediateShard(OwnedIntermediateShardBlock),
488 LeafShard(OwnedLeafShardBlock),
490}
491
492impl OwnedBlock {
493 #[inline(always)]
495 pub fn header(&self) -> BlockHeader<'_> {
496 match self {
497 Self::BeaconChain(block) => BlockHeader::BeaconChain(block.header.header().clone()),
498 Self::IntermediateShard(block) => {
499 BlockHeader::IntermediateShard(block.header.header().clone())
500 }
501 Self::LeafShard(block) => BlockHeader::LeafShard(block.header.header().clone()),
502 }
503 }
504
505 #[inline(always)]
507 pub fn body(&self) -> BlockBody<'_> {
508 match self {
509 Self::BeaconChain(block) => BlockBody::BeaconChain(*block.body.body()),
510 Self::IntermediateShard(block) => BlockBody::IntermediateShard(*block.body.body()),
511 Self::LeafShard(block) => BlockBody::LeafShard(*block.body.body()),
512 }
513 }
514
515 #[inline]
519 pub fn from_buffers(
520 header: SharedAlignedBuffer,
521 body: SharedAlignedBuffer,
522 shard_kind: ShardKind,
523 ) -> Option<Self> {
524 Some(match shard_kind {
525 ShardKind::BeaconChain => {
526 Self::BeaconChain(OwnedBeaconChainBlock::from_buffers(header, body)?)
527 }
528 ShardKind::IntermediateShard => {
529 Self::IntermediateShard(OwnedIntermediateShardBlock::from_buffers(header, body)?)
530 }
531 ShardKind::LeafShard => {
532 Self::LeafShard(OwnedLeafShardBlock::from_buffers(header, body)?)
533 }
534 ShardKind::Phantom | ShardKind::Invalid => {
535 return None;
537 }
538 })
539 }
540
541 #[inline(always)]
543 pub fn block(&self) -> Block<'_> {
544 match self {
545 Self::BeaconChain(block) => Block::BeaconChain(block.block()),
546 Self::IntermediateShard(block) => Block::IntermediateShard(block.block()),
547 Self::LeafShard(block) => Block::LeafShard(block.block()),
548 }
549 }
550}