1#![no_std]
2#![cfg_attr(not(test), deny(missing_docs))]
3
4extern crate alloc;
27
28use alloc::boxed::Box;
29use alloc::vec::Vec;
30use core::cmp::{Ordering, min};
31use core::hash::{Hash, Hasher};
32use sha2::digest::Output;
33use sha2::{Digest, Sha256};
34
35pub type Sha256Hash = Output<Sha256>;
37
38type HashOf<H> = Output<H>;
39
40type Link<T, H, P> = Option<Box<Node<T, H, P>>>;
41
42pub trait Priority: Copy + Ord + Default {
44 fn from_digest_bytes(bytes: &[u8]) -> Self;
46}
47
48macro_rules! impl_priority_from_bytes {
49 ($($ty:ty),+) => {
50 $(
51 impl Priority for $ty {
52 #[inline(always)]
53 fn from_digest_bytes(bytes: &[u8]) -> Self {
54 let mut out = [0u8; core::mem::size_of::<$ty>()];
55 let copy_len = bytes.len().min(out.len());
56 out[..copy_len].copy_from_slice(&bytes[..copy_len]);
57 <$ty>::from_be_bytes(out)
58 }
59 }
60 )+
61 };
62}
63
64impl_priority_from_bytes!(u16, u32, u64, u128);
65
66struct Node<T, H, P>
67where
68 T: Clone + Ord + Hash,
69 H: Digest + Clone,
70 P: Priority,
71{
72 key: T,
73 key_digest: HashOf<H>,
74 priority: P,
75 hash: HashOf<H>,
76 left: Link<T, H, P>,
77 right: Link<T, H, P>,
78}
79
80impl<T, H, P> Node<T, H, P>
81where
82 T: Clone + Ord + Hash,
83 H: Digest + Clone,
84 P: Priority,
85{
86 #[inline(always)]
87 fn new(key: T) -> Self {
88 let key_digest = hash_key::<T, H>(&key);
89 let priority = P::from_digest_bytes(key_digest.as_ref());
90 let zero = zero_hash::<H>();
91 let hash = calculate_node_hash::<H>(&key_digest, &zero, &zero);
92 Self {
93 key,
94 key_digest,
95 priority,
96 hash,
97 left: None,
98 right: None,
99 }
100 }
101
102 #[inline(always)]
103 fn left_hash(&self) -> HashOf<H> {
104 self.left
105 .as_ref()
106 .map(|child| child.hash.clone())
107 .unwrap_or_else(|| zero_hash::<H>())
108 }
109
110 #[inline(always)]
111 fn right_hash(&self) -> HashOf<H> {
112 self.right
113 .as_ref()
114 .map(|child| child.hash.clone())
115 .unwrap_or_else(|| zero_hash::<H>())
116 }
117
118 #[inline(always)]
119 fn left_priority(&self) -> P {
120 self.left
121 .as_ref()
122 .map(|child| child.priority)
123 .unwrap_or_default()
124 }
125
126 #[inline(always)]
127 fn right_priority(&self) -> P {
128 self.right
129 .as_ref()
130 .map(|child| child.priority)
131 .unwrap_or_default()
132 }
133
134 #[inline(always)]
135 fn key_digest(&self) -> &HashOf<H> {
136 &self.key_digest
137 }
138
139 #[inline(always)]
140 fn update_hash(&mut self) {
141 let left = self.left_hash();
142 let right = self.right_hash();
143 self.hash = calculate_node_hash::<H>(self.key_digest(), &left, &right);
144 }
145}
146
147pub struct CMTree<T, H = Sha256, P = u128>
185where
186 T: Clone + Ord + Hash,
187 H: Digest + Clone,
188 P: Priority,
189{
190 root: Link<T, H, P>,
191 size: usize,
192}
193
194impl<T, H, P> CMTree<T, H, P>
195where
196 T: Clone + Ord + Hash,
197 H: Digest + Clone,
198 P: Priority,
199{
200 #[inline(always)]
202 pub const fn new() -> Self {
203 Self {
204 root: None,
205 size: 0,
206 }
207 }
208
209 #[inline(always)]
211 pub const fn len(&self) -> usize {
212 self.size
213 }
214
215 #[inline(always)]
217 pub const fn is_empty(&self) -> bool {
218 self.size == 0
219 }
220
221 #[inline(always)]
225 pub fn root_hash(&self) -> HashOf<H> {
226 self.root
227 .as_ref()
228 .map(|node| node.hash.clone())
229 .unwrap_or_else(|| zero_hash::<H>())
230 }
231
232 #[inline]
236 pub fn insert(&mut self, key: T) -> bool {
237 let (new_root, inserted) = Self::insert_node(self.root.take(), key);
238 self.root = new_root;
239 if inserted {
240 self.size += 1;
241 }
242 inserted
243 }
244
245 #[inline]
247 pub fn contains(&self, key: &T) -> bool {
248 let mut current = self.root.as_deref();
249 while let Some(node) = current {
250 match key.cmp(&node.key) {
251 Ordering::Less => current = node.left.as_deref(),
252 Ordering::Greater => current = node.right.as_deref(),
253 Ordering::Equal => return true,
254 }
255 }
256 false
257 }
258
259 #[inline]
263 pub fn remove(&mut self, key: &T) -> bool {
264 let (new_root, removed) = Self::remove_node(self.root.take(), key);
265 if removed {
266 self.size -= 1;
267 }
268 self.root = new_root;
269 removed
270 }
271
272 #[inline]
278 pub fn generate_proof(&self, key: &T) -> Option<Proof<H>> {
279 let mut current = self.root.as_deref()?;
280 let mut path: Vec<(&Node<T, H, P>, Direction)> = Vec::new();
281 let mut existence = false;
282 let mut non_existence_key_digest: Option<HashOf<H>> = None;
283
284 let suffix = loop {
285 match key.cmp(¤t.key) {
286 Ordering::Less => {
287 if let Some(left_child) = current.left.as_deref() {
288 path.push((current, Direction::Left));
289 current = left_child;
290 } else {
291 non_existence_key_digest = Some(current.key_digest().clone());
292 break [current.left_hash(), current.right_hash()];
293 }
294 }
295 Ordering::Greater => {
296 if let Some(right_child) = current.right.as_deref() {
297 path.push((current, Direction::Right));
298 current = right_child;
299 } else {
300 non_existence_key_digest = Some(current.key_digest().clone());
301 break [current.left_hash(), current.right_hash()];
302 }
303 }
304 Ordering::Equal => {
305 existence = true;
306 break [current.left_hash(), current.right_hash()];
307 }
308 }
309 };
310
311 let mut prefix = Vec::with_capacity(path.len());
312 for (node, direction) in path.into_iter().rev() {
313 let sibling_hash = match direction {
314 Direction::Left => node.right_hash(),
315 Direction::Right => node.left_hash(),
316 };
317 prefix.push(ProofNode {
318 parent_key_digest: node.key_digest().clone(),
319 sibling_hash,
320 });
321 }
322
323 Some(Proof {
324 prefix,
325 suffix,
326 existence,
327 non_existence_key_digest,
328 })
329 }
330
331 #[inline]
332 fn insert_node(node: Link<T, H, P>, key: T) -> (Link<T, H, P>, bool) {
333 match node {
334 None => (Some(Box::new(Node::new(key))), true),
335 Some(mut boxed) => match key.cmp(&boxed.key) {
336 Ordering::Less => {
337 let (new_left, inserted) = Self::insert_node(boxed.left.take(), key);
338 boxed.left = new_left;
339 if inserted
340 && boxed
341 .left
342 .as_ref()
343 .is_some_and(|left| left.priority > boxed.priority)
344 {
345 boxed = Self::rotate_right_owned(boxed);
346 return (Some(boxed), true);
347 }
348 boxed.update_hash();
349 (Some(boxed), inserted)
350 }
351 Ordering::Greater => {
352 let (new_right, inserted) = Self::insert_node(boxed.right.take(), key);
353 boxed.right = new_right;
354 if inserted
355 && boxed
356 .right
357 .as_ref()
358 .is_some_and(|right| right.priority > boxed.priority)
359 {
360 boxed = Self::rotate_left_owned(boxed);
361 return (Some(boxed), true);
362 }
363 boxed.update_hash();
364 (Some(boxed), inserted)
365 }
366 Ordering::Equal => (Some(boxed), false),
367 },
368 }
369 }
370
371 #[inline]
372 fn remove_node(node: Link<T, H, P>, key: &T) -> (Link<T, H, P>, bool) {
373 let mut boxed = match node {
374 Some(node) => node,
375 None => return (None, false),
376 };
377
378 match key.cmp(&boxed.key) {
379 Ordering::Less => {
380 let (new_left, removed) = Self::remove_node(boxed.left.take(), key);
381 boxed.left = new_left;
382 if removed {
383 boxed.update_hash();
384 }
385 (Some(boxed), removed)
386 }
387 Ordering::Greater => {
388 let (new_right, removed) = Self::remove_node(boxed.right.take(), key);
389 boxed.right = new_right;
390 if removed {
391 boxed.update_hash();
392 }
393 (Some(boxed), removed)
394 }
395 Ordering::Equal => {
396 if boxed.left.is_none() {
397 return (boxed.right.take(), true);
398 }
399 if boxed.right.is_none() {
400 return (boxed.left.take(), true);
401 }
402 if boxed.left_priority() > boxed.right_priority() {
403 boxed = Self::rotate_right_owned(boxed);
404 let (new_right, removed) = Self::remove_node(boxed.right.take(), key);
405 boxed.right = new_right;
406 boxed.update_hash();
407 (Some(boxed), removed)
408 } else {
409 boxed = Self::rotate_left_owned(boxed);
410 let (new_left, removed) = Self::remove_node(boxed.left.take(), key);
411 boxed.left = new_left;
412 boxed.update_hash();
413 (Some(boxed), removed)
414 }
415 }
416 }
417 }
418
419 #[inline]
420 fn rotate_left_owned(mut node: Box<Node<T, H, P>>) -> Box<Node<T, H, P>> {
421 let mut right = node
422 .right
423 .take()
424 .expect("rotate_left_owned requires a right child");
425 node.right = right.left.take();
426 node.update_hash();
427 right.left = Some(node);
428 right.update_hash();
429 right
430 }
431
432 #[inline]
433 fn rotate_right_owned(mut node: Box<Node<T, H, P>>) -> Box<Node<T, H, P>> {
434 let mut left = node
435 .left
436 .take()
437 .expect("rotate_right_owned requires a left child");
438 node.left = left.right.take();
439 node.update_hash();
440 left.right = Some(node);
441 left.update_hash();
442 left
443 }
444}
445
446impl<T, H, P> Default for CMTree<T, H, P>
447where
448 T: Clone + Ord + Hash,
449 H: Digest + Clone,
450 P: Priority,
451{
452 #[inline]
453 fn default() -> Self {
454 Self::new()
455 }
456}
457
458#[derive(Clone, Debug, PartialEq, Eq)]
460pub struct ProofNode<H>
461where
462 H: Digest + Clone,
463{
464 pub parent_key_digest: HashOf<H>,
466 pub sibling_hash: HashOf<H>,
468}
469
470#[derive(Clone, Debug, PartialEq, Eq)]
472pub struct Proof<H>
473where
474 H: Digest + Clone,
475{
476 pub prefix: Vec<ProofNode<H>>,
478 pub suffix: [HashOf<H>; 2],
480 pub existence: bool,
483 pub non_existence_key_digest: Option<HashOf<H>>,
485}
486
487impl<H> Proof<H>
488where
489 H: Digest + Clone,
490{
491 #[inline(always)]
512 pub fn verify<K>(&self, key: &K, expected_root: &HashOf<H>) -> bool
513 where
514 K: Hash,
515 {
516 let key_digest = hash_key::<K, H>(key);
517 self.verify_digest(&key_digest, expected_root)
518 }
519
520 #[inline(always)]
521 fn verify_digest(&self, key_digest: &HashOf<H>, expected_root: &HashOf<H>) -> bool {
522 let base_key = if self.existence {
523 key_digest
524 } else {
525 match self.non_existence_key_digest.as_ref() {
526 Some(d) => d,
527 None => return false,
528 }
529 };
530
531 let mut acc = calculate_node_hash::<H>(base_key, &self.suffix[0], &self.suffix[1]);
532 for node in &self.prefix {
533 acc = calculate_node_hash::<H>(&node.parent_key_digest, &acc, &node.sibling_hash);
534 }
535
536 &acc == expected_root
537 }
538}
539
540enum Direction {
541 Left,
542 Right,
543}
544
545struct DigestHasher<H>
546where
547 H: Digest + Clone,
548{
549 digest: H,
550}
551
552impl<H> DigestHasher<H>
553where
554 H: Digest + Clone,
555{
556 #[inline(always)]
557 fn new() -> Self {
558 Self { digest: H::new() }
559 }
560
561 #[inline(always)]
562 fn finalize(self) -> HashOf<H> {
563 self.digest.finalize()
564 }
565}
566
567impl<H> Hasher for DigestHasher<H>
568where
569 H: Digest + Clone,
570{
571 #[inline(always)]
572 fn finish(&self) -> u64 {
573 let output = self.digest.clone().finalize();
574 let bytes = output.as_ref();
575 let mut buf = [0u8; 8];
576 let copy_len = min(buf.len(), bytes.len());
577 buf[..copy_len].copy_from_slice(&bytes[..copy_len]);
578 u64::from_be_bytes(buf)
579 }
580
581 #[inline(always)]
582 fn write(&mut self, bytes: &[u8]) {
583 self.digest.update(bytes);
584 }
585}
586
587#[inline(always)]
588fn hash_key<T, H>(key: &T) -> HashOf<H>
589where
590 T: Hash,
591 H: Digest + Clone,
592{
593 let mut hasher = DigestHasher::<H>::new();
594 key.hash(&mut hasher);
595 hasher.finalize()
596}
597
598#[inline(always)]
599fn zero_hash<H: Digest>() -> HashOf<H> {
600 Output::<H>::default()
601}
602
603#[inline(always)]
604fn calculate_node_hash<H: Digest>(
605 key_digest: &HashOf<H>,
606 left: &HashOf<H>,
607 right: &HashOf<H>,
608) -> HashOf<H> {
609 let (low, high) = if left.as_ref() <= right.as_ref() {
610 (left, right)
611 } else {
612 (right, left)
613 };
614
615 let mut hasher = H::new();
616 hasher.update(key_digest.as_ref());
617 hasher.update(low.as_ref());
618 hasher.update(high.as_ref());
619 hasher.finalize()
620}
621
622#[cfg(test)]
623mod tests {
624 use super::*;
625 extern crate std;
626
627 fn key(bytes: &[u8]) -> Vec<u8> {
628 bytes.to_vec()
629 }
630
631 #[test]
632 fn insert_and_contains() {
633 let mut tree = CMTree::<Vec<u8>>::new();
634 let k10 = key(b"10");
635 let k5 = key(b"5");
636 let k20 = key(b"20");
637
638 assert!(tree.insert(k10.clone()));
639 assert!(tree.insert(k5.clone()));
640 assert!(tree.insert(k20.clone()));
641 assert!(!tree.insert(k5.clone()));
642
643 assert!(tree.contains(&k10));
644 assert!(tree.contains(&k5));
645 assert!(tree.contains(&k20));
646 assert!(!tree.contains(&key(b"1")));
647 }
648
649 #[test]
650 fn remove_keys() {
651 let mut tree = CMTree::<Vec<u8>>::new();
652 let k10 = key(b"10");
653 let k5 = key(b"5");
654 let k20 = key(b"20");
655 let k18 = key(b"18");
656 let k25 = key(b"25");
657
658 for k in [&k10, &k5, &k20, &k18, &k25] {
659 assert!(tree.insert((*k).clone()));
660 }
661 assert_eq!(tree.len(), 5);
662 assert!(tree.remove(&k20));
663 assert_eq!(tree.len(), 4);
664 assert!(!tree.contains(&k20));
665 assert!(tree.remove(&k10));
666 assert_eq!(tree.len(), 3);
667 }
668
669 #[test]
670 fn membership_proof_verifies() {
671 let mut tree = CMTree::<Vec<u8>>::new();
672 let keys = ["10", "5", "20", "18", "25"];
673 for k in keys {
674 let key_vec = key(k.as_bytes());
675 tree.insert(key_vec.clone());
676 }
677 let root = tree.root_hash();
678 let target = key(b"18");
679 let proof = tree.generate_proof(&target).unwrap();
680 assert!(proof.existence);
681 assert!(proof.verify(&target, &root));
682 }
683
684 #[test]
685 fn non_membership_proof_verifies() {
686 let mut tree = CMTree::<Vec<u8>>::new();
687 let keys = ["10", "5", "20", "18", "25"];
688 for k in keys {
689 tree.insert(key(k.as_bytes()));
690 }
691 let root = tree.root_hash();
692 let missing = key(b"13");
693 let proof = tree.generate_proof(&missing).unwrap();
694 assert!(!proof.existence);
695 assert!(proof.verify(&missing, &root));
696 }
697
698 #[test]
699 fn empty_tree_has_zero_root_and_no_proof() {
700 let tree = CMTree::<Vec<u8>>::new();
701 assert_eq!(tree.root_hash(), zero_hash::<Sha256>());
702 assert!(tree.generate_proof(&key(b"nonexistent")).is_none());
703 }
704
705 #[test]
706 fn removing_missing_key_does_not_change_tree() {
707 let mut tree = CMTree::<Vec<u8>>::new();
708 for k in ["1", "2", "3", "4"] {
709 assert!(tree.insert(key(k.as_bytes())));
710 }
711 let len_before = tree.len();
712 assert!(!tree.remove(&key(b"999")));
713 assert_eq!(tree.len(), len_before);
714 }
715
716 #[test]
717 fn removing_root_keeps_structure_valid() {
718 let mut tree = CMTree::<Vec<u8>>::new();
719 let root_key = key(b"10");
720 let left_key = key(b"05");
721 let right_key = key(b"20");
722 for k in [&root_key, &left_key, &right_key] {
723 assert!(tree.insert((*k).clone()));
724 }
725 assert!(tree.remove(&root_key));
726 assert_eq!(tree.len(), 2);
727 assert!(!tree.contains(&root_key));
728 assert!(tree.contains(&left_key));
729 assert!(tree.contains(&right_key));
730 }
731
732 #[test]
733 fn duplicate_insertions_are_idempotent() {
734 let mut tree = CMTree::<Vec<u8>>::new();
735 let set = ["a", "b", "c", "d", "e"];
736 for k in set {
737 assert!(tree.insert(key(k.as_bytes())));
738 }
739 let root_after_first = tree.root_hash();
740 for k in set {
741 assert!(!tree.insert(key(k.as_bytes())));
742 }
743 assert_eq!(tree.len(), set.len());
744 assert_eq!(tree.root_hash(), root_after_first);
745 }
746
747 #[test]
748 fn deterministic_root_for_different_insertion_orders() {
749 let mut tree_a = CMTree::<Vec<u8>>::new();
750 let mut tree_b = CMTree::<Vec<u8>>::new();
751 let mut inputs: Vec<Vec<u8>> = ["alpha", "beta", "gamma", "delta", "epsilon"]
752 .iter()
753 .map(|s| key(s.as_bytes()))
754 .collect();
755 for k in &inputs {
756 tree_a.insert(k.clone());
757 }
758 inputs.reverse();
759 for k in &inputs {
760 tree_b.insert(k.clone());
761 }
762 assert_eq!(tree_a.len(), tree_b.len());
763 assert_eq!(tree_a.root_hash(), tree_b.root_hash());
764 }
765
766 #[test]
767 fn proofs_match_across_insertion_orders() {
768 let mut tree_a = CMTree::<Vec<u8>>::new();
769 let mut tree_b = CMTree::<Vec<u8>>::new();
770 let mut inputs: Vec<Vec<u8>> = ["alpha", "beta", "gamma", "delta", "epsilon"]
771 .iter()
772 .map(|s| key(s.as_bytes()))
773 .collect();
774 for k in &inputs {
775 tree_a.insert(k.clone());
776 }
777 inputs.reverse();
778 for k in &inputs {
779 tree_b.insert(k.clone());
780 }
781
782 let target = key(b"gamma");
783 let proof_a = tree_a.generate_proof(&target).expect("proof from order A");
784 let proof_b = tree_b.generate_proof(&target).expect("proof from order B");
785
786 let root = tree_a.root_hash();
787 assert!(proof_a.verify(&target, &root));
788 assert!(proof_b.verify(&target, &root));
789 assert_eq!(proof_a.prefix.len(), proof_b.prefix.len());
790 assert_eq!(proof_a.suffix, proof_b.suffix);
791 assert_eq!(proof_a.existence, proof_b.existence);
792 }
793
794 #[test]
795 fn membership_proof_rejects_when_flag_flipped() {
796 let mut tree = CMTree::<Vec<u8>>::new();
797 for k in ["left", "right", "root", "branch"] {
798 tree.insert(key(k.as_bytes()));
799 }
800 let root = tree.root_hash();
801 let target = key(b"branch");
802 let mut proof = tree.generate_proof(&target).unwrap();
803 proof.existence = false;
804 assert!(!proof.verify(&target, &root));
805 }
806
807 #[test]
808 fn membership_proof_rejects_with_wrong_root() {
809 let mut tree_a = CMTree::<Vec<u8>>::new();
810 let mut tree_b = CMTree::<Vec<u8>>::new();
811 for k in ["1", "2", "3", "4"] {
812 let vec_key = key(k.as_bytes());
813 tree_a.insert(vec_key.clone());
814 tree_b.insert(vec_key);
815 }
816 tree_b.insert(key(b"extra"));
817 let proof = tree_a.generate_proof(&key(b"3")).unwrap();
818 assert!(proof.verify(&key(b"3"), &tree_a.root_hash()));
819 assert!(!proof.verify(&key(b"3"), &tree_b.root_hash()));
820 }
821
822 #[test]
823 fn mutated_suffix_breaks_non_membership_proof() {
824 let mut tree = CMTree::<Vec<u8>>::new();
825 for k in ["10", "5", "20", "18", "25"] {
826 tree.insert(key(k.as_bytes()));
827 }
828 let root = tree.root_hash();
829 let mut proof = tree.generate_proof(&key(b"13")).unwrap();
830 assert!(!proof.existence);
831 proof.suffix[0] = zero_hash::<Sha256>();
832 proof.suffix[1] = zero_hash::<Sha256>();
833 proof.existence = true;
835 assert!(!proof.verify(&key(b"13"), &root));
836 }
837
838 #[test]
839 fn supports_integer_keys() {
840 let mut tree = CMTree::<u64>::new();
841 for k in [10, 5, 20, 18, 25] {
842 assert!(tree.insert(k));
843 }
844 assert!(tree.contains(&18u64));
845 assert!(!tree.contains(&13u64));
846 let root = tree.root_hash();
847 let proof = tree.generate_proof(&18u64).unwrap();
848 assert!(proof.existence);
849 assert!(proof.verify(&18u64, &root));
850 }
851
852 #[test]
853 fn large_tree_membership_and_non_membership_proofs() {
854 const COUNT: usize = 5_000;
855 let mut tree = CMTree::<u64>::new();
856 for value in 0u64..COUNT as u64 {
857 assert!(tree.insert(value));
858 }
859 assert_eq!(tree.len(), COUNT);
860
861 let target = 3_456u64;
862 let root = tree.root_hash();
863 let proof = tree.generate_proof(&target).expect("proof should exist");
864 assert!(proof.existence);
865 assert!(proof.verify(&target, &root));
866
867 let missing = COUNT as u64 + 1;
868 let root_again = tree.root_hash();
869 let non_membership = tree
870 .generate_proof(&missing)
871 .expect("proof should be generated");
872 assert!(!non_membership.existence);
873 assert!(non_membership.verify(&missing, &root_again));
874 }
875
876 #[test]
877 fn large_tree_sequential_removals() {
878 const COUNT: usize = 10_000;
879 let mut tree = CMTree::<u64>::new();
880 for value in 0u64..COUNT as u64 {
881 assert!(tree.insert(value));
882 }
883 for value in 0u64..COUNT as u64 {
884 assert!(tree.remove(&value));
885 }
886 assert!(tree.is_empty());
887 assert_eq!(tree.root_hash(), zero_hash::<Sha256>());
888 }
889
890 #[test]
891 fn supports_lower_priority_width() {
892 let mut tree = CMTree::<Vec<u8>, Sha256, u64>::new();
893 for key in ["10", "5", "20", "18", "25"] {
894 assert!(tree.insert(key.as_bytes().to_vec()));
895 }
896 let root = tree.root_hash();
897 let proof = tree.generate_proof(&b"18".to_vec()).unwrap();
898 assert!(proof.existence);
899 assert!(proof.verify(&b"18".to_vec(), &root));
900 }
901
902 #[test]
903 fn works_with_alternative_digest() {
904 use sha2::Sha512;
905
906 let mut tree = CMTree::<Vec<u8>, Sha512>::new();
907 for key in ["alpha", "beta", "gamma", "delta"] {
908 assert!(tree.insert(key.as_bytes().to_vec()));
909 }
910 assert!(tree.contains(&b"gamma".to_vec()));
911 let root = tree.root_hash();
912 let proof = tree.generate_proof(&b"beta".to_vec()).unwrap();
913 assert!(proof.existence);
914 assert!(proof.verify(&b"beta".to_vec(), &root));
915 }
916}