1use crate::hash::Hash;
18use crate::pmmr::{self, Backend, ReadablePMMR, ReadonlyPMMR};
19use crate::ser::{Error, PMMRIndexHashable, PMMRable, Readable, Reader, Writeable, Writer};
20use croaring::Bitmap;
21use std::cmp::min;
22use std::fmt::Debug;
23
24#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
25pub enum SegmentError {
27 #[error("Missing leaf at pos {0}")]
29 MissingLeaf(u64),
30 #[error("Missing hash at pos {0}")]
32 MissingHash(u64),
33 #[error("Segment does not exist")]
35 NonExistent,
36 #[error("Root hash mismatch")]
38 Mismatch,
39}
40
41#[derive(Copy, Clone, Debug, Eq, PartialEq)]
43pub struct SegmentIdentifier {
44 pub height: u8,
46 pub idx: u64,
48}
49
50impl Readable for SegmentIdentifier {
51 fn read<R: Reader>(reader: &mut R) -> Result<Self, Error> {
52 let height = reader.read_u8()?;
53 let idx = reader.read_u64()?;
54 Ok(Self { height, idx })
55 }
56}
57
58impl Writeable for SegmentIdentifier {
59 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
60 writer.write_u8(self.height)?;
61 writer.write_u64(self.idx)
62 }
63}
64
65impl SegmentIdentifier {
66 pub fn traversal_iter(
69 target_mmr_size: u64,
70 segment_height: u8,
71 ) -> impl Iterator<Item = SegmentIdentifier> {
72 (0..SegmentIdentifier::count_segments_required(target_mmr_size, segment_height)).map(
73 move |idx| SegmentIdentifier {
74 height: segment_height,
75 idx: idx as u64,
76 },
77 )
78 }
79
80 pub fn count_segments_required(target_mmr_size: u64, segment_height: u8) -> usize {
83 let d = 1 << segment_height;
84 ((pmmr::n_leaves(target_mmr_size) + d - 1) / d) as usize
85 }
86}
87
88#[derive(Clone, Debug, Eq, PartialEq)]
91pub struct Segment<T> {
92 identifier: SegmentIdentifier,
93 hash_pos: Vec<u64>,
94 hashes: Vec<Hash>,
95 leaf_pos: Vec<u64>,
96 leaf_data: Vec<T>,
97 proof: SegmentProof,
98}
99
100impl<T> Segment<T> {
101 fn empty(identifier: SegmentIdentifier) -> Self {
103 Segment {
104 identifier,
105 hash_pos: Vec::new(),
106 hashes: Vec::new(),
107 leaf_pos: Vec::new(),
108 leaf_data: Vec::new(),
109 proof: SegmentProof::empty(),
110 }
111 }
112
113 fn segment_capacity(&self) -> u64 {
115 1 << self.identifier.height
116 }
117
118 fn leaf_offset(&self) -> u64 {
120 self.identifier.idx * self.segment_capacity()
121 }
122
123 fn segment_unpruned_size(&self, mmr_size: u64) -> u64 {
125 min(
126 self.segment_capacity(),
127 pmmr::n_leaves(mmr_size).saturating_sub(self.leaf_offset()),
128 )
129 }
130
131 fn full_segment(&self, mmr_size: u64) -> bool {
133 self.segment_unpruned_size(mmr_size) == self.segment_capacity()
134 }
135
136 pub fn segment_pos_range(&self, mmr_size: u64) -> (u64, u64) {
138 let segment_size = self.segment_unpruned_size(mmr_size);
139 let leaf_offset = self.leaf_offset();
140 let first = pmmr::insertion_to_pmmr_index(leaf_offset);
141 let last = if self.full_segment(mmr_size) {
142 pmmr::insertion_to_pmmr_index(leaf_offset + segment_size - 1)
143 + (self.identifier.height as u64)
144 } else {
145 mmr_size - 1
146 };
147 (first, last)
148 }
149
150 fn get_hash(&self, pos0: u64) -> Result<Hash, SegmentError> {
152 self.hash_pos
153 .iter()
154 .zip(&self.hashes)
155 .find(|&(&p, _)| p == pos0)
156 .map(|(_, &h)| h)
157 .ok_or_else(|| SegmentError::MissingHash(pos0))
158 }
159
160 pub fn identifier(&self) -> SegmentIdentifier {
162 self.identifier
163 }
164
165 pub fn parts(
167 self,
168 ) -> (
169 SegmentIdentifier,
170 Vec<u64>,
171 Vec<Hash>,
172 Vec<u64>,
173 Vec<T>,
174 SegmentProof,
175 ) {
176 (
177 self.identifier,
178 self.hash_pos,
179 self.hashes,
180 self.leaf_pos,
181 self.leaf_data,
182 self.proof,
183 )
184 }
185
186 pub fn from_parts(
188 identifier: SegmentIdentifier,
189 hash_pos: Vec<u64>,
190 hashes: Vec<Hash>,
191 leaf_pos: Vec<u64>,
192 leaf_data: Vec<T>,
193 proof: SegmentProof,
194 ) -> Self {
195 assert_eq!(hash_pos.len(), hashes.len());
196 let mut last = 0;
197 for &pos in &hash_pos {
198 assert!(last == 0 || pos > last);
199 last = pos;
200 }
201 assert_eq!(leaf_pos.len(), leaf_data.len());
202 last = 0;
203 for &pos in &leaf_pos {
204 assert!(last == 0 || pos > last);
205 last = pos;
206 }
207
208 Self {
209 identifier,
210 hash_pos,
211 hashes,
212 leaf_pos,
213 leaf_data,
214 proof,
215 }
216 }
217
218 pub fn leaf_iter(&self) -> impl Iterator<Item = (u64, &T)> + '_ {
220 self.leaf_pos.iter().map(|&p| p).zip(&self.leaf_data)
221 }
222
223 pub fn hash_iter(&self) -> impl Iterator<Item = (u64, Hash)> + '_ {
225 self.hash_pos
226 .iter()
227 .zip(&self.hashes)
228 .map(|(&p, &h)| (p, h))
229 }
230
231 pub fn proof(&self) -> &SegmentProof {
233 &self.proof
234 }
235
236 pub fn id(&self) -> SegmentIdentifier {
238 self.identifier
239 }
240}
241
242impl<T> Segment<T>
243where
244 T: Readable + Writeable + Debug,
245{
246 pub fn from_pmmr<U, B>(
248 segment_id: SegmentIdentifier,
249 pmmr: &ReadonlyPMMR<'_, U, B>,
250 prunable: bool,
251 ) -> Result<Self, SegmentError>
252 where
253 U: PMMRable<E = T>,
254 B: Backend<U>,
255 {
256 let mut segment = Segment::empty(segment_id);
257
258 let mmr_size = pmmr.unpruned_size();
259 if segment.segment_unpruned_size(mmr_size) == 0 {
260 return Err(SegmentError::NonExistent);
261 }
262
263 let (segment_first_pos, segment_last_pos) = segment.segment_pos_range(mmr_size);
265 for pos0 in segment_first_pos..=segment_last_pos {
266 if pmmr::is_leaf(pos0) {
267 if let Some(data) = pmmr.get_data_from_file(pos0) {
268 segment.leaf_data.push(data);
269 segment.leaf_pos.push(pos0);
270 continue;
271 } else if !prunable {
272 return Err(SegmentError::MissingLeaf(pos0));
273 }
274 }
275 if prunable {
277 if let Some(hash) = pmmr.get_from_file(pos0) {
278 segment.hashes.push(hash);
279 segment.hash_pos.push(pos0);
280 }
281 }
282 }
283
284 let mut start_pos = None;
285 if segment.leaf_data.is_empty() && segment.hashes.is_empty() {
287 let family_branch = pmmr::family_branch(segment_last_pos, mmr_size);
288 for (pos0, _) in family_branch {
289 if let Some(hash) = pmmr.get_from_file(pos0) {
290 segment.hashes.push(hash);
291 segment.hash_pos.push(pos0);
292 start_pos = Some(1 + pos0);
293 break;
294 }
295 }
296 }
297
298 segment.proof = SegmentProof::generate(
300 pmmr,
301 mmr_size,
302 1 + segment_first_pos,
303 1 + segment_last_pos,
304 start_pos,
305 )?;
306
307 Ok(segment)
308 }
309}
310
311impl<T> Segment<T>
312where
313 T: PMMRIndexHashable,
314{
315 pub fn root(
318 &self,
319 mmr_size: u64,
320 bitmap: Option<&Bitmap>,
321 ) -> Result<Option<Hash>, SegmentError> {
322 let (segment_first_pos, segment_last_pos) = self.segment_pos_range(mmr_size);
323 let mut hashes = Vec::<Option<Hash>>::with_capacity(2 * (self.identifier.height as usize));
324 let mut leaves0 = self.leaf_pos.iter().zip(&self.leaf_data);
325 for pos0 in segment_first_pos..=segment_last_pos {
326 let height = pmmr::bintree_postorder_height(pos0);
327 let hash = if height == 0 {
328 if bitmap
330 .map(|b| {
331 let idx_1 = pmmr::n_leaves(pos0 + 1) - 1;
332 let idx_2 = if pmmr::is_left_sibling(pos0) {
333 idx_1 + 1
334 } else {
335 idx_1 - 1
336 };
337 b.contains(idx_1 as u32) || b.contains(idx_2 as u32) || pos0 == mmr_size - 1
338 })
339 .unwrap_or(true)
340 {
341 let data = leaves0
348 .find(|&(&p, _)| p == pos0)
349 .map(|(_, l)| l)
350 .ok_or_else(|| SegmentError::MissingLeaf(pos0))?;
351 Some(data.hash_with_index(pos0))
352 } else {
353 None
354 }
355 } else {
356 let left_child_pos = 1 + pos0 - (1 << height);
357 let right_child_pos = pos0;
358
359 let right_child = hashes.pop().unwrap();
360 let left_child = hashes.pop().unwrap();
361
362 if bitmap.is_some() {
363 match (left_child, right_child) {
365 (None, None) => None,
366 (Some(l), Some(r)) => Some((l, r).hash_with_index(pos0)),
367 (None, Some(r)) => {
368 let l = self.get_hash(left_child_pos - 1)?;
369 Some((l, r).hash_with_index(pos0))
370 }
371 (Some(l), None) => {
372 let r = self.get_hash(right_child_pos - 1)?;
373 Some((l, r).hash_with_index(pos0))
374 }
375 }
376 } else {
377 Some(
379 (
380 left_child.ok_or_else(|| SegmentError::MissingHash(left_child_pos))?,
381 right_child
382 .ok_or_else(|| SegmentError::MissingHash(right_child_pos))?,
383 )
384 .hash_with_index(pos0),
385 )
386 }
387 };
388 hashes.push(hash);
389 }
390
391 if self.full_segment(mmr_size) {
392 Ok(hashes.pop().unwrap())
394 } else {
395 let peaks = pmmr::peaks(mmr_size)
397 .into_iter()
398 .filter(|&pos0| pos0 >= segment_first_pos && pos0 <= segment_last_pos)
399 .rev();
400 let mut hash = None;
401 for pos0 in peaks {
402 let mut lhash = hashes
403 .pop()
404 .ok_or_else(|| SegmentError::MissingHash(1 + pos0))?;
405 if lhash.is_none() && bitmap.is_some() {
406 lhash = Some(self.get_hash(pos0)?);
408 }
409 let lhash = lhash.ok_or_else(|| SegmentError::MissingHash(1 + pos0))?;
410
411 hash = match hash {
412 None => Some(lhash),
413 Some(rhash) => Some((lhash, rhash).hash_with_index(mmr_size)),
414 };
415 }
416 Ok(Some(hash.unwrap()))
417 }
418 }
419
420 pub fn first_unpruned_parent(
422 &self,
423 mmr_size: u64,
424 bitmap: Option<&Bitmap>,
425 ) -> Result<(Hash, u64), SegmentError> {
426 let root = self.root(mmr_size, bitmap)?;
427 let (_, last) = self.segment_pos_range(mmr_size);
428 if let Some(root) = root {
429 return Ok((root, 1 + last));
430 }
431 let bitmap = bitmap.unwrap();
432 let n_leaves = pmmr::n_leaves(mmr_size);
433
434 let mut cardinality = 0;
435 let mut pos0 = last;
436 let mut hash = Err(SegmentError::MissingHash(last));
437 let mut family_branch = pmmr::family_branch(last, mmr_size).into_iter();
438 while cardinality == 0 {
439 hash = self.get_hash(pos0).map(|h| (h, 1 + pos0));
440 if hash.is_ok() {
441 return hash;
444 }
445
446 if let Some((p0, _)) = family_branch.next() {
447 pos0 = p0;
448 let range = (pmmr::n_leaves(1 + pmmr::bintree_leftmost(p0)) - 1)
449 ..min(pmmr::n_leaves(1 + pmmr::bintree_rightmost(p0)), n_leaves);
450 cardinality = bitmap.range_cardinality(range);
451 } else {
452 break;
453 }
454 }
455 hash
456 }
457
458 pub fn validate(
460 &self,
461 mmr_size: u64,
462 bitmap: Option<&Bitmap>,
463 mmr_root: Hash,
464 ) -> Result<(), SegmentError> {
465 let (first, last) = self.segment_pos_range(mmr_size);
466 let (segment_root, segment_unpruned_pos) = self.first_unpruned_parent(mmr_size, bitmap)?;
467 self.proof.validate(
468 mmr_size,
469 mmr_root,
470 first,
471 last,
472 segment_root,
473 segment_unpruned_pos,
474 )
475 }
476
477 pub fn validate_with(
480 &self,
481 mmr_size: u64,
482 bitmap: Option<&Bitmap>,
483 mmr_root: Hash,
484 hash_last_pos: u64,
485 other_root: Hash,
486 other_is_left: bool,
487 ) -> Result<(), SegmentError> {
488 let (first, last) = self.segment_pos_range(mmr_size);
489 let (segment_root, segment_unpruned_pos) = self.first_unpruned_parent(mmr_size, bitmap)?;
490 self.proof.validate_with(
491 mmr_size,
492 mmr_root,
493 first,
494 last,
495 segment_root,
496 segment_unpruned_pos,
497 hash_last_pos,
498 other_root,
499 other_is_left,
500 )
501 }
502}
503
504impl<T: Readable> Readable for Segment<T> {
505 fn read<R: Reader>(reader: &mut R) -> Result<Self, Error> {
506 let identifier = Readable::read(reader)?;
507
508 let n_hashes = reader.read_u64()? as usize;
509 let mut hash_pos = Vec::with_capacity(n_hashes);
510 let mut last_pos = 0;
511 for _ in 0..n_hashes {
512 let pos = reader.read_u64()?;
513 if pos <= last_pos {
514 return Err(Error::SortError);
515 }
516 last_pos = pos;
517 hash_pos.push(pos - 1);
518 }
519
520 let mut hashes = Vec::<Hash>::with_capacity(n_hashes);
521 for _ in 0..n_hashes {
522 hashes.push(Readable::read(reader)?);
523 }
524
525 let n_leaves = reader.read_u64()? as usize;
526 let mut leaf_pos = Vec::with_capacity(n_leaves);
527 last_pos = 0;
528 for _ in 0..n_leaves {
529 let pos = reader.read_u64()?;
530 if pos <= last_pos {
531 return Err(Error::SortError);
532 }
533 last_pos = pos;
534 leaf_pos.push(pos - 1);
535 }
536
537 let mut leaf_data = Vec::<T>::with_capacity(n_leaves);
538 for _ in 0..n_leaves {
539 leaf_data.push(Readable::read(reader)?);
540 }
541
542 let proof = Readable::read(reader)?;
543
544 Ok(Self {
545 identifier,
546 hash_pos,
547 hashes,
548 leaf_pos,
549 leaf_data,
550 proof,
551 })
552 }
553}
554
555impl<T: Writeable> Writeable for Segment<T> {
556 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
557 Writeable::write(&self.identifier, writer)?;
558 writer.write_u64(self.hashes.len() as u64)?;
559 for &pos in &self.hash_pos {
560 writer.write_u64(1 + pos)?;
561 }
562 for hash in &self.hashes {
563 Writeable::write(hash, writer)?;
564 }
565 writer.write_u64(self.leaf_data.len() as u64)?;
566 for &pos in &self.leaf_pos {
567 writer.write_u64(1 + pos)?;
568 }
569 for data in &self.leaf_data {
570 Writeable::write(data, writer)?;
571 }
572 Writeable::write(&self.proof, writer)?;
573 Ok(())
574 }
575}
576
577#[derive(Clone, Debug, Eq, PartialEq)]
579pub struct SegmentProof {
580 hashes: Vec<Hash>,
581}
582
583impl SegmentProof {
584 fn empty() -> Self {
585 Self { hashes: Vec::new() }
586 }
587
588 fn generate<U, B>(
589 pmmr: &ReadonlyPMMR<'_, U, B>,
590 last_pos: u64,
591 segment_first_pos: u64,
592 segment_last_pos: u64,
593 start_pos: Option<u64>,
594 ) -> Result<Self, SegmentError>
595 where
596 U: PMMRable,
597 B: Backend<U>,
598 {
599 let family_branch = pmmr::family_branch(segment_last_pos - 1, last_pos);
600
601 let hashes: Result<Vec<_>, _> = family_branch
603 .iter()
604 .filter(|&&(p0, _)| start_pos.map(|s| p0 >= s).unwrap_or(true))
605 .map(|&(_, s0)| {
606 pmmr.get_hash(s0)
607 .ok_or_else(|| SegmentError::MissingHash(s0))
608 })
609 .collect();
610 let mut proof = Self { hashes: hashes? };
611
612 let peak_pos = family_branch
614 .last()
615 .map(|&(p0, _)| p0)
616 .unwrap_or(segment_last_pos - 1);
617 if let Some(h) = pmmr.bag_the_rhs(peak_pos) {
618 proof.hashes.push(h);
619 }
620
621 let peaks: Result<Vec<_>, _> = pmmr::peaks(last_pos)
623 .into_iter()
624 .filter(|&x| 1 + x < segment_first_pos)
625 .rev()
626 .map(|p| pmmr.get_hash(p).ok_or_else(|| SegmentError::MissingHash(p)))
627 .collect();
628 proof.hashes.extend(peaks?);
629
630 Ok(proof)
631 }
632
633 pub fn size(&self) -> usize {
635 self.hashes.len()
636 }
637
638 pub fn reconstruct_root(
640 &self,
641 last_pos: u64,
642 segment_first_pos0: u64,
643 segment_last_pos0: u64,
644 segment_root: Hash,
645 segment_unpruned_pos: u64,
646 ) -> Result<Hash, SegmentError> {
647 let mut iter = self.hashes.iter();
648 let family_branch = pmmr::family_branch(segment_last_pos0, last_pos);
649
650 let mut root = segment_root;
652 for &(p0, s0) in family_branch
653 .iter()
654 .filter(|&&(p0, _)| p0 >= segment_unpruned_pos)
655 {
656 let sibling_hash = iter
657 .next()
658 .ok_or_else(|| SegmentError::MissingHash(1 + s0))?;
659 root = if pmmr::is_left_sibling(s0) {
660 (sibling_hash, root).hash_with_index(p0)
661 } else {
662 (root, sibling_hash).hash_with_index(p0)
663 };
664 }
665
666 let peak_pos0 = family_branch
668 .last()
669 .map(|&(p0, _)| p0)
670 .unwrap_or(segment_last_pos0);
671
672 let rhs = pmmr::peaks(last_pos)
673 .into_iter()
674 .filter(|&x| x > peak_pos0)
675 .next();
676
677 if let Some(pos0) = rhs {
678 root = (
679 root,
680 iter.next()
681 .ok_or_else(|| SegmentError::MissingHash(1 + pos0))?,
682 )
683 .hash_with_index(last_pos)
684 }
685
686 let peaks = pmmr::peaks(last_pos)
688 .into_iter()
689 .filter(|&x| x < segment_first_pos0)
690 .rev();
691 for pos0 in peaks {
692 root = (
693 iter.next()
694 .ok_or_else(|| SegmentError::MissingHash(1 + pos0))?,
695 root,
696 )
697 .hash_with_index(last_pos);
698 }
699
700 Ok(root)
701 }
702
703 pub fn validate(
705 &self,
706 last_pos: u64,
707 mmr_root: Hash,
708 segment_first_pos: u64,
709 segment_last_pos: u64,
710 segment_root: Hash,
711 segment_unpruned_pos: u64,
712 ) -> Result<(), SegmentError> {
713 let root = self.reconstruct_root(
714 last_pos,
715 segment_first_pos,
716 segment_last_pos,
717 segment_root,
718 segment_unpruned_pos,
719 )?;
720 if root == mmr_root {
721 Ok(())
722 } else {
723 Err(SegmentError::Mismatch)
724 }
725 }
726
727 pub fn validate_with(
730 &self,
731 last_pos: u64,
732 mmr_root: Hash,
733 segment_first_pos: u64,
734 segment_last_pos: u64,
735 segment_root: Hash,
736 segment_unpruned_pos: u64,
737 hash_last_pos: u64,
738 other_root: Hash,
739 other_is_left: bool,
740 ) -> Result<(), SegmentError> {
741 let root = self.reconstruct_root(
742 last_pos,
743 segment_first_pos,
744 segment_last_pos,
745 segment_root,
746 segment_unpruned_pos,
747 )?;
748 let root = if other_is_left {
749 (other_root, root).hash_with_index(hash_last_pos)
750 } else {
751 (root, other_root).hash_with_index(hash_last_pos)
752 };
753 if root == mmr_root {
754 Ok(())
755 } else {
756 Err(SegmentError::Mismatch)
757 }
758 }
759}
760
761impl Readable for SegmentProof {
762 fn read<R: Reader>(reader: &mut R) -> Result<Self, Error> {
763 let n_hashes = reader.read_u64()? as usize;
764 let mut hashes = Vec::with_capacity(n_hashes);
765 for _ in 0..n_hashes {
766 let hash: Hash = Readable::read(reader)?;
767 hashes.push(hash);
768 }
769 Ok(Self { hashes })
770 }
771}
772
773impl Writeable for SegmentProof {
774 fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
775 writer.write_u64(self.hashes.len() as u64)?;
776 for hash in &self.hashes {
777 Writeable::write(hash, writer)?;
778 }
779 Ok(())
780 }
781}