Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

store: support adding existing structures #139

Merged
merged 6 commits into from
Apr 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 20 additions & 22 deletions benches/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn get_empty_leaf_simplesmt(c: &mut Criterion) {
// both SMT and the store are pre-populated with empty hashes, accessing these values is what is
// being benchmarked here, so no values are inserted into the backends
let smt = SimpleSmt::new(depth).unwrap();
let store = MerkleStore::new();
let store = MerkleStore::from(&smt);
let root = smt.root();

group.bench_function(BenchmarkId::new("SimpleSmt", depth), |b| {
Expand Down Expand Up @@ -66,7 +66,7 @@ fn get_leaf_merkletree(c: &mut Criterion) {

let mtree_leaves: Vec<Word> = leaves.iter().map(|v| v.into()).collect();
let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap();
let store = MerkleStore::new().with_merkle_tree(mtree_leaves).unwrap();
let store = MerkleStore::from(&mtree);
let depth = mtree.depth();
let root = mtree.root();
let size_u64 = size as u64;
Expand Down Expand Up @@ -108,9 +108,7 @@ fn get_leaf_simplesmt(c: &mut Criterion) {
.unwrap()
.with_leaves(smt_leaves.clone())
.unwrap();
let store = MerkleStore::new()
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
.unwrap();
let store = MerkleStore::from(&smt);
let depth = smt.depth();
let root = smt.root();
let size_u64 = size as u64;
Expand Down Expand Up @@ -143,7 +141,7 @@ fn get_node_of_empty_simplesmt(c: &mut Criterion) {
// of these values is what is being benchmarked here, so no values are inserted into the
// backends.
let smt = SimpleSmt::new(depth).unwrap();
let store = MerkleStore::new();
let store = MerkleStore::from(&smt);
let root = smt.root();
let half_depth = depth / 2;
let half_size = 2_u64.pow(half_depth as u32);
Expand Down Expand Up @@ -178,7 +176,7 @@ fn get_node_merkletree(c: &mut Criterion) {

let mtree_leaves: Vec<Word> = leaves.iter().map(|v| v.into()).collect();
let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap();
let store = MerkleStore::new().with_merkle_tree(mtree_leaves).unwrap();
let store = MerkleStore::from(&mtree);
let root = mtree.root();
let half_depth = mtree.depth() / 2;
let half_size = 2_u64.pow(half_depth as u32);
Expand Down Expand Up @@ -221,9 +219,7 @@ fn get_node_simplesmt(c: &mut Criterion) {
.unwrap()
.with_leaves(smt_leaves.clone())
.unwrap();
let store = MerkleStore::new()
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
.unwrap();
let store = MerkleStore::from(&smt);
let root = smt.root();
let half_depth = smt.depth() / 2;
let half_size = 2_u64.pow(half_depth as u32);
Expand Down Expand Up @@ -258,7 +254,7 @@ fn get_leaf_path_merkletree(c: &mut Criterion) {

let mtree_leaves: Vec<Word> = leaves.iter().map(|v| v.into()).collect();
let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap();
let store = MerkleStore::new().with_merkle_tree(mtree_leaves).unwrap();
let store = MerkleStore::from(&mtree);
let depth = mtree.depth();
let root = mtree.root();
let size_u64 = size as u64;
Expand Down Expand Up @@ -300,9 +296,7 @@ fn get_leaf_path_simplesmt(c: &mut Criterion) {
.unwrap()
.with_leaves(smt_leaves.clone())
.unwrap();
let store = MerkleStore::new()
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
.unwrap();
let store = MerkleStore::from(&smt);
let depth = smt.depth();
let root = smt.root();
let size_u64 = size as u64;
Expand Down Expand Up @@ -347,10 +341,13 @@ fn new(c: &mut Criterion) {

// This could be done with `bench_with_input`, however to remove variables while comparing
// with MerkleTree it is using `iter_batched`
group.bench_function(BenchmarkId::new("MerkleStore::with_merkle_tree", size), |b| {
group.bench_function(BenchmarkId::new("MerkleStore::extend::MerkleTree", size), |b| {
b.iter_batched(
|| leaves.iter().map(|v| v.into()).collect::<Vec<Word>>(),
|l| black_box(MerkleStore::new().with_merkle_tree(l)),
|l| {
let mtree = MerkleTree::new(l).unwrap();
black_box(MerkleStore::from(&mtree));
},
BatchSize::SmallInput,
)
});
Expand All @@ -369,7 +366,7 @@ fn new(c: &mut Criterion) {
)
});

group.bench_function(BenchmarkId::new("MerkleStore::with_sparse_merkle_tree", size), |b| {
group.bench_function(BenchmarkId::new("MerkleStore::extend::SimpleSmt", size), |b| {
b.iter_batched(
|| {
leaves
Expand All @@ -378,7 +375,10 @@ fn new(c: &mut Criterion) {
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
.collect::<Vec<(u64, Word)>>()
},
|l| black_box(MerkleStore::new().with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, l)),
|l| {
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l).unwrap();
black_box(MerkleStore::from(&smt));
},
BatchSize::SmallInput,
)
});
Expand All @@ -397,7 +397,7 @@ fn update_leaf_merkletree(c: &mut Criterion) {

let mtree_leaves: Vec<Word> = leaves.iter().map(|v| v.into()).collect();
let mut mtree = MerkleTree::new(mtree_leaves.clone()).unwrap();
let mut store = MerkleStore::new().with_merkle_tree(mtree_leaves).unwrap();
let mut store = MerkleStore::from(&mtree);
let depth = mtree.depth();
let root = mtree.root();
let size_u64 = size as u64;
Expand Down Expand Up @@ -446,9 +446,7 @@ fn update_leaf_simplesmt(c: &mut Criterion) {
.unwrap()
.with_leaves(smt_leaves.clone())
.unwrap();
let mut store = MerkleStore::new()
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
.unwrap();
let mut store = MerkleStore::from(&smt);
let depth = smt.depth();
let root = smt.root();
let size_u64 = size as u64;
Expand Down
15 changes: 10 additions & 5 deletions src/merkle/merkle_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,11 @@ impl MerkleTree {
Ok(())
}

/// An iterator over every inner node in the tree. The iterator order is unspecified.
pub fn inner_nodes(&self) -> MerkleTreeNodes<'_> {
MerkleTreeNodes {
/// 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
}
Expand All @@ -165,12 +167,12 @@ impl MerkleTree {
/// An iterator over every inner node of the [MerkleTree].
///
/// Use this to extract the data of the tree, there is no guarantee on the order of the elements.
pub struct MerkleTreeNodes<'a> {
pub struct InnerNodeIterator<'a> {
nodes: &'a Vec<Word>,
index: usize,
}

impl<'a> Iterator for MerkleTreeNodes<'a> {
impl<'a> Iterator for InnerNodeIterator<'a> {
type Item = InnerNodeInfo;

fn next(&mut self) -> Option<Self::Item> {
Expand All @@ -192,6 +194,9 @@ impl<'a> Iterator for MerkleTreeNodes<'a> {
}
}

// UTILITY FUNCTIONS
// ================================================================================================

/// Utility to visualize a [MerkleTree] in text.
pub fn tree_to_text(tree: &MerkleTree) -> Result<String, fmt::Error> {
let indent = " ";
Expand Down
84 changes: 78 additions & 6 deletions src/merkle/path.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{vec, MerkleError, NodeIndex, Rpo256, Vec, Word};
use super::{vec, InnerNodeInfo, MerkleError, NodeIndex, Rpo256, Vec, Word};
use core::ops::{Deref, DerefMut};

// MERKLE PATH
Expand All @@ -22,6 +22,11 @@ impl MerklePath {
// PROVIDERS
// --------------------------------------------------------------------------------------------

/// Returns the depth in which this Merkle path proof is valid.
pub fn depth(&self) -> u8 {
self.nodes.len() as u8
}

/// Computes the merkle root for this opening.
pub fn compute_root(&self, index: u64, node: Word) -> Result<Word, MerkleError> {
let mut index = NodeIndex::new(self.depth(), index)?;
Expand All @@ -34,11 +39,6 @@ impl MerklePath {
Ok(root)
}

/// Returns the depth in which this Merkle path proof is valid.
pub fn depth(&self) -> u8 {
self.nodes.len() as u8
}

/// Verifies the Merkle opening proof towards the provided root.
///
/// Returns `true` if `node` exists at `index` in a Merkle tree with `root`.
Expand All @@ -48,6 +48,20 @@ impl MerklePath {
Err(_) => false,
}
}

/// Returns an iterator over every inner node of this [MerklePath].
///
/// The iteration order is unspecified.
///
/// # Errors
/// Returns an error if the specified index is not valid for this path.
pub fn inner_nodes(&self, index: u64, node: Word) -> Result<InnerNodeIterator, MerkleError> {
Ok(InnerNodeIterator {
nodes: &self.nodes,
index: NodeIndex::new(self.depth(), index)?,
value: node,
})
}
}

impl From<Vec<Word>> for MerklePath {
Expand All @@ -72,6 +86,9 @@ impl DerefMut for MerklePath {
}
}

// ITERATORS
// ================================================================================================

impl FromIterator<Word> for MerklePath {
fn from_iter<T: IntoIterator<Item = Word>>(iter: T) -> Self {
Self::new(iter.into_iter().collect())
Expand All @@ -87,6 +104,39 @@ impl IntoIterator for MerklePath {
}
}

/// An iterator over internal nodes of a [MerklePath].
pub struct InnerNodeIterator<'a> {
nodes: &'a Vec<Word>,
index: NodeIndex,
value: Word,
}

impl<'a> Iterator for InnerNodeIterator<'a> {
type Item = InnerNodeInfo;

fn next(&mut self) -> Option<Self::Item> {
if !self.index.is_root() {
let sibling_pos = self.nodes.len() - self.index.depth() as usize;
let (left, right) = if self.index.is_value_odd() {
(self.nodes[sibling_pos], self.value)
} else {
(self.value, self.nodes[sibling_pos])
};

self.value = Rpo256::merge(&[left.into(), right.into()]).into();
self.index.move_up();

Some(InnerNodeInfo {
value: self.value,
left,
right,
})
} else {
None
}
}
}

// MERKLE PATH CONTAINERS
// ================================================================================================

Expand All @@ -110,3 +160,25 @@ pub struct RootPath {
/// The path from `value` to `root` (exclusive).
pub path: MerklePath,
}

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

#[cfg(test)]
mod tests {
use crate::merkle::{int_to_node, MerklePath};

#[test]
fn test_inner_nodes() {
let nodes = vec![int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
let merkle_path = MerklePath::new(nodes);

let index = 6;
let node = int_to_node(5);
let root = merkle_path.compute_root(index, node).unwrap();

let inner_root = merkle_path.inner_nodes(index, node).unwrap().last().unwrap().value;

assert_eq!(root, inner_root);
}
}
Loading