The store builds the path from root to leaf, this updates the code to return a path from leaf to root, as it is done by the other structures. This also added custom error for missing root.al-gkr-basic-workflow
@ -0,0 +1,497 @@ |
|||||
|
use super::*;
|
||||
|
use crate::{
|
||||
|
hash::rpo::Rpo256,
|
||||
|
merkle::{int_to_node, MerklePathSet},
|
||||
|
Felt, Word,
|
||||
|
};
|
||||
|
|
||||
|
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),
|
||||
|
];
|
||||
|
|
||||
|
#[test]
|
||||
|
fn test_root_not_in_storage() -> Result<(), MerkleError> {
|
||||
|
let mtree = MerkleTree::new(LEAVES4.to_vec())?;
|
||||
|
let store = MerkleStore::default().with_merkle_tree(LEAVES4)?;
|
||||
|
assert_eq!(
|
||||
|
store.get_node(LEAVES4[0], NodeIndex::new(mtree.depth(), 0)),
|
||||
|
Err(MerkleError::RootNotInStore(LEAVES4[0])),
|
||||
|
"Leaf 0 is not a root"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_path(LEAVES4[0], NodeIndex::new(mtree.depth(), 0)),
|
||||
|
Err(MerkleError::RootNotInStore(LEAVES4[0])),
|
||||
|
"Leaf 0 is not a root"
|
||||
|
);
|
||||
|
|
||||
|
Ok(())
|
||||
|
}
|
||||
|
|
||||
|
#[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())?;
|
||||
|
|
||||
|
// STORE LEAVES ARE CORRECT ==============================================================
|
||||
|
// checks the leaves in the store corresponds to the expected values
|
||||
|
assert_eq!(
|
||||
|
store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 0)),
|
||||
|
Ok(LEAVES4[0]),
|
||||
|
"node 0 must be in the tree"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 1)),
|
||||
|
Ok(LEAVES4[1]),
|
||||
|
"node 1 must be in the tree"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 2)),
|
||||
|
Ok(LEAVES4[2]),
|
||||
|
"node 2 must be in the tree"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 3)),
|
||||
|
Ok(LEAVES4[3]),
|
||||
|
"node 3 must be in the tree"
|
||||
|
);
|
||||
|
|
||||
|
// STORE LEAVES MATCH TREE ===============================================================
|
||||
|
// sanity check the values returned by the store and the tree
|
||||
|
assert_eq!(
|
||||
|
mtree.get_node(NodeIndex::new(mtree.depth(), 0)),
|
||||
|
store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 0)),
|
||||
|
"node 0 must be the same for both MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
mtree.get_node(NodeIndex::new(mtree.depth(), 1)),
|
||||
|
store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 1)),
|
||||
|
"node 1 must be the same for both MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
mtree.get_node(NodeIndex::new(mtree.depth(), 2)),
|
||||
|
store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 2)),
|
||||
|
"node 2 must be the same for both MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
mtree.get_node(NodeIndex::new(mtree.depth(), 3)),
|
||||
|
store.get_node(mtree.root(), NodeIndex::new(mtree.depth(), 3)),
|
||||
|
"node 3 must be the same for both MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
// 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::new(mtree.depth(), 0))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[0], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
mtree.get_path(NodeIndex::new(mtree.depth(), 0)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
let result = store
|
||||
|
.get_path(mtree.root(), NodeIndex::new(mtree.depth(), 1))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[1], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
mtree.get_path(NodeIndex::new(mtree.depth(), 1)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 1 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
let result = store
|
||||
|
.get_path(mtree.root(), NodeIndex::new(mtree.depth(), 2))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[2], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
mtree.get_path(NodeIndex::new(mtree.depth(), 2)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
let result = store
|
||||
|
.get_path(mtree.root(), NodeIndex::new(mtree.depth(), 3))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[3], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
mtree.get_path(NodeIndex::new(mtree.depth(), 3)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
Ok(())
|
||||
|
}
|
||||
|
|
||||
|
#[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.get_node(mtree.root(), NodeIndex::new(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(keys2.into_iter().zip(leaves2.into_iter()))?;
|
||||
|
let smt = SimpleSmt::new(1)
|
||||
|
.unwrap()
|
||||
|
.with_leaves(keys2.into_iter().zip(leaves2.into_iter()))
|
||||
|
.unwrap();
|
||||
|
|
||||
|
let idx = NodeIndex::new(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()
|
||||
|
);
|
||||
|
|
||||
|
let idx = NodeIndex::new(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()
|
||||
|
);
|
||||
|
|
||||
|
Ok(())
|
||||
|
}
|
||||
|
|
||||
|
#[test]
|
||||
|
fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
|
||||
|
let mut store = MerkleStore::default();
|
||||
|
store.add_sparse_merkle_tree(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();
|
||||
|
|
||||
|
// STORE LEAVES ARE CORRECT ==============================================================
|
||||
|
// checks the leaves in the store corresponds to the expected values
|
||||
|
assert_eq!(
|
||||
|
store.get_node(smt.root(), NodeIndex::new(smt.depth(), 0)),
|
||||
|
Ok(LEAVES4[0]),
|
||||
|
"node 0 must be in the tree"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_node(smt.root(), NodeIndex::new(smt.depth(), 1)),
|
||||
|
Ok(LEAVES4[1]),
|
||||
|
"node 1 must be in the tree"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_node(smt.root(), NodeIndex::new(smt.depth(), 2)),
|
||||
|
Ok(LEAVES4[2]),
|
||||
|
"node 2 must be in the tree"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_node(smt.root(), NodeIndex::new(smt.depth(), 3)),
|
||||
|
Ok(LEAVES4[3]),
|
||||
|
"node 3 must be in the tree"
|
||||
|
);
|
||||
|
|
||||
|
// STORE LEAVES MATCH TREE ===============================================================
|
||||
|
// sanity check the values returned by the store and the tree
|
||||
|
assert_eq!(
|
||||
|
smt.get_node(&NodeIndex::new(smt.depth(), 0)),
|
||||
|
store.get_node(smt.root(), NodeIndex::new(smt.depth(), 0)),
|
||||
|
"node 0 must be the same for both SparseMerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
smt.get_node(&NodeIndex::new(smt.depth(), 1)),
|
||||
|
store.get_node(smt.root(), NodeIndex::new(smt.depth(), 1)),
|
||||
|
"node 1 must be the same for both SparseMerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
smt.get_node(&NodeIndex::new(smt.depth(), 2)),
|
||||
|
store.get_node(smt.root(), NodeIndex::new(smt.depth(), 2)),
|
||||
|
"node 2 must be the same for both SparseMerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
smt.get_node(&NodeIndex::new(smt.depth(), 3)),
|
||||
|
store.get_node(smt.root(), NodeIndex::new(smt.depth(), 3)),
|
||||
|
"node 3 must be the same for both SparseMerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
// 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::new(smt.depth(), 0))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[0], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
smt.get_path(NodeIndex::new(smt.depth(), 0)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
let result = store
|
||||
|
.get_path(smt.root(), NodeIndex::new(smt.depth(), 1))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[1], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
smt.get_path(NodeIndex::new(smt.depth(), 1)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 1 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
let result = store
|
||||
|
.get_path(smt.root(), NodeIndex::new(smt.depth(), 2))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[2], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
smt.get_path(NodeIndex::new(smt.depth(), 2)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
let result = store
|
||||
|
.get_path(smt.root(), NodeIndex::new(smt.depth(), 3))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[3], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
smt.get_path(NodeIndex::new(smt.depth(), 3)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
Ok(())
|
||||
|
}
|
||||
|
|
||||
|
#[test]
|
||||
|
fn test_add_merkle_paths() -> Result<(), MerkleError> {
|
||||
|
let mtree = MerkleTree::new(LEAVES4.to_vec())?;
|
||||
|
|
||||
|
let i0 = 0;
|
||||
|
let p0 = mtree.get_path(NodeIndex::new(2, i0)).unwrap();
|
||||
|
|
||||
|
let i1 = 1;
|
||||
|
let p1 = mtree.get_path(NodeIndex::new(2, i1)).unwrap();
|
||||
|
|
||||
|
let i2 = 2;
|
||||
|
let p2 = mtree.get_path(NodeIndex::new(2, i2)).unwrap();
|
||||
|
|
||||
|
let i3 = 3;
|
||||
|
let p3 = mtree.get_path(NodeIndex::new(2, i3)).unwrap();
|
||||
|
|
||||
|
let paths = [
|
||||
|
(i0, LEAVES4[i0 as usize], p0),
|
||||
|
(i1, LEAVES4[i1 as usize], p1),
|
||||
|
(i2, LEAVES4[i2 as usize], p2),
|
||||
|
(i3, LEAVES4[i3 as usize], p3),
|
||||
|
];
|
||||
|
|
||||
|
let mut store = MerkleStore::default();
|
||||
|
store
|
||||
|
.add_merkle_paths(paths.clone())
|
||||
|
.expect("the valid paths must work");
|
||||
|
|
||||
|
let depth = 3;
|
||||
|
let set = MerklePathSet::new(depth).with_paths(paths).unwrap();
|
||||
|
|
||||
|
// STORE LEAVES ARE CORRECT ==============================================================
|
||||
|
// checks the leaves in the store corresponds to the expected values
|
||||
|
assert_eq!(
|
||||
|
store.get_node(set.root(), NodeIndex::new(set.depth() - 1, 0)),
|
||||
|
Ok(LEAVES4[0]),
|
||||
|
"node 0 must be in the set"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_node(set.root(), NodeIndex::new(set.depth() - 1, 1)),
|
||||
|
Ok(LEAVES4[1]),
|
||||
|
"node 1 must be in the set"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_node(set.root(), NodeIndex::new(set.depth() - 1, 2)),
|
||||
|
Ok(LEAVES4[2]),
|
||||
|
"node 2 must be in the set"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
store.get_node(set.root(), NodeIndex::new(set.depth() - 1, 3)),
|
||||
|
Ok(LEAVES4[3]),
|
||||
|
"node 3 must be in the set"
|
||||
|
);
|
||||
|
|
||||
|
// STORE LEAVES MATCH SET ================================================================
|
||||
|
// sanity check the values returned by the store and the set
|
||||
|
assert_eq!(
|
||||
|
set.get_node(NodeIndex::new(set.depth(), 0)),
|
||||
|
store.get_node(set.root(), NodeIndex::new(set.depth() - 1, 0)),
|
||||
|
"node 0 must be the same for both SparseMerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
set.get_node(NodeIndex::new(set.depth(), 1)),
|
||||
|
store.get_node(set.root(), NodeIndex::new(set.depth() - 1, 1)),
|
||||
|
"node 1 must be the same for both SparseMerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
set.get_node(NodeIndex::new(set.depth(), 2)),
|
||||
|
store.get_node(set.root(), NodeIndex::new(set.depth() - 1, 2)),
|
||||
|
"node 2 must be the same for both SparseMerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
set.get_node(NodeIndex::new(set.depth(), 3)),
|
||||
|
store.get_node(set.root(), NodeIndex::new(set.depth() - 1, 3)),
|
||||
|
"node 3 must be the same for both SparseMerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
// 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::new(set.depth() - 1, 0))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[0], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
set.get_path(NodeIndex::new(set.depth(), 0)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
let result = store
|
||||
|
.get_path(set.root(), NodeIndex::new(set.depth() - 1, 1))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[1], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
set.get_path(NodeIndex::new(set.depth(), 1)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 1 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
let result = store
|
||||
|
.get_path(set.root(), NodeIndex::new(set.depth() - 1, 2))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[2], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
set.get_path(NodeIndex::new(set.depth(), 2)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
let result = store
|
||||
|
.get_path(set.root(), NodeIndex::new(set.depth() - 1, 3))
|
||||
|
.unwrap();
|
||||
|
assert_eq!(
|
||||
|
LEAVES4[3], result.0,
|
||||
|
"Value for merkle path at index 0 must match leaf value"
|
||||
|
);
|
||||
|
assert_eq!(
|
||||
|
set.get_path(NodeIndex::new(set.depth(), 3)),
|
||||
|
Ok(result.1),
|
||||
|
"merkle path for index 0 must be the same for the MerkleTree and MerkleStore"
|
||||
|
);
|
||||
|
|
||||
|
Ok(())
|
||||
|
}
|
||||
|
|
||||
|
#[test]
|
||||
|
fn wont_open_to_different_depth_root() {
|
||||
|
let empty = EmptySubtreeRoots::empty_hashes(64);
|
||||
|
let a = [Felt::new(1); 4];
|
||||
|
let b = [Felt::new(2); 4];
|
||||
|
|
||||
|
// Compute the root for a different depth. We cherry-pick this specific depth to prevent a
|
||||
|
// regression to a bug in the past that allowed the user to fetch a node at a depth lower than
|
||||
|
// the inserted path of a Merkle tree.
|
||||
|
let mut root = Rpo256::merge(&[a.into(), b.into()]);
|
||||
|
for depth in (1..=63).rev() {
|
||||
|
root = Rpo256::merge(&[root, empty[depth]]);
|
||||
|
}
|
||||
|
let root = Word::from(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 index = NodeIndex::root();
|
||||
|
let err = store.get_node(root, index).err().unwrap();
|
||||
|
assert_eq!(err, MerkleError::RootNotInStore(root));
|
||||
|
}
|
||||
|
|
||||
|
#[test]
|
||||
|
fn store_path_opens_from_leaf() {
|
||||
|
let a = [Felt::new(1); 4];
|
||||
|
let b = [Felt::new(2); 4];
|
||||
|
let c = [Felt::new(3); 4];
|
||||
|
let d = [Felt::new(4); 4];
|
||||
|
let e = [Felt::new(5); 4];
|
||||
|
let f = [Felt::new(6); 4];
|
||||
|
let g = [Felt::new(7); 4];
|
||||
|
let h = [Felt::new(8); 4];
|
||||
|
|
||||
|
let i = Rpo256::merge(&[a.into(), b.into()]);
|
||||
|
let j = Rpo256::merge(&[c.into(), d.into()]);
|
||||
|
let k = Rpo256::merge(&[e.into(), f.into()]);
|
||||
|
let l = Rpo256::merge(&[g.into(), h.into()]);
|
||||
|
|
||||
|
let m = Rpo256::merge(&[i.into(), j.into()]);
|
||||
|
let n = Rpo256::merge(&[k.into(), l.into()]);
|
||||
|
|
||||
|
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::new(3, 1)).unwrap();
|
||||
|
|
||||
|
let expected = MerklePath::new([a.into(), j.into(), n.into()].to_vec());
|
||||
|
assert_eq!(path.1, expected);
|
||||
|
}
|
||||
|
|
||||
|
#[test]
|
||||
|
fn test_set_node() -> Result<(), MerkleError> {
|
||||
|
let mtree = MerkleTree::new(LEAVES4.to_vec())?;
|
||||
|
let mut store = MerkleStore::default().with_merkle_tree(LEAVES4)?;
|
||||
|
let value = int_to_node(42);
|
||||
|
let index = NodeIndex::new(mtree.depth(), 0);
|
||||
|
let new_root = store.set_node(mtree.root(), index, value)?;
|
||||
|
assert_eq!(
|
||||
|
store.get_node(new_root, index),
|
||||
|
Ok(value),
|
||||
|
"Value must have changed"
|
||||
|
);
|
||||
|
|
||||
|
Ok(())
|
||||
|
}
|