1use crate::block::body::owned::{
4 GenericOwnedBlockBody, OwnedBeaconChainBody, OwnedBeaconChainBodyError, OwnedBlockBody,
5 OwnedIntermediateShardBlockBodyBuilder, OwnedIntermediateShardBody,
6 OwnedIntermediateShardBodyError, OwnedLeafShardBlockBodyBuilder, OwnedLeafShardBody,
7 OwnedLeafShardBodyError, WritableBodyTransaction,
8};
9use crate::block::body::{BlockBody, IntermediateShardBlockInfo, LeafShardBlockInfo};
10use crate::block::header::owned::{
11 GenericOwnedBlockHeader, OwnedBeaconChainBlockHeaderUnsealed, OwnedBeaconChainHeader,
12 OwnedBeaconChainHeaderError, OwnedBlockHeader, OwnedIntermediateShardBlockHeaderUnsealed,
13 OwnedIntermediateShardHeader, OwnedIntermediateShardHeaderError,
14 OwnedLeafShardBlockHeaderUnsealed, OwnedLeafShardHeader,
15};
16use crate::block::header::{
17 BlockHeader, BlockHeaderBeaconChainInfo, BlockHeaderBeaconChainParameters,
18 BlockHeaderConsensusInfo, BlockHeaderPrefix, BlockHeaderResult, BlockHeaderSealRef,
19};
20use crate::block::{BeaconChainBlock, Block, GenericBlock, IntermediateShardBlock, LeafShardBlock};
21use crate::hashes::Blake3Hash;
22use crate::pot::PotCheckpoints;
23use crate::segments::SegmentRoot;
24use crate::shard::ShardKind;
25use ab_aligned_buffer::SharedAlignedBuffer;
26use alloc::vec::Vec;
27use core::iter::TrustedLen;
28use derive_more::From;
29
30pub trait GenericOwnedBlock {
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, thiserror::Error)]
53pub enum OwnedBeaconChainBlockError {
54 #[error("Beacon chain block header error: {0}")]
56 Header(#[from] OwnedBeaconChainHeaderError),
57 #[error("Beacon chain block body error: {0}")]
59 Body(#[from] OwnedBeaconChainBodyError),
60}
61
62#[derive(Debug, Clone)]
67pub struct OwnedBeaconChainBlock {
68 pub header: OwnedBeaconChainHeader,
70 pub body: OwnedBeaconChainBody,
72}
73
74impl GenericOwnedBlock for OwnedBeaconChainBlock {
75 type Header = OwnedBeaconChainHeader;
76 type Body = OwnedBeaconChainBody;
77 type Block<'a> = BeaconChainBlock<'a>;
78
79 #[inline(always)]
80 fn header(&self) -> Self::Header {
81 self.header.clone()
82 }
83
84 #[inline(always)]
85 fn body(&self) -> Self::Body {
86 self.body.clone()
87 }
88
89 #[inline(always)]
90 fn block(&self) -> Self::Block<'_> {
91 self.block()
92 }
93}
94
95impl OwnedBeaconChainBlock {
96 pub fn init<'a, ISB>(
98 own_segment_roots: &[SegmentRoot],
99 intermediate_shard_blocks: ISB,
100 pot_checkpoints: &[PotCheckpoints],
101 ) -> Result<OwnedBeaconChainBlockBuilder, OwnedBeaconChainBodyError>
102 where
103 ISB: TrustedLen<Item = IntermediateShardBlockInfo<'a>> + Clone + 'a,
104 {
105 Ok(OwnedBeaconChainBlockBuilder {
106 body: OwnedBeaconChainBody::init(
107 own_segment_roots,
108 intermediate_shard_blocks,
109 pot_checkpoints,
110 )?,
111 })
112 }
113
114 #[inline]
116 pub fn from_block(block: BeaconChainBlock<'_>) -> Result<Self, OwnedBeaconChainBlockError> {
117 Ok(Self {
118 header: OwnedBeaconChainHeader::from_header(block.header)?,
119 body: OwnedBeaconChainBody::from_body(block.body)?,
120 })
121 }
122
123 #[inline]
125 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
126 let block = Self {
127 header: OwnedBeaconChainHeader::from_buffer(header).ok()?,
128 body: OwnedBeaconChainBody::from_buffer(body).ok()?,
129 };
130
131 if !block.block().is_internally_consistent() {
133 return None;
134 }
135
136 Some(block)
137 }
138
139 pub fn block(&self) -> BeaconChainBlock<'_> {
141 BeaconChainBlock {
142 header: self.header.header(),
143 body: self.body.body(),
144 }
145 }
146}
147
148#[derive(Debug, Clone)]
150pub struct OwnedBeaconChainBlockBuilder {
151 body: OwnedBeaconChainBody,
152}
153
154impl OwnedBeaconChainBlockBuilder {
155 pub fn with_header(
157 self,
158 prefix: &BlockHeaderPrefix,
159 state_root: Blake3Hash,
160 consensus_info: &BlockHeaderConsensusInfo,
161 consensus_parameters: BlockHeaderBeaconChainParameters<'_>,
162 ) -> Result<OwnedBeaconChainBlockUnsealed, OwnedBeaconChainHeaderError> {
163 let body = self.body;
164 let header = OwnedBeaconChainHeader::from_parts(
165 prefix,
166 &BlockHeaderResult {
167 body_root: body.body().root(),
168 state_root,
169 },
170 consensus_info,
171 &body
172 .body()
173 .intermediate_shard_blocks
174 .iter()
175 .map(|block| block.header.root())
176 .collect::<Vec<_>>(),
177 consensus_parameters,
178 )?;
179
180 Ok(OwnedBeaconChainBlockUnsealed { body, header })
181 }
182}
183
184#[derive(Debug, Clone)]
186pub struct OwnedBeaconChainBlockUnsealed {
187 body: OwnedBeaconChainBody,
188 header: OwnedBeaconChainBlockHeaderUnsealed,
189}
190
191impl OwnedBeaconChainBlockUnsealed {
192 #[inline(always)]
194 pub fn pre_seal_hash(&self) -> Blake3Hash {
195 self.header.pre_seal_hash()
196 }
197
198 pub fn with_seal(self, seal: BlockHeaderSealRef<'_>) -> OwnedBeaconChainBlock {
200 let header = self.header.with_seal(seal);
201
202 OwnedBeaconChainBlock {
203 header,
204 body: self.body,
205 }
206 }
207}
208
209#[derive(Debug, thiserror::Error)]
211pub enum OwnedIntermediateShardBlockError {
212 #[error("Intermediate shard block header error: {0}")]
214 Header(#[from] OwnedIntermediateShardHeaderError),
215 #[error("Intermediate shard block body error: {0}")]
217 Body(#[from] OwnedIntermediateShardBodyError),
218}
219
220#[derive(Debug, Clone)]
225pub struct OwnedIntermediateShardBlock {
226 pub header: OwnedIntermediateShardHeader,
228 pub body: OwnedIntermediateShardBody,
230}
231
232impl GenericOwnedBlock for OwnedIntermediateShardBlock {
233 type Header = OwnedIntermediateShardHeader;
234 type Body = OwnedIntermediateShardBody;
235 type Block<'a> = IntermediateShardBlock<'a>;
236
237 #[inline(always)]
238 fn header(&self) -> Self::Header {
239 self.header.clone()
240 }
241
242 #[inline(always)]
243 fn body(&self) -> Self::Body {
244 self.body.clone()
245 }
246
247 #[inline(always)]
248 fn block(&self) -> Self::Block<'_> {
249 self.block()
250 }
251}
252
253impl OwnedIntermediateShardBlock {
254 pub fn init<'a, LSB>(
256 own_segment_roots: &[SegmentRoot],
257 leaf_shard_blocks: LSB,
258 ) -> Result<OwnedIntermediateShardBlockBuilder, OwnedIntermediateShardBodyError>
259 where
260 LSB: TrustedLen<Item = LeafShardBlockInfo<'a>> + Clone + 'a,
261 {
262 Ok(OwnedIntermediateShardBlockBuilder {
263 body_builder: OwnedIntermediateShardBody::init(own_segment_roots, leaf_shard_blocks)?,
264 })
265 }
266
267 #[inline]
269 pub fn from_block(
270 block: IntermediateShardBlock<'_>,
271 ) -> Result<Self, OwnedIntermediateShardBlockError> {
272 Ok(Self {
273 header: OwnedIntermediateShardHeader::from_header(block.header)?,
274 body: OwnedIntermediateShardBody::from_body(block.body)?,
275 })
276 }
277
278 #[inline]
280 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
281 let block = Self {
282 header: OwnedIntermediateShardHeader::from_buffer(header).ok()?,
283 body: OwnedIntermediateShardBody::from_buffer(body).ok()?,
284 };
285
286 if !block.block().is_internally_consistent() {
288 return None;
289 }
290
291 Some(block)
292 }
293
294 pub fn block(&self) -> IntermediateShardBlock<'_> {
296 IntermediateShardBlock {
297 header: self.header.header(),
298 body: self.body.body(),
299 }
300 }
301}
302
303#[derive(Debug, Clone)]
305pub struct OwnedIntermediateShardBlockBuilder {
306 body_builder: OwnedIntermediateShardBlockBodyBuilder,
307}
308
309impl OwnedIntermediateShardBlockBuilder {
310 #[inline(always)]
312 pub fn add_transaction<T>(
313 &mut self,
314 transaction: T,
315 ) -> Result<(), OwnedIntermediateShardBodyError>
316 where
317 T: WritableBodyTransaction,
318 {
319 self.body_builder.add_transaction(transaction)?;
320
321 Ok(())
322 }
323
324 pub fn with_header(
326 self,
327 prefix: &BlockHeaderPrefix,
328 state_root: Blake3Hash,
329 consensus_info: &BlockHeaderConsensusInfo,
330 beacon_chain_info: &BlockHeaderBeaconChainInfo,
331 ) -> Result<OwnedIntermediateShardBlockUnsealed, OwnedIntermediateShardHeaderError> {
332 let body = self.body_builder.finish();
333 let header = OwnedIntermediateShardHeader::from_parts(
334 prefix,
335 &BlockHeaderResult {
336 body_root: body.body().root(),
337 state_root,
338 },
339 consensus_info,
340 beacon_chain_info,
341 &body
342 .body()
343 .leaf_shard_blocks
344 .iter()
345 .map(|block| block.header.root())
346 .collect::<Vec<_>>(),
347 )?;
348
349 Ok(OwnedIntermediateShardBlockUnsealed { body, header })
350 }
351}
352
353#[derive(Debug, Clone)]
355pub struct OwnedIntermediateShardBlockUnsealed {
356 body: OwnedIntermediateShardBody,
357 header: OwnedIntermediateShardBlockHeaderUnsealed,
358}
359
360impl OwnedIntermediateShardBlockUnsealed {
361 #[inline(always)]
363 pub fn pre_seal_hash(&self) -> Blake3Hash {
364 self.header.pre_seal_hash()
365 }
366
367 pub fn with_seal(self, seal: BlockHeaderSealRef<'_>) -> OwnedIntermediateShardBlock {
369 let header = self.header.with_seal(seal);
370
371 OwnedIntermediateShardBlock {
372 header,
373 body: self.body,
374 }
375 }
376}
377
378#[derive(Debug, thiserror::Error)]
380pub enum OwnedLeafShardBlockError {
381 #[error("Leaf shard block body error: {0}")]
383 Body(#[from] OwnedLeafShardBodyError),
384}
385
386#[derive(Debug, Clone)]
391pub struct OwnedLeafShardBlock {
392 pub header: OwnedLeafShardHeader,
394 pub body: OwnedLeafShardBody,
396}
397
398impl GenericOwnedBlock for OwnedLeafShardBlock {
399 type Header = OwnedLeafShardHeader;
400 type Body = OwnedLeafShardBody;
401 type Block<'a> = LeafShardBlock<'a>;
402
403 #[inline(always)]
404 fn header(&self) -> Self::Header {
405 self.header.clone()
406 }
407
408 #[inline(always)]
409 fn body(&self) -> Self::Body {
410 self.body.clone()
411 }
412
413 #[inline(always)]
414 fn block(&self) -> Self::Block<'_> {
415 self.block()
416 }
417}
418
419impl OwnedLeafShardBlock {
420 pub fn init(
422 own_segment_roots: &[SegmentRoot],
423 ) -> Result<OwnedLeafShardBlockBuilder, OwnedLeafShardBodyError> {
424 Ok(OwnedLeafShardBlockBuilder {
425 body_builder: OwnedLeafShardBody::init(own_segment_roots)?,
426 })
427 }
428
429 #[inline]
431 pub fn from_block(block: LeafShardBlock<'_>) -> Result<Self, OwnedLeafShardBlockError> {
432 Ok(Self {
433 header: OwnedLeafShardHeader::from_header(block.header),
434 body: OwnedLeafShardBody::from_body(block.body)?,
435 })
436 }
437
438 #[inline]
440 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
441 let block = Self {
442 header: OwnedLeafShardHeader::from_buffer(header).ok()?,
443 body: OwnedLeafShardBody::from_buffer(body).ok()?,
444 };
445
446 if !block.block().is_internally_consistent() {
448 return None;
449 }
450
451 Some(block)
452 }
453
454 pub fn block(&self) -> LeafShardBlock<'_> {
456 LeafShardBlock {
457 header: self.header.header(),
458 body: self.body.body(),
459 }
460 }
461}
462
463#[derive(Debug, Clone)]
465pub struct OwnedLeafShardBlockBuilder {
466 body_builder: OwnedLeafShardBlockBodyBuilder,
467}
468
469impl OwnedLeafShardBlockBuilder {
470 #[inline(always)]
472 pub fn add_transaction<T>(&mut self, transaction: T) -> Result<(), OwnedLeafShardBodyError>
473 where
474 T: WritableBodyTransaction,
475 {
476 self.body_builder.add_transaction(transaction)?;
477
478 Ok(())
479 }
480
481 pub fn with_header(
483 self,
484 prefix: &BlockHeaderPrefix,
485 state_root: Blake3Hash,
486 consensus_info: &BlockHeaderConsensusInfo,
487 beacon_chain_info: &BlockHeaderBeaconChainInfo,
488 ) -> OwnedLeafShardBlockUnsealed {
489 let body = self.body_builder.finish();
490 let header = OwnedLeafShardHeader::from_parts(
491 prefix,
492 &BlockHeaderResult {
493 body_root: body.body().root(),
494 state_root,
495 },
496 consensus_info,
497 beacon_chain_info,
498 );
499 OwnedLeafShardBlockUnsealed { body, header }
500 }
501}
502
503#[derive(Debug, Clone)]
505pub struct OwnedLeafShardBlockUnsealed {
506 body: OwnedLeafShardBody,
507 header: OwnedLeafShardBlockHeaderUnsealed,
508}
509
510impl OwnedLeafShardBlockUnsealed {
511 #[inline(always)]
513 pub fn pre_seal_hash(&self) -> Blake3Hash {
514 self.header.pre_seal_hash()
515 }
516
517 pub fn with_seal(self, seal: BlockHeaderSealRef<'_>) -> OwnedLeafShardBlock {
519 let header = self.header.with_seal(seal);
520
521 OwnedLeafShardBlock {
522 header,
523 body: self.body,
524 }
525 }
526}
527
528#[derive(Debug, thiserror::Error)]
530pub enum OwnedBlockError {
531 #[error("Beacon chain block error: {0}")]
533 BeaconChain(#[from] OwnedBeaconChainBlockError),
534 #[error("Intermediate shard block error: {0}")]
536 IntermediateShard(#[from] OwnedIntermediateShardBlockError),
537 #[error("Leaf shard block error: {0}")]
539 LeafShard(#[from] OwnedLeafShardBlockError),
540}
541
542#[derive(Debug, Clone, From)]
548pub enum OwnedBlock {
549 BeaconChain(OwnedBeaconChainBlock),
551 IntermediateShard(OwnedIntermediateShardBlock),
553 LeafShard(OwnedLeafShardBlock),
555}
556
557impl GenericOwnedBlock for OwnedBlock {
558 type Header = OwnedBlockHeader;
559 type Body = OwnedBlockBody;
560 type Block<'a> = Block<'a>;
561
562 #[inline(always)]
563 fn header(&self) -> Self::Header {
564 match self {
565 Self::BeaconChain(block) => OwnedBlockHeader::BeaconChain(block.header.clone()),
566 Self::IntermediateShard(block) => {
567 OwnedBlockHeader::IntermediateShard(block.header.clone())
568 }
569 Self::LeafShard(block) => OwnedBlockHeader::LeafShard(block.header.clone()),
570 }
571 }
572
573 #[inline(always)]
574 fn body(&self) -> Self::Body {
575 match self {
576 Self::BeaconChain(block) => OwnedBlockBody::BeaconChain(block.body.clone()),
577 Self::IntermediateShard(block) => OwnedBlockBody::IntermediateShard(block.body.clone()),
578 Self::LeafShard(block) => OwnedBlockBody::LeafShard(block.body.clone()),
579 }
580 }
581
582 #[inline(always)]
583 fn block(&self) -> Self::Block<'_> {
584 self.block()
585 }
586}
587
588impl OwnedBlock {
589 #[inline(always)]
591 pub fn header(&self) -> BlockHeader<'_> {
592 match self {
593 Self::BeaconChain(block) => BlockHeader::BeaconChain(block.header.header()),
594 Self::IntermediateShard(block) => BlockHeader::IntermediateShard(block.header.header()),
595 Self::LeafShard(block) => BlockHeader::LeafShard(block.header.header()),
596 }
597 }
598
599 #[inline(always)]
601 pub fn body(&self) -> BlockBody<'_> {
602 match self {
603 Self::BeaconChain(block) => BlockBody::BeaconChain(block.body.body()),
604 Self::IntermediateShard(block) => BlockBody::IntermediateShard(block.body.body()),
605 Self::LeafShard(block) => BlockBody::LeafShard(block.body.body()),
606 }
607 }
608
609 #[inline]
611 pub fn from_block(block: Block<'_>) -> Result<Self, OwnedBlockError> {
612 Ok(match block {
613 Block::BeaconChain(block) => {
614 Self::BeaconChain(OwnedBeaconChainBlock::from_block(block)?)
615 }
616 Block::IntermediateShard(block) => {
617 Self::IntermediateShard(OwnedIntermediateShardBlock::from_block(block)?)
618 }
619 Block::LeafShard(block) => Self::LeafShard(OwnedLeafShardBlock::from_block(block)?),
620 })
621 }
622
623 #[inline]
627 pub fn from_buffers(
628 header: SharedAlignedBuffer,
629 body: SharedAlignedBuffer,
630 shard_kind: ShardKind,
631 ) -> Option<Self> {
632 Some(match shard_kind {
633 ShardKind::BeaconChain => {
634 Self::BeaconChain(OwnedBeaconChainBlock::from_buffers(header, body)?)
635 }
636 ShardKind::IntermediateShard => {
637 Self::IntermediateShard(OwnedIntermediateShardBlock::from_buffers(header, body)?)
638 }
639 ShardKind::LeafShard => {
640 Self::LeafShard(OwnedLeafShardBlock::from_buffers(header, body)?)
641 }
642 ShardKind::Phantom | ShardKind::Invalid => {
643 return None;
645 }
646 })
647 }
648
649 #[inline(always)]
651 pub fn block(&self) -> Block<'_> {
652 match self {
653 Self::BeaconChain(block) => Block::BeaconChain(block.block()),
654 Self::IntermediateShard(block) => Block::IntermediateShard(block.block()),
655 Self::LeafShard(block) => Block::LeafShard(block.block()),
656 }
657 }
658}