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 blake3::OUT_LEN;
29use core::array::TryFromSliceError;
30use core::hash::Hash;
31use core::iter::Step;
32use core::mem::MaybeUninit;
33#[cfg(feature = "alloc")]
34use core::slice;
35use core::{fmt, mem};
36use derive_more::{
37 Add, AddAssign, AsMut, AsRef, Deref, DerefMut, Display, Div, DivAssign, From, Into, Mul,
38 MulAssign, Sub, SubAssign,
39};
40#[cfg(feature = "scale-codec")]
41use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
42#[cfg(feature = "serde")]
43use serde_big_array::BigArray;
44
45#[derive(
47 Debug,
48 Display,
49 Default,
50 Copy,
51 Clone,
52 Ord,
53 PartialOrd,
54 Eq,
55 PartialEq,
56 Hash,
57 Add,
58 AddAssign,
59 Sub,
60 SubAssign,
61 Mul,
62 MulAssign,
63 Div,
64 DivAssign,
65)]
66#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
67#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
68#[repr(C)]
69pub struct PieceIndex(u64);
70
71impl Step for PieceIndex {
72 #[inline]
73 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
74 u64::steps_between(&start.0, &end.0)
75 }
76
77 #[inline]
78 fn forward_checked(start: Self, count: usize) -> Option<Self> {
79 u64::forward_checked(start.0, count).map(Self)
80 }
81
82 #[inline(always)]
83 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
84 let (n, overflowing) = u64::forward_overflowing(start.0, count);
85 (Self(n), overflowing)
86 }
87
88 #[inline]
89 fn backward_checked(start: Self, count: usize) -> Option<Self> {
90 u64::backward_checked(start.0, count).map(Self)
91 }
92
93 #[inline(always)]
94 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
95 let (n, overflowing) = u64::backward_overflowing(start.0, count);
96 (Self(n), overflowing)
97 }
98}
99
100const impl From<u64> for PieceIndex {
101 #[inline(always)]
102 fn from(value: u64) -> Self {
103 Self(value)
104 }
105}
106
107const impl From<PieceIndex> for u64 {
108 #[inline(always)]
109 fn from(value: PieceIndex) -> Self {
110 value.0
111 }
112}
113
114impl PieceIndex {
115 pub const SIZE: usize = size_of::<u64>();
117 pub const ZERO: PieceIndex = PieceIndex(0);
119 pub const ONE: PieceIndex = PieceIndex(1);
121
122 #[inline]
124 pub const fn from_bytes(bytes: [u8; Self::SIZE]) -> Self {
125 Self(u64::from_le_bytes(bytes))
126 }
127
128 #[inline]
130 pub const fn to_bytes(self) -> [u8; Self::SIZE] {
131 self.0.to_le_bytes()
132 }
133
134 #[inline]
136 pub const fn segment_index(&self) -> SegmentIndex {
137 SegmentIndex::from(self.0 / RecordedHistorySegment::NUM_PIECES as u64)
138 }
139
140 #[inline]
142 pub fn position(&self) -> PiecePosition {
143 PiecePosition::from((self.0 % RecordedHistorySegment::NUM_PIECES as u64) as u8)
144 }
145}
146
147const {
148 assert!(RecordedHistorySegment::NUM_PIECES == usize::from(u8::MAX) + 1);
150}
151
152#[derive(
154 Debug,
155 Display,
156 Default,
157 Copy,
158 Clone,
159 Ord,
160 PartialOrd,
161 Eq,
162 PartialEq,
163 Hash,
164 From,
165 Into,
166 TrivialType,
167)]
168#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
170#[repr(C)]
171pub struct PiecePosition(u8);
172
173impl Step for PiecePosition {
174 #[inline]
175 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
176 u8::steps_between(&start.0, &end.0)
177 }
178
179 #[inline]
180 fn forward_checked(start: Self, count: usize) -> Option<Self> {
181 u8::forward_checked(start.0, count).map(Self)
182 }
183
184 #[inline(always)]
185 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
186 let (n, overflowing) = u8::forward_overflowing(start.0, count);
187 (Self(n), overflowing)
188 }
189
190 #[inline]
191 fn backward_checked(start: Self, count: usize) -> Option<Self> {
192 u8::backward_checked(start.0, count).map(Self)
193 }
194
195 #[inline(always)]
196 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
197 let (n, overflowing) = u8::backward_overflowing(start.0, count);
198 (Self(n), overflowing)
199 }
200}
201
202impl From<PiecePosition> for u16 {
203 #[inline]
204 fn from(original: PiecePosition) -> Self {
205 Self::from(original.0)
206 }
207}
208
209impl From<PiecePosition> for u32 {
210 #[inline]
211 fn from(original: PiecePosition) -> Self {
212 Self::from(original.0)
213 }
214}
215
216impl From<PiecePosition> for u64 {
217 #[inline]
218 fn from(original: PiecePosition) -> Self {
219 Self::from(original.0)
220 }
221}
222
223impl From<PiecePosition> for usize {
224 #[inline]
225 fn from(original: PiecePosition) -> Self {
226 usize::from(original.0)
227 }
228}
229
230#[derive(
232 Debug,
233 Display,
234 Default,
235 Copy,
236 Clone,
237 Ord,
238 PartialOrd,
239 Eq,
240 PartialEq,
241 Hash,
242 From,
243 Into,
244 Add,
245 AddAssign,
246 Sub,
247 SubAssign,
248 Mul,
249 MulAssign,
250 Div,
251 DivAssign,
252 TrivialType,
253)]
254#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
255#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
256#[repr(C)]
257pub struct PieceOffset(u16);
258
259impl Step for PieceOffset {
260 #[inline]
261 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
262 u16::steps_between(&start.0, &end.0)
263 }
264
265 #[inline]
266 fn forward_checked(start: Self, count: usize) -> Option<Self> {
267 u16::forward_checked(start.0, count).map(Self)
268 }
269
270 #[inline(always)]
271 fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
272 let (n, overflowing) = u16::forward_overflowing(start.0, count);
273 (Self(n), overflowing)
274 }
275
276 #[inline]
277 fn backward_checked(start: Self, count: usize) -> Option<Self> {
278 u16::backward_checked(start.0, count).map(Self)
279 }
280
281 #[inline(always)]
282 fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
283 let (n, overflowing) = u16::backward_overflowing(start.0, count);
284 (Self(n), overflowing)
285 }
286}
287
288impl From<PieceOffset> for u32 {
289 #[inline]
290 fn from(original: PieceOffset) -> Self {
291 Self::from(original.0)
292 }
293}
294
295impl From<PieceOffset> for u64 {
296 #[inline]
297 fn from(original: PieceOffset) -> Self {
298 Self::from(original.0)
299 }
300}
301
302impl From<PieceOffset> for usize {
303 #[inline]
304 fn from(original: PieceOffset) -> Self {
305 usize::from(original.0)
306 }
307}
308
309impl PieceOffset {
310 pub const ZERO: Self = Self(0);
312 pub const ONE: Self = Self(1);
314 pub const SIZE: usize = size_of::<u16>();
316
317 #[inline]
319 pub const fn to_bytes(self) -> [u8; Self::SIZE] {
320 self.0.to_le_bytes()
321 }
322}
323
324#[derive(
326 Default,
327 Copy,
328 Clone,
329 Eq,
330 PartialEq,
331 Ord,
332 PartialOrd,
333 Hash,
334 From,
335 Into,
336 AsRef,
337 AsMut,
338 Deref,
339 DerefMut,
340 TrivialType,
341)]
342#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
343#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
344#[cfg_attr(feature = "serde", serde(transparent))]
345#[repr(C)]
346pub struct RecordChunk([u8; RecordChunk::SIZE]);
347
348impl fmt::Debug for RecordChunk {
349 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350 for byte in self.0 {
351 write!(f, "{byte:02x}")?;
352 }
353 Ok(())
354 }
355}
356
357impl RecordChunk {
358 pub const SIZE: usize = 32;
360
361 #[inline]
363 pub fn slice_to_repr(value: &[Self]) -> &[[u8; Self::SIZE]] {
364 unsafe { mem::transmute(value) }
366 }
367
368 #[inline]
370 pub fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
371 unsafe { mem::transmute(value) }
373 }
374
375 #[inline]
378 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; Self::SIZE]] {
379 unsafe { mem::transmute(value) }
381 }
382
383 #[inline]
386 pub fn slice_mut_from_repr(value: &mut [[u8; Self::SIZE]]) -> &mut [Self] {
387 unsafe { mem::transmute(value) }
389 }
390}
391
392#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut, TrivialType)]
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 From<&Record> for &[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
438 #[inline]
439 fn from(value: &Record) -> Self {
440 unsafe { mem::transmute(value) }
442 }
443}
444
445impl From<&[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &Record {
446 #[inline]
447 fn from(value: &[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
448 unsafe { mem::transmute(value) }
450 }
451}
452
453impl From<&mut Record> for &mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
454 #[inline]
455 fn from(value: &mut Record) -> Self {
456 unsafe { mem::transmute(value) }
458 }
459}
460
461impl From<&mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &mut Record {
462 #[inline]
463 fn from(value: &mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
464 unsafe { mem::transmute(value) }
466 }
467}
468
469impl Record {
470 pub const NUM_CHUNKS: usize = 2usize.pow(15);
472 pub const NUM_S_BUCKETS: usize = Record::NUM_CHUNKS
476 * RecordedHistorySegment::ERASURE_CODING_RATE.1
477 / RecordedHistorySegment::ERASURE_CODING_RATE.0;
478 pub const SIZE: usize = RecordChunk::SIZE * Record::NUM_CHUNKS;
480
481 #[inline]
483 #[cfg(feature = "alloc")]
484 pub fn new_boxed() -> Box<Self> {
485 unsafe { Box::new_zeroed().assume_init() }
488 }
489
490 #[inline]
492 #[cfg(feature = "alloc")]
493 pub fn new_zero_vec(length: usize) -> Vec<Self> {
494 let mut records = Vec::with_capacity(length);
497 {
498 let slice = records.spare_capacity_mut();
499 let slice = unsafe {
503 slice::from_raw_parts_mut(
504 slice
505 .as_mut_ptr()
506 .cast::<[[MaybeUninit<u8>; RecordChunk::SIZE]; Record::NUM_CHUNKS]>(),
507 length,
508 )
509 };
510 for byte in slice.as_flattened_mut().as_flattened_mut() {
511 byte.write(0);
512 }
513 }
514 unsafe {
516 records.set_len(records.capacity());
517 }
518
519 records
520 }
521
522 #[inline(always)]
525 pub fn slice_to_repr(value: &[Self]) -> &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
526 unsafe { mem::transmute(value) }
528 }
529
530 #[inline(always)]
533 pub fn slice_from_repr(value: &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]]) -> &[Self] {
534 unsafe { mem::transmute(value) }
536 }
537
538 #[inline(always)]
541 pub fn slice_mut_to_repr(
542 value: &mut [Self],
543 ) -> &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
544 unsafe { mem::transmute(value) }
546 }
547
548 #[inline(always)]
551 pub fn slice_mut_from_repr(
552 value: &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]],
553 ) -> &mut [Self] {
554 unsafe { mem::transmute(value) }
556 }
557
558 #[inline(always)]
560 pub fn source_chunks_root(&self) -> RecordChunksRoot {
561 RecordChunksRoot(BalancedMerkleTree::compute_root_only(self))
562 }
563}
564
565#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
569#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
570#[repr(C)]
571pub struct RecordRoot([u8; RecordRoot::SIZE]);
572
573impl fmt::Debug for RecordRoot {
574 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575 for byte in self.0 {
576 write!(f, "{byte:02x}")?;
577 }
578 Ok(())
579 }
580}
581
582#[cfg(feature = "serde")]
583#[derive(Serialize, Deserialize)]
584#[serde(transparent)]
585struct RecordRootBinary(#[serde(with = "BigArray")] [u8; RecordRoot::SIZE]);
586
587#[cfg(feature = "serde")]
588#[derive(Serialize, Deserialize)]
589#[serde(transparent)]
590struct RecordRootHex(#[serde(with = "hex")] [u8; RecordRoot::SIZE]);
591
592#[cfg(feature = "serde")]
593impl Serialize for RecordRoot {
594 #[inline]
595 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
596 where
597 S: Serializer,
598 {
599 if serializer.is_human_readable() {
600 RecordRootHex(self.0).serialize(serializer)
601 } else {
602 RecordRootBinary(self.0).serialize(serializer)
603 }
604 }
605}
606
607#[cfg(feature = "serde")]
608impl<'de> Deserialize<'de> for RecordRoot {
609 #[inline]
610 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
611 where
612 D: Deserializer<'de>,
613 {
614 Ok(Self(if deserializer.is_human_readable() {
615 RecordRootHex::deserialize(deserializer)?.0
616 } else {
617 RecordRootBinary::deserialize(deserializer)?.0
618 }))
619 }
620}
621
622impl Default for RecordRoot {
623 #[inline]
624 fn default() -> Self {
625 Self([0; _])
626 }
627}
628
629impl TryFrom<&[u8]> for RecordRoot {
630 type Error = TryFromSliceError;
631
632 #[inline]
633 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
634 <[u8; Self::SIZE]>::try_from(slice).map(Self)
635 }
636}
637
638impl AsRef<[u8]> for RecordRoot {
639 #[inline]
640 fn as_ref(&self) -> &[u8] {
641 &self.0
642 }
643}
644
645impl AsMut<[u8]> for RecordRoot {
646 #[inline]
647 fn as_mut(&mut self) -> &mut [u8] {
648 &mut self.0
649 }
650}
651
652impl From<&RecordRoot> for &[u8; RecordRoot::SIZE] {
653 #[inline]
654 fn from(value: &RecordRoot) -> Self {
655 unsafe { mem::transmute(value) }
658 }
659}
660
661impl From<&[u8; RecordRoot::SIZE]> for &RecordRoot {
662 #[inline]
663 fn from(value: &[u8; RecordRoot::SIZE]) -> Self {
664 unsafe { mem::transmute(value) }
667 }
668}
669
670impl From<&mut RecordRoot> for &mut [u8; RecordRoot::SIZE] {
671 #[inline]
672 fn from(value: &mut RecordRoot) -> Self {
673 unsafe { mem::transmute(value) }
676 }
677}
678
679impl From<&mut [u8; RecordRoot::SIZE]> for &mut RecordRoot {
680 #[inline]
681 fn from(value: &mut [u8; RecordRoot::SIZE]) -> Self {
682 unsafe { mem::transmute(value) }
685 }
686}
687
688impl RecordRoot {
689 pub const SIZE: usize = 32;
691
692 pub fn is_valid(
694 &self,
695 segment_root: &SegmentRoot,
696 record_proof: &RecordProof,
697 position: PiecePosition,
698 ) -> bool {
699 BalancedMerkleTree::<{ RecordedHistorySegment::NUM_PIECES }>::verify(
700 segment_root,
701 record_proof,
702 usize::from(position),
703 self.0,
704 )
705 }
706}
707
708#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
710#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
711#[repr(C)]
712pub struct RecordChunksRoot([u8; RecordChunksRoot::SIZE]);
713
714impl fmt::Debug for RecordChunksRoot {
715 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
716 for byte in self.0 {
717 write!(f, "{byte:02x}")?;
718 }
719 Ok(())
720 }
721}
722
723#[cfg(feature = "serde")]
724#[derive(Serialize, Deserialize)]
725#[serde(transparent)]
726struct RecordChunksRootBinary(#[serde(with = "BigArray")] [u8; RecordChunksRoot::SIZE]);
727
728#[cfg(feature = "serde")]
729#[derive(Serialize, Deserialize)]
730#[serde(transparent)]
731struct RecordChunksRootHex(#[serde(with = "hex")] [u8; RecordChunksRoot::SIZE]);
732
733#[cfg(feature = "serde")]
734impl Serialize for RecordChunksRoot {
735 #[inline]
736 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
737 where
738 S: Serializer,
739 {
740 if serializer.is_human_readable() {
741 RecordChunksRootHex(self.0).serialize(serializer)
742 } else {
743 RecordChunksRootBinary(self.0).serialize(serializer)
744 }
745 }
746}
747
748#[cfg(feature = "serde")]
749impl<'de> Deserialize<'de> for RecordChunksRoot {
750 #[inline]
751 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
752 where
753 D: Deserializer<'de>,
754 {
755 Ok(Self(if deserializer.is_human_readable() {
756 RecordChunksRootHex::deserialize(deserializer)?.0
757 } else {
758 RecordChunksRootBinary::deserialize(deserializer)?.0
759 }))
760 }
761}
762
763impl Default for RecordChunksRoot {
764 #[inline]
765 fn default() -> Self {
766 Self([0; _])
767 }
768}
769
770impl TryFrom<&[u8]> for RecordChunksRoot {
771 type Error = TryFromSliceError;
772
773 #[inline]
774 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
775 <[u8; Self::SIZE]>::try_from(slice).map(Self)
776 }
777}
778
779impl AsRef<[u8]> for RecordChunksRoot {
780 #[inline]
781 fn as_ref(&self) -> &[u8] {
782 &self.0
783 }
784}
785
786impl AsMut<[u8]> for RecordChunksRoot {
787 #[inline]
788 fn as_mut(&mut self) -> &mut [u8] {
789 &mut self.0
790 }
791}
792
793impl From<&RecordChunksRoot> for &[u8; RecordChunksRoot::SIZE] {
794 #[inline]
795 fn from(value: &RecordChunksRoot) -> Self {
796 unsafe { mem::transmute(value) }
799 }
800}
801
802impl From<&[u8; RecordChunksRoot::SIZE]> for &RecordChunksRoot {
803 #[inline]
804 fn from(value: &[u8; RecordChunksRoot::SIZE]) -> Self {
805 unsafe { mem::transmute(value) }
808 }
809}
810
811impl From<&mut RecordChunksRoot> for &mut [u8; RecordChunksRoot::SIZE] {
812 #[inline]
813 fn from(value: &mut RecordChunksRoot) -> Self {
814 unsafe { mem::transmute(value) }
817 }
818}
819
820impl From<&mut [u8; RecordChunksRoot::SIZE]> for &mut RecordChunksRoot {
821 #[inline]
822 fn from(value: &mut [u8; RecordChunksRoot::SIZE]) -> Self {
823 unsafe { mem::transmute(value) }
826 }
827}
828
829impl RecordChunksRoot {
830 pub const SIZE: usize = 32;
832}
833
834#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
836#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
837#[repr(C)]
838pub struct RecordProof([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
839
840impl fmt::Debug for RecordProof {
841 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
842 write!(f, "[")?;
843 for hash in self.0 {
844 for byte in hash {
845 write!(f, "{byte:02x}")?;
846 }
847 write!(f, ", ")?;
848 }
849 write!(f, "]")?;
850 Ok(())
851 }
852}
853
854#[cfg(feature = "serde")]
855#[derive(Serialize, Deserialize)]
856#[serde(transparent)]
857struct RecordProofBinary([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
858
859#[cfg(feature = "serde")]
860#[derive(Serialize, Deserialize)]
861#[serde(transparent)]
862struct RecordProofHexHash(#[serde(with = "hex")] [u8; OUT_LEN]);
863
864#[cfg(feature = "serde")]
865#[derive(Serialize, Deserialize)]
866#[serde(transparent)]
867struct RecordProofHex([RecordProofHexHash; RecordProof::NUM_HASHES]);
868
869#[cfg(feature = "serde")]
870impl Serialize for RecordProof {
871 #[inline]
872 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
873 where
874 S: Serializer,
875 {
876 if serializer.is_human_readable() {
877 RecordProofHex(unsafe {
880 mem::transmute::<
881 [[u8; OUT_LEN]; Self::NUM_HASHES],
882 [RecordProofHexHash; Self::NUM_HASHES],
883 >(self.0)
884 })
885 .serialize(serializer)
886 } else {
887 RecordProofBinary(self.0).serialize(serializer)
888 }
889 }
890}
891
892#[cfg(feature = "serde")]
893impl<'de> Deserialize<'de> for RecordProof {
894 #[inline]
895 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
896 where
897 D: Deserializer<'de>,
898 {
899 Ok(Self(if deserializer.is_human_readable() {
900 unsafe {
903 mem::transmute::<
904 [RecordProofHexHash; Self::NUM_HASHES],
905 [[u8; OUT_LEN]; Self::NUM_HASHES],
906 >(RecordProofHex::deserialize(deserializer)?.0)
907 }
908 } else {
909 RecordProofBinary::deserialize(deserializer)?.0
910 }))
911 }
912}
913
914impl Default for RecordProof {
915 #[inline]
916 fn default() -> Self {
917 Self([[0; OUT_LEN]; _])
918 }
919}
920
921impl AsRef<[u8]> for RecordProof {
922 #[inline]
923 fn as_ref(&self) -> &[u8] {
924 self.0.as_flattened()
925 }
926}
927
928impl AsMut<[u8]> for RecordProof {
929 #[inline]
930 fn as_mut(&mut self) -> &mut [u8] {
931 self.0.as_flattened_mut()
932 }
933}
934
935impl From<&RecordProof> for &[u8; RecordProof::SIZE] {
936 #[inline]
937 fn from(value: &RecordProof) -> Self {
938 unsafe { mem::transmute(value) }
941 }
942}
943
944impl From<&[u8; RecordProof::SIZE]> for &RecordProof {
945 #[inline]
946 fn from(value: &[u8; RecordProof::SIZE]) -> Self {
947 unsafe { mem::transmute(value) }
950 }
951}
952
953impl From<&mut RecordProof> for &mut [u8; RecordProof::SIZE] {
954 #[inline]
955 fn from(value: &mut RecordProof) -> Self {
956 unsafe { mem::transmute(value) }
959 }
960}
961
962impl From<&mut [u8; RecordProof::SIZE]> for &mut RecordProof {
963 #[inline]
964 fn from(value: &mut [u8; RecordProof::SIZE]) -> Self {
965 unsafe { mem::transmute(value) }
968 }
969}
970
971impl RecordProof {
972 pub const SIZE: usize = OUT_LEN * Self::NUM_HASHES;
974 const NUM_HASHES: usize = RecordedHistorySegment::NUM_PIECES.ilog2() as usize;
975}
976
977#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
979#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
980#[repr(C)]
981pub struct SegmentProof([[u8; OUT_LEN]; SegmentProof::NUM_HASHES]);
982
983impl fmt::Debug for SegmentProof {
984 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
985 write!(f, "[")?;
986 for hash in self.0 {
987 for byte in hash {
988 write!(f, "{byte:02x}")?;
989 }
990 write!(f, ", ")?;
991 }
992 write!(f, "]")?;
993 Ok(())
994 }
995}
996
997#[cfg(feature = "serde")]
998#[derive(Serialize, Deserialize)]
999#[serde(transparent)]
1000struct SegmentProofBinary([[u8; OUT_LEN]; SegmentProof::NUM_HASHES]);
1001
1002#[cfg(feature = "serde")]
1003#[derive(Serialize, Deserialize)]
1004#[serde(transparent)]
1005struct SegmentProofHexHash(#[serde(with = "hex")] [u8; OUT_LEN]);
1006
1007#[cfg(feature = "serde")]
1008#[derive(Serialize, Deserialize)]
1009#[serde(transparent)]
1010struct SegmentProofHex([SegmentProofHexHash; SegmentProof::NUM_HASHES]);
1011
1012#[cfg(feature = "serde")]
1013impl Serialize for SegmentProof {
1014 #[inline]
1015 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1016 where
1017 S: Serializer,
1018 {
1019 if serializer.is_human_readable() {
1020 SegmentProofHex(unsafe {
1023 mem::transmute::<
1024 [[u8; OUT_LEN]; Self::NUM_HASHES],
1025 [SegmentProofHexHash; Self::NUM_HASHES],
1026 >(self.0)
1027 })
1028 .serialize(serializer)
1029 } else {
1030 SegmentProofBinary(self.0).serialize(serializer)
1031 }
1032 }
1033}
1034
1035#[cfg(feature = "serde")]
1036impl<'de> Deserialize<'de> for SegmentProof {
1037 #[inline]
1038 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1039 where
1040 D: Deserializer<'de>,
1041 {
1042 Ok(Self(if deserializer.is_human_readable() {
1043 unsafe {
1046 mem::transmute::<
1047 [SegmentProofHexHash; Self::NUM_HASHES],
1048 [[u8; OUT_LEN]; Self::NUM_HASHES],
1049 >(SegmentProofHex::deserialize(deserializer)?.0)
1050 }
1051 } else {
1052 SegmentProofBinary::deserialize(deserializer)?.0
1053 }))
1054 }
1055}
1056
1057impl Default for SegmentProof {
1058 #[inline]
1059 fn default() -> Self {
1060 Self([[0; OUT_LEN]; _])
1061 }
1062}
1063
1064impl AsRef<[u8]> for SegmentProof {
1065 #[inline]
1066 fn as_ref(&self) -> &[u8] {
1067 self.0.as_flattened()
1068 }
1069}
1070
1071impl AsMut<[u8]> for SegmentProof {
1072 #[inline]
1073 fn as_mut(&mut self) -> &mut [u8] {
1074 self.0.as_flattened_mut()
1075 }
1076}
1077
1078impl From<&SegmentProof> for &[u8; SegmentProof::SIZE] {
1079 #[inline]
1080 fn from(value: &SegmentProof) -> Self {
1081 unsafe { mem::transmute(value) }
1084 }
1085}
1086
1087impl From<&[u8; SegmentProof::SIZE]> for &SegmentProof {
1088 #[inline]
1089 fn from(value: &[u8; SegmentProof::SIZE]) -> Self {
1090 unsafe { mem::transmute(value) }
1093 }
1094}
1095
1096impl From<&mut SegmentProof> for &mut [u8; SegmentProof::SIZE] {
1097 #[inline]
1098 fn from(value: &mut SegmentProof) -> Self {
1099 unsafe { mem::transmute(value) }
1102 }
1103}
1104
1105impl From<&mut [u8; SegmentProof::SIZE]> for &mut SegmentProof {
1106 #[inline]
1107 fn from(value: &mut [u8; SegmentProof::SIZE]) -> Self {
1108 unsafe { mem::transmute(value) }
1111 }
1112}
1113
1114impl SegmentProof {
1115 pub const SIZE: usize = OUT_LEN * Self::NUM_HASHES;
1117 const NUM_HASHES: usize = SuperSegmentRoot::MAX_SEGMENTS.next_power_of_two().ilog2() as usize;
1118
1119 pub fn as_uninit_repr(
1123 &mut self,
1124 ) -> &mut [MaybeUninit<[u8; OUT_LEN]>; SegmentProof::NUM_HASHES] {
1125 unsafe { mem::transmute(&mut self.0) }
1127 }
1128}
1129
1130#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, TrivialType)]
1134#[cfg_attr(feature = "scale-codec", derive(Encode, Decode))]
1135#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1136#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1137#[repr(C)]
1138pub struct PieceHeader {
1139 pub shard_index: Unaligned<ShardIndex>,
1141 pub local_segment_index: Unaligned<LocalSegmentIndex>,
1143 pub super_segment_index: Unaligned<SuperSegmentIndex>,
1145 pub segment_position: Unaligned<SegmentPosition>,
1147 pub segment_root: SegmentRoot,
1149 pub segment_proof: SegmentProof,
1151 pub parity_chunks_root: RecordChunksRoot,
1155 pub record_proof: RecordProof,
1157}
1158
1159const {
1160 assert!(align_of::<PieceHeader>() == 1);
1162}
1163
1164#[derive(Debug, Copy, Clone, Eq, PartialEq, TrivialType)]
1173#[repr(C)]
1174pub struct InnerPiece {
1175 pub header: PieceHeader,
1177 pub record: Record,
1179}
1180
1181const {
1182 assert!(align_of::<InnerPiece>() == 1);
1184}
1185
1186impl InnerPiece {
1187 pub const SIZE: usize = size_of::<Self>();
1189
1190 #[inline]
1192 #[cfg(feature = "alloc")]
1193 pub fn new_boxed() -> Box<Self> {
1194 unsafe { Box::<Self>::new_zeroed().assume_init() }
1197 }
1198
1199 pub fn is_valid(
1201 &self,
1202 super_segment_root: &SuperSegmentRoot,
1203 num_segments: u32,
1204 position: PiecePosition,
1205 ) -> bool {
1206 if !self.header.segment_root.is_valid(
1207 self.header.shard_index.as_inner(),
1208 self.header.local_segment_index.as_inner(),
1209 self.header.segment_position.as_inner(),
1210 &self.header.segment_proof,
1211 num_segments,
1212 super_segment_root,
1213 ) {
1214 return false;
1215 }
1216 self.record_root().is_valid(
1217 &self.header.segment_root,
1218 &self.header.record_proof,
1219 position,
1220 )
1221 }
1222
1223 #[inline]
1227 pub fn record_root(&self) -> RecordRoot {
1228 let record_merkle_tree_root = BalancedMerkleTree::compute_root_only(&[
1229 *self.record.source_chunks_root(),
1230 *self.header.parity_chunks_root,
1231 ]);
1232
1233 RecordRoot::from(record_merkle_tree_root)
1234 }
1235
1236 #[inline]
1239 pub fn slice_to_repr(value: &[Self]) -> &[[u8; Self::SIZE]] {
1240 unsafe { mem::transmute(value) }
1243 }
1244
1245 #[inline]
1248 pub fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
1249 unsafe { mem::transmute(value) }
1252 }
1253
1254 #[inline]
1257 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; Self::SIZE]] {
1258 unsafe { mem::transmute(value) }
1261 }
1262
1263 #[inline]
1266 pub fn slice_mut_from_repr(value: &mut [[u8; Self::SIZE]]) -> &mut [Self] {
1267 unsafe { mem::transmute(value) }
1270 }
1271}