1use std::collections::HashMap;
2
3use crate::{Entry, EntryKind, EntryLink, Error, Version};
4
5pub struct Tree<V: Version> {
17 stored: HashMap<u32, Entry<V>>,
18
19 generated: Vec<Entry<V>>,
21
22 stored_count: u32,
24
25 root: EntryLink,
26}
27
28impl<V: Version> Tree<V> {
29 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 #[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 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 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 (r#gen, (idx, node)) in peaks.into_iter().enumerate() {
95 result.stored.insert(idx, node);
96 if r#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 pub(crate) fn get_peaks(
119 &self,
120 root: EntryLink,
121 target: &mut Vec<EntryLink>,
122 ) -> Result<(), Error> {
123 let (left_child_link, right_child_link) = {
124 let root = self.resolve_link(root)?;
125 if root.node.complete() {
126 target.push(root.link);
127 return Ok(());
128 }
129 (root.left()?, root.right()?)
130 };
131
132 self.get_peaks(left_child_link, target)?;
133 self.get_peaks(right_child_link, target)?;
134 Ok(())
135 }
136
137 pub fn append_leaf(&mut self, new_leaf: V::NodeData) -> Result<Vec<EntryLink>, Error> {
143 let root = self.root;
144 let new_leaf_link = self.push(Entry::new_leaf(new_leaf));
145 let mut appended = vec![new_leaf_link];
146
147 let mut peaks = Vec::new();
148 self.get_peaks(root, &mut peaks)?;
149
150 let mut merge_stack = vec![new_leaf_link];
151
152 while let Some(next_peak) = peaks.pop() {
156 let next_merge = merge_stack
157 .pop()
158 .expect("there should be at least one, initial or re-pushed");
159
160 if let Some(stored) = {
161 let peak = self.resolve_link(next_peak)?;
162 let m = self.resolve_link(next_merge)?;
163 if peak.node.leaf_count() == m.node.leaf_count() {
164 Some(combine_nodes(peak, m))
165 } else {
166 None
167 }
168 } {
169 let link = self.push(stored);
170 merge_stack.push(link);
171 appended.push(link);
172 continue;
173 } else {
174 merge_stack.push(next_merge);
175 merge_stack.push(next_peak);
176 }
177 }
178
179 let mut new_root = merge_stack
180 .pop()
181 .expect("Loop above cannot reduce the merge_stack");
182 while let Some(next_child) = merge_stack.pop() {
185 new_root = self.push_generated(combine_nodes(
186 self.resolve_link(new_root)?,
187 self.resolve_link(next_child)?,
188 ))
189 }
190
191 self.root = new_root;
192
193 Ok(appended)
194 }
195
196 #[cfg(test)]
197 fn for_children<F: Fn(EntryLink, EntryLink)>(&self, node: EntryLink, f: F) {
198 let (left, right) = {
199 let link = self
200 .resolve_link(node)
201 .expect("Failed to resolve link in test");
202 (
203 link.left().expect("Failed to find node in test"),
204 link.right().expect("Failed to find node in test"),
205 )
206 };
207 f(left, right);
208 }
209
210 fn pop(&mut self) {
211 self.stored.remove(&(self.stored_count - 1));
212 self.stored_count -= 1;
213 }
214
215 pub fn truncate_leaf(&mut self) -> Result<u32, Error> {
220 let root = {
221 let (leaves, root_left_child) = {
222 let n = self.resolve_link(self.root)?;
223 (n.node.leaf_count(), n.node.left()?)
224 };
225 if leaves & 1 != 0 {
226 self.pop();
227 self.root = root_left_child;
228 return Ok(1);
229 } else {
230 self.resolve_link(self.root)?
231 }
232 };
233
234 let mut peaks = vec![root.left()?];
235 let mut subtree_root_link = root.right()?;
236 let mut truncated = 1;
237
238 loop {
239 let left_link = self.resolve_link(subtree_root_link)?.node;
240 if let EntryKind::Node(left, right) = left_link.kind {
241 peaks.push(left);
242 subtree_root_link = right;
243 truncated += 1;
244 } else {
245 if root.node.complete() {
246 truncated += 1;
247 }
248 break;
249 }
250 }
251
252 let mut new_root = *peaks.first().expect("At lest 1 elements in peaks");
253
254 for next_peak in peaks.into_iter().skip(1) {
255 new_root = self.push_generated(combine_nodes(
256 self.resolve_link(new_root)?,
257 self.resolve_link(next_peak)?,
258 ));
259 }
260
261 for _ in 0..truncated {
262 self.pop();
263 }
264
265 self.root = new_root;
266
267 Ok(truncated)
268 }
269
270 pub fn len(&self) -> u32 {
272 self.stored_count
273 }
274
275 pub fn root(&self) -> EntryLink {
277 self.root
278 }
279
280 pub fn root_node(&self) -> Result<IndexedNode<'_, V>, Error> {
282 self.resolve_link(self.root)
283 }
284
285 pub fn is_empty(&self) -> bool {
287 self.stored_count == 0
288 }
289}
290
291#[derive(Debug)]
293pub struct IndexedNode<'a, V: Version> {
294 node: &'a Entry<V>,
295 link: EntryLink,
296}
297
298impl<V: Version> IndexedNode<'_, V> {
299 fn left(&self) -> Result<EntryLink, Error> {
300 self.node.left().map_err(|e| e.augment(self.link))
301 }
302
303 fn right(&self) -> Result<EntryLink, Error> {
304 self.node.right().map_err(|e| e.augment(self.link))
305 }
306
307 pub fn node(&self) -> &Entry<V> {
309 self.node
310 }
311
312 pub fn data(&self) -> &V::NodeData {
314 &self.node.data
315 }
316
317 pub fn link(&self) -> EntryLink {
319 self.link
320 }
321}
322
323fn combine_nodes<'a, V: Version>(left: IndexedNode<'a, V>, right: IndexedNode<'a, V>) -> Entry<V> {
324 Entry {
325 kind: EntryKind::Node(left.link, right.link),
326 data: V::combine(&left.node.data, &right.node.data),
327 }
328}
329
330#[cfg(test)]
331mod tests {
332 use super::{Entry, EntryKind, EntryLink, Tree};
333 use crate::{NodeData, NodeDataV2, NodeDataV3, V2, V3, Version};
334
335 use assert_matches::assert_matches;
336 use proptest::prelude::*;
337
338 fn leaf(height: u32) -> NodeDataV2 {
339 NodeDataV2 {
340 v1: NodeData {
341 consensus_branch_id: 1,
342 subtree_commitment: [0u8; 32],
343 start_time: 0,
344 end_time: 0,
345 start_target: 0,
346 end_target: 0,
347 start_sapling_root: [0u8; 32],
348 end_sapling_root: [0u8; 32],
349 subtree_total_work: 0.into(),
350 start_height: height as u64,
351 end_height: height as u64,
352 sapling_tx: 7,
353 },
354 start_orchard_root: [0u8; 32],
355 end_orchard_root: [0u8; 32],
356 orchard_tx: 42,
357 }
358 }
359
360 fn ironwood_leaf(height: u32) -> NodeDataV3 {
361 NodeDataV3 {
362 v2: leaf(height),
363 start_ironwood_root: [height as u8; 32],
364 end_ironwood_root: [height as u8; 32],
365 ironwood_tx: u64::from(height),
366 }
367 }
368
369 fn initial() -> Tree<V2> {
370 let node1 = Entry::new_leaf(leaf(1));
371 let node2 = Entry::new_leaf(leaf(2));
372
373 let node3 = Entry {
374 data: V2::combine(&node1.data, &node2.data),
375 kind: EntryKind::Leaf,
376 };
377
378 Tree::populate(vec![node1, node2, node3], EntryLink::Stored(2))
379 }
380
381 fn generated(length: u32) -> Tree<V2> {
383 assert!(length >= 3);
384 let mut tree = initial();
385 for i in 2..length {
386 tree.append_leaf(leaf(i + 1)).expect("Failed to append");
387 }
388
389 tree
390 }
391
392 fn ironwood_initial() -> Tree<V3> {
393 let node1 = Entry::new_leaf(ironwood_leaf(1));
394 let node2 = Entry::new_leaf(ironwood_leaf(2));
395
396 let node3 = Entry {
397 data: V3::combine(&node1.data, &node2.data),
398 kind: EntryKind::Leaf,
399 };
400
401 Tree::populate(vec![node1, node2, node3], EntryLink::Stored(2))
402 }
403
404 #[test]
405 fn discrete_append() {
406 let mut tree = initial();
407
408 let appended = tree.append_leaf(leaf(3)).expect("Failed to append");
410 let new_root = tree.root_node().expect("Failed to resolve root").node;
411
412 assert_eq!(new_root.data.v1.end_height, 3);
426 assert_eq!(appended.len(), 1);
427
428 let appended = tree.append_leaf(leaf(4)).expect("Failed to append");
430
431 let new_root = tree.root_node().expect("Failed to resolve root").node;
432
433 assert_eq!(new_root.data.v1.end_height, 4);
450 assert_eq!(appended.len(), 3);
451 assert_matches!(tree.root(), EntryLink::Stored(6));
452
453 let appended = tree.append_leaf(leaf(5)).expect("Failed to append");
456 let new_root = tree.root_node().expect("Failed to resolve root").node;
457
458 assert_eq!(new_root.data.v1.end_height, 5);
477 assert_eq!(appended.len(), 1);
478 assert_matches!(tree.root(), EntryLink::Generated(_));
479 tree.for_children(tree.root(), |l, r| {
480 assert_matches!(l, EntryLink::Stored(6));
481 assert_matches!(r, EntryLink::Stored(7));
482 });
483
484 let appended = tree.append_leaf(leaf(6)).expect("Failed to append");
486 let new_root = tree.root_node().expect("Failed to resolve root").node;
487
488 assert_eq!(new_root.data.v1.end_height, 6);
509 assert_eq!(appended.len(), 2);
510 assert_matches!(tree.root(), EntryLink::Generated(_));
511 tree.for_children(tree.root(), |l, r| {
512 assert_matches!(l, EntryLink::Stored(6));
513 assert_matches!(r, EntryLink::Stored(9));
514 });
515
516 let appended = tree.append_leaf(leaf(7)).expect("Failed to append");
519 let new_root = tree.root_node().expect("Failed to resolve root").node;
520
521 assert_eq!(new_root.data.v1.end_height, 7);
544 assert_eq!(appended.len(), 1);
545 assert_matches!(tree.root(), EntryLink::Generated(_));
546 tree.for_children(tree.root(), |l, r| {
547 assert_matches!(l, EntryLink::Generated(_));
548 tree.for_children(l, |l, r| {
549 assert_matches!((l, r), (EntryLink::Stored(6), EntryLink::Stored(9)))
550 });
551 assert_matches!(r, EntryLink::Stored(10));
552 });
553 }
554
555 #[test]
556 fn truncate_simple() {
557 let mut tree = generated(9);
558 let total_truncated = tree.truncate_leaf().expect("Failed to truncate");
559
560 assert_matches!(tree.root(), EntryLink::Stored(14));
585 assert_eq!(total_truncated, 1);
586 assert_eq!(tree.len(), 15);
587 }
588
589 #[test]
590 fn truncate_generated() {
591 let mut tree = generated(10);
592 let deleted = tree.truncate_leaf().expect("Failed to truncate");
593
594 assert_matches!(tree.root(), EntryLink::Generated(_));
620
621 tree.for_children(tree.root(), |left, right| {
622 assert_matches!(
623 (left, right),
624 (EntryLink::Stored(14), EntryLink::Stored(15))
625 )
626 });
627
628 assert_eq!(deleted, 2);
630 assert_eq!(tree.len(), 16);
631 }
632
633 #[test]
634 fn ironwood_version_append_and_truncate() {
635 let mut tree = ironwood_initial();
636
637 let appended = tree
638 .append_leaf(ironwood_leaf(3))
639 .expect("Failed to append");
640 let root = tree.root_node().expect("Failed to resolve root").node;
641
642 assert_eq!(appended.len(), 1);
643 assert_eq!(root.data.v2.v1.start_height, 1);
644 assert_eq!(root.data.v2.v1.end_height, 3);
645 assert_eq!(root.data.start_ironwood_root, [1; 32]);
646 assert_eq!(root.data.end_ironwood_root, [3; 32]);
647 assert_eq!(root.data.ironwood_tx, 6);
648
649 let truncated = tree.truncate_leaf().expect("Failed to truncate");
650 let root = tree.root_node().expect("Failed to resolve root").node;
651
652 assert_eq!(truncated, 1);
653 assert_eq!(root.data.v2.v1.start_height, 1);
654 assert_eq!(root.data.v2.v1.end_height, 2);
655 assert_eq!(root.data.start_ironwood_root, [1; 32]);
656 assert_eq!(root.data.end_ironwood_root, [2; 32]);
657 assert_eq!(root.data.ironwood_tx, 3);
658 }
659
660 #[test]
661 fn tree_len() {
662 let mut tree = initial();
663
664 assert_eq!(tree.len(), 3);
665
666 for i in 0..2 {
667 tree.append_leaf(leaf(i + 3)).expect("Failed to append");
668 }
669 assert_eq!(tree.len(), 7);
670
671 tree.truncate_leaf().expect("Failed to truncate");
672
673 assert_eq!(tree.len(), 4);
674 }
675
676 #[test]
677 fn tree_len_long() {
678 let mut tree = initial();
679
680 assert_eq!(tree.len(), 3);
681
682 for i in 0..4094 {
683 tree.append_leaf(leaf(i + 3)).expect("Failed to append");
684 }
685 assert_eq!(tree.len(), 8191); for _ in 0..2049 {
688 tree.truncate_leaf().expect("Failed to truncate");
689 }
690
691 assert_eq!(tree.len(), 4083); }
693
694 proptest! {
695 #[test]
696 fn prop_there_and_back(number in 0u32..=1024) {
697 let mut tree = initial();
698 for i in 0..number {
699 tree.append_leaf(leaf(i+3)).expect("Failed to append");
700 }
701 for _ in 0..number {
702 tree.truncate_leaf().expect("Failed to truncate");
703 }
704
705 assert_matches!(tree.root(), EntryLink::Stored(2));
706 }
707
708 #[test]
709 fn prop_leaf_count(number in 3u32..=1024) {
710 let mut tree = initial();
711 for i in 1..(number-1) {
712 tree.append_leaf(leaf(i+2)).expect("Failed to append");
713 }
714
715 assert_eq!(tree.root_node().expect("no root").node.leaf_count(), number as u64);
716 }
717
718 #[test]
719 fn prop_parity(number in 3u32..=2048) {
720 let mut tree = initial();
721 for i in 1..(number-1) {
722 tree.append_leaf(leaf(i+2)).expect("Failed to append");
723 }
724
725 if number & (number - 1) == 0 {
726 assert_matches!(tree.root(), EntryLink::Stored(_));
727 } else {
728 assert_matches!(tree.root(), EntryLink::Generated(_));
729 }
730 }
731
732 #[test]
733 fn prop_parity_with_truncate(
734 add_and_delete in (0u32..=2048).prop_flat_map(
735 |add| (Just(add), 0..=add)
736 )
737 ) {
738 let (add, delete) = add_and_delete;
739 let mut tree = initial();
742 for i in 0..add {
743 tree.append_leaf(leaf(i+3)).expect("Failed to append");
744 }
745 for _ in 0..delete {
746 tree.truncate_leaf().expect("Failed to truncate");
747 }
748
749 let total = add - delete + 2;
750
751 if total & (total - 1) == 0 {
752 assert_matches!(tree.root(), EntryLink::Stored(_));
753 } else {
754 assert_matches!(tree.root(), EntryLink::Generated(_));
755 }
756 }
757
758 #[test]
759 fn prop_stored_length(
760 add_and_delete in (0u32..=2048).prop_flat_map(
761 |add| (Just(add), 0..=add)
762 )
763 ) {
764 let (add, delete) = add_and_delete;
765 let mut tree = initial();
766 for i in 0..add {
767 tree.append_leaf(leaf(i+3)).expect("Failed to append");
768 }
769 for _ in 0..delete {
770 tree.truncate_leaf().expect("Failed to truncate");
771 }
772
773 let total = add - delete + 2;
774
775 assert!(total * total > tree.len())
776 }
777 }
778}