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