arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
Remove `ExactSizeIterator` constraint from `SimpleSmt::with_leaves()` (#228)

* Change InvalidNumEntries error

* max computation

* remove length check

* remove ExactSizeIterator constraint

* fix InvalidNumEntries error condition

* 2_usize
Philippe Laferrière plafer@protonmail.com
Tue, 28 Nov 2023 15:34:20 -0500
commit

d719cc26635fd56090081eb406482abeda54dfe3

parent

fa475d1929c33f45ef50d8d255f618eddeb4c5e6

3 files changed, 29 insertions(+), 31 deletions(-)

jump to
M src/merkle/error.rs → src/merkle/error.rs

@@ -14,7 +14,7 @@ DuplicateValuesForKey(RpoDigest),

InvalidIndex { depth: u8, value: u64 }, InvalidDepth { expected: u8, provided: u8 }, InvalidPath(MerklePath), - InvalidNumEntries(usize, usize), + InvalidNumEntries(usize), NodeNotInSet(NodeIndex), NodeNotInStore(RpoDigest, NodeIndex), NumLeavesNotPowerOfTwo(usize),

@@ -30,18 +30,18 @@ DepthTooSmall(depth) => write!(f, "the provided depth {depth} is too small"),

DepthTooBig(depth) => write!(f, "the provided depth {depth} is too big"), DuplicateValuesForIndex(key) => write!(f, "multiple values provided for key {key}"), DuplicateValuesForKey(key) => write!(f, "multiple values provided for key {key}"), - InvalidIndex{ depth, value} => write!( - f, - "the index value {value} is not valid for the depth {depth}" - ), - InvalidDepth { expected, provided } => write!( - f, - "the provided depth {provided} is not valid for {expected}" - ), + InvalidIndex { depth, value } => { + write!(f, "the index value {value} is not valid for the depth {depth}") + } + InvalidDepth { expected, provided } => { + write!(f, "the provided depth {provided} is not valid for {expected}") + } InvalidPath(_path) => write!(f, "the provided path is not valid"), - InvalidNumEntries(max, provided) => write!(f, "the provided number of entries is {provided}, but the maximum for the given depth is {max}"), + InvalidNumEntries(max) => write!(f, "number of entries exceeded the maximum: {max}"), NodeNotInSet(index) => write!(f, "the node with index ({index}) is not in the set"), - NodeNotInStore(hash, index) => write!(f, "the node {hash:?} with index ({index}) is not in the store"), + NodeNotInStore(hash, index) => { + write!(f, "the node {hash:?} with index ({index}) is not in the store") + } NumLeavesNotPowerOfTwo(leaves) => { write!(f, "the leaves count {leaves} is not a power of 2") }
M src/merkle/partial_mt/mod.rs → src/merkle/partial_mt/mod.rs

@@ -109,9 +109,9 @@ }

// check if the number of leaves can be accommodated by the tree's depth; we use a min // depth of 63 because we consider passing in a vector of size 2^64 infeasible. - let max = (1_u64 << 63) as usize; + let max = 2usize.pow(63); if layers.len() > max { - return Err(MerkleError::InvalidNumEntries(max, layers.len())); + return Err(MerkleError::InvalidNumEntries(max)); } // Get maximum depth
M src/merkle/simple_smt/mod.rs → src/merkle/simple_smt/mod.rs

@@ -71,27 +71,26 @@ /// Returns an error if:

/// - If the depth is 0 or is greater than 64. /// - The number of entries exceeds the maximum tree capacity, that is 2^{depth}. /// - The provided entries contain multiple values for the same key. - pub fn with_leaves<R, I>(depth: u8, entries: R) -> Result<Self, MerkleError> - where - R: IntoIterator<IntoIter = I>, - I: Iterator<Item = (u64, Word)> + ExactSizeIterator, - { + pub fn with_leaves( + depth: u8, + entries: impl IntoIterator<Item = (u64, Word)>, + ) -> Result<Self, MerkleError> { // create an empty tree let mut tree = Self::new(depth)?; - // check if the number of leaves can be accommodated by the tree's depth; we use a min - // depth of 63 because we consider passing in a vector of size 2^64 infeasible. - let entries = entries.into_iter(); - let max = 1 << tree.depth.min(63); - if entries.len() > max { - return Err(MerkleError::InvalidNumEntries(max, entries.len())); - } + // compute the max number of entries. We use an upper bound of depth 63 because we consider + // passing in a vector of size 2^64 infeasible. + let max_num_entries = 2_usize.pow(tree.depth.min(63).into()); // This being a sparse data structure, the EMPTY_WORD is not assigned to the `BTreeMap`, so // entries with the empty value need additional tracking. let mut key_set_to_zero = BTreeSet::new(); - for (key, value) in entries { + for (idx, (key, value)) in entries.into_iter().enumerate() { + if idx >= max_num_entries { + return Err(MerkleError::InvalidNumEntries(max_num_entries)); + } + let old_value = tree.update_leaf(key, value)?; if old_value != Self::EMPTY_VALUE || key_set_to_zero.contains(&key) {

@@ -107,11 +106,10 @@ }

/// Wrapper around [`SimpleSmt::with_leaves`] which inserts leaves at contiguous indices /// starting at index 0. - pub fn with_contiguous_leaves<R, I>(depth: u8, entries: R) -> Result<Self, MerkleError> - where - R: IntoIterator<IntoIter = I>, - I: Iterator<Item = Word> + ExactSizeIterator, - { + pub fn with_contiguous_leaves( + depth: u8, + entries: impl IntoIterator<Item = Word>, + ) -> Result<Self, MerkleError> { Self::with_leaves( depth, entries