diff --git a/benches/store.rs b/benches/store.rs index b59a537..804faa6 100644 --- a/benches/store.rs +++ b/benches/store.rs @@ -18,9 +18,10 @@ fn random_word() -> Word { rand_array::().into() } -/// Generates a u64 in `0..range`. -fn random_index(range: u64) -> u64 { - rand_value::() % range +/// Generates an index at the specified depth in `0..range`. +fn random_index(range: u64, depth: u8) -> NodeIndex { + let value = rand_value::() % range; + NodeIndex::new(depth, value).unwrap() } /// Benchmarks getting an empty leaf from the SMT and MerkleStore backends. @@ -28,7 +29,7 @@ fn get_empty_leaf_simplesmt(c: &mut Criterion) { let mut group = c.benchmark_group("get_empty_leaf_simplesmt"); let depth = SimpleSmt::MAX_DEPTH; - let size = 2u64.pow(depth as u32); + let size = u64::MAX; // both SMT and the store are pre-populated with empty hashes, accessing these values is what is // being benchmarked here, so no values are inserted into the backends @@ -38,16 +39,16 @@ fn get_empty_leaf_simplesmt(c: &mut Criterion) { group.bench_function(BenchmarkId::new("SimpleSmt", depth), |b| { b.iter_batched( - || random_index(size), - |value| black_box(smt.get_node(&NodeIndex::new(depth, value))), + || random_index(size, depth), + |index| black_box(smt.get_node(index)), BatchSize::SmallInput, ) }); group.bench_function(BenchmarkId::new("MerkleStore", depth), |b| { b.iter_batched( - || random_index(size), - |value| black_box(store.get_node(root, NodeIndex::new(depth, value))), + || random_index(size, depth), + |index| black_box(store.get_node(root, index)), BatchSize::SmallInput, ) }); @@ -72,16 +73,16 @@ fn get_leaf_merkletree(c: &mut Criterion) { group.bench_function(BenchmarkId::new("MerkleTree", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(mtree.get_node(NodeIndex::new(depth, value))), + || random_index(size_u64, depth), + |index| black_box(mtree.get_node(index)), BatchSize::SmallInput, ) }); group.bench_function(BenchmarkId::new("MerkleStore", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(store.get_node(root, NodeIndex::new(depth, value))), + || random_index(size_u64, depth), + |index| black_box(store.get_node(root, index)), BatchSize::SmallInput, ) }); @@ -116,16 +117,16 @@ fn get_leaf_simplesmt(c: &mut Criterion) { group.bench_function(BenchmarkId::new("SimpleSmt", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(smt.get_node(&NodeIndex::new(depth, value))), + || random_index(size_u64, depth), + |index| black_box(smt.get_node(index)), BatchSize::SmallInput, ) }); group.bench_function(BenchmarkId::new("MerkleStore", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(store.get_node(root, NodeIndex::new(depth, value))), + || random_index(size_u64, depth), + |index| black_box(store.get_node(root, index)), BatchSize::SmallInput, ) }); @@ -137,7 +138,6 @@ fn get_node_of_empty_simplesmt(c: &mut Criterion) { let mut group = c.benchmark_group("get_node_of_empty_simplesmt"); let depth = SimpleSmt::MAX_DEPTH; - let size = 2u64.pow(depth as u32); // both SMT and the store are pre-populated with the empty hashes, accessing the internal nodes // of these values is what is being benchmarked here, so no values are inserted into the @@ -146,19 +146,20 @@ fn get_node_of_empty_simplesmt(c: &mut Criterion) { let store = MerkleStore::new(); let root = smt.root(); let half_depth = depth / 2; + let half_size = 2_u64.pow(half_depth as u32); group.bench_function(BenchmarkId::new("SimpleSmt", depth), |b| { b.iter_batched( - || random_index(size), - |value| black_box(smt.get_node(&NodeIndex::new(half_depth, value))), + || random_index(half_size, half_depth), + |index| black_box(smt.get_node(index)), BatchSize::SmallInput, ) }); group.bench_function(BenchmarkId::new("MerkleStore", depth), |b| { b.iter_batched( - || random_index(size), - |value| black_box(store.get_node(root, NodeIndex::new(half_depth, value))), + || random_index(half_size, half_depth), + |index| black_box(store.get_node(root, index)), BatchSize::SmallInput, ) }); @@ -178,22 +179,22 @@ fn get_node_merkletree(c: &mut Criterion) { let mtree_leaves: Vec = leaves.iter().map(|v| v.into()).collect(); let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap(); let store = MerkleStore::new().with_merkle_tree(mtree_leaves).unwrap(); - let half_depth = mtree.depth() / 2; let root = mtree.root(); - let size_u64 = size as u64; + let half_depth = mtree.depth() / 2; + let half_size = 2_u64.pow(half_depth as u32); group.bench_function(BenchmarkId::new("MerkleTree", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(mtree.get_node(NodeIndex::new(half_depth, value))), + || random_index(half_size, half_depth), + |index| black_box(mtree.get_node(index)), BatchSize::SmallInput, ) }); group.bench_function(BenchmarkId::new("MerkleStore", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(store.get_node(root, NodeIndex::new(half_depth, value))), + || random_index(half_size, half_depth), + |index| black_box(store.get_node(root, index)), BatchSize::SmallInput, ) }); @@ -224,21 +225,21 @@ fn get_node_simplesmt(c: &mut Criterion) { .with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves) .unwrap(); let root = smt.root(); - let size_u64 = size as u64; let half_depth = smt.depth() / 2; + let half_size = 2_u64.pow(half_depth as u32); group.bench_function(BenchmarkId::new("SimpleSmt", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(smt.get_node(&NodeIndex::new(half_depth, value))), + || random_index(half_size, half_depth), + |index| black_box(smt.get_node(index)), BatchSize::SmallInput, ) }); group.bench_function(BenchmarkId::new("MerkleStore", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(store.get_node(root, NodeIndex::new(half_depth, value))), + || random_index(half_size, half_depth), + |index| black_box(store.get_node(root, index)), BatchSize::SmallInput, ) }); @@ -264,16 +265,16 @@ fn get_leaf_path_merkletree(c: &mut Criterion) { group.bench_function(BenchmarkId::new("MerkleTree", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(mtree.get_path(NodeIndex::new(depth, value))), + || random_index(size_u64, depth), + |index| black_box(mtree.get_path(index)), BatchSize::SmallInput, ) }); group.bench_function(BenchmarkId::new("MerkleStore", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(store.get_path(root, NodeIndex::new(depth, value))), + || random_index(size_u64, depth), + |index| black_box(store.get_path(root, index)), BatchSize::SmallInput, ) }); @@ -308,16 +309,16 @@ fn get_leaf_path_simplesmt(c: &mut Criterion) { group.bench_function(BenchmarkId::new("SimpleSmt", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(smt.get_path(NodeIndex::new(depth, value))), + || random_index(size_u64, depth), + |index| black_box(smt.get_path(index)), BatchSize::SmallInput, ) }); group.bench_function(BenchmarkId::new("MerkleStore", size), |b| { b.iter_batched( - || random_index(size_u64), - |value| black_box(store.get_path(root, NodeIndex::new(depth, value))), + || random_index(size_u64, depth), + |index| black_box(store.get_path(root, index)), BatchSize::SmallInput, ) }); @@ -413,7 +414,7 @@ fn update_leaf_merkletree(c: &mut Criterion) { group.bench_function(BenchmarkId::new("MerkleTree", size), |b| { b.iter_batched( - || (random_index(size_u64), random_word()), + || (rand_value::() % size_u64, random_word()), |(index, value)| black_box(mtree.update_leaf(index, value)), BatchSize::SmallInput, ) @@ -422,15 +423,12 @@ fn update_leaf_merkletree(c: &mut Criterion) { let mut store_root = root; group.bench_function(BenchmarkId::new("MerkleStore", size), |b| { b.iter_batched( - || (random_index(size_u64), random_word()), + || (random_index(size_u64, depth), random_word()), |(index, value)| { // The MerkleTree automatically updates its internal root, the Store maintains // the old root and adds the new one. Here we update the root to have a fair // comparison - store_root = store - .set_node(root, NodeIndex::new(depth, index), value) - .unwrap() - .root; + store_root = store.set_node(root, index, value).unwrap().root; black_box(store_root) }, BatchSize::SmallInput, @@ -467,7 +465,7 @@ fn update_leaf_simplesmt(c: &mut Criterion) { group.bench_function(BenchmarkId::new("SimpleSMT", size), |b| { b.iter_batched( - || (random_index(size_u64), random_word()), + || (rand_value::() % size_u64, random_word()), |(index, value)| black_box(smt.update_leaf(index, value)), BatchSize::SmallInput, ) @@ -476,15 +474,12 @@ fn update_leaf_simplesmt(c: &mut Criterion) { let mut store_root = root; group.bench_function(BenchmarkId::new("MerkleStore", size), |b| { b.iter_batched( - || (random_index(size_u64), random_word()), + || (random_index(size_u64, depth), random_word()), |(index, value)| { // The MerkleTree automatically updates its internal root, the Store maintains // the old root and adds the new one. Here we update the root to have a fair // comparison - store_root = store - .set_node(root, NodeIndex::new(depth, index), value) - .unwrap() - .root; + store_root = store.set_node(root, index, value).unwrap().root; black_box(store_root) }, BatchSize::SmallInput, diff --git a/src/bit.rs b/src/bit.rs deleted file mode 100644 index 5eb2577..0000000 --- a/src/bit.rs +++ /dev/null @@ -1,169 +0,0 @@ -/// Yields the bits of a `u64`. -pub struct BitIterator { - /// The value that is being iterated bit-wise - value: u64, - /// True bits in the `mask` are the bits that have been visited. - mask: u64, -} - -impl BitIterator { - pub fn new(value: u64) -> BitIterator { - BitIterator { value, mask: 0 } - } - - /// An efficient skip implementation. - /// - /// Note: The compiler is smart enough to translate a `skip(n)` into a single shift instruction - /// if the code is inlined, however inlining does not always happen. - pub fn skip_front(mut self, n: u32) -> Self { - let mask = bitmask(n); - let ones = self.mask.trailing_ones(); - let mask_position = ones; - self.mask ^= mask.checked_shl(mask_position).unwrap_or(0); - self - } - - /// An efficient skip from the back. - /// - /// Note: The compiler is smart enough to translate a `skip(n)` into a single shift instruction - /// if the code is inlined, however inlining does not always happen. - pub fn skip_back(mut self, n: u32) -> Self { - let mask = bitmask(n); - let ones = self.mask.leading_ones(); - let mask_position = u64::BITS - ones - n; - self.mask ^= mask.checked_shl(mask_position).unwrap_or(0); - self - } -} - -impl Iterator for BitIterator { - type Item = bool; - - fn next(&mut self) -> Option<::Item> { - // trailing_ones is implemented with trailing_zeros, and the zeros are computed with the - // intrinsic cttz. [Rust 1.67.0] x86 uses the `bsf` instruction. AArch64 uses the `rbit - // clz` instructions. - let ones = self.mask.trailing_ones(); - - if ones == u64::BITS { - None - } else { - let bit_position = ones; - let mask = 1 << bit_position; - self.mask ^= mask; - let bit = self.value & mask; - Some(bit != 0) - } - } -} - -impl DoubleEndedIterator for BitIterator { - fn next_back(&mut self) -> Option<::Item> { - // leading_ones is implemented with leading_zeros, and the zeros are computed with the - // intrinsic ctlz. [Rust 1.67.0] x86 uses the `bsr` instruction. AArch64 uses the `clz` - // instruction. - let ones = self.mask.leading_ones(); - - if ones == u64::BITS { - None - } else { - let bit_position = u64::BITS - ones - 1; - let mask = 1 << bit_position; - self.mask ^= mask; - let bit = self.value & mask; - Some(bit != 0) - } - } -} - -#[cfg(test)] -mod test { - use super::BitIterator; - - #[test] - fn test_bit_iterator() { - let v = 0b1; - let mut it = BitIterator::new(v); - assert!(it.next().unwrap(), "first bit is true"); - assert!(it.all(|v| v == false), "every other value is false"); - - let v = 0b10; - let mut it = BitIterator::new(v); - assert!(!it.next().unwrap(), "first bit is false"); - assert!(it.next().unwrap(), "first bit is true"); - assert!(it.all(|v| v == false), "every other value is false"); - - let v = 0b10; - let mut it = BitIterator::new(v); - assert!(!it.next_back().unwrap(), "last bit is false"); - assert!(!it.next().unwrap(), "first bit is false"); - assert!(it.next().unwrap(), "first bit is true"); - assert!(it.all(|v| v == false), "every other value is false"); - } - - #[test] - fn test_bit_iterator_skip() { - let v = 0b1; - let mut it = BitIterator::new(v).skip_front(1); - assert!(it.all(|v| v == false), "every other value is false"); - - let v = 0b10; - let mut it = BitIterator::new(v).skip_front(1); - assert!(it.next().unwrap(), "first bit is true"); - assert!(it.all(|v| v == false), "every other value is false"); - - let high_bit = 0b1 << (u64::BITS - 1); - let mut it = BitIterator::new(high_bit).skip_back(1); - assert!(it.all(|v| v == false), "every other value is false"); - - let v = 0b10; - let mut it = BitIterator::new(v).skip_back(1); - assert!(!it.next_back().unwrap(), "last bit is false"); - assert!(!it.next().unwrap(), "first bit is false"); - assert!(it.next().unwrap(), "first bit is true"); - assert!(it.all(|v| v == false), "every other value is false"); - } - - #[test] - fn test_skip_all() { - let v = 0b1; - let mut it = BitIterator::new(v).skip_front(u64::BITS); - assert!(it.next().is_none(), "iterator must be exhausted"); - - let v = 0b1; - let mut it = BitIterator::new(v).skip_back(u64::BITS); - assert!(it.next().is_none(), "iterator must be exhausted"); - } - - #[test] - fn test_bit_iterator_count_bits_after_skip() { - let any_value = 0b1; - for s in 0..u64::BITS { - let it = BitIterator::new(any_value).skip_front(s); - assert_eq!(it.count() as u32, u64::BITS - s) - } - - let any_value = 0b1; - for s in 1..u64::BITS { - let it = BitIterator::new(any_value).skip_back(s); - assert_eq!(it.count() as u32, u64::BITS - s) - } - } - - #[test] - fn test_bit_iterator_rev() { - let v = 0b1; - let mut it = BitIterator::new(v).rev(); - assert!(it.nth(63).unwrap(), "the last value is true"); - } -} - -// UTILITIES -// =============================================================================================== - -fn bitmask(s: u32) -> u64 { - match 1u64.checked_shl(s) { - Some(r) => r - 1, - None => u64::MAX, - } -} diff --git a/src/lib.rs b/src/lib.rs index 7701d36..7c7d753 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,6 @@ #[cfg_attr(test, macro_use)] extern crate alloc; -mod bit; pub mod hash; pub mod merkle; pub mod utils; diff --git a/src/merkle/index.rs b/src/merkle/index.rs index 5729083..b4f3bdf 100644 --- a/src/merkle/index.rs +++ b/src/merkle/index.rs @@ -1,13 +1,23 @@ use super::{Felt, MerkleError, RpoDigest, StarkField}; -use crate::bit::BitIterator; // NODE INDEX // ================================================================================================ -/// A Merkle tree address to an arbitrary node. +/// Address to an arbitrary node in a binary tree using level order form. /// -/// The position is relative to a tree in level order, where for a given depth `d` elements are -/// numbered from $0..2^d$. +/// The position is represented by the pair `(depth, pos)`, where for a given depth `d` elements +/// are numbered from $0..(2^d)-1$. Example: +/// +/// ```ignore +/// depth +/// 0 0 +/// 1 0 1 +/// 2 0 1 2 3 +/// 3 0 1 2 3 4 5 6 7 +/// ``` +/// +/// The root is represented by the pair $(0, 0)$, its left child is $(1, 0)$ and its right child +/// $(1, 1)$. #[derive(Debug, Default, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct NodeIndex { depth: u8, @@ -19,20 +29,37 @@ impl NodeIndex { // -------------------------------------------------------------------------------------------- /// Creates a new node index. - pub const fn new(depth: u8, value: u64) -> Self { - Self { depth, value } + /// + /// # Errors + /// Returns an error if the `value` is greater than or equal to 2^{depth}. + pub const fn new(depth: u8, value: u64) -> Result { + if (64 - value.leading_zeros()) > depth as u32 { + Err(MerkleError::InvalidIndex { depth, value }) + } else { + Ok(Self { depth, value }) + } + } + + /// Creates a new node index for testing purposes. + /// + /// # Panics + /// Panics if the `value` is greater than or equal to 2^{depth}. + #[cfg(test)] + pub fn make(depth: u8, value: u64) -> Self { + Self::new(depth, value).unwrap() } /// Creates a node index from a pair of field elements representing the depth and value. /// /// # Errors - /// - /// Will error if the `u64` representation of the depth doesn't fit a `u8`. + /// Returns an error if: + /// - `depth` doesn't fit in a `u8`. + /// - `value` is greater than or equal to 2^{depth}. pub fn from_elements(depth: &Felt, value: &Felt) -> Result { let depth = depth.as_int(); let depth = u8::try_from(depth).map_err(|_| MerkleError::DepthTooBig(depth))?; let value = value.as_int(); - Ok(Self::new(depth, value)) + Self::new(depth, value) } /// Creates a new node index pointing to the root of the tree. @@ -40,12 +67,6 @@ impl NodeIndex { Self { depth: 0, value: 0 } } - /// Mutates the instance and returns it, replacing the depth. - pub const fn with_depth(mut self, depth: u8) -> Self { - self.depth = depth; - self - } - /// Computes the value of the sibling of the current node. pub fn sibling(mut self) -> Self { self.value ^= 1; @@ -83,11 +104,6 @@ impl NodeIndex { self.value } - /// Returns true if the current value fits the current depth for a binary tree. - pub const fn is_valid(&self) -> bool { - self.value < (1 << self.depth as u64) - } - /// Returns true if the current instance points to a right sibling node. pub const fn is_value_odd(&self) -> bool { (self.value & 1) == 1 @@ -98,19 +114,6 @@ impl NodeIndex { self.depth == 0 } - /// Returns a bit iterator for the `value`. - /// - /// Bits read from left-to-right represent which internal node's child should be visited to - /// arrive at the leaf. From the right-to-left the bit represent the position the hash of the - /// current element should go. - /// - /// Additionally, the value that is not visited are the sibling values necessary for a Merkle - /// opening. - pub fn bit_iterator(&self) -> BitIterator { - let depth: u32 = self.depth.into(); - BitIterator::new(self.value).skip_back(u64::BITS - depth) - } - // STATE MUTATORS // -------------------------------------------------------------------------------------------- @@ -127,14 +130,43 @@ mod tests { use super::*; use proptest::prelude::*; + #[test] + fn test_node_index_value_too_high() { + assert_eq!( + NodeIndex::new(0, 0).unwrap(), + NodeIndex { depth: 0, value: 0 } + ); + match NodeIndex::new(0, 1) { + Err(MerkleError::InvalidIndex { depth, value }) => { + assert_eq!(depth, 0); + assert_eq!(value, 1); + } + _ => unreachable!(), + } + } + + #[test] + fn test_node_index_can_represent_depth_64() { + assert!(NodeIndex::new(64, u64::MAX).is_ok()); + } + + prop_compose! { + fn node_index()(value in 0..2u64.pow(u64::BITS - 1)) -> NodeIndex { + // unwrap never panics because the range of depth is 0..u64::BITS + let mut depth = value.ilog2() as u8; + if value > (1 << depth) { // round up + depth += 1; + } + NodeIndex::new(depth, value.into()).unwrap() + } + } + proptest! { #[test] fn arbitrary_index_wont_panic_on_move_up( - depth in prop::num::u8::ANY, - value in prop::num::u64::ANY, + mut index in node_index(), count in prop::num::u8::ANY, ) { - let mut index = NodeIndex::new(depth, value); for _ in 0..count { index.move_up(); } diff --git a/src/merkle/merkle_tree.rs b/src/merkle/merkle_tree.rs index 6b767ae..3587fc6 100644 --- a/src/merkle/merkle_tree.rs +++ b/src/merkle/merkle_tree.rs @@ -79,8 +79,6 @@ impl MerkleTree { return Err(MerkleError::DepthTooSmall(index.depth())); } else if index.depth() > self.depth() { return Err(MerkleError::DepthTooBig(index.depth() as u64)); - } else if !index.is_valid() { - return Err(MerkleError::InvalidIndex(index)); } let pos = index.to_scalar_index() as usize; @@ -99,8 +97,6 @@ impl MerkleTree { return Err(MerkleError::DepthTooSmall(index.depth())); } else if index.depth() > self.depth() { return Err(MerkleError::DepthTooBig(index.depth() as u64)); - } else if !index.is_valid() { - return Err(MerkleError::InvalidIndex(index)); } // TODO should we create a helper in `NodeIndex` that will encapsulate traversal to root so @@ -126,11 +122,7 @@ impl MerkleTree { /// # Errors /// Returns an error if the specified index value is not a valid leaf value for this tree. pub fn update_leaf<'a>(&'a mut self, index_value: u64, value: Word) -> Result<(), MerkleError> { - let depth = self.depth(); - let mut index = NodeIndex::new(depth, index_value); - if !index.is_valid() { - return Err(MerkleError::InvalidIndex(index)); - } + let mut index = NodeIndex::new(self.depth(), index_value)?; // we don't need to copy the pairs into a new address as we are logically guaranteed to not // overlap write instructions. however, it's important to bind the lifetime of pairs to @@ -203,7 +195,7 @@ impl<'a> Iterator for MerkleTreeNodes<'a> { } } -/// Utility to vizualize a [MerkleTree] in text. +/// Utility to visualize a [MerkleTree] in text. pub fn tree_to_text(tree: &MerkleTree) -> Result { let indent = " "; let mut s = String::new(); @@ -212,11 +204,8 @@ pub fn tree_to_text(tree: &MerkleTree) -> Result { for d in 1..=tree.depth() { let entries = 2u64.pow(d.into()); for i in 0..entries { - let index = NodeIndex::new(d, i); - - let node = tree - .get_node(index) - .expect("The index must always be valid"); + let index = NodeIndex::new(d, i).expect("The index must always be valid"); + let node = tree.get_node(index).expect("The node must always be found"); for _ in 0..d { s.push_str(indent); @@ -229,7 +218,7 @@ pub fn tree_to_text(tree: &MerkleTree) -> Result { Ok(s) } -/// Utility to vizualize a [MerklePath] in text. +/// Utility to visualize a [MerklePath] in text. pub fn path_to_text(path: &MerklePath) -> Result { let mut s = String::new(); s.push('['); @@ -301,16 +290,16 @@ mod tests { let tree = super::MerkleTree::new(LEAVES4.to_vec()).unwrap(); // check depth 2 - assert_eq!(LEAVES4[0], tree.get_node(NodeIndex::new(2, 0)).unwrap()); - assert_eq!(LEAVES4[1], tree.get_node(NodeIndex::new(2, 1)).unwrap()); - assert_eq!(LEAVES4[2], tree.get_node(NodeIndex::new(2, 2)).unwrap()); - assert_eq!(LEAVES4[3], tree.get_node(NodeIndex::new(2, 3)).unwrap()); + assert_eq!(LEAVES4[0], tree.get_node(NodeIndex::make(2, 0)).unwrap()); + assert_eq!(LEAVES4[1], tree.get_node(NodeIndex::make(2, 1)).unwrap()); + assert_eq!(LEAVES4[2], tree.get_node(NodeIndex::make(2, 2)).unwrap()); + assert_eq!(LEAVES4[3], tree.get_node(NodeIndex::make(2, 3)).unwrap()); // check depth 1 let (_, node2, node3) = compute_internal_nodes(); - assert_eq!(node2, tree.get_node(NodeIndex::new(1, 0)).unwrap()); - assert_eq!(node3, tree.get_node(NodeIndex::new(1, 1)).unwrap()); + assert_eq!(node2, tree.get_node(NodeIndex::make(1, 0)).unwrap()); + assert_eq!(node3, tree.get_node(NodeIndex::make(1, 1)).unwrap()); } #[test] @@ -322,24 +311,24 @@ mod tests { // check depth 2 assert_eq!( vec![LEAVES4[1], node3], - *tree.get_path(NodeIndex::new(2, 0)).unwrap() + *tree.get_path(NodeIndex::make(2, 0)).unwrap() ); assert_eq!( vec![LEAVES4[0], node3], - *tree.get_path(NodeIndex::new(2, 1)).unwrap() + *tree.get_path(NodeIndex::make(2, 1)).unwrap() ); assert_eq!( vec![LEAVES4[3], node2], - *tree.get_path(NodeIndex::new(2, 2)).unwrap() + *tree.get_path(NodeIndex::make(2, 2)).unwrap() ); assert_eq!( vec![LEAVES4[2], node2], - *tree.get_path(NodeIndex::new(2, 3)).unwrap() + *tree.get_path(NodeIndex::make(2, 3)).unwrap() ); // check depth 1 - assert_eq!(vec![node3], *tree.get_path(NodeIndex::new(1, 0)).unwrap()); - assert_eq!(vec![node2], *tree.get_path(NodeIndex::new(1, 1)).unwrap()); + assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap()); + assert_eq!(vec![node2], *tree.get_path(NodeIndex::make(1, 1)).unwrap()); } #[test] @@ -370,12 +359,12 @@ mod tests { fn nodes() -> Result<(), MerkleError> { let tree = super::MerkleTree::new(LEAVES4.to_vec()).unwrap(); let root = tree.root(); - let l1n0 = tree.get_node(NodeIndex::new(1, 0))?; - let l1n1 = tree.get_node(NodeIndex::new(1, 1))?; - let l2n0 = tree.get_node(NodeIndex::new(2, 0))?; - let l2n1 = tree.get_node(NodeIndex::new(2, 1))?; - let l2n2 = tree.get_node(NodeIndex::new(2, 2))?; - let l2n3 = tree.get_node(NodeIndex::new(2, 3))?; + let l1n0 = tree.get_node(NodeIndex::make(1, 0))?; + let l1n1 = tree.get_node(NodeIndex::make(1, 1))?; + let l2n0 = tree.get_node(NodeIndex::make(2, 0))?; + let l2n1 = tree.get_node(NodeIndex::make(2, 1))?; + let l2n2 = tree.get_node(NodeIndex::make(2, 2))?; + let l2n3 = tree.get_node(NodeIndex::make(2, 3))?; let nodes: Vec = tree.inner_nodes().collect(); let expected = vec![ diff --git a/src/merkle/mod.rs b/src/merkle/mod.rs index c12ac7a..4d36577 100644 --- a/src/merkle/mod.rs +++ b/src/merkle/mod.rs @@ -1,6 +1,6 @@ use super::{ hash::rpo::{Rpo256, RpoDigest}, - utils::collections::{vec, BTreeMap, BTreeSet, Vec}, + utils::collections::{vec, BTreeMap, Vec}, Felt, StarkField, Word, WORD_SIZE, ZERO, }; use core::fmt; @@ -45,7 +45,7 @@ pub enum MerkleError { DepthTooBig(u64), NodeNotInStore(Word, NodeIndex), NumLeavesNotPowerOfTwo(usize), - InvalidIndex(NodeIndex), + InvalidIndex { depth: u8, value: u64 }, InvalidDepth { expected: u8, provided: u8 }, InvalidPath(MerklePath), InvalidEntriesCount(usize, usize), @@ -63,9 +63,9 @@ impl fmt::Display for MerkleError { NumLeavesNotPowerOfTwo(leaves) => { write!(f, "the leaves count {leaves} is not a power of 2") } - InvalidIndex(index) => write!( + InvalidIndex{ depth, value} => write!( f, - "the index value {} is not valid for the depth {}", index.value(), index.depth() + "the index value {value} is not valid for the depth {depth}" ), InvalidDepth { expected, provided } => write!( f, diff --git a/src/merkle/path.rs b/src/merkle/path.rs index 9a4e46b..964f6d0 100644 --- a/src/merkle/path.rs +++ b/src/merkle/path.rs @@ -1,4 +1,4 @@ -use super::{vec, NodeIndex, Rpo256, Vec, Word}; +use super::{vec, MerkleError, NodeIndex, Rpo256, Vec, Word}; use core::ops::{Deref, DerefMut}; // MERKLE PATH @@ -23,14 +23,15 @@ impl MerklePath { // -------------------------------------------------------------------------------------------- /// Computes the merkle root for this opening. - pub fn compute_root(&self, index_value: u64, node: Word) -> Word { - let mut index = NodeIndex::new(self.depth(), index_value); - self.nodes.iter().copied().fold(node, |node, sibling| { + pub fn compute_root(&self, index: u64, node: Word) -> Result { + let mut index = NodeIndex::new(self.depth(), index)?; + let root = self.nodes.iter().copied().fold(node, |node, sibling| { // compute the node and move to the next iteration. let input = index.build_node(node.into(), sibling.into()); index.move_up(); Rpo256::merge(&input).into() - }) + }); + Ok(root) } /// Returns the depth in which this Merkle path proof is valid. @@ -42,7 +43,10 @@ impl MerklePath { /// /// Returns `true` if `node` exists at `index` in a Merkle tree with `root`. pub fn verify(&self, index: u64, node: Word, root: &Word) -> bool { - root == &self.compute_root(index, node) + match self.compute_root(index, node) { + Ok(computed_root) => root == &computed_root, + Err(_) => false, + } } } diff --git a/src/merkle/path_set.rs b/src/merkle/path_set.rs index 9a90687..ef3cc48 100644 --- a/src/merkle/path_set.rs +++ b/src/merkle/path_set.rs @@ -64,11 +64,6 @@ impl MerklePathSet { /// * The specified index is not valid for the depth of structure. /// * Requested node does not exist in the set. pub fn get_node(&self, index: NodeIndex) -> Result { - if !index.with_depth(self.total_depth).is_valid() { - return Err(MerkleError::InvalidIndex( - index.with_depth(self.total_depth), - )); - } if index.depth() != self.total_depth { return Err(MerkleError::InvalidDepth { expected: self.total_depth, @@ -90,7 +85,8 @@ impl MerklePathSet { /// * The specified index is not valid for the depth of the structure. /// * Leaf with the requested path does not exist in the set. pub fn get_leaf(&self, index: u64) -> Result { - self.get_node(NodeIndex::new(self.depth(), index)) + let index = NodeIndex::new(self.depth(), index)?; + self.get_node(index) } /// Returns a Merkle path to the node at the specified index. The node itself is @@ -101,9 +97,6 @@ impl MerklePathSet { /// * The specified index is not valid for the depth of structure. /// * Node of the requested path does not exist in the set. pub fn get_path(&self, index: NodeIndex) -> Result { - if !index.with_depth(self.total_depth).is_valid() { - return Err(MerkleError::InvalidIndex(index)); - } if index.depth() != self.total_depth { return Err(MerkleError::InvalidDepth { expected: self.total_depth, @@ -165,8 +158,7 @@ impl MerklePathSet { value: Word, mut path: MerklePath, ) -> Result<(), MerkleError> { - let depth = path.len() as u8; - let mut index = NodeIndex::new(depth, index_value); + let mut index = NodeIndex::new(path.len() as u8, index_value)?; if index.depth() != self.total_depth { return Err(MerkleError::InvalidDepth { expected: self.total_depth, @@ -190,7 +182,7 @@ impl MerklePathSet { if self.root == [ZERO; 4] { self.root = root; } else if self.root != root { - return Err(MerkleError::InvalidPath(path)); + return Err(MerkleError::ConflictingRoots([self.root, root].to_vec())); } // finish updating the path @@ -205,12 +197,7 @@ impl MerklePathSet { /// Returns an error if: /// * Requested node does not exist in the set. pub fn update_leaf(&mut self, base_index_value: u64, value: Word) -> Result<(), MerkleError> { - let depth = self.depth(); - let mut index = NodeIndex::new(depth, base_index_value); - if !index.is_valid() { - return Err(MerkleError::InvalidIndex(index)); - } - + let mut index = NodeIndex::new(self.depth(), base_index_value)?; let parity = index.value() & 1; let path_key = index.value() - parity; let path = match self.paths.get_mut(&path_key) { @@ -293,10 +280,9 @@ mod tests { let set = super::MerklePathSet::new(depth) .with_paths([(index, hash_6, path_6.clone().into())]) .unwrap(); - let stored_path_6 = set.get_path(NodeIndex::new(depth, index)).unwrap(); + let stored_path_6 = set.get_path(NodeIndex::make(depth, index)).unwrap(); assert_eq!(path_6, *stored_path_6); - assert!(set.get_path(NodeIndex::new(depth, 15_u64)).is_err()) } #[test] @@ -311,9 +297,8 @@ mod tests { assert_eq!( int_to_node(6u64), - set.get_node(NodeIndex::new(depth, index)).unwrap() + set.get_node(NodeIndex::make(depth, index)).unwrap() ); - assert!(set.get_node(NodeIndex::new(depth, 15_u64)).is_err()); } #[test] @@ -347,13 +332,13 @@ mod tests { let new_hash_5 = int_to_node(55); set.update_leaf(index_6, new_hash_6).unwrap(); - let new_path_4 = set.get_path(NodeIndex::new(depth, index_4)).unwrap(); + let new_path_4 = set.get_path(NodeIndex::make(depth, index_4)).unwrap(); let new_hash_67 = calculate_parent_hash(new_hash_6, 14_u64, hash_7); assert_eq!(new_hash_67, new_path_4[1]); set.update_leaf(index_5, new_hash_5).unwrap(); - let new_path_4 = set.get_path(NodeIndex::new(depth, index_4)).unwrap(); - let new_path_6 = set.get_path(NodeIndex::new(depth, index_6)).unwrap(); + let new_path_4 = set.get_path(NodeIndex::make(depth, index_4)).unwrap(); + let new_path_6 = set.get_path(NodeIndex::make(depth, index_6)).unwrap(); let new_hash_45 = calculate_parent_hash(new_hash_5, 13_u64, hash_4); assert_eq!(new_hash_45, new_path_6[1]); assert_eq!(new_hash_5, new_path_4[0]); diff --git a/src/merkle/simple_smt/mod.rs b/src/merkle/simple_smt/mod.rs index 85fec0e..b9eda8a 100644 --- a/src/merkle/simple_smt/mod.rs +++ b/src/merkle/simple_smt/mod.rs @@ -119,12 +119,12 @@ impl SimpleSmt { self.leaves.len() } - /// Returns a node at the specified key + /// Returns a node at the specified index. /// /// # Errors /// Returns an error if: /// * The specified depth is greater than the depth of the tree. - pub fn get_node(&self, index: &NodeIndex) -> Result { + pub fn get_node(&self, index: NodeIndex) -> Result { if index.is_root() { Err(MerkleError::DepthTooSmall(index.depth())) } else if index.depth() > self.depth() { @@ -137,9 +137,9 @@ impl SimpleSmt { .copied() .map(Word::from) }) - .ok_or(MerkleError::InvalidIndex(*index)) + .ok_or(MerkleError::NodeNotInSet(index.value())) } else { - let branch_node = self.get_branch_node(index); + let branch_node = self.get_branch_node(&index); Ok(Rpo256::merge(&[branch_node.left, branch_node.right]).into()) } } @@ -175,7 +175,8 @@ impl SimpleSmt { /// Returns an error if: /// * The specified key does not exist as a leaf node. pub fn get_leaf_path(&self, key: u64) -> Result { - self.get_path(NodeIndex::new(self.depth(), key)) + let index = NodeIndex::new(self.depth(), key)?; + self.get_path(index) } /// Iterator over the inner nodes of the [SimpleSmt]. @@ -190,13 +191,15 @@ impl SimpleSmt { // STATE MUTATORS // -------------------------------------------------------------------------------------------- - /// Replaces the leaf located at the specified key, and recomputes hashes by walking up the tree + /// Replaces the leaf located at the specified key, and recomputes hashes by walking up the + /// tree. /// /// # Errors /// Returns an error if the specified key is not a valid leaf index for this tree. pub fn update_leaf(&mut self, key: u64, value: Word) -> Result<(), MerkleError> { + let index = NodeIndex::new(self.depth(), key)?; if !self.check_leaf_node_exists(key) { - return Err(MerkleError::InvalidIndex(NodeIndex::new(self.depth(), key))); + return Err(MerkleError::NodeNotInSet(index.value())); } self.insert_leaf(key, value)?; @@ -208,7 +211,7 @@ impl SimpleSmt { self.insert_leaf_node(key, value); // TODO consider using a map `index |-> word` instead of `index |-> (word, word)` - let mut index = NodeIndex::new(self.depth(), key); + let mut index = NodeIndex::new(self.depth(), key)?; let mut value = RpoDigest::from(value); for _ in 0..index.depth() { let is_right = index.is_value_odd(); diff --git a/src/merkle/simple_smt/tests.rs b/src/merkle/simple_smt/tests.rs index f7b8635..82938d3 100644 --- a/src/merkle/simple_smt/tests.rs +++ b/src/merkle/simple_smt/tests.rs @@ -61,8 +61,8 @@ fn build_sparse_tree() { let mt2 = MerkleTree::new(values.clone()).unwrap(); assert_eq!(mt2.root(), smt.root()); assert_eq!( - mt2.get_path(NodeIndex::new(3, 6)).unwrap(), - smt.get_path(NodeIndex::new(3, 6)).unwrap() + mt2.get_path(NodeIndex::make(3, 6)).unwrap(), + smt.get_path(NodeIndex::make(3, 6)).unwrap() ); // insert second value at distinct leaf branch @@ -74,8 +74,8 @@ fn build_sparse_tree() { let mt3 = MerkleTree::new(values).unwrap(); assert_eq!(mt3.root(), smt.root()); assert_eq!( - mt3.get_path(NodeIndex::new(3, 2)).unwrap(), - smt.get_path(NodeIndex::new(3, 2)).unwrap() + mt3.get_path(NodeIndex::make(3, 2)).unwrap(), + smt.get_path(NodeIndex::make(3, 2)).unwrap() ); } @@ -88,8 +88,8 @@ fn build_full_tree() { let (root, node2, node3) = compute_internal_nodes(); assert_eq!(root, tree.root()); - assert_eq!(node2, tree.get_node(&NodeIndex::new(1, 0)).unwrap()); - assert_eq!(node3, tree.get_node(&NodeIndex::new(1, 1)).unwrap()); + assert_eq!(node2, tree.get_node(NodeIndex::make(1, 0)).unwrap()); + assert_eq!(node3, tree.get_node(NodeIndex::make(1, 1)).unwrap()); } #[test] @@ -100,10 +100,10 @@ fn get_values() { .unwrap(); // check depth 2 - assert_eq!(VALUES4[0], tree.get_node(&NodeIndex::new(2, 0)).unwrap()); - assert_eq!(VALUES4[1], tree.get_node(&NodeIndex::new(2, 1)).unwrap()); - assert_eq!(VALUES4[2], tree.get_node(&NodeIndex::new(2, 2)).unwrap()); - assert_eq!(VALUES4[3], tree.get_node(&NodeIndex::new(2, 3)).unwrap()); + assert_eq!(VALUES4[0], tree.get_node(NodeIndex::make(2, 0)).unwrap()); + assert_eq!(VALUES4[1], tree.get_node(NodeIndex::make(2, 1)).unwrap()); + assert_eq!(VALUES4[2], tree.get_node(NodeIndex::make(2, 2)).unwrap()); + assert_eq!(VALUES4[3], tree.get_node(NodeIndex::make(2, 3)).unwrap()); } #[test] @@ -118,24 +118,24 @@ fn get_path() { // check depth 2 assert_eq!( vec![VALUES4[1], node3], - *tree.get_path(NodeIndex::new(2, 0)).unwrap() + *tree.get_path(NodeIndex::make(2, 0)).unwrap() ); assert_eq!( vec![VALUES4[0], node3], - *tree.get_path(NodeIndex::new(2, 1)).unwrap() + *tree.get_path(NodeIndex::make(2, 1)).unwrap() ); assert_eq!( vec![VALUES4[3], node2], - *tree.get_path(NodeIndex::new(2, 2)).unwrap() + *tree.get_path(NodeIndex::make(2, 2)).unwrap() ); assert_eq!( vec![VALUES4[2], node2], - *tree.get_path(NodeIndex::new(2, 3)).unwrap() + *tree.get_path(NodeIndex::make(2, 3)).unwrap() ); // check depth 1 - assert_eq!(vec![node3], *tree.get_path(NodeIndex::new(1, 0)).unwrap()); - assert_eq!(vec![node2], *tree.get_path(NodeIndex::new(1, 1)).unwrap()); + assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap()); + assert_eq!(vec![node2], *tree.get_path(NodeIndex::make(1, 1)).unwrap()); } #[test] @@ -146,19 +146,19 @@ fn test_parent_node_iterator() -> Result<(), MerkleError> { .unwrap(); // check depth 2 - assert_eq!(VALUES4[0], tree.get_node(&NodeIndex::new(2, 0)).unwrap()); - assert_eq!(VALUES4[1], tree.get_node(&NodeIndex::new(2, 1)).unwrap()); - assert_eq!(VALUES4[2], tree.get_node(&NodeIndex::new(2, 2)).unwrap()); - assert_eq!(VALUES4[3], tree.get_node(&NodeIndex::new(2, 3)).unwrap()); + assert_eq!(VALUES4[0], tree.get_node(NodeIndex::make(2, 0)).unwrap()); + assert_eq!(VALUES4[1], tree.get_node(NodeIndex::make(2, 1)).unwrap()); + assert_eq!(VALUES4[2], tree.get_node(NodeIndex::make(2, 2)).unwrap()); + assert_eq!(VALUES4[3], tree.get_node(NodeIndex::make(2, 3)).unwrap()); // get parent nodes let root = tree.root(); - let l1n0 = tree.get_node(&NodeIndex::new(1, 0))?; - let l1n1 = tree.get_node(&NodeIndex::new(1, 1))?; - let l2n0 = tree.get_node(&NodeIndex::new(2, 0))?; - let l2n1 = tree.get_node(&NodeIndex::new(2, 1))?; - let l2n2 = tree.get_node(&NodeIndex::new(2, 2))?; - let l2n3 = tree.get_node(&NodeIndex::new(2, 3))?; + let l1n0 = tree.get_node(NodeIndex::make(1, 0))?; + let l1n1 = tree.get_node(NodeIndex::make(1, 1))?; + let l2n0 = tree.get_node(NodeIndex::make(2, 0))?; + let l2n1 = tree.get_node(NodeIndex::make(2, 1))?; + let l2n2 = tree.get_node(NodeIndex::make(2, 2))?; + let l2n3 = tree.get_node(NodeIndex::make(2, 3))?; let nodes: Vec = tree.inner_nodes().collect(); let expected = vec![ @@ -263,7 +263,7 @@ fn small_tree_opening_is_consistent() { ]; for (depth, key, path) in cases { - let opening = tree.get_path(NodeIndex::new(depth, key)).unwrap(); + let opening = tree.get_path(NodeIndex::make(depth, key)).unwrap(); assert_eq!(path, *opening); } @@ -287,7 +287,7 @@ proptest! { // traverse to root, fetching all paths for d in 1..depth { let k = key >> (depth - d); - tree.get_path(NodeIndex::new(d, k)).unwrap(); + tree.get_path(NodeIndex::make(d, k)).unwrap(); } } diff --git a/src/merkle/store/mod.rs b/src/merkle/store/mod.rs index 7a266af..3c52462 100644 --- a/src/merkle/store/mod.rs +++ b/src/merkle/store/mod.rs @@ -1,7 +1,7 @@ use super::mmr::{Mmr, MmrPeaks}; use super::{ - BTreeMap, BTreeSet, EmptySubtreeRoots, MerkleError, MerklePath, MerklePathSet, MerkleTree, - NodeIndex, RootPath, Rpo256, RpoDigest, SimpleSmt, ValuePath, Vec, Word, + BTreeMap, EmptySubtreeRoots, MerkleError, MerklePath, MerklePathSet, MerkleTree, NodeIndex, + RootPath, Rpo256, RpoDigest, SimpleSmt, ValuePath, Vec, Word, }; use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; @@ -53,15 +53,19 @@ pub struct Node { /// /// // every leaf except the last are the same /// for i in 0..7 { -/// let d0 = store.get_node(ROOT0, NodeIndex::new(3, i)).unwrap(); -/// let d1 = store.get_node(ROOT1, NodeIndex::new(3, i)).unwrap(); +/// let idx0 = NodeIndex::new(3, i).unwrap(); +/// let d0 = store.get_node(ROOT0, idx0).unwrap(); +/// let idx1 = NodeIndex::new(3, i).unwrap(); +/// let d1 = store.get_node(ROOT1, idx1).unwrap(); /// assert_eq!(d0, d1, "Both trees have the same leaf at pos {i}"); /// } /// /// // The leafs A-B-C-D are the same for both trees, so are their 2 immediate parents /// for i in 0..4 { -/// let d0 = store.get_path(ROOT0, NodeIndex::new(3, i)).unwrap(); -/// let d1 = store.get_path(ROOT1, NodeIndex::new(3, i)).unwrap(); +/// let idx0 = NodeIndex::new(3, i).unwrap(); +/// let d0 = store.get_path(ROOT0, idx0).unwrap(); +/// let idx1 = NodeIndex::new(3, i).unwrap(); +/// let d1 = store.get_path(ROOT1, idx1).unwrap(); /// assert_eq!(d0.path[0..2], d1.path[0..2], "Both sub-trees are equal up to two levels"); /// } /// @@ -184,12 +188,14 @@ impl MerkleStore { .get(&hash) .ok_or(MerkleError::RootNotInStore(hash.into()))?; - for bit in index.bit_iterator().rev() { + for i in (0..index.depth()).rev() { let node = self .nodes .get(&hash) .ok_or(MerkleError::NodeNotInStore(hash.into(), index))?; - hash = if bit { node.right } else { node.left } + + let bit = (index.value() >> i) & 1; + hash = if bit == 0 { node.left } else { node.right } } Ok(hash.into()) @@ -213,18 +219,19 @@ impl MerkleStore { .get(&hash) .ok_or(MerkleError::RootNotInStore(hash.into()))?; - for bit in index.bit_iterator().rev() { + for i in (0..index.depth()).rev() { let node = self .nodes .get(&hash) .ok_or(MerkleError::NodeNotInStore(hash.into(), index))?; - hash = if bit { - path.push(node.left.into()); - node.right - } else { + let bit = (index.value() >> i) & 1; + hash = if bit == 0 { path.push(node.right.into()); node.left + } else { + path.push(node.left.into()); + node.right } } @@ -315,7 +322,7 @@ impl MerkleStore { mut node: Word, path: MerklePath, ) -> Result { - let mut index = NodeIndex::new(self.nodes.len() as u8, index_value); + let mut index = NodeIndex::new(path.len() as u8, index_value)?; for sibling in path { let (left, right) = match index.is_value_odd() { @@ -344,33 +351,14 @@ impl MerkleStore { /// into the store. /// /// For further reference, check [MerkleStore::add_merkle_path]. - /// - /// # Errors - /// - /// Every path must resolve to the same root, otherwise this will return an `ConflictingRoots` - /// error. - pub fn add_merkle_paths(&mut self, paths: I) -> Result + pub fn add_merkle_paths(&mut self, paths: I) -> Result<(), MerkleError> where I: IntoIterator, { - let paths: Vec<(u64, Word, MerklePath)> = paths.into_iter().collect(); - - let roots: BTreeSet = paths - .iter() - .map(|(index, node, path)| path.compute_root(*index, *node).into()) - .collect(); - - if roots.len() != 1 { - return Err(MerkleError::ConflictingRoots( - roots.iter().map(|v| Word::from(*v)).collect(), - )); - } - - for (index_value, node, path) in paths { + for (index_value, node, path) in paths.into_iter() { self.add_merkle_path(index_value, node, path)?; } - - Ok(roots.iter().next().unwrap().into()) + Ok(()) } /// Appends the provided [MerklePathSet] into the store. @@ -432,15 +420,9 @@ impl MerkleStore { let root2: RpoDigest = root2.into(); if !self.nodes.contains_key(&root1) { - Err(MerkleError::NodeNotInStore( - root1.into(), - NodeIndex::new(0, 0), - )) + Err(MerkleError::NodeNotInStore(root1.into(), NodeIndex::root())) } else if !self.nodes.contains_key(&root1) { - Err(MerkleError::NodeNotInStore( - root2.into(), - NodeIndex::new(0, 0), - )) + Err(MerkleError::NodeNotInStore(root2.into(), NodeIndex::root())) } else { let parent: Word = Rpo256::merge(&[root1, root2]).into(); self.nodes.insert( diff --git a/src/merkle/store/tests.rs b/src/merkle/store/tests.rs index a14c557..e6648a9 100644 --- a/src/merkle/store/tests.rs +++ b/src/merkle/store/tests.rs @@ -22,12 +22,12 @@ fn test_root_not_in_store() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; let store = MerkleStore::default().with_merkle_tree(LEAVES4)?; assert_eq!( - store.get_node(LEAVES4[0], NodeIndex::new(mtree.depth(), 0)), + store.get_node(LEAVES4[0], NodeIndex::make(mtree.depth(), 0)), Err(MerkleError::RootNotInStore(LEAVES4[0])), "Leaf 0 is not a root" ); assert_eq!( - store.get_path(LEAVES4[0], NodeIndex::new(mtree.depth(), 0)), + store.get_path(LEAVES4[0], NodeIndex::make(mtree.depth(), 0)), Err(MerkleError::RootNotInStore(LEAVES4[0])), "Leaf 0 is not a root" ); @@ -45,22 +45,22 @@ fn test_merkle_tree() -> Result<(), MerkleError> { // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values assert_eq!( - store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 0)), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 0)), Ok(LEAVES4[0]), "node 0 must be in the tree" ); assert_eq!( - store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 1)), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 1)), Ok(LEAVES4[1]), "node 1 must be in the tree" ); assert_eq!( - store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 2)), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 2)), Ok(LEAVES4[2]), "node 2 must be in the tree" ); assert_eq!( - store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 3)), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)), Ok(LEAVES4[3]), "node 3 must be in the tree" ); @@ -68,76 +68,76 @@ fn test_merkle_tree() -> Result<(), MerkleError> { // STORE LEAVES MATCH TREE =============================================================== // sanity check the values returned by the store and the tree assert_eq!( - mtree.get_node(NodeIndex::new(mtree.depth(), 0)), - store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 0)), + mtree.get_node(NodeIndex::make(mtree.depth(), 0)), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 0)), "node 0 must be the same for both MerkleTree and MerkleStore" ); assert_eq!( - mtree.get_node(NodeIndex::new(mtree.depth(), 1)), - store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 1)), + mtree.get_node(NodeIndex::make(mtree.depth(), 1)), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 1)), "node 1 must be the same for both MerkleTree and MerkleStore" ); assert_eq!( - mtree.get_node(NodeIndex::new(mtree.depth(), 2)), - store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 2)), + mtree.get_node(NodeIndex::make(mtree.depth(), 2)), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 2)), "node 2 must be the same for both MerkleTree and MerkleStore" ); assert_eq!( - mtree.get_node(NodeIndex::new(mtree.depth(), 3)), - store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 3)), + mtree.get_node(NodeIndex::make(mtree.depth(), 3)), + store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)), "node 3 must be the same for both MerkleTree and MerkleStore" ); // STORE MERKLE PATH MATCHS ============================================================== // assert the merkle path returned by the store is the same as the one in the tree let result = store - .get_path(mtree.root(), NodeIndex::new(mtree.depth(), 0)) + .get_path(mtree.root(), NodeIndex::make(mtree.depth(), 0)) .unwrap(); assert_eq!( LEAVES4[0], result.value, "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - mtree.get_path(NodeIndex::new(mtree.depth(), 0)), + mtree.get_path(NodeIndex::make(mtree.depth(), 0)), Ok(result.path), "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(mtree.root(), NodeIndex::new(mtree.depth(), 1)) + .get_path(mtree.root(), NodeIndex::make(mtree.depth(), 1)) .unwrap(); assert_eq!( LEAVES4[1], result.value, "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - mtree.get_path(NodeIndex::new(mtree.depth(), 1)), + mtree.get_path(NodeIndex::make(mtree.depth(), 1)), Ok(result.path), "merkle path for index 1 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(mtree.root(), NodeIndex::new(mtree.depth(), 2)) + .get_path(mtree.root(), NodeIndex::make(mtree.depth(), 2)) .unwrap(); assert_eq!( LEAVES4[2], result.value, "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - mtree.get_path(NodeIndex::new(mtree.depth(), 2)), + mtree.get_path(NodeIndex::make(mtree.depth(), 2)), Ok(result.path), "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(mtree.root(), NodeIndex::new(mtree.depth(), 3)) + .get_path(mtree.root(), NodeIndex::make(mtree.depth(), 3)) .unwrap(); assert_eq!( LEAVES4[3], result.value, "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - mtree.get_path(NodeIndex::new(mtree.depth(), 3)), + mtree.get_path(NodeIndex::make(mtree.depth(), 3)), Ok(result.path), "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); @@ -153,7 +153,7 @@ fn test_empty_roots() { for depth in 0..255 { root = Rpo256::merge(&[root; 2]); assert!( - store.get_node(root.into(), NodeIndex::new(0, 0)).is_ok(), + store.get_node(root.into(), NodeIndex::make(0, 0)).is_ok(), "The root of the empty tree of depth {depth} must be registered" ); } @@ -169,7 +169,7 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> { for depth in 1..64 { let smt = SimpleSmt::new(depth)?; - let index = NodeIndex::new(depth, 0); + let index = NodeIndex::make(depth, 0); let store_path = store.get_path(smt.root(), index)?; let smt_path = smt.get_path(index)?; assert_eq!( @@ -181,7 +181,7 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> { "the returned merkle path does not match the computed values" ); assert_eq!( - store_path.path.compute_root(depth.into(), EMPTY), + store_path.path.compute_root(depth.into(), EMPTY).unwrap(), smt.root(), "computed root from the path must match the empty tree root" ); @@ -197,7 +197,7 @@ fn test_get_invalid_node() { store .add_merkle_tree(LEAVES4.to_vec()) .expect("adding a merkle tree to the store must work"); - let _ = store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 3)); + let _ = store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)); } #[test] @@ -211,18 +211,18 @@ fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> { .with_leaves(keys2.into_iter().zip(leaves2.into_iter())) .unwrap(); - let idx = NodeIndex::new(1, 0); - assert_eq!(smt.get_node(&idx).unwrap(), leaves2[0]); + let idx = NodeIndex::make(1, 0); + assert_eq!(smt.get_node(idx).unwrap(), leaves2[0]); assert_eq!( store.get_node(smt.root(), idx).unwrap(), - smt.get_node(&idx).unwrap() + smt.get_node(idx).unwrap() ); - let idx = NodeIndex::new(1, 1); - assert_eq!(smt.get_node(&idx).unwrap(), leaves2[1]); + let idx = NodeIndex::make(1, 1); + assert_eq!(smt.get_node(idx).unwrap(), leaves2[1]); assert_eq!( store.get_node(smt.root(), idx).unwrap(), - smt.get_node(&idx).unwrap() + smt.get_node(idx).unwrap() ); Ok(()) @@ -244,27 +244,27 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values assert_eq!( - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 0)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 0)), Ok(LEAVES4[0]), "node 0 must be in the tree" ); assert_eq!( - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 1)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 1)), Ok(LEAVES4[1]), "node 1 must be in the tree" ); assert_eq!( - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 2)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 2)), Ok(LEAVES4[2]), "node 2 must be in the tree" ); assert_eq!( - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 3)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 3)), Ok(LEAVES4[3]), "node 3 must be in the tree" ); assert_eq!( - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 4)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 4)), Ok(EMPTY), "unmodified node 4 must be ZERO" ); @@ -272,94 +272,94 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> { // STORE LEAVES MATCH TREE =============================================================== // sanity check the values returned by the store and the tree assert_eq!( - smt.get_node(&NodeIndex::new(smt.depth(), 0)), - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 0)), + smt.get_node(NodeIndex::make(smt.depth(), 0)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 0)), "node 0 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - smt.get_node(&NodeIndex::new(smt.depth(), 1)), - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 1)), + smt.get_node(NodeIndex::make(smt.depth(), 1)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 1)), "node 1 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - smt.get_node(&NodeIndex::new(smt.depth(), 2)), - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 2)), + smt.get_node(NodeIndex::make(smt.depth(), 2)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 2)), "node 2 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - smt.get_node(&NodeIndex::new(smt.depth(), 3)), - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 3)), + smt.get_node(NodeIndex::make(smt.depth(), 3)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 3)), "node 3 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - smt.get_node(&NodeIndex::new(smt.depth(), 4)), - store.get_node(smt.root(), NodeIndex::new(smt.depth(), 4)), + smt.get_node(NodeIndex::make(smt.depth(), 4)), + store.get_node(smt.root(), NodeIndex::make(smt.depth(), 4)), "node 4 must be the same for both SparseMerkleTree and MerkleStore" ); // STORE MERKLE PATH MATCHS ============================================================== // assert the merkle path returned by the store is the same as the one in the tree let result = store - .get_path(smt.root(), NodeIndex::new(smt.depth(), 0)) + .get_path(smt.root(), NodeIndex::make(smt.depth(), 0)) .unwrap(); assert_eq!( LEAVES4[0], result.value, "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - smt.get_path(NodeIndex::new(smt.depth(), 0)), + smt.get_path(NodeIndex::make(smt.depth(), 0)), Ok(result.path), "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(smt.root(), NodeIndex::new(smt.depth(), 1)) + .get_path(smt.root(), NodeIndex::make(smt.depth(), 1)) .unwrap(); assert_eq!( LEAVES4[1], result.value, "Value for merkle path at index 1 must match leaf value" ); assert_eq!( - smt.get_path(NodeIndex::new(smt.depth(), 1)), + smt.get_path(NodeIndex::make(smt.depth(), 1)), Ok(result.path), "merkle path for index 1 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(smt.root(), NodeIndex::new(smt.depth(), 2)) + .get_path(smt.root(), NodeIndex::make(smt.depth(), 2)) .unwrap(); assert_eq!( LEAVES4[2], result.value, "Value for merkle path at index 2 must match leaf value" ); assert_eq!( - smt.get_path(NodeIndex::new(smt.depth(), 2)), + smt.get_path(NodeIndex::make(smt.depth(), 2)), Ok(result.path), "merkle path for index 2 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(smt.root(), NodeIndex::new(smt.depth(), 3)) + .get_path(smt.root(), NodeIndex::make(smt.depth(), 3)) .unwrap(); assert_eq!( LEAVES4[3], result.value, "Value for merkle path at index 3 must match leaf value" ); assert_eq!( - smt.get_path(NodeIndex::new(smt.depth(), 3)), + smt.get_path(NodeIndex::make(smt.depth(), 3)), Ok(result.path), "merkle path for index 3 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(smt.root(), NodeIndex::new(smt.depth(), 4)) + .get_path(smt.root(), NodeIndex::make(smt.depth(), 4)) .unwrap(); assert_eq!( EMPTY, result.value, "Value for merkle path at index 4 must match leaf value" ); assert_eq!( - smt.get_path(NodeIndex::new(smt.depth(), 4)), + smt.get_path(NodeIndex::make(smt.depth(), 4)), Ok(result.path), "merkle path for index 4 must be the same for the MerkleTree and MerkleStore" ); @@ -372,16 +372,16 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; let i0 = 0; - let p0 = mtree.get_path(NodeIndex::new(2, i0)).unwrap(); + let p0 = mtree.get_path(NodeIndex::make(2, i0)).unwrap(); let i1 = 1; - let p1 = mtree.get_path(NodeIndex::new(2, i1)).unwrap(); + let p1 = mtree.get_path(NodeIndex::make(2, i1)).unwrap(); let i2 = 2; - let p2 = mtree.get_path(NodeIndex::new(2, i2)).unwrap(); + let p2 = mtree.get_path(NodeIndex::make(2, i2)).unwrap(); let i3 = 3; - let p3 = mtree.get_path(NodeIndex::new(2, i3)).unwrap(); + let p3 = mtree.get_path(NodeIndex::make(2, i3)).unwrap(); let paths = [ (i0, LEAVES4[i0 as usize], p0), @@ -401,22 +401,22 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { // STORE LEAVES ARE CORRECT ============================================================== // checks the leaves in the store corresponds to the expected values assert_eq!( - store.get_node(set.root(), NodeIndex::new(set.depth(), 0)), + store.get_node(set.root(), NodeIndex::make(set.depth(), 0)), Ok(LEAVES4[0]), "node 0 must be in the set" ); assert_eq!( - store.get_node(set.root(), NodeIndex::new(set.depth(), 1)), + store.get_node(set.root(), NodeIndex::make(set.depth(), 1)), Ok(LEAVES4[1]), "node 1 must be in the set" ); assert_eq!( - store.get_node(set.root(), NodeIndex::new(set.depth(), 2)), + store.get_node(set.root(), NodeIndex::make(set.depth(), 2)), Ok(LEAVES4[2]), "node 2 must be in the set" ); assert_eq!( - store.get_node(set.root(), NodeIndex::new(set.depth(), 3)), + store.get_node(set.root(), NodeIndex::make(set.depth(), 3)), Ok(LEAVES4[3]), "node 3 must be in the set" ); @@ -424,76 +424,76 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> { // STORE LEAVES MATCH SET ================================================================ // sanity check the values returned by the store and the set assert_eq!( - set.get_node(NodeIndex::new(set.depth(), 0)), - store.get_node(set.root(), NodeIndex::new(set.depth(), 0)), + set.get_node(NodeIndex::make(set.depth(), 0)), + store.get_node(set.root(), NodeIndex::make(set.depth(), 0)), "node 0 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - set.get_node(NodeIndex::new(set.depth(), 1)), - store.get_node(set.root(), NodeIndex::new(set.depth(), 1)), + set.get_node(NodeIndex::make(set.depth(), 1)), + store.get_node(set.root(), NodeIndex::make(set.depth(), 1)), "node 1 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - set.get_node(NodeIndex::new(set.depth(), 2)), - store.get_node(set.root(), NodeIndex::new(set.depth(), 2)), + set.get_node(NodeIndex::make(set.depth(), 2)), + store.get_node(set.root(), NodeIndex::make(set.depth(), 2)), "node 2 must be the same for both SparseMerkleTree and MerkleStore" ); assert_eq!( - set.get_node(NodeIndex::new(set.depth(), 3)), - store.get_node(set.root(), NodeIndex::new(set.depth(), 3)), + set.get_node(NodeIndex::make(set.depth(), 3)), + store.get_node(set.root(), NodeIndex::make(set.depth(), 3)), "node 3 must be the same for both SparseMerkleTree and MerkleStore" ); // STORE MERKLE PATH MATCHS ============================================================== // assert the merkle path returned by the store is the same as the one in the set let result = store - .get_path(set.root(), NodeIndex::new(set.depth(), 0)) + .get_path(set.root(), NodeIndex::make(set.depth(), 0)) .unwrap(); assert_eq!( LEAVES4[0], result.value, "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - set.get_path(NodeIndex::new(set.depth(), 0)), + set.get_path(NodeIndex::make(set.depth(), 0)), Ok(result.path), "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(set.root(), NodeIndex::new(set.depth(), 1)) + .get_path(set.root(), NodeIndex::make(set.depth(), 1)) .unwrap(); assert_eq!( LEAVES4[1], result.value, "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - set.get_path(NodeIndex::new(set.depth(), 1)), + set.get_path(NodeIndex::make(set.depth(), 1)), Ok(result.path), "merkle path for index 1 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(set.root(), NodeIndex::new(set.depth(), 2)) + .get_path(set.root(), NodeIndex::make(set.depth(), 2)) .unwrap(); assert_eq!( LEAVES4[2], result.value, "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - set.get_path(NodeIndex::new(set.depth(), 2)), + set.get_path(NodeIndex::make(set.depth(), 2)), Ok(result.path), "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); let result = store - .get_path(set.root(), NodeIndex::new(set.depth(), 3)) + .get_path(set.root(), NodeIndex::make(set.depth(), 3)) .unwrap(); assert_eq!( LEAVES4[3], result.value, "Value for merkle path at index 0 must match leaf value" ); assert_eq!( - set.get_path(NodeIndex::new(set.depth(), 3)), + set.get_path(NodeIndex::make(set.depth(), 3)), Ok(result.path), "merkle path for index 0 must be the same for the MerkleTree and MerkleStore" ); @@ -550,7 +550,7 @@ fn store_path_opens_from_leaf() { .with_merkle_tree([a, b, c, d, e, f, g, h]) .unwrap(); let path = store - .get_path(root.into(), NodeIndex::new(3, 1)) + .get_path(root.into(), NodeIndex::make(3, 1)) .unwrap() .path; @@ -563,7 +563,7 @@ fn test_set_node() -> Result<(), MerkleError> { let mtree = MerkleTree::new(LEAVES4.to_vec())?; let mut store = MerkleStore::default().with_merkle_tree(LEAVES4)?; let value = int_to_node(42); - let index = NodeIndex::new(mtree.depth(), 0); + let index = NodeIndex::make(mtree.depth(), 0); let new_root = store.set_node(mtree.root(), index, value)?.root; assert_eq!( store.get_node(new_root, index), @@ -582,7 +582,7 @@ fn test_constructors() -> Result<(), MerkleError> { let depth = mtree.depth(); let leaves = 2u64.pow(depth.into()); for index in 0..leaves { - let index = NodeIndex::new(depth, index); + let index = NodeIndex::make(depth, index); let value_path = store.get_path(mtree.root(), index)?; assert_eq!(mtree.get_path(index)?, value_path.path); } @@ -597,34 +597,50 @@ fn test_constructors() -> Result<(), MerkleError> { let depth = smt.depth(); for key in KEYS4 { - let index = NodeIndex::new(depth, key); + let index = NodeIndex::make(depth, key); let value_path = store.get_path(smt.root(), index)?; assert_eq!(smt.get_path(index)?, value_path.path); } let d = 2; let paths = [ - (0, LEAVES4[0], mtree.get_path(NodeIndex::new(d, 0)).unwrap()), - (1, LEAVES4[1], mtree.get_path(NodeIndex::new(d, 1)).unwrap()), - (2, LEAVES4[2], mtree.get_path(NodeIndex::new(d, 2)).unwrap()), - (3, LEAVES4[3], mtree.get_path(NodeIndex::new(d, 3)).unwrap()), + ( + 0, + LEAVES4[0], + mtree.get_path(NodeIndex::make(d, 0)).unwrap(), + ), + ( + 1, + LEAVES4[1], + mtree.get_path(NodeIndex::make(d, 1)).unwrap(), + ), + ( + 2, + LEAVES4[2], + mtree.get_path(NodeIndex::make(d, 2)).unwrap(), + ), + ( + 3, + LEAVES4[3], + mtree.get_path(NodeIndex::make(d, 3)).unwrap(), + ), ]; let store1 = MerkleStore::default().with_merkle_paths(paths.clone())?; let store2 = MerkleStore::default() - .with_merkle_path(0, LEAVES4[0], mtree.get_path(NodeIndex::new(d, 0))?)? - .with_merkle_path(1, LEAVES4[1], mtree.get_path(NodeIndex::new(d, 1))?)? - .with_merkle_path(2, LEAVES4[2], mtree.get_path(NodeIndex::new(d, 2))?)? - .with_merkle_path(3, LEAVES4[3], mtree.get_path(NodeIndex::new(d, 3))?)?; + .with_merkle_path(0, LEAVES4[0], mtree.get_path(NodeIndex::make(d, 0))?)? + .with_merkle_path(1, LEAVES4[1], mtree.get_path(NodeIndex::make(d, 1))?)? + .with_merkle_path(2, LEAVES4[2], mtree.get_path(NodeIndex::make(d, 2))?)? + .with_merkle_path(3, LEAVES4[3], mtree.get_path(NodeIndex::make(d, 3))?)?; let set = MerklePathSet::new(d).with_paths(paths).unwrap(); for key in [0, 1, 2, 3] { - let index = NodeIndex::new(d, key); + let index = NodeIndex::make(d, key); let value_path1 = store1.get_path(set.root(), index)?; let value_path2 = store2.get_path(set.root(), index)?; assert_eq!(value_path1, value_path2); - let index = NodeIndex::new(d, key); + let index = NodeIndex::make(d, key); assert_eq!(set.get_path(index)?, value_path1.path); }