zcash_history/
tree.rs

1use std::collections::HashMap;
2
3use crate::{Entry, EntryKind, EntryLink, Error, Version};
4
5/// Represents partially loaded tree.
6///
7/// Some kind of "view" into the array representation of the MMR tree.
8/// With only some of the leaves/nodes pre-loaded / pre-generated.
9/// Exact amount of the loaded data can be calculated by the constructing party,
10/// depending on the length of the tree and maximum amount of operations that are going
11/// to happen after construction. `Tree` should not be used as self-contained data structure,
12/// since it's internal state can grow indefinitely after serial operations.
13/// Intended use of this `Tree` is to instantiate it based on partially loaded data (see example
14/// how to pick right nodes from the array representation of MMR Tree), perform several operations
15/// (append-s/delete-s) and then drop it.
16pub struct Tree<V: Version> {
17    stored: HashMap<u32, Entry<V>>,
18
19    // This can grow indefinitely if `Tree` is misused as a self-contained data structure
20    generated: Vec<Entry<V>>,
21
22    // number of persistent(!) tree entries
23    stored_count: u32,
24
25    root: EntryLink,
26}
27
28impl<V: Version> Tree<V> {
29    /// Resolve link originated from this tree
30    pub fn resolve_link(&self, link: EntryLink) -> Result<IndexedNode<V>, Error> {
31        match link {
32            EntryLink::Generated(index) => self.generated.get(index as usize),
33            EntryLink::Stored(index) => self.stored.get(&index),
34        }
35        .map(|node| IndexedNode { node, link })
36        .ok_or(Error::ExpectedInMemory(link))
37    }
38
39    fn push(&mut self, data: Entry<V>) -> EntryLink {
40        let idx = self.stored_count;
41        self.stored_count += 1;
42        self.stored.insert(idx, data);
43        EntryLink::Stored(idx)
44    }
45
46    fn push_generated(&mut self, data: Entry<V>) -> EntryLink {
47        self.generated.push(data);
48        EntryLink::Generated(self.generated.len() as u32 - 1)
49    }
50
51    /// Populate tree with plain list of the leaves/nodes. For now, only for tests,
52    /// since this `Tree` structure is for partially loaded tree (but it might change)
53    #[cfg(test)]
54    pub fn populate(loaded: Vec<Entry<V>>, root: EntryLink) -> Self {
55        let mut result = Tree::invalid();
56        result.stored_count = loaded.len() as u32;
57        for (idx, item) in loaded.into_iter().enumerate() {
58            result.stored.insert(idx as u32, item);
59        }
60        result.root = root;
61
62        result
63    }
64
65    // Empty tree with invalid root
66    fn invalid() -> Self {
67        Tree {
68            root: EntryLink::Generated(0),
69            generated: Default::default(),
70            stored: Default::default(),
71            stored_count: 0,
72        }
73    }
74
75    /// New view into the tree array representation
76    ///
77    /// `length` is total length of the array representation (is generally not a sum of
78    ///     peaks.len + extra.len)
79    /// `peaks` is peaks of the mmr tree
80    /// `extra` is some extra nodes that calculated to be required during next one or more
81    /// operations on the tree.
82    ///
83    /// # Panics
84    ///
85    /// Will panic if `peaks` is empty.
86    pub fn new(length: u32, peaks: Vec<(u32, Entry<V>)>, extra: Vec<(u32, Entry<V>)>) -> Self {
87        assert!(!peaks.is_empty());
88
89        let mut result = Tree::invalid();
90
91        result.stored_count = length;
92
93        let mut root = EntryLink::Stored(peaks[0].0);
94        for (gen, (idx, node)) in peaks.into_iter().enumerate() {
95            result.stored.insert(idx, node);
96            if gen != 0 {
97                let next_generated = combine_nodes(
98                    result
99                        .resolve_link(root)
100                        .expect("Inserted before, cannot fail; qed"),
101                    result
102                        .resolve_link(EntryLink::Stored(idx))
103                        .expect("Inserted before, cannot fail; qed"),
104                );
105                root = result.push_generated(next_generated);
106            }
107        }
108
109        for (idx, node) in extra {
110            result.stored.insert(idx, node);
111        }
112
113        result.root = root;
114
115        result
116    }
117
118    fn get_peaks(&self, root: EntryLink, target: &mut Vec<EntryLink>) -> Result<(), Error> {
119        let (left_child_link, right_child_link) = {
120            let root = self.resolve_link(root)?;
121            if root.node.complete() {
122                target.push(root.link);
123                return Ok(());
124            }
125            (root.left()?, root.right()?)
126        };
127
128        self.get_peaks(left_child_link, target)?;
129        self.get_peaks(right_child_link, target)?;
130        Ok(())
131    }
132
133    /// Append one leaf to the tree.
134    ///
135    /// Returns links to actual nodes that has to be persisted as the result of the append.
136    /// If completed without error, at least one link to the appended
137    /// node (with metadata provided in `new_leaf`) will be returned.
138    pub fn append_leaf(&mut self, new_leaf: V::NodeData) -> Result<Vec<EntryLink>, Error> {
139        let root = self.root;
140        let new_leaf_link = self.push(Entry::new_leaf(new_leaf));
141        let mut appended = vec![new_leaf_link];
142
143        let mut peaks = Vec::new();
144        self.get_peaks(root, &mut peaks)?;
145
146        let mut merge_stack = vec![new_leaf_link];
147
148        // Scan the peaks right-to-left, merging together equal-sized adjacent
149        // complete subtrees. After this, merge_stack only contains peaks of
150        // unequal-sized subtrees.
151        while let Some(next_peak) = peaks.pop() {
152            let next_merge = merge_stack
153                .pop()
154                .expect("there should be at least one, initial or re-pushed");
155
156            if let Some(stored) = {
157                let peak = self.resolve_link(next_peak)?;
158                let m = self.resolve_link(next_merge)?;
159                if peak.node.leaf_count() == m.node.leaf_count() {
160                    Some(combine_nodes(peak, m))
161                } else {
162                    None
163                }
164            } {
165                let link = self.push(stored);
166                merge_stack.push(link);
167                appended.push(link);
168                continue;
169            } else {
170                merge_stack.push(next_merge);
171                merge_stack.push(next_peak);
172            }
173        }
174
175        let mut new_root = merge_stack
176            .pop()
177            .expect("Loop above cannot reduce the merge_stack");
178        // Scan the peaks left-to-right, producing new generated nodes that
179        // connect the subtrees
180        while let Some(next_child) = merge_stack.pop() {
181            new_root = self.push_generated(combine_nodes(
182                self.resolve_link(new_root)?,
183                self.resolve_link(next_child)?,
184            ))
185        }
186
187        self.root = new_root;
188
189        Ok(appended)
190    }
191
192    #[cfg(test)]
193    fn for_children<F: Fn(EntryLink, EntryLink)>(&self, node: EntryLink, f: F) {
194        let (left, right) = {
195            let link = self
196                .resolve_link(node)
197                .expect("Failed to resolve link in test");
198            (
199                link.left().expect("Failed to find node in test"),
200                link.right().expect("Failed to find node in test"),
201            )
202        };
203        f(left, right);
204    }
205
206    fn pop(&mut self) {
207        self.stored.remove(&(self.stored_count - 1));
208        self.stored_count -= 1;
209    }
210
211    /// Truncate one leaf from the end of the tree.
212    ///
213    /// Returns actual number of nodes that should be removed by the caller
214    /// from the end of the array representation.
215    pub fn truncate_leaf(&mut self) -> Result<u32, Error> {
216        let root = {
217            let (leaves, root_left_child) = {
218                let n = self.resolve_link(self.root)?;
219                (n.node.leaf_count(), n.node.left()?)
220            };
221            if leaves & 1 != 0 {
222                self.pop();
223                self.root = root_left_child;
224                return Ok(1);
225            } else {
226                self.resolve_link(self.root)?
227            }
228        };
229
230        let mut peaks = vec![root.left()?];
231        let mut subtree_root_link = root.right()?;
232        let mut truncated = 1;
233
234        loop {
235            let left_link = self.resolve_link(subtree_root_link)?.node;
236            if let EntryKind::Node(left, right) = left_link.kind {
237                peaks.push(left);
238                subtree_root_link = right;
239                truncated += 1;
240            } else {
241                if root.node.complete() {
242                    truncated += 1;
243                }
244                break;
245            }
246        }
247
248        let mut new_root = *peaks.first().expect("At lest 1 elements in peaks");
249
250        for next_peak in peaks.into_iter().skip(1) {
251            new_root = self.push_generated(combine_nodes(
252                self.resolve_link(new_root)?,
253                self.resolve_link(next_peak)?,
254            ));
255        }
256
257        for _ in 0..truncated {
258            self.pop();
259        }
260
261        self.root = new_root;
262
263        Ok(truncated)
264    }
265
266    /// Length of array representation of the tree.
267    pub fn len(&self) -> u32 {
268        self.stored_count
269    }
270
271    /// Link to the root node
272    pub fn root(&self) -> EntryLink {
273        self.root
274    }
275
276    /// Reference to the root node.
277    pub fn root_node(&self) -> Result<IndexedNode<V>, Error> {
278        self.resolve_link(self.root)
279    }
280
281    /// If this tree is empty.
282    pub fn is_empty(&self) -> bool {
283        self.stored_count == 0
284    }
285}
286
287/// Reference to the node with link attached.
288#[derive(Debug)]
289pub struct IndexedNode<'a, V: Version> {
290    node: &'a Entry<V>,
291    link: EntryLink,
292}
293
294impl<V: Version> IndexedNode<'_, V> {
295    fn left(&self) -> Result<EntryLink, Error> {
296        self.node.left().map_err(|e| e.augment(self.link))
297    }
298
299    fn right(&self) -> Result<EntryLink, Error> {
300        self.node.right().map_err(|e| e.augment(self.link))
301    }
302
303    /// Reference to the entry struct.
304    pub fn node(&self) -> &Entry<V> {
305        self.node
306    }
307
308    /// Reference to the entry metadata.
309    pub fn data(&self) -> &V::NodeData {
310        &self.node.data
311    }
312
313    /// Actual link by what this node was resolved.
314    pub fn link(&self) -> EntryLink {
315        self.link
316    }
317}
318
319fn combine_nodes<'a, V: Version>(left: IndexedNode<'a, V>, right: IndexedNode<'a, V>) -> Entry<V> {
320    Entry {
321        kind: EntryKind::Node(left.link, right.link),
322        data: V::combine(&left.node.data, &right.node.data),
323    }
324}
325
326#[cfg(test)]
327mod tests {
328    use super::{Entry, EntryKind, EntryLink, Tree};
329    use crate::{node_data, NodeData, Version, V2};
330
331    use assert_matches::assert_matches;
332    use proptest::prelude::*;
333
334    fn leaf(height: u32) -> node_data::V2 {
335        node_data::V2 {
336            v1: NodeData {
337                consensus_branch_id: 1,
338                subtree_commitment: [0u8; 32],
339                start_time: 0,
340                end_time: 0,
341                start_target: 0,
342                end_target: 0,
343                start_sapling_root: [0u8; 32],
344                end_sapling_root: [0u8; 32],
345                subtree_total_work: 0.into(),
346                start_height: height as u64,
347                end_height: height as u64,
348                sapling_tx: 7,
349            },
350            start_orchard_root: [0u8; 32],
351            end_orchard_root: [0u8; 32],
352            orchard_tx: 42,
353        }
354    }
355
356    fn initial() -> Tree<V2> {
357        let node1 = Entry::new_leaf(leaf(1));
358        let node2 = Entry::new_leaf(leaf(2));
359
360        let node3 = Entry {
361            data: V2::combine(&node1.data, &node2.data),
362            kind: EntryKind::Leaf,
363        };
364
365        Tree::populate(vec![node1, node2, node3], EntryLink::Stored(2))
366    }
367
368    // returns tree with specified number of leafs and it's root
369    fn generated(length: u32) -> Tree<V2> {
370        assert!(length >= 3);
371        let mut tree = initial();
372        for i in 2..length {
373            tree.append_leaf(leaf(i + 1)).expect("Failed to append");
374        }
375
376        tree
377    }
378
379    #[test]
380    fn discrete_append() {
381        let mut tree = initial();
382
383        // ** APPEND 3 **
384        let appended = tree.append_leaf(leaf(3)).expect("Failed to append");
385        let new_root = tree.root_node().expect("Failed to resolve root").node;
386
387        // initial tree:  (2)
388        //               /   \
389        //             (0)   (1)
390        //
391        // new tree:
392        //                (4g)
393        //               /   \
394        //             (2)    \
395        //             /  \    \
396        //           (0)  (1)  (3)
397        //
398        // so only (3) is added as real leaf
399        // while new root, (4g) is generated one
400        assert_eq!(new_root.data.v1.end_height, 3);
401        assert_eq!(appended.len(), 1);
402
403        // ** APPEND 4 **
404        let appended = tree.append_leaf(leaf(4)).expect("Failed to append");
405
406        let new_root = tree.root_node().expect("Failed to resolve root").node;
407
408        // intermediate tree:
409        //                (4g)
410        //               /   \
411        //             (2)    \
412        //             /  \    \
413        //           (0)  (1)  (3)
414        //
415        // new tree:
416        //                 ( 6 )
417        //                /     \
418        //             (2)       (5)
419        //             /  \     /   \
420        //           (0)  (1) (3)   (4)
421        //
422        // so (4), (5), (6) are added as real leaves
423        // and new root, (6) is stored one
424        assert_eq!(new_root.data.v1.end_height, 4);
425        assert_eq!(appended.len(), 3);
426        assert_matches!(tree.root(), EntryLink::Stored(6));
427
428        // ** APPEND 5 **
429
430        let appended = tree.append_leaf(leaf(5)).expect("Failed to append");
431        let new_root = tree.root_node().expect("Failed to resolve root").node;
432
433        // intermediate tree:
434        //                 ( 6 )
435        //                /     \
436        //             (2)       (5)
437        //             /  \     /   \
438        //           (0)  (1) (3)   (4)
439        //
440        // new tree:
441        //                     ( 8g )
442        //                    /      \
443        //                 ( 6 )      \
444        //                /     \      \
445        //             (2)       (5)    \
446        //             /  \     /   \    \
447        //           (0)  (1) (3)   (4)  (7)
448        //
449        // so (7) is added as real leaf
450        // and new root, (8g) is generated one
451        assert_eq!(new_root.data.v1.end_height, 5);
452        assert_eq!(appended.len(), 1);
453        assert_matches!(tree.root(), EntryLink::Generated(_));
454        tree.for_children(tree.root(), |l, r| {
455            assert_matches!(l, EntryLink::Stored(6));
456            assert_matches!(r, EntryLink::Stored(7));
457        });
458
459        // *** APPEND #6 ***
460        let appended = tree.append_leaf(leaf(6)).expect("Failed to append");
461        let new_root = tree.root_node().expect("Failed to resolve root").node;
462
463        // intermediate tree:
464        //                     ( 8g )
465        //                    /      \
466        //                 ( 6 )      \
467        //                /     \      \
468        //             (2)       (5)    \
469        //             /  \     /   \    \
470        //           (0)  (1) (3)   (4)  (7)
471        //
472        // new tree:
473        //                     (---10g--)
474        //                    /          \
475        //                 ( 6 )          \
476        //                /     \          \
477        //             (2)       (5)       (9)
478        //             /  \     /   \     /   \
479        //           (0)  (1) (3)   (4)  (7)  (8)
480        //
481        // so (7) is added as real leaf
482        // and new root, (10g) is generated one
483        assert_eq!(new_root.data.v1.end_height, 6);
484        assert_eq!(appended.len(), 2);
485        assert_matches!(tree.root(), EntryLink::Generated(_));
486        tree.for_children(tree.root(), |l, r| {
487            assert_matches!(l, EntryLink::Stored(6));
488            assert_matches!(r, EntryLink::Stored(9));
489        });
490
491        // *** APPEND #7 ***
492
493        let appended = tree.append_leaf(leaf(7)).expect("Failed to append");
494        let new_root = tree.root_node().expect("Failed to resolve root").node;
495
496        // intermediate tree:
497        //                     (---8g---)
498        //                    /          \
499        //                 ( 6 )          \
500        //                /     \          \
501        //             (2)       (5)       (9)
502        //             /  \     /   \     /   \
503        //           (0)  (1) (3)   (4)  (7)  (8)
504        //
505        // new tree:
506        //                          (---12g--)
507        //                         /          \
508        //                    (---11g---)      \
509        //                   /           \      \
510        //                 ( 6 )          \      \
511        //                /     \          \      \
512        //             (2)       (5)       (9)     \
513        //             /  \     /   \     /   \     \
514        //           (0)  (1) (3)   (4) (7)   (8)  (10)
515        //
516        // so (10) is added as real leaf
517        // and new root, (12g) is generated one
518        assert_eq!(new_root.data.v1.end_height, 7);
519        assert_eq!(appended.len(), 1);
520        assert_matches!(tree.root(), EntryLink::Generated(_));
521        tree.for_children(tree.root(), |l, r| {
522            assert_matches!(l, EntryLink::Generated(_));
523            tree.for_children(l, |l, r| {
524                assert_matches!((l, r), (EntryLink::Stored(6), EntryLink::Stored(9)))
525            });
526            assert_matches!(r, EntryLink::Stored(10));
527        });
528    }
529
530    #[test]
531    fn truncate_simple() {
532        let mut tree = generated(9);
533        let total_truncated = tree.truncate_leaf().expect("Failed to truncate");
534
535        // initial tree:
536        //
537        //                               (-------16g------)
538        //                              /                  \
539        //                    (--------14-------)           \
540        //                   /                   \           \
541        //                 ( 6 )              (  13  )        \
542        //                /     \            /        \        \
543        //             (2)       (5)       (9)        (12)      \
544        //             /  \     /   \     /   \      /    \      \
545        //           (0)  (1) (3)   (4) (7)   (8)  (10)  (11)    (15)
546        //
547        // new tree:
548        //                    (--------14-------)
549        //                   /                   \
550        //                 ( 6 )              (  13  )
551        //                /     \            /        \
552        //             (2)       (5)       (9)        (12)
553        //             /  \     /   \     /   \      /    \
554        //           (0)  (1) (3)   (4) (7)   (8)  (10)  (11)
555        //
556        // so (15) is truncated
557        // and new root, (14) is a stored one now
558
559        assert_matches!(tree.root(), EntryLink::Stored(14));
560        assert_eq!(total_truncated, 1);
561        assert_eq!(tree.len(), 15);
562    }
563
564    #[test]
565    fn truncate_generated() {
566        let mut tree = generated(10);
567        let deleted = tree.truncate_leaf().expect("Failed to truncate");
568
569        // initial tree:
570        //
571        //                               (--------18g--------)
572        //                              /                     \
573        //                    (--------14-------)              \
574        //                   /                   \              \
575        //                 ( 6 )              (  13  )           \
576        //                /     \            /        \           \
577        //             (2)       (5)       (9)        (12)        (17)
578        //             /  \     /   \     /   \      /    \      /    \
579        //           (0)  (1) (3)   (4) (7)   (8)  (10)  (11)  (15)  (16)
580        //
581        // new tree:
582        //                               (-------16g------)
583        //                              /                  \
584        //                    (--------14-------)           \
585        //                   /                   \           \
586        //                 ( 6 )              (  13  )        \
587        //                /     \            /        \        \
588        //             (2)       (5)       (9)        (12)      \
589        //             /  \     /   \     /   \      /    \      \
590        //           (0)  (1) (3)   (4) (7)   (8)  (10)  (11)    (15)
591
592        // new root is generated
593
594        assert_matches!(tree.root(), EntryLink::Generated(_));
595
596        tree.for_children(tree.root(), |left, right| {
597            assert_matches!(
598                (left, right),
599                (EntryLink::Stored(14), EntryLink::Stored(15))
600            )
601        });
602
603        // two stored nodes should leave us (leaf 16 and no longer needed node 17)
604        assert_eq!(deleted, 2);
605        assert_eq!(tree.len(), 16);
606    }
607
608    #[test]
609    fn tree_len() {
610        let mut tree = initial();
611
612        assert_eq!(tree.len(), 3);
613
614        for i in 0..2 {
615            tree.append_leaf(leaf(i + 3)).expect("Failed to append");
616        }
617        assert_eq!(tree.len(), 7);
618
619        tree.truncate_leaf().expect("Failed to truncate");
620
621        assert_eq!(tree.len(), 4);
622    }
623
624    #[test]
625    fn tree_len_long() {
626        let mut tree = initial();
627
628        assert_eq!(tree.len(), 3);
629
630        for i in 0..4094 {
631            tree.append_leaf(leaf(i + 3)).expect("Failed to append");
632        }
633        assert_eq!(tree.len(), 8191); // 4096*2-1 (full tree)
634
635        for _ in 0..2049 {
636            tree.truncate_leaf().expect("Failed to truncate");
637        }
638
639        assert_eq!(tree.len(), 4083); // 4095 - log2(4096)
640    }
641
642    proptest! {
643        #[test]
644        fn prop_there_and_back(number in 0u32..=1024) {
645            let mut tree = initial();
646            for i in 0..number {
647                tree.append_leaf(leaf(i+3)).expect("Failed to append");
648            }
649            for _ in 0..number {
650                tree.truncate_leaf().expect("Failed to truncate");
651            }
652
653            assert_matches!(tree.root(), EntryLink::Stored(2));
654        }
655
656        #[test]
657        fn prop_leaf_count(number in 3u32..=1024) {
658            let mut tree = initial();
659            for i in 1..(number-1) {
660                tree.append_leaf(leaf(i+2)).expect("Failed to append");
661            }
662
663            assert_eq!(tree.root_node().expect("no root").node.leaf_count(), number as u64);
664        }
665
666        #[test]
667        fn prop_parity(number in 3u32..=2048) {
668            let mut tree = initial();
669            for i in 1..(number-1) {
670                tree.append_leaf(leaf(i+2)).expect("Failed to append");
671            }
672
673            if number & (number - 1) == 0 {
674                assert_matches!(tree.root(), EntryLink::Stored(_));
675            } else {
676                assert_matches!(tree.root(), EntryLink::Generated(_));
677            }
678        }
679
680        #[test]
681        fn prop_parity_with_truncate(
682            add_and_delete in (0u32..=2048).prop_flat_map(
683                |add| (Just(add), 0..=add)
684            )
685        ) {
686            let (add, delete) = add_and_delete;
687            // First we add `add` number of leaves, then delete `delete` number of leaves
688            // What is left should be consistent with generated-stored structure
689            let mut tree = initial();
690            for i in 0..add {
691                tree.append_leaf(leaf(i+3)).expect("Failed to append");
692            }
693            for _ in 0..delete {
694                tree.truncate_leaf().expect("Failed to truncate");
695            }
696
697            let total = add - delete + 2;
698
699            if total & (total - 1) == 0 {
700                assert_matches!(tree.root(), EntryLink::Stored(_));
701            } else {
702                assert_matches!(tree.root(), EntryLink::Generated(_));
703            }
704        }
705
706        #[test]
707        fn prop_stored_length(
708            add_and_delete in (0u32..=2048).prop_flat_map(
709                |add| (Just(add), 0..=add)
710            )
711        ) {
712            let (add, delete) = add_and_delete;
713            let mut tree = initial();
714            for i in 0..add {
715                tree.append_leaf(leaf(i+3)).expect("Failed to append");
716            }
717            for _ in 0..delete {
718                tree.truncate_leaf().expect("Failed to truncate");
719            }
720
721            let total = add - delete + 2;
722
723            assert!(total * total > tree.len())
724        }
725    }
726}