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::iter::Step;
22use core::num::{NonZeroU32, NonZeroU64};
23use core::{fmt, mem};
24use derive_more::{
25 Add, AddAssign, Deref, DerefMut, Display, Div, DivAssign, From, Into, Mul, MulAssign, Sub,
26 SubAssign,
27};
28#[cfg(feature = "scale-codec")]
29use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
30#[cfg(feature = "serde")]
31use serde::{Deserialize, Deserializer, Serialize, Serializer};
32#[cfg(feature = "serde")]
33use serde_big_array::BigArray;
34
35#[derive(
37 Debug,
38 Display,
39 Default,
40 Copy,
41 Clone,
42 Ord,
43 PartialOrd,
44 Eq,
45 PartialEq,
46 Hash,
47 Add,
48 AddAssign,
49 Sub,
50 SubAssign,
51 Mul,
52 MulAssign,
53 Div,
54 DivAssign,
55 TrivialType,
56)]
57#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
58#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
59#[repr(C)]
60pub struct SuperSegmentIndex(u64);
61
62impl Step for SuperSegmentIndex {
63 #[inline]
64 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
65 u64::steps_between(&start.0, &end.0)
66 }
67
68 #[inline]
69 fn forward_checked(start: Self, count: usize) -> Option<Self> {
70 u64::forward_checked(start.0, count).map(Self)
71 }
72
73 #[inline(always)]
74 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
75 let (n, overflowing) = u64::forward_overflowing(start.0, count);
76 (Self(n), overflowing)
77 }
78
79 #[inline]
80 fn backward_checked(start: Self, count: usize) -> Option<Self> {
81 u64::backward_checked(start.0, count).map(Self)
82 }
83
84 #[inline(always)]
85 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
86 let (n, overflowing) = u64::backward_overflowing(start.0, count);
87 (Self(n), overflowing)
88 }
89}
90
91const impl From<u64> for SuperSegmentIndex {
92 #[inline(always)]
93 fn from(value: u64) -> Self {
94 Self(value)
95 }
96}
97
98const impl From<SuperSegmentIndex> for u64 {
99 #[inline(always)]
100 fn from(value: SuperSegmentIndex) -> Self {
101 value.0
102 }
103}
104
105impl SuperSegmentIndex {
106 pub const ZERO: Self = Self(0);
108 pub const ONE: Self = Self(1);
110
111 #[inline]
113 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
114 self.0.checked_sub(rhs.0).map(Self)
115 }
116
117 #[inline]
120 pub const fn saturating_sub(self, rhs: Self) -> Self {
121 Self(self.0.saturating_sub(rhs.0))
122 }
123}
124
125#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
127#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
128#[repr(C)]
129pub struct SuperSegmentRoot([u8; SuperSegmentRoot::SIZE]);
130
131impl fmt::Debug for SuperSegmentRoot {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 for byte in self.0 {
134 write!(f, "{byte:02x}")?;
135 }
136 Ok(())
137 }
138}
139
140const impl Default for SuperSegmentRoot {
141 #[inline]
142 fn default() -> Self {
143 Self([0; _])
144 }
145}
146
147#[cfg(feature = "serde")]
148#[derive(Serialize, Deserialize)]
149#[serde(transparent)]
150struct SuperSegmentRootBinary(#[serde(with = "BigArray")] [u8; SuperSegmentRoot::SIZE]);
151
152#[cfg(feature = "serde")]
153#[derive(Serialize, Deserialize)]
154#[serde(transparent)]
155struct SuperSegmentRootHex(#[serde(with = "hex")] [u8; SuperSegmentRoot::SIZE]);
156
157#[cfg(feature = "serde")]
158impl Serialize for SuperSegmentRoot {
159 #[inline]
160 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
161 where
162 S: Serializer,
163 {
164 if serializer.is_human_readable() {
165 SuperSegmentRootHex(self.0).serialize(serializer)
166 } else {
167 SuperSegmentRootBinary(self.0).serialize(serializer)
168 }
169 }
170}
171
172#[cfg(feature = "serde")]
173impl<'de> Deserialize<'de> for SuperSegmentRoot {
174 #[inline]
175 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
176 where
177 D: Deserializer<'de>,
178 {
179 Ok(Self(if deserializer.is_human_readable() {
180 SuperSegmentRootHex::deserialize(deserializer)?.0
181 } else {
182 SuperSegmentRootBinary::deserialize(deserializer)?.0
183 }))
184 }
185}
186
187impl AsRef<[u8]> for SuperSegmentRoot {
188 #[inline]
189 fn as_ref(&self) -> &[u8] {
190 &self.0
191 }
192}
193
194impl AsMut<[u8]> for SuperSegmentRoot {
195 #[inline]
196 fn as_mut(&mut self) -> &mut [u8] {
197 &mut self.0
198 }
199}
200
201impl SuperSegmentRoot {
202 pub const SIZE: usize = 32;
204 pub const MAX_SEGMENTS: u32 = 2u32.pow(20) - 1;
208}
209
210#[derive(
212 Debug,
213 Display,
214 Default,
215 Copy,
216 Clone,
217 Ord,
218 PartialOrd,
219 Eq,
220 PartialEq,
221 Hash,
222 From,
223 Into,
224 TrivialType,
225)]
226#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
227#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
228#[repr(C)]
229pub struct SegmentPosition(u32);
230
231impl From<SegmentPosition> for u64 {
232 #[inline]
233 fn from(original: SegmentPosition) -> Self {
234 Self::from(original.0)
235 }
236}
237
238impl SegmentPosition {
239 pub const ZERO: Self = Self(0);
241}
242
243#[derive(Debug, Clone, Copy, TrivialType)]
245#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
246#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
247#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
248#[repr(C)]
249pub struct ShardSegmentRootWithPosition {
250 pub shard_index: ShardIndex,
252 pub segment_position: SegmentPosition,
254 pub local_segment_index: LocalSegmentIndex,
256 pub segment_root: SegmentRoot,
258}
259
260impl ShardSegmentRootWithPosition {
261 #[inline(always)]
263 pub fn hash(&self) -> [u8; OUT_LEN] {
264 single_block_hash(self.as_bytes()).expect("Less than a single block worth of bytes; qed")
265 }
266}
267
268#[derive(Debug, Clone, Copy, Eq, PartialEq, TrivialType)]
270#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
271#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
272#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
273#[repr(C)]
274pub struct SuperSegmentHeader {
275 pub index: Unaligned<SuperSegmentIndex>,
277 pub root: SuperSegmentRoot,
279 pub prev_super_segment_header_hash: Blake3Hash,
281 pub max_segment_index: Unaligned<SegmentIndex>,
283 pub target_beacon_chain_block_number: Unaligned<BlockNumber>,
285 pub num_segments: u32,
288}
289
290#[cfg(feature = "alloc")]
292#[derive(Debug, Clone)]
293#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
296#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
297pub struct SuperSegment {
298 pub header: SuperSegmentHeader,
300 pub segment_roots: StdArc<[ShardSegmentRootWithPosition]>,
302}
303
304#[cfg(feature = "alloc")]
305impl SuperSegment {
306 pub fn new(
310 previous_header: &SuperSegmentHeader,
311 target_beacon_chain_block_number: BlockNumber,
312 segment_roots: StdArc<[ShardSegmentRootWithPosition]>,
313 ) -> Option<Self> {
314 let num_segments = u32::try_from(segment_roots.len()).ok()?;
315 let max_segment_index = SegmentIndex::from(
316 u64::from(previous_header.max_segment_index.as_inner()) + u64::from(num_segments),
317 );
318
319 let maybe_super_segment_root =
321 UnbalancedMerkleTree::compute_root_only::<
322 { u64::from(SuperSegmentRoot::MAX_SEGMENTS) },
323 _,
324 _,
325 >(segment_roots.iter().map(ShardSegmentRootWithPosition::hash))?;
326
327 Some(Self {
328 header: SuperSegmentHeader {
329 index: (previous_header.index.as_inner() + SuperSegmentIndex::ONE).into(),
330 root: SuperSegmentRoot::from(maybe_super_segment_root),
331 prev_super_segment_header_hash: Blake3Hash::from(
332 single_chunk_hash(previous_header.as_bytes())
333 .expect("Less than a single chunk worth of bytes; qed"),
334 ),
335 max_segment_index: max_segment_index.into(),
336 target_beacon_chain_block_number: target_beacon_chain_block_number.into(),
337 num_segments,
338 },
339 segment_roots,
340 })
341 }
342
343 pub fn proof_for_segment(&self, segment_position: SegmentPosition) -> Option<SegmentProof> {
345 let mut segment_proof = SegmentProof::default();
347 UnbalancedMerkleTree::compute_root_and_proof_in::<
348 { u64::from(SuperSegmentRoot::MAX_SEGMENTS) },
349 _,
350 _,
351 >(
352 self.segment_roots.iter().map(|shard_segment_root| {
353 single_block_hash(shard_segment_root.as_bytes())
354 .expect("Less than a single block worth of bytes; qed")
355 }),
356 u32::from(segment_position) as usize,
357 segment_proof.as_uninit_repr(),
358 )?;
359
360 Some(segment_proof)
361 }
362}
363
364#[derive(
366 Debug,
367 Display,
368 Default,
369 Copy,
370 Clone,
371 Ord,
372 PartialOrd,
373 Eq,
374 PartialEq,
375 Hash,
376 Add,
377 AddAssign,
378 Sub,
379 SubAssign,
380 Mul,
381 MulAssign,
382 Div,
383 DivAssign,
384 TrivialType,
385)]
386#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
387#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
388#[repr(C)]
389pub struct LocalSegmentIndex(u64);
390
391impl Step for LocalSegmentIndex {
392 #[inline]
393 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
394 u64::steps_between(&start.0, &end.0)
395 }
396
397 #[inline]
398 fn forward_checked(start: Self, count: usize) -> Option<Self> {
399 u64::forward_checked(start.0, count).map(Self)
400 }
401
402 #[inline(always)]
403 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
404 let (n, overflowing) = u64::forward_overflowing(start.0, count);
405 (Self(n), overflowing)
406 }
407
408 #[inline]
409 fn backward_checked(start: Self, count: usize) -> Option<Self> {
410 u64::backward_checked(start.0, count).map(Self)
411 }
412
413 #[inline(always)]
414 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
415 let (n, overflowing) = u64::backward_overflowing(start.0, count);
416 (Self(n), overflowing)
417 }
418}
419
420const impl From<u64> for LocalSegmentIndex {
421 #[inline(always)]
422 fn from(value: u64) -> Self {
423 Self(value)
424 }
425}
426
427const impl From<LocalSegmentIndex> for u64 {
428 #[inline(always)]
429 fn from(value: LocalSegmentIndex) -> Self {
430 value.0
431 }
432}
433
434impl LocalSegmentIndex {
435 pub const ZERO: Self = Self(0);
437 pub const ONE: Self = Self(1);
439
440 #[inline]
442 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
443 self.0.checked_sub(rhs.0).map(Self)
444 }
445
446 #[inline]
449 pub const fn saturating_sub(self, rhs: Self) -> Self {
450 Self(self.0.saturating_sub(rhs.0))
451 }
452}
453
454#[derive(
456 Debug,
457 Display,
458 Default,
459 Copy,
460 Clone,
461 Ord,
462 PartialOrd,
463 Eq,
464 PartialEq,
465 Hash,
466 Add,
467 AddAssign,
468 Sub,
469 SubAssign,
470 Mul,
471 MulAssign,
472 Div,
473 DivAssign,
474 TrivialType,
475)]
476#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
477#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
478#[repr(C)]
479pub struct SegmentIndex(u64);
480
481impl Step for SegmentIndex {
482 #[inline]
483 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
484 u64::steps_between(&start.0, &end.0)
485 }
486
487 #[inline]
488 fn forward_checked(start: Self, count: usize) -> Option<Self> {
489 u64::forward_checked(start.0, count).map(Self)
490 }
491
492 #[inline(always)]
493 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
494 let (n, overflowing) = u64::forward_overflowing(start.0, count);
495 (Self(n), overflowing)
496 }
497
498 #[inline]
499 fn backward_checked(start: Self, count: usize) -> Option<Self> {
500 u64::backward_checked(start.0, count).map(Self)
501 }
502
503 #[inline(always)]
504 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
505 let (n, overflowing) = u64::backward_overflowing(start.0, count);
506 (Self(n), overflowing)
507 }
508}
509
510const impl From<u64> for SegmentIndex {
511 #[inline(always)]
512 fn from(value: u64) -> Self {
513 Self(value)
514 }
515}
516
517const impl From<SegmentIndex> for u64 {
518 #[inline(always)]
519 fn from(value: SegmentIndex) -> Self {
520 value.0
521 }
522}
523
524impl SegmentIndex {
525 pub const ZERO: Self = Self(0);
527 pub const ONE: Self = Self(1);
529
530 #[inline]
532 pub const fn first_piece_index(&self) -> PieceIndex {
533 PieceIndex::from(self.0 * RecordedHistorySegment::NUM_PIECES as u64)
534 }
535
536 #[inline]
538 pub const fn last_piece_index(&self) -> PieceIndex {
539 PieceIndex::from((self.0 + 1) * RecordedHistorySegment::NUM_PIECES as u64 - 1)
540 }
541
542 #[inline]
544 pub fn segment_piece_indexes(&self) -> [PieceIndex; RecordedHistorySegment::NUM_PIECES] {
545 let mut piece_indices = [PieceIndex::ZERO; RecordedHistorySegment::NUM_PIECES];
546 (self.first_piece_index()..=self.last_piece_index())
547 .zip(&mut piece_indices)
548 .for_each(|(input, output)| {
549 *output = input;
550 });
551
552 piece_indices
553 }
554
555 #[inline]
557 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
558 self.0.checked_sub(rhs.0).map(Self)
559 }
560
561 #[inline]
564 pub const fn saturating_sub(self, rhs: Self) -> Self {
565 Self(self.0.saturating_sub(rhs.0))
566 }
567}
568
569#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
571#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
572#[repr(C)]
573pub struct SegmentRoot([u8; SegmentRoot::SIZE]);
574
575impl fmt::Debug for SegmentRoot {
576 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
577 for byte in self.0 {
578 write!(f, "{byte:02x}")?;
579 }
580 Ok(())
581 }
582}
583
584#[cfg(feature = "serde")]
585#[derive(Serialize, Deserialize)]
586#[serde(transparent)]
587struct SegmentRootBinary(#[serde(with = "BigArray")] [u8; SegmentRoot::SIZE]);
588
589#[cfg(feature = "serde")]
590#[derive(Serialize, Deserialize)]
591#[serde(transparent)]
592struct SegmentRootHex(#[serde(with = "hex")] [u8; SegmentRoot::SIZE]);
593
594#[cfg(feature = "serde")]
595impl Serialize for SegmentRoot {
596 #[inline]
597 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
598 where
599 S: Serializer,
600 {
601 if serializer.is_human_readable() {
602 SegmentRootHex(self.0).serialize(serializer)
603 } else {
604 SegmentRootBinary(self.0).serialize(serializer)
605 }
606 }
607}
608
609#[cfg(feature = "serde")]
610impl<'de> Deserialize<'de> for SegmentRoot {
611 #[inline]
612 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
613 where
614 D: Deserializer<'de>,
615 {
616 Ok(Self(if deserializer.is_human_readable() {
617 SegmentRootHex::deserialize(deserializer)?.0
618 } else {
619 SegmentRootBinary::deserialize(deserializer)?.0
620 }))
621 }
622}
623
624impl Default for SegmentRoot {
625 #[inline(always)]
626 fn default() -> Self {
627 Self([0; _])
628 }
629}
630
631impl AsRef<[u8]> for SegmentRoot {
632 #[inline(always)]
633 fn as_ref(&self) -> &[u8] {
634 &self.0
635 }
636}
637
638impl AsMut<[u8]> for SegmentRoot {
639 #[inline(always)]
640 fn as_mut(&mut self) -> &mut [u8] {
641 &mut self.0
642 }
643}
644
645impl SegmentRoot {
646 pub const SIZE: usize = 32;
648
649 #[inline(always)]
651 pub const fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
652 unsafe { mem::transmute(value) }
654 }
655
656 #[inline(always)]
658 pub const fn repr_from_slice(value: &[Self]) -> &[[u8; Self::SIZE]] {
659 unsafe { mem::transmute(value) }
661 }
662
663 pub fn is_valid(
665 &self,
666 shard_index: ShardIndex,
667 local_segment_index: LocalSegmentIndex,
668 segment_position: SegmentPosition,
669 segment_proof: &SegmentProof,
670 num_segments: u32,
671 super_segment_root: &SuperSegmentRoot,
672 ) -> bool {
673 let shard_segment_root = ShardSegmentRootWithPosition {
674 shard_index,
675 segment_position,
676 local_segment_index,
677 segment_root: *self,
678 };
679 let segment_proof = segment_proof
682 .split_once(|hash| hash == &[0; _])
683 .map_or(segment_proof.as_slice(), |(before, _after)| before);
684 UnbalancedMerkleTree::verify(
685 super_segment_root,
686 segment_proof,
687 u64::from(segment_position),
688 shard_segment_root.hash(),
689 u64::from(num_segments),
690 )
691 }
692}
693
694#[derive(
696 Debug,
697 Display,
698 Copy,
699 Clone,
700 Ord,
701 PartialOrd,
702 Eq,
703 PartialEq,
704 Hash,
705 From,
706 Into,
707 Deref,
708 DerefMut,
709 TrivialType,
710)]
711#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
712#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
713#[repr(C)]
714pub struct HistorySize(SegmentIndex);
716
717impl HistorySize {
718 pub const ONE: Self = Self(SegmentIndex::ZERO);
720
721 #[inline(always)]
723 pub const fn new(value: NonZeroU64) -> Self {
724 Self(SegmentIndex::from(value.get() - 1))
725 }
726
727 pub const fn as_segment_index(&self) -> SegmentIndex {
729 self.0
730 }
731
732 pub const fn as_non_zero_u64(&self) -> NonZeroU64 {
734 NonZeroU64::new(u64::from(self.0).saturating_add(1)).expect("Not zero; qed")
735 }
736
737 #[inline(always)]
739 pub const fn in_pieces(&self) -> NonZeroU64 {
740 NonZeroU64::new(
741 u64::from(self.0)
742 .saturating_add(1)
743 .saturating_mul(RecordedHistorySegment::NUM_PIECES as u64),
744 )
745 .expect("Not zero; qed")
746 }
747
748 #[inline(always)]
750 pub fn segment_index(&self) -> SegmentIndex {
751 self.0
752 }
753
754 #[inline(always)]
758 pub fn sector_expiration_check(&self, min_sector_lifetime: Self) -> Option<Self> {
759 self.as_non_zero_u64()
760 .checked_add(min_sector_lifetime.as_non_zero_u64().get())
761 .map(Self::new)
762 }
763}
764
765#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, TrivialType)]
767#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
768#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
769#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
770#[repr(C)]
771pub struct ArchivedBlockProgress {
772 bytes: u32,
774}
775
776impl Default for ArchivedBlockProgress {
777 #[inline(always)]
780 fn default() -> Self {
781 Self::new_complete()
782 }
783}
784
785impl ArchivedBlockProgress {
786 #[inline(always)]
788 pub const fn new_complete() -> Self {
789 Self { bytes: 0 }
790 }
791
792 #[inline(always)]
794 pub const fn new_partial(new_partial: NonZeroU32) -> Self {
795 Self {
796 bytes: new_partial.get(),
797 }
798 }
799
800 #[inline(always)]
802 pub const fn partial(&self) -> Option<NonZeroU32> {
803 NonZeroU32::new(self.bytes)
804 }
805}
806
807#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, TrivialType)]
809#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
810#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
811#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
812#[repr(C)]
813pub struct LastArchivedBlock {
814 pub number: Unaligned<BlockNumber>,
816 pub archived_progress: ArchivedBlockProgress,
818}
819
820impl LastArchivedBlock {
821 #[inline(always)]
823 pub fn partial_archived(&self) -> Option<NonZeroU32> {
824 self.archived_progress.partial()
825 }
826
827 #[inline(always)]
829 pub fn set_partial_archived(&mut self, new_partial: NonZeroU32) {
830 self.archived_progress = ArchivedBlockProgress::new_partial(new_partial);
831 }
832
833 #[inline(always)]
835 pub fn set_complete(&mut self) {
836 self.archived_progress = ArchivedBlockProgress::new_complete();
837 }
838
839 pub const fn number(&self) -> BlockNumber {
841 self.number.as_inner()
842 }
843}
844
845#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TrivialType)]
847#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
848#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
849#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
850#[repr(C)]
851pub struct SegmentHeader {
852 pub index: Unaligned<LocalSegmentIndex>,
854 pub root: SegmentRoot,
856 pub prev_segment_header_hash: Blake3Hash,
858 pub last_archived_block: LastArchivedBlock,
860}
861
862impl SegmentHeader {
863 #[inline(always)]
865 pub fn hash(&self) -> Blake3Hash {
866 const {
867 assert!(size_of::<Self>() <= CHUNK_LEN);
868 }
869 Blake3Hash::new(
870 single_chunk_hash(self.as_bytes())
871 .expect("Less than a single chunk worth of bytes; qed"),
872 )
873 }
874}
875
876#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
880#[repr(C)]
881pub struct RecordedHistorySegment([Record; Self::NUM_RAW_RECORDS]);
882
883impl fmt::Debug for RecordedHistorySegment {
884 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
885 f.debug_struct("RecordedHistorySegment")
886 .finish_non_exhaustive()
887 }
888}
889
890impl AsRef<[u8]> for RecordedHistorySegment {
891 #[inline]
892 fn as_ref(&self) -> &[u8] {
893 Record::slice_to_repr(&self.0).as_flattened().as_flattened()
894 }
895}
896
897impl AsMut<[u8]> for RecordedHistorySegment {
898 #[inline]
899 fn as_mut(&mut self) -> &mut [u8] {
900 Record::slice_mut_to_repr(&mut self.0)
901 .as_flattened_mut()
902 .as_flattened_mut()
903 }
904}
905
906impl RecordedHistorySegment {
907 pub const NUM_RAW_RECORDS: usize = 128;
909 pub const ERASURE_CODING_RATE: (usize, usize) = (1, 2);
911 pub const NUM_PIECES: usize =
914 Self::NUM_RAW_RECORDS * Self::ERASURE_CODING_RATE.1 / Self::ERASURE_CODING_RATE.0;
915 pub const SIZE: usize = Record::SIZE * Self::NUM_RAW_RECORDS;
921
922 #[inline]
924 #[cfg(feature = "alloc")]
925 pub fn new_boxed() -> Box<Self> {
926 unsafe { Box::<Self>::new_zeroed().assume_init() }
929 }
930}