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 From,
52 Into,
53 Add,
54 AddAssign,
55 Sub,
56 SubAssign,
57 Mul,
58 MulAssign,
59 Div,
60 DivAssign,
61)]
62#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
63#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
64#[repr(C)]
65pub struct PieceIndex(u64);
66
67impl Step for PieceIndex {
68 #[inline]
69 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
70 u64::steps_between(&start.0, &end.0)
71 }
72
73 #[inline]
74 fn forward_checked(start: Self, count: usize) -> Option<Self> {
75 u64::forward_checked(start.0, count).map(Self)
76 }
77
78 #[inline]
79 fn backward_checked(start: Self, count: usize) -> Option<Self> {
80 u64::backward_checked(start.0, count).map(Self)
81 }
82}
83
84impl PieceIndex {
85 pub const SIZE: usize = size_of::<u64>();
87 pub const ZERO: PieceIndex = PieceIndex(0);
89 pub const ONE: PieceIndex = PieceIndex(1);
91
92 #[inline]
94 pub const fn new(n: u64) -> Self {
95 Self(n)
96 }
97
98 #[inline]
100 pub const fn from_bytes(bytes: [u8; Self::SIZE]) -> Self {
101 Self(u64::from_le_bytes(bytes))
102 }
103
104 #[inline]
106 pub const fn to_bytes(self) -> [u8; Self::SIZE] {
107 self.0.to_le_bytes()
108 }
109
110 #[inline]
112 pub const fn segment_index(&self) -> SegmentIndex {
113 SegmentIndex::new(self.0 / RecordedHistorySegment::NUM_PIECES as u64)
114 }
115
116 #[inline]
118 pub const fn position(&self) -> u32 {
119 (self.0 % RecordedHistorySegment::NUM_PIECES as u64) as u32
121 }
122
123 #[inline]
125 pub const fn is_source(&self) -> bool {
126 self.position() < RecordedHistorySegment::NUM_RAW_RECORDS as u32
127 }
128
129 #[inline]
132 pub const fn next_source_index(&self) -> Self {
133 if self.position() + 1 < RecordedHistorySegment::NUM_RAW_RECORDS as u32 {
134 Self(self.0 + 1)
136 } else {
137 Self(self.0 + RecordedHistorySegment::NUM_RAW_RECORDS as u64)
139 }
140 }
141}
142
143#[derive(
145 Debug,
146 Display,
147 Default,
148 Copy,
149 Clone,
150 Ord,
151 PartialOrd,
152 Eq,
153 PartialEq,
154 Hash,
155 From,
156 Into,
157 Add,
158 AddAssign,
159 Sub,
160 SubAssign,
161 Mul,
162 MulAssign,
163 Div,
164 DivAssign,
165 TrivialType,
166)]
167#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
169#[repr(C)]
170pub struct PieceOffset(u16);
171
172impl Step for PieceOffset {
173 #[inline]
174 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
175 u16::steps_between(&start.0, &end.0)
176 }
177
178 #[inline]
179 fn forward_checked(start: Self, count: usize) -> Option<Self> {
180 u16::forward_checked(start.0, count).map(Self)
181 }
182
183 #[inline]
184 fn backward_checked(start: Self, count: usize) -> Option<Self> {
185 u16::backward_checked(start.0, count).map(Self)
186 }
187}
188
189impl From<PieceOffset> for u32 {
190 #[inline]
191 fn from(original: PieceOffset) -> Self {
192 Self::from(original.0)
193 }
194}
195
196impl From<PieceOffset> for u64 {
197 #[inline]
198 fn from(original: PieceOffset) -> Self {
199 Self::from(original.0)
200 }
201}
202
203impl From<PieceOffset> for usize {
204 #[inline]
205 fn from(original: PieceOffset) -> Self {
206 usize::from(original.0)
207 }
208}
209
210impl PieceOffset {
211 pub const ZERO: PieceOffset = PieceOffset(0);
213 pub const ONE: PieceOffset = PieceOffset(1);
215 pub const SIZE: usize = size_of::<u16>();
217
218 #[inline]
220 pub const fn to_bytes(self) -> [u8; mem::size_of::<u16>()] {
221 self.0.to_le_bytes()
222 }
223}
224
225#[derive(
227 Default,
228 Copy,
229 Clone,
230 Eq,
231 PartialEq,
232 Ord,
233 PartialOrd,
234 Hash,
235 From,
236 Into,
237 AsRef,
238 AsMut,
239 Deref,
240 DerefMut,
241 TrivialType,
242)]
243#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
245#[cfg_attr(feature = "serde", serde(transparent))]
246#[repr(C)]
247pub struct RecordChunk([u8; RecordChunk::SIZE]);
248
249impl fmt::Debug for RecordChunk {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 for byte in self.0 {
252 write!(f, "{byte:02x}")?;
253 }
254 Ok(())
255 }
256}
257
258impl RecordChunk {
259 pub const SIZE: usize = 32;
261
262 #[inline]
264 pub fn slice_to_repr(value: &[Self]) -> &[[u8; RecordChunk::SIZE]] {
265 unsafe { mem::transmute(value) }
267 }
268
269 #[inline]
271 pub fn slice_from_repr(value: &[[u8; RecordChunk::SIZE]]) -> &[Self] {
272 unsafe { mem::transmute(value) }
274 }
275
276 #[inline]
279 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; RecordChunk::SIZE]] {
280 unsafe { mem::transmute(value) }
282 }
283
284 #[inline]
287 pub fn slice_mut_from_repr(value: &mut [[u8; RecordChunk::SIZE]]) -> &mut [Self] {
288 unsafe { mem::transmute(value) }
290 }
291}
292
293#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
297#[repr(C)]
298pub struct Record([[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]);
299
300impl fmt::Debug for Record {
301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302 for byte in self.0.as_flattened() {
303 write!(f, "{byte:02x}")?;
304 }
305 Ok(())
306 }
307}
308
309impl Default for Record {
310 #[inline]
311 fn default() -> Self {
312 Self([Default::default(); Record::NUM_CHUNKS])
313 }
314}
315
316impl AsRef<[u8]> for Record {
317 #[inline]
318 fn as_ref(&self) -> &[u8] {
319 self.0.as_flattened()
320 }
321}
322
323impl AsMut<[u8]> for Record {
324 #[inline]
325 fn as_mut(&mut self) -> &mut [u8] {
326 self.0.as_flattened_mut()
327 }
328}
329
330impl From<&Record> for &[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
331 #[inline]
332 fn from(value: &Record) -> Self {
333 unsafe { mem::transmute(value) }
335 }
336}
337
338impl From<&[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &Record {
339 #[inline]
340 fn from(value: &[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
341 unsafe { mem::transmute(value) }
343 }
344}
345
346impl From<&mut Record> for &mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
347 #[inline]
348 fn from(value: &mut Record) -> Self {
349 unsafe { mem::transmute(value) }
351 }
352}
353
354impl From<&mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &mut Record {
355 #[inline]
356 fn from(value: &mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
357 unsafe { mem::transmute(value) }
359 }
360}
361
362impl From<&Record> for &[u8; Record::SIZE] {
363 #[inline]
364 fn from(value: &Record) -> Self {
365 unsafe { mem::transmute(value) }
368 }
369}
370
371impl From<&[u8; Record::SIZE]> for &Record {
372 #[inline]
373 fn from(value: &[u8; Record::SIZE]) -> Self {
374 unsafe { mem::transmute(value) }
377 }
378}
379
380impl From<&mut Record> for &mut [u8; Record::SIZE] {
381 #[inline]
382 fn from(value: &mut Record) -> Self {
383 unsafe { mem::transmute(value) }
386 }
387}
388
389impl From<&mut [u8; Record::SIZE]> for &mut Record {
390 #[inline]
391 fn from(value: &mut [u8; Record::SIZE]) -> Self {
392 unsafe { mem::transmute(value) }
395 }
396}
397
398impl Record {
399 pub const NUM_CHUNKS: usize = 2_usize.pow(15);
401 pub const NUM_S_BUCKETS: usize = Record::NUM_CHUNKS
405 * RecordedHistorySegment::ERASURE_CODING_RATE.1
406 / RecordedHistorySegment::ERASURE_CODING_RATE.0;
407 pub const SIZE: usize = RecordChunk::SIZE * Record::NUM_CHUNKS;
409
410 #[inline]
412 #[cfg(feature = "alloc")]
413 pub fn new_boxed() -> Box<Self> {
414 unsafe { Box::new_zeroed().assume_init() }
417 }
418
419 #[inline]
421 #[cfg(feature = "alloc")]
422 pub fn new_zero_vec(length: usize) -> Vec<Self> {
423 let mut records = Vec::with_capacity(length);
426 {
427 let slice = records.spare_capacity_mut();
428 let slice = unsafe {
432 slice::from_raw_parts_mut(
433 slice
434 .as_mut_ptr()
435 .cast::<[[mem::MaybeUninit<u8>; RecordChunk::SIZE]; Record::NUM_CHUNKS]>(),
436 length,
437 )
438 };
439 for byte in slice.as_flattened_mut().as_flattened_mut() {
440 byte.write(0);
441 }
442 }
443 unsafe {
445 records.set_len(records.capacity());
446 }
447
448 records
449 }
450
451 #[inline]
454 pub fn slice_to_repr(value: &[Self]) -> &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
455 unsafe { mem::transmute(value) }
457 }
458
459 #[inline]
462 pub fn slice_from_repr(value: &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]]) -> &[Self] {
463 unsafe { mem::transmute(value) }
465 }
466
467 #[inline]
470 pub fn slice_mut_to_repr(
471 value: &mut [Self],
472 ) -> &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
473 unsafe { mem::transmute(value) }
475 }
476
477 #[inline]
480 pub fn slice_mut_from_repr(
481 value: &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]],
482 ) -> &mut [Self] {
483 unsafe { mem::transmute(value) }
485 }
486}
487
488#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
490#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
491#[repr(C)]
492pub struct RecordRoot([u8; RecordRoot::SIZE]);
493
494impl fmt::Debug for RecordRoot {
495 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
496 for byte in self.0 {
497 write!(f, "{byte:02x}")?;
498 }
499 Ok(())
500 }
501}
502
503#[cfg(feature = "serde")]
504#[derive(Serialize, Deserialize)]
505#[serde(transparent)]
506struct RecordRootBinary(#[serde(with = "BigArray")] [u8; RecordRoot::SIZE]);
507
508#[cfg(feature = "serde")]
509#[derive(Serialize, Deserialize)]
510#[serde(transparent)]
511struct RecordRootHex(#[serde(with = "hex")] [u8; RecordRoot::SIZE]);
512
513#[cfg(feature = "serde")]
514impl Serialize for RecordRoot {
515 #[inline]
516 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
517 where
518 S: Serializer,
519 {
520 if serializer.is_human_readable() {
521 RecordRootHex(self.0).serialize(serializer)
522 } else {
523 RecordRootBinary(self.0).serialize(serializer)
524 }
525 }
526}
527
528#[cfg(feature = "serde")]
529impl<'de> Deserialize<'de> for RecordRoot {
530 #[inline]
531 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
532 where
533 D: Deserializer<'de>,
534 {
535 Ok(Self(if deserializer.is_human_readable() {
536 RecordRootHex::deserialize(deserializer)?.0
537 } else {
538 RecordRootBinary::deserialize(deserializer)?.0
539 }))
540 }
541}
542
543impl Default for RecordRoot {
544 #[inline]
545 fn default() -> Self {
546 Self([0; Self::SIZE])
547 }
548}
549
550impl TryFrom<&[u8]> for RecordRoot {
551 type Error = TryFromSliceError;
552
553 #[inline]
554 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
555 <[u8; Self::SIZE]>::try_from(slice).map(Self)
556 }
557}
558
559impl AsRef<[u8]> for RecordRoot {
560 #[inline]
561 fn as_ref(&self) -> &[u8] {
562 &self.0
563 }
564}
565
566impl AsMut<[u8]> for RecordRoot {
567 #[inline]
568 fn as_mut(&mut self) -> &mut [u8] {
569 &mut self.0
570 }
571}
572
573impl From<&RecordRoot> for &[u8; RecordRoot::SIZE] {
574 #[inline]
575 fn from(value: &RecordRoot) -> Self {
576 unsafe { mem::transmute(value) }
579 }
580}
581
582impl From<&[u8; RecordRoot::SIZE]> for &RecordRoot {
583 #[inline]
584 fn from(value: &[u8; RecordRoot::SIZE]) -> Self {
585 unsafe { mem::transmute(value) }
588 }
589}
590
591impl From<&mut RecordRoot> for &mut [u8; RecordRoot::SIZE] {
592 #[inline]
593 fn from(value: &mut RecordRoot) -> Self {
594 unsafe { mem::transmute(value) }
597 }
598}
599
600impl From<&mut [u8; RecordRoot::SIZE]> for &mut RecordRoot {
601 #[inline]
602 fn from(value: &mut [u8; RecordRoot::SIZE]) -> Self {
603 unsafe { mem::transmute(value) }
606 }
607}
608
609impl RecordRoot {
610 pub const SIZE: usize = 32;
612
613 pub fn is_valid(
615 &self,
616 segment_root: &SegmentRoot,
617 record_proof: &RecordProof,
618 position: u32,
619 ) -> bool {
620 BalancedMerkleTree::<{ RecordedHistorySegment::NUM_PIECES }>::verify(
621 segment_root,
622 record_proof,
623 position as usize,
624 self.0,
625 )
626 }
627}
628
629#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into)]
631#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
632pub struct RecordChunksRoot([u8; RecordChunksRoot::SIZE]);
633
634impl fmt::Debug for RecordChunksRoot {
635 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
636 for byte in self.0 {
637 write!(f, "{byte:02x}")?;
638 }
639 Ok(())
640 }
641}
642
643#[cfg(feature = "serde")]
644#[derive(Serialize, Deserialize)]
645#[serde(transparent)]
646struct RecordChunksRootBinary(#[serde(with = "BigArray")] [u8; RecordChunksRoot::SIZE]);
647
648#[cfg(feature = "serde")]
649#[derive(Serialize, Deserialize)]
650#[serde(transparent)]
651struct RecordChunksRootHex(#[serde(with = "hex")] [u8; RecordChunksRoot::SIZE]);
652
653#[cfg(feature = "serde")]
654impl Serialize for RecordChunksRoot {
655 #[inline]
656 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
657 where
658 S: Serializer,
659 {
660 if serializer.is_human_readable() {
661 RecordChunksRootHex(self.0).serialize(serializer)
662 } else {
663 RecordChunksRootBinary(self.0).serialize(serializer)
664 }
665 }
666}
667
668#[cfg(feature = "serde")]
669impl<'de> Deserialize<'de> for RecordChunksRoot {
670 #[inline]
671 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
672 where
673 D: Deserializer<'de>,
674 {
675 Ok(Self(if deserializer.is_human_readable() {
676 RecordChunksRootHex::deserialize(deserializer)?.0
677 } else {
678 RecordChunksRootBinary::deserialize(deserializer)?.0
679 }))
680 }
681}
682
683impl Default for RecordChunksRoot {
684 #[inline]
685 fn default() -> Self {
686 Self([0; Self::SIZE])
687 }
688}
689
690impl TryFrom<&[u8]> for RecordChunksRoot {
691 type Error = TryFromSliceError;
692
693 #[inline]
694 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
695 <[u8; Self::SIZE]>::try_from(slice).map(Self)
696 }
697}
698
699impl AsRef<[u8]> for RecordChunksRoot {
700 #[inline]
701 fn as_ref(&self) -> &[u8] {
702 &self.0
703 }
704}
705
706impl AsMut<[u8]> for RecordChunksRoot {
707 #[inline]
708 fn as_mut(&mut self) -> &mut [u8] {
709 &mut self.0
710 }
711}
712
713impl From<&RecordChunksRoot> for &[u8; RecordChunksRoot::SIZE] {
714 #[inline]
715 fn from(value: &RecordChunksRoot) -> Self {
716 unsafe { mem::transmute(value) }
719 }
720}
721
722impl From<&[u8; RecordChunksRoot::SIZE]> for &RecordChunksRoot {
723 #[inline]
724 fn from(value: &[u8; RecordChunksRoot::SIZE]) -> Self {
725 unsafe { mem::transmute(value) }
728 }
729}
730
731impl From<&mut RecordChunksRoot> for &mut [u8; RecordChunksRoot::SIZE] {
732 #[inline]
733 fn from(value: &mut RecordChunksRoot) -> Self {
734 unsafe { mem::transmute(value) }
737 }
738}
739
740impl From<&mut [u8; RecordChunksRoot::SIZE]> for &mut RecordChunksRoot {
741 #[inline]
742 fn from(value: &mut [u8; RecordChunksRoot::SIZE]) -> Self {
743 unsafe { mem::transmute(value) }
746 }
747}
748
749impl RecordChunksRoot {
750 pub const SIZE: usize = 32;
752}
753
754#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
756#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, MaxEncodedLen))]
757#[repr(C)]
758pub struct RecordProof([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
759
760impl fmt::Debug for RecordProof {
761 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
762 write!(f, "[")?;
763 for hash in self.0 {
764 for byte in hash {
765 write!(f, "{byte:02x}")?;
766 }
767 write!(f, ", ")?;
768 }
769 write!(f, "]")?;
770 Ok(())
771 }
772}
773
774#[cfg(feature = "serde")]
775#[derive(Serialize, Deserialize)]
776#[serde(transparent)]
777struct RecordProofBinary([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
778
779#[cfg(feature = "serde")]
780#[derive(Serialize, Deserialize)]
781#[serde(transparent)]
782struct RecordProofHexHash(#[serde(with = "hex")] [u8; OUT_LEN]);
783
784#[cfg(feature = "serde")]
785#[derive(Serialize, Deserialize)]
786#[serde(transparent)]
787struct RecordProofHex([RecordProofHexHash; RecordProof::NUM_HASHES]);
788
789#[cfg(feature = "serde")]
790impl Serialize for RecordProof {
791 #[inline]
792 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
793 where
794 S: Serializer,
795 {
796 if serializer.is_human_readable() {
797 RecordProofHex(unsafe {
800 mem::transmute::<
801 [[u8; OUT_LEN]; RecordProof::NUM_HASHES],
802 [RecordProofHexHash; RecordProof::NUM_HASHES],
803 >(self.0)
804 })
805 .serialize(serializer)
806 } else {
807 RecordProofBinary(self.0).serialize(serializer)
808 }
809 }
810}
811
812#[cfg(feature = "serde")]
813impl<'de> Deserialize<'de> for RecordProof {
814 #[inline]
815 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
816 where
817 D: Deserializer<'de>,
818 {
819 Ok(Self(if deserializer.is_human_readable() {
820 unsafe {
823 mem::transmute::<
824 [RecordProofHexHash; RecordProof::NUM_HASHES],
825 [[u8; OUT_LEN]; RecordProof::NUM_HASHES],
826 >(RecordProofHex::deserialize(deserializer)?.0)
827 }
828 } else {
829 RecordProofBinary::deserialize(deserializer)?.0
830 }))
831 }
832}
833
834impl Default for RecordProof {
835 #[inline]
836 fn default() -> Self {
837 Self([[0; OUT_LEN]; RecordProof::NUM_HASHES])
838 }
839}
840
841impl AsRef<[u8]> for RecordProof {
842 #[inline]
843 fn as_ref(&self) -> &[u8] {
844 self.0.as_flattened()
845 }
846}
847
848impl AsMut<[u8]> for RecordProof {
849 #[inline]
850 fn as_mut(&mut self) -> &mut [u8] {
851 self.0.as_flattened_mut()
852 }
853}
854
855impl From<&RecordProof> for &[u8; RecordProof::SIZE] {
856 #[inline]
857 fn from(value: &RecordProof) -> Self {
858 unsafe { mem::transmute(value) }
861 }
862}
863
864impl From<&[u8; RecordProof::SIZE]> for &RecordProof {
865 #[inline]
866 fn from(value: &[u8; RecordProof::SIZE]) -> Self {
867 unsafe { mem::transmute(value) }
870 }
871}
872
873impl From<&mut RecordProof> for &mut [u8; RecordProof::SIZE] {
874 #[inline]
875 fn from(value: &mut RecordProof) -> Self {
876 unsafe { mem::transmute(value) }
879 }
880}
881
882impl From<&mut [u8; RecordProof::SIZE]> for &mut RecordProof {
883 #[inline]
884 fn from(value: &mut [u8; RecordProof::SIZE]) -> Self {
885 unsafe { mem::transmute(value) }
888 }
889}
890
891impl RecordProof {
892 pub const SIZE: usize = OUT_LEN * Self::NUM_HASHES;
894 const NUM_HASHES: usize = RecordedHistorySegment::NUM_PIECES.ilog2() as usize;
895}
896
897#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deref, DerefMut, AsRef, AsMut)]
905#[repr(C)]
906pub struct PieceArray([u8; PieceArray::SIZE]);
907
908impl fmt::Debug for PieceArray {
909 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
910 for byte in self.0 {
911 write!(f, "{byte:02x}")?;
912 }
913 Ok(())
914 }
915}
916
917impl Default for PieceArray {
918 #[inline]
919 fn default() -> Self {
920 Self([0u8; Self::SIZE])
921 }
922}
923
924impl AsRef<[u8]> for PieceArray {
925 #[inline]
926 fn as_ref(&self) -> &[u8] {
927 &self.0
928 }
929}
930
931impl AsMut<[u8]> for PieceArray {
932 #[inline]
933 fn as_mut(&mut self) -> &mut [u8] {
934 &mut self.0
935 }
936}
937
938impl From<&PieceArray> for &[u8; PieceArray::SIZE] {
939 #[inline]
940 fn from(value: &PieceArray) -> Self {
941 unsafe { mem::transmute(value) }
944 }
945}
946
947impl From<&[u8; PieceArray::SIZE]> for &PieceArray {
948 #[inline]
949 fn from(value: &[u8; PieceArray::SIZE]) -> Self {
950 unsafe { mem::transmute(value) }
953 }
954}
955
956impl From<&mut PieceArray> for &mut [u8; PieceArray::SIZE] {
957 #[inline]
958 fn from(value: &mut PieceArray) -> Self {
959 unsafe { mem::transmute(value) }
962 }
963}
964
965impl From<&mut [u8; PieceArray::SIZE]> for &mut PieceArray {
966 #[inline]
967 fn from(value: &mut [u8; PieceArray::SIZE]) -> Self {
968 unsafe { mem::transmute(value) }
971 }
972}
973
974impl PieceArray {
975 pub const SIZE: usize =
977 Record::SIZE + RecordRoot::SIZE + RecordChunksRoot::SIZE + RecordProof::SIZE;
978
979 #[inline]
981 #[cfg(feature = "alloc")]
982 pub fn new_boxed() -> Box<Self> {
983 unsafe { Box::<Self>::new_zeroed().assume_init() }
986 }
987
988 pub fn is_valid(&self, segment_root: &SegmentRoot, position: u32) -> bool {
990 let (record, &record_root, parity_chunks_root, record_proof) = self.split();
991
992 let source_record_merkle_tree_root = BalancedMerkleTree::compute_root_only(record);
993 let record_merkle_tree_root = BalancedMerkleTree::compute_root_only(&[
994 source_record_merkle_tree_root,
995 **parity_chunks_root,
996 ]);
997
998 if record_merkle_tree_root != *record_root {
999 return false;
1000 }
1001
1002 record_root.is_valid(segment_root, record_proof, position)
1003 }
1004
1005 #[inline]
1007 pub fn split(&self) -> (&Record, &RecordRoot, &RecordChunksRoot, &RecordProof) {
1008 let (record, extra) = self.0.split_at(Record::SIZE);
1009 let (root, extra) = extra.split_at(RecordRoot::SIZE);
1010 let (parity_chunks_root, proof) = extra.split_at(RecordChunksRoot::SIZE);
1011
1012 let record = <&[u8; Record::SIZE]>::try_from(record)
1013 .expect("Slice of memory has correct length; qed");
1014 let root = <&[u8; RecordRoot::SIZE]>::try_from(root)
1015 .expect("Slice of memory has correct length; qed");
1016 let parity_chunks_root = <&[u8; RecordChunksRoot::SIZE]>::try_from(parity_chunks_root)
1017 .expect("Slice of memory has correct length; qed");
1018 let proof = <&[u8; RecordProof::SIZE]>::try_from(proof)
1019 .expect("Slice of memory has correct length; qed");
1020
1021 (
1022 record.into(),
1023 root.into(),
1024 parity_chunks_root.into(),
1025 proof.into(),
1026 )
1027 }
1028
1029 #[inline]
1031 pub fn split_mut(
1032 &mut self,
1033 ) -> (
1034 &mut Record,
1035 &mut RecordRoot,
1036 &mut RecordChunksRoot,
1037 &mut RecordProof,
1038 ) {
1039 let (record, extra) = self.0.split_at_mut(Record::SIZE);
1040 let (root, extra) = extra.split_at_mut(RecordRoot::SIZE);
1041 let (parity_chunks_root, proof) = extra.split_at_mut(RecordChunksRoot::SIZE);
1042
1043 let record = <&mut [u8; Record::SIZE]>::try_from(record)
1044 .expect("Slice of memory has correct length; qed");
1045 let root = <&mut [u8; RecordRoot::SIZE]>::try_from(root)
1046 .expect("Slice of memory has correct length; qed");
1047 let parity_chunks_root = <&mut [u8; RecordChunksRoot::SIZE]>::try_from(parity_chunks_root)
1048 .expect("Slice of memory has correct length; qed");
1049 let proof = <&mut [u8; RecordProof::SIZE]>::try_from(proof)
1050 .expect("Slice of memory has correct length; qed");
1051
1052 (
1053 record.into(),
1054 root.into(),
1055 parity_chunks_root.into(),
1056 proof.into(),
1057 )
1058 }
1059
1060 #[inline]
1062 pub fn record(&self) -> &Record {
1063 self.split().0
1064 }
1065
1066 #[inline]
1068 pub fn record_mut(&mut self) -> &mut Record {
1069 self.split_mut().0
1070 }
1071
1072 #[inline]
1074 pub fn root(&self) -> &RecordRoot {
1075 self.split().1
1076 }
1077
1078 #[inline]
1080 pub fn root_mut(&mut self) -> &mut RecordRoot {
1081 self.split_mut().1
1082 }
1083
1084 #[inline]
1086 pub fn parity_chunks_root(&self) -> &RecordChunksRoot {
1087 self.split().2
1088 }
1089
1090 #[inline]
1092 pub fn parity_chunks_root_mut(&mut self) -> &mut RecordChunksRoot {
1093 self.split_mut().2
1094 }
1095
1096 #[inline]
1098 pub fn proof(&self) -> &RecordProof {
1099 self.split().3
1100 }
1101
1102 #[inline]
1104 pub fn proof_mut(&mut self) -> &mut RecordProof {
1105 self.split_mut().3
1106 }
1107
1108 #[inline]
1111 pub fn slice_to_repr(value: &[Self]) -> &[[u8; Self::SIZE]] {
1112 unsafe { mem::transmute(value) }
1115 }
1116
1117 #[inline]
1120 pub fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
1121 unsafe { mem::transmute(value) }
1124 }
1125
1126 #[inline]
1129 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; Self::SIZE]] {
1130 unsafe { mem::transmute(value) }
1133 }
1134
1135 #[inline]
1138 pub fn slice_mut_from_repr(value: &mut [[u8; Self::SIZE]]) -> &mut [Self] {
1139 unsafe { mem::transmute(value) }
1142 }
1143}
1144
1145#[cfg(feature = "alloc")]
1146impl From<Box<PieceArray>> for Vec<u8> {
1147 fn from(value: Box<PieceArray>) -> Self {
1148 let mut value = mem::ManuallyDrop::new(value);
1149 unsafe { Vec::from_raw_parts(value.as_mut_ptr(), PieceArray::SIZE, PieceArray::SIZE) }
1151 }
1152}