1#[cfg(feature = "alloc")]
4mod cow_bytes;
5#[cfg(feature = "alloc")]
6mod flat_pieces;
7#[cfg(feature = "alloc")]
8mod piece;
9
10#[cfg(feature = "alloc")]
11pub use crate::pieces::flat_pieces::FlatPieces;
12#[cfg(feature = "alloc")]
13pub use crate::pieces::piece::Piece;
14use crate::segments::{
15 LocalSegmentIndex, RecordedHistorySegment, SegmentIndex, SegmentPosition, SegmentRoot,
16 SuperSegmentIndex, SuperSegmentRoot,
17};
18use crate::shard::ShardIndex;
19#[cfg(feature = "serde")]
20use ::serde::{Deserialize, Deserializer, Serialize, Serializer};
21use ab_io_type::trivial_type::TrivialType;
22use ab_io_type::unaligned::Unaligned;
23use ab_merkle_tree::balanced::BalancedMerkleTree;
24#[cfg(feature = "alloc")]
25use alloc::boxed::Box;
26#[cfg(feature = "alloc")]
27use alloc::vec::Vec;
28use array_reshape::{Flatten, Unflatten};
29use blake3::OUT_LEN;
30use core::array::TryFromSliceError;
31use core::hash::Hash;
32use core::iter::Step;
33#[cfg(feature = "alloc")]
34use core::mem::MaybeUninit;
35#[cfg(feature = "alloc")]
36use core::slice;
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
392#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut, TrivialType, TransparentWrapper)]
396#[repr(C)]
397pub struct Record([[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]);
398
399impl fmt::Debug for Record {
400 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
401 for byte in self.0.as_flattened() {
402 write!(f, "{byte:02x}")?;
403 }
404 Ok(())
405 }
406}
407
408impl AsRef<[u8]> for Record {
409 #[inline]
410 fn as_ref(&self) -> &[u8] {
411 self.0.as_flattened()
412 }
413}
414
415impl AsRef<[u8; Record::SIZE]> for Record {
416 #[inline(always)]
417 fn as_ref(&self) -> &[u8; Record::SIZE] {
418 self.as_bytes()
419 }
420}
421
422impl AsMut<[u8; Record::SIZE]> for Record {
423 #[inline(always)]
424 fn as_mut(&mut self) -> &mut [u8; Record::SIZE] {
425 unsafe { self.as_bytes_mut() }
427 }
428}
429
430impl AsMut<[u8]> for Record {
431 #[inline]
432 fn as_mut(&mut self) -> &mut [u8] {
433 self.0.as_flattened_mut()
434 }
435}
436
437impl<'a> From<&'a Record> for &'a [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
438 #[inline]
439 fn from(value: &'a Record) -> Self {
440 value.peel_ref()
441 }
442}
443
444impl<'a> From<&'a [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &'a Record {
445 #[inline]
446 fn from(value: &'a [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
447 Record::wrap_ref(value)
448 }
449}
450
451impl<'a> From<&'a mut Record> for &'a mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
452 #[inline]
453 fn from(value: &'a mut Record) -> Self {
454 value.peel_mut()
455 }
456}
457
458impl<'a> From<&'a mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &'a mut Record {
459 #[inline]
460 fn from(value: &'a mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
461 Record::wrap_mut(value)
462 }
463}
464
465impl Record {
466 pub const NUM_CHUNKS: usize = 2usize.pow(15);
468 pub const NUM_S_BUCKETS: usize = Record::NUM_CHUNKS
472 * RecordedHistorySegment::ERASURE_CODING_RATE.1
473 / RecordedHistorySegment::ERASURE_CODING_RATE.0;
474 pub const SIZE: usize = RecordChunk::SIZE * Record::NUM_CHUNKS;
476
477 #[inline]
479 #[cfg(feature = "alloc")]
480 pub fn new_boxed() -> Box<Self> {
481 unsafe { Box::new_zeroed().assume_init() }
484 }
485
486 #[inline]
488 #[cfg(feature = "alloc")]
489 pub fn new_zero_vec(length: usize) -> Vec<Self> {
490 let mut records = Vec::with_capacity(length);
493 {
494 let slice = records.spare_capacity_mut();
495 let slice = unsafe {
499 slice::from_raw_parts_mut(
500 slice
501 .as_mut_ptr()
502 .cast::<[[MaybeUninit<u8>; RecordChunk::SIZE]; Record::NUM_CHUNKS]>(),
503 length,
504 )
505 };
506 for byte in slice.as_flattened_mut().as_flattened_mut() {
507 byte.write(0);
508 }
509 }
510 unsafe {
512 records.set_len(records.capacity());
513 }
514
515 records
516 }
517
518 #[inline(always)]
521 pub fn slice_to_repr(value: &[Self]) -> &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
522 Self::peel_slice(value)
523 }
524
525 #[inline(always)]
528 pub fn slice_from_repr(value: &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]]) -> &[Self] {
529 Self::wrap_slice(value)
530 }
531
532 #[inline(always)]
535 pub fn slice_mut_to_repr(
536 value: &mut [Self],
537 ) -> &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
538 Self::peel_slice_mut(value)
539 }
540
541 #[inline(always)]
544 pub fn slice_mut_from_repr(
545 value: &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]],
546 ) -> &mut [Self] {
547 Self::wrap_slice_mut(value)
548 }
549
550 #[inline(always)]
552 pub fn source_chunks_root(&self) -> RecordChunksRoot {
553 RecordChunksRoot(BalancedMerkleTree::compute_root_only(self))
554 }
555}
556
557#[derive(
561 Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType, TransparentWrapper,
562)]
563#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
564#[repr(C)]
565pub struct RecordRoot([u8; RecordRoot::SIZE]);
566
567impl fmt::Debug for RecordRoot {
568 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569 for byte in self.0 {
570 write!(f, "{byte:02x}")?;
571 }
572 Ok(())
573 }
574}
575
576#[cfg(feature = "serde")]
577#[derive(Serialize, Deserialize)]
578#[serde(transparent)]
579struct RecordRootBinary(#[serde(with = "BigArray")] [u8; RecordRoot::SIZE]);
580
581#[cfg(feature = "serde")]
582#[derive(Serialize, Deserialize)]
583#[serde(transparent)]
584struct RecordRootHex(#[serde(with = "hex")] [u8; RecordRoot::SIZE]);
585
586#[cfg(feature = "serde")]
587impl Serialize for RecordRoot {
588 #[inline]
589 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
590 where
591 S: Serializer,
592 {
593 if serializer.is_human_readable() {
594 RecordRootHex(self.0).serialize(serializer)
595 } else {
596 RecordRootBinary(self.0).serialize(serializer)
597 }
598 }
599}
600
601#[cfg(feature = "serde")]
602impl<'de> Deserialize<'de> for RecordRoot {
603 #[inline]
604 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
605 where
606 D: Deserializer<'de>,
607 {
608 Ok(Self(if deserializer.is_human_readable() {
609 RecordRootHex::deserialize(deserializer)?.0
610 } else {
611 RecordRootBinary::deserialize(deserializer)?.0
612 }))
613 }
614}
615
616impl Default for RecordRoot {
617 #[inline]
618 fn default() -> Self {
619 Self([0; _])
620 }
621}
622
623impl TryFrom<&[u8]> for RecordRoot {
624 type Error = TryFromSliceError;
625
626 #[inline]
627 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
628 <[u8; Self::SIZE]>::try_from(slice).map(Self)
629 }
630}
631
632impl AsRef<[u8]> for RecordRoot {
633 #[inline]
634 fn as_ref(&self) -> &[u8] {
635 &self.0
636 }
637}
638
639impl AsMut<[u8]> for RecordRoot {
640 #[inline]
641 fn as_mut(&mut self) -> &mut [u8] {
642 &mut self.0
643 }
644}
645
646impl<'a> From<&'a RecordRoot> for &'a [u8; RecordRoot::SIZE] {
647 #[inline]
648 fn from(value: &'a RecordRoot) -> Self {
649 value.peel_ref()
650 }
651}
652
653impl<'a> From<&'a [u8; RecordRoot::SIZE]> for &'a RecordRoot {
654 #[inline]
655 fn from(value: &'a [u8; RecordRoot::SIZE]) -> Self {
656 RecordRoot::wrap_ref(value)
657 }
658}
659
660impl<'a> From<&'a mut RecordRoot> for &'a mut [u8; RecordRoot::SIZE] {
661 #[inline]
662 fn from(value: &'a mut RecordRoot) -> Self {
663 value.peel_mut()
664 }
665}
666
667impl<'a> From<&'a mut [u8; RecordRoot::SIZE]> for &'a mut RecordRoot {
668 #[inline]
669 fn from(value: &'a mut [u8; RecordRoot::SIZE]) -> Self {
670 RecordRoot::wrap_mut(value)
671 }
672}
673
674impl RecordRoot {
675 pub const SIZE: usize = 32;
677
678 pub fn is_valid(
680 &self,
681 segment_root: &SegmentRoot,
682 record_proof: &RecordProof,
683 position: PiecePosition,
684 ) -> bool {
685 BalancedMerkleTree::<{ RecordedHistorySegment::NUM_PIECES }>::verify(
686 segment_root,
687 record_proof,
688 usize::from(position),
689 self.0,
690 )
691 }
692}
693
694#[derive(
696 Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType, TransparentWrapper,
697)]
698#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
699#[repr(C)]
700pub struct RecordChunksRoot([u8; RecordChunksRoot::SIZE]);
701
702impl fmt::Debug for RecordChunksRoot {
703 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
704 for byte in self.0 {
705 write!(f, "{byte:02x}")?;
706 }
707 Ok(())
708 }
709}
710
711#[cfg(feature = "serde")]
712#[derive(Serialize, Deserialize)]
713#[serde(transparent)]
714struct RecordChunksRootBinary(#[serde(with = "BigArray")] [u8; RecordChunksRoot::SIZE]);
715
716#[cfg(feature = "serde")]
717#[derive(Serialize, Deserialize)]
718#[serde(transparent)]
719struct RecordChunksRootHex(#[serde(with = "hex")] [u8; RecordChunksRoot::SIZE]);
720
721#[cfg(feature = "serde")]
722impl Serialize for RecordChunksRoot {
723 #[inline]
724 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
725 where
726 S: Serializer,
727 {
728 if serializer.is_human_readable() {
729 RecordChunksRootHex(self.0).serialize(serializer)
730 } else {
731 RecordChunksRootBinary(self.0).serialize(serializer)
732 }
733 }
734}
735
736#[cfg(feature = "serde")]
737impl<'de> Deserialize<'de> for RecordChunksRoot {
738 #[inline]
739 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
740 where
741 D: Deserializer<'de>,
742 {
743 Ok(Self(if deserializer.is_human_readable() {
744 RecordChunksRootHex::deserialize(deserializer)?.0
745 } else {
746 RecordChunksRootBinary::deserialize(deserializer)?.0
747 }))
748 }
749}
750
751impl Default for RecordChunksRoot {
752 #[inline]
753 fn default() -> Self {
754 Self([0; _])
755 }
756}
757
758impl TryFrom<&[u8]> for RecordChunksRoot {
759 type Error = TryFromSliceError;
760
761 #[inline]
762 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
763 <[u8; Self::SIZE]>::try_from(slice).map(Self)
764 }
765}
766
767impl AsRef<[u8]> for RecordChunksRoot {
768 #[inline]
769 fn as_ref(&self) -> &[u8] {
770 &self.0
771 }
772}
773
774impl AsMut<[u8]> for RecordChunksRoot {
775 #[inline]
776 fn as_mut(&mut self) -> &mut [u8] {
777 &mut self.0
778 }
779}
780
781impl<'a> From<&'a RecordChunksRoot> for &'a [u8; RecordChunksRoot::SIZE] {
782 #[inline]
783 fn from(value: &'a RecordChunksRoot) -> Self {
784 value.peel_ref()
785 }
786}
787
788impl<'a> From<&'a [u8; RecordChunksRoot::SIZE]> for &'a RecordChunksRoot {
789 #[inline]
790 fn from(value: &'a [u8; RecordChunksRoot::SIZE]) -> Self {
791 RecordChunksRoot::wrap_ref(value)
792 }
793}
794
795impl<'a> From<&'a mut RecordChunksRoot> for &'a mut [u8; RecordChunksRoot::SIZE] {
796 #[inline]
797 fn from(value: &'a mut RecordChunksRoot) -> Self {
798 value.peel_mut()
799 }
800}
801
802impl<'a> From<&'a mut [u8; RecordChunksRoot::SIZE]> for &'a mut RecordChunksRoot {
803 #[inline]
804 fn from(value: &'a mut [u8; RecordChunksRoot::SIZE]) -> Self {
805 RecordChunksRoot::wrap_mut(value)
806 }
807}
808
809impl RecordChunksRoot {
810 pub const SIZE: usize = 32;
812}
813
814#[derive(
816 Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType, TransparentWrapper,
817)]
818#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
819#[repr(C)]
820pub struct RecordProof([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
821
822impl fmt::Debug for RecordProof {
823 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
824 write!(f, "[")?;
825 for hash in self.0 {
826 for byte in hash {
827 write!(f, "{byte:02x}")?;
828 }
829 write!(f, ", ")?;
830 }
831 write!(f, "]")?;
832 Ok(())
833 }
834}
835
836#[cfg(feature = "serde")]
837#[derive(Serialize, Deserialize)]
838#[serde(transparent)]
839struct RecordProofBinary([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
840
841#[cfg(feature = "serde")]
842#[derive(Serialize, Deserialize, TransparentWrapper)]
843#[serde(transparent)]
844#[repr(transparent)]
845struct RecordProofHexHash(#[serde(with = "hex")] [u8; OUT_LEN]);
846
847#[cfg(feature = "serde")]
848#[derive(Serialize, Deserialize)]
849#[serde(transparent)]
850struct RecordProofHex([RecordProofHexHash; RecordProof::NUM_HASHES]);
851
852#[cfg(feature = "serde")]
853impl Serialize for RecordProof {
854 #[inline]
855 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
856 where
857 S: Serializer,
858 {
859 if serializer.is_human_readable() {
860 RecordProofHex(<[RecordProofHexHash; Self::NUM_HASHES]>::wrap(self.0))
861 .serialize(serializer)
862 } else {
863 RecordProofBinary(self.0).serialize(serializer)
864 }
865 }
866}
867
868#[cfg(feature = "serde")]
869impl<'de> Deserialize<'de> for RecordProof {
870 #[inline]
871 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
872 where
873 D: Deserializer<'de>,
874 {
875 Ok(Self(if deserializer.is_human_readable() {
876 RecordProofHex::deserialize(deserializer)?.0.peel()
877 } else {
878 RecordProofBinary::deserialize(deserializer)?.0
879 }))
880 }
881}
882
883impl Default for RecordProof {
884 #[inline]
885 fn default() -> Self {
886 Self([[0; OUT_LEN]; _])
887 }
888}
889
890impl AsRef<[u8]> for RecordProof {
891 #[inline]
892 fn as_ref(&self) -> &[u8] {
893 self.0.as_flattened()
894 }
895}
896
897impl AsMut<[u8]> for RecordProof {
898 #[inline]
899 fn as_mut(&mut self) -> &mut [u8] {
900 self.0.as_flattened_mut()
901 }
902}
903
904impl<'a> From<&'a RecordProof> for &'a [u8; RecordProof::SIZE] {
905 #[inline]
906 fn from(value: &'a RecordProof) -> Self {
907 value.peel_ref().flatten_ref()
908 }
909}
910
911impl<'a> From<&'a [u8; RecordProof::SIZE]> for &'a RecordProof {
912 #[inline]
913 fn from(value: &'a [u8; RecordProof::SIZE]) -> Self {
914 RecordProof::wrap_ref(value.unflatten_ref())
915 }
916}
917
918impl<'a> From<&'a mut RecordProof> for &'a mut [u8; RecordProof::SIZE] {
919 #[inline]
920 fn from(value: &'a mut RecordProof) -> Self {
921 value.peel_mut().flatten_mut()
922 }
923}
924
925impl<'a> From<&'a mut [u8; RecordProof::SIZE]> for &'a mut RecordProof {
926 #[inline]
927 fn from(value: &'a mut [u8; RecordProof::SIZE]) -> Self {
928 RecordProof::wrap_mut(value.unflatten_mut())
929 }
930}
931
932impl RecordProof {
933 pub const SIZE: usize = OUT_LEN * Self::NUM_HASHES;
935 const NUM_HASHES: usize = RecordedHistorySegment::NUM_PIECES.ilog2() as usize;
936}
937
938#[derive(
940 Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType, TransparentWrapper,
941)]
942#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
943#[repr(C)]
944pub struct SegmentProof([[u8; OUT_LEN]; SegmentProof::NUM_HASHES]);
945
946impl fmt::Debug for SegmentProof {
947 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
948 write!(f, "[")?;
949 for hash in self.0 {
950 for byte in hash {
951 write!(f, "{byte:02x}")?;
952 }
953 write!(f, ", ")?;
954 }
955 write!(f, "]")?;
956 Ok(())
957 }
958}
959
960#[cfg(feature = "serde")]
961#[derive(Serialize, Deserialize)]
962#[serde(transparent)]
963struct SegmentProofBinary([[u8; OUT_LEN]; SegmentProof::NUM_HASHES]);
964
965#[cfg(feature = "serde")]
966#[derive(Serialize, Deserialize, TransparentWrapper)]
967#[serde(transparent)]
968#[repr(transparent)]
969struct SegmentProofHexHash(#[serde(with = "hex")] [u8; OUT_LEN]);
970
971#[cfg(feature = "serde")]
972#[derive(Serialize, Deserialize)]
973#[serde(transparent)]
974struct SegmentProofHex([SegmentProofHexHash; SegmentProof::NUM_HASHES]);
975
976#[cfg(feature = "serde")]
977impl Serialize for SegmentProof {
978 #[inline]
979 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
980 where
981 S: Serializer,
982 {
983 if serializer.is_human_readable() {
984 SegmentProofHex(<[SegmentProofHexHash; Self::NUM_HASHES]>::wrap(self.0))
985 .serialize(serializer)
986 } else {
987 SegmentProofBinary(self.0).serialize(serializer)
988 }
989 }
990}
991
992#[cfg(feature = "serde")]
993impl<'de> Deserialize<'de> for SegmentProof {
994 #[inline]
995 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
996 where
997 D: Deserializer<'de>,
998 {
999 Ok(Self(if deserializer.is_human_readable() {
1000 SegmentProofHex::deserialize(deserializer)?.0.peel()
1001 } else {
1002 SegmentProofBinary::deserialize(deserializer)?.0
1003 }))
1004 }
1005}
1006
1007impl Default for SegmentProof {
1008 #[inline]
1009 fn default() -> Self {
1010 Self([[0; OUT_LEN]; _])
1011 }
1012}
1013
1014impl AsRef<[u8]> for SegmentProof {
1015 #[inline]
1016 fn as_ref(&self) -> &[u8] {
1017 self.0.as_flattened()
1018 }
1019}
1020
1021impl AsMut<[u8]> for SegmentProof {
1022 #[inline]
1023 fn as_mut(&mut self) -> &mut [u8] {
1024 self.0.as_flattened_mut()
1025 }
1026}
1027
1028impl<'a> From<&'a SegmentProof> for &'a [u8; SegmentProof::SIZE] {
1029 #[inline]
1030 fn from(value: &'a SegmentProof) -> Self {
1031 value.peel_ref().flatten_ref()
1032 }
1033}
1034
1035impl<'a> From<&'a [u8; SegmentProof::SIZE]> for &'a SegmentProof {
1036 #[inline]
1037 fn from(value: &'a [u8; SegmentProof::SIZE]) -> Self {
1038 SegmentProof::wrap_ref(value.unflatten_ref())
1039 }
1040}
1041
1042impl<'a> From<&'a mut SegmentProof> for &'a mut [u8; SegmentProof::SIZE] {
1043 #[inline]
1044 fn from(value: &'a mut SegmentProof) -> Self {
1045 value.peel_mut().flatten_mut()
1046 }
1047}
1048
1049impl<'a> From<&'a mut [u8; SegmentProof::SIZE]> for &'a mut SegmentProof {
1050 #[inline]
1051 fn from(value: &'a mut [u8; SegmentProof::SIZE]) -> Self {
1052 SegmentProof::wrap_mut(value.unflatten_mut())
1053 }
1054}
1055
1056impl SegmentProof {
1057 pub const SIZE: usize = OUT_LEN * Self::NUM_HASHES;
1059 const NUM_HASHES: usize = SuperSegmentRoot::MAX_SEGMENTS.next_power_of_two().ilog2() as usize;
1060}
1061
1062#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, TrivialType)]
1066#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
1067#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1068#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1069#[repr(C)]
1070pub struct PieceHeader {
1071 pub shard_index: Unaligned<ShardIndex>,
1073 pub local_segment_index: Unaligned<LocalSegmentIndex>,
1075 pub super_segment_index: Unaligned<SuperSegmentIndex>,
1077 pub segment_position: Unaligned<SegmentPosition>,
1079 pub segment_root: SegmentRoot,
1081 pub segment_proof: SegmentProof,
1083 pub parity_chunks_root: RecordChunksRoot,
1087 pub record_proof: RecordProof,
1089}
1090
1091const {
1092 assert!(align_of::<PieceHeader>() == 1);
1094}
1095
1096#[derive(Debug, Copy, Clone, Eq, PartialEq, TrivialType)]
1105#[repr(C)]
1106pub struct InnerPiece {
1107 pub header: PieceHeader,
1109 pub record: Record,
1111}
1112
1113const {
1114 assert!(align_of::<InnerPiece>() == 1);
1116}
1117
1118impl InnerPiece {
1119 pub const SIZE: usize = size_of::<Self>();
1121
1122 #[inline]
1124 #[cfg(feature = "alloc")]
1125 pub fn new_boxed() -> Box<Self> {
1126 unsafe { Box::<Self>::new_zeroed().assume_init() }
1129 }
1130
1131 pub fn is_valid(
1133 &self,
1134 super_segment_root: &SuperSegmentRoot,
1135 num_segments: u32,
1136 position: PiecePosition,
1137 ) -> bool {
1138 if !self.header.segment_root.is_valid(
1139 self.header.shard_index.as_inner(),
1140 self.header.local_segment_index.as_inner(),
1141 self.header.segment_position.as_inner(),
1142 &self.header.segment_proof,
1143 num_segments,
1144 super_segment_root,
1145 ) {
1146 return false;
1147 }
1148 self.record_root().is_valid(
1149 &self.header.segment_root,
1150 &self.header.record_proof,
1151 position,
1152 )
1153 }
1154
1155 #[inline]
1159 pub fn record_root(&self) -> RecordRoot {
1160 let record_merkle_tree_root = BalancedMerkleTree::compute_root_only(&[
1161 *self.record.source_chunks_root(),
1162 *self.header.parity_chunks_root,
1163 ]);
1164
1165 RecordRoot::from(record_merkle_tree_root)
1166 }
1167
1168 #[inline]
1171 pub fn slice_to_repr(value: &[Self]) -> &[[u8; Self::SIZE]] {
1172 unsafe { mem::transmute(value) }
1175 }
1176
1177 #[inline]
1180 pub fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
1181 unsafe { mem::transmute(value) }
1184 }
1185
1186 #[inline]
1189 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; Self::SIZE]] {
1190 unsafe { mem::transmute(value) }
1193 }
1194
1195 #[inline]
1198 pub fn slice_mut_from_repr(value: &mut [[u8; Self::SIZE]]) -> &mut [Self] {
1199 unsafe { mem::transmute(value) }
1202 }
1203}