Skip to content

Commit

Permalink
Remove ExactSizeIterator constraint from SimpleSmt::with_leaves() (
Browse files Browse the repository at this point in the history
…#228)

* Change InvalidNumEntries error

* max computation

* remove length check

* remove ExactSizeIterator constraint

* fix InvalidNumEntries error condition

* 2_usize
  • Loading branch information
plafer authored and bobbinth committed Dec 21, 2023
1 parent 223fbf8 commit 81a94ec
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 31 deletions.
22 changes: 11 additions & 11 deletions src/merkle/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub enum MerkleError {
InvalidIndex { depth: u8, value: u64 },
InvalidDepth { expected: u8, provided: u8 },
InvalidPath(MerklePath),
InvalidNumEntries(usize, usize),
InvalidNumEntries(usize),
NodeNotInSet(NodeIndex),
NodeNotInStore(RpoDigest, NodeIndex),
NumLeavesNotPowerOfTwo(usize),
Expand All @@ -30,18 +30,18 @@ impl fmt::Display for MerkleError {
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")
}
Expand Down
4 changes: 2 additions & 2 deletions src/merkle/partial_mt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ impl PartialMerkleTree {

// 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
Expand Down
34 changes: 16 additions & 18 deletions src/merkle/simple_smt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,27 +71,26 @@ impl SimpleSmt {
/// - 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) {
Expand All @@ -107,11 +106,10 @@ impl SimpleSmt {

/// 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
Expand Down

0 comments on commit 81a94ec

Please sign in to comment.