Merge pull request #129 from 0xPolygonMiden/next
Tracking PR for v0.4 release
This commit is contained in:
commit
09025b4014
20 changed files with 347 additions and 576 deletions
|
@ -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)
|
||||
|
||||
- Added `depth` parameter to SMT constructors in `MerkleStore` (#115).
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
[package]
|
||||
name = "miden-crypto"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
description = "Miden Cryptographic primitives"
|
||||
authors = ["miden contributors"]
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/0xPolygonMiden/crypto"
|
||||
documentation = "https://docs.rs/miden-crypto/0.3.0"
|
||||
documentation = "https://docs.rs/miden-crypto/0.4.0"
|
||||
categories = ["cryptography", "no-std"]
|
||||
keywords = ["miden", "crypto", "hash", "merkle"]
|
||||
edition = "2021"
|
||||
|
|
|
@ -106,11 +106,5 @@ fn blake3_sequential(c: &mut Criterion) {
|
|||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
hash_group,
|
||||
rpo256_2to1,
|
||||
rpo256_sequential,
|
||||
blake3_2to1,
|
||||
blake3_sequential
|
||||
);
|
||||
criterion_group!(hash_group, rpo256_2to1, rpo256_sequential, blake3_2to1, blake3_sequential);
|
||||
criterion_main!(hash_group);
|
||||
|
|
|
@ -75,10 +75,5 @@ criterion_main!(smt_group);
|
|||
fn generate_word(seed: &mut [u8; 32]) -> Word {
|
||||
swap(seed, &mut 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])]
|
||||
}
|
||||
|
|
|
@ -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| {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -347,16 +341,16 @@ 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,
|
||||
)
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group.bench_function(BenchmarkId::new("SimpleSmt::new", size), |b| {
|
||||
b.iter_batched(
|
||||
|
@ -372,9 +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
|
||||
|
@ -384,14 +376,12 @@ fn new(c: &mut Criterion) {
|
|||
.collect::<Vec<(u64, Word)>>()
|
||||
},
|
||||
|l| {
|
||||
black_box(
|
||||
MerkleStore::new().with_sparse_merkle_tree(SimpleSmt::MAX_DEPTH, l),
|
||||
)
|
||||
let smt = SimpleSmt::new(SimpleSmt::MAX_DEPTH).unwrap().with_leaves(l).unwrap();
|
||||
black_box(MerkleStore::from(&smt));
|
||||
},
|
||||
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 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;
|
||||
|
@ -456,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;
|
||||
|
|
20
rustfmt.toml
Normal file
20
rustfmt.toml
Normal 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
|
|
@ -270,10 +270,7 @@ impl Blake3_160 {
|
|||
/// Zero-copy ref shrink to array.
|
||||
fn shrink_bytes<const M: usize, const N: usize>(bytes: &[u8; M]) -> &[u8; N] {
|
||||
// compile-time assertion
|
||||
assert!(
|
||||
M >= N,
|
||||
"N should fit in M so it can be safely transmuted into a smaller slice!"
|
||||
);
|
||||
assert!(M >= N, "N should fit in M so it can be safely transmuted into a smaller slice!");
|
||||
// safety: bytes len is asserted
|
||||
unsafe { transmute(bytes) }
|
||||
}
|
||||
|
|
|
@ -118,14 +118,13 @@ impl Ord for RpoDigest {
|
|||
// 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
|
||||
// digest is guaranteed to be in its canonical form (that is, `x in [0,p)`).
|
||||
self.0
|
||||
.iter()
|
||||
.map(Felt::inner)
|
||||
.zip(other.0.iter().map(Felt::inner))
|
||||
.fold(Ordering::Equal, |ord, (a, b)| match ord {
|
||||
self.0.iter().map(Felt::inner).zip(other.0.iter().map(Felt::inner)).fold(
|
||||
Ordering::Equal,
|
||||
|ord, (a, b)| match ord {
|
||||
Ordering::Equal => a.cmp(&b),
|
||||
_ => ord,
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -132,10 +132,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_node_index_value_too_high() {
|
||||
assert_eq!(
|
||||
NodeIndex::new(0, 0).unwrap(),
|
||||
NodeIndex { depth: 0, value: 0 }
|
||||
);
|
||||
assert_eq!(NodeIndex::new(0, 0).unwrap(), NodeIndex { depth: 0, value: 0 });
|
||||
match NodeIndex::new(0, 1) {
|
||||
Err(MerkleError::InvalidIndex { depth, value }) => {
|
||||
assert_eq!(depth, 0);
|
||||
|
|
|
@ -109,10 +109,7 @@ impl MerkleTree {
|
|||
index.move_up();
|
||||
}
|
||||
|
||||
debug_assert!(
|
||||
index.is_root(),
|
||||
"the path walk must go all the way to the root"
|
||||
);
|
||||
debug_assert!(index.is_root(), "the path walk must go all the way to the root");
|
||||
|
||||
Ok(path.into())
|
||||
}
|
||||
|
@ -153,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
|
||||
}
|
||||
|
@ -168,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> {
|
||||
|
@ -195,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 = " ";
|
||||
|
@ -248,12 +250,7 @@ mod tests {
|
|||
use core::mem::size_of;
|
||||
use proptest::prelude::*;
|
||||
|
||||
const LEAVES4: [Word; 4] = [
|
||||
int_to_node(1),
|
||||
int_to_node(2),
|
||||
int_to_node(3),
|
||||
int_to_node(4),
|
||||
];
|
||||
const LEAVES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
|
||||
|
||||
const LEAVES8: [Word; 8] = [
|
||||
int_to_node(1),
|
||||
|
@ -309,22 +306,10 @@ mod tests {
|
|||
let (_, node2, node3) = compute_internal_nodes();
|
||||
|
||||
// check depth 2
|
||||
assert_eq!(
|
||||
vec![LEAVES4[1], node3],
|
||||
*tree.get_path(NodeIndex::make(2, 0)).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()
|
||||
);
|
||||
assert_eq!(vec![LEAVES4[1], node3], *tree.get_path(NodeIndex::make(2, 0)).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
|
||||
assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap());
|
||||
|
|
|
@ -54,8 +54,6 @@ impl MmrPeaks {
|
|||
|
||||
pub fn verify(&self, value: Word, opening: MmrProof) -> bool {
|
||||
let root = &self.peaks[opening.peak_index()];
|
||||
opening
|
||||
.merkle_path
|
||||
.verify(opening.relative_pos() as u64, value, root)
|
||||
opening.merkle_path.verify(opening.relative_pos() as u64, value, root)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,10 +280,7 @@ impl<'a> Iterator for MmrNodes<'a> {
|
|||
type Item = InnerNodeInfo;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
debug_assert!(
|
||||
self.last_right.count_ones() <= 1,
|
||||
"last_right tracks zero or one element"
|
||||
);
|
||||
debug_assert!(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
|
||||
let target = self.mmr.forest & (usize::MAX << 1);
|
||||
|
|
|
@ -118,9 +118,7 @@ fn test_mmr_simple() {
|
|||
postorder.push(LEAVES[2]);
|
||||
postorder.push(LEAVES[3]);
|
||||
postorder.push(*Rpo256::hash_elements(&[LEAVES[2], LEAVES[3]].concat()));
|
||||
postorder.push(*Rpo256::hash_elements(
|
||||
&[postorder[2], postorder[5]].concat(),
|
||||
));
|
||||
postorder.push(*Rpo256::hash_elements(&[postorder[2], postorder[5]].concat()));
|
||||
postorder.push(LEAVES[4]);
|
||||
postorder.push(LEAVES[5]);
|
||||
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();
|
||||
|
||||
// node at pos 7 is the root
|
||||
assert!(
|
||||
mmr.open(7).is_err(),
|
||||
"Element 7 is not in the tree, result should be None"
|
||||
);
|
||||
assert!(mmr.open(7).is_err(), "Element 7 is not in the tree, result should be None");
|
||||
|
||||
// node at pos 6 is the root
|
||||
let empty: MerklePath = MerklePath::new(vec![]);
|
||||
|
@ -297,41 +292,13 @@ fn test_mmr_open() {
|
|||
#[test]
|
||||
fn test_mmr_get() {
|
||||
let mmr: Mmr = LEAVES.into();
|
||||
assert_eq!(
|
||||
mmr.get(0).unwrap(),
|
||||
LEAVES[0],
|
||||
"value at pos 0 must correspond"
|
||||
);
|
||||
assert_eq!(
|
||||
mmr.get(1).unwrap(),
|
||||
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_eq!(mmr.get(0).unwrap(), LEAVES[0], "value at pos 0 must correspond");
|
||||
assert_eq!(mmr.get(1).unwrap(), 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());
|
||||
}
|
||||
|
||||
|
@ -341,11 +308,7 @@ fn test_mmr_invariants() {
|
|||
for v in 1..=1028 {
|
||||
mmr.add(int_to_node(v));
|
||||
let accumulator = mmr.accumulator();
|
||||
assert_eq!(
|
||||
v as usize,
|
||||
mmr.forest(),
|
||||
"MMR leaf count must increase by one on every add"
|
||||
);
|
||||
assert_eq!(v as usize, mmr.forest(), "MMR leaf count must increase by one on every add");
|
||||
assert_eq!(
|
||||
v as usize, accumulator.num_leaves,
|
||||
"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).rev().count(), 0);
|
||||
|
||||
assert_eq!(
|
||||
TrueBitPositionIterator::new(1).collect::<Vec<u32>>(),
|
||||
vec![0]
|
||||
);
|
||||
assert_eq!(
|
||||
TrueBitPositionIterator::new(1).rev().collect::<Vec<u32>>(),
|
||||
vec![0],
|
||||
);
|
||||
assert_eq!(TrueBitPositionIterator::new(1).collect::<Vec<u32>>(), vec![0]);
|
||||
assert_eq!(TrueBitPositionIterator::new(1).rev().collect::<Vec<u32>>(), vec![0],);
|
||||
|
||||
assert_eq!(
|
||||
TrueBitPositionIterator::new(2).collect::<Vec<u32>>(),
|
||||
vec![1]
|
||||
);
|
||||
assert_eq!(
|
||||
TrueBitPositionIterator::new(2).rev().collect::<Vec<u32>>(),
|
||||
vec![1],
|
||||
);
|
||||
assert_eq!(TrueBitPositionIterator::new(2).collect::<Vec<u32>>(), vec![1]);
|
||||
assert_eq!(TrueBitPositionIterator::new(2).rev().collect::<Vec<u32>>(), vec![1],);
|
||||
|
||||
assert_eq!(
|
||||
TrueBitPositionIterator::new(3).collect::<Vec<u32>>(),
|
||||
vec![0, 1],
|
||||
);
|
||||
assert_eq!(
|
||||
TrueBitPositionIterator::new(3).rev().collect::<Vec<u32>>(),
|
||||
vec![1, 0],
|
||||
);
|
||||
assert_eq!(TrueBitPositionIterator::new(3).collect::<Vec<u32>>(), vec![0, 1],);
|
||||
assert_eq!(TrueBitPositionIterator::new(3).rev().collect::<Vec<u32>>(), vec![1, 0],);
|
||||
|
||||
assert_eq!(
|
||||
TrueBitPositionIterator::new(0b11010101).collect::<Vec<u32>>(),
|
||||
vec![0, 2, 4, 6, 7],
|
||||
);
|
||||
assert_eq!(
|
||||
TrueBitPositionIterator::new(0b11010101)
|
||||
.rev()
|
||||
.collect::<Vec<u32>>(),
|
||||
TrueBitPositionIterator::new(0b11010101).rev().collect::<Vec<u32>>(),
|
||||
vec![7, 6, 4, 2, 0],
|
||||
);
|
||||
}
|
||||
|
@ -463,10 +406,7 @@ fn test_mmr_hash_peaks() {
|
|||
// minimum length is 16
|
||||
let mut expected_peaks = [first_peak, second_peak, third_peak].to_vec();
|
||||
expected_peaks.resize(16, [ZERO; WORD_SIZE]);
|
||||
assert_eq!(
|
||||
peaks.hash_peaks(),
|
||||
*Rpo256::hash_elements(&expected_peaks.as_slice().concat())
|
||||
);
|
||||
assert_eq!(peaks.hash_peaks(), *Rpo256::hash_elements(&expected_peaks.as_slice().concat()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -27,7 +27,7 @@ mod simple_smt;
|
|||
pub use simple_smt::SimpleSmt;
|
||||
|
||||
mod mmr;
|
||||
pub use mmr::{Mmr, MmrPeaks};
|
||||
pub use mmr::{Mmr, MmrPeaks, MmrProof};
|
||||
|
||||
mod store;
|
||||
pub use store::MerkleStore;
|
||||
|
|
|
@ -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
|
||||
|
@ -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)?;
|
||||
|
@ -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`.
|
||||
|
@ -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 {
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
// ================================================================================================
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,9 +34,7 @@ impl MerklePathSet {
|
|||
where
|
||||
I: IntoIterator<Item = (u64, Word, MerklePath)>,
|
||||
{
|
||||
paths
|
||||
.into_iter()
|
||||
.try_fold(self, |mut set, (index, value, path)| {
|
||||
paths.into_iter().try_fold(self, |mut set, (index, value, path)| {
|
||||
set.add_path(index, value, path)?;
|
||||
Ok(set)
|
||||
})
|
||||
|
@ -291,14 +289,9 @@ mod tests {
|
|||
let hash_6 = int_to_node(6);
|
||||
let index = 6_u64;
|
||||
let depth = 3_u8;
|
||||
let set = MerklePathSet::new(depth)
|
||||
.with_paths([(index, hash_6, path_6.into())])
|
||||
.unwrap();
|
||||
let set = MerklePathSet::new(depth).with_paths([(index, hash_6, path_6.into())]).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
int_to_node(6u64),
|
||||
set.get_node(NodeIndex::make(depth, index)).unwrap()
|
||||
);
|
||||
assert_eq!(int_to_node(6u64), set.get_node(NodeIndex::make(depth, index)).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -131,12 +131,7 @@ impl SimpleSmt {
|
|||
Err(MerkleError::DepthTooBig(index.depth() as u64))
|
||||
} else if index.depth() == self.depth() {
|
||||
self.get_leaf_node(index.value())
|
||||
.or_else(|| {
|
||||
self.empty_hashes
|
||||
.get(index.depth() as usize)
|
||||
.copied()
|
||||
.map(Word::from)
|
||||
})
|
||||
.or_else(|| self.empty_hashes.get(index.depth() as usize).copied().map(Word::from))
|
||||
.ok_or(MerkleError::NodeNotInSet(index.value()))
|
||||
} else {
|
||||
let branch_node = self.get_branch_node(&index);
|
||||
|
@ -217,11 +212,7 @@ impl SimpleSmt {
|
|||
let is_right = index.is_value_odd();
|
||||
index.move_up();
|
||||
let BranchNode { left, right } = self.get_branch_node(&index);
|
||||
let (left, right) = if is_right {
|
||||
(left, value)
|
||||
} else {
|
||||
(value, right)
|
||||
};
|
||||
let (left, right) = if is_right { (left, value) } else { (value, right) };
|
||||
self.insert_branch_node(index, left, right);
|
||||
value = Rpo256::merge(&[left, right]);
|
||||
}
|
||||
|
|
|
@ -8,12 +8,7 @@ use rand_utils::prng_array;
|
|||
const KEYS4: [u64; 4] = [0, 1, 2, 3];
|
||||
const KEYS8: [u64; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
|
||||
|
||||
const VALUES4: [Word; 4] = [
|
||||
int_to_node(1),
|
||||
int_to_node(2),
|
||||
int_to_node(3),
|
||||
int_to_node(4),
|
||||
];
|
||||
const VALUES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
|
||||
|
||||
const VALUES8: [Word; 8] = [
|
||||
int_to_node(1),
|
||||
|
@ -56,8 +51,7 @@ fn build_sparse_tree() {
|
|||
let key = 6;
|
||||
let new_node = int_to_node(7);
|
||||
values[key as usize] = new_node;
|
||||
smt.insert_leaf(key, new_node)
|
||||
.expect("Failed to insert leaf");
|
||||
smt.insert_leaf(key, new_node).expect("Failed to insert leaf");
|
||||
let mt2 = MerkleTree::new(values.clone()).unwrap();
|
||||
assert_eq!(mt2.root(), smt.root());
|
||||
assert_eq!(
|
||||
|
@ -69,8 +63,7 @@ fn build_sparse_tree() {
|
|||
let key = 2;
|
||||
let new_node = int_to_node(3);
|
||||
values[key as usize] = new_node;
|
||||
smt.insert_leaf(key, new_node)
|
||||
.expect("Failed to insert leaf");
|
||||
smt.insert_leaf(key, new_node).expect("Failed to insert leaf");
|
||||
let mt3 = MerkleTree::new(values).unwrap();
|
||||
assert_eq!(mt3.root(), smt.root());
|
||||
assert_eq!(
|
||||
|
@ -116,22 +109,10 @@ fn get_path() {
|
|||
let (_, node2, node3) = compute_internal_nodes();
|
||||
|
||||
// check depth 2
|
||||
assert_eq!(
|
||||
vec![VALUES4[1], node3],
|
||||
*tree.get_path(NodeIndex::make(2, 0)).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()
|
||||
);
|
||||
assert_eq!(vec![VALUES4[1], node3], *tree.get_path(NodeIndex::make(2, 0)).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
|
||||
assert_eq!(vec![node3], *tree.get_path(NodeIndex::make(1, 0)).unwrap());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::mmr::{Mmr, MmrPeaks};
|
||||
use super::mmr::Mmr;
|
||||
use super::{
|
||||
BTreeMap, EmptySubtreeRoots, MerkleError, MerklePath, MerklePathSet, MerkleTree, NodeIndex,
|
||||
RootPath, Rpo256, RpoDigest, SimpleSmt, ValuePath, Vec, Word,
|
||||
BTreeMap, EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, MerklePathSet, MerkleTree,
|
||||
NodeIndex, RootPath, Rpo256, RpoDigest, SimpleSmt, ValuePath, Vec, Word,
|
||||
};
|
||||
use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
|
||||
|
||||
|
@ -47,9 +47,13 @@ pub struct Node {
|
|||
/// // the store is initialized with the SMT empty nodes
|
||||
/// 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
|
||||
/// store.add_merkle_tree([A, B, C, D, E, F, G, H0]);
|
||||
/// store.add_merkle_tree([A, B, C, D, E, F, G, H1]);
|
||||
/// store
|
||||
/// .extend(tree1.inner_nodes())
|
||||
/// .extend(tree2.inner_nodes());
|
||||
///
|
||||
/// // every leaf except the last are the same
|
||||
/// for i in 0..7 {
|
||||
|
@ -111,60 +115,6 @@ impl MerkleStore {
|
|||
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
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -184,15 +134,11 @@ impl MerkleStore {
|
|||
let mut hash: RpoDigest = root.into();
|
||||
|
||||
// corner case: check the root is in the store when called with index `NodeIndex::root()`
|
||||
self.nodes
|
||||
.get(&hash)
|
||||
.ok_or(MerkleError::RootNotInStore(hash.into()))?;
|
||||
self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash.into()))?;
|
||||
|
||||
for i in (0..index.depth()).rev() {
|
||||
let node = self
|
||||
.nodes
|
||||
.get(&hash)
|
||||
.ok_or(MerkleError::NodeNotInStore(hash.into(), index))?;
|
||||
let node =
|
||||
self.nodes.get(&hash).ok_or(MerkleError::NodeNotInStore(hash.into(), index))?;
|
||||
|
||||
let bit = (index.value() >> i) & 1;
|
||||
hash = if bit == 0 { node.left } else { node.right }
|
||||
|
@ -215,15 +161,11 @@ impl MerkleStore {
|
|||
let mut path = Vec::with_capacity(index.depth().into());
|
||||
|
||||
// corner case: check the root is in the store when called with index `NodeIndex::root()`
|
||||
self.nodes
|
||||
.get(&hash)
|
||||
.ok_or(MerkleError::RootNotInStore(hash.into()))?;
|
||||
self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash.into()))?;
|
||||
|
||||
for i in (0..index.depth()).rev() {
|
||||
let node = self
|
||||
.nodes
|
||||
.get(&hash)
|
||||
.ok_or(MerkleError::NodeNotInStore(hash.into(), index))?;
|
||||
let node =
|
||||
self.nodes.get(&hash).ok_or(MerkleError::NodeNotInStore(hash.into(), index))?;
|
||||
|
||||
let bit = (index.value() >> i) & 1;
|
||||
hash = if bit == 0 {
|
||||
|
@ -302,11 +244,7 @@ impl MerkleStore {
|
|||
};
|
||||
|
||||
// traverse down
|
||||
hash = if path & 1 == 0 {
|
||||
children.left
|
||||
} else {
|
||||
children.right
|
||||
};
|
||||
hash = if path & 1 == 0 { children.left } else { children.right };
|
||||
path >>= 1;
|
||||
}
|
||||
|
||||
|
@ -322,68 +260,21 @@ impl MerkleStore {
|
|||
// STATE MUTATORS
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
/// Adds all the nodes of a Merkle tree represented by `leaves`.
|
||||
///
|
||||
/// 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>
|
||||
/// Adds a sequence of nodes yielded by the provided iterator into the store.
|
||||
pub fn extend<I>(&mut self, iter: I) -> &mut MerkleStore
|
||||
where
|
||||
I: IntoIterator<Item = Word>,
|
||||
I: Iterator<Item = InnerNodeInfo>,
|
||||
{
|
||||
let leaves: Vec<_> = leaves.into_iter().collect();
|
||||
if leaves.len() < 2 {
|
||||
return Err(MerkleError::DepthTooSmall(leaves.len() as u8));
|
||||
for node in iter {
|
||||
let value: RpoDigest = node.value.into();
|
||||
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)?;
|
||||
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())
|
||||
self
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn add_merkle_path(
|
||||
&mut self,
|
||||
index_value: u64,
|
||||
mut node: Word,
|
||||
index: u64,
|
||||
node: Word,
|
||||
path: MerklePath,
|
||||
) -> 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 {
|
||||
let (left, right) = match index.is_value_odd() {
|
||||
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(),
|
||||
},
|
||||
);
|
||||
debug_assert_eq!(Rpo256::merge(&[left, right]), value);
|
||||
self.nodes.insert(value, Node { left, right });
|
||||
|
||||
index.move_up();
|
||||
node = parent.into();
|
||||
}
|
||||
|
||||
Ok(node)
|
||||
node.value
|
||||
});
|
||||
Ok(root)
|
||||
}
|
||||
|
||||
/// Adds all the nodes of multiple Merkle paths into the store.
|
||||
|
@ -447,25 +328,6 @@ impl MerkleStore {
|
|||
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`.
|
||||
///
|
||||
/// # Errors
|
||||
|
@ -490,27 +352,62 @@ impl MerkleStore {
|
|||
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> {
|
||||
let root1: RpoDigest = root1.into();
|
||||
let root2: RpoDigest = root2.into();
|
||||
let left: RpoDigest = root1.into();
|
||||
let right: RpoDigest = root2.into();
|
||||
|
||||
if !self.nodes.contains_key(&root1) {
|
||||
Err(MerkleError::NodeNotInStore(root1.into(), NodeIndex::root()))
|
||||
} 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,
|
||||
},
|
||||
);
|
||||
let parent = Rpo256::merge(&[left, right]);
|
||||
self.nodes.insert(parent, Node { left, right });
|
||||
|
||||
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
|
||||
|
|
|
@ -1,26 +1,21 @@
|
|||
use super::*;
|
||||
use crate::{
|
||||
hash::rpo::Rpo256,
|
||||
merkle::{int_to_node, MerklePathSet},
|
||||
merkle::{int_to_node, MerklePathSet, MerkleTree, SimpleSmt},
|
||||
Felt, Word, WORD_SIZE, ZERO,
|
||||
};
|
||||
|
||||
#[cfg(std)]
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
|
||||
const KEYS4: [u64; 4] = [0, 1, 2, 3];
|
||||
const LEAVES4: [Word; 4] = [
|
||||
int_to_node(1),
|
||||
int_to_node(2),
|
||||
int_to_node(3),
|
||||
int_to_node(4),
|
||||
];
|
||||
const LEAVES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
|
||||
const EMPTY: Word = [ZERO; WORD_SIZE];
|
||||
|
||||
#[test]
|
||||
fn test_root_not_in_store() -> Result<(), MerkleError> {
|
||||
let mtree = MerkleTree::new(LEAVES4.to_vec())?;
|
||||
let store = MerkleStore::default().with_merkle_tree(LEAVES4)?;
|
||||
let store = MerkleStore::from(&mtree);
|
||||
assert_eq!(
|
||||
store.get_node(LEAVES4[0], NodeIndex::make(mtree.depth(), 0)),
|
||||
Err(MerkleError::RootNotInStore(LEAVES4[0])),
|
||||
|
@ -37,10 +32,8 @@ fn test_root_not_in_store() -> Result<(), MerkleError> {
|
|||
|
||||
#[test]
|
||||
fn test_merkle_tree() -> Result<(), MerkleError> {
|
||||
let mut store = MerkleStore::default();
|
||||
|
||||
let mtree = MerkleTree::new(LEAVES4.to_vec())?;
|
||||
store.add_merkle_tree(LEAVES4.to_vec())?;
|
||||
let store = MerkleStore::from(&mtree);
|
||||
|
||||
// STORE LEAVES ARE CORRECT ==============================================================
|
||||
// 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 ==============================================================
|
||||
// assert the merkle path returned by the store is the same as the one in the tree
|
||||
let result = store
|
||||
.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 0))
|
||||
.unwrap();
|
||||
let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 0)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[0], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 1))
|
||||
.unwrap();
|
||||
let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 1)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[1], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 2))
|
||||
.unwrap();
|
||||
let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 2)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[2], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 3))
|
||||
.unwrap();
|
||||
let result = store.get_path(mtree.root(), NodeIndex::make(mtree.depth(), 3)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[3], result.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 store_path = store.get_path(smt.root(), index)?;
|
||||
let smt_path = smt.get_path(index)?;
|
||||
assert_eq!(
|
||||
store_path.value, EMPTY,
|
||||
"the leaf of an empty tree is always ZERO"
|
||||
);
|
||||
assert_eq!(store_path.value, EMPTY, "the leaf of an empty tree is always ZERO");
|
||||
assert_eq!(
|
||||
store_path.path, smt_path,
|
||||
"the returned merkle path does not match the computed values"
|
||||
|
@ -192,55 +174,41 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> {
|
|||
|
||||
#[test]
|
||||
fn test_get_invalid_node() {
|
||||
let mut store = MerkleStore::default();
|
||||
let mtree = MerkleTree::new(LEAVES4.to_vec()).expect("creating a merkle tree must work");
|
||||
store
|
||||
.add_merkle_tree(LEAVES4.to_vec())
|
||||
.expect("adding a merkle tree to the store must work");
|
||||
let store = MerkleStore::from(&mtree);
|
||||
let _ = store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> {
|
||||
let mut store = MerkleStore::default();
|
||||
let keys2: [u64; 2] = [0, 1];
|
||||
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)
|
||||
.unwrap()
|
||||
.with_leaves(keys2.into_iter().zip(leaves2.into_iter()))
|
||||
.unwrap();
|
||||
let store = MerkleStore::from(&smt);
|
||||
|
||||
let idx = NodeIndex::make(1, 0);
|
||||
assert_eq!(smt.get_node(idx).unwrap(), leaves2[0]);
|
||||
assert_eq!(
|
||||
store.get_node(smt.root(), idx).unwrap(),
|
||||
smt.get_node(idx).unwrap()
|
||||
);
|
||||
assert_eq!(store.get_node(smt.root(), idx).unwrap(), smt.get_node(idx).unwrap());
|
||||
|
||||
let idx = NodeIndex::make(1, 1);
|
||||
assert_eq!(smt.get_node(idx).unwrap(), leaves2[1]);
|
||||
assert_eq!(
|
||||
store.get_node(smt.root(), idx).unwrap(),
|
||||
smt.get_node(idx).unwrap()
|
||||
);
|
||||
assert_eq!(store.get_node(smt.root(), idx).unwrap(), smt.get_node(idx).unwrap());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
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)
|
||||
.unwrap()
|
||||
.with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter()))
|
||||
.unwrap();
|
||||
|
||||
let store = MerkleStore::from(&smt);
|
||||
|
||||
// STORE LEAVES ARE CORRECT ==============================================================
|
||||
// checks the leaves in the store corresponds to the expected values
|
||||
assert_eq!(
|
||||
|
@ -299,9 +267,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
|
|||
|
||||
// STORE MERKLE PATH MATCHS ==============================================================
|
||||
// assert the merkle path returned by the store is the same as the one in the tree
|
||||
let result = store
|
||||
.get_path(smt.root(), NodeIndex::make(smt.depth(), 0))
|
||||
.unwrap();
|
||||
let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 0)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[0], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(smt.root(), NodeIndex::make(smt.depth(), 1))
|
||||
.unwrap();
|
||||
let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 1)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[1], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(smt.root(), NodeIndex::make(smt.depth(), 2))
|
||||
.unwrap();
|
||||
let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 2)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[2], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(smt.root(), NodeIndex::make(smt.depth(), 3))
|
||||
.unwrap();
|
||||
let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 3)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[3], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(smt.root(), NodeIndex::make(smt.depth(), 4))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
EMPTY, result.value,
|
||||
"Value for merkle path at index 4 must match leaf value"
|
||||
);
|
||||
let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 4)).unwrap();
|
||||
assert_eq!(EMPTY, result.value, "Value for merkle path at index 4 must match leaf value");
|
||||
assert_eq!(
|
||||
smt.get_path(NodeIndex::make(smt.depth(), 4)),
|
||||
Ok(result.path),
|
||||
|
@ -391,9 +346,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> {
|
|||
];
|
||||
|
||||
let mut store = MerkleStore::default();
|
||||
store
|
||||
.add_merkle_paths(paths.clone())
|
||||
.expect("the valid paths must work");
|
||||
store.add_merkle_paths(paths.clone()).expect("the valid paths must work");
|
||||
|
||||
let depth = 2;
|
||||
let set = MerklePathSet::new(depth).with_paths(paths).unwrap();
|
||||
|
@ -446,9 +399,7 @@ fn test_add_merkle_paths() -> Result<(), MerkleError> {
|
|||
|
||||
// STORE MERKLE PATH MATCHS ==============================================================
|
||||
// assert the merkle path returned by the store is the same as the one in the set
|
||||
let result = store
|
||||
.get_path(set.root(), NodeIndex::make(set.depth(), 0))
|
||||
.unwrap();
|
||||
let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 0)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[0], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(set.root(), NodeIndex::make(set.depth(), 1))
|
||||
.unwrap();
|
||||
let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 1)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[1], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(set.root(), NodeIndex::make(set.depth(), 2))
|
||||
.unwrap();
|
||||
let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 2)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[2], result.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"
|
||||
);
|
||||
|
||||
let result = store
|
||||
.get_path(set.root(), NodeIndex::make(set.depth(), 3))
|
||||
.unwrap();
|
||||
let result = store.get_path(set.root(), NodeIndex::make(set.depth(), 3)).unwrap();
|
||||
assert_eq!(
|
||||
LEAVES4[3], result.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
|
||||
// attempt to fetch a node on the maximum depth, and it should fail because the root shouldn't
|
||||
// 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 err = store.get_node(root, index).err().unwrap();
|
||||
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 store = MerkleStore::default()
|
||||
.with_merkle_tree([a, b, c, d, e, f, g, h])
|
||||
.unwrap();
|
||||
let path = store
|
||||
.get_path(root.into(), NodeIndex::make(3, 1))
|
||||
.unwrap()
|
||||
.path;
|
||||
let mtree = MerkleTree::new(vec![a, b, c, d, e, f, g, h]).unwrap();
|
||||
let store = MerkleStore::from(&mtree);
|
||||
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());
|
||||
assert_eq!(path, expected);
|
||||
|
@ -561,23 +503,19 @@ fn store_path_opens_from_leaf() {
|
|||
#[test]
|
||||
fn test_set_node() -> Result<(), MerkleError> {
|
||||
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 index = NodeIndex::make(mtree.depth(), 0);
|
||||
let new_root = store.set_node(mtree.root(), index, value)?.root;
|
||||
assert_eq!(
|
||||
store.get_node(new_root, index),
|
||||
Ok(value),
|
||||
"Value must have changed"
|
||||
);
|
||||
assert_eq!(store.get_node(new_root, index), Ok(value), "Value must have changed");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_constructors() -> Result<(), MerkleError> {
|
||||
let store = MerkleStore::new().with_merkle_tree(LEAVES4)?;
|
||||
let mtree = MerkleTree::new(LEAVES4.to_vec())?;
|
||||
let store = MerkleStore::from(&mtree);
|
||||
|
||||
let depth = mtree.depth();
|
||||
let leaves = 2u64.pow(depth.into());
|
||||
|
@ -588,12 +526,11 @@ fn test_constructors() -> Result<(), MerkleError> {
|
|||
}
|
||||
|
||||
let depth = 32;
|
||||
let store = MerkleStore::default()
|
||||
.with_sparse_merkle_tree(depth, KEYS4.into_iter().zip(LEAVES4.into_iter()))?;
|
||||
let smt = SimpleSmt::new(depth)
|
||||
.unwrap()
|
||||
.with_leaves(KEYS4.into_iter().zip(LEAVES4.into_iter()))
|
||||
.unwrap();
|
||||
let store = MerkleStore::from(&smt);
|
||||
let depth = smt.depth();
|
||||
|
||||
for key in KEYS4 {
|
||||
|
@ -604,34 +541,20 @@ fn test_constructors() -> Result<(), MerkleError> {
|
|||
|
||||
let d = 2;
|
||||
let paths = [
|
||||
(
|
||||
0,
|
||||
LEAVES4[0],
|
||||
mtree.get_path(NodeIndex::make(d, 0)).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(),
|
||||
),
|
||||
(0, LEAVES4[0], mtree.get_path(NodeIndex::make(d, 0)).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 store2 = MerkleStore::default()
|
||||
.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))?)?
|
||||
.with_merkle_path(2, LEAVES4[2], mtree.get_path(NodeIndex::make(d, 2))?)?
|
||||
.with_merkle_path(3, LEAVES4[3], mtree.get_path(NodeIndex::make(d, 3))?)?;
|
||||
let mut store1 = MerkleStore::default();
|
||||
store1.add_merkle_paths(paths.clone())?;
|
||||
|
||||
let mut store2 = MerkleStore::default();
|
||||
store2.add_merkle_path(0, LEAVES4[0], mtree.get_path(NodeIndex::make(d, 0))?)?;
|
||||
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();
|
||||
|
||||
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
|
||||
let index = NodeIndex::new(8, a).unwrap();
|
||||
root = store.set_node(root, index, root).unwrap().root;
|
||||
assert_eq!(
|
||||
Err(MerkleError::DepthTooBig(9)),
|
||||
store.get_leaf_depth(root, 8, a)
|
||||
);
|
||||
assert_eq!(Err(MerkleError::DepthTooBig(9)), store.get_leaf_depth(root, 8, a));
|
||||
}
|
||||
|
||||
#[cfg(std)]
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_serialization() -> Result<(), Box<dyn Error>> {
|
||||
let original = MerkleStore::new().with_merkle_tree(LEAVES4)?;
|
||||
let decoded = MerkleStore::read_from_bytes(&original.to_bytes())?;
|
||||
assert_eq!(original, decoded);
|
||||
let mtree = MerkleTree::new(LEAVES4.to_vec())?;
|
||||
let store = MerkleStore::from(&mtree);
|
||||
let decoded = MerkleStore::read_from_bytes(&store.to_bytes()).expect("deserialization failed");
|
||||
assert_eq!(store, decoded);
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue