Merge pull request #115 from 0xPolygonMiden/vlopes11-store-smt-depth
feat: Add `depth` as store SMT argument
This commit is contained in:
commit
49b9029b46
5 changed files with 48 additions and 30 deletions
|
@ -13,7 +13,7 @@ For performance benchmarks of these hash functions and their comparison to other
|
||||||
[Merkle module](./src/merkle/) provides a set of data structures related to Merkle trees. All these data structures are implemented using the RPO hash function described above. The data structures are:
|
[Merkle module](./src/merkle/) provides a set of data structures related to Merkle trees. All these data structures are implemented using the RPO hash function described above. The data structures are:
|
||||||
|
|
||||||
* `MerkleTree`: a regular fully-balanced binary Merkle tree. The depth of this tree can be at most 64.
|
* `MerkleTree`: a regular fully-balanced binary Merkle tree. The depth of this tree can be at most 64.
|
||||||
* `SimpleSmt`: a Sparse Merkle Tree, mapping 63-bit keys to 4-element leaf values.
|
* `SimpleSmt`: a Sparse Merkle Tree, mapping 64-bit keys to 4-element leaf values.
|
||||||
* `MerklePathSet`: a collection of Merkle authentication paths all resolving to the same root. The length of the paths can be at most 64.
|
* `MerklePathSet`: a collection of Merkle authentication paths all resolving to the same root. The length of the paths can be at most 64.
|
||||||
* `MerkleStore`: a collection of Merkle trees of different heights designed to efficiently store trees with common subtrees.
|
* `MerkleStore`: a collection of Merkle trees of different heights designed to efficiently store trees with common subtrees.
|
||||||
* `Mmr`: a Merkle mountain range structure designed to function as an append-only log.
|
* `Mmr`: a Merkle mountain range structure designed to function as an append-only log.
|
||||||
|
|
|
@ -27,7 +27,7 @@ fn random_index(range: u64) -> u64 {
|
||||||
fn get_empty_leaf_simplesmt(c: &mut Criterion) {
|
fn get_empty_leaf_simplesmt(c: &mut Criterion) {
|
||||||
let mut group = c.benchmark_group("get_empty_leaf_simplesmt");
|
let mut group = c.benchmark_group("get_empty_leaf_simplesmt");
|
||||||
|
|
||||||
let depth = 63u8;
|
let depth = SimpleSmt::MAX_DEPTH;
|
||||||
let size = 2u64.pow(depth as u32);
|
let size = 2u64.pow(depth as u32);
|
||||||
|
|
||||||
// both SMT and the store are pre-populated with empty hashes, accessing these values is what is
|
// both SMT and the store are pre-populated with empty hashes, accessing these values is what is
|
||||||
|
@ -103,12 +103,12 @@ fn get_leaf_simplesmt(c: &mut Criterion) {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
||||||
.collect::<Vec<(u64, Word)>>();
|
.collect::<Vec<(u64, Word)>>();
|
||||||
let smt = SimpleSmt::new(63)
|
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_leaves(smt_leaves.clone())
|
.with_leaves(smt_leaves.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let store = MerkleStore::new()
|
let store = MerkleStore::new()
|
||||||
.with_sparse_merkle_tree(smt_leaves)
|
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let depth = smt.depth();
|
let depth = smt.depth();
|
||||||
let root = smt.root();
|
let root = smt.root();
|
||||||
|
@ -136,7 +136,7 @@ fn get_leaf_simplesmt(c: &mut Criterion) {
|
||||||
fn get_node_of_empty_simplesmt(c: &mut Criterion) {
|
fn get_node_of_empty_simplesmt(c: &mut Criterion) {
|
||||||
let mut group = c.benchmark_group("get_node_of_empty_simplesmt");
|
let mut group = c.benchmark_group("get_node_of_empty_simplesmt");
|
||||||
|
|
||||||
let depth = 63u8;
|
let depth = SimpleSmt::MAX_DEPTH;
|
||||||
let size = 2u64.pow(depth as u32);
|
let size = 2u64.pow(depth as u32);
|
||||||
|
|
||||||
// both SMT and the store are pre-populated with the empty hashes, accessing the internal nodes
|
// both SMT and the store are pre-populated with the empty hashes, accessing the internal nodes
|
||||||
|
@ -216,12 +216,12 @@ fn get_node_simplesmt(c: &mut Criterion) {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
||||||
.collect::<Vec<(u64, Word)>>();
|
.collect::<Vec<(u64, Word)>>();
|
||||||
let smt = SimpleSmt::new(63)
|
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_leaves(smt_leaves.clone())
|
.with_leaves(smt_leaves.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let store = MerkleStore::new()
|
let store = MerkleStore::new()
|
||||||
.with_sparse_merkle_tree(smt_leaves)
|
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let root = smt.root();
|
let root = smt.root();
|
||||||
let size_u64 = size as u64;
|
let size_u64 = size as u64;
|
||||||
|
@ -295,12 +295,12 @@ fn get_leaf_path_simplesmt(c: &mut Criterion) {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
||||||
.collect::<Vec<(u64, Word)>>();
|
.collect::<Vec<(u64, Word)>>();
|
||||||
let smt = SimpleSmt::new(63)
|
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_leaves(smt_leaves.clone())
|
.with_leaves(smt_leaves.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let store = MerkleStore::new()
|
let store = MerkleStore::new()
|
||||||
.with_sparse_merkle_tree(smt_leaves)
|
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let depth = smt.depth();
|
let depth = smt.depth();
|
||||||
let root = smt.root();
|
let root = smt.root();
|
||||||
|
@ -366,7 +366,7 @@ fn new(c: &mut Criterion) {
|
||||||
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
||||||
.collect::<Vec<(u64, Word)>>()
|
.collect::<Vec<(u64, Word)>>()
|
||||||
},
|
},
|
||||||
|l| black_box(SimpleSmt::new(63).unwrap().with_leaves(l)),
|
|l| black_box(SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l)),
|
||||||
BatchSize::SmallInput,
|
BatchSize::SmallInput,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -382,7 +382,11 @@ fn new(c: &mut Criterion) {
|
||||||
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
||||||
.collect::<Vec<(u64, Word)>>()
|
.collect::<Vec<(u64, Word)>>()
|
||||||
},
|
},
|
||||||
|l| black_box(MerkleStore::new().with_sparse_merkle_tree(l)),
|
|l| {
|
||||||
|
black_box(
|
||||||
|
MerkleStore::new().with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, l),
|
||||||
|
)
|
||||||
|
},
|
||||||
BatchSize::SmallInput,
|
BatchSize::SmallInput,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -450,12 +454,12 @@ fn update_leaf_simplesmt(c: &mut Criterion) {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
.map(|(c, v)| (c.try_into().unwrap(), v.into()))
|
||||||
.collect::<Vec<(u64, Word)>>();
|
.collect::<Vec<(u64, Word)>>();
|
||||||
let mut smt = SimpleSmt::new(63)
|
let mut smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_leaves(smt_leaves.clone())
|
.with_leaves(smt_leaves.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut store = MerkleStore::new()
|
let mut store = MerkleStore::new()
|
||||||
.with_sparse_merkle_tree(smt_leaves)
|
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let depth = smt.depth();
|
let depth = smt.depth();
|
||||||
let root = smt.root();
|
let root = smt.root();
|
||||||
|
|
|
@ -8,7 +8,7 @@ mod tests;
|
||||||
// SPARSE MERKLE TREE
|
// SPARSE MERKLE TREE
|
||||||
// ================================================================================================
|
// ================================================================================================
|
||||||
|
|
||||||
/// A sparse Merkle tree with 63-bit keys and 4-element leaf values, without compaction.
|
/// A sparse Merkle tree with 64-bit keys and 4-element leaf values, without compaction.
|
||||||
/// Manipulation and retrieval of leaves and internal nodes is provided by its internal `Store`.
|
/// Manipulation and retrieval of leaves and internal nodes is provided by its internal `Store`.
|
||||||
/// The root of the tree is recomputed on each new leaf update.
|
/// The root of the tree is recomputed on each new leaf update.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -26,7 +26,7 @@ impl SimpleSmt {
|
||||||
pub const MIN_DEPTH: u8 = 1;
|
pub const MIN_DEPTH: u8 = 1;
|
||||||
|
|
||||||
/// Maximum supported depth.
|
/// Maximum supported depth.
|
||||||
pub const MAX_DEPTH: u8 = 63;
|
pub const MAX_DEPTH: u8 = 64;
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
|
@ -57,7 +57,7 @@ impl SimpleSmt {
|
||||||
{
|
{
|
||||||
// check if the leaves count will fit the depth setup
|
// check if the leaves count will fit the depth setup
|
||||||
let mut entries = entries.into_iter();
|
let mut entries = entries.into_iter();
|
||||||
let max = 1 << self.depth;
|
let max = 1 << self.depth.min(63);
|
||||||
if entries.len() > max {
|
if entries.len() > max {
|
||||||
return Err(MerkleError::InvalidEntriesCount(max, entries.len()));
|
return Err(MerkleError::InvalidEntriesCount(max, entries.len()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,13 +115,19 @@ impl MerkleStore {
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Appends the provided sparse merkle tree represented by its `entries` to the set.
|
/// Appends the provided Sparse Merkle tree represented by its `entries` to the set.
|
||||||
pub fn with_sparse_merkle_tree<R, I>(mut self, entries: R) -> Result<Self, MerkleError>
|
///
|
||||||
|
/// For more information, check [MerkleStore::add_sparse_merkle_tree].
|
||||||
|
pub fn with_sparse_merkle_tree<R, I>(
|
||||||
|
mut self,
|
||||||
|
depth: u8,
|
||||||
|
entries: R,
|
||||||
|
) -> Result<Self, MerkleError>
|
||||||
where
|
where
|
||||||
R: IntoIterator<IntoIter = I>,
|
R: IntoIterator<IntoIter = I>,
|
||||||
I: Iterator<Item = (u64, Word)> + ExactSizeIterator,
|
I: Iterator<Item = (u64, Word)> + ExactSizeIterator,
|
||||||
{
|
{
|
||||||
self.add_sparse_merkle_tree(entries)?;
|
self.add_sparse_merkle_tree(depth, entries)?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,20 +278,24 @@ impl MerkleStore {
|
||||||
Ok(tree.nodes[1])
|
Ok(tree.nodes[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds all the nodes of a Sparse Merkle tree represented by `entries`.
|
/// Adds a Sparse Merkle tree defined by the specified `entries` to the store, and returns the
|
||||||
|
/// root of the added tree.
|
||||||
///
|
///
|
||||||
/// This will instantiate a Sparse Merkle tree using `entries` and include all the nodes into
|
/// The entries are expected to contain tuples of `(index, node)` describing nodes in the tree
|
||||||
/// the store.
|
/// at `depth`.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
/// Returns an error if the provided `depth` is greater than [SimpleSmt::MAX_DEPTH].
|
||||||
/// This will return `InvalidEntriesCount` if the length of `entries` is not `63`.
|
pub fn add_sparse_merkle_tree<R, I>(
|
||||||
pub fn add_sparse_merkle_tree<R, I>(&mut self, entries: R) -> Result<Word, MerkleError>
|
&mut self,
|
||||||
|
depth: u8,
|
||||||
|
entries: R,
|
||||||
|
) -> Result<Word, MerkleError>
|
||||||
where
|
where
|
||||||
R: IntoIterator<IntoIter = I>,
|
R: IntoIterator<IntoIter = I>,
|
||||||
I: Iterator<Item = (u64, Word)> + ExactSizeIterator,
|
I: Iterator<Item = (u64, Word)> + ExactSizeIterator,
|
||||||
{
|
{
|
||||||
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)?.with_leaves(entries)?;
|
let smt = SimpleSmt::new(depth)?.with_leaves(entries)?;
|
||||||
for branch in smt.store.branches.values() {
|
for branch in smt.store.branches.values() {
|
||||||
let parent = Rpo256::merge(&[branch.left, branch.right]);
|
let parent = Rpo256::merge(&[branch.left, branch.right]);
|
||||||
self.nodes.insert(
|
self.nodes.insert(
|
||||||
|
|
|
@ -205,7 +205,7 @@ fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> {
|
||||||
let mut store = MerkleStore::default();
|
let mut store = MerkleStore::default();
|
||||||
let keys2: [u64; 2] = [0, 1];
|
let keys2: [u64; 2] = [0, 1];
|
||||||
let leaves2: [Word; 2] = [int_to_node(1), int_to_node(2)];
|
let leaves2: [Word; 2] = [int_to_node(1), int_to_node(2)];
|
||||||
store.add_sparse_merkle_tree(keys2.into_iter().zip(leaves2.into_iter()))?;
|
store.add_sparse_merkle_tree(48, keys2.into_iter().zip(leaves2.into_iter()))?;
|
||||||
let smt = SimpleSmt::new(1)
|
let smt = SimpleSmt::new(1)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_leaves(keys2.into_iter().zip(leaves2.into_iter()))
|
.with_leaves(keys2.into_iter().zip(leaves2.into_iter()))
|
||||||
|
@ -231,7 +231,10 @@ fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
|
fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
|
||||||
let mut store = MerkleStore::default();
|
let mut store = MerkleStore::default();
|
||||||
store.add_sparse_merkle_tree(KEYS4.into_iter().zip(LEAVES4.into_iter()))?;
|
store.add_sparse_merkle_tree(
|
||||||
|
SimpleSmt::MAX_DEPTH,
|
||||||
|
KEYS4.into_iter().zip(LEAVES4.into_iter()),
|
||||||
|
)?;
|
||||||
|
|
||||||
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
|
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -584,9 +587,10 @@ fn test_constructors() -> Result<(), MerkleError> {
|
||||||
assert_eq!(mtree.get_path(index)?, value_path.path);
|
assert_eq!(mtree.get_path(index)?, value_path.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let depth = 32;
|
||||||
let store = MerkleStore::default()
|
let store = MerkleStore::default()
|
||||||
.with_sparse_merkle_tree(KEYS4.into_iter().zip(LEAVES4.into_iter()))?;
|
.with_sparse_merkle_tree(depth, KEYS4.into_iter().zip(LEAVES4.into_iter()))?;
|
||||||
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH)
|
let smt = SimpleSmt::new(depth)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter()))
|
.with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
Loading…
Add table
Reference in a new issue