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::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: RealShardKind;
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: RealShardKind = RealShardKind::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, OS, ISB>(
112 own_segments: OS,
113 intermediate_shard_blocks: ISB,
114 pot_checkpoints: &[PotCheckpoints],
115 ) -> Result<OwnedBeaconChainBlockBuilder, OwnedBeaconChainBodyError>
116 where
117 OS: TrustedLen<Item = (LocalSegmentIndex, SegmentRoot)>,
118 ISB: TrustedLen<Item = IntermediateShardBlockInfo<'a>> + Clone + 'a,
119 {
120 Ok(OwnedBeaconChainBlockBuilder {
121 body: OwnedBeaconChainBody::new(
122 own_segments,
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: RealShardKind = RealShardKind::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, OS, LSB>(
276 own_segments: OS,
277 leaf_shard_blocks: LSB,
278 ) -> Result<OwnedIntermediateShardBlockBuilder, OwnedIntermediateShardBodyError>
279 where
280 OS: TrustedLen<Item = (LocalSegmentIndex, SegmentRoot)>,
281 LSB: TrustedLen<Item = LeafShardBlockInfo<'a>> + Clone + 'a,
282 {
283 Ok(OwnedIntermediateShardBlockBuilder {
284 body: OwnedIntermediateShardBody::new(own_segments, 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: RealShardKind = RealShardKind::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<OS>(own_segments: OS) -> Result<OwnedLeafShardBlockBuilder, OwnedLeafShardBodyError>
424 where
425 OS: TrustedLen<Item = (LocalSegmentIndex, SegmentRoot)>,
426 {
427 Ok(OwnedLeafShardBlockBuilder {
428 body_builder: OwnedLeafShardBody::init(own_segments)?,
429 })
430 }
431
432 #[inline]
434 pub fn from_buffers(header: SharedAlignedBuffer, body: SharedAlignedBuffer) -> Option<Self> {
435 let block = Self {
436 header: OwnedLeafShardHeader::from_buffer(header).ok()?,
437 body: OwnedLeafShardBody::from_buffer(body).ok()?,
438 };
439
440 if !block.block().is_internally_consistent() {
442 return None;
443 }
444
445 Some(block)
446 }
447
448 pub fn block(&self) -> LeafShardBlock<'_> {
450 LeafShardBlock {
451 header: self.header.header().clone(),
452 body: *self.body.body(),
453 }
454 }
455}
456
457#[derive(Debug, Clone)]
459pub struct OwnedLeafShardBlockBuilder {
460 body_builder: OwnedLeafShardBlockBodyBuilder,
461}
462
463impl OwnedLeafShardBlockBuilder {
464 #[inline(always)]
466 pub fn add_transaction<T>(&mut self, transaction: T) -> Result<(), OwnedLeafShardBodyError>
467 where
468 T: WritableBodyTransaction,
469 {
470 self.body_builder.add_transaction(transaction)?;
471
472 Ok(())
473 }
474
475 pub fn with_header(
477 self,
478 prefix: &BlockHeaderPrefix,
479 state_root: Blake3Hash,
480 consensus_info: &BlockHeaderConsensusInfo,
481 beacon_chain_info: &BlockHeaderBeaconChainInfo,
482 ) -> OwnedLeafShardBlockUnsealed {
483 let body = self.body_builder.finish();
484 let header = OwnedLeafShardHeader::from_parts(
485 prefix,
486 &BlockHeaderResult {
487 body_root: body.body().root(),
488 state_root,
489 },
490 consensus_info,
491 beacon_chain_info,
492 );
493 OwnedLeafShardBlockUnsealed { body, header }
494 }
495}
496
497#[derive(Debug, Clone)]
499pub struct OwnedLeafShardBlockUnsealed {
500 body: OwnedLeafShardBody,
501 header: OwnedLeafShardHeaderUnsealed,
502}
503
504impl OwnedLeafShardBlockUnsealed {
505 #[inline(always)]
507 pub fn pre_seal_hash(&self) -> Blake3Hash {
508 self.header.pre_seal_hash()
509 }
510
511 pub fn with_seal(self, seal: BlockHeaderSeal<'_>) -> OwnedLeafShardBlock {
513 let header = self.header.with_seal(seal);
514
515 OwnedLeafShardBlock {
516 header,
517 body: self.body,
518 }
519 }
520}
521
522#[derive(Debug, Clone, From)]
528pub enum OwnedBlock {
529 BeaconChain(OwnedBeaconChainBlock),
531 IntermediateShard(OwnedIntermediateShardBlock),
533 LeafShard(OwnedLeafShardBlock),
535}
536
537impl OwnedBlock {
538 #[inline]
540 pub fn split(self) -> (OwnedBlockHeader, OwnedBlockBody) {
541 match self {
542 Self::BeaconChain(block) => {
543 let (header, body) = block.split();
544 (header.into(), body.into())
545 }
546 Self::IntermediateShard(block) => {
547 let (header, body) = block.split();
548 (header.into(), body.into())
549 }
550 Self::LeafShard(block) => {
551 let (header, body) = block.split();
552 (header.into(), body.into())
553 }
554 }
555 }
556
557 #[inline(always)]
559 pub fn header(&self) -> BlockHeader<'_> {
560 match self {
561 Self::BeaconChain(block) => BlockHeader::BeaconChain(block.header.header().clone()),
562 Self::IntermediateShard(block) => {
563 BlockHeader::IntermediateShard(block.header.header().clone())
564 }
565 Self::LeafShard(block) => BlockHeader::LeafShard(block.header.header().clone()),
566 }
567 }
568
569 #[inline(always)]
571 pub fn body(&self) -> BlockBody<'_> {
572 match self {
573 Self::BeaconChain(block) => BlockBody::BeaconChain(*block.body.body()),
574 Self::IntermediateShard(block) => BlockBody::IntermediateShard(*block.body.body()),
575 Self::LeafShard(block) => BlockBody::LeafShard(*block.body.body()),
576 }
577 }
578
579 #[inline]
583 pub fn from_buffers(
584 header: SharedAlignedBuffer,
585 body: SharedAlignedBuffer,
586 shard_kind: RealShardKind,
587 ) -> Option<Self> {
588 Some(match shard_kind {
589 RealShardKind::BeaconChain => {
590 Self::BeaconChain(OwnedBeaconChainBlock::from_buffers(header, body)?)
591 }
592 RealShardKind::IntermediateShard => {
593 Self::IntermediateShard(OwnedIntermediateShardBlock::from_buffers(header, body)?)
594 }
595 RealShardKind::LeafShard => {
596 Self::LeafShard(OwnedLeafShardBlock::from_buffers(header, body)?)
597 }
598 })
599 }
600
601 #[inline(always)]
603 pub fn block(&self) -> Block<'_> {
604 match self {
605 Self::BeaconChain(block) => Block::BeaconChain(block.block()),
606 Self::IntermediateShard(block) => Block::IntermediateShard(block.block()),
607 Self::LeafShard(block) => Block::LeafShard(block.block()),
608 }
609 }
610}