1#[cfg(feature = "alloc")]
4mod cow_bytes;
5#[cfg(feature = "alloc")]
6mod flat_pieces;
7#[cfg(feature = "alloc")]
8mod piece;
9#[cfg(all(test, feature = "alloc"))]
10mod tests;
11
12#[cfg(feature = "alloc")]
13pub use crate::pieces::flat_pieces::FlatPieces;
14#[cfg(feature = "alloc")]
15pub use crate::pieces::piece::Piece;
16use crate::sectors::SBucket;
17use crate::segments::{
18 LocalSegmentIndex, RecordedHistorySegment, SegmentIndex, SegmentPosition, SegmentRoot,
19 SuperSegmentIndex, SuperSegmentRoot,
20};
21use crate::shard::ShardIndex;
22#[cfg(feature = "serde")]
23use ::serde::{Deserialize, Deserializer, Serialize, Serializer};
24use ab_io_type::trivial_type::{AnyBitPattern, TrivialType};
25use ab_io_type::unaligned::Unaligned;
26use ab_merkle_tree::blake3::BalancedMerkleTree;
27#[cfg(feature = "alloc")]
28use alloc::boxed::Box;
29#[cfg(feature = "alloc")]
30use alloc::vec::Vec;
31use array_reshape::{Flatten, Unflatten};
32use blake3::OUT_LEN;
33use core::array::TryFromSliceError;
34use core::hash::Hash;
35use core::iter::Step;
36use core::ops::{Index, IndexMut};
37use core::{fmt, mem};
38use derive_more::{
39 Add, AddAssign, AsMut, AsRef, Deref, DerefMut, Display, Div, DivAssign, From, Into, Mul,
40 MulAssign, Sub, SubAssign,
41};
42#[cfg(feature = "scale-codec")]
43use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
44#[cfg(feature = "serde")]
45use serde_big_array::BigArray;
46use transparent_wrapper::TransparentWrapper;
47
48#[derive(
50 Debug,
51 Display,
52 Default,
53 Copy,
54 Clone,
55 Ord,
56 PartialOrd,
57 Eq,
58 PartialEq,
59 Hash,
60 Add,
61 AddAssign,
62 Sub,
63 SubAssign,
64 Mul,
65 MulAssign,
66 Div,
67 DivAssign,
68)]
69#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
71#[repr(C)]
72pub struct PieceIndex(u64);
73
74impl Step for PieceIndex {
75 #[inline]
76 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
77 u64::steps_between(&start.0, &end.0)
78 }
79
80 #[inline]
81 fn forward_checked(start: Self, count: usize) -> Option<Self> {
82 u64::forward_checked(start.0, count).map(Self)
83 }
84
85 #[inline(always)]
86 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
87 let (n, overflowing) = u64::forward_overflowing(start.0, count);
88 (Self(n), overflowing)
89 }
90
91 #[inline]
92 fn backward_checked(start: Self, count: usize) -> Option<Self> {
93 u64::backward_checked(start.0, count).map(Self)
94 }
95
96 #[inline(always)]
97 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
98 let (n, overflowing) = u64::backward_overflowing(start.0, count);
99 (Self(n), overflowing)
100 }
101}
102
103const impl From<u64> for PieceIndex {
104 #[inline(always)]
105 fn from(value: u64) -> Self {
106 Self(value)
107 }
108}
109
110const impl From<PieceIndex> for u64 {
111 #[inline(always)]
112 fn from(value: PieceIndex) -> Self {
113 value.0
114 }
115}
116
117impl PieceIndex {
118 pub const SIZE: usize = size_of::<u64>();
120 pub const ZERO: PieceIndex = PieceIndex(0);
122 pub const ONE: PieceIndex = PieceIndex(1);
124
125 #[inline]
127 pub const fn from_bytes(bytes: [u8; Self::SIZE]) -> Self {
128 Self(u64::from_le_bytes(bytes))
129 }
130
131 #[inline]
133 pub const fn to_bytes(self) -> [u8; Self::SIZE] {
134 self.0.to_le_bytes()
135 }
136
137 #[inline]
139 pub const fn segment_index(&self) -> SegmentIndex {
140 SegmentIndex::from(self.0 / RecordedHistorySegment::NUM_PIECES as u64)
141 }
142
143 #[inline]
145 pub fn position(&self) -> PiecePosition {
146 PiecePosition::from((self.0 % RecordedHistorySegment::NUM_PIECES as u64) as u8)
147 }
148}
149
150const {
151 assert!(RecordedHistorySegment::NUM_PIECES == usize::from(u8::MAX) + 1);
153}
154
155#[derive(
157 Debug,
158 Display,
159 Default,
160 Copy,
161 Clone,
162 Ord,
163 PartialOrd,
164 Eq,
165 PartialEq,
166 Hash,
167 From,
168 Into,
169 TrivialType,
170)]
171#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
172#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
173#[repr(C)]
174pub struct PiecePosition(u8);
175
176impl Step for PiecePosition {
177 #[inline]
178 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
179 u8::steps_between(&start.0, &end.0)
180 }
181
182 #[inline]
183 fn forward_checked(start: Self, count: usize) -> Option<Self> {
184 u8::forward_checked(start.0, count).map(Self)
185 }
186
187 #[inline(always)]
188 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
189 let (n, overflowing) = u8::forward_overflowing(start.0, count);
190 (Self(n), overflowing)
191 }
192
193 #[inline]
194 fn backward_checked(start: Self, count: usize) -> Option<Self> {
195 u8::backward_checked(start.0, count).map(Self)
196 }
197
198 #[inline(always)]
199 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
200 let (n, overflowing) = u8::backward_overflowing(start.0, count);
201 (Self(n), overflowing)
202 }
203}
204
205impl From<PiecePosition> for u16 {
206 #[inline]
207 fn from(original: PiecePosition) -> Self {
208 Self::from(original.0)
209 }
210}
211
212impl From<PiecePosition> for u32 {
213 #[inline]
214 fn from(original: PiecePosition) -> Self {
215 Self::from(original.0)
216 }
217}
218
219impl From<PiecePosition> for u64 {
220 #[inline]
221 fn from(original: PiecePosition) -> Self {
222 Self::from(original.0)
223 }
224}
225
226impl From<PiecePosition> for usize {
227 #[inline]
228 fn from(original: PiecePosition) -> Self {
229 usize::from(original.0)
230 }
231}
232
233#[derive(
235 Debug,
236 Display,
237 Default,
238 Copy,
239 Clone,
240 Ord,
241 PartialOrd,
242 Eq,
243 PartialEq,
244 Hash,
245 From,
246 Into,
247 Add,
248 AddAssign,
249 Sub,
250 SubAssign,
251 Mul,
252 MulAssign,
253 Div,
254 DivAssign,
255 TrivialType,
256)]
257#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
259#[repr(C)]
260pub struct PieceOffset(u16);
261
262impl Step for PieceOffset {
263 #[inline]
264 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
265 u16::steps_between(&start.0, &end.0)
266 }
267
268 #[inline]
269 fn forward_checked(start: Self, count: usize) -> Option<Self> {
270 u16::forward_checked(start.0, count).map(Self)
271 }
272
273 #[inline(always)]
274 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
275 let (n, overflowing) = u16::forward_overflowing(start.0, count);
276 (Self(n), overflowing)
277 }
278
279 #[inline]
280 fn backward_checked(start: Self, count: usize) -> Option<Self> {
281 u16::backward_checked(start.0, count).map(Self)
282 }
283
284 #[inline(always)]
285 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
286 let (n, overflowing) = u16::backward_overflowing(start.0, count);
287 (Self(n), overflowing)
288 }
289}
290
291impl From<PieceOffset> for u32 {
292 #[inline]
293 fn from(original: PieceOffset) -> Self {
294 Self::from(original.0)
295 }
296}
297
298impl From<PieceOffset> for u64 {
299 #[inline]
300 fn from(original: PieceOffset) -> Self {
301 Self::from(original.0)
302 }
303}
304
305impl From<PieceOffset> for usize {
306 #[inline]
307 fn from(original: PieceOffset) -> Self {
308 usize::from(original.0)
309 }
310}
311
312impl PieceOffset {
313 pub const ZERO: Self = Self(0);
315 pub const ONE: Self = Self(1);
317 pub const SIZE: usize = size_of::<u16>();
319
320 #[inline]
322 pub const fn to_bytes(self) -> [u8; Self::SIZE] {
323 self.0.to_le_bytes()
324 }
325}
326
327#[derive(
329 Default,
330 Copy,
331 Clone,
332 Eq,
333 PartialEq,
334 Ord,
335 PartialOrd,
336 Hash,
337 From,
338 Into,
339 AsRef,
340 AsMut,
341 Deref,
342 DerefMut,
343 TrivialType,
344 TransparentWrapper,
345)]
346#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
347#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
348#[cfg_attr(feature = "serde", serde(transparent))]
349#[repr(C)]
350pub struct RecordChunk([u8; RecordChunk::SIZE]);
351
352impl fmt::Debug for RecordChunk {
353 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354 for byte in self.0 {
355 write!(f, "{byte:02x}")?;
356 }
357 Ok(())
358 }
359}
360
361impl RecordChunk {
362 pub const SIZE: usize = 32;
364
365 #[inline]
367 pub fn slice_to_repr(value: &[Self]) -> &[[u8; Self::SIZE]] {
368 Self::peel_slice(value)
369 }
370
371 #[inline]
373 pub fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
374 Self::wrap_slice(value)
375 }
376
377 #[inline]
380 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; Self::SIZE]] {
381 Self::peel_slice_mut(value)
382 }
383
384 #[inline]
387 pub fn slice_mut_from_repr(value: &mut [[u8; Self::SIZE]]) -> &mut [Self] {
388 Self::wrap_slice_mut(value)
389 }
390
391 #[inline(always)]
393 pub const fn array_to_repr<const N: usize>(value: &[Self; N]) -> &[[u8; Self::SIZE]; N] {
394 unsafe { mem::transmute(value) }
397 }
398
399 #[inline(always)]
401 pub const fn array_from_repr<const N: usize>(value: &[[u8; Self::SIZE]; N]) -> &[Self; N] {
402 unsafe { mem::transmute(value) }
405 }
406
407 #[inline(always)]
410 pub const fn array_mut_to_repr<const N: usize>(
411 value: &mut [Self; N],
412 ) -> &mut [[u8; Self::SIZE]; N] {
413 unsafe { mem::transmute(value) }
416 }
417
418 #[inline(always)]
421 pub const fn array_mut_from_repr<const N: usize>(
422 value: &mut [[u8; Self::SIZE]; N],
423 ) -> &mut [Self; N] {
424 unsafe { mem::transmute(value) }
427 }
428}
429
430#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut, TrivialType, TransparentWrapper)]
434#[repr(C)]
435pub struct Record([[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]);
436
437impl fmt::Debug for Record {
438 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
439 for byte in self.0.as_flattened() {
440 write!(f, "{byte:02x}")?;
441 }
442 Ok(())
443 }
444}
445
446impl AsRef<[u8]> for Record {
447 #[inline]
448 fn as_ref(&self) -> &[u8] {
449 self.0.as_flattened()
450 }
451}
452
453impl AsRef<[u8; Record::SIZE]> for Record {
454 #[inline(always)]
455 fn as_ref(&self) -> &[u8; Record::SIZE] {
456 self.as_bytes()
457 }
458}
459
460impl AsMut<[u8; Record::SIZE]> for Record {
461 #[inline(always)]
462 fn as_mut(&mut self) -> &mut [u8; Record::SIZE] {
463 self.as_bytes_mut()
464 }
465}
466
467impl AsMut<[u8]> for Record {
468 #[inline]
469 fn as_mut(&mut self) -> &mut [u8] {
470 self.0.as_flattened_mut()
471 }
472}
473
474impl<'a> From<&'a Record> for &'a [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
475 #[inline]
476 fn from(value: &'a Record) -> Self {
477 value.peel_ref()
478 }
479}
480
481impl<'a> From<&'a [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &'a Record {
482 #[inline]
483 fn from(value: &'a [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
484 Record::wrap_ref(value)
485 }
486}
487
488impl<'a> From<&'a mut Record> for &'a mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
489 #[inline]
490 fn from(value: &'a mut Record) -> Self {
491 value.peel_mut()
492 }
493}
494
495impl<'a> From<&'a mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &'a mut Record {
496 #[inline]
497 fn from(value: &'a mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
498 Record::wrap_mut(value)
499 }
500}
501
502impl Record {
503 pub const NUM_CHUNKS: usize = 2usize.pow(15);
505 pub const NUM_S_BUCKETS: usize = Record::NUM_CHUNKS
509 * RecordedHistorySegment::ERASURE_CODING_RATE.1
510 / RecordedHistorySegment::ERASURE_CODING_RATE.0;
511 pub const SIZE: usize = RecordChunk::SIZE * Record::NUM_CHUNKS;
513
514 #[inline]
516 #[cfg(feature = "alloc")]
517 pub fn new_boxed() -> Box<Self> {
518 unsafe { Box::new_zeroed().assume_init() }
521 }
522
523 #[inline]
525 #[cfg(feature = "alloc")]
526 pub fn new_zero_vec(length: usize) -> Vec<Self> {
527 unsafe { Box::<[Self]>::new_zeroed_slice(length).assume_init() }.into_vec()
531 }
532
533 #[inline(always)]
536 pub fn slice_to_repr(value: &[Self]) -> &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
537 Self::peel_slice(value)
538 }
539
540 #[inline(always)]
543 pub fn slice_from_repr(value: &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]]) -> &[Self] {
544 Self::wrap_slice(value)
545 }
546
547 #[inline(always)]
550 pub fn slice_mut_to_repr(
551 value: &mut [Self],
552 ) -> &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
553 Self::peel_slice_mut(value)
554 }
555
556 #[inline(always)]
559 pub fn slice_mut_from_repr(
560 value: &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]],
561 ) -> &mut [Self] {
562 Self::wrap_slice_mut(value)
563 }
564
565 #[inline(always)]
568 pub const fn array_to_repr<const N: usize>(
569 value: &[Self; N],
570 ) -> &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]; N] {
571 unsafe { mem::transmute(value) }
574 }
575
576 #[inline(always)]
579 pub const fn array_from_repr<const N: usize>(
580 value: &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]; N],
581 ) -> &[Self; N] {
582 unsafe { mem::transmute(value) }
585 }
586
587 #[inline(always)]
590 pub const fn array_mut_to_repr<const N: usize>(
591 value: &mut [Self; N],
592 ) -> &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]; N] {
593 unsafe { mem::transmute(value) }
596 }
597
598 #[inline(always)]
601 pub const fn array_mut_from_repr<const N: usize>(
602 value: &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]; N],
603 ) -> &mut [Self; N] {
604 unsafe { mem::transmute(value) }
607 }
608
609 #[inline(always)]
611 pub fn source_chunks_root(&self) -> RecordChunksRoot {
612 RecordChunksRoot(BalancedMerkleTree::compute_root_only(self))
613 }
614}
615
616#[derive(Debug, Copy, Clone, Eq, PartialEq)]
621#[repr(C)]
622pub struct ExtendedRecord {
623 pub source: Record,
625 pub parity: Record,
627}
628
629const {
630 assert!(size_of::<ExtendedRecord>() == size_of::<[Record; 2]>());
632 assert!(align_of::<ExtendedRecord>() == align_of::<[Record; 2]>());
633 assert!(usize::from(u16::from(SBucket::MAX)) == Record::NUM_S_BUCKETS - 1);
635}
636
637impl Index<SBucket> for ExtendedRecord {
638 type Output = RecordChunk;
639
640 #[inline(always)]
641 fn index(&self, index: SBucket) -> &Self::Output {
642 self.as_s_buckets()
643 .get(usize::from(index))
644 .expect("S-bucket is at most `SBucket::MAX`, which is within range, checked above; qed")
645 }
646}
647
648impl IndexMut<SBucket> for ExtendedRecord {
649 #[inline(always)]
650 fn index_mut(&mut self, index: SBucket) -> &mut Self::Output {
651 self.as_s_buckets_mut()
652 .get_mut(usize::from(index))
653 .expect("S-bucket is at most `SBucket::MAX`, which is within range, checked above; qed")
654 }
655}
656
657impl ExtendedRecord {
658 #[inline]
660 #[cfg(feature = "alloc")]
661 pub fn new_boxed() -> Box<Self> {
662 unsafe { Box::new_zeroed().assume_init() }
665 }
666
667 #[inline(always)]
669 pub const fn as_records(&self) -> &[Record; 2] {
670 unsafe { mem::transmute(self) }
673 }
674
675 #[inline(always)]
677 pub const fn as_records_mut(&mut self) -> &mut [Record; 2] {
678 unsafe { mem::transmute(self) }
681 }
682
683 #[inline(always)]
685 pub fn as_s_buckets(&self) -> &[RecordChunk; Record::NUM_S_BUCKETS] {
686 RecordChunk::array_from_repr(Record::array_to_repr(self.as_records()).flatten_ref())
687 }
688
689 #[inline(always)]
691 pub fn as_s_buckets_mut(&mut self) -> &mut [RecordChunk; Record::NUM_S_BUCKETS] {
692 RecordChunk::array_mut_from_repr(
693 Record::array_mut_to_repr(self.as_records_mut()).flatten_mut(),
694 )
695 }
696}
697
698#[derive(
702 Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType, TransparentWrapper,
703)]
704#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
705#[repr(C)]
706pub struct RecordRoot([u8; RecordRoot::SIZE]);
707
708impl fmt::Debug for RecordRoot {
709 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
710 for byte in self.0 {
711 write!(f, "{byte:02x}")?;
712 }
713 Ok(())
714 }
715}
716
717#[cfg(feature = "serde")]
718#[derive(Serialize, Deserialize)]
719#[serde(transparent)]
720struct RecordRootBinary(#[serde(with = "BigArray")] [u8; RecordRoot::SIZE]);
721
722#[cfg(feature = "serde")]
723#[derive(Serialize, Deserialize)]
724#[serde(transparent)]
725struct RecordRootHex(#[serde(with = "hex")] [u8; RecordRoot::SIZE]);
726
727#[cfg(feature = "serde")]
728impl Serialize for RecordRoot {
729 #[inline]
730 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
731 where
732 S: Serializer,
733 {
734 if serializer.is_human_readable() {
735 RecordRootHex(self.0).serialize(serializer)
736 } else {
737 RecordRootBinary(self.0).serialize(serializer)
738 }
739 }
740}
741
742#[cfg(feature = "serde")]
743impl<'de> Deserialize<'de> for RecordRoot {
744 #[inline]
745 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
746 where
747 D: Deserializer<'de>,
748 {
749 Ok(Self(if deserializer.is_human_readable() {
750 RecordRootHex::deserialize(deserializer)?.0
751 } else {
752 RecordRootBinary::deserialize(deserializer)?.0
753 }))
754 }
755}
756
757impl Default for RecordRoot {
758 #[inline]
759 fn default() -> Self {
760 Self([0; _])
761 }
762}
763
764impl TryFrom<&[u8]> for RecordRoot {
765 type Error = TryFromSliceError;
766
767 #[inline]
768 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
769 <[u8; Self::SIZE]>::try_from(slice).map(Self)
770 }
771}
772
773impl AsRef<[u8]> for RecordRoot {
774 #[inline]
775 fn as_ref(&self) -> &[u8] {
776 &self.0
777 }
778}
779
780impl AsMut<[u8]> for RecordRoot {
781 #[inline]
782 fn as_mut(&mut self) -> &mut [u8] {
783 &mut self.0
784 }
785}
786
787impl<'a> From<&'a RecordRoot> for &'a [u8; RecordRoot::SIZE] {
788 #[inline]
789 fn from(value: &'a RecordRoot) -> Self {
790 value.peel_ref()
791 }
792}
793
794impl<'a> From<&'a [u8; RecordRoot::SIZE]> for &'a RecordRoot {
795 #[inline]
796 fn from(value: &'a [u8; RecordRoot::SIZE]) -> Self {
797 RecordRoot::wrap_ref(value)
798 }
799}
800
801impl<'a> From<&'a mut RecordRoot> for &'a mut [u8; RecordRoot::SIZE] {
802 #[inline]
803 fn from(value: &'a mut RecordRoot) -> Self {
804 value.peel_mut()
805 }
806}
807
808impl<'a> From<&'a mut [u8; RecordRoot::SIZE]> for &'a mut RecordRoot {
809 #[inline]
810 fn from(value: &'a mut [u8; RecordRoot::SIZE]) -> Self {
811 RecordRoot::wrap_mut(value)
812 }
813}
814
815impl RecordRoot {
816 pub const SIZE: usize = 32;
818
819 pub fn is_valid(
821 &self,
822 segment_root: &SegmentRoot,
823 record_proof: &RecordProof,
824 position: PiecePosition,
825 ) -> bool {
826 BalancedMerkleTree::<{ RecordedHistorySegment::NUM_PIECES }>::verify(
827 segment_root,
828 record_proof,
829 usize::from(position),
830 self.0,
831 )
832 }
833}
834
835#[derive(
837 Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType, TransparentWrapper,
838)]
839#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
840#[repr(C)]
841pub struct RecordChunksRoot([u8; RecordChunksRoot::SIZE]);
842
843impl fmt::Debug for RecordChunksRoot {
844 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
845 for byte in self.0 {
846 write!(f, "{byte:02x}")?;
847 }
848 Ok(())
849 }
850}
851
852#[cfg(feature = "serde")]
853#[derive(Serialize, Deserialize)]
854#[serde(transparent)]
855struct RecordChunksRootBinary(#[serde(with = "BigArray")] [u8; RecordChunksRoot::SIZE]);
856
857#[cfg(feature = "serde")]
858#[derive(Serialize, Deserialize)]
859#[serde(transparent)]
860struct RecordChunksRootHex(#[serde(with = "hex")] [u8; RecordChunksRoot::SIZE]);
861
862#[cfg(feature = "serde")]
863impl Serialize for RecordChunksRoot {
864 #[inline]
865 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
866 where
867 S: Serializer,
868 {
869 if serializer.is_human_readable() {
870 RecordChunksRootHex(self.0).serialize(serializer)
871 } else {
872 RecordChunksRootBinary(self.0).serialize(serializer)
873 }
874 }
875}
876
877#[cfg(feature = "serde")]
878impl<'de> Deserialize<'de> for RecordChunksRoot {
879 #[inline]
880 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
881 where
882 D: Deserializer<'de>,
883 {
884 Ok(Self(if deserializer.is_human_readable() {
885 RecordChunksRootHex::deserialize(deserializer)?.0
886 } else {
887 RecordChunksRootBinary::deserialize(deserializer)?.0
888 }))
889 }
890}
891
892impl Default for RecordChunksRoot {
893 #[inline]
894 fn default() -> Self {
895 Self([0; _])
896 }
897}
898
899impl TryFrom<&[u8]> for RecordChunksRoot {
900 type Error = TryFromSliceError;
901
902 #[inline]
903 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
904 <[u8; Self::SIZE]>::try_from(slice).map(Self)
905 }
906}
907
908impl AsRef<[u8]> for RecordChunksRoot {
909 #[inline]
910 fn as_ref(&self) -> &[u8] {
911 &self.0
912 }
913}
914
915impl AsMut<[u8]> for RecordChunksRoot {
916 #[inline]
917 fn as_mut(&mut self) -> &mut [u8] {
918 &mut self.0
919 }
920}
921
922impl<'a> From<&'a RecordChunksRoot> for &'a [u8; RecordChunksRoot::SIZE] {
923 #[inline]
924 fn from(value: &'a RecordChunksRoot) -> Self {
925 value.peel_ref()
926 }
927}
928
929impl<'a> From<&'a [u8; RecordChunksRoot::SIZE]> for &'a RecordChunksRoot {
930 #[inline]
931 fn from(value: &'a [u8; RecordChunksRoot::SIZE]) -> Self {
932 RecordChunksRoot::wrap_ref(value)
933 }
934}
935
936impl<'a> From<&'a mut RecordChunksRoot> for &'a mut [u8; RecordChunksRoot::SIZE] {
937 #[inline]
938 fn from(value: &'a mut RecordChunksRoot) -> Self {
939 value.peel_mut()
940 }
941}
942
943impl<'a> From<&'a mut [u8; RecordChunksRoot::SIZE]> for &'a mut RecordChunksRoot {
944 #[inline]
945 fn from(value: &'a mut [u8; RecordChunksRoot::SIZE]) -> Self {
946 RecordChunksRoot::wrap_mut(value)
947 }
948}
949
950impl RecordChunksRoot {
951 pub const SIZE: usize = 32;
953}
954
955#[derive(
957 Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType, TransparentWrapper,
958)]
959#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
960#[repr(C)]
961pub struct RecordProof([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
962
963impl fmt::Debug for RecordProof {
964 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
965 write!(f, "[")?;
966 for hash in self.0 {
967 for byte in hash {
968 write!(f, "{byte:02x}")?;
969 }
970 write!(f, ", ")?;
971 }
972 write!(f, "]")?;
973 Ok(())
974 }
975}
976
977#[cfg(feature = "serde")]
978#[derive(Serialize, Deserialize)]
979#[serde(transparent)]
980struct RecordProofBinary([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
981
982#[cfg(feature = "serde")]
983#[derive(Serialize, Deserialize, TransparentWrapper)]
984#[serde(transparent)]
985#[repr(transparent)]
986struct RecordProofHexHash(#[serde(with = "hex")] [u8; OUT_LEN]);
987
988#[cfg(feature = "serde")]
989#[derive(Serialize, Deserialize)]
990#[serde(transparent)]
991struct RecordProofHex([RecordProofHexHash; RecordProof::NUM_HASHES]);
992
993#[cfg(feature = "serde")]
994impl Serialize for RecordProof {
995 #[inline]
996 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
997 where
998 S: Serializer,
999 {
1000 if serializer.is_human_readable() {
1001 RecordProofHex(<[RecordProofHexHash; Self::NUM_HASHES]>::wrap(self.0))
1002 .serialize(serializer)
1003 } else {
1004 RecordProofBinary(self.0).serialize(serializer)
1005 }
1006 }
1007}
1008
1009#[cfg(feature = "serde")]
1010impl<'de> Deserialize<'de> for RecordProof {
1011 #[inline]
1012 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1013 where
1014 D: Deserializer<'de>,
1015 {
1016 Ok(Self(if deserializer.is_human_readable() {
1017 RecordProofHex::deserialize(deserializer)?.0.peel()
1018 } else {
1019 RecordProofBinary::deserialize(deserializer)?.0
1020 }))
1021 }
1022}
1023
1024impl Default for RecordProof {
1025 #[inline]
1026 fn default() -> Self {
1027 Self([[0; OUT_LEN]; _])
1028 }
1029}
1030
1031impl AsRef<[u8]> for RecordProof {
1032 #[inline]
1033 fn as_ref(&self) -> &[u8] {
1034 self.0.as_flattened()
1035 }
1036}
1037
1038impl AsMut<[u8]> for RecordProof {
1039 #[inline]
1040 fn as_mut(&mut self) -> &mut [u8] {
1041 self.0.as_flattened_mut()
1042 }
1043}
1044
1045impl<'a> From<&'a RecordProof> for &'a [u8; RecordProof::SIZE] {
1046 #[inline]
1047 fn from(value: &'a RecordProof) -> Self {
1048 value.peel_ref().flatten_ref()
1049 }
1050}
1051
1052impl<'a> From<&'a [u8; RecordProof::SIZE]> for &'a RecordProof {
1053 #[inline]
1054 fn from(value: &'a [u8; RecordProof::SIZE]) -> Self {
1055 RecordProof::wrap_ref(value.unflatten_ref())
1056 }
1057}
1058
1059impl<'a> From<&'a mut RecordProof> for &'a mut [u8; RecordProof::SIZE] {
1060 #[inline]
1061 fn from(value: &'a mut RecordProof) -> Self {
1062 value.peel_mut().flatten_mut()
1063 }
1064}
1065
1066impl<'a> From<&'a mut [u8; RecordProof::SIZE]> for &'a mut RecordProof {
1067 #[inline]
1068 fn from(value: &'a mut [u8; RecordProof::SIZE]) -> Self {
1069 RecordProof::wrap_mut(value.unflatten_mut())
1070 }
1071}
1072
1073impl RecordProof {
1074 pub const SIZE: usize = OUT_LEN * Self::NUM_HASHES;
1076 const NUM_HASHES: usize = RecordedHistorySegment::NUM_PIECES.ilog2() as usize;
1077}
1078
1079#[derive(
1081 Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType, TransparentWrapper,
1082)]
1083#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
1084#[repr(C)]
1085pub struct SegmentProof([[u8; OUT_LEN]; SegmentProof::NUM_HASHES]);
1086
1087impl fmt::Debug for SegmentProof {
1088 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1089 write!(f, "[")?;
1090 for hash in self.0 {
1091 for byte in hash {
1092 write!(f, "{byte:02x}")?;
1093 }
1094 write!(f, ", ")?;
1095 }
1096 write!(f, "]")?;
1097 Ok(())
1098 }
1099}
1100
1101#[cfg(feature = "serde")]
1102#[derive(Serialize, Deserialize)]
1103#[serde(transparent)]
1104struct SegmentProofBinary([[u8; OUT_LEN]; SegmentProof::NUM_HASHES]);
1105
1106#[cfg(feature = "serde")]
1107#[derive(Serialize, Deserialize, TransparentWrapper)]
1108#[serde(transparent)]
1109#[repr(transparent)]
1110struct SegmentProofHexHash(#[serde(with = "hex")] [u8; OUT_LEN]);
1111
1112#[cfg(feature = "serde")]
1113#[derive(Serialize, Deserialize)]
1114#[serde(transparent)]
1115struct SegmentProofHex([SegmentProofHexHash; SegmentProof::NUM_HASHES]);
1116
1117#[cfg(feature = "serde")]
1118impl Serialize for SegmentProof {
1119 #[inline]
1120 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1121 where
1122 S: Serializer,
1123 {
1124 if serializer.is_human_readable() {
1125 SegmentProofHex(<[SegmentProofHexHash; Self::NUM_HASHES]>::wrap(self.0))
1126 .serialize(serializer)
1127 } else {
1128 SegmentProofBinary(self.0).serialize(serializer)
1129 }
1130 }
1131}
1132
1133#[cfg(feature = "serde")]
1134impl<'de> Deserialize<'de> for SegmentProof {
1135 #[inline]
1136 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1137 where
1138 D: Deserializer<'de>,
1139 {
1140 Ok(Self(if deserializer.is_human_readable() {
1141 SegmentProofHex::deserialize(deserializer)?.0.peel()
1142 } else {
1143 SegmentProofBinary::deserialize(deserializer)?.0
1144 }))
1145 }
1146}
1147
1148impl Default for SegmentProof {
1149 #[inline]
1150 fn default() -> Self {
1151 Self([[0; OUT_LEN]; _])
1152 }
1153}
1154
1155impl AsRef<[u8]> for SegmentProof {
1156 #[inline]
1157 fn as_ref(&self) -> &[u8] {
1158 self.0.as_flattened()
1159 }
1160}
1161
1162impl AsMut<[u8]> for SegmentProof {
1163 #[inline]
1164 fn as_mut(&mut self) -> &mut [u8] {
1165 self.0.as_flattened_mut()
1166 }
1167}
1168
1169impl<'a> From<&'a SegmentProof> for &'a [u8; SegmentProof::SIZE] {
1170 #[inline]
1171 fn from(value: &'a SegmentProof) -> Self {
1172 value.peel_ref().flatten_ref()
1173 }
1174}
1175
1176impl<'a> From<&'a [u8; SegmentProof::SIZE]> for &'a SegmentProof {
1177 #[inline]
1178 fn from(value: &'a [u8; SegmentProof::SIZE]) -> Self {
1179 SegmentProof::wrap_ref(value.unflatten_ref())
1180 }
1181}
1182
1183impl<'a> From<&'a mut SegmentProof> for &'a mut [u8; SegmentProof::SIZE] {
1184 #[inline]
1185 fn from(value: &'a mut SegmentProof) -> Self {
1186 value.peel_mut().flatten_mut()
1187 }
1188}
1189
1190impl<'a> From<&'a mut [u8; SegmentProof::SIZE]> for &'a mut SegmentProof {
1191 #[inline]
1192 fn from(value: &'a mut [u8; SegmentProof::SIZE]) -> Self {
1193 SegmentProof::wrap_mut(value.unflatten_mut())
1194 }
1195}
1196
1197impl SegmentProof {
1198 pub const SIZE: usize = OUT_LEN * Self::NUM_HASHES;
1200 const NUM_HASHES: usize = SuperSegmentRoot::MAX_SEGMENTS.next_power_of_two().ilog2() as usize;
1201}
1202
1203#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, TrivialType)]
1207#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
1208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1209#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1210#[repr(C)]
1211pub struct PieceHeader {
1212 pub shard_index: Unaligned<ShardIndex>,
1214 pub local_segment_index: Unaligned<LocalSegmentIndex>,
1216 pub super_segment_index: Unaligned<SuperSegmentIndex>,
1218 pub segment_position: Unaligned<SegmentPosition>,
1220 pub segment_root: SegmentRoot,
1222 pub segment_proof: SegmentProof,
1224 pub parity_chunks_root: RecordChunksRoot,
1228 pub record_proof: RecordProof,
1230}
1231
1232const {
1233 assert!(align_of::<PieceHeader>() == 1);
1235}
1236
1237#[derive(Debug, Copy, Clone, Eq, PartialEq, TrivialType)]
1246#[repr(C)]
1247pub struct InnerPiece {
1248 pub header: PieceHeader,
1250 pub record: Record,
1252}
1253
1254const {
1255 const fn assert_any_bit_pattern<T>()
1256 where
1257 T: AnyBitPattern,
1258 {
1259 }
1260
1261 assert!(align_of::<InnerPiece>() == 1);
1263 assert!(size_of::<InnerPiece>() == size_of::<PieceHeader>() + size_of::<Record>());
1265 assert_any_bit_pattern::<InnerPiece>();
1267}
1268
1269impl InnerPiece {
1270 pub const SIZE: usize = size_of::<Self>();
1272
1273 #[inline]
1275 #[cfg(feature = "alloc")]
1276 pub fn new_boxed() -> Box<Self> {
1277 unsafe { Box::<Self>::new_zeroed().assume_init() }
1280 }
1281
1282 pub fn is_valid(
1284 &self,
1285 super_segment_root: &SuperSegmentRoot,
1286 num_segments: u32,
1287 position: PiecePosition,
1288 ) -> bool {
1289 if !self.header.segment_root.is_valid(
1290 self.header.shard_index.as_inner(),
1291 self.header.local_segment_index.as_inner(),
1292 self.header.segment_position.as_inner(),
1293 &self.header.segment_proof,
1294 num_segments,
1295 super_segment_root,
1296 ) {
1297 return false;
1298 }
1299 self.record_root().is_valid(
1300 &self.header.segment_root,
1301 &self.header.record_proof,
1302 position,
1303 )
1304 }
1305
1306 #[inline]
1310 pub fn record_root(&self) -> RecordRoot {
1311 let record_merkle_tree_root = BalancedMerkleTree::compute_root_only(&[
1312 *self.record.source_chunks_root(),
1313 *self.header.parity_chunks_root,
1314 ]);
1315
1316 RecordRoot::from(record_merkle_tree_root)
1317 }
1318
1319 #[inline]
1322 pub fn slice_to_repr(value: &[Self]) -> &[[u8; Self::SIZE]] {
1323 unsafe { mem::transmute(value) }
1326 }
1327
1328 #[inline]
1331 pub fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
1332 unsafe { mem::transmute(value) }
1335 }
1336
1337 #[inline]
1340 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; Self::SIZE]] {
1341 unsafe { mem::transmute(value) }
1344 }
1345
1346 #[inline]
1349 pub fn slice_mut_from_repr(value: &mut [[u8; Self::SIZE]]) -> &mut [Self] {
1350 unsafe { mem::transmute(value) }
1353 }
1354}