1#[cfg(feature = "alloc")]
4mod archival_history_segment;
5
6use crate::block::BlockNumber;
7use crate::hashes::Blake3Hash;
8use crate::pieces::{PieceIndex, Record};
9#[cfg(feature = "alloc")]
10pub use crate::segments::archival_history_segment::ArchivedHistorySegment;
11use ab_blake3::single_chunk_hash;
12use ab_io_type::trivial_type::TrivialType;
13use ab_io_type::unaligned::Unaligned;
14#[cfg(feature = "alloc")]
15use alloc::boxed::Box;
16use blake3::CHUNK_LEN;
17use core::iter::Step;
18use core::num::{NonZeroU32, NonZeroU64};
19use core::{fmt, mem};
20use derive_more::{
21 Add, AddAssign, Deref, DerefMut, Display, Div, DivAssign, From, Into, Mul, MulAssign, Sub,
22 SubAssign,
23};
24#[cfg(feature = "scale-codec")]
25use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
26#[cfg(feature = "scale-codec")]
27use scale_info::TypeInfo;
28#[cfg(feature = "serde")]
29use serde::{Deserialize, Deserializer, Serialize, Serializer};
30#[cfg(feature = "serde")]
31use serde_big_array::BigArray;
32
33#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
35#[cfg_attr(
36 feature = "scale-codec",
37 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
38)]
39#[repr(C)]
40pub struct SuperSegmentRoot([u8; SuperSegmentRoot::SIZE]);
41
42impl fmt::Debug for SuperSegmentRoot {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 for byte in self.0 {
45 write!(f, "{byte:02x}")?;
46 }
47 Ok(())
48 }
49}
50
51#[cfg(feature = "serde")]
52#[derive(Serialize, Deserialize)]
53#[serde(transparent)]
54struct SuperSegmentRootBinary(#[serde(with = "BigArray")] [u8; SuperSegmentRoot::SIZE]);
55
56#[cfg(feature = "serde")]
57#[derive(Serialize, Deserialize)]
58#[serde(transparent)]
59struct SuperSegmentRootHex(#[serde(with = "hex")] [u8; SuperSegmentRoot::SIZE]);
60
61#[cfg(feature = "serde")]
62impl Serialize for SuperSegmentRoot {
63 #[inline]
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: Serializer,
67 {
68 if serializer.is_human_readable() {
69 SuperSegmentRootHex(self.0).serialize(serializer)
70 } else {
71 SuperSegmentRootBinary(self.0).serialize(serializer)
72 }
73 }
74}
75
76#[cfg(feature = "serde")]
77impl<'de> Deserialize<'de> for SuperSegmentRoot {
78 #[inline]
79 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
80 where
81 D: Deserializer<'de>,
82 {
83 Ok(Self(if deserializer.is_human_readable() {
84 SuperSegmentRootHex::deserialize(deserializer)?.0
85 } else {
86 SuperSegmentRootBinary::deserialize(deserializer)?.0
87 }))
88 }
89}
90
91impl Default for SuperSegmentRoot {
92 #[inline]
93 fn default() -> Self {
94 Self([0; Self::SIZE])
95 }
96}
97
98impl AsRef<[u8]> for SuperSegmentRoot {
99 #[inline]
100 fn as_ref(&self) -> &[u8] {
101 &self.0
102 }
103}
104
105impl AsMut<[u8]> for SuperSegmentRoot {
106 #[inline]
107 fn as_mut(&mut self) -> &mut [u8] {
108 &mut self.0
109 }
110}
111
112impl SuperSegmentRoot {
113 pub const SIZE: usize = 32;
115}
116
117#[derive(
119 Debug,
120 Display,
121 Default,
122 Copy,
123 Clone,
124 Ord,
125 PartialOrd,
126 Eq,
127 PartialEq,
128 Hash,
129 From,
130 Into,
131 Add,
132 AddAssign,
133 Sub,
134 SubAssign,
135 Mul,
136 MulAssign,
137 Div,
138 DivAssign,
139 TrivialType,
140)]
141#[cfg_attr(
142 feature = "scale-codec",
143 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
144)]
145#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
146#[repr(C)]
147pub struct SegmentIndex(u64);
148
149impl Step for SegmentIndex {
150 #[inline]
151 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
152 u64::steps_between(&start.0, &end.0)
153 }
154
155 #[inline]
156 fn forward_checked(start: Self, count: usize) -> Option<Self> {
157 u64::forward_checked(start.0, count).map(Self)
158 }
159
160 #[inline]
161 fn backward_checked(start: Self, count: usize) -> Option<Self> {
162 u64::backward_checked(start.0, count).map(Self)
163 }
164}
165
166impl SegmentIndex {
167 pub const ZERO: SegmentIndex = SegmentIndex(0);
169 pub const ONE: SegmentIndex = SegmentIndex(1);
171
172 #[inline]
174 pub const fn new(n: u64) -> Self {
175 Self(n)
176 }
177
178 #[inline(always)]
180 pub const fn as_u64(self) -> u64 {
181 self.0
182 }
183
184 #[inline]
186 pub const fn first_piece_index(&self) -> PieceIndex {
187 PieceIndex::new(self.0 * RecordedHistorySegment::NUM_PIECES as u64)
188 }
189
190 #[inline]
192 pub const fn last_piece_index(&self) -> PieceIndex {
193 PieceIndex::new((self.0 + 1) * RecordedHistorySegment::NUM_PIECES as u64 - 1)
194 }
195
196 #[inline]
198 pub fn segment_piece_indexes(&self) -> [PieceIndex; RecordedHistorySegment::NUM_PIECES] {
199 let mut piece_indices = [PieceIndex::ZERO; RecordedHistorySegment::NUM_PIECES];
200 (self.first_piece_index()..=self.last_piece_index())
201 .zip(&mut piece_indices)
202 .for_each(|(input, output)| {
203 *output = input;
204 });
205
206 piece_indices
207 }
208
209 #[inline]
211 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
212 self.0.checked_sub(rhs.0).map(Self)
213 }
214
215 #[inline]
218 pub const fn saturating_sub(self, rhs: Self) -> Self {
219 Self(self.0.saturating_sub(rhs.0))
220 }
221}
222
223#[derive(Copy, Clone, Eq, PartialEq, Hash, Deref, DerefMut, From, Into, TrivialType)]
225#[cfg_attr(
226 feature = "scale-codec",
227 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
228)]
229#[repr(C)]
230pub struct SegmentRoot([u8; SegmentRoot::SIZE]);
231
232impl fmt::Debug for SegmentRoot {
233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234 for byte in self.0 {
235 write!(f, "{byte:02x}")?;
236 }
237 Ok(())
238 }
239}
240
241#[cfg(feature = "serde")]
242#[derive(Serialize, Deserialize)]
243#[serde(transparent)]
244struct SegmentRootBinary(#[serde(with = "BigArray")] [u8; SegmentRoot::SIZE]);
245
246#[cfg(feature = "serde")]
247#[derive(Serialize, Deserialize)]
248#[serde(transparent)]
249struct SegmentRootHex(#[serde(with = "hex")] [u8; SegmentRoot::SIZE]);
250
251#[cfg(feature = "serde")]
252impl Serialize for SegmentRoot {
253 #[inline]
254 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
255 where
256 S: Serializer,
257 {
258 if serializer.is_human_readable() {
259 SegmentRootHex(self.0).serialize(serializer)
260 } else {
261 SegmentRootBinary(self.0).serialize(serializer)
262 }
263 }
264}
265
266#[cfg(feature = "serde")]
267impl<'de> Deserialize<'de> for SegmentRoot {
268 #[inline]
269 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
270 where
271 D: Deserializer<'de>,
272 {
273 Ok(Self(if deserializer.is_human_readable() {
274 SegmentRootHex::deserialize(deserializer)?.0
275 } else {
276 SegmentRootBinary::deserialize(deserializer)?.0
277 }))
278 }
279}
280
281impl Default for SegmentRoot {
282 #[inline(always)]
283 fn default() -> Self {
284 Self([0; Self::SIZE])
285 }
286}
287
288impl AsRef<[u8]> for SegmentRoot {
289 #[inline(always)]
290 fn as_ref(&self) -> &[u8] {
291 &self.0
292 }
293}
294
295impl AsMut<[u8]> for SegmentRoot {
296 #[inline(always)]
297 fn as_mut(&mut self) -> &mut [u8] {
298 &mut self.0
299 }
300}
301
302impl SegmentRoot {
303 pub const SIZE: usize = 32;
305
306 #[inline(always)]
308 pub const fn slice_from_repr(value: &[[u8; Self::SIZE]]) -> &[Self] {
309 unsafe { mem::transmute(value) }
311 }
312
313 #[inline(always)]
315 pub const fn repr_from_slice(value: &[Self]) -> &[[u8; Self::SIZE]] {
316 unsafe { mem::transmute(value) }
318 }
319}
320
321#[derive(
323 Debug,
324 Display,
325 Copy,
326 Clone,
327 Ord,
328 PartialOrd,
329 Eq,
330 PartialEq,
331 Hash,
332 From,
333 Into,
334 Deref,
335 DerefMut,
336 TrivialType,
337)]
338#[cfg_attr(
339 feature = "scale-codec",
340 derive(Encode, Decode, TypeInfo, MaxEncodedLen)
341)]
342#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
343#[repr(C)]
344pub struct HistorySize(SegmentIndex);
346
347impl HistorySize {
348 pub const ONE: Self = Self(SegmentIndex::ZERO);
350
351 #[inline(always)]
353 pub const fn new(value: NonZeroU64) -> Self {
354 Self(SegmentIndex::new(value.get() - 1))
355 }
356
357 pub const fn as_segment_index(&self) -> SegmentIndex {
359 self.0
360 }
361
362 pub const fn as_non_zero_u64(&self) -> NonZeroU64 {
364 NonZeroU64::new(self.0.as_u64().saturating_add(1)).expect("Not zero; qed")
365 }
366
367 #[inline(always)]
369 pub const fn in_pieces(&self) -> NonZeroU64 {
370 NonZeroU64::new(
371 self.0
372 .as_u64()
373 .saturating_add(1)
374 .saturating_mul(RecordedHistorySegment::NUM_PIECES as u64),
375 )
376 .expect("Not zero; qed")
377 }
378
379 #[inline(always)]
381 pub fn segment_index(&self) -> SegmentIndex {
382 self.0
383 }
384
385 #[inline(always)]
389 pub fn sector_expiration_check(&self, min_sector_lifetime: Self) -> Option<Self> {
390 self.as_non_zero_u64()
391 .checked_add(min_sector_lifetime.as_non_zero_u64().get())
392 .map(Self::new)
393 }
394}
395
396#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, TrivialType)]
398#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, TypeInfo))]
399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
400#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
401#[repr(C)]
402pub struct ArchivedBlockProgress {
403 bytes: u32,
405}
406
407impl Default for ArchivedBlockProgress {
408 #[inline(always)]
411 fn default() -> Self {
412 Self::new_complete()
413 }
414}
415
416impl ArchivedBlockProgress {
417 #[inline(always)]
419 pub const fn new_complete() -> Self {
420 Self { bytes: 0 }
421 }
422
423 #[inline(always)]
425 pub const fn new_partial(new_partial: NonZeroU32) -> Self {
426 Self {
427 bytes: new_partial.get(),
428 }
429 }
430
431 #[inline(always)]
433 pub const fn partial(&self) -> Option<NonZeroU32> {
434 NonZeroU32::new(self.bytes)
435 }
436}
437
438#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, TrivialType)]
440#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, TypeInfo))]
441#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
442#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
443#[repr(C)]
444pub struct LastArchivedBlock {
445 pub number: Unaligned<BlockNumber>,
447 pub archived_progress: ArchivedBlockProgress,
449}
450
451impl LastArchivedBlock {
452 #[inline(always)]
454 pub fn partial_archived(&self) -> Option<NonZeroU32> {
455 self.archived_progress.partial()
456 }
457
458 #[inline(always)]
460 pub fn set_partial_archived(&mut self, new_partial: NonZeroU32) {
461 self.archived_progress = ArchivedBlockProgress::new_partial(new_partial);
462 }
463
464 #[inline(always)]
466 pub fn set_complete(&mut self) {
467 self.archived_progress = ArchivedBlockProgress::new_complete();
468 }
469
470 pub const fn number(&self) -> BlockNumber {
472 self.number.as_inner()
473 }
474}
475
476#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TrivialType)]
483#[cfg_attr(feature = "scale-codec", derive(Encode, Decode, TypeInfo))]
484#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
485#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
486#[repr(C)]
487pub struct SegmentHeader {
488 pub segment_index: Unaligned<SegmentIndex>,
490 pub segment_root: SegmentRoot,
492 pub prev_segment_header_hash: Blake3Hash,
494 pub last_archived_block: LastArchivedBlock,
496}
497
498impl SegmentHeader {
499 #[inline(always)]
501 pub fn hash(&self) -> Blake3Hash {
502 const {
503 assert!(size_of::<Self>() <= CHUNK_LEN);
504 }
505 Blake3Hash::new(
506 single_chunk_hash(self.as_bytes())
507 .expect("Less than a single chunk worth of bytes; qed"),
508 )
509 }
510
511 #[inline(always)]
513 pub const fn segment_index(&self) -> SegmentIndex {
514 self.segment_index.as_inner()
515 }
516}
517
518#[derive(Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
522#[repr(C)]
523pub struct RecordedHistorySegment([Record; Self::NUM_RAW_RECORDS]);
524
525impl fmt::Debug for RecordedHistorySegment {
526 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527 f.debug_struct("RecordedHistorySegment")
528 .finish_non_exhaustive()
529 }
530}
531
532impl Default for RecordedHistorySegment {
533 #[inline]
534 fn default() -> Self {
535 Self([Record::default(); Self::NUM_RAW_RECORDS])
536 }
537}
538
539impl AsRef<[u8]> for RecordedHistorySegment {
540 #[inline]
541 fn as_ref(&self) -> &[u8] {
542 Record::slice_to_repr(&self.0).as_flattened().as_flattened()
543 }
544}
545
546impl AsMut<[u8]> for RecordedHistorySegment {
547 #[inline]
548 fn as_mut(&mut self) -> &mut [u8] {
549 Record::slice_mut_to_repr(&mut self.0)
550 .as_flattened_mut()
551 .as_flattened_mut()
552 }
553}
554
555impl RecordedHistorySegment {
556 pub const NUM_RAW_RECORDS: usize = 128;
558 pub const ERASURE_CODING_RATE: (usize, usize) = (1, 2);
560 pub const NUM_PIECES: usize =
563 Self::NUM_RAW_RECORDS * Self::ERASURE_CODING_RATE.1 / Self::ERASURE_CODING_RATE.0;
564 pub const SIZE: usize = Record::SIZE * Self::NUM_RAW_RECORDS;
570
571 #[inline]
573 #[cfg(feature = "alloc")]
574 pub fn new_boxed() -> Box<Self> {
575 unsafe { Box::<Self>::new_zeroed().assume_init() }
578 }
579}