1#[cfg(feature = "alloc")]
4mod archival_history_segment;
5#[cfg(all(test, feature = "alloc"))]
6mod tests;
7
8use crate::block::BlockNumber;
9use crate::hashes::Blake3Hash;
10use crate::pieces::{PieceIndex, Record, SegmentProof};
11#[cfg(feature = "alloc")]
12pub use crate::segments::archival_history_segment::ArchivedHistorySegment;
13use crate::shard::ShardIndex;
14use crate::trees::SuperSegmentMerkleTree;
15use ab_blake3::{single_block_hash, single_chunk_hash};
16use ab_io_type::trivial_type::TrivialType;
17use ab_io_type::unaligned::Unaligned;
18#[cfg(feature = "alloc")]
19use alloc::boxed::Box;
20#[cfg(feature = "alloc")]
21use alloc::sync::Arc as StdArc;
22use blake3::{CHUNK_LEN, OUT_LEN};
23use core::fmt;
24use core::iter::Step;
25#[cfg(feature = "alloc")]
26use core::mem::MaybeUninit;
27use core::num::{NonZeroU32, NonZeroU64};
28use derive_more::{
29 Add, AddAssign, Deref, DerefMut, Display, Div, DivAssign, From, Into, Mul, MulAssign, Sub,
30 SubAssign,
31};
32#[cfg(feature = "scale-codec")]
33use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
34#[cfg(feature = "serde")]
35use serde::{Deserialize, Deserializer, Serialize, Serializer};
36#[cfg(feature = "serde")]
37use serde_big_array::BigArray;
38use transparent_wrapper::TransparentWrapper;
39
40#[derive(
42 Debug,
43 Display,
44 Default,
45 Copy,
46 Clone,
47 Ord,
48 PartialOrd,
49 Eq,
50 PartialEq,
51 Hash,
52 Add,
53 AddAssign,
54 Sub,
55 SubAssign,
56 Mul,
57 MulAssign,
58 Div,
59 DivAssign,
60 TrivialType,
61)]
62#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
63#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
64#[repr(C)]
65pub struct SuperSegmentIndex(u64);
66
67impl Step for SuperSegmentIndex {
68 #[inline]
69 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
70 u64::steps_between(&start.0, &end.0)
71 }
72
73 #[inline]
74 fn forward_checked(start: Self, count: usize) -> Option<Self> {
75 u64::forward_checked(start.0, count).map(Self)
76 }
77
78 #[inline(always)]
79 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
80 let (n, overflowing) = u64::forward_overflowing(start.0, count);
81 (Self(n), overflowing)
82 }
83
84 #[inline]
85 fn backward_checked(start: Self, count: usize) -> Option<Self> {
86 u64::backward_checked(start.0, count).map(Self)
87 }
88
89 #[inline(always)]
90 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
91 let (n, overflowing) = u64::backward_overflowing(start.0, count);
92 (Self(n), overflowing)
93 }
94}
95
96const impl From<u64> for SuperSegmentIndex {
97 #[inline(always)]
98 fn from(value: u64) -> Self {
99 Self(value)
100 }
101}
102
103const impl From<SuperSegmentIndex> for u64 {
104 #[inline(always)]
105 fn from(value: SuperSegmentIndex) -> Self {
106 value.0
107 }
108}
109
110impl SuperSegmentIndex {
111 pub const ZERO: Self = Self(0);
113 pub const ONE: Self = Self(1);
115
116 #[inline]
118 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
119 self.0.checked_sub(rhs.0).map(Self)
120 }
121
122 #[inline]
125 pub const fn saturating_sub(self, rhs: Self) -> Self {
126 Self(self.0.saturating_sub(rhs.0))
127 }
128}
129
130#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
132#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
133#[repr(C)]
134pub struct SuperSegmentRoot([u8; SuperSegmentRoot::SIZE]);
135
136impl fmt::Debug for SuperSegmentRoot {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 for byte in self.0 {
139 write!(f, "{byte:02x}")?;
140 }
141 Ok(())
142 }
143}
144
145const impl Default for SuperSegmentRoot {
146 #[inline]
147 fn default() -> Self {
148 Self([0; _])
149 }
150}
151
152#[cfg(feature = "serde")]
153#[derive(Serialize, Deserialize)]
154#[serde(transparent)]
155struct SuperSegmentRootBinary(#[serde(with = "BigArray")] [u8; SuperSegmentRoot::SIZE]);
156
157#[cfg(feature = "serde")]
158#[derive(Serialize, Deserialize)]
159#[serde(transparent)]
160struct SuperSegmentRootHex(#[serde(with = "hex")] [u8; SuperSegmentRoot::SIZE]);
161
162#[cfg(feature = "serde")]
163impl Serialize for SuperSegmentRoot {
164 #[inline]
165 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
166 where
167 S: Serializer,
168 {
169 if serializer.is_human_readable() {
170 SuperSegmentRootHex(self.0).serialize(serializer)
171 } else {
172 SuperSegmentRootBinary(self.0).serialize(serializer)
173 }
174 }
175}
176
177#[cfg(feature = "serde")]
178impl<'de> Deserialize<'de> for SuperSegmentRoot {
179 #[inline]
180 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
181 where
182 D: Deserializer<'de>,
183 {
184 Ok(Self(if deserializer.is_human_readable() {
185 SuperSegmentRootHex::deserialize(deserializer)?.0
186 } else {
187 SuperSegmentRootBinary::deserialize(deserializer)?.0
188 }))
189 }
190}
191
192impl AsRef<[u8]> for SuperSegmentRoot {
193 #[inline]
194 fn as_ref(&self) -> &[u8] {
195 &self.0
196 }
197}
198
199impl AsMut<[u8]> for SuperSegmentRoot {
200 #[inline]
201 fn as_mut(&mut self) -> &mut [u8] {
202 &mut self.0
203 }
204}
205
206impl SuperSegmentRoot {
207 pub const SIZE: usize = 32;
209 pub const MAX_SEGMENTS: u32 = 2u32.pow(20) - 1;
213}
214
215#[derive(
217 Debug,
218 Display,
219 Default,
220 Copy,
221 Clone,
222 Ord,
223 PartialOrd,
224 Eq,
225 PartialEq,
226 Hash,
227 From,
228 Into,
229 TrivialType,
230)]
231#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
233#[repr(C)]
234pub struct SegmentPosition(u32);
235
236impl From<SegmentPosition> for u64 {
237 #[inline]
238 fn from(original: SegmentPosition) -> Self {
239 Self::from(original.0)
240 }
241}
242
243impl SegmentPosition {
244 pub const ZERO: Self = Self(0);
246}
247
248#[derive(Debug, Clone, Copy, TrivialType)]
250#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
252#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
253#[repr(C)]
254pub struct ShardSegmentRootWithPosition {
255 pub shard_index: ShardIndex,
257 pub segment_position: SegmentPosition,
259 pub local_segment_index: LocalSegmentIndex,
261 pub segment_root: SegmentRoot,
263}
264
265impl ShardSegmentRootWithPosition {
266 #[inline(always)]
268 pub fn hash(&self) -> [u8; OUT_LEN] {
269 single_block_hash(self.as_bytes()).expect("Less than a single block worth of bytes; qed")
270 }
271}
272
273#[derive(Debug, Clone, Copy, Eq, PartialEq, TrivialType)]
275#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
277#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
278#[repr(C)]
279pub struct SuperSegmentHeader {
280 pub index: Unaligned<SuperSegmentIndex>,
282 pub root: SuperSegmentRoot,
284 pub prev_super_segment_header_hash: Blake3Hash,
286 pub max_segment_index: Unaligned<SegmentIndex>,
288 pub target_beacon_chain_block_number: Unaligned<BlockNumber>,
290 pub num_segments: u32,
293}
294
295#[cfg(feature = "alloc")]
297#[derive(Debug, Clone)]
298#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
301#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
302pub struct SuperSegment {
303 pub header: SuperSegmentHeader,
305 pub segment_roots: StdArc<[ShardSegmentRootWithPosition]>,
307}
308
309#[cfg(feature = "alloc")]
310impl SuperSegment {
311 pub fn new(
315 previous_header: &SuperSegmentHeader,
316 target_beacon_chain_block_number: BlockNumber,
317 segment_roots: StdArc<[ShardSegmentRootWithPosition]>,
318 ) -> Option<Self> {
319 let num_segments = u32::try_from(segment_roots.len()).ok()?;
320 let max_segment_index = SegmentIndex::from(
321 u64::from(previous_header.max_segment_index.as_inner()) + u64::from(num_segments),
322 );
323
324 let maybe_super_segment_root =
325 SuperSegmentMerkleTree::compute_root_only::<
326 { u64::from(SuperSegmentRoot::MAX_SEGMENTS) },
327 _,
328 _,
329 >(segment_roots.iter().map(ShardSegmentRootWithPosition::hash))?;
330
331 Some(Self {
332 header: SuperSegmentHeader {
333 index: (previous_header.index.as_inner() + SuperSegmentIndex::ONE).into(),
334 root: SuperSegmentRoot::from(maybe_super_segment_root),
335 prev_super_segment_header_hash: Blake3Hash::from(
336 single_chunk_hash(previous_header.as_bytes())
337 .expect("Less than a single chunk worth of bytes; qed"),
338 ),
339 max_segment_index: max_segment_index.into(),
340 target_beacon_chain_block_number: target_beacon_chain_block_number.into(),
341 num_segments,
342 },
343 segment_roots,
344 })
345 }
346
347 pub fn proof_for_segment(&self, segment_position: SegmentPosition) -> Option<SegmentProof> {
349 let mut segment_proof = [MaybeUninit::uninit(); _];
350 let (_root, proof_hashes) = SuperSegmentMerkleTree::compute_root_and_proof_in::<
351 { u64::from(SuperSegmentRoot::MAX_SEGMENTS) },
352 _,
353 _,
354 >(
355 self.segment_roots.iter().map(|shard_segment_root| {
356 single_block_hash(shard_segment_root.as_bytes())
357 .expect("Less than a single block worth of bytes; qed")
358 }),
359 u32::from(segment_position) as usize,
360 &mut segment_proof,
361 )?;
362 let proof_length = proof_hashes.len();
363
364 segment_proof
366 .get_mut(proof_length..)
367 .expect("Proof is a prefix of the provided memory; qed")
368 .write_filled([0; OUT_LEN]);
369 let segment_proof = unsafe { MaybeUninit::from(segment_proof).assume_init() };
372
373 Some(SegmentProof::from(segment_proof))
374 }
375}
376
377#[derive(
379 Debug,
380 Display,
381 Default,
382 Copy,
383 Clone,
384 Ord,
385 PartialOrd,
386 Eq,
387 PartialEq,
388 Hash,
389 Add,
390 AddAssign,
391 Sub,
392 SubAssign,
393 Mul,
394 MulAssign,
395 Div,
396 DivAssign,
397 TrivialType,
398)]
399#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
401#[repr(C)]
402pub struct LocalSegmentIndex(u64);
403
404impl Step for LocalSegmentIndex {
405 #[inline]
406 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
407 u64::steps_between(&start.0, &end.0)
408 }
409
410 #[inline]
411 fn forward_checked(start: Self, count: usize) -> Option<Self> {
412 u64::forward_checked(start.0, count).map(Self)
413 }
414
415 #[inline(always)]
416 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
417 let (n, overflowing) = u64::forward_overflowing(start.0, count);
418 (Self(n), overflowing)
419 }
420
421 #[inline]
422 fn backward_checked(start: Self, count: usize) -> Option<Self> {
423 u64::backward_checked(start.0, count).map(Self)
424 }
425
426 #[inline(always)]
427 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
428 let (n, overflowing) = u64::backward_overflowing(start.0, count);
429 (Self(n), overflowing)
430 }
431}
432
433const impl From<u64> for LocalSegmentIndex {
434 #[inline(always)]
435 fn from(value: u64) -> Self {
436 Self(value)
437 }
438}
439
440const impl From<LocalSegmentIndex> for u64 {
441 #[inline(always)]
442 fn from(value: LocalSegmentIndex) -> Self {
443 value.0
444 }
445}
446
447impl LocalSegmentIndex {
448 pub const ZERO: Self = Self(0);
450 pub const ONE: Self = Self(1);
452
453 #[inline]
455 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
456 self.0.checked_sub(rhs.0).map(Self)
457 }
458
459 #[inline]
462 pub const fn saturating_sub(self, rhs: Self) -> Self {
463 Self(self.0.saturating_sub(rhs.0))
464 }
465}
466
467#[derive(
469 Debug,
470 Display,
471 Default,
472 Copy,
473 Clone,
474 Ord,
475 PartialOrd,
476 Eq,
477 PartialEq,
478 Hash,
479 Add,
480 AddAssign,
481 Sub,
482 SubAssign,
483 Mul,
484 MulAssign,
485 Div,
486 DivAssign,
487 TrivialType,
488)]
489#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
490#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
491#[repr(C)]
492pub struct SegmentIndex(u64);
493
494impl Step for SegmentIndex {
495 #[inline]
496 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
497 u64::steps_between(&start.0, &end.0)
498 }
499
500 #[inline]
501 fn forward_checked(start: Self, count: usize) -> Option<Self> {
502 u64::forward_checked(start.0, count).map(Self)
503 }
504
505 #[inline(always)]
506 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
507 let (n, overflowing) = u64::forward_overflowing(start.0, count);
508 (Self(n), overflowing)
509 }
510
511 #[inline]
512 fn backward_checked(start: Self, count: usize) -> Option<Self> {
513 u64::backward_checked(start.0, count).map(Self)
514 }
515
516 #[inline(always)]
517 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
518 let (n, overflowing) = u64::backward_overflowing(start.0, count);
519 (Self(n), overflowing)
520 }
521}
522
523const impl From<u64> for SegmentIndex {
524 #[inline(always)]
525 fn from(value: u64) -> Self {
526 Self(value)
527 }
528}
529
530const impl From<SegmentIndex> for u64 {
531 #[inline(always)]
532 fn from(value: SegmentIndex) -> Self {
533 value.0
534 }
535}
536
537impl SegmentIndex {
538 pub const ZERO: Self = Self(0);
540 pub const ONE: Self = Self(1);
542
543 #[inline]
545 pub const fn first_piece_index(&self) -> PieceIndex {
546 PieceIndex::from(self.0 * RecordedHistorySegment::NUM_PIECES as u64)
547 }
548
549 #[inline]
551 pub const fn last_piece_index(&self) -> PieceIndex {
552 PieceIndex::from((self.0 + 1) * RecordedHistorySegment::NUM_PIECES as u64 - 1)
553 }
554
555 #[inline]
557 pub fn segment_piece_indexes(&self) -> [PieceIndex; RecordedHistorySegment::NUM_PIECES] {
558 let mut piece_indices = [PieceIndex::ZERO; RecordedHistorySegment::NUM_PIECES];
559 (self.first_piece_index()..=self.last_piece_index())
560 .zip(&mut piece_indices)
561 .for_each(|(input, output)| {
562 *output = input;
563 });
564
565 piece_indices
566 }
567
568 #[inline]
570 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
571 self.0.checked_sub(rhs.0).map(Self)
572 }
573
574 #[inline]
577 pub const fn saturating_sub(self, rhs: Self) -> Self {
578 Self(self.0.saturating_sub(rhs.0))
579 }
580}
581
582#[derive(
584 Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType, TransparentWrapper,
585)]
586#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
587#[repr(C)]
588pub struct SegmentRoot([u8; SegmentRoot::SIZE]);
589
590impl fmt::Debug for SegmentRoot {
591 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
592 for byte in self.0 {
593 write!(f, "{byte:02x}")?;
594 }
595 Ok(())
596 }
597}
598
599#[cfg(feature = "serde")]
600#[derive(Serialize, Deserialize)]
601#[serde(transparent)]
602struct SegmentRootBinary(#[serde(with = "BigArray")] [u8; SegmentRoot::SIZE]);
603
604#[cfg(feature = "serde")]
605#[derive(Serialize, Deserialize)]
606#[serde(transparent)]
607struct SegmentRootHex(#[serde(with = "hex")] [u8; SegmentRoot::SIZE]);
608
609#[cfg(feature = "serde")]
610impl Serialize for SegmentRoot {
611 #[inline]
612 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
613 where
614 S: Serializer,
615 {
616 if serializer.is_human_readable() {
617 SegmentRootHex(self.0).serialize(serializer)
618 } else {
619 SegmentRootBinary(self.0).serialize(serializer)
620 }
621 }
622}
623
624#[cfg(feature = "serde")]
625impl<'de> Deserialize<'de> for SegmentRoot {
626 #[inline]
627 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
628 where
629 D: Deserializer<'de>,
630 {
631 Ok(Self(if deserializer.is_human_readable() {
632 SegmentRootHex::deserialize(deserializer)?.0
633 } else {
634 SegmentRootBinary::deserialize(deserializer)?.0
635 }))
636 }
637}
638
639impl Default for SegmentRoot {
640 #[inline(always)]
641 fn default() -> Self {
642 Self([0; _])
643 }
644}
645
646impl AsRef<[u8]> for SegmentRoot {
647 #[inline(always)]
648 fn as_ref(&self) -> &[u8] {
649 &self.0
650 }
651}
652
653impl AsMut<[u8]> for SegmentRoot {
654 #[inline(always)]
655 fn as_mut(&mut self) -> &mut [u8] {
656 &mut self.0
657 }
658}
659
660impl SegmentRoot {
661 pub const SIZE: usize = 32;
663
664 #[inline(always)]
666 pub const fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
667 Self::wrap_slice(value)
668 }
669
670 #[inline(always)]
672 pub const fn repr_from_slice(value: &[Self]) -> &[[u8; Self::SIZE]] {
673 Self::peel_slice(value)
674 }
675
676 pub fn is_valid(
678 &self,
679 shard_index: ShardIndex,
680 local_segment_index: LocalSegmentIndex,
681 segment_position: SegmentPosition,
682 segment_proof: &SegmentProof,
683 num_segments: u32,
684 super_segment_root: &SuperSegmentRoot,
685 ) -> bool {
686 let shard_segment_root = ShardSegmentRootWithPosition {
687 shard_index,
688 segment_position,
689 local_segment_index,
690 segment_root: *self,
691 };
692 let (segment_proof, padding) = segment_proof
695 .split_once(|hash| hash == &[0; _])
696 .unwrap_or((segment_proof.as_slice(), &[]));
697 if padding.iter().any(|hash| hash != &[0; _]) {
699 return false;
700 }
701 SuperSegmentMerkleTree::verify(
702 super_segment_root,
703 segment_proof,
704 u64::from(segment_position),
705 shard_segment_root.hash(),
706 u64::from(num_segments),
707 )
708 }
709}
710
711#[derive(
713 Debug,
714 Display,
715 Copy,
716 Clone,
717 Ord,
718 PartialOrd,
719 Eq,
720 PartialEq,
721 Hash,
722 From,
723 Into,
724 Deref,
725 DerefMut,
726 TrivialType,
727)]
728#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
729#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
730#[repr(C)]
731pub struct HistorySize(SegmentIndex);
733
734impl HistorySize {
735 pub const ONE: Self = Self(SegmentIndex::ZERO);
737
738 #[inline(always)]
740 pub const fn new(value: NonZeroU64) -> Self {
741 Self(SegmentIndex::from(value.get() - 1))
742 }
743
744 pub const fn as_segment_index(&self) -> SegmentIndex {
746 self.0
747 }
748
749 pub const fn as_non_zero_u64(&self) -> NonZeroU64 {
751 NonZeroU64::new(u64::from(self.0).saturating_add(1)).expect("Not zero; qed")
752 }
753
754 #[inline(always)]
756 pub const fn in_pieces(&self) -> NonZeroU64 {
757 NonZeroU64::new(
758 u64::from(self.0)
759 .saturating_add(1)
760 .saturating_mul(RecordedHistorySegment::NUM_PIECES as u64),
761 )
762 .expect("Not zero; qed")
763 }
764
765 #[inline(always)]
767 pub fn segment_index(&self) -> SegmentIndex {
768 self.0
769 }
770
771 #[inline(always)]
775 pub fn sector_expiration_check(&self, min_sector_lifetime: Self) -> Option<Self> {
776 self.as_non_zero_u64()
777 .checked_add(min_sector_lifetime.as_non_zero_u64().get())
778 .map(Self::new)
779 }
780}
781
782#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, TrivialType)]
784#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
785#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
786#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
787#[repr(C)]
788pub struct ArchivedBlockProgress {
789 bytes: u32,
791}
792
793impl Default for ArchivedBlockProgress {
794 #[inline(always)]
797 fn default() -> Self {
798 Self::new_complete()
799 }
800}
801
802impl ArchivedBlockProgress {
803 #[inline(always)]
805 pub const fn new_complete() -> Self {
806 Self { bytes: 0 }
807 }
808
809 #[inline(always)]
811 pub const fn new_partial(new_partial: NonZeroU32) -> Self {
812 Self {
813 bytes: new_partial.get(),
814 }
815 }
816
817 #[inline(always)]
819 pub const fn partial(&self) -> Option<NonZeroU32> {
820 NonZeroU32::new(self.bytes)
821 }
822}
823
824#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, TrivialType)]
826#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
828#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
829#[repr(C)]
830pub struct LastArchivedBlock {
831 pub number: Unaligned<BlockNumber>,
833 pub archived_progress: ArchivedBlockProgress,
835}
836
837impl LastArchivedBlock {
838 #[inline(always)]
840 pub fn partial_archived(&self) -> Option<NonZeroU32> {
841 self.archived_progress.partial()
842 }
843
844 #[inline(always)]
846 pub fn set_partial_archived(&mut self, new_partial: NonZeroU32) {
847 self.archived_progress = ArchivedBlockProgress::new_partial(new_partial);
848 }
849
850 #[inline(always)]
852 pub fn set_complete(&mut self) {
853 self.archived_progress = ArchivedBlockProgress::new_complete();
854 }
855
856 pub const fn number(&self) -> BlockNumber {
858 self.number.as_inner()
859 }
860}
861
862#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TrivialType)]
864#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
865#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
866#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
867#[repr(C)]
868pub struct SegmentHeader {
869 pub index: Unaligned<LocalSegmentIndex>,
871 pub root: SegmentRoot,
873 pub prev_segment_header_hash: Blake3Hash,
875 pub last_archived_block: LastArchivedBlock,
877}
878
879impl SegmentHeader {
880 #[inline(always)]
882 pub fn hash(&self) -> Blake3Hash {
883 const {
884 assert!(size_of::<Self>() <= CHUNK_LEN);
885 }
886 Blake3Hash::new(
887 single_chunk_hash(self.as_bytes())
888 .expect("Less than a single chunk worth of bytes; qed"),
889 )
890 }
891}
892
893#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
897#[repr(C)]
898pub struct RecordedHistorySegment([Record; Self::NUM_RAW_RECORDS]);
899
900impl fmt::Debug for RecordedHistorySegment {
901 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
902 f.debug_struct("RecordedHistorySegment")
903 .finish_non_exhaustive()
904 }
905}
906
907impl AsRef<[u8]> for RecordedHistorySegment {
908 #[inline]
909 fn as_ref(&self) -> &[u8] {
910 Record::slice_to_repr(&self.0).as_flattened().as_flattened()
911 }
912}
913
914impl AsMut<[u8]> for RecordedHistorySegment {
915 #[inline]
916 fn as_mut(&mut self) -> &mut [u8] {
917 Record::slice_mut_to_repr(&mut self.0)
918 .as_flattened_mut()
919 .as_flattened_mut()
920 }
921}
922
923impl RecordedHistorySegment {
924 pub const NUM_RAW_RECORDS: usize = 128;
926 pub const ERASURE_CODING_RATE: (usize, usize) = (1, 2);
928 pub const NUM_PIECES: usize =
931 Self::NUM_RAW_RECORDS * Self::ERASURE_CODING_RATE.1 / Self::ERASURE_CODING_RATE.0;
932 pub const SIZE: usize = Record::SIZE * Self::NUM_RAW_RECORDS;
938
939 #[inline]
941 #[cfg(feature = "alloc")]
942 pub fn new_boxed() -> Box<Self> {
943 unsafe { Box::<Self>::new_zeroed().assume_init() }
946 }
947}