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