1#[cfg(feature = "alloc")]
4mod archival_history_segment;
5
6use crate::block::BlockNumber;
7use crate::hashes::Blake3Hash;
8use crate::pieces::{PieceIndex, Record, SegmentProof};
9#[cfg(feature = "alloc")]
10pub use crate::segments::archival_history_segment::ArchivedHistorySegment;
11use crate::shard::ShardIndex;
12use ab_blake3::{single_block_hash, single_chunk_hash};
13use ab_io_type::trivial_type::TrivialType;
14use ab_io_type::unaligned::Unaligned;
15use ab_merkle_tree::unbalanced::UnbalancedMerkleTree;
16#[cfg(feature = "alloc")]
17use alloc::boxed::Box;
18#[cfg(feature = "alloc")]
19use alloc::sync::Arc as StdArc;
20use blake3::{CHUNK_LEN, OUT_LEN};
21use core::fmt;
22use core::iter::Step;
23#[cfg(feature = "alloc")]
24use core::mem::MaybeUninit;
25use core::num::{NonZeroU32, NonZeroU64};
26use derive_more::{
27 Add, AddAssign, Deref, DerefMut, Display, Div, DivAssign, From, Into, Mul, MulAssign, Sub,
28 SubAssign,
29};
30#[cfg(feature = "scale-codec")]
31use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
32#[cfg(feature = "serde")]
33use serde::{Deserialize, Deserializer, Serialize, Serializer};
34#[cfg(feature = "serde")]
35use serde_big_array::BigArray;
36use transparent_wrapper::TransparentWrapper;
37
38#[derive(
40 Debug,
41 Display,
42 Default,
43 Copy,
44 Clone,
45 Ord,
46 PartialOrd,
47 Eq,
48 PartialEq,
49 Hash,
50 Add,
51 AddAssign,
52 Sub,
53 SubAssign,
54 Mul,
55 MulAssign,
56 Div,
57 DivAssign,
58 TrivialType,
59)]
60#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62#[repr(C)]
63pub struct SuperSegmentIndex(u64);
64
65impl Step for SuperSegmentIndex {
66 #[inline]
67 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
68 u64::steps_between(&start.0, &end.0)
69 }
70
71 #[inline]
72 fn forward_checked(start: Self, count: usize) -> Option<Self> {
73 u64::forward_checked(start.0, count).map(Self)
74 }
75
76 #[inline(always)]
77 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
78 let (n, overflowing) = u64::forward_overflowing(start.0, count);
79 (Self(n), overflowing)
80 }
81
82 #[inline]
83 fn backward_checked(start: Self, count: usize) -> Option<Self> {
84 u64::backward_checked(start.0, count).map(Self)
85 }
86
87 #[inline(always)]
88 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
89 let (n, overflowing) = u64::backward_overflowing(start.0, count);
90 (Self(n), overflowing)
91 }
92}
93
94const impl From<u64> for SuperSegmentIndex {
95 #[inline(always)]
96 fn from(value: u64) -> Self {
97 Self(value)
98 }
99}
100
101const impl From<SuperSegmentIndex> for u64 {
102 #[inline(always)]
103 fn from(value: SuperSegmentIndex) -> Self {
104 value.0
105 }
106}
107
108impl SuperSegmentIndex {
109 pub const ZERO: Self = Self(0);
111 pub const ONE: Self = Self(1);
113
114 #[inline]
116 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
117 self.0.checked_sub(rhs.0).map(Self)
118 }
119
120 #[inline]
123 pub const fn saturating_sub(self, rhs: Self) -> Self {
124 Self(self.0.saturating_sub(rhs.0))
125 }
126}
127
128#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
130#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
131#[repr(C)]
132pub struct SuperSegmentRoot([u8; SuperSegmentRoot::SIZE]);
133
134impl fmt::Debug for SuperSegmentRoot {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 for byte in self.0 {
137 write!(f, "{byte:02x}")?;
138 }
139 Ok(())
140 }
141}
142
143const impl Default for SuperSegmentRoot {
144 #[inline]
145 fn default() -> Self {
146 Self([0; _])
147 }
148}
149
150#[cfg(feature = "serde")]
151#[derive(Serialize, Deserialize)]
152#[serde(transparent)]
153struct SuperSegmentRootBinary(#[serde(with = "BigArray")] [u8; SuperSegmentRoot::SIZE]);
154
155#[cfg(feature = "serde")]
156#[derive(Serialize, Deserialize)]
157#[serde(transparent)]
158struct SuperSegmentRootHex(#[serde(with = "hex")] [u8; SuperSegmentRoot::SIZE]);
159
160#[cfg(feature = "serde")]
161impl Serialize for SuperSegmentRoot {
162 #[inline]
163 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
164 where
165 S: Serializer,
166 {
167 if serializer.is_human_readable() {
168 SuperSegmentRootHex(self.0).serialize(serializer)
169 } else {
170 SuperSegmentRootBinary(self.0).serialize(serializer)
171 }
172 }
173}
174
175#[cfg(feature = "serde")]
176impl<'de> Deserialize<'de> for SuperSegmentRoot {
177 #[inline]
178 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
179 where
180 D: Deserializer<'de>,
181 {
182 Ok(Self(if deserializer.is_human_readable() {
183 SuperSegmentRootHex::deserialize(deserializer)?.0
184 } else {
185 SuperSegmentRootBinary::deserialize(deserializer)?.0
186 }))
187 }
188}
189
190impl AsRef<[u8]> for SuperSegmentRoot {
191 #[inline]
192 fn as_ref(&self) -> &[u8] {
193 &self.0
194 }
195}
196
197impl AsMut<[u8]> for SuperSegmentRoot {
198 #[inline]
199 fn as_mut(&mut self) -> &mut [u8] {
200 &mut self.0
201 }
202}
203
204impl SuperSegmentRoot {
205 pub const SIZE: usize = 32;
207 pub const MAX_SEGMENTS: u32 = 2u32.pow(20) - 1;
211}
212
213#[derive(
215 Debug,
216 Display,
217 Default,
218 Copy,
219 Clone,
220 Ord,
221 PartialOrd,
222 Eq,
223 PartialEq,
224 Hash,
225 From,
226 Into,
227 TrivialType,
228)]
229#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
230#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
231#[repr(C)]
232pub struct SegmentPosition(u32);
233
234impl From<SegmentPosition> for u64 {
235 #[inline]
236 fn from(original: SegmentPosition) -> Self {
237 Self::from(original.0)
238 }
239}
240
241impl SegmentPosition {
242 pub const ZERO: Self = Self(0);
244}
245
246#[derive(Debug, Clone, Copy, TrivialType)]
248#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
250#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
251#[repr(C)]
252pub struct ShardSegmentRootWithPosition {
253 pub shard_index: ShardIndex,
255 pub segment_position: SegmentPosition,
257 pub local_segment_index: LocalSegmentIndex,
259 pub segment_root: SegmentRoot,
261}
262
263impl ShardSegmentRootWithPosition {
264 #[inline(always)]
266 pub fn hash(&self) -> [u8; OUT_LEN] {
267 single_block_hash(self.as_bytes()).expect("Less than a single block worth of bytes; qed")
268 }
269}
270
271#[derive(Debug, Clone, Copy, Eq, PartialEq, TrivialType)]
273#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
274#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
275#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
276#[repr(C)]
277pub struct SuperSegmentHeader {
278 pub index: Unaligned<SuperSegmentIndex>,
280 pub root: SuperSegmentRoot,
282 pub prev_super_segment_header_hash: Blake3Hash,
284 pub max_segment_index: Unaligned<SegmentIndex>,
286 pub target_beacon_chain_block_number: Unaligned<BlockNumber>,
288 pub num_segments: u32,
291}
292
293#[cfg(feature = "alloc")]
295#[derive(Debug, Clone)]
296#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
299#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
300pub struct SuperSegment {
301 pub header: SuperSegmentHeader,
303 pub segment_roots: StdArc<[ShardSegmentRootWithPosition]>,
305}
306
307#[cfg(feature = "alloc")]
308impl SuperSegment {
309 pub fn new(
313 previous_header: &SuperSegmentHeader,
314 target_beacon_chain_block_number: BlockNumber,
315 segment_roots: StdArc<[ShardSegmentRootWithPosition]>,
316 ) -> Option<Self> {
317 let num_segments = u32::try_from(segment_roots.len()).ok()?;
318 let max_segment_index = SegmentIndex::from(
319 u64::from(previous_header.max_segment_index.as_inner()) + u64::from(num_segments),
320 );
321
322 let maybe_super_segment_root =
324 UnbalancedMerkleTree::compute_root_only::<
325 { u64::from(SuperSegmentRoot::MAX_SEGMENTS) },
326 _,
327 _,
328 >(segment_roots.iter().map(ShardSegmentRootWithPosition::hash))?;
329
330 Some(Self {
331 header: SuperSegmentHeader {
332 index: (previous_header.index.as_inner() + SuperSegmentIndex::ONE).into(),
333 root: SuperSegmentRoot::from(maybe_super_segment_root),
334 prev_super_segment_header_hash: Blake3Hash::from(
335 single_chunk_hash(previous_header.as_bytes())
336 .expect("Less than a single chunk worth of bytes; qed"),
337 ),
338 max_segment_index: max_segment_index.into(),
339 target_beacon_chain_block_number: target_beacon_chain_block_number.into(),
340 num_segments,
341 },
342 segment_roots,
343 })
344 }
345
346 pub fn proof_for_segment(&self, segment_position: SegmentPosition) -> Option<SegmentProof> {
348 let mut segment_proof = [MaybeUninit::uninit(); _];
350 let (_root, proof_hashes) = UnbalancedMerkleTree::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 = segment_proof
695 .split_once(|hash| hash == &[0; _])
696 .map_or(segment_proof.as_slice(), |(before, _after)| before);
697 UnbalancedMerkleTree::verify(
698 super_segment_root,
699 segment_proof,
700 u64::from(segment_position),
701 shard_segment_root.hash(),
702 u64::from(num_segments),
703 )
704 }
705}
706
707#[derive(
709 Debug,
710 Display,
711 Copy,
712 Clone,
713 Ord,
714 PartialOrd,
715 Eq,
716 PartialEq,
717 Hash,
718 From,
719 Into,
720 Deref,
721 DerefMut,
722 TrivialType,
723)]
724#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
725#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
726#[repr(C)]
727pub struct HistorySize(SegmentIndex);
729
730impl HistorySize {
731 pub const ONE: Self = Self(SegmentIndex::ZERO);
733
734 #[inline(always)]
736 pub const fn new(value: NonZeroU64) -> Self {
737 Self(SegmentIndex::from(value.get() - 1))
738 }
739
740 pub const fn as_segment_index(&self) -> SegmentIndex {
742 self.0
743 }
744
745 pub const fn as_non_zero_u64(&self) -> NonZeroU64 {
747 NonZeroU64::new(u64::from(self.0).saturating_add(1)).expect("Not zero; qed")
748 }
749
750 #[inline(always)]
752 pub const fn in_pieces(&self) -> NonZeroU64 {
753 NonZeroU64::new(
754 u64::from(self.0)
755 .saturating_add(1)
756 .saturating_mul(RecordedHistorySegment::NUM_PIECES as u64),
757 )
758 .expect("Not zero; qed")
759 }
760
761 #[inline(always)]
763 pub fn segment_index(&self) -> SegmentIndex {
764 self.0
765 }
766
767 #[inline(always)]
771 pub fn sector_expiration_check(&self, min_sector_lifetime: Self) -> Option<Self> {
772 self.as_non_zero_u64()
773 .checked_add(min_sector_lifetime.as_non_zero_u64().get())
774 .map(Self::new)
775 }
776}
777
778#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, TrivialType)]
780#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
781#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
782#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
783#[repr(C)]
784pub struct ArchivedBlockProgress {
785 bytes: u32,
787}
788
789impl Default for ArchivedBlockProgress {
790 #[inline(always)]
793 fn default() -> Self {
794 Self::new_complete()
795 }
796}
797
798impl ArchivedBlockProgress {
799 #[inline(always)]
801 pub const fn new_complete() -> Self {
802 Self { bytes: 0 }
803 }
804
805 #[inline(always)]
807 pub const fn new_partial(new_partial: NonZeroU32) -> Self {
808 Self {
809 bytes: new_partial.get(),
810 }
811 }
812
813 #[inline(always)]
815 pub const fn partial(&self) -> Option<NonZeroU32> {
816 NonZeroU32::new(self.bytes)
817 }
818}
819
820#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, TrivialType)]
822#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
823#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
824#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
825#[repr(C)]
826pub struct LastArchivedBlock {
827 pub number: Unaligned<BlockNumber>,
829 pub archived_progress: ArchivedBlockProgress,
831}
832
833impl LastArchivedBlock {
834 #[inline(always)]
836 pub fn partial_archived(&self) -> Option<NonZeroU32> {
837 self.archived_progress.partial()
838 }
839
840 #[inline(always)]
842 pub fn set_partial_archived(&mut self, new_partial: NonZeroU32) {
843 self.archived_progress = ArchivedBlockProgress::new_partial(new_partial);
844 }
845
846 #[inline(always)]
848 pub fn set_complete(&mut self) {
849 self.archived_progress = ArchivedBlockProgress::new_complete();
850 }
851
852 pub const fn number(&self) -> BlockNumber {
854 self.number.as_inner()
855 }
856}
857
858#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TrivialType)]
860#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
861#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
862#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
863#[repr(C)]
864pub struct SegmentHeader {
865 pub index: Unaligned<LocalSegmentIndex>,
867 pub root: SegmentRoot,
869 pub prev_segment_header_hash: Blake3Hash,
871 pub last_archived_block: LastArchivedBlock,
873}
874
875impl SegmentHeader {
876 #[inline(always)]
878 pub fn hash(&self) -> Blake3Hash {
879 const {
880 assert!(size_of::<Self>() <= CHUNK_LEN);
881 }
882 Blake3Hash::new(
883 single_chunk_hash(self.as_bytes())
884 .expect("Less than a single chunk worth of bytes; qed"),
885 )
886 }
887}
888
889#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
893#[repr(C)]
894pub struct RecordedHistorySegment([Record; Self::NUM_RAW_RECORDS]);
895
896impl fmt::Debug for RecordedHistorySegment {
897 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
898 f.debug_struct("RecordedHistorySegment")
899 .finish_non_exhaustive()
900 }
901}
902
903impl AsRef<[u8]> for RecordedHistorySegment {
904 #[inline]
905 fn as_ref(&self) -> &[u8] {
906 Record::slice_to_repr(&self.0).as_flattened().as_flattened()
907 }
908}
909
910impl AsMut<[u8]> for RecordedHistorySegment {
911 #[inline]
912 fn as_mut(&mut self) -> &mut [u8] {
913 Record::slice_mut_to_repr(&mut self.0)
914 .as_flattened_mut()
915 .as_flattened_mut()
916 }
917}
918
919impl RecordedHistorySegment {
920 pub const NUM_RAW_RECORDS: usize = 128;
922 pub const ERASURE_CODING_RATE: (usize, usize) = (1, 2);
924 pub const NUM_PIECES: usize =
927 Self::NUM_RAW_RECORDS * Self::ERASURE_CODING_RATE.1 / Self::ERASURE_CODING_RATE.0;
928 pub const SIZE: usize = Record::SIZE * Self::NUM_RAW_RECORDS;
934
935 #[inline]
937 #[cfg(feature = "alloc")]
938 pub fn new_boxed() -> Box<Self> {
939 unsafe { Box::<Self>::new_zeroed().assume_init() }
942 }
943}