16 Commits

Author SHA1 Message Date
Bobbin Threadbare
09025b4014 Merge pull request #129 from 0xPolygonMiden/next
Tracking PR for v0.4 release
2023-04-21 15:38:33 -07:00
Bobbin Threadbare
e983e940b2 chore: update changelog 2023-04-21 14:42:08 -07:00
Bobbin Threadbare
ae4e27b6c7 Merge pull request #139 from 0xPolygonMiden/hacka-support-adding-existing-structures-to-store
store: support adding existing structures
2023-04-21 14:32:52 -07:00
Bobbin Threadbare
130ae3d12a feat: add inner node iterator to MerklePath 2023-04-21 14:27:58 -07:00
Bobbin Threadbare
22c9f382c4 fix: serialization test 2023-04-21 11:39:49 -07:00
Bobbin Threadbare
9be4253f19 feat: remove clone requirement for MerkleStore From constructors 2023-04-21 11:22:36 -07:00
Augusto F. Hack
59595a2e04 feat: added From convertions for the MerkleStore 2023-04-21 14:47:58 +02:00
Augusto F. Hack
eb316f51bc store: remove SimpleSMT/MerkleTree/Mmr add/with methods 2023-04-21 14:47:48 +02:00
Augusto F. Hack
8161477d6a store: support adding existing structures 2023-04-20 13:45:31 +02:00
Augusto Hack
158167356d Merge pull request #138 from 0xPolygonMiden/hacka-merge-support-for-leaves
feat: allow merging of leaves
2023-04-17 12:29:13 +02:00
Augusto F. Hack
3996374a8b feat: allow merging of leaves
Consider the case of a MMR with one entry, and a new entry is being
added. Both of these values are quite unique, they are at the same time
the root and only leaf of their corresponding tree. Currently this
representation is not supported by the [MerkleStore], so the leaves are
not in it. Once the two values are merged, they both become leaves of a
new tree under the new parent, and the existing validation didn't permit
that promotion from happening.

This lifts the validation, and changes the method to clarify that not
only `root` are being merged, by arbitrary nodes of a tree (leafs,
internal, or roots), with arbitrary mixing of each.
2023-04-17 12:21:51 +02:00
Augusto Hack
7fa03c7967 Merge pull request #137 from 0xPolygonMiden/frisitano-reexport-mmr-proof
re-export mmr proof
2023-04-14 14:34:58 +02:00
frisitano
79915cc346 feat: re-export MmrProof 2023-04-14 13:25:19 +01:00
Augusto Hack
45412b5cec Merge pull request #134 from 0xPolygonMiden/add-rustfmt-config
config: add rustfmt config
2023-04-11 17:58:06 +02:00
Augusto F. Hack
bbb1e641a3 config: add rustfmt config 2023-04-11 17:38:39 +02:00
Bobbin Threadbare
e02507d11e chore: update version to v0.4.0 2023-04-08 12:46:53 -07:00
20 changed files with 347 additions and 576 deletions

View File

@@ -1,3 +1,9 @@
## 0.4.0 (2023-04-21)
- Exported `MmrProof` from the crate (#137).
- Allowed merging of leaves in `MerkleStore` (#138).
- [BREAKING] Refactored how existing data structures are added to `MerkleStore` (#139).
## 0.3.0 (2023-04-08) ## 0.3.0 (2023-04-08)
- Added `depth` parameter to SMT constructors in `MerkleStore` (#115). - Added `depth` parameter to SMT constructors in `MerkleStore` (#115).

View File

@@ -1,12 +1,12 @@
[package] [package]
name = "miden-crypto" name = "miden-crypto"
version = "0.3.0" version = "0.4.0"
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.3.0" documentation = "https://docs.rs/miden-crypto/0.4.0"
categories = ["cryptography", "no-std"] categories = ["cryptography", "no-std"]
keywords = ["miden", "crypto", "hash", "merkle"] keywords = ["miden", "crypto", "hash", "merkle"]
edition = "2021" edition = "2021"

View File

@@ -106,11 +106,5 @@ fn blake3_sequential(c: &mut Criterion) {
}); });
} }
criterion_group!( criterion_group!(hash_group, rpo256_2to1, rpo256_sequential, blake3_2to1, blake3_sequential);
hash_group,
rpo256_2to1,
rpo256_sequential,
blake3_2to1,
blake3_sequential
);
criterion_main!(hash_group); criterion_main!(hash_group);

View File

@@ -75,10 +75,5 @@ criterion_main!(smt_group);
fn generate_word(seed: &mut [u8; 32]) -> Word { fn generate_word(seed: &mut [u8; 32]) -> Word {
swap(seed, &mut prng_array(*seed)); swap(seed, &mut prng_array(*seed));
let nums: [u64; 4] = prng_array(*seed); let nums: [u64; 4] = prng_array(*seed);
[ [Felt::new(nums[0]), Felt::new(nums[1]), Felt::new(nums[2]), Felt::new(nums[3])]
Felt::new(nums[0]),
Felt::new(nums[1]),
Felt::new(nums[2]),
Felt::new(nums[3]),
]
} }

View File

@@ -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 // 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 // being benchmarked here, so no values are inserted into the backends
let smt = SimpleSmt::new(depth).unwrap(); let smt = SimpleSmt::new(depth).unwrap();
let store = MerkleStore::new(); let store = MerkleStore::from(&smt);
let root = smt.root(); let root = smt.root();
group.bench_function(BenchmarkId::new("SimpleSmt", depth), |b| { group.bench_function(BenchmarkId::new("SimpleSmt", depth), |b| {
@@ -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_leaves: Vec<Word> = leaves.iter().map(|v| v.into()).collect();
let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap(); 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 depth = mtree.depth();
let root = mtree.root(); let root = mtree.root();
let size_u64 = size as u64; let size_u64 = size as u64;
@@ -108,9 +108,7 @@ fn get_leaf_simplesmt(c: &mut Criterion) {
.unwrap() .unwrap()
.with_leaves(smt_leaves.clone()) .with_leaves(smt_leaves.clone())
.unwrap(); .unwrap();
let store = MerkleStore::new() let store = MerkleStore::from(&smt);
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
.unwrap();
let depth = smt.depth(); let depth = smt.depth();
let root = smt.root(); let root = smt.root();
let size_u64 = size as u64; let size_u64 = size as u64;
@@ -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 // of these values is what is being benchmarked here, so no values are inserted into the
// backends. // backends.
let smt = SimpleSmt::new(depth).unwrap(); let smt = SimpleSmt::new(depth).unwrap();
let store = MerkleStore::new(); let store = MerkleStore::from(&smt);
let root = smt.root(); let root = smt.root();
let half_depth = depth / 2; let half_depth = depth / 2;
let half_size = 2_u64.pow(half_depth as u32); let half_size = 2_u64.pow(half_depth as u32);
@@ -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_leaves: Vec<Word> = leaves.iter().map(|v| v.into()).collect();
let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap(); 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 root = mtree.root();
let half_depth = mtree.depth() / 2; let half_depth = mtree.depth() / 2;
let half_size = 2_u64.pow(half_depth as u32); let half_size = 2_u64.pow(half_depth as u32);
@@ -221,9 +219,7 @@ fn get_node_simplesmt(c: &mut Criterion) {
.unwrap() .unwrap()
.with_leaves(smt_leaves.clone()) .with_leaves(smt_leaves.clone())
.unwrap(); .unwrap();
let store = MerkleStore::new() let store = MerkleStore::from(&smt);
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
.unwrap();
let root = smt.root(); let root = smt.root();
let half_depth = smt.depth() / 2; let half_depth = smt.depth() / 2;
let half_size = 2_u64.pow(half_depth as u32); let half_size = 2_u64.pow(half_depth as u32);
@@ -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_leaves: Vec<Word> = leaves.iter().map(|v| v.into()).collect();
let mtree = MerkleTree::new(mtree_leaves.clone()).unwrap(); 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 depth = mtree.depth();
let root = mtree.root(); let root = mtree.root();
let size_u64 = size as u64; let size_u64 = size as u64;
@@ -300,9 +296,7 @@ fn get_leaf_path_simplesmt(c: &mut Criterion) {
.unwrap() .unwrap()
.with_leaves(smt_leaves.clone()) .with_leaves(smt_leaves.clone())
.unwrap(); .unwrap();
let store = MerkleStore::new() let store = MerkleStore::from(&smt);
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
.unwrap();
let depth = smt.depth(); let depth = smt.depth();
let root = smt.root(); let root = smt.root();
let size_u64 = size as u64; let size_u64 = size as u64;
@@ -347,16 +341,16 @@ fn new(c: &mut Criterion) {
// This could be done with `bench_with_input`, however to remove variables while comparing // This could be done with `bench_with_input`, however to remove variables while comparing
// with MerkleTree it is using `iter_batched` // with MerkleTree it is using `iter_batched`
group.bench_function( group.bench_function(BenchmarkId::new("MerkleStore::extend::MerkleTree", size), |b| {
BenchmarkId::new("MerkleStore::with_merkle_tree", size),
|b| {
b.iter_batched( b.iter_batched(
|| leaves.iter().map(|v| v.into()).collect::<Vec<Word>>(), || 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, BatchSize::SmallInput,
) )
}, });
);
group.bench_function(BenchmarkId::new("SimpleSmt::new", size), |b| { group.bench_function(BenchmarkId::new("SimpleSmt::new", size), |b| {
b.iter_batched( b.iter_batched(
@@ -372,9 +366,7 @@ fn new(c: &mut Criterion) {
) )
}); });
group.bench_function( group.bench_function(BenchmarkId::new("MerkleStore::extend::SimpleSmt", size), |b| {
BenchmarkId::new("MerkleStore::with_sparse_merkle_tree", size),
|b| {
b.iter_batched( b.iter_batched(
|| { || {
leaves leaves
@@ -384,14 +376,12 @@ fn new(c: &mut Criterion) {
.collect::<Vec<(u64, Word)>>() .collect::<Vec<(u64, Word)>>()
}, },
|l| { |l| {
black_box( let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l).unwrap();
MerkleStore::new().with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, l), black_box(MerkleStore::from(&smt));
)
}, },
BatchSize::SmallInput, BatchSize::SmallInput,
) )
}, });
);
} }
} }
@@ -407,7 +397,7 @@ fn update_leaf_merkletree(c: &mut Criterion) {
let mtree_leaves: Vec<Word> = leaves.iter().map(|v| v.into()).collect(); let mtree_leaves: Vec<Word> = leaves.iter().map(|v| v.into()).collect();
let mut mtree = MerkleTree::new(mtree_leaves.clone()).unwrap(); 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 depth = mtree.depth();
let root = mtree.root(); let root = mtree.root();
let size_u64 = size as u64; let size_u64 = size as u64;
@@ -456,9 +446,7 @@ fn update_leaf_simplesmt(c: &mut Criterion) {
.unwrap() .unwrap()
.with_leaves(smt_leaves.clone()) .with_leaves(smt_leaves.clone())
.unwrap(); .unwrap();
let mut store = MerkleStore::new() let mut store = MerkleStore::from(&smt);
.with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, smt_leaves)
.unwrap();
let depth = smt.depth(); let depth = smt.depth();
let root = smt.root(); let root = smt.root();
let size_u64 = size as u64; let size_u64 = size as u64;

20
rustfmt.toml Normal file
View File

@@ -0,0 +1,20 @@
edition = "2021"
array_width = 80
attr_fn_like_width = 80
chain_width = 80
#condense_wildcard_suffixes = true
#enum_discrim_align_threshold = 40
fn_call_width = 80
#fn_single_line = true
#format_code_in_doc_comments = true
#format_macro_matchers = true
#format_strings = true
#group_imports = "StdExternalCrate"
#hex_literal_case = "Lower"
#imports_granularity = "Crate"
newline_style = "Unix"
#normalize_doc_attributes = true
#reorder_impl_items = true
single_line_if_else_max_width = 60
use_field_init_shorthand = true
use_try_shorthand = true

View File

@@ -270,10 +270,7 @@ impl Blake3_160 {
/// Zero-copy ref shrink to array. /// Zero-copy ref shrink to array.
fn shrink_bytes<const M: usize, const N: usize>(bytes: &[u8; M]) -> &[u8; N] { fn shrink_bytes<const M: usize, const N: usize>(bytes: &[u8; M]) -> &[u8; N] {
// compile-time assertion // compile-time assertion
assert!( assert!(M >= N, "N should fit in M so it can be safely transmuted into a smaller slice!");
M >= N,
"N should fit in M so it can be safely transmuted into a smaller slice!"
);
// safety: bytes len is asserted // safety: bytes len is asserted
unsafe { transmute(bytes) } unsafe { transmute(bytes) }
} }

View File

@@ -118,14 +118,13 @@ impl Ord for RpoDigest {
// finally, we use `Felt::inner` instead of `Felt::as_int` so we avoid performing a // finally, we use `Felt::inner` instead of `Felt::as_int` so we avoid performing a
// montgomery reduction for every limb. that is safe because every inner element of the // montgomery reduction for every limb. that is safe because every inner element of the
// digest is guaranteed to be in its canonical form (that is, `x in [0,p)`). // digest is guaranteed to be in its canonical form (that is, `x in [0,p)`).
self.0 self.0.iter().map(Felt::inner).zip(other.0.iter().map(Felt::inner)).fold(
.iter() Ordering::Equal,
.map(Felt::inner) |ord, (a, b)| match ord {
.zip(other.0.iter().map(Felt::inner))
.fold(Ordering::Equal, |ord, (a, b)| match ord {
Ordering::Equal => a.cmp(&b), Ordering::Equal => a.cmp(&b),
_ => ord, _ => ord,
}) },
)
} }
} }

View File

@@ -132,10 +132,7 @@ mod tests {
#[test] #[test]
fn test_node_index_value_too_high() { fn test_node_index_value_too_high() {
assert_eq!( assert_eq!(NodeIndex::new(0, 0).unwrap(), NodeIndex { depth: 0, value: 0 });
NodeIndex::new(0, 0).unwrap(),
NodeIndex { depth: 0, value: 0 }
);
match NodeIndex::new(0, 1) { match NodeIndex::new(0, 1) {
Err(MerkleError::InvalidIndex { depth, value }) => { Err(MerkleError::InvalidIndex { depth, value }) => {
assert_eq!(depth, 0); assert_eq!(depth, 0);

View File

@@ -109,10 +109,7 @@ impl MerkleTree {
index.move_up(); index.move_up();
} }
debug_assert!( debug_assert!(index.is_root(), "the path walk must go all the way to the root");
index.is_root(),
"the path walk must go all the way to the root"
);
Ok(path.into()) Ok(path.into())
} }
@@ -153,9 +150,11 @@ impl MerkleTree {
Ok(()) Ok(())
} }
/// An iterator over every inner node in the tree. The iterator order is unspecified. /// Returns n iterator over every inner node of this [MerkleTree].
pub fn inner_nodes(&self) -> MerkleTreeNodes<'_> { ///
MerkleTreeNodes { /// The iterator order is unspecified.
pub fn inner_nodes(&self) -> InnerNodeIterator<'_> {
InnerNodeIterator {
nodes: &self.nodes, nodes: &self.nodes,
index: 1, // index 0 is just padding, start at 1 index: 1, // index 0 is just padding, start at 1
} }
@@ -168,12 +167,12 @@ impl MerkleTree {
/// An iterator over every inner node of the [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. /// 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>, nodes: &'a Vec<Word>,
index: usize, index: usize,
} }
impl<'a> Iterator for MerkleTreeNodes<'a> { impl<'a> Iterator for InnerNodeIterator<'a> {
type Item = InnerNodeInfo; type Item = InnerNodeInfo;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@@ -195,6 +194,9 @@ impl<'a> Iterator for MerkleTreeNodes<'a> {
} }
} }
// UTILITY FUNCTIONS
// ================================================================================================
/// Utility to visualize a [MerkleTree] in text. /// Utility to visualize a [MerkleTree] in text.
pub fn tree_to_text(tree: &MerkleTree) -> Result<String, fmt::Error> { pub fn tree_to_text(tree: &MerkleTree) -> Result<String, fmt::Error> {
let indent = " "; let indent = " ";
@@ -248,12 +250,7 @@ mod tests {
use core::mem::size_of; use core::mem::size_of;
use proptest::prelude::*; use proptest::prelude::*;
const LEAVES4: [Word; 4] = [ const LEAVES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
int_to_node(1),
int_to_node(2),
int_to_node(3),
int_to_node(4),
];
const LEAVES8: [Word; 8] = [ const LEAVES8: [Word; 8] = [
int_to_node(1), int_to_node(1),
@@ -309,22 +306,10 @@ mod tests {
let (_, node2, node3) = compute_internal_nodes(); let (_, node2, node3) = compute_internal_nodes();
// check depth 2 // check depth 2
assert_eq!( assert_eq!(vec![LEAVES4[1], node3], *tree.get_path(NodeIndex::make(2, 0)).unwrap());
vec![LEAVES4[1], node3], assert_eq!(vec![LEAVES4[0], node3], *tree.get_path(NodeIndex::make(2, 1)).unwrap());
*tree.get_path(NodeIndex::make(2, 0)).unwrap() assert_eq!(vec![LEAVES4[3], node2], *tree.get_path(NodeIndex::make(2, 2)).unwrap());
); assert_eq!(vec![LEAVES4[2], node2], *tree.get_path(NodeIndex::make(2, 3)).unwrap());
assert_eq!(
vec![LEAVES4[0], node3],
*tree.get_path(NodeIndex::make(2, 1)).unwrap()
);
assert_eq!(
vec![LEAVES4[3], node2],
*tree.get_path(NodeIndex::make(2, 2)).unwrap()
);
assert_eq!(
vec![LEAVES4[2], node2],
*tree.get_path(NodeIndex::make(2, 3)).unwrap()
);
// check depth 1 // check depth 1
assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap()); assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap());

View File

@@ -54,8 +54,6 @@ impl MmrPeaks {
pub fn verify(&self, value: Word, opening: MmrProof) -> bool { pub fn verify(&self, value: Word, opening: MmrProof) -> bool {
let root = &self.peaks[opening.peak_index()]; let root = &self.peaks[opening.peak_index()];
opening opening.merkle_path.verify(opening.relative_pos() as u64, value, root)
.merkle_path
.verify(opening.relative_pos() as u64, value, root)
} }
} }

View File

@@ -280,10 +280,7 @@ impl<'a> Iterator for MmrNodes<'a> {
type Item = InnerNodeInfo; type Item = InnerNodeInfo;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
debug_assert!( debug_assert!(self.last_right.count_ones() <= 1, "last_right tracks zero or one element");
self.last_right.count_ones() <= 1,
"last_right tracks zero or one element"
);
// only parent nodes are emitted, remove the single node tree from the forest // only parent nodes are emitted, remove the single node tree from the forest
let target = self.mmr.forest & (usize::MAX << 1); let target = self.mmr.forest & (usize::MAX << 1);

View File

@@ -118,9 +118,7 @@ fn test_mmr_simple() {
postorder.push(LEAVES[2]); postorder.push(LEAVES[2]);
postorder.push(LEAVES[3]); postorder.push(LEAVES[3]);
postorder.push(*Rpo256::hash_elements(&[LEAVES[2], LEAVES[3]].concat())); postorder.push(*Rpo256::hash_elements(&[LEAVES[2], LEAVES[3]].concat()));
postorder.push(*Rpo256::hash_elements( postorder.push(*Rpo256::hash_elements(&[postorder[2], postorder[5]].concat()));
&[postorder[2], postorder[5]].concat(),
));
postorder.push(LEAVES[4]); postorder.push(LEAVES[4]);
postorder.push(LEAVES[5]); postorder.push(LEAVES[5]);
postorder.push(*Rpo256::hash_elements(&[LEAVES[4], LEAVES[5]].concat())); postorder.push(*Rpo256::hash_elements(&[LEAVES[4], LEAVES[5]].concat()));
@@ -201,10 +199,7 @@ fn test_mmr_open() {
let h23: Word = Rpo256::hash_elements(&LEAVES[2..4].concat()).into(); let h23: Word = Rpo256::hash_elements(&LEAVES[2..4].concat()).into();
// node at pos 7 is the root // node at pos 7 is the root
assert!( assert!(mmr.open(7).is_err(), "Element 7 is not in the tree, result should be None");
mmr.open(7).is_err(),
"Element 7 is not in the tree, result should be None"
);
// node at pos 6 is the root // node at pos 6 is the root
let empty: MerklePath = MerklePath::new(vec![]); let empty: MerklePath = MerklePath::new(vec![]);
@@ -297,41 +292,13 @@ fn test_mmr_open() {
#[test] #[test]
fn test_mmr_get() { fn test_mmr_get() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
assert_eq!( assert_eq!(mmr.get(0).unwrap(), LEAVES[0], "value at pos 0 must correspond");
mmr.get(0).unwrap(), assert_eq!(mmr.get(1).unwrap(), LEAVES[1], "value at pos 1 must correspond");
LEAVES[0], assert_eq!(mmr.get(2).unwrap(), LEAVES[2], "value at pos 2 must correspond");
"value at pos 0 must correspond" assert_eq!(mmr.get(3).unwrap(), LEAVES[3], "value at pos 3 must correspond");
); assert_eq!(mmr.get(4).unwrap(), LEAVES[4], "value at pos 4 must correspond");
assert_eq!( assert_eq!(mmr.get(5).unwrap(), LEAVES[5], "value at pos 5 must correspond");
mmr.get(1).unwrap(), assert_eq!(mmr.get(6).unwrap(), LEAVES[6], "value at pos 6 must correspond");
LEAVES[1],
"value at pos 1 must correspond"
);
assert_eq!(
mmr.get(2).unwrap(),
LEAVES[2],
"value at pos 2 must correspond"
);
assert_eq!(
mmr.get(3).unwrap(),
LEAVES[3],
"value at pos 3 must correspond"
);
assert_eq!(
mmr.get(4).unwrap(),
LEAVES[4],
"value at pos 4 must correspond"
);
assert_eq!(
mmr.get(5).unwrap(),
LEAVES[5],
"value at pos 5 must correspond"
);
assert_eq!(
mmr.get(6).unwrap(),
LEAVES[6],
"value at pos 6 must correspond"
);
assert!(mmr.get(7).is_err()); assert!(mmr.get(7).is_err());
} }
@@ -341,11 +308,7 @@ fn test_mmr_invariants() {
for v in 1..=1028 { for v in 1..=1028 {
mmr.add(int_to_node(v)); mmr.add(int_to_node(v));
let accumulator = mmr.accumulator(); let accumulator = mmr.accumulator();
assert_eq!( assert_eq!(v as usize, mmr.forest(), "MMR leaf count must increase by one on every add");
v as usize,
mmr.forest(),
"MMR leaf count must increase by one on every add"
);
assert_eq!( assert_eq!(
v as usize, accumulator.num_leaves, v as usize, accumulator.num_leaves,
"MMR and its accumulator must match leaves count" "MMR and its accumulator must match leaves count"
@@ -374,41 +337,21 @@ fn test_bit_position_iterator() {
assert_eq!(TrueBitPositionIterator::new(0).count(), 0); assert_eq!(TrueBitPositionIterator::new(0).count(), 0);
assert_eq!(TrueBitPositionIterator::new(0).rev().count(), 0); assert_eq!(TrueBitPositionIterator::new(0).rev().count(), 0);
assert_eq!( assert_eq!(TrueBitPositionIterator::new(1).collect::<Vec<u32>>(), vec![0]);
TrueBitPositionIterator::new(1).collect::<Vec<u32>>(), assert_eq!(TrueBitPositionIterator::new(1).rev().collect::<Vec<u32>>(), vec![0],);
vec![0]
);
assert_eq!(
TrueBitPositionIterator::new(1).rev().collect::<Vec<u32>>(),
vec![0],
);
assert_eq!( assert_eq!(TrueBitPositionIterator::new(2).collect::<Vec<u32>>(), vec![1]);
TrueBitPositionIterator::new(2).collect::<Vec<u32>>(), assert_eq!(TrueBitPositionIterator::new(2).rev().collect::<Vec<u32>>(), vec![1],);
vec![1]
);
assert_eq!(
TrueBitPositionIterator::new(2).rev().collect::<Vec<u32>>(),
vec![1],
);
assert_eq!( assert_eq!(TrueBitPositionIterator::new(3).collect::<Vec<u32>>(), vec![0, 1],);
TrueBitPositionIterator::new(3).collect::<Vec<u32>>(), assert_eq!(TrueBitPositionIterator::new(3).rev().collect::<Vec<u32>>(), vec![1, 0],);
vec![0, 1],
);
assert_eq!(
TrueBitPositionIterator::new(3).rev().collect::<Vec<u32>>(),
vec![1, 0],
);
assert_eq!( assert_eq!(
TrueBitPositionIterator::new(0b11010101).collect::<Vec<u32>>(), TrueBitPositionIterator::new(0b11010101).collect::<Vec<u32>>(),
vec![0, 2, 4, 6, 7], vec![0, 2, 4, 6, 7],
); );
assert_eq!( assert_eq!(
TrueBitPositionIterator::new(0b11010101) TrueBitPositionIterator::new(0b11010101).rev().collect::<Vec<u32>>(),
.rev()
.collect::<Vec<u32>>(),
vec![7, 6, 4, 2, 0], vec![7, 6, 4, 2, 0],
); );
} }
@@ -463,10 +406,7 @@ fn test_mmr_hash_peaks() {
// minimum length is 16 // minimum length is 16
let mut expected_peaks = [first_peak, second_peak, third_peak].to_vec(); let mut expected_peaks = [first_peak, second_peak, third_peak].to_vec();
expected_peaks.resize(16, [ZERO; WORD_SIZE]); expected_peaks.resize(16, [ZERO; WORD_SIZE]);
assert_eq!( assert_eq!(peaks.hash_peaks(), *Rpo256::hash_elements(&expected_peaks.as_slice().concat()));
peaks.hash_peaks(),
*Rpo256::hash_elements(&expected_peaks.as_slice().concat())
);
} }
#[test] #[test]

View File

@@ -27,7 +27,7 @@ mod simple_smt;
pub use simple_smt::SimpleSmt; pub use simple_smt::SimpleSmt;
mod mmr; mod mmr;
pub use mmr::{Mmr, MmrPeaks}; pub use mmr::{Mmr, MmrPeaks, MmrProof};
mod store; mod store;
pub use store::MerkleStore; pub use store::MerkleStore;

View File

@@ -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}; use core::ops::{Deref, DerefMut};
// MERKLE PATH // MERKLE PATH
@@ -22,6 +22,11 @@ impl MerklePath {
// PROVIDERS // 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. /// Computes the merkle root for this opening.
pub fn compute_root(&self, index: u64, node: Word) -> Result<Word, MerkleError> { pub fn compute_root(&self, index: u64, node: Word) -> Result<Word, MerkleError> {
let mut index = NodeIndex::new(self.depth(), index)?; let mut index = NodeIndex::new(self.depth(), index)?;
@@ -34,11 +39,6 @@ impl MerklePath {
Ok(root) 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. /// Verifies the Merkle opening proof towards the provided root.
/// ///
/// Returns `true` if `node` exists at `index` in a Merkle tree with `root`. /// Returns `true` if `node` exists at `index` in a Merkle tree with `root`.
@@ -48,6 +48,20 @@ impl MerklePath {
Err(_) => false, 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 { impl From<Vec<Word>> for MerklePath {
@@ -72,6 +86,9 @@ impl DerefMut for MerklePath {
} }
} }
// ITERATORS
// ================================================================================================
impl FromIterator<Word> for MerklePath { impl FromIterator<Word> for MerklePath {
fn from_iter<T: IntoIterator<Item = Word>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = Word>>(iter: T) -> Self {
Self::new(iter.into_iter().collect()) Self::new(iter.into_iter().collect())
@@ -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 // MERKLE PATH CONTAINERS
// ================================================================================================ // ================================================================================================
@@ -110,3 +160,25 @@ pub struct RootPath {
/// The path from `value` to `root` (exclusive). /// The path from `value` to `root` (exclusive).
pub path: MerklePath, 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);
}
}

View File

@@ -34,9 +34,7 @@ impl MerklePathSet {
where where
I: IntoIterator<Item = (u64, Word, MerklePath)>, I: IntoIterator<Item = (u64, Word, MerklePath)>,
{ {
paths paths.into_iter().try_fold(self, |mut set, (index, value, path)| {
.into_iter()
.try_fold(self, |mut set, (index, value, path)| {
set.add_path(index, value, path)?; set.add_path(index, value, path)?;
Ok(set) Ok(set)
}) })
@@ -291,14 +289,9 @@ mod tests {
let hash_6 = int_to_node(6); let hash_6 = int_to_node(6);
let index = 6_u64; let index = 6_u64;
let depth = 3_u8; let depth = 3_u8;
let set = MerklePathSet::new(depth) let set = MerklePathSet::new(depth).with_paths([(index, hash_6, path_6.into())]).unwrap();
.with_paths([(index, hash_6, path_6.into())])
.unwrap();
assert_eq!( assert_eq!(int_to_node(6u64), set.get_node(NodeIndex::make(depth, index)).unwrap());
int_to_node(6u64),
set.get_node(NodeIndex::make(depth, index)).unwrap()
);
} }
#[test] #[test]

View File

@@ -131,12 +131,7 @@ impl SimpleSmt {
Err(MerkleError::DepthTooBig(index.depth() as u64)) Err(MerkleError::DepthTooBig(index.depth() as u64))
} else if index.depth() == self.depth() { } else if index.depth() == self.depth() {
self.get_leaf_node(index.value()) self.get_leaf_node(index.value())
.or_else(|| { .or_else(|| self.empty_hashes.get(index.depth() as usize).copied().map(Word::from))
self.empty_hashes
.get(index.depth() as usize)
.copied()
.map(Word::from)
})
.ok_or(MerkleError::NodeNotInSet(index.value())) .ok_or(MerkleError::NodeNotInSet(index.value()))
} else { } else {
let branch_node = self.get_branch_node(&index); let branch_node = self.get_branch_node(&index);
@@ -217,11 +212,7 @@ impl SimpleSmt {
let is_right = index.is_value_odd(); let is_right = index.is_value_odd();
index.move_up(); index.move_up();
let BranchNode { left, right } = self.get_branch_node(&index); let BranchNode { left, right } = self.get_branch_node(&index);
let (left, right) = if is_right { let (left, right) = if is_right { (left, value) } else { (value, right) };
(left, value)
} else {
(value, right)
};
self.insert_branch_node(index, left, right); self.insert_branch_node(index, left, right);
value = Rpo256::merge(&[left, right]); value = Rpo256::merge(&[left, right]);
} }

View File

@@ -8,12 +8,7 @@ use rand_utils::prng_array;
const KEYS4: [u64; 4] = [0, 1, 2, 3]; const KEYS4: [u64; 4] = [0, 1, 2, 3];
const KEYS8: [u64; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; const KEYS8: [u64; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
const VALUES4: [Word; 4] = [ const VALUES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
int_to_node(1),
int_to_node(2),
int_to_node(3),
int_to_node(4),
];
const VALUES8: [Word; 8] = [ const VALUES8: [Word; 8] = [
int_to_node(1), int_to_node(1),
@@ -56,8 +51,7 @@ fn build_sparse_tree() {
let key = 6; let key = 6;
let new_node = int_to_node(7); let new_node = int_to_node(7);
values[key as usize] = new_node; values[key as usize] = new_node;
smt.insert_leaf(key, new_node) smt.insert_leaf(key, new_node).expect("Failed to insert leaf");
.expect("Failed to insert leaf");
let mt2 = MerkleTree::new(values.clone()).unwrap(); let mt2 = MerkleTree::new(values.clone()).unwrap();
assert_eq!(mt2.root(), smt.root()); assert_eq!(mt2.root(), smt.root());
assert_eq!( assert_eq!(
@@ -69,8 +63,7 @@ fn build_sparse_tree() {
let key = 2; let key = 2;
let new_node = int_to_node(3); let new_node = int_to_node(3);
values[key as usize] = new_node; values[key as usize] = new_node;
smt.insert_leaf(key, new_node) smt.insert_leaf(key, new_node).expect("Failed to insert leaf");
.expect("Failed to insert leaf");
let mt3 = MerkleTree::new(values).unwrap(); let mt3 = MerkleTree::new(values).unwrap();
assert_eq!(mt3.root(), smt.root()); assert_eq!(mt3.root(), smt.root());
assert_eq!( assert_eq!(
@@ -116,22 +109,10 @@ fn get_path() {
let (_, node2, node3) = compute_internal_nodes(); let (_, node2, node3) = compute_internal_nodes();
// check depth 2 // check depth 2
assert_eq!( assert_eq!(vec![VALUES4[1], node3], *tree.get_path(NodeIndex::make(2, 0)).unwrap());
vec![VALUES4[1], node3], assert_eq!(vec![VALUES4[0], node3], *tree.get_path(NodeIndex::make(2, 1)).unwrap());
*tree.get_path(NodeIndex::make(2, 0)).unwrap() assert_eq!(vec![VALUES4[3], node2], *tree.get_path(NodeIndex::make(2, 2)).unwrap());
); assert_eq!(vec![VALUES4[2], node2], *tree.get_path(NodeIndex::make(2, 3)).unwrap());
assert_eq!(
vec![VALUES4[0], node3],
*tree.get_path(NodeIndex::make(2, 1)).unwrap()
);
assert_eq!(
vec![VALUES4[3], node2],
*tree.get_path(NodeIndex::make(2, 2)).unwrap()
);
assert_eq!(
vec![VALUES4[2], node2],
*tree.get_path(NodeIndex::make(2, 3)).unwrap()
);
// check depth 1 // check depth 1
assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap()); assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap());

View File

@@ -1,7 +1,7 @@
use super::mmr::{Mmr, MmrPeaks}; use super::mmr::Mmr;
use super::{ use super::{
BTreeMap, EmptySubtreeRoots, MerkleError, MerklePath, MerklePathSet, MerkleTree, NodeIndex, BTreeMap, EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, MerklePathSet, MerkleTree,
RootPath, Rpo256, RpoDigest, SimpleSmt, ValuePath, Vec, Word, NodeIndex, RootPath, Rpo256, RpoDigest, SimpleSmt, ValuePath, Vec, Word,
}; };
use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
@@ -47,9 +47,13 @@ pub struct Node {
/// // the store is initialized with the SMT empty nodes /// // the store is initialized with the SMT empty nodes
/// assert_eq!(store.num_internal_nodes(), 255); /// assert_eq!(store.num_internal_nodes(), 255);
/// ///
/// let tree1 = MerkleTree::new(vec![A, B, C, D, E, F, G, H0]).unwrap();
/// let tree2 = MerkleTree::new(vec![A, B, C, D, E, F, G, H1]).unwrap();
///
/// // populates the store with two merkle trees, common nodes are shared /// // populates the store with two merkle trees, common nodes are shared
/// store.add_merkle_tree([A, B, C, D, E, F, G, H0]); /// store
/// store.add_merkle_tree([A, B, C, D, E, F, G, H1]); /// .extend(tree1.inner_nodes())
/// .extend(tree2.inner_nodes());
/// ///
/// // every leaf except the last are the same /// // every leaf except the last are the same
/// for i in 0..7 { /// for i in 0..7 {
@@ -111,60 +115,6 @@ impl MerkleStore {
MerkleStore { nodes } MerkleStore { nodes }
} }
/// Appends the provided merkle tree represented by its `leaves` to the set.
pub fn with_merkle_tree<I>(mut self, leaves: I) -> Result<Self, MerkleError>
where
I: IntoIterator<Item = Word>,
{
self.add_merkle_tree(leaves)?;
Ok(self)
}
/// Appends the provided Sparse Merkle tree represented by its `entries` to the set.
///
/// 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
R: IntoIterator<IntoIter = I>,
I: Iterator<Item = (u64, Word)> + ExactSizeIterator,
{
self.add_sparse_merkle_tree(depth, entries)?;
Ok(self)
}
/// Appends the provided merkle path set.
pub fn with_merkle_path(
mut self,
index_value: u64,
node: Word,
path: MerklePath,
) -> Result<Self, MerkleError> {
self.add_merkle_path(index_value, node, path)?;
Ok(self)
}
/// Appends the provided merkle path set.
pub fn with_merkle_paths<I>(mut self, paths: I) -> Result<Self, MerkleError>
where
I: IntoIterator<Item = (u64, Word, MerklePath)>,
{
self.add_merkle_paths(paths)?;
Ok(self)
}
/// Appends the provided [Mmr] represented by its `leaves` to the set.
pub fn with_mmr<I>(mut self, leaves: I) -> Result<Self, MerkleError>
where
I: IntoIterator<Item = Word>,
{
self.add_mmr(leaves)?;
Ok(self)
}
// PUBLIC ACCESSORS // PUBLIC ACCESSORS
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
@@ -184,15 +134,11 @@ impl MerkleStore {
let mut hash: RpoDigest = root.into(); let mut hash: RpoDigest = root.into();
// corner case: check the root is in the store when called with index `NodeIndex::root()` // corner case: check the root is in the store when called with index `NodeIndex::root()`
self.nodes self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash.into()))?;
.get(&hash)
.ok_or(MerkleError::RootNotInStore(hash.into()))?;
for i in (0..index.depth()).rev() { for i in (0..index.depth()).rev() {
let node = self let node =
.nodes self.nodes.get(&hash).ok_or(MerkleError::NodeNotInStore(hash.into(), index))?;
.get(&hash)
.ok_or(MerkleError::NodeNotInStore(hash.into(), index))?;
let bit = (index.value() >> i) & 1; let bit = (index.value() >> i) & 1;
hash = if bit == 0 { node.left } else { node.right } hash = if bit == 0 { node.left } else { node.right }
@@ -215,15 +161,11 @@ impl MerkleStore {
let mut path = Vec::with_capacity(index.depth().into()); let mut path = Vec::with_capacity(index.depth().into());
// corner case: check the root is in the store when called with index `NodeIndex::root()` // corner case: check the root is in the store when called with index `NodeIndex::root()`
self.nodes self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash.into()))?;
.get(&hash)
.ok_or(MerkleError::RootNotInStore(hash.into()))?;
for i in (0..index.depth()).rev() { for i in (0..index.depth()).rev() {
let node = self let node =
.nodes self.nodes.get(&hash).ok_or(MerkleError::NodeNotInStore(hash.into(), index))?;
.get(&hash)
.ok_or(MerkleError::NodeNotInStore(hash.into(), index))?;
let bit = (index.value() >> i) & 1; let bit = (index.value() >> i) & 1;
hash = if bit == 0 { hash = if bit == 0 {
@@ -302,11 +244,7 @@ impl MerkleStore {
}; };
// traverse down // traverse down
hash = if path & 1 == 0 { hash = if path & 1 == 0 { children.left } else { children.right };
children.left
} else {
children.right
};
path >>= 1; path >>= 1;
} }
@@ -322,68 +260,21 @@ impl MerkleStore {
// STATE MUTATORS // STATE MUTATORS
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
/// Adds all the nodes of a Merkle tree represented by `leaves`. /// Adds a sequence of nodes yielded by the provided iterator into the store.
/// pub fn extend<I>(&mut self, iter: I) -> &mut MerkleStore
/// This will instantiate a Merkle tree using `leaves` and include all the nodes into the
/// store.
///
/// # Errors
///
/// This method may return the following errors:
/// - `DepthTooSmall` if leaves is empty or contains only 1 element
/// - `NumLeavesNotPowerOfTwo` if the number of leaves is not a power-of-two
pub fn add_merkle_tree<I>(&mut self, leaves: I) -> Result<Word, MerkleError>
where where
I: IntoIterator<Item = Word>, I: Iterator<Item = InnerNodeInfo>,
{ {
let leaves: Vec<_> = leaves.into_iter().collect(); for node in iter {
if leaves.len() < 2 { let value: RpoDigest = node.value.into();
return Err(MerkleError::DepthTooSmall(leaves.len() as u8)); let left: RpoDigest = node.left.into();
let right: RpoDigest = node.right.into();
debug_assert_eq!(Rpo256::merge(&[left, right]), value);
self.nodes.insert(value, Node { left, right });
} }
let tree = MerkleTree::new(leaves)?; self
for node in tree.inner_nodes() {
self.nodes.insert(
node.value.into(),
Node {
left: node.left.into(),
right: node.right.into(),
},
);
}
Ok(tree.root())
}
/// Adds a Sparse Merkle tree defined by the specified `entries` to the store, and returns the
/// root of the added tree.
///
/// The entries are expected to contain tuples of `(index, node)` describing nodes in the tree
/// at `depth`.
///
/// # Errors
/// Returns an error if the provided `depth` is greater than [SimpleSmt::MAX_DEPTH].
pub fn add_sparse_merkle_tree<R, I>(
&mut self,
depth: u8,
entries: R,
) -> Result<Word, MerkleError>
where
R: IntoIterator<IntoIter = I>,
I: Iterator<Item = (u64, Word)> + ExactSizeIterator,
{
let smt = SimpleSmt::new(depth)?.with_leaves(entries)?;
for node in smt.inner_nodes() {
self.nodes.insert(
node.value.into(),
Node {
left: node.left.into(),
right: node.right.into(),
},
);
}
Ok(smt.root())
} }
/// Adds all the nodes of a Merkle path represented by `path`, opening to `node`. Returns the /// Adds all the nodes of a Merkle path represented by `path`, opening to `node`. Returns the
@@ -393,31 +284,21 @@ impl MerkleStore {
/// include all the nodes into the store. /// include all the nodes into the store.
pub fn add_merkle_path( pub fn add_merkle_path(
&mut self, &mut self,
index_value: u64, index: u64,
mut node: Word, node: Word,
path: MerklePath, path: MerklePath,
) -> Result<Word, MerkleError> { ) -> Result<Word, MerkleError> {
let mut index = NodeIndex::new(path.len() as u8, index_value)?; let root = path.inner_nodes(index, node)?.fold(Word::default(), |_, node| {
let value: RpoDigest = node.value.into();
let left: RpoDigest = node.left.into();
let right: RpoDigest = node.right.into();
for sibling in path { debug_assert_eq!(Rpo256::merge(&[left, right]), value);
let (left, right) = match index.is_value_odd() { self.nodes.insert(value, Node { left, right });
true => (sibling, node),
false => (node, sibling),
};
let parent = Rpo256::merge(&[left.into(), right.into()]);
self.nodes.insert(
parent,
Node {
left: left.into(),
right: right.into(),
},
);
index.move_up(); node.value
node = parent.into(); });
} Ok(root)
Ok(node)
} }
/// Adds all the nodes of multiple Merkle paths into the store. /// Adds all the nodes of multiple Merkle paths into the store.
@@ -447,25 +328,6 @@ impl MerkleStore {
Ok(root) Ok(root)
} }
/// Appends the provided [Mmr] into the store.
pub fn add_mmr<I>(&mut self, leaves: I) -> Result<MmrPeaks, MerkleError>
where
I: IntoIterator<Item = Word>,
{
let mmr = Mmr::from(leaves);
for node in mmr.inner_nodes() {
self.nodes.insert(
node.value.into(),
Node {
left: node.left.into(),
right: node.right.into(),
},
);
}
Ok(mmr.accumulator())
}
/// Sets a node to `value`. /// Sets a node to `value`.
/// ///
/// # Errors /// # Errors
@@ -490,27 +352,62 @@ impl MerkleStore {
Ok(RootPath { root, path }) Ok(RootPath { root, path })
} }
/// Merges two elements and adds the resulting node into the store.
///
/// Merges arbitrary values. They may be leafs, nodes, or a mixture of both.
pub fn merge_roots(&mut self, root1: Word, root2: Word) -> Result<Word, MerkleError> { pub fn merge_roots(&mut self, root1: Word, root2: Word) -> Result<Word, MerkleError> {
let root1: RpoDigest = root1.into(); let left: RpoDigest = root1.into();
let root2: RpoDigest = root2.into(); let right: RpoDigest = root2.into();
if !self.nodes.contains_key(&root1) { let parent = Rpo256::merge(&[left, right]);
Err(MerkleError::NodeNotInStore(root1.into(), NodeIndex::root())) self.nodes.insert(parent, Node { left, right });
} else if !self.nodes.contains_key(&root1) {
Err(MerkleError::NodeNotInStore(root2.into(), NodeIndex::root()))
} else {
let parent: Word = Rpo256::merge(&[root1, root2]).into();
self.nodes.insert(
parent.into(),
Node {
left: root1,
right: root2,
},
);
Ok(parent) Ok(parent.into())
} }
} }
// CONVERSIONS
// ================================================================================================
impl From<&MerkleTree> for MerkleStore {
fn from(value: &MerkleTree) -> Self {
let mut store = MerkleStore::new();
store.extend(value.inner_nodes());
store
}
}
impl From<&SimpleSmt> for MerkleStore {
fn from(value: &SimpleSmt) -> Self {
let mut store = MerkleStore::new();
store.extend(value.inner_nodes());
store
}
}
impl From<&Mmr> for MerkleStore {
fn from(value: &Mmr) -> Self {
let mut store = MerkleStore::new();
store.extend(value.inner_nodes());
store
}
}
impl FromIterator<InnerNodeInfo> for MerkleStore {
fn from_iter<T: IntoIterator<Item = InnerNodeInfo>>(iter: T) -> Self {
let mut store = MerkleStore::new();
store.extend(iter.into_iter());
store
}
}
// ITERATORS
// ================================================================================================
impl Extend<InnerNodeInfo> for MerkleStore {
fn extend<T: IntoIterator<Item = InnerNodeInfo>>(&mut self, iter: T) {
self.extend(iter.into_iter());
}
} }
// SERIALIZATION // SERIALIZATION

View File

@@ -1,26 +1,21 @@
use super::*; use super::*;
use crate::{ use crate::{
hash::rpo::Rpo256, hash::rpo::Rpo256,
merkle::{int_to_node, MerklePathSet}, merkle::{int_to_node, MerklePathSet, MerkleTree, SimpleSmt},
Felt, Word, WORD_SIZE, ZERO, Felt, Word, WORD_SIZE, ZERO,
}; };
#[cfg(std)] #[cfg(feature = "std")]
use std::error::Error; use std::error::Error;
const KEYS4: [u64; 4] = [0, 1, 2, 3]; const KEYS4: [u64; 4] = [0, 1, 2, 3];
const LEAVES4: [Word; 4] = [ const LEAVES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
int_to_node(1),
int_to_node(2),
int_to_node(3),
int_to_node(4),
];
const EMPTY: Word = [ZERO; WORD_SIZE]; const EMPTY: Word = [ZERO; WORD_SIZE];
#[test] #[test]
fn test_root_not_in_store() -> Result<(), MerkleError> { fn test_root_not_in_store() -> Result<(), MerkleError> {
let mtree = MerkleTree::new(LEAVES4.to_vec())?; let mtree = MerkleTree::new(LEAVES4.to_vec())?;
let store = MerkleStore::default().with_merkle_tree(LEAVES4)?; let store = MerkleStore::from(&mtree);
assert_eq!( assert_eq!(
store.get_node(LEAVES4[0], NodeIndex::make(mtree.depth(), 0)), store.get_node(LEAVES4[0], NodeIndex::make(mtree.depth(), 0)),
Err(MerkleError::RootNotInStore(LEAVES4[0])), Err(MerkleError::RootNotInStore(LEAVES4[0])),
@@ -37,10 +32,8 @@ fn test_root_not_in_store() -> Result<(), MerkleError> {
#[test] #[test]
fn test_merkle_tree() -> Result<(), MerkleError> { fn test_merkle_tree() -> Result<(), MerkleError> {
let mut store = MerkleStore::default();
let mtree = MerkleTree::new(LEAVES4.to_vec())?; let mtree = MerkleTree::new(LEAVES4.to_vec())?;
store.add_merkle_tree(LEAVES4.to_vec())?; let store = MerkleStore::from(&mtree);
// STORE LEAVES ARE CORRECT ============================================================== // STORE LEAVES ARE CORRECT ==============================================================
// checks the leaves in the store corresponds to the expected values // checks the leaves in the store corresponds to the expected values
@@ -90,9 +83,7 @@ fn test_merkle_tree() -> Result<(), MerkleError> {
// STORE MERKLE PATH MATCHS ============================================================== // STORE MERKLE PATH MATCHS ==============================================================
// assert the merkle path returned by the store is the same as the one in the tree // assert the merkle path returned by the store is the same as the one in the tree
let result = store let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 0)).unwrap();
.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 0))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[0], result.value, LEAVES4[0], result.value,
"Value for merkle path at index 0 must match leaf value" "Value for merkle path at index 0 must match leaf value"
@@ -103,9 +94,7 @@ fn test_merkle_tree() -> Result<(), MerkleError> {
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore" "merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 1)).unwrap();
.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 1))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[1], result.value, LEAVES4[1], result.value,
"Value for merkle path at index 0 must match leaf value" "Value for merkle path at index 0 must match leaf value"
@@ -116,9 +105,7 @@ fn test_merkle_tree() -> Result<(), MerkleError> {
"merkle path for index 1 must be the same for the MerkleTree and MerkleStore" "merkle path for index 1 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 2)).unwrap();
.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 2))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[2], result.value, LEAVES4[2], result.value,
"Value for merkle path at index 0 must match leaf value" "Value for merkle path at index 0 must match leaf value"
@@ -129,9 +116,7 @@ fn test_merkle_tree() -> Result<(), MerkleError> {
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore" "merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 3)).unwrap();
.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 3))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[3], result.value, LEAVES4[3], result.value,
"Value for merkle path at index 0 must match leaf value" "Value for merkle path at index 0 must match leaf value"
@@ -172,10 +157,7 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> {
let index = NodeIndex::make(depth, 0); let index = NodeIndex::make(depth, 0);
let store_path = store.get_path(smt.root(), index)?; let store_path = store.get_path(smt.root(), index)?;
let smt_path = smt.get_path(index)?; let smt_path = smt.get_path(index)?;
assert_eq!( assert_eq!(store_path.value, EMPTY, "the leaf of an empty tree is always ZERO");
store_path.value, EMPTY,
"the leaf of an empty tree is always ZERO"
);
assert_eq!( assert_eq!(
store_path.path, smt_path, store_path.path, smt_path,
"the returned merkle path does not match the computed values" "the returned merkle path does not match the computed values"
@@ -192,55 +174,41 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> {
#[test] #[test]
fn test_get_invalid_node() { fn test_get_invalid_node() {
let mut store = MerkleStore::default();
let mtree = MerkleTree::new(LEAVES4.to_vec()).expect("creating a merkle tree must work"); let mtree = MerkleTree::new(LEAVES4.to_vec()).expect("creating a merkle tree must work");
store let store = MerkleStore::from(&mtree);
.add_merkle_tree(LEAVES4.to_vec())
.expect("adding a merkle tree to the store must work");
let _ = store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)); let _ = store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3));
} }
#[test] #[test]
fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> { fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> {
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(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()))
.unwrap(); .unwrap();
let store = MerkleStore::from(&smt);
let idx = NodeIndex::make(1, 0); let idx = NodeIndex::make(1, 0);
assert_eq!(smt.get_node(idx).unwrap(), leaves2[0]); assert_eq!(smt.get_node(idx).unwrap(), leaves2[0]);
assert_eq!( assert_eq!(store.get_node(smt.root(), idx).unwrap(), smt.get_node(idx).unwrap());
store.get_node(smt.root(), idx).unwrap(),
smt.get_node(idx).unwrap()
);
let idx = NodeIndex::make(1, 1); let idx = NodeIndex::make(1, 1);
assert_eq!(smt.get_node(idx).unwrap(), leaves2[1]); assert_eq!(smt.get_node(idx).unwrap(), leaves2[1]);
assert_eq!( assert_eq!(store.get_node(smt.root(), idx).unwrap(), smt.get_node(idx).unwrap());
store.get_node(smt.root(), idx).unwrap(),
smt.get_node(idx).unwrap()
);
Ok(()) Ok(())
} }
#[test] #[test]
fn test_sparse_merkle_tree() -> Result<(), MerkleError> { fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
let mut store = MerkleStore::default();
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()
.with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter())) .with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter()))
.unwrap(); .unwrap();
let store = MerkleStore::from(&smt);
// STORE LEAVES ARE CORRECT ============================================================== // STORE LEAVES ARE CORRECT ==============================================================
// checks the leaves in the store corresponds to the expected values // checks the leaves in the store corresponds to the expected values
assert_eq!( assert_eq!(
@@ -299,9 +267,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
// STORE MERKLE PATH MATCHS ============================================================== // STORE MERKLE PATH MATCHS ==============================================================
// assert the merkle path returned by the store is the same as the one in the tree // assert the merkle path returned by the store is the same as the one in the tree
let result = store let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 0)).unwrap();
.get_path(smt.root(), NodeIndex::make(smt.depth(), 0))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[0], result.value, LEAVES4[0], result.value,
"Value for merkle path at index 0 must match leaf value" "Value for merkle path at index 0 must match leaf value"
@@ -312,9 +278,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore" "merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 1)).unwrap();
.get_path(smt.root(), NodeIndex::make(smt.depth(), 1))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[1], result.value, LEAVES4[1], result.value,
"Value for merkle path at index 1 must match leaf value" "Value for merkle path at index 1 must match leaf value"
@@ -325,9 +289,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
"merkle path for index 1 must be the same for the MerkleTree and MerkleStore" "merkle path for index 1 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 2)).unwrap();
.get_path(smt.root(), NodeIndex::make(smt.depth(), 2))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[2], result.value, LEAVES4[2], result.value,
"Value for merkle path at index 2 must match leaf value" "Value for merkle path at index 2 must match leaf value"
@@ -338,9 +300,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
"merkle path for index 2 must be the same for the MerkleTree and MerkleStore" "merkle path for index 2 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 3)).unwrap();
.get_path(smt.root(), NodeIndex::make(smt.depth(), 3))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[3], result.value, LEAVES4[3], result.value,
"Value for merkle path at index 3 must match leaf value" "Value for merkle path at index 3 must match leaf value"
@@ -351,13 +311,8 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
"merkle path for index 3 must be the same for the MerkleTree and MerkleStore" "merkle path for index 3 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 4)).unwrap();
.get_path(smt.root(), NodeIndex::make(smt.depth(), 4)) assert_eq!(EMPTY, result.value, "Value for merkle path at index 4 must match leaf value");
.unwrap();
assert_eq!(
EMPTY, result.value,
"Value for merkle path at index 4 must match leaf value"
);
assert_eq!( assert_eq!(
smt.get_path(NodeIndex::make(smt.depth(), 4)), smt.get_path(NodeIndex::make(smt.depth(), 4)),
Ok(result.path), Ok(result.path),
@@ -391,9 +346,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> {
]; ];
let mut store = MerkleStore::default(); let mut store = MerkleStore::default();
store store.add_merkle_paths(paths.clone()).expect("the valid paths must work");
.add_merkle_paths(paths.clone())
.expect("the valid paths must work");
let depth = 2; let depth = 2;
let set = MerklePathSet::new(depth).with_paths(paths).unwrap(); let set = MerklePathSet::new(depth).with_paths(paths).unwrap();
@@ -446,9 +399,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> {
// STORE MERKLE PATH MATCHS ============================================================== // STORE MERKLE PATH MATCHS ==============================================================
// assert the merkle path returned by the store is the same as the one in the set // assert the merkle path returned by the store is the same as the one in the set
let result = store let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 0)).unwrap();
.get_path(set.root(), NodeIndex::make(set.depth(), 0))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[0], result.value, LEAVES4[0], result.value,
"Value for merkle path at index 0 must match leaf value" "Value for merkle path at index 0 must match leaf value"
@@ -459,9 +410,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> {
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore" "merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 1)).unwrap();
.get_path(set.root(), NodeIndex::make(set.depth(), 1))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[1], result.value, LEAVES4[1], result.value,
"Value for merkle path at index 0 must match leaf value" "Value for merkle path at index 0 must match leaf value"
@@ -472,9 +421,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> {
"merkle path for index 1 must be the same for the MerkleTree and MerkleStore" "merkle path for index 1 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 2)).unwrap();
.get_path(set.root(), NodeIndex::make(set.depth(), 2))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[2], result.value, LEAVES4[2], result.value,
"Value for merkle path at index 0 must match leaf value" "Value for merkle path at index 0 must match leaf value"
@@ -485,9 +432,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> {
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore" "merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
); );
let result = store let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 3)).unwrap();
.get_path(set.root(), NodeIndex::make(set.depth(), 3))
.unwrap();
assert_eq!( assert_eq!(
LEAVES4[3], result.value, LEAVES4[3], result.value,
"Value for merkle path at index 0 must match leaf value" "Value for merkle path at index 0 must match leaf value"
@@ -519,7 +464,8 @@ fn wont_open_to_different_depth_root() {
// For this example, the depth of the Merkle tree is 1, as we have only two leaves. Here we // For this example, the depth of the Merkle tree is 1, as we have only two leaves. Here we
// attempt to fetch a node on the maximum depth, and it should fail because the root shouldn't // attempt to fetch a node on the maximum depth, and it should fail because the root shouldn't
// exist for the set. // exist for the set.
let store = MerkleStore::default().with_merkle_tree([a, b]).unwrap(); let mtree = MerkleTree::new(vec![a, b]).unwrap();
let store = MerkleStore::from(&mtree);
let index = NodeIndex::root(); let index = NodeIndex::root();
let err = store.get_node(root, index).err().unwrap(); let err = store.get_node(root, index).err().unwrap();
assert_eq!(err, MerkleError::RootNotInStore(root)); assert_eq!(err, MerkleError::RootNotInStore(root));
@@ -546,13 +492,9 @@ fn store_path_opens_from_leaf() {
let root = Rpo256::merge(&[m.into(), n.into()]); let root = Rpo256::merge(&[m.into(), n.into()]);
let store = MerkleStore::default() let mtree = MerkleTree::new(vec![a, b, c, d, e, f, g, h]).unwrap();
.with_merkle_tree([a, b, c, d, e, f, g, h]) let store = MerkleStore::from(&mtree);
.unwrap(); let path = store.get_path(root.into(), NodeIndex::make(3, 1)).unwrap().path;
let path = store
.get_path(root.into(), NodeIndex::make(3, 1))
.unwrap()
.path;
let expected = MerklePath::new([a.into(), j.into(), n.into()].to_vec()); let expected = MerklePath::new([a.into(), j.into(), n.into()].to_vec());
assert_eq!(path, expected); assert_eq!(path, expected);
@@ -561,23 +503,19 @@ fn store_path_opens_from_leaf() {
#[test] #[test]
fn test_set_node() -> Result<(), MerkleError> { fn test_set_node() -> Result<(), MerkleError> {
let mtree = MerkleTree::new(LEAVES4.to_vec())?; let mtree = MerkleTree::new(LEAVES4.to_vec())?;
let mut store = MerkleStore::default().with_merkle_tree(LEAVES4)?; let mut store = MerkleStore::from(&mtree);
let value = int_to_node(42); let value = int_to_node(42);
let index = NodeIndex::make(mtree.depth(), 0); let index = NodeIndex::make(mtree.depth(), 0);
let new_root = store.set_node(mtree.root(), index, value)?.root; let new_root = store.set_node(mtree.root(), index, value)?.root;
assert_eq!( assert_eq!(store.get_node(new_root, index), Ok(value), "Value must have changed");
store.get_node(new_root, index),
Ok(value),
"Value must have changed"
);
Ok(()) Ok(())
} }
#[test] #[test]
fn test_constructors() -> Result<(), MerkleError> { fn test_constructors() -> Result<(), MerkleError> {
let store = MerkleStore::new().with_merkle_tree(LEAVES4)?;
let mtree = MerkleTree::new(LEAVES4.to_vec())?; let mtree = MerkleTree::new(LEAVES4.to_vec())?;
let store = MerkleStore::from(&mtree);
let depth = mtree.depth(); let depth = mtree.depth();
let leaves = 2u64.pow(depth.into()); let leaves = 2u64.pow(depth.into());
@@ -588,12 +526,11 @@ fn test_constructors() -> Result<(), MerkleError> {
} }
let depth = 32; let depth = 32;
let store = MerkleStore::default()
.with_sparse_merkle_tree(depth, KEYS4.into_iter().zip(LEAVES4.into_iter()))?;
let smt = SimpleSmt::new(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();
let store = MerkleStore::from(&smt);
let depth = smt.depth(); let depth = smt.depth();
for key in KEYS4 { for key in KEYS4 {
@@ -604,34 +541,20 @@ fn test_constructors() -> Result<(), MerkleError> {
let d = 2; let d = 2;
let paths = [ let paths = [
( (0, LEAVES4[0], mtree.get_path(NodeIndex::make(d, 0)).unwrap()),
0, (1, LEAVES4[1], mtree.get_path(NodeIndex::make(d, 1)).unwrap()),
LEAVES4[0], (2, LEAVES4[2], mtree.get_path(NodeIndex::make(d, 2)).unwrap()),
mtree.get_path(NodeIndex::make(d, 0)).unwrap(), (3, LEAVES4[3], mtree.get_path(NodeIndex::make(d, 3)).unwrap()),
),
(
1,
LEAVES4[1],
mtree.get_path(NodeIndex::make(d, 1)).unwrap(),
),
(
2,
LEAVES4[2],
mtree.get_path(NodeIndex::make(d, 2)).unwrap(),
),
(
3,
LEAVES4[3],
mtree.get_path(NodeIndex::make(d, 3)).unwrap(),
),
]; ];
let store1 = MerkleStore::default().with_merkle_paths(paths.clone())?; let mut store1 = MerkleStore::default();
let store2 = MerkleStore::default() store1.add_merkle_paths(paths.clone())?;
.with_merkle_path(0, LEAVES4[0], mtree.get_path(NodeIndex::make(d, 0))?)?
.with_merkle_path(1, LEAVES4[1], mtree.get_path(NodeIndex::make(d, 1))?)? let mut store2 = MerkleStore::default();
.with_merkle_path(2, LEAVES4[2], mtree.get_path(NodeIndex::make(d, 2))?)? store2.add_merkle_path(0, LEAVES4[0], mtree.get_path(NodeIndex::make(d, 0))?)?;
.with_merkle_path(3, LEAVES4[3], mtree.get_path(NodeIndex::make(d, 3))?)?; store2.add_merkle_path(1, LEAVES4[1], mtree.get_path(NodeIndex::make(d, 1))?)?;
store2.add_merkle_path(2, LEAVES4[2], mtree.get_path(NodeIndex::make(d, 2))?)?;
store2.add_merkle_path(3, LEAVES4[3], mtree.get_path(NodeIndex::make(d, 3))?)?;
let set = MerklePathSet::new(d).with_paths(paths).unwrap(); let set = MerklePathSet::new(d).with_paths(paths).unwrap();
for key in [0, 1, 2, 3] { for key in [0, 1, 2, 3] {
@@ -792,17 +715,15 @@ fn get_leaf_depth_works_with_depth_8() {
// duplicate the tree on `a` and assert the depth is short-circuited by such sub-tree // duplicate the tree on `a` and assert the depth is short-circuited by such sub-tree
let index = NodeIndex::new(8, a).unwrap(); let index = NodeIndex::new(8, a).unwrap();
root = store.set_node(root, index, root).unwrap().root; root = store.set_node(root, index, root).unwrap().root;
assert_eq!( assert_eq!(Err(MerkleError::DepthTooBig(9)), store.get_leaf_depth(root, 8, a));
Err(MerkleError::DepthTooBig(9)),
store.get_leaf_depth(root, 8, a)
);
} }
#[cfg(std)] #[cfg(feature = "std")]
#[test] #[test]
fn test_serialization() -> Result<(), Box<dyn Error>> { fn test_serialization() -> Result<(), Box<dyn Error>> {
let original = MerkleStore::new().with_merkle_tree(LEAVES4)?; let mtree = MerkleTree::new(LEAVES4.to_vec())?;
let decoded = MerkleStore::read_from_bytes(&original.to_bytes())?; let store = MerkleStore::from(&mtree);
assert_eq!(original, decoded); let decoded = MerkleStore::read_from_bytes(&store.to_bytes()).expect("deserialization failed");
assert_eq!(store, decoded);
Ok(()) Ok(())
} }