convert (col, hash) tuples to a dedicated struct

This commit is contained in:
Qyriad 2024-10-28 14:57:36 -06:00
parent bd0a69bcfa
commit 1102b8e4ea
5 changed files with 24 additions and 27 deletions

View file

@ -3,7 +3,7 @@ use std::{fmt::Debug, hint, mem, time::Duration};
use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion};
use miden_crypto::{ use miden_crypto::{
hash::rpo::RpoDigest, hash::rpo::RpoDigest,
merkle::{NodeIndex, Smt, SmtLeaf, SMT_DEPTH}, merkle::{NodeIndex, Smt, SmtLeaf, SubtreeLeaf, SMT_DEPTH},
Felt, Word, ONE, Felt, Word, ONE,
}; };
use rand_utils::prng_array; use rand_utils::prng_array;
@ -43,11 +43,11 @@ fn smt_subtree_even(c: &mut Criterion) {
let leaf = SmtLeaf::new_single(*key, *value); let leaf = SmtLeaf::new_single(*key, *value);
let col = NodeIndex::from(leaf.index()).value(); let col = NodeIndex::from(leaf.index()).value();
let hash = leaf.hash(); let hash = leaf.hash();
(col, hash) SubtreeLeaf { col, hash }
}) })
.collect(); .collect();
leaves.sort(); leaves.sort();
leaves.dedup_by_key(|leaf| leaf.0); leaves.dedup_by_key(|leaf| leaf.col);
leaves leaves
}, },
|leaves| { |leaves| {
@ -93,7 +93,7 @@ fn smt_subtree_random(c: &mut Criterion) {
let leaf = SmtLeaf::new_single(*key, *value); let leaf = SmtLeaf::new_single(*key, *value);
let col = NodeIndex::from(leaf.index()).value(); let col = NodeIndex::from(leaf.index()).value();
let hash = leaf.hash(); let hash = leaf.hash();
(col, hash) SubtreeLeaf { col, hash }
}) })
.collect(); .collect();
leaves.sort(); leaves.sort();

View file

@ -23,7 +23,7 @@ pub use path::{MerklePath, RootPath, ValuePath};
mod smt; mod smt;
pub use smt::{ pub use smt::{
LeafIndex, MutationSet, SimpleSmt, Smt, SmtLeaf, SmtLeafError, SmtProof, SmtProofError, LeafIndex, MutationSet, SimpleSmt, Smt, SmtLeaf, SmtLeafError, SmtProof, SmtProofError,
SMT_DEPTH, SMT_MAX_DEPTH, SMT_MIN_DEPTH, SubtreeLeaf, SMT_DEPTH, SMT_MAX_DEPTH, SMT_MIN_DEPTH,
}; };
mod mmr; mod mmr;

View file

@ -6,7 +6,7 @@ use alloc::{
use super::{ use super::{
EmptySubtreeRoots, Felt, InnerNode, InnerNodeInfo, LeafIndex, MerkleError, MerklePath, EmptySubtreeRoots, Felt, InnerNode, InnerNodeInfo, LeafIndex, MerkleError, MerklePath,
MutationSet, NodeIndex, Rpo256, RpoDigest, SparseMerkleTree, Word, EMPTY_WORD, MutationSet, NodeIndex, Rpo256, RpoDigest, SparseMerkleTree, SubtreeLeaf, Word, EMPTY_WORD,
}; };
mod error; mod error;
@ -251,9 +251,9 @@ impl Smt {
} }
pub fn build_subtree( pub fn build_subtree(
leaves: Vec<(u64, RpoDigest)>, leaves: Vec<SubtreeLeaf>,
bottom_depth: u8, bottom_depth: u8,
) -> (BTreeMap<NodeIndex, InnerNode>, Vec<(u64, RpoDigest)>) { ) -> (BTreeMap<NodeIndex, InnerNode>, Vec<SubtreeLeaf>) {
<Self as SparseMerkleTree<SMT_DEPTH>>::build_subtree(leaves, bottom_depth) <Self as SparseMerkleTree<SMT_DEPTH>>::build_subtree(leaves, bottom_depth)
} }
} }

View file

@ -357,11 +357,10 @@ pub(crate) trait SparseMerkleTree<const DEPTH: u8> {
/// more entries than can fit in a depth-8 subtree (more than 256), if `bottom_depth` is /// more entries than can fit in a depth-8 subtree (more than 256), if `bottom_depth` is
/// lower in the tree than the specified maximum depth (`DEPTH`), or if `leaves` is not sorted. /// lower in the tree than the specified maximum depth (`DEPTH`), or if `leaves` is not sorted.
// FIXME: more complete docstring. // FIXME: more complete docstring.
#[cfg_attr(not(test), allow(dead_code))]
fn build_subtree( fn build_subtree(
mut leaves: Vec<(u64, RpoDigest)>, mut leaves: Vec<SubtreeLeaf>,
bottom_depth: u8, bottom_depth: u8,
) -> (BTreeMap<NodeIndex, InnerNode>, Vec<(u64, RpoDigest)>) { ) -> (BTreeMap<NodeIndex, InnerNode>, Vec<SubtreeLeaf>) {
debug_assert!(bottom_depth <= DEPTH); debug_assert!(bottom_depth <= DEPTH);
debug_assert!(bottom_depth.is_multiple_of(&8)); debug_assert!(bottom_depth.is_multiple_of(&8));
debug_assert!(leaves.len() <= usize::pow(2, 8)); debug_assert!(leaves.len() <= usize::pow(2, 8));
@ -370,7 +369,7 @@ pub(crate) trait SparseMerkleTree<const DEPTH: u8> {
let mut inner_nodes: BTreeMap<NodeIndex, InnerNode> = Default::default(); let mut inner_nodes: BTreeMap<NodeIndex, InnerNode> = Default::default();
let mut next_leaves: Vec<(u64, RpoDigest)> = Vec::with_capacity(leaves.len() / 2); let mut next_leaves: Vec<SubtreeLeaf> = Vec::with_capacity(leaves.len() / 2);
for next_depth in (subtree_root..bottom_depth).rev() { for next_depth in (subtree_root..bottom_depth).rev() {
debug_assert!(next_depth <= bottom_depth); debug_assert!(next_depth <= bottom_depth);
@ -379,7 +378,7 @@ pub(crate) trait SparseMerkleTree<const DEPTH: u8> {
// `current_depth` is the stuff we have. // `current_depth` is the stuff we have.
let current_depth = next_depth + 1; let current_depth = next_depth + 1;
let mut iter = leaves.drain(..).map(SubtreeLeaf::from_tuple).peekable(); let mut iter = leaves.drain(..).peekable();
while let Some(first) = iter.next() { while let Some(first) = iter.next() {
// On non-continuous iterations, including the first iteration, `first_column` may // On non-continuous iterations, including the first iteration, `first_column` may
// be a left or right node. On subsequent continuous iterations, we will always call // be a left or right node. On subsequent continuous iterations, we will always call
@ -432,7 +431,7 @@ pub(crate) trait SparseMerkleTree<const DEPTH: u8> {
if hash != equivalent_empty_hash { if hash != equivalent_empty_hash {
inner_nodes.insert(index, node); inner_nodes.insert(index, node);
// FIXME: is it possible for this to end up not being sorted? I don't think so. // FIXME: is it possible for this to end up not being sorted? I don't think so.
next_leaves.push((index.value(), hash)); next_leaves.push(SubtreeLeaf { col: index.value(), hash });
} }
} }
@ -568,14 +567,9 @@ impl<const DEPTH: u8, K, V> MutationSet<DEPTH, K, V> {
// HELPERS // HELPERS
// ================================================================================================ // ================================================================================================
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
struct SubtreeLeaf { pub struct SubtreeLeaf {
col: u64, pub col: u64,
hash: RpoDigest, pub hash: RpoDigest,
}
impl SubtreeLeaf {
const fn from_tuple((col, hash): (u64, RpoDigest)) -> Self {
Self { col, hash }
}
} }
// TESTS // TESTS
@ -587,7 +581,7 @@ mod test {
use super::SparseMerkleTree; use super::SparseMerkleTree;
use crate::{ use crate::{
hash::rpo::RpoDigest, hash::rpo::RpoDigest,
merkle::{Smt, SmtLeaf, SMT_DEPTH}, merkle::{smt::SubtreeLeaf, Smt, SmtLeaf, SMT_DEPTH},
Felt, Word, ONE, Felt, Word, ONE,
}; };
@ -606,17 +600,17 @@ mod test {
let control = Smt::with_entries(entries.clone()).unwrap(); let control = Smt::with_entries(entries.clone()).unwrap();
let mut leaves: Vec<(u64, RpoDigest)> = entries let mut leaves: Vec<SubtreeLeaf> = entries
.iter() .iter()
.map(|(key, value)| { .map(|(key, value)| {
let leaf = SmtLeaf::new_single(*key, *value); let leaf = SmtLeaf::new_single(*key, *value);
let col = leaf.index().index.value(); let col = leaf.index().index.value();
let hash = leaf.hash(); let hash = leaf.hash();
(col, hash) SubtreeLeaf { col, hash }
}) })
.collect(); .collect();
leaves.sort(); leaves.sort();
leaves.dedup_by_key(|leaf| leaf.0); leaves.dedup_by_key(|leaf| leaf.col);
let (first_subtree, _) = Smt::build_subtree(leaves, SMT_DEPTH); let (first_subtree, _) = Smt::build_subtree(leaves, SMT_DEPTH);
assert!(!first_subtree.is_empty()); assert!(!first_subtree.is_empty());

View file

@ -1,4 +1,7 @@
use alloc::collections::{BTreeMap, BTreeSet}; use alloc::{
collections::{BTreeMap, BTreeSet},
vec::Vec,
};
use super::{ use super::{
super::ValuePath, EmptySubtreeRoots, InnerNode, InnerNodeInfo, LeafIndex, MerkleError, super::ValuePath, EmptySubtreeRoots, InnerNode, InnerNodeInfo, LeafIndex, MerkleError,