make from_iter_with_depth private, make sure iterators in tests have the same length
This commit is contained in:
parent
b284b4c556
commit
262c896ad3
3 changed files with 58 additions and 44 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -254,7 +254,7 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"criterion-plot",
|
"criterion-plot",
|
||||||
"is-terminal",
|
"is-terminal",
|
||||||
"itertools",
|
"itertools 0.10.5",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"oorandom",
|
"oorandom",
|
||||||
|
@ -275,7 +275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cast",
|
"cast",
|
||||||
"itertools",
|
"itertools 0.10.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -453,6 +453,15 @@ dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
|
@ -524,6 +533,7 @@ dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"hex",
|
"hex",
|
||||||
|
"itertools 0.14.0",
|
||||||
"num",
|
"num",
|
||||||
"num-complex",
|
"num-complex",
|
||||||
"proptest",
|
"proptest",
|
||||||
|
|
|
@ -83,6 +83,7 @@ assert_matches = { version = "1.5", default-features = false }
|
||||||
criterion = { version = "0.5", features = ["html_reports"] }
|
criterion = { version = "0.5", features = ["html_reports"] }
|
||||||
getrandom = { version = "0.3", default-features = false }
|
getrandom = { version = "0.3", default-features = false }
|
||||||
hex = { version = "0.4", default-features = false, features = ["alloc"] }
|
hex = { version = "0.4", default-features = false, features = ["alloc"] }
|
||||||
|
itertools = { version = "0.14.0" }
|
||||||
proptest = { version = "1.6", default-features = false, features = ["alloc"]}
|
proptest = { version = "1.6", default-features = false, features = ["alloc"]}
|
||||||
rand_chacha = { version = "0.9", default-features = false }
|
rand_chacha = { version = "0.9", default-features = false }
|
||||||
rand-utils = { version = "0.12", package = "winter-rand-utils" }
|
rand-utils = { version = "0.12", package = "winter-rand-utils" }
|
||||||
|
|
|
@ -36,8 +36,7 @@ impl SparseMerklePath {
|
||||||
/// of deepest to shallowest.
|
/// of deepest to shallowest.
|
||||||
///
|
///
|
||||||
/// Knowing the size is necessary to calculate the depth of the tree, which is needed to detect
|
/// Knowing the size is necessary to calculate the depth of the tree, which is needed to detect
|
||||||
/// which nodes are empty nodes. If you know the size but your iterator type is not
|
/// which nodes are empty nodes.
|
||||||
/// [ExactSizeIterator], use [`SparseMerklePath::from_iter_with_depth()`].
|
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// Returns [MerkleError::DepthTooBig] if `tree_depth` is greater than [SMT_MAX_DEPTH].
|
/// Returns [MerkleError::DepthTooBig] if `tree_depth` is greater than [SMT_MAX_DEPTH].
|
||||||
|
@ -51,35 +50,6 @@ impl SparseMerklePath {
|
||||||
Self::from_iter_with_depth(iterator.len() as u8, iterator)
|
Self::from_iter_with_depth(iterator.len() as u8, iterator)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a sparse Merkle path from a manually specified tree depth, and an iterator over
|
|
||||||
/// Merkle nodes from deepest to shallowest.
|
|
||||||
///
|
|
||||||
/// Knowing the size is necessary to calculate the depth of the tree, which is needed to detect
|
|
||||||
/// which nodes are empty nodes.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// Returns [MerkleError::DepthTooBig] if `tree_depth` is greater than [SMT_MAX_DEPTH].
|
|
||||||
pub fn from_iter_with_depth(
|
|
||||||
tree_depth: u8,
|
|
||||||
iter: impl IntoIterator<Item = RpoDigest>,
|
|
||||||
) -> Result<Self, MerkleError> {
|
|
||||||
if tree_depth > SMT_MAX_DEPTH {
|
|
||||||
return Err(MerkleError::DepthTooBig(tree_depth as u64));
|
|
||||||
}
|
|
||||||
|
|
||||||
let path: Self = iter::zip(path_depth_iter(tree_depth), iter)
|
|
||||||
.map(|(depth, node)| {
|
|
||||||
let &equivalent_empty_node = EmptySubtreeRoots::entry(tree_depth, depth.get());
|
|
||||||
let is_empty = node == equivalent_empty_node;
|
|
||||||
let node = if is_empty { None } else { Some(node) };
|
|
||||||
|
|
||||||
(depth, node)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the total depth of this path, i.e., the number of nodes this path represents.
|
/// Returns the total depth of this path, i.e., the number of nodes this path represents.
|
||||||
pub fn depth(&self) -> u8 {
|
pub fn depth(&self) -> u8 {
|
||||||
(self.nodes.len() + self.empty_nodes_mask.count_ones() as usize) as u8
|
(self.nodes.len() + self.empty_nodes_mask.count_ones() as usize) as u8
|
||||||
|
@ -159,6 +129,37 @@ impl SparseMerklePath {
|
||||||
// PRIVATE HELPERS
|
// PRIVATE HELPERS
|
||||||
// ============================================================================================
|
// ============================================================================================
|
||||||
|
|
||||||
|
/// Constructs a sparse Merkle path from a manually specified tree depth, and an iterator over
|
||||||
|
/// Merkle nodes from deepest to shallowest.
|
||||||
|
///
|
||||||
|
/// Knowing the size is necessary to calculate the depth of the tree, which is needed to detect
|
||||||
|
/// which nodes are empty nodes.
|
||||||
|
///
|
||||||
|
/// Warning: this method does not check if the iterator contained more elements.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Returns [MerkleError::DepthTooBig] if `tree_depth` is greater than [SMT_MAX_DEPTH].
|
||||||
|
fn from_iter_with_depth(
|
||||||
|
tree_depth: u8,
|
||||||
|
iter: impl IntoIterator<Item = RpoDigest>,
|
||||||
|
) -> Result<Self, MerkleError> {
|
||||||
|
if tree_depth > SMT_MAX_DEPTH {
|
||||||
|
return Err(MerkleError::DepthTooBig(tree_depth as u64));
|
||||||
|
}
|
||||||
|
|
||||||
|
let path: Self = iter::zip(path_depth_iter(tree_depth), iter)
|
||||||
|
.map(|(depth, node)| {
|
||||||
|
let &equivalent_empty_node = EmptySubtreeRoots::entry(tree_depth, depth.get());
|
||||||
|
let is_empty = node == equivalent_empty_node;
|
||||||
|
let node = if is_empty { None } else { Some(node) };
|
||||||
|
|
||||||
|
(depth, node)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(path)
|
||||||
|
}
|
||||||
|
|
||||||
const fn bitmask_for_depth(node_depth: NonZero<u8>) -> u64 {
|
const fn bitmask_for_depth(node_depth: NonZero<u8>) -> u64 {
|
||||||
// - 1 because paths do not include the root.
|
// - 1 because paths do not include the root.
|
||||||
1 << (node_depth.get() - 1)
|
1 << (node_depth.get() - 1)
|
||||||
|
@ -477,7 +478,7 @@ fn path_depth_iter(tree_depth: u8) -> impl ExactSizeIterator<Item = NonZero<u8>>
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::{iter, num::NonZero};
|
use core::num::NonZero;
|
||||||
|
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
|
|
||||||
|
@ -725,25 +726,25 @@ mod tests {
|
||||||
let index = NodeIndex::from(Smt::key_to_leaf_index(key));
|
let index = NodeIndex::from(Smt::key_to_leaf_index(key));
|
||||||
|
|
||||||
let control_path = tree.get_path(key);
|
let control_path = tree.get_path(key);
|
||||||
for (i, (&control_node, proof_index)) in
|
for (&control_node, proof_index) in
|
||||||
iter::zip(&*control_path, index.proof_indices()).enumerate()
|
itertools::zip_eq(&*control_path, index.proof_indices())
|
||||||
{
|
{
|
||||||
let proof_node = tree.get_hash(proof_index);
|
let proof_node = tree.get_hash(proof_index);
|
||||||
assert_eq!(control_node, proof_node, "on iteration {i}");
|
assert_eq!(control_node, proof_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sparse_path =
|
let sparse_path =
|
||||||
SparseMerklePath::from_sized_iter(control_path.clone().into_iter()).unwrap();
|
SparseMerklePath::from_sized_iter(control_path.clone().into_iter()).unwrap();
|
||||||
for (i, (sparse_node, proof_idx)) in
|
for (sparse_node, proof_idx) in
|
||||||
iter::zip(sparse_path.clone(), index.proof_indices()).enumerate()
|
itertools::zip_eq(sparse_path.clone(), index.proof_indices())
|
||||||
{
|
{
|
||||||
let proof_node = tree.get_hash(proof_idx);
|
let proof_node = tree.get_hash(proof_idx);
|
||||||
assert_eq!(sparse_node, proof_node, "on iteration {i}");
|
assert_eq!(sparse_node, proof_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(control_path.depth(), sparse_path.depth());
|
assert_eq!(control_path.depth(), sparse_path.depth());
|
||||||
for (i, (control, sparse)) in iter::zip(control_path, sparse_path).enumerate() {
|
for (control, sparse) in itertools::zip_eq(control_path, sparse_path) {
|
||||||
assert_eq!(control, sparse, "on iteration {i}");
|
assert_eq!(control, sparse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -788,7 +789,9 @@ mod tests {
|
||||||
|
|
||||||
// Test that both iterators yield the same amount of the same values.
|
// Test that both iterators yield the same amount of the same values.
|
||||||
let mut count: u64 = 0;
|
let mut count: u64 = 0;
|
||||||
for (&control_node, sparse_node) in iter::zip(control_path.iter(), sparse_path.iter()) {
|
for (&control_node, sparse_node) in
|
||||||
|
itertools::zip_eq(control_path.iter(), sparse_path.iter())
|
||||||
|
{
|
||||||
count += 1;
|
count += 1;
|
||||||
assert_eq!(control_node, sparse_node);
|
assert_eq!(control_node, sparse_node);
|
||||||
}
|
}
|
||||||
|
@ -809,7 +812,7 @@ mod tests {
|
||||||
|
|
||||||
// Test that both iterators yield the same amount of the same values.
|
// Test that both iterators yield the same amount of the same values.
|
||||||
let mut count: u64 = 0;
|
let mut count: u64 = 0;
|
||||||
for (control_node, sparse_node) in iter::zip(control_path, sparse_path) {
|
for (control_node, sparse_node) in itertools::zip_eq(control_path, sparse_path) {
|
||||||
count += 1;
|
count += 1;
|
||||||
assert_eq!(control_node, sparse_node);
|
assert_eq!(control_node, sparse_node);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue