bridgetree/
lib.rs

1//! # `bridgetree`
2//!
3//! This crate provides an implementation of an append-only Merkle tree structure. Individual
4//! leaves of the merkle tree may be marked such that witnesses will be maintained for the marked
5//! leaves as additional nodes are appended to the tree, but leaf and node data not specifically
6//! required to maintain these witnesses is not retained, for space efficiency. The data structure
7//! also supports checkpointing of the tree state such that the tree may be reset to a previously
8//! checkpointed state, up to a fixed number of checkpoints.
9//!
10//! The crate also supports using "bridges" containing the minimal possible amount of data to
11//! advance witnesses for marked leaves data up to recent checkpoints or the the latest state of
12//! the tree without having to append each intermediate leaf individually, given a bridge between
13//! the desired states computed by an outside source. The state of the tree is internally
14//! represented as a set of such bridges, and the data structure supports fusing and splitting of
15//! bridges.
16//!
17//! ## Marking
18//!
19//! Merkle trees can be used to show that a value exists in the tree by providing a witness
20//! to a leaf value. We provide an API that allows us to mark the current leaf as a value we wish
21//! to compute witnesses for even after the tree has been appended to in the future; this is called
22//! maintaining a witness. When we're later no longer in a leaf, we can remove the mark and drop
23//! the now unnecessary information from the structure.
24//!
25//! ## Checkpoints and Rollbacks
26//!
27//! This data structure supports a limited capability to restore previous states of the Merkle
28//! tree. It is possible identify the current state of the tree as a "checkpoint" to which the tree
29//! can be reset, and later remove checkpoints that we're no longer interested in being able to
30//! reset the state to.
31//!
32//! In this module, the term "ommer" is used as for the sibling of a parent node in a binary tree.
33pub use incrementalmerkletree::{
34    frontier::{Frontier, NonEmptyFrontier},
35    Address, Hashable, Level, Position, Retention, Source,
36};
37use std::collections::{BTreeMap, BTreeSet, VecDeque};
38use std::fmt::Debug;
39use std::ops::Range;
40
41/// Errors that can be discovered during checks that verify the compatibility of adjacent bridges.
42#[derive(Clone, Debug, PartialEq, Eq)]
43pub enum ContinuityError {
44    /// Returned when a bridge with no prior position information is
45    PriorPositionNotFound,
46    /// Returned when the subsequent bridge's prior position does not match the position of the
47    /// prior bridge's frontier.
48    PositionMismatch(Position, Position),
49}
50
51/// Errors that can be discovered during the process of attempting to create
52/// the witness for a leaf node.
53#[derive(Clone, Debug, PartialEq, Eq)]
54pub enum WitnessingError {
55    AuthBaseNotFound,
56    CheckpointInvalid,
57    CheckpointTooDeep(usize),
58    PositionNotMarked(Position),
59    BridgeFusionError(ContinuityError),
60    BridgeAddressInvalid(Address),
61}
62
63/// The information required to "update" witnesses from one state of a Merkle tree to another.
64///
65/// The witness for a particular leaf of a Merkle tree consists of the siblings of that leaf, plus
66/// the siblings of the parents of that leaf in a path to the root of the tree. When considering a
67/// Merkle tree where leaves are appended to the tree in a linear fashion (rather than being
68/// inserted at arbitrary positions), we often wish to produce a witness for a leaf that was
69/// appended to the tree at some point in the past. A [`MerkleBridge`] from one position in the
70/// tree to another position in the tree contains the minimal amount of information necessary to
71/// produce a witness for the leaf at the former position, given that leaves have been subsequently
72/// appended to reach the current position.
73///
74/// [`MerkleBridge`] values have a semigroup, such that the sum (`fuse`d) value of two successive
75/// bridges, along with a [`NonEmptyFrontier`] with its tip at the prior position of the first bridge
76/// being fused, can be used to produce a witness for the leaf at the tip of the prior frontier.
77#[derive(Clone, Debug, PartialEq, Eq)]
78pub struct MerkleBridge<H> {
79    /// The position of the final leaf in the frontier of the bridge that this bridge is the
80    /// successor of, or None if this is the first bridge in a tree.
81    prior_position: Option<Position>,
82    /// The set of addresses for which we are waiting to discover the ommers.  The values of this
83    /// set and the keys of the `need` map should always be disjoint. Also, this set should
84    /// never contain an address for which the sibling value has been discovered; at that point,
85    /// the address is replaced in this set with its parent and the address/sibling pair is stored
86    /// in `ommers`.
87    ///
88    /// Another way to consider the contents of this set is that the values that exist in
89    /// `ommers`, combined with the values in previous bridges' `ommers` and an original leaf
90    /// node, already contain all the values needed to compute the value at the given address.
91    /// Therefore, we are tracking that address as we do not yet have enough information to compute
92    /// its sibling without filling the sibling subtree with empty nodes.
93    tracking: BTreeSet<Address>,
94    /// A map from addresses that were being tracked to the values of their ommers that have been
95    /// discovered while scanning this bridge's range by adding leaves to the bridge's frontier.
96    ommers: BTreeMap<Address, H>,
97    /// The leading edge of the bridge.
98    frontier: NonEmptyFrontier<H>,
99}
100
101impl<H> MerkleBridge<H> {
102    /// Construct a new Merkle bridge containing only the specified
103    /// leaf.
104    pub fn new(value: H) -> Self {
105        Self {
106            prior_position: None,
107            tracking: BTreeSet::new(),
108            ommers: BTreeMap::new(),
109            frontier: NonEmptyFrontier::new(value),
110        }
111    }
112
113    /// Construct a new Merkle bridge from its constituent parts.
114    pub fn from_parts(
115        prior_position: Option<Position>,
116        tracking: BTreeSet<Address>,
117        ommers: BTreeMap<Address, H>,
118        frontier: NonEmptyFrontier<H>,
119    ) -> Self {
120        Self {
121            prior_position,
122            tracking,
123            ommers,
124            frontier,
125        }
126    }
127
128    /// Returns the position of the final leaf in the frontier of the
129    /// bridge that this bridge is the successor of, or None
130    /// if this is the first bridge in a tree.
131    pub fn prior_position(&self) -> Option<Position> {
132        self.prior_position
133    }
134
135    /// Returns the position of the most recently appended leaf.
136    pub fn position(&self) -> Position {
137        self.frontier.position()
138    }
139
140    /// Returns the set of internal node addresses that we're searching
141    /// for the ommers for.
142    pub fn tracking(&self) -> &BTreeSet<Address> {
143        &self.tracking
144    }
145
146    /// Returns the set of internal node addresses that we're searching
147    /// for the ommers for.
148    pub fn ommers(&self) -> &BTreeMap<Address, H> {
149        &self.ommers
150    }
151
152    /// Returns the non-empty frontier of this Merkle bridge.
153    pub fn frontier(&self) -> &NonEmptyFrontier<H> {
154        &self.frontier
155    }
156
157    /// Returns the value of the most recently appended leaf.
158    pub fn current_leaf(&self) -> &H {
159        self.frontier.leaf()
160    }
161
162    /// Checks whether this bridge is a valid successor for the specified
163    /// bridge.
164    pub fn check_continuity(&self, next: &Self) -> Result<(), ContinuityError> {
165        if let Some(pos) = next.prior_position {
166            if pos == self.frontier.position() {
167                Ok(())
168            } else {
169                Err(ContinuityError::PositionMismatch(
170                    self.frontier.position(),
171                    pos,
172                ))
173            }
174        } else {
175            Err(ContinuityError::PriorPositionNotFound)
176        }
177    }
178
179    /// Returns the range of positions observed by this bridge.
180    pub fn position_range(&self) -> Range<Position> {
181        Range {
182            start: self.prior_position.unwrap_or_else(|| Position::from(0)),
183            end: self.position() + 1,
184        }
185    }
186}
187
188impl<'a, H: Hashable + Clone + Ord + 'a> MerkleBridge<H> {
189    /// Constructs a new bridge to follow this one. If `mark_current_leaf` is true, the successor
190    /// will track the information necessary to create a witness for the leaf most
191    /// recently appended to this bridge's frontier.
192    #[must_use]
193    pub fn successor(&self, track_current_leaf: bool) -> Self {
194        let mut result = Self {
195            prior_position: Some(self.frontier.position()),
196            tracking: self.tracking.clone(),
197            ommers: BTreeMap::new(),
198            frontier: self.frontier.clone(),
199        };
200
201        if track_current_leaf {
202            result.track_current_leaf();
203        }
204
205        result
206    }
207
208    fn track_current_leaf(&mut self) {
209        self.tracking
210            .insert(Address::from(self.frontier.position()).current_incomplete());
211    }
212
213    /// Advances this bridge's frontier by appending the specified node,
214    /// and updates any auth path ommers being tracked if necessary.
215    pub fn append(&mut self, value: H) {
216        self.frontier.append(value);
217
218        let mut found = vec![];
219        for address in self.tracking.iter() {
220            // We know that there will only ever be one address that we're
221            // tracking at a given level, because as soon as we find a
222            // value for the sibling of the address we're tracking, we
223            // remove the tracked address and replace it the next parent
224            // of that address for which we need to find a sibling.
225            if self
226                .frontier()
227                .position()
228                .is_complete_subtree(address.level())
229            {
230                let digest = self.frontier.root(Some(address.level()));
231                self.ommers.insert(address.sibling(), digest);
232                found.push(*address);
233            }
234        }
235
236        for address in found {
237            self.tracking.remove(&address);
238
239            // The address of the next incomplete parent note for which
240            // we need to find a sibling.
241            let parent = address.next_incomplete_parent();
242            assert!(!self.ommers.contains_key(&parent));
243            self.tracking.insert(parent);
244        }
245    }
246
247    /// Returns a single MerkleBridge that contains the aggregate information
248    /// of this bridge and `next`, or None if `next` is not a valid successor
249    /// to this bridge. The resulting Bridge will have the same state as though
250    /// `self` had had every leaf used to construct `next` appended to it
251    /// directly.
252    fn fuse(&self, next: &Self) -> Result<Self, ContinuityError> {
253        self.check_continuity(next)?;
254
255        Ok(Self {
256            prior_position: self.prior_position,
257            tracking: next.tracking.clone(),
258            ommers: self
259                .ommers
260                .iter()
261                .chain(next.ommers.iter())
262                .map(|(k, v)| (*k, v.clone()))
263                .collect(),
264            frontier: next.frontier.clone(),
265        })
266    }
267
268    /// Returns a single MerkleBridge that contains the aggregate information
269    /// of all the provided bridges (discarding internal frontiers) or None
270    /// if the provided iterator is empty. Returns a continuity error if
271    /// any of the bridges are not valid successors to one another.
272    fn fuse_all<T: Iterator<Item = &'a Self>>(
273        mut iter: T,
274    ) -> Result<Option<Self>, ContinuityError> {
275        let mut fused = iter.next().cloned();
276        for next in iter {
277            fused = Some(fused.unwrap().fuse(next)?);
278        }
279        Ok(fused)
280    }
281
282    /// If this bridge contains sufficient auth fragment information, construct an authentication
283    /// path for the specified position by interleaving with values from the prior frontier. This
284    /// method will panic if the position of the prior frontier does not match this bridge's prior
285    /// position.
286    fn witness(
287        &self,
288        depth: u8,
289        prior_frontier: &NonEmptyFrontier<H>,
290    ) -> Result<Vec<H>, WitnessingError> {
291        assert!(Some(prior_frontier.position()) == self.prior_position);
292
293        prior_frontier
294            .witness(depth, |addr| {
295                let r = addr.position_range();
296                if self.frontier.position() < r.start {
297                    Some(H::empty_root(addr.level()))
298                } else if r.contains(&self.frontier.position()) {
299                    Some(self.frontier.root(Some(addr.level())))
300                } else {
301                    // the frontier's position is after the end of the requested
302                    // range, so the requested value should exist in a stored
303                    // fragment
304                    self.ommers.get(&addr).cloned()
305                }
306            })
307            .map_err(WitnessingError::BridgeAddressInvalid)
308    }
309
310    fn retain(&mut self, ommer_addrs: &BTreeSet<Address>) {
311        // Prune away any ommers & tracking addresses we don't need
312        self.tracking
313            .retain(|addr| ommer_addrs.contains(&addr.sibling()));
314        self.ommers.retain(|addr, _| ommer_addrs.contains(addr));
315    }
316}
317
318/// A data structure used to store the information necessary to "rewind" the state of a
319/// [`BridgeTree`] to a particular leaf position.
320///
321/// This is needed because the [`BridgeTree::marked_indices`] map is a cache of information that
322/// crosses [`MerkleBridge`] boundaries, and so it is not sufficient to just truncate the list of
323/// bridges; instead, we use [`Checkpoint`] values to be able to rapidly restore the cache to its
324/// previous state.
325#[derive(Clone, Debug, PartialEq, Eq)]
326pub struct Checkpoint<C> {
327    /// The unique identifier for this checkpoint.
328    id: C,
329    /// The number of bridges that will be retained in a rewind.
330    bridges_len: usize,
331    /// A set of the positions that have been marked during the period that this
332    /// checkpoint is the current checkpoint.
333    marked: BTreeSet<Position>,
334    /// When a mark is forgotten, we add it to the checkpoint's forgotten set but
335    /// don't immediately remove it from the `saved` map; that removal occurs when
336    /// the checkpoint is eventually dropped.
337    forgotten: BTreeSet<Position>,
338}
339
340impl<C> Checkpoint<C> {
341    /// Creates a new checkpoint from its constituent parts.
342    pub fn from_parts(
343        id: C,
344        bridges_len: usize,
345        marked: BTreeSet<Position>,
346        forgotten: BTreeSet<Position>,
347    ) -> Self {
348        Self {
349            id,
350            bridges_len,
351            marked,
352            forgotten,
353        }
354    }
355
356    /// Creates a new empty checkpoint for the specified [`BridgeTree`] state.
357    pub fn at_length(bridges_len: usize, id: C) -> Self {
358        Checkpoint {
359            id,
360            bridges_len,
361            marked: BTreeSet::new(),
362            forgotten: BTreeSet::new(),
363        }
364    }
365
366    /// The unique identifier for the checkpoint.
367    pub fn id(&self) -> &C {
368        &self.id
369    }
370
371    /// Returns the length of the [`BridgeTree::prior_bridges`] vector of the [`BridgeTree`] to
372    /// which this checkpoint refers.
373    ///
374    /// This is the number of bridges that will be retained in the event of a rewind to this
375    /// checkpoint.
376    pub fn bridges_len(&self) -> usize {
377        self.bridges_len
378    }
379
380    /// Returns a set of the positions that have been marked during the period that this
381    /// checkpoint is the current checkpoint.
382    pub fn marked(&self) -> &BTreeSet<Position> {
383        &self.marked
384    }
385
386    /// Returns the set of previously-marked positions that have had their marks removed
387    /// during the period that this checkpoint is the current checkpoint.
388    pub fn forgotten(&self) -> &BTreeSet<Position> {
389        &self.forgotten
390    }
391
392    // A private convenience method that returns the root of the bridge corresponding to
393    // this checkpoint at a specified depth, given the slice of bridges from which this checkpoint
394    // was derived.
395    fn root<H>(&self, bridges: &[MerkleBridge<H>], level: Level) -> H
396    where
397        H: Hashable + Clone + Ord,
398    {
399        if self.bridges_len == 0 {
400            H::empty_root(level)
401        } else {
402            bridges[self.bridges_len - 1].frontier().root(Some(level))
403        }
404    }
405
406    // A private convenience method that returns the position of the bridge corresponding
407    // to this checkpoint, if the checkpoint is not for the empty bridge.
408    fn position<H: Ord>(&self, bridges: &[MerkleBridge<H>]) -> Option<Position> {
409        if self.bridges_len == 0 {
410            None
411        } else {
412            Some(bridges[self.bridges_len - 1].position())
413        }
414    }
415
416    // A private method that rewrites the indices of each forgotten marked record
417    // using the specified rewrite function. Used during garbage collection.
418    fn rewrite_indices<F: Fn(usize) -> usize>(&mut self, f: F) {
419        self.bridges_len = f(self.bridges_len);
420    }
421}
422
423/// A sparse representation of a Merkle tree with linear appending of leaves that contains enough
424/// information to produce a witness for any `mark`ed leaf.
425#[derive(Clone, PartialEq, Eq)]
426pub struct BridgeTree<H, C, const DEPTH: u8> {
427    /// The ordered list of Merkle bridges representing the history
428    /// of the tree. There will be one bridge for each saved leaf.
429    prior_bridges: Vec<MerkleBridge<H>>,
430    /// The current (mutable) bridge at the tip of the tree.
431    current_bridge: Option<MerkleBridge<H>>,
432    /// A map from positions for which we wish to be able to compute a
433    /// witness to index in the bridges vector.
434    saved: BTreeMap<Position, usize>,
435    /// A deque of bridge indices to which it's possible to rewind directly.
436    /// This deque must be maintained to have a minimum size of 1 and a maximum
437    /// size of `max_checkpoints` in order to correctly maintain mark & rewind
438    /// semantics.
439    checkpoints: VecDeque<Checkpoint<C>>,
440    /// The maximum number of checkpoints to retain. If this number is
441    /// exceeded, the oldest checkpoint will be dropped when creating
442    /// a new checkpoint.
443    max_checkpoints: usize,
444}
445
446impl<H: Debug, C: Debug, const DEPTH: u8> Debug for BridgeTree<H, C, DEPTH> {
447    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
448        write!(
449            f,
450            "BridgeTree {{\n  depth: {:?},\n  prior_bridges: {:?},\n  current_bridge: {:?},\n  saved: {:?},\n  checkpoints: {:?},\n  max_checkpoints: {:?}\n}}",
451            DEPTH, self.prior_bridges, self.current_bridge, self.saved, self.checkpoints, self.max_checkpoints
452        )
453    }
454}
455
456/// Errors that can appear when validating the internal consistency of a `[BridgeTree]`
457/// value when constructing a tree from its constituent parts.
458#[derive(Debug, Clone, PartialEq, Eq)]
459pub enum BridgeTreeError {
460    IncorrectIncompleteIndex,
461    InvalidMarkIndex(usize),
462    PositionMismatch { expected: Position, found: Position },
463    InvalidSavePoints,
464    Discontinuity(ContinuityError),
465    CheckpointMismatch,
466}
467
468impl<H, C, const DEPTH: u8> BridgeTree<H, C, DEPTH> {
469    /// Construct an empty BridgeTree value with the specified maximum number of checkpoints.
470    ///
471    /// Panics if `max_checkpoints < 1` because mark/rewind logic depends upon the presence
472    /// of checkpoints to function.
473    pub fn new(max_checkpoints: usize) -> Self {
474        assert!(max_checkpoints >= 1);
475        Self {
476            prior_bridges: vec![],
477            current_bridge: None,
478            saved: BTreeMap::new(),
479            checkpoints: VecDeque::new(),
480            max_checkpoints,
481        }
482    }
483
484    /// Removes the oldest checkpoint if there are more than `max_checkpoints`. Returns true if
485    /// successful and false if there are not enough checkpoints.
486    fn drop_oldest_checkpoint(&mut self) -> bool {
487        if self.checkpoints.len() > self.max_checkpoints {
488            let c = self
489                .checkpoints
490                .pop_front()
491                .expect("Checkpoints deque is known to be non-empty.");
492            for pos in c.forgotten.iter() {
493                self.saved.remove(pos);
494            }
495            true
496        } else {
497            false
498        }
499    }
500
501    /// Returns the prior bridges that make up this tree
502    pub fn prior_bridges(&self) -> &[MerkleBridge<H>] {
503        &self.prior_bridges
504    }
505
506    /// Returns the current bridge at the tip of this tree
507    pub fn current_bridge(&self) -> &Option<MerkleBridge<H>> {
508        &self.current_bridge
509    }
510
511    /// Returns the map from leaf positions that have been marked to the index of
512    /// the bridge whose tip is at that position in this tree's list of bridges.
513    pub fn marked_indices(&self) -> &BTreeMap<Position, usize> {
514        &self.saved
515    }
516
517    /// Returns the checkpoints to which this tree may be rewound.
518    pub fn checkpoints(&self) -> &VecDeque<Checkpoint<C>> {
519        &self.checkpoints
520    }
521
522    /// Returns the maximum number of checkpoints that will be maintained
523    /// by the data structure. When this number of checkpoints is exceeded,
524    /// the oldest checkpoints are discarded when creating new checkpoints.
525    pub fn max_checkpoints(&self) -> usize {
526        self.max_checkpoints
527    }
528
529    /// Returns the bridge's frontier.
530    pub fn frontier(&self) -> Option<&NonEmptyFrontier<H>> {
531        self.current_bridge.as_ref().map(|b| b.frontier())
532    }
533}
534
535impl<H: Hashable + Clone + Ord, C: Clone + Ord, const DEPTH: u8> BridgeTree<H, C, DEPTH> {
536    /// Construct a new BridgeTree that will start recording changes from the state of
537    /// the specified frontier.
538    pub fn from_frontier(max_checkpoints: usize, frontier: NonEmptyFrontier<H>) -> Self {
539        Self {
540            prior_bridges: vec![],
541            current_bridge: Some(MerkleBridge::from_parts(
542                None,
543                BTreeSet::new(),
544                BTreeMap::new(),
545                frontier,
546            )),
547            saved: BTreeMap::new(),
548            checkpoints: VecDeque::new(),
549            max_checkpoints,
550        }
551    }
552
553    /// Construct a new BridgeTree from its constituent parts, checking for internal
554    /// consistency.
555    pub fn from_parts(
556        prior_bridges: Vec<MerkleBridge<H>>,
557        current_bridge: Option<MerkleBridge<H>>,
558        saved: BTreeMap<Position, usize>,
559        checkpoints: VecDeque<Checkpoint<C>>,
560        max_checkpoints: usize,
561    ) -> Result<Self, BridgeTreeError> {
562        Self::check_consistency_internal(
563            &prior_bridges,
564            &current_bridge,
565            &saved,
566            &checkpoints,
567            max_checkpoints,
568        )?;
569        Ok(BridgeTree {
570            prior_bridges,
571            current_bridge,
572            saved,
573            checkpoints,
574            max_checkpoints,
575        })
576    }
577
578    fn check_consistency(&self) -> Result<(), BridgeTreeError> {
579        Self::check_consistency_internal(
580            &self.prior_bridges,
581            &self.current_bridge,
582            &self.saved,
583            &self.checkpoints,
584            self.max_checkpoints,
585        )
586    }
587
588    fn check_consistency_internal(
589        prior_bridges: &[MerkleBridge<H>],
590        current_bridge: &Option<MerkleBridge<H>>,
591        saved: &BTreeMap<Position, usize>,
592        checkpoints: &VecDeque<Checkpoint<C>>,
593        max_checkpoints: usize,
594    ) -> Result<(), BridgeTreeError> {
595        // check that saved values correspond to bridges
596        for (pos, i) in saved {
597            if i >= &prior_bridges.len() {
598                return Err(BridgeTreeError::InvalidMarkIndex(*i));
599            }
600            let found = prior_bridges[*i].position();
601            if &found != pos {
602                return Err(BridgeTreeError::PositionMismatch {
603                    expected: *pos,
604                    found,
605                });
606            }
607        }
608
609        if checkpoints.len() > max_checkpoints
610            || checkpoints
611                .iter()
612                .any(|c| c.bridges_len > prior_bridges.len())
613        {
614            return Err(BridgeTreeError::CheckpointMismatch);
615        }
616
617        for (prev, next) in prior_bridges.iter().zip(prior_bridges.iter().skip(1)) {
618            prev.check_continuity(next)
619                .map_err(BridgeTreeError::Discontinuity)?;
620        }
621
622        if let Some((prev, next)) = prior_bridges.last().zip(current_bridge.as_ref()) {
623            prev.check_continuity(next)
624                .map_err(BridgeTreeError::Discontinuity)?;
625        }
626
627        Ok(())
628    }
629
630    /// Appends a new value to the tree at the next available slot.
631    /// Returns true if successful and false if the tree would exceed
632    /// the maximum allowed depth.
633    pub fn append(&mut self, value: H) -> bool {
634        if let Some(bridge) = self.current_bridge.as_mut() {
635            if bridge
636                .frontier
637                .position()
638                .is_complete_subtree(Level::from(DEPTH))
639            {
640                false
641            } else {
642                bridge.append(value);
643                true
644            }
645        } else {
646            self.current_bridge = Some(MerkleBridge::new(value));
647            true
648        }
649    }
650
651    /// Obtains the root of the Merkle tree at the specified checkpoint depth
652    /// by hashing against empty nodes up to the maximum height of the tree.
653    /// Returns `None` if there are not enough checkpoints available to reach the
654    /// requested checkpoint depth.
655    pub fn root(&self, checkpoint_depth: usize) -> Option<H> {
656        let root_level = Level::from(DEPTH);
657        if checkpoint_depth == 0 {
658            Some(
659                self.current_bridge
660                    .as_ref()
661                    .map_or(H::empty_root(root_level), |bridge| {
662                        bridge.frontier().root(Some(root_level))
663                    }),
664            )
665        } else if self.checkpoints.len() >= checkpoint_depth {
666            let checkpoint_idx = self.checkpoints.len() - checkpoint_depth;
667            self.checkpoints
668                .get(checkpoint_idx)
669                .map(|c| c.root(&self.prior_bridges, root_level))
670        } else {
671            None
672        }
673    }
674
675    /// Returns the most recently appended leaf value.
676    pub fn current_position(&self) -> Option<Position> {
677        self.current_bridge.as_ref().map(|b| b.position())
678    }
679
680    /// Returns the most recently appended leaf value.
681    pub fn current_leaf(&self) -> Option<&H> {
682        self.current_bridge.as_ref().map(|b| b.current_leaf())
683    }
684
685    /// Marks the current leaf as one for which we're interested in producing a witness.
686    ///
687    /// Returns an optional value containing the current position if successful or if the current
688    /// value was already marked, or None if the tree is empty.
689    pub fn mark(&mut self) -> Option<Position> {
690        match self.current_bridge.take() {
691            Some(mut cur_b) => {
692                let pos = cur_b.position();
693                // If the latest bridge is a newly created checkpoint, the last prior
694                // bridge will have the same position and all we need to do is mark
695                // the checkpointed leaf as being saved.
696                if self
697                    .prior_bridges
698                    .last()
699                    .map_or(false, |prior_b| prior_b.position() == cur_b.position())
700                {
701                    // the current bridge has not been advanced, so we just need to make
702                    // sure that we have are tracking the marked leaf
703                    cur_b.track_current_leaf();
704                    self.current_bridge = Some(cur_b);
705                } else {
706                    // the successor(true) call will ensure that the marked leaf is tracked
707                    let successor = cur_b.successor(true);
708                    self.prior_bridges.push(cur_b);
709                    self.current_bridge = Some(successor);
710                }
711
712                // mark the position as having been marked in the current checkpoint
713                if let std::collections::btree_map::Entry::Vacant(e) = self.saved.entry(pos) {
714                    if let Some(c) = self.checkpoints.back_mut() {
715                        c.marked.insert(pos);
716                    }
717                    e.insert(self.prior_bridges.len() - 1);
718                }
719
720                Some(pos)
721            }
722            None => None,
723        }
724    }
725
726    /// Return a set of all the positions for which we have marked.
727    pub fn marked_positions(&self) -> BTreeSet<Position> {
728        self.saved.keys().cloned().collect()
729    }
730
731    /// Returns the leaf at the specified position if the tree can produce
732    /// a witness for it.
733    pub fn get_marked_leaf(&self, position: Position) -> Option<&H> {
734        self.saved
735            .get(&position)
736            .and_then(|idx| self.prior_bridges.get(*idx).map(|b| b.current_leaf()))
737    }
738
739    /// Marks the value at the specified position as a value we're no longer
740    /// interested in maintaining a mark for. Returns true if successful and
741    /// false if we were already not maintaining a mark at this position.
742    pub fn remove_mark(&mut self, position: Position) -> bool {
743        if self.saved.contains_key(&position) {
744            if let Some(c) = self.checkpoints.back_mut() {
745                c.forgotten.insert(position);
746            } else {
747                self.saved.remove(&position);
748            }
749            true
750        } else {
751            false
752        }
753    }
754
755    /// Creates a new checkpoint for the current tree state, with the given identifier.
756    ///
757    /// It is valid to have multiple checkpoints for the same tree state, and each `rewind` call
758    /// will remove a single checkpoint. Successive checkpoint identifiers must always be provided
759    /// in increasing order.
760    pub fn checkpoint(&mut self, id: C) -> bool {
761        if Some(&id) > self.checkpoints.back().map(|c| &c.id) {
762            match self.current_bridge.take() {
763                Some(cur_b) => {
764                    // Do not create a duplicate bridge
765                    if self
766                        .prior_bridges
767                        .last()
768                        .map_or(false, |pb| pb.position() == cur_b.position())
769                    {
770                        self.current_bridge = Some(cur_b);
771                    } else {
772                        self.current_bridge = Some(cur_b.successor(false));
773                        self.prior_bridges.push(cur_b);
774                    }
775
776                    self.checkpoints
777                        .push_back(Checkpoint::at_length(self.prior_bridges.len(), id));
778                }
779                None => {
780                    self.checkpoints.push_back(Checkpoint::at_length(0, id));
781                }
782            }
783
784            if self.checkpoints.len() > self.max_checkpoints {
785                self.drop_oldest_checkpoint();
786            }
787
788            true
789        } else {
790            false
791        }
792    }
793
794    /// Rewinds the tree state to the previous checkpoint, and then removes
795    /// that checkpoint record. If there are multiple checkpoints at a given
796    /// tree state, the tree state will not be altered until all checkpoints
797    /// at that tree state have been removed using `rewind`. This function
798    /// return false and leave the tree unmodified if no checkpoints exist.
799    pub fn rewind(&mut self) -> bool {
800        if let Some(c) = self.checkpoints.pop_back() {
801            // Remove marks for positions that were marked during the lifetime of this checkpoint.
802            for pos in c.marked {
803                self.saved.remove(&pos);
804            }
805
806            self.prior_bridges.truncate(c.bridges_len);
807            self.current_bridge = self
808                .prior_bridges
809                .last()
810                .map(|b| b.successor(self.saved.contains_key(&b.position())));
811            true
812        } else {
813            false
814        }
815    }
816
817    /// Obtains a witness for the value at the specified leaf position, as of the tree state at the
818    /// given checkpoint depth. Returns `None` if there is no witness information for the requested
819    /// position or if no checkpoint is available at the specified depth.
820    pub fn witness(
821        &self,
822        position: Position,
823        checkpoint_depth: usize,
824    ) -> Result<Vec<H>, WitnessingError> {
825        #[derive(Debug)]
826        enum AuthBase<'a, C> {
827            Current,
828            Checkpoint(usize, &'a Checkpoint<C>),
829        }
830
831        // Find the earliest checkpoint having a matching root, or the current
832        // root if it matches and there is no earlier matching checkpoint.
833        let auth_base = if checkpoint_depth == 0 {
834            Ok(AuthBase::Current)
835        } else if self.checkpoints.len() >= checkpoint_depth {
836            let c_idx = self.checkpoints.len() - checkpoint_depth;
837            if self
838                .checkpoints
839                .iter()
840                .skip(c_idx)
841                .take_while(|c| {
842                    c.position(&self.prior_bridges)
843                        .iter()
844                        .any(|p| p <= &position)
845                })
846                .any(|c| c.marked.contains(&position))
847            {
848                // The mark had not yet been established at the point the checkpoint was
849                // created, so we can't treat it as marked.
850                Err(WitnessingError::PositionNotMarked(position))
851            } else {
852                Ok(AuthBase::Checkpoint(c_idx, &self.checkpoints[c_idx]))
853            }
854        } else {
855            Err(WitnessingError::CheckpointInvalid)
856        }?;
857
858        let saved_idx = self
859            .saved
860            .get(&position)
861            .ok_or(WitnessingError::PositionNotMarked(position))?;
862
863        let prior_frontier = &self.prior_bridges[*saved_idx].frontier;
864
865        // Fuse the following bridges to obtain a bridge that has all
866        // of the data to the right of the selected value in the tree,
867        // up to the specified checkpoint depth.
868        let fuse_from = saved_idx + 1;
869        let successor = match auth_base {
870            AuthBase::Current => {
871                // fuse all the way up to the current tip
872                MerkleBridge::fuse_all(
873                    self.prior_bridges[fuse_from..]
874                        .iter()
875                        .chain(&self.current_bridge),
876                )
877                .map(|fused| fused.unwrap()) // safe as the iterator being fused is nonempty
878                .map_err(WitnessingError::BridgeFusionError)
879            }
880            AuthBase::Checkpoint(_, checkpoint) if fuse_from < checkpoint.bridges_len => {
881                // fuse from the provided checkpoint
882                MerkleBridge::fuse_all(self.prior_bridges[fuse_from..checkpoint.bridges_len].iter())
883                    .map(|fused| fused.unwrap()) // safe as the iterator being fused is nonempty
884                    .map_err(WitnessingError::BridgeFusionError)
885            }
886            AuthBase::Checkpoint(_, checkpoint) if fuse_from == checkpoint.bridges_len => {
887                // The successor bridge should just be the empty successor to the
888                // checkpointed bridge.
889                if checkpoint.bridges_len > 0 {
890                    Ok(self.prior_bridges[checkpoint.bridges_len - 1].successor(false))
891                } else {
892                    Err(WitnessingError::CheckpointInvalid)
893                }
894            }
895            AuthBase::Checkpoint(_, checkpoint) => {
896                // if the saved index is after the checkpoint, we can't generate
897                // an auth path
898                Err(WitnessingError::CheckpointTooDeep(
899                    fuse_from - checkpoint.bridges_len,
900                ))
901            }
902        }?;
903
904        successor.witness(DEPTH, prior_frontier)
905    }
906
907    /// Remove state from the tree that no longer needs to be maintained
908    /// because it is associated with checkpoints or marks that
909    /// have been removed from the tree at positions deeper than those
910    /// reachable by calls to `rewind`.
911    pub fn garbage_collect(&mut self) {
912        // Only garbage collect once we have more bridges than the maximum number of
913        // checkpoints; we cannot remove information that we might need to restore in
914        // a rewind.
915        if self.checkpoints.len() == self.max_checkpoints {
916            let gc_len = self.checkpoints.front().unwrap().bridges_len;
917            let mut cur: Option<MerkleBridge<H>> = None;
918            let mut merged = 0;
919            let mut ommer_addrs: BTreeSet<Address> = BTreeSet::new();
920            for (i, next_bridge) in std::mem::take(&mut self.prior_bridges)
921                .into_iter()
922                .enumerate()
923            {
924                if let Some(cur_bridge) = cur {
925                    let pos = cur_bridge.position();
926                    let mut new_cur = if self.saved.contains_key(&pos) || i > gc_len {
927                        // We need to remember cur_bridge; update its save index & put next_bridge
928                        // on the chopping block
929                        if let Some(idx) = self.saved.get_mut(&pos) {
930                            *idx -= merged;
931                        }
932
933                        // Add the elements of the auth path to the set of addresses we should
934                        // continue to track and retain information for
935                        for (addr, source) in cur_bridge
936                            .frontier
937                            .position()
938                            .witness_addrs(Level::from(DEPTH))
939                        {
940                            if source == Source::Future {
941                                ommer_addrs.insert(addr);
942                            }
943                        }
944
945                        self.prior_bridges.push(cur_bridge);
946                        next_bridge
947                    } else {
948                        // We can fuse these bridges together because we don't need to
949                        // remember next_bridge.
950                        merged += 1;
951                        cur_bridge.fuse(&next_bridge).unwrap()
952                    };
953
954                    new_cur.retain(&ommer_addrs);
955                    cur = Some(new_cur);
956                } else {
957                    // this case will only occur for the first bridge
958                    cur = Some(next_bridge);
959                }
960            }
961
962            // unwrap is safe because we know that prior_bridges was nonempty.
963            if let Some(last_bridge) = cur {
964                if let Some(idx) = self.saved.get_mut(&last_bridge.position()) {
965                    *idx -= merged;
966                }
967                self.prior_bridges.push(last_bridge);
968            }
969
970            for c in self.checkpoints.iter_mut() {
971                c.rewrite_indices(|idx| idx - merged);
972            }
973        }
974        if let Err(e) = self.check_consistency() {
975            panic!(
976                "Consistency check failed after garbage collection with {:?}",
977                e
978            );
979        }
980    }
981}
982
983#[cfg(test)]
984mod tests {
985    use proptest::prelude::*;
986    use std::fmt::Debug;
987
988    use super::*;
989    use incrementalmerkletree::Hashable;
990    use incrementalmerkletree_testing::{
991        self as testing, apply_operation, arb_operation, check_checkpoint_rewind, check_operations,
992        check_remove_mark, check_rewind_remove_mark, check_root_hashes, check_witnesses,
993        complete_tree::CompleteTree, CombinedTree, SipHashable,
994    };
995
996    impl<H: Hashable + Clone + Ord, const DEPTH: u8> testing::Tree<H, usize>
997        for BridgeTree<H, usize, DEPTH>
998    {
999        fn append(&mut self, value: H, retention: Retention<usize>) -> bool {
1000            let appended = BridgeTree::append(self, value);
1001            if appended {
1002                if retention.is_marked() {
1003                    BridgeTree::mark(self);
1004                }
1005                if let Retention::Checkpoint { id, .. } = retention {
1006                    BridgeTree::checkpoint(self, id);
1007                }
1008            }
1009            appended
1010        }
1011
1012        fn depth(&self) -> u8 {
1013            DEPTH
1014        }
1015
1016        fn current_position(&self) -> Option<Position> {
1017            BridgeTree::current_position(self)
1018        }
1019
1020        fn get_marked_leaf(&self, position: Position) -> Option<H> {
1021            BridgeTree::get_marked_leaf(self, position).cloned()
1022        }
1023
1024        fn marked_positions(&self) -> BTreeSet<Position> {
1025            BridgeTree::marked_positions(self)
1026        }
1027
1028        fn root(&self, checkpoint_depth: usize) -> Option<H> {
1029            BridgeTree::root(self, checkpoint_depth)
1030        }
1031
1032        fn witness(&self, position: Position, checkpoint_depth: usize) -> Option<Vec<H>> {
1033            BridgeTree::witness(self, position, checkpoint_depth).ok()
1034        }
1035
1036        fn remove_mark(&mut self, position: Position) -> bool {
1037            BridgeTree::remove_mark(self, position)
1038        }
1039
1040        fn checkpoint(&mut self, id: usize) -> bool {
1041            BridgeTree::checkpoint(self, id)
1042        }
1043
1044        fn rewind(&mut self) -> bool {
1045            BridgeTree::rewind(self)
1046        }
1047    }
1048
1049    #[test]
1050    fn tree_depth() {
1051        let mut tree = BridgeTree::<String, usize, 3>::new(100);
1052        for c in 'a'..'i' {
1053            assert!(tree.append(c.to_string()))
1054        }
1055        assert!(!tree.append('i'.to_string()));
1056    }
1057
1058    fn check_garbage_collect<H: Hashable + Clone + Ord + Debug, const DEPTH: u8>(
1059        mut tree: BridgeTree<H, usize, DEPTH>,
1060    ) {
1061        // Add checkpoints until we're sure everything that can be gc'ed will be gc'ed
1062        for i in 0..tree.max_checkpoints {
1063            tree.checkpoint(i + 1);
1064        }
1065
1066        let mut tree_mut = tree.clone();
1067        tree_mut.garbage_collect();
1068
1069        for pos in tree.saved.keys() {
1070            assert_eq!(tree.witness(*pos, 0), tree_mut.witness(*pos, 0));
1071        }
1072    }
1073
1074    fn arb_bridgetree<G: Strategy + Clone>(
1075        item_gen: G,
1076        max_count: usize,
1077    ) -> impl Strategy<Value = BridgeTree<G::Value, usize, 8>>
1078    where
1079        G::Value: Hashable + Clone + Ord + Debug + 'static,
1080    {
1081        let pos_gen = (0..max_count).prop_map(|p| Position::try_from(p).unwrap());
1082        proptest::collection::vec(arb_operation(item_gen, pos_gen), 0..max_count).prop_map(|ops| {
1083            let mut tree: BridgeTree<G::Value, usize, 8> = BridgeTree::new(10);
1084            for (i, op) in ops.into_iter().enumerate() {
1085                apply_operation(&mut tree, op.map_checkpoint_id(|_| i));
1086            }
1087            tree
1088        })
1089    }
1090
1091    proptest! {
1092        #[test]
1093        fn bridgetree_from_parts(
1094            tree in arb_bridgetree((97u8..123).prop_map(|c| char::from(c).to_string()), 100)
1095        ) {
1096            assert_eq!(
1097                BridgeTree::from_parts(
1098                    tree.prior_bridges.clone(),
1099                    tree.current_bridge.clone(),
1100                    tree.saved.clone(),
1101                    tree.checkpoints.clone(),
1102                    tree.max_checkpoints
1103                ),
1104                Ok(tree),
1105            );
1106        }
1107
1108        #[test]
1109        fn prop_garbage_collect(
1110            tree in arb_bridgetree((97u8..123).prop_map(|c| char::from(c).to_string()), 100)
1111        ) {
1112            check_garbage_collect(tree);
1113        }
1114    }
1115
1116    #[test]
1117    fn root_hashes() {
1118        check_root_hashes(BridgeTree::<String, usize, 4>::new);
1119    }
1120
1121    #[test]
1122    fn witness() {
1123        check_witnesses(BridgeTree::<String, usize, 4>::new);
1124    }
1125
1126    #[test]
1127    fn checkpoint_rewind() {
1128        check_checkpoint_rewind(|max_checkpoints| {
1129            BridgeTree::<String, usize, 4>::new(max_checkpoints)
1130        });
1131    }
1132
1133    #[test]
1134    fn rewind_remove_mark() {
1135        check_rewind_remove_mark(|max_checkpoints| {
1136            BridgeTree::<String, usize, 4>::new(max_checkpoints)
1137        });
1138    }
1139
1140    #[test]
1141    fn garbage_collect() {
1142        let mut tree: BridgeTree<String, usize, 7> = BridgeTree::new(1000);
1143        let empty_root = tree.root(0);
1144        tree.append("a".to_string());
1145        for i in 0..100 {
1146            tree.checkpoint(i + 1);
1147        }
1148        tree.garbage_collect();
1149        assert!(tree.root(0) != empty_root);
1150        tree.rewind();
1151        assert!(tree.root(0) != empty_root);
1152
1153        let mut t = BridgeTree::<String, usize, 7>::new(10);
1154        let mut to_unmark = vec![];
1155        let mut has_witness = vec![];
1156        for i in 0u64..100 {
1157            let elem: String = format!("{},", i);
1158            assert!(t.append(elem), "Append should succeed.");
1159            if i % 5 == 0 {
1160                t.checkpoint(usize::try_from(i).unwrap() + 1);
1161            }
1162            if i % 7 == 0 {
1163                t.mark();
1164                if i > 0 && i % 2 == 0 {
1165                    to_unmark.push(Position::from(i));
1166                } else {
1167                    has_witness.push(Position::from(i));
1168                }
1169            }
1170            if i % 11 == 0 && !to_unmark.is_empty() {
1171                let pos = to_unmark.remove(0);
1172                t.remove_mark(pos);
1173            }
1174        }
1175        // 32 = 20 (checkpointed) + 14 (marked) - 2 (marked & checkpointed)
1176        assert_eq!(t.prior_bridges().len(), 20 + 14 - 2);
1177        let witness = has_witness
1178            .iter()
1179            .map(|pos| match t.witness(*pos, 0) {
1180                Ok(path) => path,
1181                Err(e) => panic!("Failed to get auth path: {:?}", e),
1182            })
1183            .collect::<Vec<_>>();
1184        t.garbage_collect();
1185        // 20 = 32 - 10 (removed checkpoints) + 1 (not removed due to mark) - 3 (removed marks)
1186        assert_eq!(t.prior_bridges().len(), 32 - 10 + 1 - 3);
1187        let retained_witness = has_witness
1188            .iter()
1189            .map(|pos| t.witness(*pos, 0).expect("Must be able to get auth path"))
1190            .collect::<Vec<_>>();
1191        assert_eq!(witness, retained_witness);
1192    }
1193
1194    // Combined tree tests
1195    fn new_combined_tree<H: Hashable + Clone + Ord + Debug>(
1196        max_checkpoints: usize,
1197    ) -> CombinedTree<H, usize, CompleteTree<H, usize, 4>, BridgeTree<H, usize, 4>> {
1198        CombinedTree::new(
1199            CompleteTree::<H, usize, 4>::new(max_checkpoints),
1200            BridgeTree::<H, usize, 4>::new(max_checkpoints),
1201        )
1202    }
1203
1204    #[test]
1205    fn combined_remove_mark() {
1206        check_remove_mark(new_combined_tree);
1207    }
1208
1209    #[test]
1210    fn combined_rewind_remove_mark() {
1211        check_rewind_remove_mark(new_combined_tree);
1212    }
1213
1214    proptest! {
1215        #![proptest_config(ProptestConfig::with_cases(100000))]
1216
1217        #[test]
1218        fn check_randomized_u64_ops(
1219            ops in proptest::collection::vec(
1220                arb_operation(
1221                    (0..32u64).prop_map(SipHashable),
1222                    (0u64..100).prop_map(Position::from)
1223                ),
1224                1..100
1225            )
1226        ) {
1227            let tree = new_combined_tree(100);
1228            let indexed_ops = ops.iter().enumerate().map(|(i, op)| op.map_checkpoint_id(|_| i + 1)).collect::<Vec<_>>();
1229            check_operations(tree, &indexed_ops)?;
1230        }
1231
1232        #[test]
1233        fn check_randomized_str_ops(
1234            ops in proptest::collection::vec(
1235                arb_operation(
1236                    (97u8..123).prop_map(|c| char::from(c).to_string()),
1237                    (0u64..100).prop_map(Position::from)
1238                ),
1239                1..100
1240            )
1241        ) {
1242            let tree = new_combined_tree(100);
1243            let indexed_ops = ops.iter().enumerate().map(|(i, op)| op.map_checkpoint_id(|_| i + 1)).collect::<Vec<_>>();
1244            check_operations(tree, &indexed_ops)?;
1245        }
1246    }
1247}