1use crate::block::body::owned::{
4 GenericOwnedBlockBody, OwnedBeaconChainBody, OwnedBeaconChainBodyError, OwnedBlockBody,
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, OwnedBlockHeader, 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::{LocalSegmentIndex, SegmentRoot};
23use crate::shard::RealShardKind;
24use ab_aligned_buffer::SharedAlignedBuffer;
25use alloc::vec::Vec;
26use core::any::Any;
27use core::fmt;
28use core::iter::TrustedLen;
29use derive_more::From;
30
31pub trait GenericOwnedBlock:
33 Clone + fmt::Debug + Send + Sync + Into<OwnedBlock> + Any + 'static
34{
35 const SHARD_KIND: RealShardKind;
37
38 type Header: GenericOwnedBlockHeader;
40 type Body: GenericOwnedBlockBody;
42 type Block<'a>: GenericBlock<'a>
44 where
45 Self: 'a;
46
47 fn split(self) -> (Self::Header, Self::Body);
49
50 fn header(&self) -> &Self::Header;
52
53 fn body(&self) -> &Self::Body;
55
56 fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self>;
60
61 fn block(&self) -> Self::Block<'_>;
63}
64
65#[derive(Debug, Clone)]
70#[non_exhaustive]
72pub struct OwnedBeaconChainBlock {
73 pub header: OwnedBeaconChainHeader,
75 pub body: OwnedBeaconChainBody,
77}
78
79impl GenericOwnedBlock for OwnedBeaconChainBlock {
80 const SHARD_KIND: RealShardKind = RealShardKind::BeaconChain;
81
82 type Header = OwnedBeaconChainHeader;
83 type Body = OwnedBeaconChainBody;
84 type Block<'a> = BeaconChainBlock<'a>;
85
86 #[inline(always)]
87 fn split(self) -> (Self::Header, Self::Body) {
88 (self.header, self.body)
89 }
90
91 #[inline(always)]
92 fn header(&self) -> &Self::Header {
93 &self.header
94 }
95
96 #[inline(always)]
97 fn body(&self) -> &Self::Body {
98 &self.body
99 }
100
101 #[inline(always)]
102 fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
103 Self::from_buffers(header, body)
104 }
105
106 #[inline(always)]
107 fn block(&self) -> Self::Block<'_> {
108 self.block()
109 }
110}
111
112impl OwnedBeaconChainBlock {
113 pub fn init<'a, OS, ISB>(
115 own_segments: OS,
116 intermediate_shard_blocks: ISB,
117 pot_checkpoints: &[PotCheckpoints],
118 ) -> Result<OwnedBeaconChainBlockBuilder, OwnedBeaconChainBodyError>
119 where
120 OS: TrustedLen<Item = (LocalSegmentIndex, SegmentRoot)>,
121 ISB: TrustedLen<Item = IntermediateShardBlockInfo<'a>> + Clone + 'a,
122 {
123 Ok(OwnedBeaconChainBlockBuilder {
124 body: OwnedBeaconChainBody::new(
125 own_segments,
126 intermediate_shard_blocks,
127 pot_checkpoints,
128 )?,
129 })
130 }
131
132 #[inline]
134 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
135 let block = Self {
136 header: OwnedBeaconChainHeader::from_buffer(header).ok()?,
137 body: OwnedBeaconChainBody::from_buffer(body).ok()?,
138 };
139
140 if !block.block().is_internally_consistent() {
142 return None;
143 }
144
145 Some(block)
146 }
147
148 pub fn block(&self) -> BeaconChainBlock<'_> {
150 BeaconChainBlock {
151 header: self.header.header().clone(),
152 body: *self.body.body(),
153 }
154 }
155}
156
157#[derive(Debug, Clone)]
159pub struct OwnedBeaconChainBlockBuilder {
160 body: OwnedBeaconChainBody,
161}
162
163impl OwnedBeaconChainBlockBuilder {
164 pub fn with_header(
166 self,
167 prefix: &BlockHeaderPrefix,
168 state_root: Blake3Hash,
169 consensus_info: &BlockHeaderConsensusInfo,
170 consensus_parameters: &BlockHeaderConsensusParameters<'_>,
171 ) -> Result<OwnedBeaconChainBlockUnsealed, OwnedBeaconChainHeaderError> {
172 let body = self.body;
173 let header = OwnedBeaconChainHeader::from_parts(
174 prefix,
175 &BlockHeaderResult {
176 body_root: body.body().root(),
177 state_root,
178 },
179 consensus_info,
180 &body
181 .body()
182 .intermediate_shard_blocks()
183 .iter()
184 .map(|block| *block.header.root())
185 .collect::<Vec<_>>(),
186 consensus_parameters,
187 )?;
188
189 Ok(OwnedBeaconChainBlockUnsealed { body, header })
190 }
191}
192
193#[derive(Debug, Clone)]
195pub struct OwnedBeaconChainBlockUnsealed {
196 body: OwnedBeaconChainBody,
197 header: OwnedBeaconChainHeaderUnsealed,
198}
199
200impl OwnedBeaconChainBlockUnsealed {
201 #[inline(always)]
203 pub fn pre_seal_hash(&self) -> Blake3Hash {
204 self.header.pre_seal_hash()
205 }
206
207 pub fn with_seal(self, seal: BlockHeaderSeal<'_>) -> OwnedBeaconChainBlock {
209 let header = self.header.with_seal(seal);
210
211 OwnedBeaconChainBlock {
212 header,
213 body: self.body,
214 }
215 }
216}
217
218#[derive(Debug, thiserror::Error)]
220pub enum OwnedIntermediateShardBlockError {
221 #[error("Intermediate shard block header error: {0}")]
223 Header(#[from] OwnedIntermediateShardHeaderError),
224 #[error("Intermediate shard block body error: {0}")]
226 Body(#[from] OwnedIntermediateShardBodyError),
227}
228
229#[derive(Debug, Clone)]
234#[non_exhaustive]
236pub struct OwnedIntermediateShardBlock {
237 pub header: OwnedIntermediateShardHeader,
239 pub body: OwnedIntermediateShardBody,
241}
242
243impl GenericOwnedBlock for OwnedIntermediateShardBlock {
244 const SHARD_KIND: RealShardKind = RealShardKind::IntermediateShard;
245
246 type Header = OwnedIntermediateShardHeader;
247 type Body = OwnedIntermediateShardBody;
248 type Block<'a> = IntermediateShardBlock<'a>;
249
250 #[inline(always)]
251 fn split(self) -> (Self::Header, Self::Body) {
252 (self.header, self.body)
253 }
254
255 #[inline(always)]
256 fn header(&self) -> &Self::Header {
257 &self.header
258 }
259
260 #[inline(always)]
261 fn body(&self) -> &Self::Body {
262 &self.body
263 }
264
265 #[inline(always)]
266 fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
267 Self::from_buffers(header, body)
268 }
269
270 #[inline(always)]
271 fn block(&self) -> Self::Block<'_> {
272 self.block()
273 }
274}
275
276impl OwnedIntermediateShardBlock {
277 pub fn init<'a, OS, LSB>(
279 own_segments: OS,
280 leaf_shard_blocks: LSB,
281 ) -> Result<OwnedIntermediateShardBlockBuilder, OwnedIntermediateShardBodyError>
282 where
283 OS: TrustedLen<Item = (LocalSegmentIndex, SegmentRoot)>,
284 LSB: TrustedLen<Item = LeafShardBlockInfo<'a>> + Clone + 'a,
285 {
286 Ok(OwnedIntermediateShardBlockBuilder {
287 body: OwnedIntermediateShardBody::new(own_segments, leaf_shard_blocks)?,
288 })
289 }
290
291 #[inline]
293 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
294 let block = Self {
295 header: OwnedIntermediateShardHeader::from_buffer(header).ok()?,
296 body: OwnedIntermediateShardBody::from_buffer(body).ok()?,
297 };
298
299 if !block.block().is_internally_consistent() {
301 return None;
302 }
303
304 Some(block)
305 }
306
307 pub fn block(&self) -> IntermediateShardBlock<'_> {
309 IntermediateShardBlock {
310 header: self.header.header().clone(),
311 body: *self.body.body(),
312 }
313 }
314}
315
316#[derive(Debug, Clone)]
318pub struct OwnedIntermediateShardBlockBuilder {
319 body: OwnedIntermediateShardBody,
320}
321
322impl OwnedIntermediateShardBlockBuilder {
323 pub fn with_header(
325 self,
326 prefix: &BlockHeaderPrefix,
327 state_root: Blake3Hash,
328 consensus_info: &BlockHeaderConsensusInfo,
329 beacon_chain_info: &BlockHeaderBeaconChainInfo,
330 ) -> Result<OwnedIntermediateShardBlockUnsealed, OwnedIntermediateShardHeaderError> {
331 let body = self.body;
332 let header = OwnedIntermediateShardHeader::from_parts(
333 prefix,
334 &BlockHeaderResult {
335 body_root: body.body().root(),
336 state_root,
337 },
338 consensus_info,
339 beacon_chain_info,
340 &body
341 .body()
342 .leaf_shard_blocks()
343 .iter()
344 .map(|block| *block.header.root())
345 .collect::<Vec<_>>(),
346 )?;
347
348 Ok(OwnedIntermediateShardBlockUnsealed { body, header })
349 }
350}
351
352#[derive(Debug, Clone)]
354pub struct OwnedIntermediateShardBlockUnsealed {
355 body: OwnedIntermediateShardBody,
356 header: OwnedIntermediateShardHeaderUnsealed,
357}
358
359impl OwnedIntermediateShardBlockUnsealed {
360 #[inline(always)]
362 pub fn pre_seal_hash(&self) -> Blake3Hash {
363 self.header.pre_seal_hash()
364 }
365
366 pub fn with_seal(self, seal: BlockHeaderSeal<'_>) -> OwnedIntermediateShardBlock {
368 let header = self.header.with_seal(seal);
369
370 OwnedIntermediateShardBlock {
371 header,
372 body: self.body,
373 }
374 }
375}
376
377#[derive(Debug, Clone)]
382#[non_exhaustive]
384pub struct OwnedLeafShardBlock {
385 pub header: OwnedLeafShardHeader,
387 pub body: OwnedLeafShardBody,
389}
390
391impl GenericOwnedBlock for OwnedLeafShardBlock {
392 const SHARD_KIND: RealShardKind = RealShardKind::LeafShard;
393
394 type Header = OwnedLeafShardHeader;
395 type Body = OwnedLeafShardBody;
396 type Block<'a> = LeafShardBlock<'a>;
397
398 #[inline(always)]
399 fn split(self) -> (Self::Header, Self::Body) {
400 (self.header, self.body)
401 }
402
403 #[inline(always)]
404 fn header(&self) -> &Self::Header {
405 &self.header
406 }
407
408 #[inline(always)]
409 fn body(&self) -> &Self::Body {
410 &self.body
411 }
412
413 #[inline(always)]
414 fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
415 Self::from_buffers(header, body)
416 }
417
418 #[inline(always)]
419 fn block(&self) -> Self::Block<'_> {
420 self.block()
421 }
422}
423
424impl OwnedLeafShardBlock {
425 pub fn init<OS>(own_segments: OS) -> Result<OwnedLeafShardBlockBuilder, OwnedLeafShardBodyError>
427 where
428 OS: TrustedLen<Item = (LocalSegmentIndex, SegmentRoot)>,
429 {
430 Ok(OwnedLeafShardBlockBuilder {
431 body_builder: OwnedLeafShardBody::init(own_segments)?,
432 })
433 }
434
435 #[inline]
437 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
438 let block = Self {
439 header: OwnedLeafShardHeader::from_buffer(header).ok()?,
440 body: OwnedLeafShardBody::from_buffer(body).ok()?,
441 };
442
443 if !block.block().is_internally_consistent() {
445 return None;
446 }
447
448 Some(block)
449 }
450
451 pub fn block(&self) -> LeafShardBlock<'_> {
453 LeafShardBlock {
454 header: self.header.header().clone(),
455 body: *self.body.body(),
456 }
457 }
458}
459
460#[derive(Debug, Clone)]
462pub struct OwnedLeafShardBlockBuilder {
463 body_builder: OwnedLeafShardBlockBodyBuilder,
464}
465
466impl OwnedLeafShardBlockBuilder {
467 #[inline(always)]
469 pub fn add_transaction<T>(&mut self, transaction: T) -> Result<(), OwnedLeafShardBodyError>
470 where
471 T: WritableBodyTransaction,
472 {
473 self.body_builder.add_transaction(transaction)?;
474
475 Ok(())
476 }
477
478 pub fn with_header(
480 self,
481 prefix: &BlockHeaderPrefix,
482 state_root: Blake3Hash,
483 consensus_info: &BlockHeaderConsensusInfo,
484 beacon_chain_info: &BlockHeaderBeaconChainInfo,
485 ) -> OwnedLeafShardBlockUnsealed {
486 let body = self.body_builder.finish();
487 let header = OwnedLeafShardHeader::from_parts(
488 prefix,
489 &BlockHeaderResult {
490 body_root: body.body().root(),
491 state_root,
492 },
493 consensus_info,
494 beacon_chain_info,
495 );
496 OwnedLeafShardBlockUnsealed { body, header }
497 }
498}
499
500#[derive(Debug, Clone)]
502pub struct OwnedLeafShardBlockUnsealed {
503 body: OwnedLeafShardBody,
504 header: OwnedLeafShardHeaderUnsealed,
505}
506
507impl OwnedLeafShardBlockUnsealed {
508 #[inline(always)]
510 pub fn pre_seal_hash(&self) -> Blake3Hash {
511 self.header.pre_seal_hash()
512 }
513
514 pub fn with_seal(self, seal: BlockHeaderSeal<'_>) -> OwnedLeafShardBlock {
516 let header = self.header.with_seal(seal);
517
518 OwnedLeafShardBlock {
519 header,
520 body: self.body,
521 }
522 }
523}
524
525#[derive(Debug, Clone, From)]
531pub enum OwnedBlock {
532 BeaconChain(OwnedBeaconChainBlock),
534 IntermediateShard(OwnedIntermediateShardBlock),
536 LeafShard(OwnedLeafShardBlock),
538}
539
540impl OwnedBlock {
541 #[inline]
543 pub fn split(self) -> (OwnedBlockHeader, OwnedBlockBody) {
544 match self {
545 Self::BeaconChain(block) => {
546 let (header, body) = block.split();
547 (header.into(), body.into())
548 }
549 Self::IntermediateShard(block) => {
550 let (header, body) = block.split();
551 (header.into(), body.into())
552 }
553 Self::LeafShard(block) => {
554 let (header, body) = block.split();
555 (header.into(), body.into())
556 }
557 }
558 }
559
560 #[inline(always)]
562 pub fn header(&self) -> BlockHeader<'_> {
563 match self {
564 Self::BeaconChain(block) => BlockHeader::BeaconChain(block.header.header().clone()),
565 Self::IntermediateShard(block) => {
566 BlockHeader::IntermediateShard(block.header.header().clone())
567 }
568 Self::LeafShard(block) => BlockHeader::LeafShard(block.header.header().clone()),
569 }
570 }
571
572 #[inline(always)]
574 pub fn body(&self) -> BlockBody<'_> {
575 match self {
576 Self::BeaconChain(block) => BlockBody::BeaconChain(*block.body.body()),
577 Self::IntermediateShard(block) => BlockBody::IntermediateShard(*block.body.body()),
578 Self::LeafShard(block) => BlockBody::LeafShard(*block.body.body()),
579 }
580 }
581
582 #[inline]
586 pub fn from_buffers(
587 header: SharedAlignedBuffer,
588 body: SharedAlignedBuffer,
589 shard_kind: RealShardKind,
590 ) -> Option<Self> {
591 Some(match shard_kind {
592 RealShardKind::BeaconChain => {
593 Self::BeaconChain(OwnedBeaconChainBlock::from_buffers(header, body)?)
594 }
595 RealShardKind::IntermediateShard => {
596 Self::IntermediateShard(OwnedIntermediateShardBlock::from_buffers(header, body)?)
597 }
598 RealShardKind::LeafShard => {
599 Self::LeafShard(OwnedLeafShardBlock::from_buffers(header, body)?)
600 }
601 })
602 }
603
604 #[inline(always)]
606 pub fn block(&self) -> Block<'_> {
607 match self {
608 Self::BeaconChain(block) => Block::BeaconChain(block.block()),
609 Self::IntermediateShard(block) => Block::IntermediateShard(block.block()),
610 Self::LeafShard(block) => Block::LeafShard(block.block()),
611 }
612 }
613}