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
This commit is contained in:
parent
fa475d1929
commit
d719cc2663
3 changed files with 29 additions and 31 deletions
|
@ -14,7 +14,7 @@ pub enum MerkleError {
|
||||||
InvalidIndex { depth: u8, value: u64 },
|
InvalidIndex { depth: u8, value: u64 },
|
||||||
InvalidDepth { expected: u8, provided: u8 },
|
InvalidDepth { expected: u8, provided: u8 },
|
||||||
InvalidPath(MerklePath),
|
InvalidPath(MerklePath),
|
||||||
InvalidNumEntries(usize, usize),
|
InvalidNumEntries(usize),
|
||||||
NodeNotInSet(NodeIndex),
|
NodeNotInSet(NodeIndex),
|
||||||
NodeNotInStore(RpoDigest, NodeIndex),
|
NodeNotInStore(RpoDigest, NodeIndex),
|
||||||
NumLeavesNotPowerOfTwo(usize),
|
NumLeavesNotPowerOfTwo(usize),
|
||||||
|
@ -30,18 +30,18 @@ impl fmt::Display for MerkleError {
|
||||||
DepthTooBig(depth) => write!(f, "the provided depth {depth} is too big"),
|
DepthTooBig(depth) => write!(f, "the provided depth {depth} is too big"),
|
||||||
DuplicateValuesForIndex(key) => write!(f, "multiple values provided for key {key}"),
|
DuplicateValuesForIndex(key) => write!(f, "multiple values provided for key {key}"),
|
||||||
DuplicateValuesForKey(key) => write!(f, "multiple values provided for key {key}"),
|
DuplicateValuesForKey(key) => write!(f, "multiple values provided for key {key}"),
|
||||||
InvalidIndex{ depth, value} => write!(
|
InvalidIndex { depth, value } => {
|
||||||
f,
|
write!(f, "the index value {value} is not valid for the depth {depth}")
|
||||||
"the index value {value} is not valid for the depth {depth}"
|
}
|
||||||
),
|
InvalidDepth { expected, provided } => {
|
||||||
InvalidDepth { expected, provided } => write!(
|
write!(f, "the provided depth {provided} is not valid for {expected}")
|
||||||
f,
|
}
|
||||||
"the provided depth {provided} is not valid for {expected}"
|
|
||||||
),
|
|
||||||
InvalidPath(_path) => write!(f, "the provided path is not valid"),
|
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"),
|
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) => {
|
NumLeavesNotPowerOfTwo(leaves) => {
|
||||||
write!(f, "the leaves count {leaves} is not a power of 2")
|
write!(f, "the leaves count {leaves} is not a power of 2")
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,9 +109,9 @@ impl PartialMerkleTree {
|
||||||
|
|
||||||
// check if the number of leaves can be accommodated by the tree's depth; we use a min
|
// 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.
|
// 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 {
|
if layers.len() > max {
|
||||||
return Err(MerkleError::InvalidNumEntries(max, layers.len()));
|
return Err(MerkleError::InvalidNumEntries(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get maximum depth
|
// Get maximum depth
|
||||||
|
|
|
@ -71,27 +71,26 @@ impl SimpleSmt {
|
||||||
/// - If the depth is 0 or is greater than 64.
|
/// - If the depth is 0 or is greater than 64.
|
||||||
/// - The number of entries exceeds the maximum tree capacity, that is 2^{depth}.
|
/// - The number of entries exceeds the maximum tree capacity, that is 2^{depth}.
|
||||||
/// - The provided entries contain multiple values for the same key.
|
/// - The provided entries contain multiple values for the same key.
|
||||||
pub fn with_leaves<R, I>(depth: u8, entries: R) -> Result<Self, MerkleError>
|
pub fn with_leaves(
|
||||||
where
|
depth: u8,
|
||||||
R: IntoIterator<IntoIter = I>,
|
entries: impl IntoIterator<Item = (u64, Word)>,
|
||||||
I: Iterator<Item = (u64, Word)> + ExactSizeIterator,
|
) -> Result<Self, MerkleError> {
|
||||||
{
|
|
||||||
// create an empty tree
|
// create an empty tree
|
||||||
let mut tree = Self::new(depth)?;
|
let mut tree = Self::new(depth)?;
|
||||||
|
|
||||||
// check if the number of leaves can be accommodated by the tree's depth; we use a min
|
// compute the max number of entries. We use an upper bound of depth 63 because we consider
|
||||||
// depth of 63 because we consider passing in a vector of size 2^64 infeasible.
|
// passing in a vector of size 2^64 infeasible.
|
||||||
let entries = entries.into_iter();
|
let max_num_entries = 2_usize.pow(tree.depth.min(63).into());
|
||||||
let max = 1 << tree.depth.min(63);
|
|
||||||
if entries.len() > max {
|
|
||||||
return Err(MerkleError::InvalidNumEntries(max, entries.len()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// This being a sparse data structure, the EMPTY_WORD is not assigned to the `BTreeMap`, so
|
// This being a sparse data structure, the EMPTY_WORD is not assigned to the `BTreeMap`, so
|
||||||
// entries with the empty value need additional tracking.
|
// entries with the empty value need additional tracking.
|
||||||
let mut key_set_to_zero = BTreeSet::new();
|
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)?;
|
let old_value = tree.update_leaf(key, value)?;
|
||||||
|
|
||||||
if old_value != Self::EMPTY_VALUE || key_set_to_zero.contains(&key) {
|
if old_value != Self::EMPTY_VALUE || key_set_to_zero.contains(&key) {
|
||||||
|
@ -107,11 +106,10 @@ impl SimpleSmt {
|
||||||
|
|
||||||
/// Wrapper around [`SimpleSmt::with_leaves`] which inserts leaves at contiguous indices
|
/// Wrapper around [`SimpleSmt::with_leaves`] which inserts leaves at contiguous indices
|
||||||
/// starting at index 0.
|
/// starting at index 0.
|
||||||
pub fn with_contiguous_leaves<R, I>(depth: u8, entries: R) -> Result<Self, MerkleError>
|
pub fn with_contiguous_leaves(
|
||||||
where
|
depth: u8,
|
||||||
R: IntoIterator<IntoIter = I>,
|
entries: impl IntoIterator<Item = Word>,
|
||||||
I: Iterator<Item = Word> + ExactSizeIterator,
|
) -> Result<Self, MerkleError> {
|
||||||
{
|
|
||||||
Self::with_leaves(
|
Self::with_leaves(
|
||||||
depth,
|
depth,
|
||||||
entries
|
entries
|
||||||
|
|
Loading…
Add table
Reference in a new issue