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_hashed::BalancedHashedMerkleTree;
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 = "scale-codec")]
37use scale_info::TypeInfo;
38#[cfg(feature = "serde")]
39use serde_big_array::BigArray;
40
41#[derive(
43 Debug,
44 Display,
45 Default,
46 Copy,
47 Clone,
48 Ord,
49 PartialOrd,
50 Eq,
51 PartialEq,
52 Hash,
53 From,
54 Into,
55 Add,
56 AddAssign,
57 Sub,
58 SubAssign,
59 Mul,
60 MulAssign,
61 Div,
62 DivAssign,
63)]
64#[cfg_attr(
65 feature = "scale-codec",
66 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
67)]
68#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
69#[repr(C)]
70pub struct PieceIndex(u64);
71
72impl Step for PieceIndex {
73 #[inline]
74 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
75 u64::steps_between(&start.0, &end.0)
76 }
77
78 #[inline]
79 fn forward_checked(start: Self, count: usize) -> Option<Self> {
80 u64::forward_checked(start.0, count).map(Self)
81 }
82
83 #[inline]
84 fn backward_checked(start: Self, count: usize) -> Option<Self> {
85 u64::backward_checked(start.0, count).map(Self)
86 }
87}
88
89impl PieceIndex {
90 pub const SIZE: usize = size_of::<u64>();
92 pub const ZERO: PieceIndex = PieceIndex(0);
94 pub const ONE: PieceIndex = PieceIndex(1);
96
97 #[inline]
99 pub const fn new(n: u64) -> Self {
100 Self(n)
101 }
102
103 #[inline]
105 pub const fn from_bytes(bytes: [u8; Self::SIZE]) -> Self {
106 Self(u64::from_le_bytes(bytes))
107 }
108
109 #[inline]
111 pub const fn to_bytes(self) -> [u8; Self::SIZE] {
112 self.0.to_le_bytes()
113 }
114
115 #[inline]
117 pub const fn segment_index(&self) -> SegmentIndex {
118 SegmentIndex::new(self.0 / RecordedHistorySegment::NUM_PIECES as u64)
119 }
120
121 #[inline]
123 pub const fn position(&self) -> u32 {
124 (self.0 % RecordedHistorySegment::NUM_PIECES as u64) as u32
126 }
127
128 #[inline]
130 pub const fn is_source(&self) -> bool {
131 self.position() < RecordedHistorySegment::NUM_RAW_RECORDS as u32
132 }
133
134 #[inline]
137 pub const fn next_source_index(&self) -> Self {
138 if self.position() + 1 < RecordedHistorySegment::NUM_RAW_RECORDS as u32 {
139 Self(self.0 + 1)
141 } else {
142 Self(self.0 + RecordedHistorySegment::NUM_RAW_RECORDS as u64)
144 }
145 }
146}
147
148#[derive(
150 Debug,
151 Display,
152 Default,
153 Copy,
154 Clone,
155 Ord,
156 PartialOrd,
157 Eq,
158 PartialEq,
159 Hash,
160 From,
161 Into,
162 Add,
163 AddAssign,
164 Sub,
165 SubAssign,
166 Mul,
167 MulAssign,
168 Div,
169 DivAssign,
170 TrivialType,
171)]
172#[cfg_attr(
173 feature = "scale-codec",
174 derive(Encode, Decode, MaxEncodedLen, TypeInfo)
175)]
176#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
177#[repr(C)]
178pub struct PieceOffset(u16);
179
180impl Step for PieceOffset {
181 #[inline]
182 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
183 u16::steps_between(&start.0, &end.0)
184 }
185
186 #[inline]
187 fn forward_checked(start: Self, count: usize) -> Option<Self> {
188 u16::forward_checked(start.0, count).map(Self)
189 }
190
191 #[inline]
192 fn backward_checked(start: Self, count: usize) -> Option<Self> {
193 u16::backward_checked(start.0, count).map(Self)
194 }
195}
196
197impl From<PieceOffset> for u32 {
198 #[inline]
199 fn from(original: PieceOffset) -> Self {
200 Self::from(original.0)
201 }
202}
203
204impl From<PieceOffset> for u64 {
205 #[inline]
206 fn from(original: PieceOffset) -> Self {
207 Self::from(original.0)
208 }
209}
210
211impl From<PieceOffset> for usize {
212 #[inline]
213 fn from(original: PieceOffset) -> Self {
214 usize::from(original.0)
215 }
216}
217
218impl PieceOffset {
219 pub const ZERO: PieceOffset = PieceOffset(0);
221 pub const ONE: PieceOffset = PieceOffset(1);
223 pub const SIZE: usize = size_of::<u16>();
225
226 #[inline]
228 pub const fn to_bytes(self) -> [u8; mem::size_of::<u16>()] {
229 self.0.to_le_bytes()
230 }
231}
232
233#[derive(
235 Default,
236 Copy,
237 Clone,
238 Eq,
239 PartialEq,
240 Ord,
241 PartialOrd,
242 Hash,
243 From,
244 Into,
245 AsRef,
246 AsMut,
247 Deref,
248 DerefMut,
249 TrivialType,
250)]
251#[cfg_attr(
252 feature = "scale-codec",
253 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
254)]
255#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
256#[cfg_attr(feature = "serde", serde(transparent))]
257#[repr(C)]
258pub struct RecordChunk([u8; RecordChunk::SIZE]);
259
260impl fmt::Debug for RecordChunk {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 for byte in self.0 {
263 write!(f, "{byte:02x}")?;
264 }
265 Ok(())
266 }
267}
268
269impl RecordChunk {
270 pub const SIZE: usize = 32;
272
273 #[inline]
275 pub fn slice_to_repr(value: &[Self]) -> &[[u8; RecordChunk::SIZE]] {
276 unsafe { mem::transmute(value) }
278 }
279
280 #[inline]
282 pub fn slice_from_repr(value: &[[u8; RecordChunk::SIZE]]) -> &[Self] {
283 unsafe { mem::transmute(value) }
285 }
286
287 #[inline]
290 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; RecordChunk::SIZE]] {
291 unsafe { mem::transmute(value) }
293 }
294
295 #[inline]
298 pub fn slice_mut_from_repr(value: &mut [[u8; RecordChunk::SIZE]]) -> &mut [Self] {
299 unsafe { mem::transmute(value) }
301 }
302}
303
304#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
308#[repr(C)]
309pub struct Record([[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]);
310
311impl fmt::Debug for Record {
312 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
313 for byte in self.0.as_flattened() {
314 write!(f, "{byte:02x}")?;
315 }
316 Ok(())
317 }
318}
319
320impl Default for Record {
321 #[inline]
322 fn default() -> Self {
323 Self([Default::default(); Record::NUM_CHUNKS])
324 }
325}
326
327impl AsRef<[u8]> for Record {
328 #[inline]
329 fn as_ref(&self) -> &[u8] {
330 self.0.as_flattened()
331 }
332}
333
334impl AsMut<[u8]> for Record {
335 #[inline]
336 fn as_mut(&mut self) -> &mut [u8] {
337 self.0.as_flattened_mut()
338 }
339}
340
341impl From<&Record> for &[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
342 #[inline]
343 fn from(value: &Record) -> Self {
344 unsafe { mem::transmute(value) }
346 }
347}
348
349impl From<&[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &Record {
350 #[inline]
351 fn from(value: &[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
352 unsafe { mem::transmute(value) }
354 }
355}
356
357impl From<&mut Record> for &mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS] {
358 #[inline]
359 fn from(value: &mut Record) -> Self {
360 unsafe { mem::transmute(value) }
362 }
363}
364
365impl From<&mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]> for &mut Record {
366 #[inline]
367 fn from(value: &mut [[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]) -> Self {
368 unsafe { mem::transmute(value) }
370 }
371}
372
373impl From<&Record> for &[u8; Record::SIZE] {
374 #[inline]
375 fn from(value: &Record) -> Self {
376 unsafe { mem::transmute(value) }
379 }
380}
381
382impl From<&[u8; Record::SIZE]> for &Record {
383 #[inline]
384 fn from(value: &[u8; Record::SIZE]) -> Self {
385 unsafe { mem::transmute(value) }
388 }
389}
390
391impl From<&mut Record> for &mut [u8; Record::SIZE] {
392 #[inline]
393 fn from(value: &mut Record) -> Self {
394 unsafe { mem::transmute(value) }
397 }
398}
399
400impl From<&mut [u8; Record::SIZE]> for &mut Record {
401 #[inline]
402 fn from(value: &mut [u8; Record::SIZE]) -> Self {
403 unsafe { mem::transmute(value) }
406 }
407}
408
409impl Record {
410 pub const NUM_CHUNKS: usize = 2_usize.pow(15);
412 pub const NUM_S_BUCKETS: usize = Record::NUM_CHUNKS
416 * RecordedHistorySegment::ERASURE_CODING_RATE.1
417 / RecordedHistorySegment::ERASURE_CODING_RATE.0;
418 pub const SIZE: usize = RecordChunk::SIZE * Record::NUM_CHUNKS;
420
421 #[inline]
423 #[cfg(feature = "alloc")]
424 pub fn new_boxed() -> Box<Self> {
425 unsafe { Box::new_zeroed().assume_init() }
428 }
429
430 #[inline]
432 #[cfg(feature = "alloc")]
433 pub fn new_zero_vec(length: usize) -> Vec<Self> {
434 let mut records = Vec::with_capacity(length);
437 {
438 let slice = records.spare_capacity_mut();
439 let slice = unsafe {
443 slice::from_raw_parts_mut(
444 slice.as_mut_ptr()
445 as *mut [[mem::MaybeUninit<u8>; RecordChunk::SIZE]; Record::NUM_CHUNKS],
446 length,
447 )
448 };
449 for byte in slice.as_flattened_mut().as_flattened_mut() {
450 byte.write(0);
451 }
452 }
453 unsafe {
455 records.set_len(records.capacity());
456 }
457
458 records
459 }
460
461 #[inline]
464 pub fn slice_to_repr(value: &[Self]) -> &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
465 unsafe { mem::transmute(value) }
467 }
468
469 #[inline]
472 pub fn slice_from_repr(value: &[[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]]) -> &[Self] {
473 unsafe { mem::transmute(value) }
475 }
476
477 #[inline]
480 pub fn slice_mut_to_repr(
481 value: &mut [Self],
482 ) -> &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]] {
483 unsafe { mem::transmute(value) }
485 }
486
487 #[inline]
490 pub fn slice_mut_from_repr(
491 value: &mut [[[u8; RecordChunk::SIZE]; Record::NUM_CHUNKS]],
492 ) -> &mut [Self] {
493 unsafe { mem::transmute(value) }
495 }
496}
497
498#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
500#[cfg_attr(
501 feature = "scale-codec",
502 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
503)]
504#[repr(C)]
505pub struct RecordRoot([u8; RecordRoot::SIZE]);
506
507impl fmt::Debug for RecordRoot {
508 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509 for byte in self.0 {
510 write!(f, "{byte:02x}")?;
511 }
512 Ok(())
513 }
514}
515
516#[cfg(feature = "serde")]
517#[derive(Serialize, Deserialize)]
518#[serde(transparent)]
519struct RecordRootBinary(#[serde(with = "BigArray")] [u8; RecordRoot::SIZE]);
520
521#[cfg(feature = "serde")]
522#[derive(Serialize, Deserialize)]
523#[serde(transparent)]
524struct RecordRootHex(#[serde(with = "hex")] [u8; RecordRoot::SIZE]);
525
526#[cfg(feature = "serde")]
527impl Serialize for RecordRoot {
528 #[inline]
529 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
530 where
531 S: Serializer,
532 {
533 if serializer.is_human_readable() {
534 RecordRootHex(self.0).serialize(serializer)
535 } else {
536 RecordRootBinary(self.0).serialize(serializer)
537 }
538 }
539}
540
541#[cfg(feature = "serde")]
542impl<'de> Deserialize<'de> for RecordRoot {
543 #[inline]
544 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
545 where
546 D: Deserializer<'de>,
547 {
548 Ok(Self(if deserializer.is_human_readable() {
549 RecordRootHex::deserialize(deserializer)?.0
550 } else {
551 RecordRootBinary::deserialize(deserializer)?.0
552 }))
553 }
554}
555
556impl Default for RecordRoot {
557 #[inline]
558 fn default() -> Self {
559 Self([0; Self::SIZE])
560 }
561}
562
563impl TryFrom<&[u8]> for RecordRoot {
564 type Error = TryFromSliceError;
565
566 #[inline]
567 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
568 <[u8; Self::SIZE]>::try_from(slice).map(Self)
569 }
570}
571
572impl AsRef<[u8]> for RecordRoot {
573 #[inline]
574 fn as_ref(&self) -> &[u8] {
575 &self.0
576 }
577}
578
579impl AsMut<[u8]> for RecordRoot {
580 #[inline]
581 fn as_mut(&mut self) -> &mut [u8] {
582 &mut self.0
583 }
584}
585
586impl From<&RecordRoot> for &[u8; RecordRoot::SIZE] {
587 #[inline]
588 fn from(value: &RecordRoot) -> Self {
589 unsafe { mem::transmute(value) }
592 }
593}
594
595impl From<&[u8; RecordRoot::SIZE]> for &RecordRoot {
596 #[inline]
597 fn from(value: &[u8; RecordRoot::SIZE]) -> Self {
598 unsafe { mem::transmute(value) }
601 }
602}
603
604impl From<&mut RecordRoot> for &mut [u8; RecordRoot::SIZE] {
605 #[inline]
606 fn from(value: &mut RecordRoot) -> Self {
607 unsafe { mem::transmute(value) }
610 }
611}
612
613impl From<&mut [u8; RecordRoot::SIZE]> for &mut RecordRoot {
614 #[inline]
615 fn from(value: &mut [u8; RecordRoot::SIZE]) -> Self {
616 unsafe { mem::transmute(value) }
619 }
620}
621
622impl RecordRoot {
623 pub const SIZE: usize = 32;
625
626 pub fn is_valid(
628 &self,
629 segment_root: &SegmentRoot,
630 record_proof: &RecordProof,
631 position: u32,
632 ) -> bool {
633 BalancedHashedMerkleTree::<{ RecordedHistorySegment::NUM_PIECES }>::verify(
634 segment_root,
635 record_proof,
636 position as usize,
637 self.0,
638 )
639 }
640}
641
642#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into)]
644#[cfg_attr(
645 feature = "scale-codec",
646 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
647)]
648pub struct RecordChunksRoot([u8; RecordChunksRoot::SIZE]);
649
650impl fmt::Debug for RecordChunksRoot {
651 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
652 for byte in self.0 {
653 write!(f, "{byte:02x}")?;
654 }
655 Ok(())
656 }
657}
658
659#[cfg(feature = "serde")]
660#[derive(Serialize, Deserialize)]
661#[serde(transparent)]
662struct RecordChunksRootBinary(#[serde(with = "BigArray")] [u8; RecordChunksRoot::SIZE]);
663
664#[cfg(feature = "serde")]
665#[derive(Serialize, Deserialize)]
666#[serde(transparent)]
667struct RecordChunksRootHex(#[serde(with = "hex")] [u8; RecordChunksRoot::SIZE]);
668
669#[cfg(feature = "serde")]
670impl Serialize for RecordChunksRoot {
671 #[inline]
672 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
673 where
674 S: Serializer,
675 {
676 if serializer.is_human_readable() {
677 RecordChunksRootHex(self.0).serialize(serializer)
678 } else {
679 RecordChunksRootBinary(self.0).serialize(serializer)
680 }
681 }
682}
683
684#[cfg(feature = "serde")]
685impl<'de> Deserialize<'de> for RecordChunksRoot {
686 #[inline]
687 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
688 where
689 D: Deserializer<'de>,
690 {
691 Ok(Self(if deserializer.is_human_readable() {
692 RecordChunksRootHex::deserialize(deserializer)?.0
693 } else {
694 RecordChunksRootBinary::deserialize(deserializer)?.0
695 }))
696 }
697}
698
699impl Default for RecordChunksRoot {
700 #[inline]
701 fn default() -> Self {
702 Self([0; Self::SIZE])
703 }
704}
705
706impl TryFrom<&[u8]> for RecordChunksRoot {
707 type Error = TryFromSliceError;
708
709 #[inline]
710 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
711 <[u8; Self::SIZE]>::try_from(slice).map(Self)
712 }
713}
714
715impl AsRef<[u8]> for RecordChunksRoot {
716 #[inline]
717 fn as_ref(&self) -> &[u8] {
718 &self.0
719 }
720}
721
722impl AsMut<[u8]> for RecordChunksRoot {
723 #[inline]
724 fn as_mut(&mut self) -> &mut [u8] {
725 &mut self.0
726 }
727}
728
729impl From<&RecordChunksRoot> for &[u8; RecordChunksRoot::SIZE] {
730 #[inline]
731 fn from(value: &RecordChunksRoot) -> Self {
732 unsafe { mem::transmute(value) }
735 }
736}
737
738impl From<&[u8; RecordChunksRoot::SIZE]> for &RecordChunksRoot {
739 #[inline]
740 fn from(value: &[u8; RecordChunksRoot::SIZE]) -> Self {
741 unsafe { mem::transmute(value) }
744 }
745}
746
747impl From<&mut RecordChunksRoot> for &mut [u8; RecordChunksRoot::SIZE] {
748 #[inline]
749 fn from(value: &mut RecordChunksRoot) -> Self {
750 unsafe { mem::transmute(value) }
753 }
754}
755
756impl From<&mut [u8; RecordChunksRoot::SIZE]> for &mut RecordChunksRoot {
757 #[inline]
758 fn from(value: &mut [u8; RecordChunksRoot::SIZE]) -> Self {
759 unsafe { mem::transmute(value) }
762 }
763}
764
765impl RecordChunksRoot {
766 pub const SIZE: usize = 32;
768}
769
770#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
772#[cfg_attr(
773 feature = "scale-codec",
774 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
775)]
776#[repr(C)]
777pub struct RecordProof([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
778
779impl fmt::Debug for RecordProof {
780 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
781 write!(f, "[")?;
782 for hash in self.0 {
783 for byte in hash {
784 write!(f, "{byte:02x}")?;
785 }
786 write!(f, ", ")?;
787 }
788 write!(f, "]")?;
789 Ok(())
790 }
791}
792
793#[cfg(feature = "serde")]
794#[derive(Serialize, Deserialize)]
795#[serde(transparent)]
796struct RecordProofBinary([[u8; OUT_LEN]; RecordProof::NUM_HASHES]);
797
798#[cfg(feature = "serde")]
799#[derive(Serialize, Deserialize)]
800#[serde(transparent)]
801struct RecordProofHexHash(#[serde(with = "hex")] [u8; OUT_LEN]);
802
803#[cfg(feature = "serde")]
804#[derive(Serialize, Deserialize)]
805#[serde(transparent)]
806struct RecordProofHex([RecordProofHexHash; RecordProof::NUM_HASHES]);
807
808#[cfg(feature = "serde")]
809impl Serialize for RecordProof {
810 #[inline]
811 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
812 where
813 S: Serializer,
814 {
815 if serializer.is_human_readable() {
816 RecordProofHex(unsafe {
819 mem::transmute::<
820 [[u8; OUT_LEN]; RecordProof::NUM_HASHES],
821 [RecordProofHexHash; RecordProof::NUM_HASHES],
822 >(self.0)
823 })
824 .serialize(serializer)
825 } else {
826 RecordProofBinary(self.0).serialize(serializer)
827 }
828 }
829}
830
831#[cfg(feature = "serde")]
832impl<'de> Deserialize<'de> for RecordProof {
833 #[inline]
834 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
835 where
836 D: Deserializer<'de>,
837 {
838 Ok(Self(if deserializer.is_human_readable() {
839 unsafe {
842 mem::transmute::<
843 [RecordProofHexHash; RecordProof::NUM_HASHES],
844 [[u8; OUT_LEN]; RecordProof::NUM_HASHES],
845 >(RecordProofHex::deserialize(deserializer)?.0)
846 }
847 } else {
848 RecordProofBinary::deserialize(deserializer)?.0
849 }))
850 }
851}
852
853impl Default for RecordProof {
854 #[inline]
855 fn default() -> Self {
856 Self([[0; OUT_LEN]; RecordProof::NUM_HASHES])
857 }
858}
859
860impl AsRef<[u8]> for RecordProof {
861 #[inline]
862 fn as_ref(&self) -> &[u8] {
863 self.0.as_flattened()
864 }
865}
866
867impl AsMut<[u8]> for RecordProof {
868 #[inline]
869 fn as_mut(&mut self) -> &mut [u8] {
870 self.0.as_flattened_mut()
871 }
872}
873
874impl From<&RecordProof> for &[u8; RecordProof::SIZE] {
875 #[inline]
876 fn from(value: &RecordProof) -> Self {
877 unsafe { mem::transmute(value) }
880 }
881}
882
883impl From<&[u8; RecordProof::SIZE]> for &RecordProof {
884 #[inline]
885 fn from(value: &[u8; RecordProof::SIZE]) -> Self {
886 unsafe { mem::transmute(value) }
889 }
890}
891
892impl From<&mut RecordProof> for &mut [u8; RecordProof::SIZE] {
893 #[inline]
894 fn from(value: &mut RecordProof) -> Self {
895 unsafe { mem::transmute(value) }
898 }
899}
900
901impl From<&mut [u8; RecordProof::SIZE]> for &mut RecordProof {
902 #[inline]
903 fn from(value: &mut [u8; RecordProof::SIZE]) -> Self {
904 unsafe { mem::transmute(value) }
907 }
908}
909
910impl RecordProof {
911 pub const SIZE: usize = OUT_LEN * Self::NUM_HASHES;
913 const NUM_HASHES: usize = RecordedHistorySegment::NUM_PIECES.ilog2() as usize;
914}
915
916#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deref, DerefMut, AsRef, AsMut)]
924#[repr(C)]
925pub struct PieceArray([u8; PieceArray::SIZE]);
926
927impl fmt::Debug for PieceArray {
928 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
929 for byte in self.0 {
930 write!(f, "{byte:02x}")?;
931 }
932 Ok(())
933 }
934}
935
936impl Default for PieceArray {
937 #[inline]
938 fn default() -> Self {
939 Self([0u8; Self::SIZE])
940 }
941}
942
943impl AsRef<[u8]> for PieceArray {
944 #[inline]
945 fn as_ref(&self) -> &[u8] {
946 &self.0
947 }
948}
949
950impl AsMut<[u8]> for PieceArray {
951 #[inline]
952 fn as_mut(&mut self) -> &mut [u8] {
953 &mut self.0
954 }
955}
956
957impl From<&PieceArray> for &[u8; PieceArray::SIZE] {
958 #[inline]
959 fn from(value: &PieceArray) -> Self {
960 unsafe { mem::transmute(value) }
963 }
964}
965
966impl From<&[u8; PieceArray::SIZE]> for &PieceArray {
967 #[inline]
968 fn from(value: &[u8; PieceArray::SIZE]) -> Self {
969 unsafe { mem::transmute(value) }
972 }
973}
974
975impl From<&mut PieceArray> for &mut [u8; PieceArray::SIZE] {
976 #[inline]
977 fn from(value: &mut PieceArray) -> Self {
978 unsafe { mem::transmute(value) }
981 }
982}
983
984impl From<&mut [u8; PieceArray::SIZE]> for &mut PieceArray {
985 #[inline]
986 fn from(value: &mut [u8; PieceArray::SIZE]) -> Self {
987 unsafe { mem::transmute(value) }
990 }
991}
992
993impl PieceArray {
994 pub const SIZE: usize =
996 Record::SIZE + RecordRoot::SIZE + RecordChunksRoot::SIZE + RecordProof::SIZE;
997
998 #[inline]
1000 #[cfg(feature = "alloc")]
1001 pub fn new_boxed() -> Box<Self> {
1002 unsafe { Box::<Self>::new_zeroed().assume_init() }
1005 }
1006
1007 pub fn is_valid(&self, segment_root: &SegmentRoot, position: u32) -> bool {
1009 let (record, &record_root, parity_chunks_root, record_proof) = self.split();
1010
1011 let source_record_merkle_tree_root = BalancedHashedMerkleTree::compute_root_only(record);
1012 let record_merkle_tree_root = BalancedHashedMerkleTree::compute_root_only(&[
1013 source_record_merkle_tree_root,
1014 **parity_chunks_root,
1015 ]);
1016
1017 if record_merkle_tree_root != *record_root {
1018 return false;
1019 }
1020
1021 record_root.is_valid(segment_root, record_proof, position)
1022 }
1023
1024 #[inline]
1026 pub fn split(&self) -> (&Record, &RecordRoot, &RecordChunksRoot, &RecordProof) {
1027 let (record, extra) = self.0.split_at(Record::SIZE);
1028 let (root, extra) = extra.split_at(RecordRoot::SIZE);
1029 let (parity_chunks_root, proof) = extra.split_at(RecordChunksRoot::SIZE);
1030
1031 let record = <&[u8; Record::SIZE]>::try_from(record)
1032 .expect("Slice of memory has correct length; qed");
1033 let root = <&[u8; RecordRoot::SIZE]>::try_from(root)
1034 .expect("Slice of memory has correct length; qed");
1035 let parity_chunks_root = <&[u8; RecordChunksRoot::SIZE]>::try_from(parity_chunks_root)
1036 .expect("Slice of memory has correct length; qed");
1037 let proof = <&[u8; RecordProof::SIZE]>::try_from(proof)
1038 .expect("Slice of memory has correct length; qed");
1039
1040 (
1041 record.into(),
1042 root.into(),
1043 parity_chunks_root.into(),
1044 proof.into(),
1045 )
1046 }
1047
1048 #[inline]
1050 pub fn split_mut(
1051 &mut self,
1052 ) -> (
1053 &mut Record,
1054 &mut RecordRoot,
1055 &mut RecordChunksRoot,
1056 &mut RecordProof,
1057 ) {
1058 let (record, extra) = self.0.split_at_mut(Record::SIZE);
1059 let (root, extra) = extra.split_at_mut(RecordRoot::SIZE);
1060 let (parity_chunks_root, proof) = extra.split_at_mut(RecordChunksRoot::SIZE);
1061
1062 let record = <&mut [u8; Record::SIZE]>::try_from(record)
1063 .expect("Slice of memory has correct length; qed");
1064 let root = <&mut [u8; RecordRoot::SIZE]>::try_from(root)
1065 .expect("Slice of memory has correct length; qed");
1066 let parity_chunks_root = <&mut [u8; RecordChunksRoot::SIZE]>::try_from(parity_chunks_root)
1067 .expect("Slice of memory has correct length; qed");
1068 let proof = <&mut [u8; RecordProof::SIZE]>::try_from(proof)
1069 .expect("Slice of memory has correct length; qed");
1070
1071 (
1072 record.into(),
1073 root.into(),
1074 parity_chunks_root.into(),
1075 proof.into(),
1076 )
1077 }
1078
1079 #[inline]
1081 pub fn record(&self) -> &Record {
1082 self.split().0
1083 }
1084
1085 #[inline]
1087 pub fn record_mut(&mut self) -> &mut Record {
1088 self.split_mut().0
1089 }
1090
1091 #[inline]
1093 pub fn root(&self) -> &RecordRoot {
1094 self.split().1
1095 }
1096
1097 #[inline]
1099 pub fn root_mut(&mut self) -> &mut RecordRoot {
1100 self.split_mut().1
1101 }
1102
1103 #[inline]
1105 pub fn parity_chunks_root(&self) -> &RecordChunksRoot {
1106 self.split().2
1107 }
1108
1109 #[inline]
1111 pub fn parity_chunks_root_mut(&mut self) -> &mut RecordChunksRoot {
1112 self.split_mut().2
1113 }
1114
1115 #[inline]
1117 pub fn proof(&self) -> &RecordProof {
1118 self.split().3
1119 }
1120
1121 #[inline]
1123 pub fn proof_mut(&mut self) -> &mut RecordProof {
1124 self.split_mut().3
1125 }
1126
1127 #[inline]
1130 pub fn slice_to_repr(value: &[Self]) -> &[[u8; Self::SIZE]] {
1131 unsafe { mem::transmute(value) }
1134 }
1135
1136 #[inline]
1139 pub fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
1140 unsafe { mem::transmute(value) }
1143 }
1144
1145 #[inline]
1148 pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [[u8; Self::SIZE]] {
1149 unsafe { mem::transmute(value) }
1152 }
1153
1154 #[inline]
1157 pub fn slice_mut_from_repr(value: &mut [[u8; Self::SIZE]]) -> &mut [Self] {
1158 unsafe { mem::transmute(value) }
1161 }
1162}
1163
1164#[cfg(feature = "alloc")]
1165impl From<Box<PieceArray>> for Vec<u8> {
1166 fn from(value: Box<PieceArray>) -> Self {
1167 let mut value = mem::ManuallyDrop::new(value);
1168 unsafe { Vec::from_raw_parts(value.as_mut_ptr(), PieceArray::SIZE, PieceArray::SIZE) }
1170 }
1171}