diff --git a/src/dynamic_merkle_tree.rs b/src/dynamic_merkle_tree.rs index ed82956..2151437 100644 --- a/src/dynamic_merkle_tree.rs +++ b/src/dynamic_merkle_tree.rs @@ -12,6 +12,17 @@ use mmap_rs::{MmapMut, MmapOptions}; use rayon::prelude::*; /// A dynamically growable array represented merkle tree. +/// The left most branch of the tree consists of progressively increasing powers +/// of two. The right child of each power of two looks like a traditionally +/// indexed binary tree offset by its parent. +/// +/// The underlying storage is a 1-indexed dynamically growable array that is +/// always a power of two in length. The tree is built succesively from the +/// bottom left to the top right. +/// +/// The zeroth index of the underlying storage is used to store the number of +/// leaves in the tree. Because of this, the Hash used must be able to be cast +/// as a usize. If this is not possible, the code will panic at runtime. /// /// ```markdown /// 8 @@ -50,7 +61,7 @@ impl> DynamicMerkleTree { empty_value: &H::Hash, leaves: &[H::Hash], ) -> DynamicMerkleTree { - assert!(depth > 0); + assert!(depth > 0, "Tree depth must be greater than 0"); let storage = Self::storage_from_leaves(config, empty_value, leaves); let sparse_column = Self::sparse_column(depth, empty_value); @@ -742,8 +753,8 @@ mod tests { } } - fn debug_tree + std::fmt::Debug>( - tree: &DynamicMerkleTree, + fn debug_tree + std::fmt::Debug>( + tree: &DynamicMerkleTree, ) { println!("{tree:?}"); let storage_depth = tree.storage.len().ilog2(); @@ -886,6 +897,21 @@ mod tests { println!("Siblings: {:?}", children); } + #[should_panic] + #[test] + fn test_hash_too_small() { + #[derive(Debug, Clone, PartialEq, Eq)] + struct InvalidHasher; + impl Hasher for InvalidHasher { + type Hash = u32; + + fn hash_node(left: &Self::Hash, right: &Self::Hash) -> Self::Hash { + left + right + } + } + let _ = DynamicMerkleTree::::new_with_leaves((), 1, &0, &[]); + } + #[test] fn test_min_sized_tree() { let num_leaves = 1; @@ -1083,6 +1109,7 @@ mod tests { for (leaf, expected_proof) in expected { let proof = tree.proof_from_hash(leaf).unwrap(); assert_eq!(proof.0, expected_proof); + assert!(tree.verify(leaf, &proof)); } }