4 Commits

Author SHA1 Message Date
Bobbin Threadbare
da67f8c7e5 chore: increment doc version to v0.9.1 2024-04-02 13:07:02 -07:00
Bobbin Threadbare
9454e1a8ae chore: increment crate version to v0.9.1 2024-04-02 13:02:38 -07:00
Bobbin Threadbare
4bf087daf8 fix: decrement leaf count in simple SMT when inserting empty value (#303) 2024-04-02 13:01:00 -07:00
polydez
b4dc373925 feat: add leaf count to SimpleSmt (#302) 2024-04-02 12:07:00 -07:00
5 changed files with 60 additions and 32 deletions

View File

@@ -1,3 +1,7 @@
## 0.9.1 (2024-04-02)
* Added `num_leaves()` method to `SimpleSmt` (#302).
## 0.9.0 (2024-03-24) ## 0.9.0 (2024-03-24)
* [BREAKING] Removed deprecated re-exports from liballoc/libstd (#290). * [BREAKING] Removed deprecated re-exports from liballoc/libstd (#290).

46
Cargo.lock generated
View File

@@ -79,9 +79,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]] [[package]]
name = "bit-set" name = "bit-set"
@@ -183,9 +183,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.3" version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@@ -205,9 +205,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.3" version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@@ -347,9 +347,9 @@ dependencies = [
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.0.1" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
[[package]] [[package]]
name = "fnv" name = "fnv"
@@ -436,9 +436,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.10" version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]] [[package]]
name = "jobserver" name = "jobserver"
@@ -499,13 +499,13 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.1" version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]] [[package]]
name = "miden-crypto" name = "miden-crypto"
version = "0.9.0" version = "0.9.1"
dependencies = [ dependencies = [
"blake3", "blake3",
"cc", "cc",
@@ -736,9 +736,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [ dependencies = [
"either", "either",
"rayon-core", "rayon-core",
@@ -779,9 +779,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "rustix" name = "rustix"
@@ -851,9 +851,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.114" version = "1.0.115"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@@ -878,9 +878,9 @@ checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.53" version = "2.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -1139,9 +1139,9 @@ dependencies = [
[[package]] [[package]]
name = "winter-math" name = "winter-math"
version = "0.8.3" version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c91111b368b08c5a76009514e9b6d26af41fbb28604ea77a249282323b64d5" checksum = "9c36d2a04b4f79f2c8c6945aab6545b7310a0cd6ae47b9210750400df6775a04"
dependencies = [ dependencies = [
"serde", "serde",
"winter-utils", "winter-utils",

View File

@@ -1,12 +1,12 @@
[package] [package]
name = "miden-crypto" name = "miden-crypto"
version = "0.9.0" version = "0.9.1"
description = "Miden Cryptographic primitives" description = "Miden Cryptographic primitives"
authors = ["miden contributors"] authors = ["miden contributors"]
readme = "README.md" readme = "README.md"
license = "MIT" license = "MIT"
repository = "https://github.com/0xPolygonMiden/crypto" repository = "https://github.com/0xPolygonMiden/crypto"
documentation = "https://docs.rs/miden-crypto/0.9.0" documentation = "https://docs.rs/miden-crypto/0.9.1"
categories = ["cryptography", "no-std"] categories = ["cryptography", "no-std"]
keywords = ["miden", "crypto", "hash", "merkle"] keywords = ["miden", "crypto", "hash", "merkle"]
edition = "2021" edition = "2021"
@@ -49,7 +49,7 @@ std = [
blake3 = { version = "1.5", default-features = false } blake3 = { version = "1.5", default-features = false }
clap = { version = "4.5", optional = true, features = ["derive"] } clap = { version = "4.5", optional = true, features = ["derive"] }
num = { version = "0.4", default-features = false, features = ["alloc", "libm"] } num = { version = "0.4", default-features = false, features = ["alloc", "libm"] }
num-complex = { version = "0.4.4", default-features = false } num-complex = { version = "0.4", default-features = false }
rand = { version = "0.8", default-features = false } rand = { version = "0.8", default-features = false }
rand_core = { version = "0.6", default-features = false } rand_core = { version = "0.6", default-features = false }
rand-utils = { version = "0.8", package = "winter-rand-utils", optional = true } rand-utils = { version = "0.8", package = "winter-rand-utils", optional = true }

View File

@@ -122,6 +122,11 @@ impl<const DEPTH: u8> SimpleSmt<DEPTH> {
<Self as SparseMerkleTree<DEPTH>>::root(self) <Self as SparseMerkleTree<DEPTH>>::root(self)
} }
/// Returns the number of non-empty leaves in this tree.
pub fn num_leaves(&self) -> usize {
self.leaves.len()
}
/// Returns the leaf at the specified index. /// Returns the leaf at the specified index.
pub fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word { pub fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word {
<Self as SparseMerkleTree<DEPTH>>::get_leaf(self, key) <Self as SparseMerkleTree<DEPTH>>::get_leaf(self, key)
@@ -276,17 +281,18 @@ impl<const DEPTH: u8> SparseMerkleTree<DEPTH> for SimpleSmt<DEPTH> {
} }
fn insert_value(&mut self, key: LeafIndex<DEPTH>, value: Word) -> Option<Word> { fn insert_value(&mut self, key: LeafIndex<DEPTH>, value: Word) -> Option<Word> {
self.leaves.insert(key.value(), value) if value == Self::EMPTY_VALUE {
self.leaves.remove(&key.value())
} else {
self.leaves.insert(key.value(), value)
}
} }
fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word { fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word {
// the lookup in empty_hashes could fail only if empty_hashes were not built correctly
// by the constructor as we check the depth of the lookup above.
let leaf_pos = key.value(); let leaf_pos = key.value();
match self.leaves.get(&leaf_pos) { match self.leaves.get(&leaf_pos) {
Some(word) => *word, Some(word) => *word,
None => Word::from(*EmptySubtreeRoots::entry(DEPTH, DEPTH)), None => Self::EMPTY_VALUE,
} }
} }

View File

@@ -50,6 +50,8 @@ fn build_sparse_tree() {
let mut smt = SimpleSmt::<DEPTH>::new().unwrap(); let mut smt = SimpleSmt::<DEPTH>::new().unwrap();
let mut values = ZERO_VALUES8.to_vec(); let mut values = ZERO_VALUES8.to_vec();
assert_eq!(smt.num_leaves(), 0);
// insert single value // insert single value
let key = 6; let key = 6;
let new_node = int_to_leaf(7); let new_node = int_to_leaf(7);
@@ -62,6 +64,7 @@ fn build_sparse_tree() {
smt.open(&LeafIndex::<3>::new(6).unwrap()).path smt.open(&LeafIndex::<3>::new(6).unwrap()).path
); );
assert_eq!(old_value, EMPTY_WORD); assert_eq!(old_value, EMPTY_WORD);
assert_eq!(smt.num_leaves(), 1);
// insert second value at distinct leaf branch // insert second value at distinct leaf branch
let key = 2; let key = 2;
@@ -75,6 +78,7 @@ fn build_sparse_tree() {
smt.open(&LeafIndex::<3>::new(2).unwrap()).path smt.open(&LeafIndex::<3>::new(2).unwrap()).path
); );
assert_eq!(old_value, EMPTY_WORD); assert_eq!(old_value, EMPTY_WORD);
assert_eq!(smt.num_leaves(), 2);
} }
/// Tests that [`SimpleSmt::with_contiguous_leaves`] works as expected /// Tests that [`SimpleSmt::with_contiguous_leaves`] works as expected
@@ -146,10 +150,11 @@ fn test_inner_node_iterator() -> Result<(), MerkleError> {
} }
#[test] #[test]
fn update_leaf() { fn test_insert() {
const DEPTH: u8 = 3; const DEPTH: u8 = 3;
let mut tree = let mut tree =
SimpleSmt::<DEPTH>::with_leaves(KEYS8.into_iter().zip(digests_to_words(&VALUES8))).unwrap(); SimpleSmt::<DEPTH>::with_leaves(KEYS8.into_iter().zip(digests_to_words(&VALUES8))).unwrap();
assert_eq!(tree.num_leaves(), 8);
// update one value // update one value
let key = 3; let key = 3;
@@ -161,6 +166,7 @@ fn update_leaf() {
let old_leaf = tree.insert(LeafIndex::<DEPTH>::new(key as u64).unwrap(), new_node); let old_leaf = tree.insert(LeafIndex::<DEPTH>::new(key as u64).unwrap(), new_node);
assert_eq!(expected_tree.root(), tree.root); assert_eq!(expected_tree.root(), tree.root);
assert_eq!(old_leaf, *VALUES8[key]); assert_eq!(old_leaf, *VALUES8[key]);
assert_eq!(tree.num_leaves(), 8);
// update another value // update another value
let key = 6; let key = 6;
@@ -171,6 +177,18 @@ fn update_leaf() {
let old_leaf = tree.insert(LeafIndex::<DEPTH>::new(key as u64).unwrap(), new_node); let old_leaf = tree.insert(LeafIndex::<DEPTH>::new(key as u64).unwrap(), new_node);
assert_eq!(expected_tree.root(), tree.root); assert_eq!(expected_tree.root(), tree.root);
assert_eq!(old_leaf, *VALUES8[key]); assert_eq!(old_leaf, *VALUES8[key]);
assert_eq!(tree.num_leaves(), 8);
// set a leaf to empty value
let key = 5;
let new_node = EMPTY_WORD;
expected_values[key] = new_node;
let expected_tree = MerkleTree::new(expected_values.clone()).unwrap();
let old_leaf = tree.insert(LeafIndex::<DEPTH>::new(key as u64).unwrap(), new_node);
assert_eq!(expected_tree.root(), tree.root);
assert_eq!(old_leaf, *VALUES8[key]);
assert_eq!(tree.num_leaves(), 7);
} }
#[test] #[test]