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::{RecordedHistorySegment, SegmentIndex, SegmentRoot};
15#[cfg(feature = "serde")]
16use ::serde::{Deserialize, Deserializer, Serialize, Serializer};
17use ab_io_type::trivial_type::TrivialType;
18use ab_merkle_tree::balanced::BalancedMerkleTree;
19#[cfg(feature = "alloc")]
20use alloc::boxed::Box;
21#[cfg(feature = "alloc")]
22use alloc::vec::Vec;
23use blake3::OUT_LEN;
24use core::array::TryFromSliceError;
25use core::hash::Hash;
26use core::iter::Step;
27#[cfg(feature = "alloc")]
28use core::slice;
29use core::{fmt, mem};
30use derive_more::{
31 Add, AddAssign, AsMut, AsRef, Deref, DerefMut, Display, Div, DivAssign, From, Into, Mul,
32 MulAssign, Sub, SubAssign,
33};
34#[cfg(feature = "scale-codec")]
35use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
36#[cfg(feature = "serde")]
37use serde_big_array::BigArray;
38
39#[derive(
41 Debug,
42 Display,
43 Default,
44 Copy,
45 Clone,
46 Ord,
47 PartialOrd,
48 Eq,
49 PartialEq,
50 Hash,
51 Add,
52 AddAssign,
53 Sub,
54 SubAssign,
55 Mul,
56 MulAssign,
57 Div,
58 DivAssign,
59)]
60#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62#[repr(C)]
63pub struct PieceIndex(u64);
64
65impl Step for PieceIndex {
66 #[inline]
67 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
68 u64::steps_between(&start.0, &end.0)
69 }
70
71 #[inline]
72 fn forward_checked(start: Self, count: usize) -> Option<Self> {
73 u64::forward_checked(start.0, count).map(Self)
74 }
75
76 #[inline]
77 fn backward_checked(start: Self, count: usize) -> Option<Self> {
78 u64::backward_checked(start.0, count).map(Self)
79 }
80}
81
82impl const From<u64> for PieceIndex {
83 #[inline(always)]
84 fn from(value: u64) -> Self {
85 Self(value)
86 }
87}
88
89impl const From<PieceIndex> for u64 {
90 #[inline(always)]
91 fn from(value: PieceIndex) -> Self {
92 value.0
93 }
94}
95
96impl PieceIndex {
97 pub const SIZE: usize = size_of::<u64>();
99 pub const ZERO: PieceIndex = PieceIndex(0);
101 pub const ONE: PieceIndex = PieceIndex(1);
103
104 #[inline]
106 pub const fn from_bytes(bytes: [u8; Self::SIZE]) -> Self {
107 Self(u64::from_le_bytes(bytes))
108 }
109
110 #[inline]
112 pub const fn to_bytes(self) -> [u8; Self::SIZE] {
113 self.0.to_le_bytes()
114 }
115
116 #[inline]
118 pub const fn segment_index(&self) -> SegmentIndex {
119 SegmentIndex::from(self.0 / RecordedHistorySegment::NUM_PIECES as u64)
120 }
121
122 #[inline]
124 pub fn position(&self) -> PiecePosition {
125 PiecePosition::from((self.0 % RecordedHistorySegment::NUM_PIECES as u64) as u8)
126 }
127}
128
129const {
130 assert!(RecordedHistorySegment::NUM_PIECES == usize::from(u8::MAX) + 1);
132}
133
134#[derive(
136 Debug,
137 Display,
138 Default,
139 Copy,
140 Clone,
141 Ord,
142 PartialOrd,
143 Eq,
144 PartialEq,
145 Hash,
146 From,
147 Into,
148 TrivialType,
149)]
150#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
151#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
152#[repr(C)]
153pub struct PiecePosition(u8);
154
155impl Step for PiecePosition {
156 #[inline]
157 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
158 u8::steps_between(&start.0, &end.0)
159 }
160
161 #[inline]
162 fn forward_checked(start: Self, count: usize) -> Option<Self> {
163 u8::forward_checked(start.0, count).map(Self)
164 }
165
166 #[inline]
167 fn backward_checked(start: Self, count: usize) -> Option<Self> {
168 u8::backward_checked(start.0, count).map(Self)
169 }
170}
171
172impl From<PiecePosition> for u16 {
173 #[inline]
174 fn from(original: PiecePosition) -> Self {
175 Self::from(original.0)
176 }
177}
178
179impl From<PiecePosition> for u32 {
180 #[inline]
181 fn from(original: PiecePosition) -> Self {
182 Self::from(original.0)
183 }
184}
185
186impl From<PiecePosition> for u64 {
187 #[inline]
188 fn from(original: PiecePosition) -> Self {
189 Self::from(original.0)
190 }
191}
192
193impl From<PiecePosition> for usize {
194 #[inline]
195 fn from(original: PiecePosition) -> Self {
196 usize::from(original.0)
197 }
198}
199
200#[derive(
202 Debug,
203 Display,
204 Default,
205 Copy,
206 Clone,
207 Ord,
208 PartialOrd,
209 Eq,
210 PartialEq,
211 Hash,
212 From,
213 Into,
214 Add,
215 AddAssign,
216 Sub,
217 SubAssign,
218 Mul,
219 MulAssign,
220 Div,
221 DivAssign,
222 TrivialType,
223)]
224#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
226#[repr(C)]
227pub struct PieceOffset(u16);
228
229impl Step for PieceOffset {
230 #[inline]
231 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
232 u16::steps_between(&start.0, &end.0)
233 }
234
235 #[inline]
236 fn forward_checked(start: Self, count: usize) -> Option<Self> {
237 u16::forward_checked(start.0, count).map(Self)
238 }
239
240 #[inline]
241 fn backward_checked(start: Self, count: usize) -> Option<Self> {
242 u16::backward_checked(start.0, count).map(Self)
243 }
244}
245
246impl From<PieceOffset> for u32 {
247 #[inline]
248 fn from(original: PieceOffset) -> Self {
249 Self::from(original.0)
250 }
251}
252
253impl From<PieceOffset> for u64 {
254 #[inline]
255 fn from(original: PieceOffset) -> Self {
256 Self::from(original.0)
257 }
258}
259
260impl From<PieceOffset> for usize {
261 #[inline]
262 fn from(original: PieceOffset) -> Self {
263 usize::from(original.0)
264 }
265}
266
267impl PieceOffset {
268 pub const ZERO: Self = Self(0);
270 pub const ONE: Self = Self(1);
272 pub const SIZE: usize = size_of::<u16>();
274
275 #[inline]
277 pub const fn to_bytes(self) -> [u8; size_of::<u16>()] {
278 self.0.to_le_bytes()
279 }
280}
281
282#[derive(
284 Default,
285 Copy,
286 Clone,
287 Eq,
288 PartialEq,
289 Ord,
290 PartialOrd,
291 Hash,
292 From,
293 Into,
294 AsRef,
295 AsMut,
296 Deref,
297 DerefMut,
298 TrivialType,
299)]
300#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
301#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
302#[cfg_attr(feature = "serde", serde(transparent))]
303#[repr(C)]
304pub struct RecordChunk([u8; RecordChunk::SIZE]);
305
306impl fmt::Debug for RecordChunk {
307 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308 for byte in self.0 {
309 write!(f, "{byte:02x}")?;
310 }
311 Ok(())
312 }
313}
314
315impl RecordChunk {
316 pub const SIZE: usize = 32;
318
319 #[inline]
321 pub fn slice_to_repr(value: &[Self]) -> &[[u8; RecordChunk::SIZE]] {
322 unsafe { mem::transmute(value) }
324 }
325
326 #[inline]
328 pub fn slice_from_repr(value: &[[u8; RecordChunk::SIZE]]) -> &[Self] {
329 unsafe { mem::transmute(value) }
331 }
332
333 #[inline]
336 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; RecordChunk::SIZE]] {
337 unsafe { mem::transmute(value) }
339 }
340
341 #[inline]
344 pub fn slice_mut_from_repr(value: &mut [[u8; RecordChunk::SIZE]]) -> &mut [Self] {
345 unsafe { mem::transmute(value) }
347 }
348}
349
350#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
354#[repr(C)]
355pub struct Record([[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]);
356
357impl fmt::Debug for Record {
358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359 for byte in self.0.as_flattened() {
360 write!(f, "{byte:02x}")?;
361 }
362 Ok(())
363 }
364}
365
366impl Default for Record {
367 #[inline]
368 fn default() -> Self {
369 Self([Default::default(); Record::NUM_CHUNKS])
370 }
371}
372
373impl AsRef<[u8]> for Record {
374 #[inline]
375 fn as_ref(&self) -> &[u8] {
376 self.0.as_flattened()
377 }
378}
379
380impl AsMut<[u8]> for Record {
381 #[inline]
382 fn as_mut(&mut self) -> &mut [u8] {
383 self.0.as_flattened_mut()
384 }
385}
386
387impl From<&Record> for &[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
388 #[inline]
389 fn from(value: &Record) -> Self {
390 unsafe { mem::transmute(value) }
392 }
393}
394
395impl From<&[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &Record {
396 #[inline]
397 fn from(value: &[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
398 unsafe { mem::transmute(value) }
400 }
401}
402
403impl From<&mut Record> for &mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
404 #[inline]
405 fn from(value: &mut Record) -> Self {
406 unsafe { mem::transmute(value) }
408 }
409}
410
411impl From<&mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &mut Record {
412 #[inline]
413 fn from(value: &mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
414 unsafe { mem::transmute(value) }
416 }
417}
418
419impl From<&Record> for &[u8; Record::SIZE] {
420 #[inline]
421 fn from(value: &Record) -> Self {
422 unsafe { mem::transmute(value) }
425 }
426}
427
428impl From<&[u8; Record::SIZE]> for &Record {
429 #[inline]
430 fn from(value: &[u8; Record::SIZE]) -> Self {
431 unsafe { mem::transmute(value) }
434 }
435}
436
437impl From<&mut Record> for &mut [u8; Record::SIZE] {
438 #[inline]
439 fn from(value: &mut Record) -> Self {
440 unsafe { mem::transmute(value) }
443 }
444}
445
446impl From<&mut [u8; Record::SIZE]> for &mut Record {
447 #[inline]
448 fn from(value: &mut [u8; Record::SIZE]) -> Self {
449 unsafe { mem::transmute(value) }
452 }
453}
454
455impl Record {
456 pub const NUM_CHUNKS: usize = 2_usize.pow(15);
458 pub const NUM_S_BUCKETS: usize = Record::NUM_CHUNKS
462 * RecordedHistorySegment::ERASURE_CODING_RATE.1
463 / RecordedHistorySegment::ERASURE_CODING_RATE.0;
464 pub const SIZE: usize = RecordChunk::SIZE * Record::NUM_CHUNKS;
466
467 #[inline]
469 #[cfg(feature = "alloc")]
470 pub fn new_boxed() -> Box<Self> {
471 unsafe { Box::new_zeroed().assume_init() }
474 }
475
476 #[inline]
478 #[cfg(feature = "alloc")]
479 pub fn new_zero_vec(length: usize) -> Vec<Self> {
480 let mut records = Vec::with_capacity(length);
483 {
484 let slice = records.spare_capacity_mut();
485 let slice = unsafe {
489 slice::from_raw_parts_mut(
490 slice
491 .as_mut_ptr()
492 .cast::<[[mem::MaybeUninit<u8>; RecordChunk::SIZE]; Record::NUM_CHUNKS]>(),
493 length,
494 )
495 };
496 for byte in slice.as_flattened_mut().as_flattened_mut() {
497 byte.write(0);
498 }
499 }
500 unsafe {
502 records.set_len(records.capacity());
503 }
504
505 records
506 }
507
508 #[inline]
511 pub fn slice_to_repr(value: &[Self]) -> &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
512 unsafe { mem::transmute(value) }
514 }
515
516 #[inline]
519 pub fn slice_from_repr(value: &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]]) -> &[Self] {
520 unsafe { mem::transmute(value) }
522 }
523
524 #[inline]
527 pub fn slice_mut_to_repr(
528 value: &mut [Self],
529 ) -> &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
530 unsafe { mem::transmute(value) }
532 }
533
534 #[inline]
537 pub fn slice_mut_from_repr(
538 value: &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]],
539 ) -> &mut [Self] {
540 unsafe { mem::transmute(value) }
542 }
543}
544
545#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
547#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
548#[repr(C)]
549pub struct RecordRoot([u8; RecordRoot::SIZE]);
550
551impl fmt::Debug for RecordRoot {
552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553 for byte in self.0 {
554 write!(f, "{byte:02x}")?;
555 }
556 Ok(())
557 }
558}
559
560#[cfg(feature = "serde")]
561#[derive(Serialize, Deserialize)]
562#[serde(transparent)]
563struct RecordRootBinary(#[serde(with = "BigArray")] [u8; RecordRoot::SIZE]);
564
565#[cfg(feature = "serde")]
566#[derive(Serialize, Deserialize)]
567#[serde(transparent)]
568struct RecordRootHex(#[serde(with = "hex")] [u8; RecordRoot::SIZE]);
569
570#[cfg(feature = "serde")]
571impl Serialize for RecordRoot {
572 #[inline]
573 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
574 where
575 S: Serializer,
576 {
577 if serializer.is_human_readable() {
578 RecordRootHex(self.0).serialize(serializer)
579 } else {
580 RecordRootBinary(self.0).serialize(serializer)
581 }
582 }
583}
584
585#[cfg(feature = "serde")]
586impl<'de> Deserialize<'de> for RecordRoot {
587 #[inline]
588 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
589 where
590 D: Deserializer<'de>,
591 {
592 Ok(Self(if deserializer.is_human_readable() {
593 RecordRootHex::deserialize(deserializer)?.0
594 } else {
595 RecordRootBinary::deserialize(deserializer)?.0
596 }))
597 }
598}
599
600impl Default for RecordRoot {
601 #[inline]
602 fn default() -> Self {
603 Self([0; Self::SIZE])
604 }
605}
606
607impl TryFrom<&[u8]> for RecordRoot {
608 type Error = TryFromSliceError;
609
610 #[inline]
611 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
612 <[u8; Self::SIZE]>::try_from(slice).map(Self)
613 }
614}
615
616impl AsRef<[u8]> for RecordRoot {
617 #[inline]
618 fn as_ref(&self) -> &[u8] {
619 &self.0
620 }
621}
622
623impl AsMut<[u8]> for RecordRoot {
624 #[inline]
625 fn as_mut(&mut self) -> &mut [u8] {
626 &mut self.0
627 }
628}
629
630impl From<&RecordRoot> for &[u8; RecordRoot::SIZE] {
631 #[inline]
632 fn from(value: &RecordRoot) -> Self {
633 unsafe { mem::transmute(value) }
636 }
637}
638
639impl From<&[u8; RecordRoot::SIZE]> for &RecordRoot {
640 #[inline]
641 fn from(value: &[u8; RecordRoot::SIZE]) -> Self {
642 unsafe { mem::transmute(value) }
645 }
646}
647
648impl From<&mut RecordRoot> for &mut [u8; RecordRoot::SIZE] {
649 #[inline]
650 fn from(value: &mut RecordRoot) -> Self {
651 unsafe { mem::transmute(value) }
654 }
655}
656
657impl From<&mut [u8; RecordRoot::SIZE]> for &mut RecordRoot {
658 #[inline]
659 fn from(value: &mut [u8; RecordRoot::SIZE]) -> Self {
660 unsafe { mem::transmute(value) }
663 }
664}
665
666impl RecordRoot {
667 pub const SIZE: usize = 32;
669
670 pub fn is_valid(
672 &self,
673 segment_root: &SegmentRoot,
674 record_proof: &RecordProof,
675 position: PiecePosition,
676 ) -> bool {
677 BalancedMerkleTree::<{ RecordedHistorySegment::NUM_PIECES }>::verify(
678 segment_root,
679 record_proof,
680 usize::from(position),
681 self.0,
682 )
683 }
684}
685
686#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into)]
688#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
689pub struct RecordChunksRoot([u8; RecordChunksRoot::SIZE]);
690
691impl fmt::Debug for RecordChunksRoot {
692 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
693 for byte in self.0 {
694 write!(f, "{byte:02x}")?;
695 }
696 Ok(())
697 }
698}
699
700#[cfg(feature = "serde")]
701#[derive(Serialize, Deserialize)]
702#[serde(transparent)]
703struct RecordChunksRootBinary(#[serde(with = "BigArray")] [u8; RecordChunksRoot::SIZE]);
704
705#[cfg(feature = "serde")]
706#[derive(Serialize, Deserialize)]
707#[serde(transparent)]
708struct RecordChunksRootHex(#[serde(with = "hex")] [u8; RecordChunksRoot::SIZE]);
709
710#[cfg(feature = "serde")]
711impl Serialize for RecordChunksRoot {
712 #[inline]
713 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
714 where
715 S: Serializer,
716 {
717 if serializer.is_human_readable() {
718 RecordChunksRootHex(self.0).serialize(serializer)
719 } else {
720 RecordChunksRootBinary(self.0).serialize(serializer)
721 }
722 }
723}
724
725#[cfg(feature = "serde")]
726impl<'de> Deserialize<'de> for RecordChunksRoot {
727 #[inline]
728 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
729 where
730 D: Deserializer<'de>,
731 {
732 Ok(Self(if deserializer.is_human_readable() {
733 RecordChunksRootHex::deserialize(deserializer)?.0
734 } else {
735 RecordChunksRootBinary::deserialize(deserializer)?.0
736 }))
737 }
738}
739
740impl Default for RecordChunksRoot {
741 #[inline]
742 fn default() -> Self {
743 Self([0; Self::SIZE])
744 }
745}
746
747impl TryFrom<&[u8]> for RecordChunksRoot {
748 type Error = TryFromSliceError;
749
750 #[inline]
751 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
752 <[u8; Self::SIZE]>::try_from(slice).map(Self)
753 }
754}
755
756impl AsRef<[u8]> for RecordChunksRoot {
757 #[inline]
758 fn as_ref(&self) -> &[u8] {
759 &self.0
760 }
761}
762
763impl AsMut<[u8]> for RecordChunksRoot {
764 #[inline]
765 fn as_mut(&mut self) -> &mut [u8] {
766 &mut self.0
767 }
768}
769
770impl From<&RecordChunksRoot> for &[u8; RecordChunksRoot::SIZE] {
771 #[inline]
772 fn from(value: &RecordChunksRoot) -> Self {
773 unsafe { mem::transmute(value) }
776 }
777}
778
779impl From<&[u8; RecordChunksRoot::SIZE]> for &RecordChunksRoot {
780 #[inline]
781 fn from(value: &[u8; RecordChunksRoot::SIZE]) -> Self {
782 unsafe { mem::transmute(value) }
785 }
786}
787
788impl From<&mut RecordChunksRoot> for &mut [u8; RecordChunksRoot::SIZE] {
789 #[inline]
790 fn from(value: &mut RecordChunksRoot) -> Self {
791 unsafe { mem::transmute(value) }
794 }
795}
796
797impl From<&mut [u8; RecordChunksRoot::SIZE]> for &mut RecordChunksRoot {
798 #[inline]
799 fn from(value: &mut [u8; RecordChunksRoot::SIZE]) -> Self {
800 unsafe { mem::transmute(value) }
803 }
804}
805
806impl RecordChunksRoot {
807 pub const SIZE: usize = 32;
809}
810
811#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
813#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
814#[repr(C)]
815pub struct RecordProof([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
816
817impl fmt::Debug for RecordProof {
818 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
819 write!(f, "[")?;
820 for hash in self.0 {
821 for byte in hash {
822 write!(f, "{byte:02x}")?;
823 }
824 write!(f, ", ")?;
825 }
826 write!(f, "]")?;
827 Ok(())
828 }
829}
830
831#[cfg(feature = "serde")]
832#[derive(Serialize, Deserialize)]
833#[serde(transparent)]
834struct RecordProofBinary([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
835
836#[cfg(feature = "serde")]
837#[derive(Serialize, Deserialize)]
838#[serde(transparent)]
839struct RecordProofHexHash(#[serde(with = "hex")] [u8; OUT_LEN]);
840
841#[cfg(feature = "serde")]
842#[derive(Serialize, Deserialize)]
843#[serde(transparent)]
844struct RecordProofHex([RecordProofHexHash; RecordProof::NUM_HASHES]);
845
846#[cfg(feature = "serde")]
847impl Serialize for RecordProof {
848 #[inline]
849 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
850 where
851 S: Serializer,
852 {
853 if serializer.is_human_readable() {
854 RecordProofHex(unsafe {
857 mem::transmute::<
858 [[u8; OUT_LEN]; RecordProof::NUM_HASHES],
859 [RecordProofHexHash; RecordProof::NUM_HASHES],
860 >(self.0)
861 })
862 .serialize(serializer)
863 } else {
864 RecordProofBinary(self.0).serialize(serializer)
865 }
866 }
867}
868
869#[cfg(feature = "serde")]
870impl<'de> Deserialize<'de> for RecordProof {
871 #[inline]
872 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
873 where
874 D: Deserializer<'de>,
875 {
876 Ok(Self(if deserializer.is_human_readable() {
877 unsafe {
880 mem::transmute::<
881 [RecordProofHexHash; RecordProof::NUM_HASHES],
882 [[u8; OUT_LEN]; RecordProof::NUM_HASHES],
883 >(RecordProofHex::deserialize(deserializer)?.0)
884 }
885 } else {
886 RecordProofBinary::deserialize(deserializer)?.0
887 }))
888 }
889}
890
891impl Default for RecordProof {
892 #[inline]
893 fn default() -> Self {
894 Self([[0; OUT_LEN]; RecordProof::NUM_HASHES])
895 }
896}
897
898impl AsRef<[u8]> for RecordProof {
899 #[inline]
900 fn as_ref(&self) -> &[u8] {
901 self.0.as_flattened()
902 }
903}
904
905impl AsMut<[u8]> for RecordProof {
906 #[inline]
907 fn as_mut(&mut self) -> &mut [u8] {
908 self.0.as_flattened_mut()
909 }
910}
911
912impl From<&RecordProof> for &[u8; RecordProof::SIZE] {
913 #[inline]
914 fn from(value: &RecordProof) -> Self {
915 unsafe { mem::transmute(value) }
918 }
919}
920
921impl From<&[u8; RecordProof::SIZE]> for &RecordProof {
922 #[inline]
923 fn from(value: &[u8; RecordProof::SIZE]) -> Self {
924 unsafe { mem::transmute(value) }
927 }
928}
929
930impl From<&mut RecordProof> for &mut [u8; RecordProof::SIZE] {
931 #[inline]
932 fn from(value: &mut RecordProof) -> Self {
933 unsafe { mem::transmute(value) }
936 }
937}
938
939impl From<&mut [u8; RecordProof::SIZE]> for &mut RecordProof {
940 #[inline]
941 fn from(value: &mut [u8; RecordProof::SIZE]) -> Self {
942 unsafe { mem::transmute(value) }
945 }
946}
947
948impl RecordProof {
949 pub const SIZE: usize = OUT_LEN * Self::NUM_HASHES;
951 const NUM_HASHES: usize = RecordedHistorySegment::NUM_PIECES.ilog2() as usize;
952}
953
954#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deref, DerefMut, AsRef, AsMut)]
962#[repr(C)]
963pub struct PieceArray([u8; PieceArray::SIZE]);
964
965impl fmt::Debug for PieceArray {
966 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
967 for byte in self.0 {
968 write!(f, "{byte:02x}")?;
969 }
970 Ok(())
971 }
972}
973
974impl Default for PieceArray {
975 #[inline]
976 fn default() -> Self {
977 Self([0u8; Self::SIZE])
978 }
979}
980
981impl AsRef<[u8]> for PieceArray {
982 #[inline]
983 fn as_ref(&self) -> &[u8] {
984 &self.0
985 }
986}
987
988impl AsMut<[u8]> for PieceArray {
989 #[inline]
990 fn as_mut(&mut self) -> &mut [u8] {
991 &mut self.0
992 }
993}
994
995impl From<&PieceArray> for &[u8; PieceArray::SIZE] {
996 #[inline]
997 fn from(value: &PieceArray) -> Self {
998 unsafe { mem::transmute(value) }
1001 }
1002}
1003
1004impl From<&[u8; PieceArray::SIZE]> for &PieceArray {
1005 #[inline]
1006 fn from(value: &[u8; PieceArray::SIZE]) -> Self {
1007 unsafe { mem::transmute(value) }
1010 }
1011}
1012
1013impl From<&mut PieceArray> for &mut [u8; PieceArray::SIZE] {
1014 #[inline]
1015 fn from(value: &mut PieceArray) -> Self {
1016 unsafe { mem::transmute(value) }
1019 }
1020}
1021
1022impl From<&mut [u8; PieceArray::SIZE]> for &mut PieceArray {
1023 #[inline]
1024 fn from(value: &mut [u8; PieceArray::SIZE]) -> Self {
1025 unsafe { mem::transmute(value) }
1028 }
1029}
1030
1031impl PieceArray {
1032 pub const SIZE: usize =
1034 Record::SIZE + RecordRoot::SIZE + RecordChunksRoot::SIZE + RecordProof::SIZE;
1035
1036 #[inline]
1038 #[cfg(feature = "alloc")]
1039 pub fn new_boxed() -> Box<Self> {
1040 unsafe { Box::<Self>::new_zeroed().assume_init() }
1043 }
1044
1045 pub fn is_valid(&self, segment_root: &SegmentRoot, position: PiecePosition) -> bool {
1047 let (record, &record_root, parity_chunks_root, record_proof) = self.split();
1048
1049 let source_record_merkle_tree_root = BalancedMerkleTree::compute_root_only(record);
1050 let record_merkle_tree_root = BalancedMerkleTree::compute_root_only(&[
1051 source_record_merkle_tree_root,
1052 **parity_chunks_root,
1053 ]);
1054
1055 if record_merkle_tree_root != *record_root {
1056 return false;
1057 }
1058
1059 record_root.is_valid(segment_root, record_proof, position)
1060 }
1061
1062 #[inline]
1064 pub fn split(&self) -> (&Record, &RecordRoot, &RecordChunksRoot, &RecordProof) {
1065 let (record, extra) = self.0.split_at(Record::SIZE);
1066 let (root, extra) = extra.split_at(RecordRoot::SIZE);
1067 let (parity_chunks_root, proof) = extra.split_at(RecordChunksRoot::SIZE);
1068
1069 let record = <&[u8; Record::SIZE]>::try_from(record)
1070 .expect("Slice of memory has correct length; qed");
1071 let root = <&[u8; RecordRoot::SIZE]>::try_from(root)
1072 .expect("Slice of memory has correct length; qed");
1073 let parity_chunks_root = <&[u8; RecordChunksRoot::SIZE]>::try_from(parity_chunks_root)
1074 .expect("Slice of memory has correct length; qed");
1075 let proof = <&[u8; RecordProof::SIZE]>::try_from(proof)
1076 .expect("Slice of memory has correct length; qed");
1077
1078 (
1079 record.into(),
1080 root.into(),
1081 parity_chunks_root.into(),
1082 proof.into(),
1083 )
1084 }
1085
1086 #[inline]
1088 pub fn split_mut(
1089 &mut self,
1090 ) -> (
1091 &mut Record,
1092 &mut RecordRoot,
1093 &mut RecordChunksRoot,
1094 &mut RecordProof,
1095 ) {
1096 let (record, extra) = self.0.split_at_mut(Record::SIZE);
1097 let (root, extra) = extra.split_at_mut(RecordRoot::SIZE);
1098 let (parity_chunks_root, proof) = extra.split_at_mut(RecordChunksRoot::SIZE);
1099
1100 let record = <&mut [u8; Record::SIZE]>::try_from(record)
1101 .expect("Slice of memory has correct length; qed");
1102 let root = <&mut [u8; RecordRoot::SIZE]>::try_from(root)
1103 .expect("Slice of memory has correct length; qed");
1104 let parity_chunks_root = <&mut [u8; RecordChunksRoot::SIZE]>::try_from(parity_chunks_root)
1105 .expect("Slice of memory has correct length; qed");
1106 let proof = <&mut [u8; RecordProof::SIZE]>::try_from(proof)
1107 .expect("Slice of memory has correct length; qed");
1108
1109 (
1110 record.into(),
1111 root.into(),
1112 parity_chunks_root.into(),
1113 proof.into(),
1114 )
1115 }
1116
1117 #[inline]
1119 pub fn record(&self) -> &Record {
1120 self.split().0
1121 }
1122
1123 #[inline]
1125 pub fn record_mut(&mut self) -> &mut Record {
1126 self.split_mut().0
1127 }
1128
1129 #[inline]
1131 pub fn root(&self) -> &RecordRoot {
1132 self.split().1
1133 }
1134
1135 #[inline]
1137 pub fn root_mut(&mut self) -> &mut RecordRoot {
1138 self.split_mut().1
1139 }
1140
1141 #[inline]
1143 pub fn parity_chunks_root(&self) -> &RecordChunksRoot {
1144 self.split().2
1145 }
1146
1147 #[inline]
1149 pub fn parity_chunks_root_mut(&mut self) -> &mut RecordChunksRoot {
1150 self.split_mut().2
1151 }
1152
1153 #[inline]
1155 pub fn proof(&self) -> &RecordProof {
1156 self.split().3
1157 }
1158
1159 #[inline]
1161 pub fn proof_mut(&mut self) -> &mut RecordProof {
1162 self.split_mut().3
1163 }
1164
1165 #[inline]
1168 pub fn slice_to_repr(value: &[Self]) -> &[[u8; Self::SIZE]] {
1169 unsafe { mem::transmute(value) }
1172 }
1173
1174 #[inline]
1177 pub fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
1178 unsafe { mem::transmute(value) }
1181 }
1182
1183 #[inline]
1186 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; Self::SIZE]] {
1187 unsafe { mem::transmute(value) }
1190 }
1191
1192 #[inline]
1195 pub fn slice_mut_from_repr(value: &mut [[u8; Self::SIZE]]) -> &mut [Self] {
1196 unsafe { mem::transmute(value) }
1199 }
1200}
1201
1202#[cfg(feature = "alloc")]
1203impl From<Box<PieceArray>> for Vec<u8> {
1204 fn from(value: Box<PieceArray>) -> Self {
1205 let mut value = mem::ManuallyDrop::new(value);
1206 unsafe { Vec::from_raw_parts(value.as_mut_ptr(), PieceArray::SIZE, PieceArray::SIZE) }
1208 }
1209}