Skip to content

Commit

Permalink
Merge pull request #140 from 0xPolygonMiden/next
Browse files Browse the repository at this point in the history
Tracking PR for v0.5 release
  • Loading branch information
bobbinth authored May 26, 2023
2 parents 09025b4 + dcda57f commit daa27f4
Show file tree
Hide file tree
Showing 18 changed files with 1,472 additions and 364 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 0.5.0 (2023-05-26)
* Implemented `TieredSmt` (#152, #153).
* Implemented ability to extract a subset of a `MerkleStore` (#151).
* Cleaned up `SimpleSmt` interface (#149).
* Decoupled hashing and padding of peaks in `Mmr` (#148).
* Added `inner_nodes()` to `MerkleStore` (#146).

## 0.4.0 (2023-04-21)

- Exported `MmrProof` from the crate (#137).
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[package]
name = "miden-crypto"
version = "0.4.0"
version = "0.5.0"
description = "Miden Cryptographic primitives"
authors = ["miden contributors"]
readme = "README.md"
license = "MIT"
repository = "https://github.com/0xPolygonMiden/crypto"
documentation = "https://docs.rs/miden-crypto/0.4.0"
documentation = "https://docs.rs/miden-crypto/0.5.0"
categories = ["cryptography", "no-std"]
keywords = ["miden", "crypto", "hash", "merkle"]
edition = "2021"
Expand Down Expand Up @@ -35,6 +35,6 @@ winter_math = { version = "0.6", package = "winter-math", default-features = fal
winter_utils = { version = "0.6", package = "winter-utils", default-features = false }

[dev-dependencies]
criterion = { version = "0.4", features = ["html_reports"] }
criterion = { version = "0.5", features = ["html_reports"] }
proptest = "1.1.0"
rand_utils = { version = "0.6", package = "winter-rand-utils" }
14 changes: 6 additions & 8 deletions benches/smt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ fn smt_rpo(c: &mut Criterion) {
(i, word)
})
.collect();
let tree = SimpleSmt::new(depth).unwrap().with_leaves(entries).unwrap();
trees.push(tree);
let tree = SimpleSmt::with_leaves(depth, entries).unwrap();
trees.push((tree, count));
}
}

Expand All @@ -29,10 +29,9 @@ fn smt_rpo(c: &mut Criterion) {

let mut insert = c.benchmark_group(format!("smt update_leaf"));

for tree in trees.iter_mut() {
for (tree, count) in trees.iter_mut() {
let depth = tree.depth();
let count = tree.leaves_count() as u64;
let key = count >> 2;
let key = *count >> 2;
insert.bench_with_input(
format!("simple smt(depth:{depth},count:{count})"),
&(key, leaf),
Expand All @@ -48,10 +47,9 @@ fn smt_rpo(c: &mut Criterion) {

let mut path = c.benchmark_group(format!("smt get_leaf_path"));

for tree in trees.iter_mut() {
for (tree, count) in trees.iter_mut() {
let depth = tree.depth();
let count = tree.leaves_count() as u64;
let key = count >> 2;
let key = *count >> 2;
path.bench_with_input(
format!("simple smt(depth:{depth},count:{count})"),
&key,
Expand Down
24 changes: 6 additions & 18 deletions benches/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,7 @@ fn get_leaf_simplesmt(c: &mut Criterion) {
.enumerate()
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
.collect::<Vec<(u64, Word)>>();
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
.unwrap()
.with_leaves(smt_leaves.clone())
.unwrap();
let smt = SimpleSmt::with_leaves(SimpleSmt::MAX_DEPTH, smt_leaves.clone()).unwrap();
let store = MerkleStore::from(&smt);
let depth = smt.depth();
let root = smt.root();
Expand Down Expand Up @@ -215,10 +212,7 @@ fn get_node_simplesmt(c: &mut Criterion) {
.enumerate()
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
.collect::<Vec<(u64, Word)>>();
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
.unwrap()
.with_leaves(smt_leaves.clone())
.unwrap();
let smt = SimpleSmt::with_leaves(SimpleSmt::MAX_DEPTH, smt_leaves.clone()).unwrap();
let store = MerkleStore::from(&smt);
let root = smt.root();
let half_depth = smt.depth() / 2;
Expand Down Expand Up @@ -292,10 +286,7 @@ fn get_leaf_path_simplesmt(c: &mut Criterion) {
.enumerate()
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
.collect::<Vec<(u64, Word)>>();
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
.unwrap()
.with_leaves(smt_leaves.clone())
.unwrap();
let smt = SimpleSmt::with_leaves(SimpleSmt::MAX_DEPTH, smt_leaves.clone()).unwrap();
let store = MerkleStore::from(&smt);
let depth = smt.depth();
let root = smt.root();
Expand Down Expand Up @@ -361,7 +352,7 @@ fn new(c: &mut Criterion) {
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
.collect::<Vec<(u64, Word)>>()
},
|l| black_box(SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l)),
|l| black_box(SimpleSmt::with_leaves(SimpleSmt::MAX_DEPTH, l)),
BatchSize::SmallInput,
)
});
Expand All @@ -376,7 +367,7 @@ fn new(c: &mut Criterion) {
.collect::<Vec<(u64, Word)>>()
},
|l| {
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l).unwrap();
let smt = SimpleSmt::with_leaves(SimpleSmt::MAX_DEPTH, l).unwrap();
black_box(MerkleStore::from(&smt));
},
BatchSize::SmallInput,
Expand Down Expand Up @@ -442,10 +433,7 @@ fn update_leaf_simplesmt(c: &mut Criterion) {
.enumerate()
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
.collect::<Vec<(u64, Word)>>();
let mut smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
.unwrap()
.with_leaves(smt_leaves.clone())
.unwrap();
let mut smt = SimpleSmt::with_leaves(SimpleSmt::MAX_DEPTH, smt_leaves.clone()).unwrap();
let mut store = MerkleStore::from(&smt);
let depth = smt.depth();
let root = smt.root();
Expand Down
33 changes: 32 additions & 1 deletion src/hash/rpo/digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{Digest, Felt, StarkField, DIGEST_SIZE, ZERO};
use crate::utils::{
string::String, ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
};
use core::{cmp::Ordering, ops::Deref};
use core::{cmp::Ordering, fmt::Display, ops::Deref};

// DIGEST TRAIT IMPLEMENTATIONS
// ================================================================================================
Expand Down Expand Up @@ -85,6 +85,28 @@ impl From<RpoDigest> for [Felt; DIGEST_SIZE] {
}
}

impl From<&RpoDigest> for [u64; DIGEST_SIZE] {
fn from(value: &RpoDigest) -> Self {
[
value.0[0].as_int(),
value.0[1].as_int(),
value.0[2].as_int(),
value.0[3].as_int(),
]
}
}

impl From<RpoDigest> for [u64; DIGEST_SIZE] {
fn from(value: RpoDigest) -> Self {
[
value.0[0].as_int(),
value.0[1].as_int(),
value.0[2].as_int(),
value.0[3].as_int(),
]
}
}

impl From<&RpoDigest> for [u8; 32] {
fn from(value: &RpoDigest) -> Self {
value.as_bytes()
Expand Down Expand Up @@ -134,6 +156,15 @@ impl PartialOrd for RpoDigest {
}
}

impl Display for RpoDigest {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
for byte in self.as_bytes() {
write!(f, "{byte:02x}")?;
}
Ok(())
}
}

// TESTS
// ================================================================================================

Expand Down
10 changes: 8 additions & 2 deletions src/merkle/empty_roots.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use super::{Felt, RpoDigest, WORD_SIZE, ZERO};
use super::{Felt, RpoDigest, Word, WORD_SIZE, ZERO};
use core::slice;

// CONSTANTS
// ================================================================================================

/// A word consisting of 4 ZERO elements.
pub const EMPTY_WORD: Word = [ZERO; WORD_SIZE];

// EMPTY NODES SUBTREES
// ================================================================================================

Expand Down Expand Up @@ -1570,7 +1576,7 @@ fn all_depths_opens_to_zero() {
assert_eq!(depth as usize + 1, subtree.len());

// assert the opening is zero
let initial = RpoDigest::new([ZERO; WORD_SIZE]);
let initial = RpoDigest::new(EMPTY_WORD);
assert_eq!(initial, subtree.remove(0));

// compute every node of the path manually and compare with the output
Expand Down
46 changes: 41 additions & 5 deletions src/merkle/index.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::{Felt, MerkleError, RpoDigest, StarkField};
use core::fmt::Display;

// NODE INDEX
// ================================================================================================
Expand Down Expand Up @@ -40,6 +41,12 @@ impl NodeIndex {
}
}

/// Creates a new node index without checking its validity.
pub const fn new_unchecked(depth: u8, value: u64) -> Self {
debug_assert!((64 - value.leading_zeros()) <= depth as u32);
Self { depth, value }
}

/// Creates a new node index for testing purposes.
///
/// # Panics
Expand Down Expand Up @@ -67,12 +74,26 @@ impl NodeIndex {
Self { depth: 0, value: 0 }
}

/// Computes the value of the sibling of the current node.
pub fn sibling(mut self) -> Self {
/// Computes sibling index of the current node.
pub const fn sibling(mut self) -> Self {
self.value ^= 1;
self
}

/// Returns left child index of the current node.
pub const fn left_child(mut self) -> Self {
self.depth += 1;
self.value <<= 1;
self
}

/// Returns right child index of the current node.
pub const fn right_child(mut self) -> Self {
self.depth += 1;
self.value = (self.value << 1) + 1;
self
}

// PROVIDERS
// --------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -117,11 +138,26 @@ impl NodeIndex {
// STATE MUTATORS
// --------------------------------------------------------------------------------------------

/// Traverse one level towards the root, decrementing the depth by `1`.
pub fn move_up(&mut self) -> &mut Self {
/// Traverses one level towards the root, decrementing the depth by `1`.
pub fn move_up(&mut self) {
self.depth = self.depth.saturating_sub(1);
self.value >>= 1;
self
}

/// Traverses towards the root until the specified depth is reached.
///
/// Assumes that the specified depth is smaller than the current depth.
pub fn move_up_to(&mut self, depth: u8) {
debug_assert!(depth < self.depth);
let delta = self.depth.saturating_sub(depth);
self.depth = self.depth.saturating_sub(delta);
self.value >>= delta as u32;
}
}

impl Display for NodeIndex {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "depth={}, value={}", self.depth, self.value)
}
}

Expand Down
32 changes: 22 additions & 10 deletions src/merkle/merkle_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,28 @@ impl MerkleTree {
Ok(path.into())
}

// ITERATORS
// --------------------------------------------------------------------------------------------

/// Returns an iterator over the leaves of this [MerkleTree].
pub fn leaves(&self) -> impl Iterator<Item = (u64, &Word)> {
let leaves_start = self.nodes.len() / 2;
self.nodes.iter().skip(leaves_start).enumerate().map(|(i, v)| (i as u64, v))
}

/// Returns n iterator over every inner node of this [MerkleTree].
///
/// The iterator order is unspecified.
pub fn inner_nodes(&self) -> InnerNodeIterator {
InnerNodeIterator {
nodes: &self.nodes,
index: 1, // index 0 is just padding, start at 1
}
}

// STATE MUTATORS
// --------------------------------------------------------------------------------------------

/// Replaces the leaf at the specified index with the provided value.
///
/// # Errors
Expand Down Expand Up @@ -149,16 +171,6 @@ impl MerkleTree {

Ok(())
}

/// Returns n iterator over every inner node of this [MerkleTree].
///
/// The iterator order is unspecified.
pub fn inner_nodes(&self) -> InnerNodeIterator<'_> {
InnerNodeIterator {
nodes: &self.nodes,
index: 1, // index 0 is just padding, start at 1
}
}
}

// ITERATORS
Expand Down
Loading

0 comments on commit daa27f4

Please sign in to comment.