Browse Source

Merge pull request #157 from 0xPolygonMiden/tohrnii-digest

refactor: refactor crypto APIs to use RpoDigest instead of Word
al-gkr-basic-workflow
Bobbin Threadbare 1 year ago
committed by GitHub
parent
commit
1be64fc43d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 421 additions and 342 deletions
  1. +2
    -2
      benches/store.rs
  2. +5
    -2
      src/hash/rpo/tests.rs
  3. +42
    -35
      src/merkle/merkle_tree.rs
  4. +15
    -4
      src/merkle/mmr/accumulator.rs
  5. +10
    -10
      src/merkle/mmr/full.rs
  6. +41
    -27
      src/merkle/mmr/tests.rs
  7. +14
    -5
      src/merkle/mod.rs
  8. +4
    -4
      src/merkle/node.rs
  9. +24
    -20
      src/merkle/path.rs
  10. +48
    -47
      src/merkle/path_set.rs
  11. +18
    -17
      src/merkle/simple_smt/mod.rs
  12. +57
    -47
      src/merkle/simple_smt/tests.rs
  13. +53
    -45
      src/merkle/store/mod.rs
  14. +59
    -48
      src/merkle/store/tests.rs
  15. +7
    -7
      src/merkle/tiered_smt/mod.rs
  16. +22
    -22
      src/merkle/tiered_smt/tests.rs

+ 2
- 2
benches/store.rs

@ -409,7 +409,7 @@ fn update_leaf_merkletree(c: &mut Criterion) {
// The MerkleTree automatically updates its internal root, the Store maintains // The MerkleTree automatically updates its internal root, the Store maintains
// the old root and adds the new one. Here we update the root to have a fair // the old root and adds the new one. Here we update the root to have a fair
// comparison // comparison
store_root = store.set_node(root, index, value).unwrap().root;
store_root = store.set_node(root, index, value.into()).unwrap().root;
black_box(store_root) black_box(store_root)
}, },
BatchSize::SmallInput, BatchSize::SmallInput,
@ -455,7 +455,7 @@ fn update_leaf_simplesmt(c: &mut Criterion) {
// The MerkleTree automatically updates its internal root, the Store maintains // The MerkleTree automatically updates its internal root, the Store maintains
// the old root and adds the new one. Here we update the root to have a fair // the old root and adds the new one. Here we update the root to have a fair
// comparison // comparison
store_root = store.set_node(root, index, value).unwrap().root;
store_root = store.set_node(root, index, value.into()).unwrap().root;
black_box(store_root) black_box(store_root)
}, },
BatchSize::SmallInput, BatchSize::SmallInput,

+ 5
- 2
src/hash/rpo/tests.rs

@ -2,7 +2,10 @@ use super::{
Felt, FieldElement, Hasher, Rpo256, RpoDigest, StarkField, ALPHA, INV_ALPHA, ONE, STATE_WIDTH, Felt, FieldElement, Hasher, Rpo256, RpoDigest, StarkField, ALPHA, INV_ALPHA, ONE, STATE_WIDTH,
ZERO, ZERO,
}; };
use crate::utils::collections::{BTreeSet, Vec};
use crate::{
utils::collections::{BTreeSet, Vec},
Word,
};
use core::convert::TryInto; use core::convert::TryInto;
use proptest::prelude::*; use proptest::prelude::*;
use rand_utils::rand_value; use rand_utils::rand_value;
@ -232,7 +235,7 @@ proptest! {
} }
} }
const EXPECTED: [[Felt; 4]; 19] = [
const EXPECTED: [Word; 19] = [
[ [
Felt::new(1502364727743950833), Felt::new(1502364727743950833),
Felt::new(5880949717274681448), Felt::new(5880949717274681448),

+ 42
- 35
src/merkle/merkle_tree.rs

@ -1,11 +1,6 @@
use super::{
Felt, InnerNodeInfo, MerkleError, MerklePath, NodeIndex, Rpo256, RpoDigest, Vec, Word,
};
use crate::{
utils::{string::String, uninit_vector, word_to_hex},
FieldElement,
};
use core::{fmt, slice};
use super::{InnerNodeInfo, MerkleError, MerklePath, NodeIndex, Rpo256, RpoDigest, Vec, Word};
use crate::utils::{string::String, uninit_vector, word_to_hex};
use core::{fmt, ops::Deref, slice};
use winter_math::log2; use winter_math::log2;
// MERKLE TREE // MERKLE TREE
@ -14,7 +9,7 @@ use winter_math::log2;
/// A fully-balanced binary Merkle tree (i.e., a tree where the number of leaves is a power of two). /// A fully-balanced binary Merkle tree (i.e., a tree where the number of leaves is a power of two).
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct MerkleTree { pub struct MerkleTree {
nodes: Vec<Word>,
nodes: Vec<RpoDigest>,
} }
impl MerkleTree { impl MerkleTree {
@ -34,10 +29,12 @@ impl MerkleTree {
// create un-initialized vector to hold all tree nodes // create un-initialized vector to hold all tree nodes
let mut nodes = unsafe { uninit_vector(2 * n) }; let mut nodes = unsafe { uninit_vector(2 * n) };
nodes[0] = [Felt::ZERO; 4];
nodes[0] = RpoDigest::default();
// copy leaves into the second part of the nodes vector // copy leaves into the second part of the nodes vector
nodes[n..].copy_from_slice(&leaves);
nodes[n..].iter_mut().zip(leaves).for_each(|(node, leaf)| {
*node = RpoDigest::from(leaf);
});
// re-interpret nodes as an array of two nodes fused together // re-interpret nodes as an array of two nodes fused together
// Safety: `nodes` will never move here as it is not bound to an external lifetime (i.e. // Safety: `nodes` will never move here as it is not bound to an external lifetime (i.e.
@ -47,7 +44,7 @@ impl MerkleTree {
// calculate all internal tree nodes // calculate all internal tree nodes
for i in (1..n).rev() { for i in (1..n).rev() {
nodes[i] = Rpo256::merge(&pairs[i]).into();
nodes[i] = Rpo256::merge(&pairs[i]);
} }
Ok(Self { nodes }) Ok(Self { nodes })
@ -57,7 +54,7 @@ impl MerkleTree {
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
/// Returns the root of this Merkle tree. /// Returns the root of this Merkle tree.
pub fn root(&self) -> Word {
pub fn root(&self) -> RpoDigest {
self.nodes[1] self.nodes[1]
} }
@ -74,7 +71,7 @@ impl MerkleTree {
/// Returns an error if: /// Returns an error if:
/// * The specified depth is greater than the depth of the tree. /// * The specified depth is greater than the depth of the tree.
/// * The specified index is not valid for the specified depth. /// * The specified index is not valid for the specified depth.
pub fn get_node(&self, index: NodeIndex) -> Result<Word, MerkleError> {
pub fn get_node(&self, index: NodeIndex) -> Result<RpoDigest, MerkleError> {
if index.is_root() { if index.is_root() {
return Err(MerkleError::DepthTooSmall(index.depth())); return Err(MerkleError::DepthTooSmall(index.depth()));
} else if index.depth() > self.depth() { } else if index.depth() > self.depth() {
@ -120,7 +117,11 @@ impl MerkleTree {
/// Returns an iterator over the leaves of this [MerkleTree]. /// Returns an iterator over the leaves of this [MerkleTree].
pub fn leaves(&self) -> impl Iterator<Item = (u64, &Word)> { pub fn leaves(&self) -> impl Iterator<Item = (u64, &Word)> {
let leaves_start = self.nodes.len() / 2; let leaves_start = self.nodes.len() / 2;
self.nodes.iter().skip(leaves_start).enumerate().map(|(i, v)| (i as u64, v))
self.nodes
.iter()
.skip(leaves_start)
.enumerate()
.map(|(i, v)| (i as u64, v.deref()))
} }
/// Returns n iterator over every inner node of this [MerkleTree]. /// Returns n iterator over every inner node of this [MerkleTree].
@ -159,13 +160,13 @@ impl MerkleTree {
// update the current node // update the current node
let pos = index.to_scalar_index() as usize; let pos = index.to_scalar_index() as usize;
self.nodes[pos] = value;
self.nodes[pos] = value.into();
// traverse to the root, updating each node with the merged values of its parents // traverse to the root, updating each node with the merged values of its parents
for _ in 0..index.depth() { for _ in 0..index.depth() {
index.move_up(); index.move_up();
let pos = index.to_scalar_index() as usize; let pos = index.to_scalar_index() as usize;
let value = Rpo256::merge(&pairs[pos]).into();
let value = Rpo256::merge(&pairs[pos]);
self.nodes[pos] = value; self.nodes[pos] = value;
} }
@ -180,7 +181,7 @@ impl 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 InnerNodeIterator<'a> { pub struct InnerNodeIterator<'a> {
nodes: &'a Vec<Word>,
nodes: &'a Vec<RpoDigest>,
index: usize, index: usize,
} }
@ -258,13 +259,17 @@ pub fn path_to_text(path: &MerklePath) -> Result {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::merkle::{int_to_node, InnerNodeInfo};
use crate::{
merkle::{digests_to_words, int_to_leaf, int_to_node, InnerNodeInfo},
Felt, Word, WORD_SIZE,
};
use core::mem::size_of; use core::mem::size_of;
use proptest::prelude::*; 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: [RpoDigest; WORD_SIZE] =
[int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
const LEAVES8: [Word; 8] = [
const LEAVES8: [RpoDigest; 8] = [
int_to_node(1), int_to_node(1),
int_to_node(2), int_to_node(2),
int_to_node(3), int_to_node(3),
@ -277,12 +282,12 @@ mod tests {
#[test] #[test]
fn build_merkle_tree() { fn build_merkle_tree() {
let tree = super::MerkleTree::new(LEAVES4.to_vec()).unwrap();
let tree = super::MerkleTree::new(digests_to_words(&LEAVES4)).unwrap();
assert_eq!(8, tree.nodes.len()); assert_eq!(8, tree.nodes.len());
// leaves were copied correctly // leaves were copied correctly
for (a, b) in tree.nodes.iter().skip(4).zip(LEAVES4.iter()) { for (a, b) in tree.nodes.iter().skip(4).zip(LEAVES4.iter()) {
assert_eq!(a, b);
assert_eq!(*a, RpoDigest::from(*b));
} }
let (root, node2, node3) = compute_internal_nodes(); let (root, node2, node3) = compute_internal_nodes();
@ -296,7 +301,7 @@ mod tests {
#[test] #[test]
fn get_leaf() { fn get_leaf() {
let tree = super::MerkleTree::new(LEAVES4.to_vec()).unwrap();
let tree = super::MerkleTree::new(digests_to_words(&LEAVES4)).unwrap();
// check depth 2 // check depth 2
assert_eq!(LEAVES4[0], tree.get_node(NodeIndex::make(2, 0)).unwrap()); assert_eq!(LEAVES4[0], tree.get_node(NodeIndex::make(2, 0)).unwrap());
@ -313,7 +318,7 @@ mod tests {
#[test] #[test]
fn get_path() { fn get_path() {
let tree = super::MerkleTree::new(LEAVES4.to_vec()).unwrap();
let tree = super::MerkleTree::new(digests_to_words(&LEAVES4)).unwrap();
let (_, node2, node3) = compute_internal_nodes(); let (_, node2, node3) = compute_internal_nodes();
@ -330,13 +335,13 @@ mod tests {
#[test] #[test]
fn update_leaf() { fn update_leaf() {
let mut tree = super::MerkleTree::new(LEAVES8.to_vec()).unwrap();
let mut tree = super::MerkleTree::new(digests_to_words(&LEAVES8)).unwrap();
// update one leaf // update one leaf
let value = 3; let value = 3;
let new_node = int_to_node(9);
let mut expected_leaves = LEAVES8.to_vec();
expected_leaves[value as usize] = new_node;
let new_node = int_to_leaf(9);
let mut expected_leaves = digests_to_words(&LEAVES8);
expected_leaves[value as usize] = new_node.into();
let expected_tree = super::MerkleTree::new(expected_leaves.clone()).unwrap(); let expected_tree = super::MerkleTree::new(expected_leaves.clone()).unwrap();
tree.update_leaf(value, new_node).unwrap(); tree.update_leaf(value, new_node).unwrap();
@ -344,7 +349,7 @@ mod tests {
// update another leaf // update another leaf
let value = 6; let value = 6;
let new_node = int_to_node(10);
let new_node = int_to_leaf(10);
expected_leaves[value as usize] = new_node; expected_leaves[value as usize] = new_node;
let expected_tree = super::MerkleTree::new(expected_leaves.clone()).unwrap(); let expected_tree = super::MerkleTree::new(expected_leaves.clone()).unwrap();
@ -354,7 +359,7 @@ mod tests {
#[test] #[test]
fn nodes() -> Result<(), MerkleError> { fn nodes() -> Result<(), MerkleError> {
let tree = super::MerkleTree::new(LEAVES4.to_vec()).unwrap();
let tree = super::MerkleTree::new(digests_to_words(&LEAVES4)).unwrap();
let root = tree.root(); let root = tree.root();
let l1n0 = tree.get_node(NodeIndex::make(1, 0))?; let l1n0 = tree.get_node(NodeIndex::make(1, 0))?;
let l1n1 = tree.get_node(NodeIndex::make(1, 1))?; let l1n1 = tree.get_node(NodeIndex::make(1, 1))?;
@ -417,11 +422,13 @@ mod tests {
// HELPER FUNCTIONS // HELPER FUNCTIONS
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
fn compute_internal_nodes() -> (Word, Word, Word) {
let node2 = Rpo256::hash_elements(&[LEAVES4[0], LEAVES4[1]].concat());
let node3 = Rpo256::hash_elements(&[LEAVES4[2], LEAVES4[3]].concat());
fn compute_internal_nodes() -> (RpoDigest, RpoDigest, RpoDigest) {
let node2 =
Rpo256::hash_elements(&[Word::from(LEAVES4[0]), Word::from(LEAVES4[1])].concat());
let node3 =
Rpo256::hash_elements(&[Word::from(LEAVES4[2]), Word::from(LEAVES4[3])].concat());
let root = Rpo256::merge(&[node2, node3]); let root = Rpo256::merge(&[node2, node3]);
(root.into(), node2.into(), node3.into())
(root, node2, node3)
} }
} }

+ 15
- 4
src/merkle/mmr/accumulator.rs

@ -1,4 +1,7 @@
use super::{super::Vec, super::ZERO, Felt, MmrProof, Rpo256, Word};
use super::{
super::{RpoDigest, Vec, ZERO},
Felt, MmrProof, Rpo256, Word,
};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct MmrPeaks { pub struct MmrPeaks {
@ -25,7 +28,7 @@ pub struct MmrPeaks {
/// leaves, starting from the peak with most children, to the one with least. /// leaves, starting from the peak with most children, to the one with least.
/// ///
/// Invariant: The length of `peaks` must be equal to the number of true bits in `num_leaves`. /// Invariant: The length of `peaks` must be equal to the number of true bits in `num_leaves`.
pub peaks: Vec<Word>,
pub peaks: Vec<RpoDigest>,
} }
impl MmrPeaks { impl MmrPeaks {
@ -38,7 +41,7 @@ impl MmrPeaks {
Rpo256::hash_elements(&self.flatten_and_pad_peaks()).into() Rpo256::hash_elements(&self.flatten_and_pad_peaks()).into()
} }
pub fn verify(&self, value: Word, opening: MmrProof) -> bool {
pub fn verify(&self, value: RpoDigest, opening: MmrProof) -> bool {
let root = &self.peaks[opening.peak_index()]; 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)
} }
@ -72,7 +75,15 @@ impl MmrPeaks {
}; };
let mut elements = Vec::with_capacity(len); let mut elements = Vec::with_capacity(len);
elements.extend_from_slice(&self.peaks.as_slice().concat());
elements.extend_from_slice(
&self
.peaks
.as_slice()
.iter()
.map(|digest| digest.into())
.collect::<Vec<Word>>()
.concat(),
);
elements.resize(len, ZERO); elements.resize(len, ZERO);
elements elements
} }

+ 10
- 10
src/merkle/mmr/full.rs

@ -10,10 +10,10 @@
//! depths, i.e. as part of adding adding a new element to the forest the trees with same depth are //! depths, i.e. as part of adding adding a new element to the forest the trees with same depth are
//! merged, creating a new tree with depth d+1, this process is continued until the property is //! merged, creating a new tree with depth d+1, this process is continued until the property is
//! restabilished. //! restabilished.
use super::bit::TrueBitPositionIterator;
use super::{ use super::{
super::{InnerNodeInfo, MerklePath, Vec},
MmrPeaks, MmrProof, Rpo256, Word,
super::{InnerNodeInfo, MerklePath, RpoDigest, Vec},
bit::TrueBitPositionIterator,
MmrPeaks, MmrProof, Rpo256,
}; };
use core::fmt::{Display, Formatter}; use core::fmt::{Display, Formatter};
@ -38,7 +38,7 @@ pub struct Mmr {
/// the elements of every tree in the forest to be stored in the same sequential buffer. It /// the elements of every tree in the forest to be stored in the same sequential buffer. It
/// also means new elements can be added to the forest, and merging of trees is very cheap with /// also means new elements can be added to the forest, and merging of trees is very cheap with
/// no need to copy elements. /// no need to copy elements.
pub(super) nodes: Vec<Word>,
pub(super) nodes: Vec<RpoDigest>,
} }
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
@ -129,7 +129,7 @@ impl Mmr {
/// Note: The leaf position is the 0-indexed number corresponding to the order the leaves were /// Note: The leaf position is the 0-indexed number corresponding to the order the leaves were
/// added, this corresponds to the MMR size _prior_ to adding the element. So the 1st element /// added, this corresponds to the MMR size _prior_ to adding the element. So the 1st element
/// has position 0, the second position 1, and so on. /// has position 0, the second position 1, and so on.
pub fn get(&self, pos: usize) -> Result<Word, MmrError> {
pub fn get(&self, pos: usize) -> Result<RpoDigest, MmrError> {
// find the target tree responsible for the MMR position // find the target tree responsible for the MMR position
let tree_bit = let tree_bit =
leaf_to_corresponding_tree(pos, self.forest).ok_or(MmrError::InvalidPosition(pos))?; leaf_to_corresponding_tree(pos, self.forest).ok_or(MmrError::InvalidPosition(pos))?;
@ -153,7 +153,7 @@ impl Mmr {
} }
/// Adds a new element to the MMR. /// Adds a new element to the MMR.
pub fn add(&mut self, el: Word) {
pub fn add(&mut self, el: RpoDigest) {
// Note: every node is also a tree of size 1, adding an element to the forest creates a new // Note: every node is also a tree of size 1, adding an element to the forest creates a new
// rooted-tree of size 1. This may temporarily break the invariant that every tree in the // rooted-tree of size 1. This may temporarily break the invariant that every tree in the
// forest has different sizes, the loop below will eagerly merge trees of same size and // forest has different sizes, the loop below will eagerly merge trees of same size and
@ -164,7 +164,7 @@ impl Mmr {
let mut right = el; let mut right = el;
let mut left_tree = 1; let mut left_tree = 1;
while self.forest & left_tree != 0 { while self.forest & left_tree != 0 {
right = *Rpo256::merge(&[self.nodes[left_offset].into(), right.into()]);
right = Rpo256::merge(&[self.nodes[left_offset], right]);
self.nodes.push(right); self.nodes.push(right);
left_offset = left_offset.saturating_sub(nodes_in_forest(left_tree)); left_offset = left_offset.saturating_sub(nodes_in_forest(left_tree));
@ -176,7 +176,7 @@ impl Mmr {
/// Returns an accumulator representing the current state of the MMR. /// Returns an accumulator representing the current state of the MMR.
pub fn accumulator(&self) -> MmrPeaks { pub fn accumulator(&self) -> MmrPeaks {
let peaks: Vec<Word> = TrueBitPositionIterator::new(self.forest)
let peaks: Vec<RpoDigest> = TrueBitPositionIterator::new(self.forest)
.rev() .rev()
.map(|bit| nodes_in_forest(1 << bit)) .map(|bit| nodes_in_forest(1 << bit))
.scan(0, |offset, el| { .scan(0, |offset, el| {
@ -212,7 +212,7 @@ impl Mmr {
relative_pos: usize, relative_pos: usize,
index_offset: usize, index_offset: usize,
mut index: usize, mut index: usize,
) -> (Word, Vec<Word>) {
) -> (RpoDigest, Vec<RpoDigest>) {
// collect the Merkle path // collect the Merkle path
let mut tree_depth = tree_bit as usize; let mut tree_depth = tree_bit as usize;
let mut path = Vec::with_capacity(tree_depth + 1); let mut path = Vec::with_capacity(tree_depth + 1);
@ -247,7 +247,7 @@ impl Mmr {
impl<T> From<T> for Mmr impl<T> From<T> for Mmr
where where
T: IntoIterator<Item = Word>,
T: IntoIterator<Item = RpoDigest>,
{ {
fn from(values: T) -> Self { fn from(values: T) -> Self {
let mut mmr = Mmr::new(); let mut mmr = Mmr::new();

+ 41
- 27
src/merkle/mmr/tests.rs

@ -1,10 +1,14 @@
use super::bit::TrueBitPositionIterator;
use super::full::{high_bitmask, leaf_to_corresponding_tree, nodes_in_forest};
use super::{ use super::{
super::{InnerNodeInfo, Vec, WORD_SIZE, ZERO},
Mmr, MmrPeaks, Rpo256, Word,
super::{InnerNodeInfo, Vec},
bit::TrueBitPositionIterator,
full::{high_bitmask, leaf_to_corresponding_tree, nodes_in_forest},
Mmr, MmrPeaks, Rpo256,
};
use crate::{
hash::rpo::RpoDigest,
merkle::{int_to_node, MerklePath},
Felt, Word,
}; };
use crate::merkle::{int_to_node, MerklePath};
#[test] #[test]
fn test_position_equal_or_higher_than_leafs_is_never_contained() { fn test_position_equal_or_higher_than_leafs_is_never_contained() {
@ -99,7 +103,7 @@ fn test_nodes_in_forest_single_bit() {
} }
} }
const LEAVES: [Word; 7] = [
const LEAVES: [RpoDigest; 7] = [
int_to_node(0), int_to_node(0),
int_to_node(1), int_to_node(1),
int_to_node(2), int_to_node(2),
@ -114,14 +118,14 @@ fn test_mmr_simple() {
let mut postorder = Vec::new(); let mut postorder = Vec::new();
postorder.push(LEAVES[0]); postorder.push(LEAVES[0]);
postorder.push(LEAVES[1]); postorder.push(LEAVES[1]);
postorder.push(*Rpo256::hash_elements(&[LEAVES[0], LEAVES[1]].concat()));
postorder.push(Rpo256::merge(&[LEAVES[0], LEAVES[1]]));
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(&[postorder[2], postorder[5]].concat()));
postorder.push(Rpo256::merge(&[LEAVES[2], LEAVES[3]]));
postorder.push(Rpo256::merge(&[postorder[2], postorder[5]]));
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::merge(&[LEAVES[4], LEAVES[5]]));
postorder.push(LEAVES[6]); postorder.push(LEAVES[6]);
let mut mmr = Mmr::new(); let mut mmr = Mmr::new();
@ -195,8 +199,8 @@ fn test_mmr_simple() {
#[test] #[test]
fn test_mmr_open() { fn test_mmr_open() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let h01: Word = Rpo256::hash_elements(&LEAVES[0..2].concat()).into();
let h23: Word = Rpo256::hash_elements(&LEAVES[2..4].concat()).into();
let h01 = Rpo256::merge(&[LEAVES[0], LEAVES[1]]);
let h23 = Rpo256::merge(&[LEAVES[2], LEAVES[3]]);
// node at pos 7 is the root // 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");
@ -214,7 +218,7 @@ fn test_mmr_open() {
"MmrProof should be valid for the current accumulator." "MmrProof should be valid for the current accumulator."
); );
// nodes 4,5 are detph 1
// nodes 4,5 are depth 1
let root_to_path = MerklePath::new(vec![LEAVES[4]]); let root_to_path = MerklePath::new(vec![LEAVES[4]]);
let opening = mmr let opening = mmr
.open(5) .open(5)
@ -361,10 +365,10 @@ fn test_mmr_inner_nodes() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let nodes: Vec<InnerNodeInfo> = mmr.inner_nodes().collect(); let nodes: Vec<InnerNodeInfo> = mmr.inner_nodes().collect();
let h01 = *Rpo256::hash_elements(&[LEAVES[0], LEAVES[1]].concat());
let h23 = *Rpo256::hash_elements(&[LEAVES[2], LEAVES[3]].concat());
let h0123 = *Rpo256::hash_elements(&[h01, h23].concat());
let h45 = *Rpo256::hash_elements(&[LEAVES[4], LEAVES[5]].concat());
let h01 = Rpo256::merge(&[LEAVES[0], LEAVES[1]]);
let h23 = Rpo256::merge(&[LEAVES[2], LEAVES[3]]);
let h0123 = Rpo256::merge(&[h01, h23]);
let h45 = Rpo256::merge(&[LEAVES[4], LEAVES[5]]);
let postorder = vec![ let postorder = vec![
InnerNodeInfo { InnerNodeInfo {
value: h01, value: h01,
@ -396,17 +400,20 @@ fn test_mmr_hash_peaks() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let peaks = mmr.accumulator(); let peaks = mmr.accumulator();
let first_peak = *Rpo256::merge(&[
Rpo256::hash_elements(&[LEAVES[0], LEAVES[1]].concat()),
Rpo256::hash_elements(&[LEAVES[2], LEAVES[3]].concat()),
let first_peak = Rpo256::merge(&[
Rpo256::merge(&[LEAVES[0], LEAVES[1]]),
Rpo256::merge(&[LEAVES[2], LEAVES[3]]),
]); ]);
let second_peak = *Rpo256::hash_elements(&[LEAVES[4], LEAVES[5]].concat());
let second_peak = Rpo256::merge(&[LEAVES[4], LEAVES[5]]);
let third_peak = LEAVES[6]; let third_peak = LEAVES[6];
// 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]);
assert_eq!(peaks.hash_peaks(), *Rpo256::hash_elements(&expected_peaks.as_slice().concat()));
expected_peaks.resize(16, RpoDigest::default());
assert_eq!(
peaks.hash_peaks(),
*Rpo256::hash_elements(&digests_to_elements(&expected_peaks))
);
} }
#[test] #[test]
@ -422,10 +429,10 @@ fn test_mmr_peaks_hash_less_than_16() {
// minimum length is 16 // minimum length is 16
let mut expected_peaks = peaks.clone(); let mut expected_peaks = peaks.clone();
expected_peaks.resize(16, [ZERO; WORD_SIZE]);
expected_peaks.resize(16, RpoDigest::default());
assert_eq!( assert_eq!(
accumulator.hash_peaks(), accumulator.hash_peaks(),
*Rpo256::hash_elements(&expected_peaks.as_slice().concat())
*Rpo256::hash_elements(&digests_to_elements(&expected_peaks))
); );
} }
} }
@ -441,10 +448,10 @@ fn test_mmr_peaks_hash_odd() {
// odd length bigger than 16 is padded to the next even nubmer // odd length bigger than 16 is padded to the next even nubmer
let mut expected_peaks = peaks.clone(); let mut expected_peaks = peaks.clone();
expected_peaks.resize(18, [ZERO; WORD_SIZE]);
expected_peaks.resize(18, RpoDigest::default());
assert_eq!( assert_eq!(
accumulator.hash_peaks(), accumulator.hash_peaks(),
*Rpo256::hash_elements(&expected_peaks.as_slice().concat())
*Rpo256::hash_elements(&digests_to_elements(&expected_peaks))
); );
} }
@ -476,3 +483,10 @@ mod property_tests {
} }
} }
} }
// HELPER FUNCTIONS
// ================================================================================================
fn digests_to_elements(digests: &[RpoDigest]) -> Vec<Felt> {
digests.iter().flat_map(|v| Word::from(v)).collect()
}

+ 14
- 5
src/merkle/mod.rs

@ -10,7 +10,6 @@ use core::fmt;
mod empty_roots; mod empty_roots;
pub use empty_roots::EmptySubtreeRoots; pub use empty_roots::EmptySubtreeRoots;
use empty_roots::EMPTY_WORD;
mod index; mod index;
pub use index::NodeIndex; pub use index::NodeIndex;
@ -44,7 +43,7 @@ pub use node::InnerNodeInfo;
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum MerkleError { pub enum MerkleError {
ConflictingRoots(Vec<Word>),
ConflictingRoots(Vec<RpoDigest>),
DepthTooSmall(u8), DepthTooSmall(u8),
DepthTooBig(u64), DepthTooBig(u64),
DuplicateValuesForIndex(u64), DuplicateValuesForIndex(u64),
@ -54,9 +53,9 @@ pub enum MerkleError {
InvalidPath(MerklePath), InvalidPath(MerklePath),
InvalidNumEntries(usize, usize), InvalidNumEntries(usize, usize),
NodeNotInSet(NodeIndex), NodeNotInSet(NodeIndex),
NodeNotInStore(Word, NodeIndex),
NodeNotInStore(RpoDigest, NodeIndex),
NumLeavesNotPowerOfTwo(usize), NumLeavesNotPowerOfTwo(usize),
RootNotInStore(Word),
RootNotInStore(RpoDigest),
} }
impl fmt::Display for MerkleError { impl fmt::Display for MerkleError {
@ -95,6 +94,16 @@ impl std::error::Error for MerkleError {}
// ================================================================================================ // ================================================================================================
#[cfg(test)] #[cfg(test)]
const fn int_to_node(value: u64) -> Word {
const fn int_to_node(value: u64) -> RpoDigest {
RpoDigest::new([Felt::new(value), ZERO, ZERO, ZERO])
}
#[cfg(test)]
const fn int_to_leaf(value: u64) -> Word {
[Felt::new(value), ZERO, ZERO, ZERO] [Felt::new(value), ZERO, ZERO, ZERO]
} }
#[cfg(test)]
fn digests_to_words(digests: &[RpoDigest]) -> Vec<Word> {
digests.iter().map(|d| d.into()).collect()
}

+ 4
- 4
src/merkle/node.rs

@ -1,9 +1,9 @@
use super::Word;
use crate::hash::rpo::RpoDigest;
/// Representation of a node with two children used for iterating over containers. /// Representation of a node with two children used for iterating over containers.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct InnerNodeInfo { pub struct InnerNodeInfo {
pub value: Word,
pub left: Word,
pub right: Word,
pub value: RpoDigest,
pub left: RpoDigest,
pub right: RpoDigest,
} }

+ 24
- 20
src/merkle/path.rs

@ -1,4 +1,4 @@
use super::{vec, InnerNodeInfo, MerkleError, NodeIndex, Rpo256, Vec, Word};
use super::{vec, InnerNodeInfo, MerkleError, NodeIndex, Rpo256, RpoDigest, Vec};
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
// MERKLE PATH // MERKLE PATH
@ -7,7 +7,7 @@ use core::ops::{Deref, DerefMut};
/// A merkle path container, composed of a sequence of nodes of a Merkle tree. /// A merkle path container, composed of a sequence of nodes of a Merkle tree.
#[derive(Clone, Debug, Default, PartialEq, Eq)] #[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct MerklePath { pub struct MerklePath {
nodes: Vec<Word>,
nodes: Vec<RpoDigest>,
} }
impl MerklePath { impl MerklePath {
@ -15,7 +15,7 @@ impl MerklePath {
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
/// Creates a new Merkle path from a list of nodes. /// Creates a new Merkle path from a list of nodes.
pub fn new(nodes: Vec<Word>) -> Self {
pub fn new(nodes: Vec<RpoDigest>) -> Self {
Self { nodes } Self { nodes }
} }
@ -28,13 +28,13 @@ impl MerklePath {
} }
/// 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: RpoDigest) -> Result<RpoDigest, MerkleError> {
let mut index = NodeIndex::new(self.depth(), index)?; let mut index = NodeIndex::new(self.depth(), index)?;
let root = self.nodes.iter().copied().fold(node, |node, sibling| { let root = self.nodes.iter().copied().fold(node, |node, sibling| {
// compute the node and move to the next iteration. // compute the node and move to the next iteration.
let input = index.build_node(node.into(), sibling.into());
let input = index.build_node(node, sibling);
index.move_up(); index.move_up();
Rpo256::merge(&input).into()
Rpo256::merge(&input)
}); });
Ok(root) Ok(root)
} }
@ -42,7 +42,7 @@ impl MerklePath {
/// 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`.
pub fn verify(&self, index: u64, node: Word, root: &Word) -> bool {
pub fn verify(&self, index: u64, node: RpoDigest, root: &RpoDigest) -> bool {
match self.compute_root(index, node) { match self.compute_root(index, node) {
Ok(computed_root) => root == &computed_root, Ok(computed_root) => root == &computed_root,
Err(_) => false, Err(_) => false,
@ -55,7 +55,11 @@ impl MerklePath {
/// ///
/// # Errors /// # Errors
/// Returns an error if the specified index is not valid for this path. /// 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> {
pub fn inner_nodes(
&self,
index: u64,
node: RpoDigest,
) -> Result<InnerNodeIterator, MerkleError> {
Ok(InnerNodeIterator { Ok(InnerNodeIterator {
nodes: &self.nodes, nodes: &self.nodes,
index: NodeIndex::new(self.depth(), index)?, index: NodeIndex::new(self.depth(), index)?,
@ -64,8 +68,8 @@ impl MerklePath {
} }
} }
impl From<Vec<Word>> for MerklePath {
fn from(path: Vec<Word>) -> Self {
impl From<Vec<RpoDigest>> for MerklePath {
fn from(path: Vec<RpoDigest>) -> Self {
Self::new(path) Self::new(path)
} }
} }
@ -73,7 +77,7 @@ impl From> for MerklePath {
impl Deref for MerklePath { impl Deref for MerklePath {
// we use `Vec` here instead of slice so we can call vector mutation methods directly from the // we use `Vec` here instead of slice so we can call vector mutation methods directly from the
// merkle path (example: `Vec::remove`). // merkle path (example: `Vec::remove`).
type Target = Vec<Word>;
type Target = Vec<RpoDigest>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.nodes &self.nodes
@ -89,15 +93,15 @@ impl DerefMut for MerklePath {
// ITERATORS // ITERATORS
// ================================================================================================ // ================================================================================================
impl FromIterator<Word> for MerklePath {
fn from_iter<T: IntoIterator<Item = Word>>(iter: T) -> Self {
impl FromIterator<RpoDigest> for MerklePath {
fn from_iter<T: IntoIterator<Item = RpoDigest>>(iter: T) -> Self {
Self::new(iter.into_iter().collect()) Self::new(iter.into_iter().collect())
} }
} }
impl IntoIterator for MerklePath { impl IntoIterator for MerklePath {
type Item = Word;
type IntoIter = vec::IntoIter<Word>;
type Item = RpoDigest;
type IntoIter = vec::IntoIter<RpoDigest>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.nodes.into_iter() self.nodes.into_iter()
@ -106,9 +110,9 @@ impl IntoIterator for MerklePath {
/// An iterator over internal nodes of a [MerklePath]. /// An iterator over internal nodes of a [MerklePath].
pub struct InnerNodeIterator<'a> { pub struct InnerNodeIterator<'a> {
nodes: &'a Vec<Word>,
nodes: &'a Vec<RpoDigest>,
index: NodeIndex, index: NodeIndex,
value: Word,
value: RpoDigest,
} }
impl<'a> Iterator for InnerNodeIterator<'a> { impl<'a> Iterator for InnerNodeIterator<'a> {
@ -123,7 +127,7 @@ impl<'a> Iterator for InnerNodeIterator<'a> {
(self.value, self.nodes[sibling_pos]) (self.value, self.nodes[sibling_pos])
}; };
self.value = Rpo256::merge(&[left.into(), right.into()]).into();
self.value = Rpo256::merge(&[left, right]);
self.index.move_up(); self.index.move_up();
Some(InnerNodeInfo { Some(InnerNodeInfo {
@ -144,7 +148,7 @@ impl<'a> Iterator for InnerNodeIterator<'a> {
#[derive(Clone, Debug, Default, PartialEq, Eq)] #[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct ValuePath { pub struct ValuePath {
/// The node value opening for `path`. /// The node value opening for `path`.
pub value: Word,
pub value: RpoDigest,
/// The path from `value` to `root` (exclusive). /// The path from `value` to `root` (exclusive).
pub path: MerklePath, pub path: MerklePath,
} }
@ -156,7 +160,7 @@ pub struct ValuePath {
#[derive(Clone, Debug, Default, PartialEq, Eq)] #[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct RootPath { pub struct RootPath {
/// The node value opening for `path`. /// The node value opening for `path`.
pub root: Word,
pub root: RpoDigest,
/// The path from `value` to `root` (exclusive). /// The path from `value` to `root` (exclusive).
pub path: MerklePath, pub path: MerklePath,
} }

+ 48
- 47
src/merkle/path_set.rs

@ -1,4 +1,5 @@
use super::{BTreeMap, MerkleError, MerklePath, NodeIndex, Rpo256, ValuePath, Vec, Word, ZERO};
use super::{BTreeMap, MerkleError, MerklePath, NodeIndex, Rpo256, ValuePath, Vec};
use crate::{hash::rpo::RpoDigest, Word};
// MERKLE PATH SET // MERKLE PATH SET
// ================================================================================================ // ================================================================================================
@ -6,7 +7,7 @@ use super::{BTreeMap, MerkleError, MerklePath, NodeIndex, Rpo256, ValuePath, Vec
/// A set of Merkle paths. /// A set of Merkle paths.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct MerklePathSet { pub struct MerklePathSet {
root: Word,
root: RpoDigest,
total_depth: u8, total_depth: u8,
paths: BTreeMap<u64, MerklePath>, paths: BTreeMap<u64, MerklePath>,
} }
@ -17,7 +18,7 @@ impl MerklePathSet {
/// Returns an empty MerklePathSet. /// Returns an empty MerklePathSet.
pub fn new(depth: u8) -> Self { pub fn new(depth: u8) -> Self {
let root = [ZERO; 4];
let root = RpoDigest::default();
let paths = BTreeMap::new(); let paths = BTreeMap::new();
Self { Self {
@ -32,10 +33,10 @@ impl MerklePathSet {
/// Analogous to `[Self::add_path]`. /// Analogous to `[Self::add_path]`.
pub fn with_paths<I>(self, paths: I) -> Result<Self, MerkleError> pub fn with_paths<I>(self, paths: I) -> Result<Self, MerkleError>
where where
I: IntoIterator<Item = (u64, Word, MerklePath)>,
I: IntoIterator<Item = (u64, RpoDigest, 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)?;
set.add_path(index, value.into(), path)?;
Ok(set) Ok(set)
}) })
} }
@ -44,7 +45,7 @@ impl MerklePathSet {
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
/// Returns the root to which all paths in this set resolve. /// Returns the root to which all paths in this set resolve.
pub const fn root(&self) -> Word {
pub const fn root(&self) -> RpoDigest {
self.root self.root
} }
@ -61,7 +62,7 @@ impl MerklePathSet {
/// Returns an error if: /// Returns an error if:
/// * The specified index is not valid for the depth of structure. /// * The specified index is not valid for the depth of structure.
/// * Requested node does not exist in the set. /// * Requested node does not exist in the set.
pub fn get_node(&self, index: NodeIndex) -> Result<Word, MerkleError> {
pub fn get_node(&self, index: NodeIndex) -> Result<RpoDigest, MerkleError> {
if index.depth() != self.total_depth { if index.depth() != self.total_depth {
return Err(MerkleError::InvalidDepth { return Err(MerkleError::InvalidDepth {
expected: self.total_depth, expected: self.total_depth,
@ -84,7 +85,7 @@ impl MerklePathSet {
/// * Leaf with the requested path does not exist in the set. /// * Leaf with the requested path does not exist in the set.
pub fn get_leaf(&self, index: u64) -> Result<Word, MerkleError> { pub fn get_leaf(&self, index: u64) -> Result<Word, MerkleError> {
let index = NodeIndex::new(self.depth(), index)?; let index = NodeIndex::new(self.depth(), index)?;
self.get_node(index)
Ok(self.get_node(index)?.into())
} }
/// Returns a Merkle path to the node at the specified index. The node itself is /// Returns a Merkle path to the node at the specified index. The node itself is
@ -163,18 +164,18 @@ impl MerklePathSet {
// update the current path // update the current path
let parity = index_value & 1; let parity = index_value & 1;
path.insert(parity as usize, value);
path.insert(parity as usize, value.into());
// traverse to the root, updating the nodes // traverse to the root, updating the nodes
let root: Word = Rpo256::merge(&[path[0].into(), path[1].into()]).into();
let root = Rpo256::merge(&[path[0], path[1]]);
let root = path.iter().skip(2).copied().fold(root, |root, hash| { let root = path.iter().skip(2).copied().fold(root, |root, hash| {
index.move_up(); index.move_up();
Rpo256::merge(&index.build_node(root.into(), hash.into())).into()
Rpo256::merge(&index.build_node(root, hash))
}); });
// if the path set is empty (the root is all ZEROs), set the root to the root of the added // if the path set is empty (the root is all ZEROs), set the root to the root of the added
// path; otherwise, the root of the added path must be identical to the current root // path; otherwise, the root of the added path must be identical to the current root
if self.root == [ZERO; 4] {
if self.root == RpoDigest::default() {
self.root = root; self.root = root;
} else if self.root != root { } else if self.root != root {
return Err(MerkleError::ConflictingRoots([self.root, root].to_vec())); return Err(MerkleError::ConflictingRoots([self.root, root].to_vec()));
@ -203,24 +204,24 @@ impl MerklePathSet {
// Fill old_hashes vector ----------------------------------------------------------------- // Fill old_hashes vector -----------------------------------------------------------------
let mut current_index = index; let mut current_index = index;
let mut old_hashes = Vec::with_capacity(path.len().saturating_sub(2)); let mut old_hashes = Vec::with_capacity(path.len().saturating_sub(2));
let mut root: Word = Rpo256::merge(&[path[0].into(), path[1].into()]).into();
let mut root = Rpo256::merge(&[path[0], path[1]]);
for hash in path.iter().skip(2).copied() { for hash in path.iter().skip(2).copied() {
old_hashes.push(root); old_hashes.push(root);
current_index.move_up(); current_index.move_up();
let input = current_index.build_node(hash.into(), root.into());
root = Rpo256::merge(&input).into();
let input = current_index.build_node(hash, root);
root = Rpo256::merge(&input);
} }
// Fill new_hashes vector ----------------------------------------------------------------- // Fill new_hashes vector -----------------------------------------------------------------
path[index.is_value_odd() as usize] = value;
path[index.is_value_odd() as usize] = value.into();
let mut new_hashes = Vec::with_capacity(path.len().saturating_sub(2)); let mut new_hashes = Vec::with_capacity(path.len().saturating_sub(2));
let mut new_root: Word = Rpo256::merge(&[path[0].into(), path[1].into()]).into();
let mut new_root = Rpo256::merge(&[path[0], path[1]]);
for path_hash in path.iter().skip(2).copied() { for path_hash in path.iter().skip(2).copied() {
new_hashes.push(new_root); new_hashes.push(new_root);
index.move_up(); index.move_up();
let input = current_index.build_node(path_hash.into(), new_root.into());
new_root = Rpo256::merge(&input).into();
let input = current_index.build_node(path_hash, new_root);
new_root = Rpo256::merge(&input);
} }
self.root = new_root; self.root = new_root;
@ -245,7 +246,7 @@ impl MerklePathSet {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::merkle::int_to_node;
use crate::merkle::{int_to_leaf, int_to_node};
#[test] #[test]
fn get_root() { fn get_root() {
@ -318,20 +319,20 @@ mod tests {
]) ])
.unwrap(); .unwrap();
let new_hash_6 = int_to_node(100);
let new_hash_5 = int_to_node(55);
let new_hash_6 = int_to_leaf(100);
let new_hash_5 = int_to_leaf(55);
set.update_leaf(index_6, new_hash_6).unwrap(); set.update_leaf(index_6, new_hash_6).unwrap();
let new_path_4 = set.get_path(NodeIndex::make(depth, index_4)).unwrap(); let new_path_4 = set.get_path(NodeIndex::make(depth, index_4)).unwrap();
let new_hash_67 = calculate_parent_hash(new_hash_6, 14_u64, hash_7);
let new_hash_67 = calculate_parent_hash(new_hash_6.into(), 14_u64, hash_7);
assert_eq!(new_hash_67, new_path_4[1]); assert_eq!(new_hash_67, new_path_4[1]);
set.update_leaf(index_5, new_hash_5).unwrap(); set.update_leaf(index_5, new_hash_5).unwrap();
let new_path_4 = set.get_path(NodeIndex::make(depth, index_4)).unwrap(); let new_path_4 = set.get_path(NodeIndex::make(depth, index_4)).unwrap();
let new_path_6 = set.get_path(NodeIndex::make(depth, index_6)).unwrap(); let new_path_6 = set.get_path(NodeIndex::make(depth, index_6)).unwrap();
let new_hash_45 = calculate_parent_hash(new_hash_5, 13_u64, hash_4);
let new_hash_45 = calculate_parent_hash(new_hash_5.into(), 13_u64, hash_4);
assert_eq!(new_hash_45, new_path_6[1]); assert_eq!(new_hash_45, new_path_6[1]);
assert_eq!(new_hash_5, new_path_4[0]);
assert_eq!(RpoDigest::from(new_hash_5), new_path_4[0]);
} }
#[test] #[test]
@ -345,13 +346,13 @@ mod tests {
let g = int_to_node(7); let g = int_to_node(7);
let h = int_to_node(8); let h = int_to_node(8);
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 i = Rpo256::merge(&[a, b]);
let j = Rpo256::merge(&[c, d]);
let k = Rpo256::merge(&[e, f]);
let l = Rpo256::merge(&[g, h]);
let m = Rpo256::merge(&[i.into(), j.into()]);
let n = Rpo256::merge(&[k.into(), l.into()]);
let m = Rpo256::merge(&[i, j]);
let n = Rpo256::merge(&[k, l]);
let root = Rpo256::merge(&[m.into(), n.into()]); let root = Rpo256::merge(&[m.into(), n.into()]);
@ -359,31 +360,31 @@ mod tests {
let value = b; let value = b;
let index = 1; let index = 1;
let path = MerklePath::new([a.into(), j.into(), n.into()].to_vec());
set.add_path(index, value, path.clone()).unwrap();
assert_eq!(value, set.get_leaf(index).unwrap());
assert_eq!(Word::from(root), set.root());
let path = MerklePath::new([a, j, n].to_vec());
set.add_path(index, value.into(), path.clone()).unwrap();
assert_eq!(*value, set.get_leaf(index).unwrap());
assert_eq!(root, set.root());
let value = e; let value = e;
let index = 4; let index = 4;
let path = MerklePath::new([f.into(), l.into(), m.into()].to_vec()); let path = MerklePath::new([f.into(), l.into(), m.into()].to_vec());
set.add_path(index, value, path.clone()).unwrap();
assert_eq!(value, set.get_leaf(index).unwrap());
assert_eq!(Word::from(root), set.root());
set.add_path(index, value.into(), path.clone()).unwrap();
assert_eq!(*value, set.get_leaf(index).unwrap());
assert_eq!(root, set.root());
let value = a; let value = a;
let index = 0; let index = 0;
let path = MerklePath::new([b.into(), j.into(), n.into()].to_vec()); let path = MerklePath::new([b.into(), j.into(), n.into()].to_vec());
set.add_path(index, value, path.clone()).unwrap();
assert_eq!(value, set.get_leaf(index).unwrap());
assert_eq!(Word::from(root), set.root());
set.add_path(index, value.into(), path.clone()).unwrap();
assert_eq!(*value, set.get_leaf(index).unwrap());
assert_eq!(root, set.root());
let value = h; let value = h;
let index = 7; let index = 7;
let path = MerklePath::new([g.into(), k.into(), m.into()].to_vec()); let path = MerklePath::new([g.into(), k.into(), m.into()].to_vec());
set.add_path(index, value, path.clone()).unwrap();
assert_eq!(value, set.get_leaf(index).unwrap());
assert_eq!(Word::from(root), set.root());
set.add_path(index, value.into(), path.clone()).unwrap();
assert_eq!(*value, set.get_leaf(index).unwrap());
assert_eq!(root, set.root());
} }
// HELPER FUNCTIONS // HELPER FUNCTIONS
@ -397,11 +398,11 @@ mod tests {
/// - node — current node /// - node — current node
/// - node_pos — position of the current node /// - node_pos — position of the current node
/// - sibling — neighboring vertex in the tree /// - sibling — neighboring vertex in the tree
fn calculate_parent_hash(node: Word, node_pos: u64, sibling: Word) -> Word {
fn calculate_parent_hash(node: RpoDigest, node_pos: u64, sibling: RpoDigest) -> RpoDigest {
if is_even(node_pos) { if is_even(node_pos) {
Rpo256::merge(&[node.into(), sibling.into()]).into()
Rpo256::merge(&[node, sibling])
} else { } else {
Rpo256::merge(&[sibling.into(), node.into()]).into()
Rpo256::merge(&[sibling, node])
} }
} }
} }

+ 18
- 17
src/merkle/simple_smt/mod.rs

@ -1,6 +1,6 @@
use super::{ use super::{
BTreeMap, BTreeSet, EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, NodeIndex,
Rpo256, RpoDigest, Vec, Word, EMPTY_WORD,
empty_roots::EMPTY_WORD, BTreeMap, BTreeSet, EmptySubtreeRoots, InnerNodeInfo, MerkleError,
MerklePath, NodeIndex, Rpo256, RpoDigest, Vec, Word,
}; };
#[cfg(test)] #[cfg(test)]
@ -15,7 +15,7 @@ mod tests;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct SimpleSmt { pub struct SimpleSmt {
depth: u8, depth: u8,
root: Word,
root: RpoDigest,
leaves: BTreeMap<u64, Word>, leaves: BTreeMap<u64, Word>,
branches: BTreeMap<NodeIndex, BranchNode>, branches: BTreeMap<NodeIndex, BranchNode>,
empty_hashes: Vec<RpoDigest>, empty_hashes: Vec<RpoDigest>,
@ -49,7 +49,7 @@ impl SimpleSmt {
} }
let empty_hashes = EmptySubtreeRoots::empty_hashes(depth).to_vec(); let empty_hashes = EmptySubtreeRoots::empty_hashes(depth).to_vec();
let root = empty_hashes[0].into();
let root = empty_hashes[0];
Ok(Self { Ok(Self {
root, root,
@ -107,7 +107,7 @@ impl SimpleSmt {
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
/// Returns the root of this Merkle tree. /// Returns the root of this Merkle tree.
pub const fn root(&self) -> Word {
pub const fn root(&self) -> RpoDigest {
self.root self.root
} }
@ -121,7 +121,7 @@ impl SimpleSmt {
/// # Errors /// # Errors
/// Returns an error if the specified index has depth set to 0 or the depth is greater than /// Returns an error if the specified index has depth set to 0 or the depth is greater than
/// the depth of this Merkle tree. /// the depth of this Merkle tree.
pub fn get_node(&self, index: NodeIndex) -> Result<Word, MerkleError> {
pub fn get_node(&self, index: NodeIndex) -> Result<RpoDigest, MerkleError> {
if index.is_root() { if index.is_root() {
Err(MerkleError::DepthTooSmall(index.depth())) Err(MerkleError::DepthTooSmall(index.depth()))
} else if index.depth() > self.depth() { } else if index.depth() > self.depth() {
@ -129,11 +129,12 @@ impl SimpleSmt {
} else if index.depth() == self.depth() { } else if index.depth() == self.depth() {
// the lookup in empty_hashes could fail only if empty_hashes were not built correctly // the lookup in empty_hashes could fail only if empty_hashes were not built correctly
// by the constructor as we check the depth of the lookup above. // by the constructor as we check the depth of the lookup above.
Ok(self
.get_leaf_node(index.value())
.unwrap_or_else(|| self.empty_hashes[index.depth() as usize].into()))
Ok(RpoDigest::from(
self.get_leaf_node(index.value())
.unwrap_or_else(|| *self.empty_hashes[index.depth() as usize]),
))
} else { } else {
Ok(self.get_branch_node(&index).parent().into())
Ok(self.get_branch_node(&index).parent())
} }
} }
@ -143,7 +144,7 @@ impl SimpleSmt {
/// Returns an error if the index is greater than the maximum tree capacity, that is 2^{depth}. /// Returns an error if the index is greater than the maximum tree capacity, that is 2^{depth}.
pub fn get_leaf(&self, index: u64) -> Result<Word, MerkleError> { pub fn get_leaf(&self, index: u64) -> Result<Word, MerkleError> {
let index = NodeIndex::new(self.depth, index)?; let index = NodeIndex::new(self.depth, index)?;
self.get_node(index)
Ok(self.get_node(index)?.into())
} }
/// Returns a Merkle path from the node at the specified index to the root. /// Returns a Merkle path from the node at the specified index to the root.
@ -166,9 +167,9 @@ impl SimpleSmt {
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 value = if is_right { left } else { right }; let value = if is_right { left } else { right };
path.push(*value);
path.push(value);
} }
Ok(path.into())
Ok(MerklePath::new(path))
} }
/// Return a Merkle path from the leaf at the specified index to the root. /// Return a Merkle path from the leaf at the specified index to the root.
@ -193,9 +194,9 @@ impl SimpleSmt {
/// Returns an iterator over the inner nodes of this Merkle tree. /// Returns an iterator over the inner nodes of this Merkle tree.
pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ { pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
self.branches.values().map(|e| InnerNodeInfo { self.branches.values().map(|e| InnerNodeInfo {
value: e.parent().into(),
left: e.left.into(),
right: e.right.into(),
value: e.parent(),
left: e.left,
right: e.right,
}) })
} }
@ -226,7 +227,7 @@ impl SimpleSmt {
self.insert_branch_node(index, left, right); self.insert_branch_node(index, left, right);
value = Rpo256::merge(&[left, right]); value = Rpo256::merge(&[left, right]);
} }
self.root = value.into();
self.root = value;
Ok(old_value) Ok(old_value)
} }

+ 57
- 47
src/merkle/simple_smt/tests.rs

@ -1,6 +1,10 @@
use super::{ use super::{
super::{int_to_node, InnerNodeInfo, MerkleError, MerkleTree, RpoDigest, SimpleSmt},
NodeIndex, Rpo256, Vec, Word, EMPTY_WORD,
super::{InnerNodeInfo, MerkleError, MerkleTree, RpoDigest, SimpleSmt},
NodeIndex, Rpo256, Vec,
};
use crate::{
merkle::{digests_to_words, empty_roots::EMPTY_WORD, int_to_leaf, int_to_node},
Word,
}; };
// TEST DATA // TEST DATA
@ -9,9 +13,9 @@ use super::{
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] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
const VALUES4: [RpoDigest; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
const VALUES8: [Word; 8] = [
const VALUES8: [RpoDigest; 8] = [
int_to_node(1), int_to_node(1),
int_to_node(2), int_to_node(2),
int_to_node(3), int_to_node(3),
@ -22,7 +26,7 @@ const VALUES8: [Word; 8] = [
int_to_node(8), int_to_node(8),
]; ];
const ZERO_VALUES8: [Word; 8] = [int_to_node(0); 8];
const ZERO_VALUES8: [Word; 8] = [int_to_leaf(0); 8];
// TESTS // TESTS
// ================================================================================================ // ================================================================================================
@ -42,7 +46,7 @@ fn build_sparse_tree() {
// insert single value // insert single value
let key = 6; let key = 6;
let new_node = int_to_node(7);
let new_node = int_to_leaf(7);
values[key as usize] = new_node; values[key as usize] = new_node;
let old_value = smt.update_leaf(key, new_node).expect("Failed to update leaf"); let old_value = smt.update_leaf(key, new_node).expect("Failed to update leaf");
let mt2 = MerkleTree::new(values.clone()).unwrap(); let mt2 = MerkleTree::new(values.clone()).unwrap();
@ -55,7 +59,7 @@ fn build_sparse_tree() {
// insert second value at distinct leaf branch // insert second value at distinct leaf branch
let key = 2; let key = 2;
let new_node = int_to_node(3);
let new_node = int_to_leaf(3);
values[key as usize] = new_node; values[key as usize] = new_node;
let old_value = smt.update_leaf(key, new_node).expect("Failed to update leaf"); let old_value = smt.update_leaf(key, new_node).expect("Failed to update leaf");
let mt3 = MerkleTree::new(values).unwrap(); let mt3 = MerkleTree::new(values).unwrap();
@ -69,7 +73,9 @@ fn build_sparse_tree() {
#[test] #[test]
fn test_depth2_tree() { fn test_depth2_tree() {
let tree = SimpleSmt::with_leaves(2, KEYS4.into_iter().zip(VALUES4.into_iter())).unwrap();
let tree =
SimpleSmt::with_leaves(2, KEYS4.into_iter().zip(digests_to_words(&VALUES4).into_iter()))
.unwrap();
// check internal structure // check internal structure
let (root, node2, node3) = compute_internal_nodes(); let (root, node2, node3) = compute_internal_nodes();
@ -96,7 +102,9 @@ fn test_depth2_tree() {
#[test] #[test]
fn test_inner_node_iterator() -> Result<(), MerkleError> { fn test_inner_node_iterator() -> Result<(), MerkleError> {
let tree = SimpleSmt::with_leaves(2, KEYS4.into_iter().zip(VALUES4.into_iter())).unwrap();
let tree =
SimpleSmt::with_leaves(2, KEYS4.into_iter().zip(digests_to_words(&VALUES4).into_iter()))
.unwrap();
// check depth 2 // check depth 2
assert_eq!(VALUES4[0], tree.get_node(NodeIndex::make(2, 0)).unwrap()); assert_eq!(VALUES4[0], tree.get_node(NodeIndex::make(2, 0)).unwrap());
@ -116,19 +124,19 @@ fn test_inner_node_iterator() -> Result<(), MerkleError> {
let nodes: Vec<InnerNodeInfo> = tree.inner_nodes().collect(); let nodes: Vec<InnerNodeInfo> = tree.inner_nodes().collect();
let expected = vec![ let expected = vec![
InnerNodeInfo { InnerNodeInfo {
value: root.into(),
left: l1n0.into(),
right: l1n1.into(),
value: root,
left: l1n0,
right: l1n1,
}, },
InnerNodeInfo { InnerNodeInfo {
value: l1n0.into(),
left: l2n0.into(),
right: l2n1.into(),
value: l1n0,
left: l2n0,
right: l2n1,
}, },
InnerNodeInfo { InnerNodeInfo {
value: l1n1.into(),
left: l2n2.into(),
right: l2n3.into(),
value: l1n1,
left: l2n2,
right: l2n3,
}, },
]; ];
assert_eq!(nodes, expected); assert_eq!(nodes, expected);
@ -138,28 +146,30 @@ fn test_inner_node_iterator() -> Result<(), MerkleError> {
#[test] #[test]
fn update_leaf() { fn update_leaf() {
let mut tree = SimpleSmt::with_leaves(3, KEYS8.into_iter().zip(VALUES8.into_iter())).unwrap();
let mut tree =
SimpleSmt::with_leaves(3, KEYS8.into_iter().zip(digests_to_words(&VALUES8).into_iter()))
.unwrap();
// update one value // update one value
let key = 3; let key = 3;
let new_node = int_to_node(9);
let mut expected_values = VALUES8.to_vec();
let new_node = int_to_leaf(9);
let mut expected_values = digests_to_words(&VALUES8);
expected_values[key] = new_node; expected_values[key] = new_node;
let expected_tree = MerkleTree::new(expected_values.clone()).unwrap(); let expected_tree = MerkleTree::new(expected_values.clone()).unwrap();
let old_leaf = tree.update_leaf(key as u64, new_node).unwrap(); let old_leaf = tree.update_leaf(key as u64, new_node).unwrap();
assert_eq!(expected_tree.root(), tree.root); assert_eq!(expected_tree.root(), tree.root);
assert_eq!(old_leaf, VALUES8[key]);
assert_eq!(old_leaf, *VALUES8[key]);
// update another value // update another value
let key = 6; let key = 6;
let new_node = int_to_node(10);
let new_node = int_to_leaf(10);
expected_values[key] = new_node; expected_values[key] = new_node;
let expected_tree = MerkleTree::new(expected_values.clone()).unwrap(); let expected_tree = MerkleTree::new(expected_values.clone()).unwrap();
let old_leaf = tree.update_leaf(key as u64, new_node).unwrap(); let old_leaf = tree.update_leaf(key as u64, new_node).unwrap();
assert_eq!(expected_tree.root(), tree.root); assert_eq!(expected_tree.root(), tree.root);
assert_eq!(old_leaf, VALUES8[key]);
assert_eq!(old_leaf, *VALUES8[key]);
} }
#[test] #[test]
@ -172,34 +182,34 @@ fn small_tree_opening_is_consistent() {
// / \ / \ / \ / \ // / \ / \ / \ / \
// a b 0 0 c 0 0 d // a b 0 0 c 0 0 d
let z = Word::from(RpoDigest::default());
let z = EMPTY_WORD;
let a = Word::from(Rpo256::merge(&[z.into(); 2])); let a = Word::from(Rpo256::merge(&[z.into(); 2]));
let b = Word::from(Rpo256::merge(&[a.into(); 2])); let b = Word::from(Rpo256::merge(&[a.into(); 2]));
let c = Word::from(Rpo256::merge(&[b.into(); 2])); let c = Word::from(Rpo256::merge(&[b.into(); 2]));
let d = Word::from(Rpo256::merge(&[c.into(); 2])); let d = Word::from(Rpo256::merge(&[c.into(); 2]));
let e = Word::from(Rpo256::merge(&[a.into(), b.into()]));
let f = Word::from(Rpo256::merge(&[z.into(), z.into()]));
let g = Word::from(Rpo256::merge(&[c.into(), z.into()]));
let h = Word::from(Rpo256::merge(&[z.into(), d.into()]));
let e = Rpo256::merge(&[a.into(), b.into()]);
let f = Rpo256::merge(&[z.into(), z.into()]);
let g = Rpo256::merge(&[c.into(), z.into()]);
let h = Rpo256::merge(&[z.into(), d.into()]);
let i = Word::from(Rpo256::merge(&[e.into(), f.into()]));
let j = Word::from(Rpo256::merge(&[g.into(), h.into()]));
let i = Rpo256::merge(&[e, f]);
let j = Rpo256::merge(&[g, h]);
let k = Word::from(Rpo256::merge(&[i.into(), j.into()]));
let k = Rpo256::merge(&[i, j]);
let depth = 3; let depth = 3;
let entries = vec![(0, a), (1, b), (4, c), (7, d)]; let entries = vec![(0, a), (1, b), (4, c), (7, d)];
let tree = SimpleSmt::with_leaves(depth, entries).unwrap(); let tree = SimpleSmt::with_leaves(depth, entries).unwrap();
assert_eq!(tree.root(), Word::from(k));
assert_eq!(tree.root(), RpoDigest::from(k));
let cases: Vec<(u8, u64, Vec<Word>)> = vec![
(3, 0, vec![b, f, j]),
(3, 1, vec![a, f, j]),
(3, 4, vec![z, h, i]),
(3, 7, vec![z, g, i]),
let cases: Vec<(u8, u64, Vec<RpoDigest>)> = vec![
(3, 0, vec![b.into(), f, j]),
(3, 1, vec![a.into(), f, j]),
(3, 4, vec![z.into(), h, i]),
(3, 7, vec![z.into(), g, i]),
(2, 0, vec![f, j]), (2, 0, vec![f, j]),
(2, 1, vec![e, j]), (2, 1, vec![e, j]),
(2, 2, vec![h, i]), (2, 2, vec![h, i]),
@ -217,26 +227,26 @@ fn small_tree_opening_is_consistent() {
#[test] #[test]
fn fail_on_duplicates() { fn fail_on_duplicates() {
let entries = [(1_u64, int_to_node(1)), (5, int_to_node(2)), (1_u64, int_to_node(3))];
let entries = [(1_u64, int_to_leaf(1)), (5, int_to_leaf(2)), (1_u64, int_to_leaf(3))];
let smt = SimpleSmt::with_leaves(64, entries); let smt = SimpleSmt::with_leaves(64, entries);
assert!(smt.is_err()); assert!(smt.is_err());
let entries = [(1_u64, int_to_node(0)), (5, int_to_node(2)), (1_u64, int_to_node(0))];
let entries = [(1_u64, int_to_leaf(0)), (5, int_to_leaf(2)), (1_u64, int_to_leaf(0))];
let smt = SimpleSmt::with_leaves(64, entries); let smt = SimpleSmt::with_leaves(64, entries);
assert!(smt.is_err()); assert!(smt.is_err());
let entries = [(1_u64, int_to_node(0)), (5, int_to_node(2)), (1_u64, int_to_node(1))];
let entries = [(1_u64, int_to_leaf(0)), (5, int_to_leaf(2)), (1_u64, int_to_leaf(1))];
let smt = SimpleSmt::with_leaves(64, entries); let smt = SimpleSmt::with_leaves(64, entries);
assert!(smt.is_err()); assert!(smt.is_err());
let entries = [(1_u64, int_to_node(1)), (5, int_to_node(2)), (1_u64, int_to_node(0))];
let entries = [(1_u64, int_to_leaf(1)), (5, int_to_leaf(2)), (1_u64, int_to_leaf(0))];
let smt = SimpleSmt::with_leaves(64, entries); let smt = SimpleSmt::with_leaves(64, entries);
assert!(smt.is_err()); assert!(smt.is_err());
} }
#[test] #[test]
fn with_no_duplicates_empty_node() { fn with_no_duplicates_empty_node() {
let entries = [(1_u64, int_to_node(0)), (5, int_to_node(2))];
let entries = [(1_u64, int_to_leaf(0)), (5, int_to_leaf(2))];
let smt = SimpleSmt::with_leaves(64, entries); let smt = SimpleSmt::with_leaves(64, entries);
assert!(smt.is_ok()); assert!(smt.is_ok());
} }
@ -244,10 +254,10 @@ fn with_no_duplicates_empty_node() {
// HELPER FUNCTIONS // HELPER FUNCTIONS
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
fn compute_internal_nodes() -> (Word, Word, Word) {
let node2 = Rpo256::hash_elements(&[VALUES4[0], VALUES4[1]].concat());
let node3 = Rpo256::hash_elements(&[VALUES4[2], VALUES4[3]].concat());
fn compute_internal_nodes() -> (RpoDigest, RpoDigest, RpoDigest) {
let node2 = Rpo256::merge(&[VALUES4[0], VALUES4[1]]);
let node3 = Rpo256::merge(&[VALUES4[2], VALUES4[3]]);
let root = Rpo256::merge(&[node2, node3]); let root = Rpo256::merge(&[node2, node3]);
(root.into(), node2.into(), node3.into())
(root, node2, node3)
} }

+ 53
- 45
src/merkle/store/mod.rs

@ -1,6 +1,6 @@
use super::{ use super::{
mmr::Mmr, BTreeMap, EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, MerklePathSet, mmr::Mmr, BTreeMap, EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, MerklePathSet,
MerkleTree, NodeIndex, RootPath, Rpo256, RpoDigest, SimpleSmt, TieredSmt, ValuePath, Vec, Word,
MerkleTree, NodeIndex, RootPath, Rpo256, RpoDigest, SimpleSmt, TieredSmt, ValuePath, Vec,
}; };
use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
use core::borrow::Borrow; use core::borrow::Borrow;
@ -130,21 +130,20 @@ impl MerkleStore {
/// This method can return the following errors: /// This method can return the following errors:
/// - `RootNotInStore` if the `root` is not present in the store. /// - `RootNotInStore` if the `root` is not present in the store.
/// - `NodeNotInStore` if a node needed to traverse from `root` to `index` is not present in the store. /// - `NodeNotInStore` if a node needed to traverse from `root` to `index` is not present in the store.
pub fn get_node(&self, root: Word, index: NodeIndex) -> Result<Word, MerkleError> {
let mut hash: RpoDigest = root.into();
pub fn get_node(&self, root: RpoDigest, index: NodeIndex) -> Result<RpoDigest, MerkleError> {
let mut hash = root;
// 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.get(&hash).ok_or(MerkleError::RootNotInStore(hash.into()))?;
self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash))?;
for i in (0..index.depth()).rev() { 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, 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 }
} }
Ok(hash.into())
Ok(hash)
} }
/// Returns the node at the specified `index` and its opening to the `root`. /// Returns the node at the specified `index` and its opening to the `root`.
@ -155,23 +154,22 @@ impl MerkleStore {
/// This method can return the following errors: /// This method can return the following errors:
/// - `RootNotInStore` if the `root` is not present in the store. /// - `RootNotInStore` if the `root` is not present in the store.
/// - `NodeNotInStore` if a node needed to traverse from `root` to `index` is not present in the store. /// - `NodeNotInStore` if a node needed to traverse from `root` to `index` is not present in the store.
pub fn get_path(&self, root: Word, index: NodeIndex) -> Result<ValuePath, MerkleError> {
let mut hash: RpoDigest = root.into();
pub fn get_path(&self, root: RpoDigest, index: NodeIndex) -> Result<ValuePath, MerkleError> {
let mut hash = root;
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.get(&hash).ok_or(MerkleError::RootNotInStore(hash.into()))?;
self.nodes.get(&hash).ok_or(MerkleError::RootNotInStore(hash))?;
for i in (0..index.depth()).rev() { 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, index))?;
let bit = (index.value() >> i) & 1; let bit = (index.value() >> i) & 1;
hash = if bit == 0 { hash = if bit == 0 {
path.push(node.right.into());
path.push(node.right);
node.left node.left
} else { } else {
path.push(node.left.into());
path.push(node.left);
node.right node.right
} }
} }
@ -180,7 +178,7 @@ impl MerkleStore {
path.reverse(); path.reverse();
Ok(ValuePath { Ok(ValuePath {
value: hash.into(),
value: hash,
path: MerklePath::new(path), path: MerklePath::new(path),
}) })
} }
@ -202,7 +200,7 @@ impl MerkleStore {
/// information, check [NodeIndex::new]. /// information, check [NodeIndex::new].
pub fn get_leaf_depth( pub fn get_leaf_depth(
&self, &self,
root: Word,
root: RpoDigest,
tree_depth: u8, tree_depth: u8,
index: u64, index: u64,
) -> Result<u8, MerkleError> { ) -> Result<u8, MerkleError> {
@ -221,9 +219,9 @@ impl MerkleStore {
// check if the root exists, providing the proper error report if it doesn't // check if the root exists, providing the proper error report if it doesn't
let empty = EmptySubtreeRoots::empty_hashes(tree_depth); let empty = EmptySubtreeRoots::empty_hashes(tree_depth);
let mut hash: RpoDigest = root.into();
let mut hash = root;
if !self.nodes.contains_key(&hash) { if !self.nodes.contains_key(&hash) {
return Err(MerkleError::RootNotInStore(hash.into()));
return Err(MerkleError::RootNotInStore(hash));
} }
// we traverse from root to leaf, so the path is reversed // we traverse from root to leaf, so the path is reversed
@ -266,11 +264,11 @@ impl MerkleStore {
pub fn subset<I, R>(&self, roots: I) -> MerkleStore pub fn subset<I, R>(&self, roots: I) -> MerkleStore
where where
I: Iterator<Item = R>, I: Iterator<Item = R>,
R: Borrow<Word>,
R: Borrow<RpoDigest>,
{ {
let mut store = MerkleStore::new(); let mut store = MerkleStore::new();
for root in roots { for root in roots {
let root = RpoDigest::from(*root.borrow());
let root = *root.borrow();
store.clone_tree_from(root, self); store.clone_tree_from(root, self);
} }
store store
@ -279,9 +277,9 @@ impl MerkleStore {
/// Iterator over the inner nodes of the [MerkleStore]. /// Iterator over the inner nodes of the [MerkleStore].
pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ { pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
self.nodes.iter().map(|(r, n)| InnerNodeInfo { self.nodes.iter().map(|(r, n)| InnerNodeInfo {
value: r.into(),
left: n.left.into(),
right: n.right.into(),
value: *r,
left: n.left,
right: n.right,
}) })
} }
@ -294,9 +292,9 @@ impl MerkleStore {
I: Iterator<Item = InnerNodeInfo>, I: Iterator<Item = InnerNodeInfo>,
{ {
for node in iter { for node in iter {
let value: RpoDigest = node.value.into();
let left: RpoDigest = node.left.into();
let right: RpoDigest = node.right.into();
let value: RpoDigest = node.value;
let left: RpoDigest = node.left;
let right: RpoDigest = node.right;
debug_assert_eq!(Rpo256::merge(&[left, right]), value); debug_assert_eq!(Rpo256::merge(&[left, right]), value);
self.nodes.insert(value, Node { left, right }); self.nodes.insert(value, Node { left, right });
@ -313,13 +311,13 @@ impl MerkleStore {
pub fn add_merkle_path( pub fn add_merkle_path(
&mut self, &mut self,
index: u64, index: u64,
node: Word,
node: RpoDigest,
path: MerklePath, path: MerklePath,
) -> Result<Word, MerkleError> {
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();
) -> Result<RpoDigest, MerkleError> {
let root = path.inner_nodes(index, node)?.fold(RpoDigest::default(), |_, node| {
let value: RpoDigest = node.value;
let left: RpoDigest = node.left;
let right: RpoDigest = node.right;
debug_assert_eq!(Rpo256::merge(&[left, right]), value); debug_assert_eq!(Rpo256::merge(&[left, right]), value);
self.nodes.insert(value, Node { left, right }); self.nodes.insert(value, Node { left, right });
@ -337,7 +335,7 @@ impl MerkleStore {
/// For further reference, check [MerkleStore::add_merkle_path]. /// For further reference, check [MerkleStore::add_merkle_path].
pub fn add_merkle_paths<I>(&mut self, paths: I) -> Result<(), MerkleError> pub fn add_merkle_paths<I>(&mut self, paths: I) -> Result<(), MerkleError>
where where
I: IntoIterator<Item = (u64, Word, MerklePath)>,
I: IntoIterator<Item = (u64, RpoDigest, MerklePath)>,
{ {
for (index_value, node, path) in paths.into_iter() { for (index_value, node, path) in paths.into_iter() {
self.add_merkle_path(index_value, node, path)?; self.add_merkle_path(index_value, node, path)?;
@ -348,7 +346,10 @@ impl MerkleStore {
/// Appends the provided [MerklePathSet] into the store. /// Appends the provided [MerklePathSet] into the store.
/// ///
/// For further reference, check [MerkleStore::add_merkle_path]. /// For further reference, check [MerkleStore::add_merkle_path].
pub fn add_merkle_path_set(&mut self, path_set: &MerklePathSet) -> Result<Word, MerkleError> {
pub fn add_merkle_path_set(
&mut self,
path_set: &MerklePathSet,
) -> Result<RpoDigest, MerkleError> {
let root = path_set.root(); let root = path_set.root();
for (index, path) in path_set.to_paths() { for (index, path) in path_set.to_paths() {
self.add_merkle_path(index, path.value, path.path)?; self.add_merkle_path(index, path.value, path.path)?;
@ -365,9 +366,9 @@ impl MerkleStore {
/// - `NodeNotInStore` if a node needed to traverse from `root` to `index` is not present in the store. /// - `NodeNotInStore` if a node needed to traverse from `root` to `index` is not present in the store.
pub fn set_node( pub fn set_node(
&mut self, &mut self,
mut root: Word,
mut root: RpoDigest,
index: NodeIndex, index: NodeIndex,
value: Word,
value: RpoDigest,
) -> Result<RootPath, MerkleError> { ) -> Result<RootPath, MerkleError> {
let node = value; let node = value;
let ValuePath { value, path } = self.get_path(root, index)?; let ValuePath { value, path } = self.get_path(root, index)?;
@ -383,14 +384,21 @@ impl MerkleStore {
/// Merges two elements and adds the resulting node into the store. /// Merges two elements and adds the resulting node into the store.
/// ///
/// Merges arbitrary values. They may be leafs, nodes, or a mixture of both. /// 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 left: RpoDigest = root1.into();
let right: RpoDigest = root2.into();
let parent = Rpo256::merge(&[left, right]);
self.nodes.insert(parent, Node { left, right });
Ok(parent.into())
pub fn merge_roots(
&mut self,
left_root: RpoDigest,
right_root: RpoDigest,
) -> Result<RpoDigest, MerkleError> {
let parent = Rpo256::merge(&[left_root, right_root]);
self.nodes.insert(
parent,
Node {
left: left_root,
right: right_root,
},
);
Ok(parent)
} }
// HELPER METHODS // HELPER METHODS
@ -404,7 +412,7 @@ impl MerkleStore {
if let Some(node) = source.nodes.get(&root) { if let Some(node) = source.nodes.get(&root) {
// if the node has already been inserted, no need to process it further as all of its // if the node has already been inserted, no need to process it further as all of its
// descendants should be already cloned from the source store // descendants should be already cloned from the source store
if matches!(self.nodes.insert(root, *node), None) {
if self.nodes.insert(root, *node).is_none() {
self.clone_tree_from(node.left, source); self.clone_tree_from(node.left, source);
self.clone_tree_from(node.right, source); self.clone_tree_from(node.right, source);
} }

+ 59
- 48
src/merkle/store/tests.rs

@ -1,10 +1,10 @@
use super::{ use super::{
super::EMPTY_WORD, Deserializable, EmptySubtreeRoots, MerkleError, MerklePath, MerkleStore,
NodeIndex, RpoDigest, Serializable,
Deserializable, EmptySubtreeRoots, MerkleError, MerklePath, MerkleStore, NodeIndex, RpoDigest,
Serializable,
}; };
use crate::{ use crate::{
hash::rpo::Rpo256, hash::rpo::Rpo256,
merkle::{int_to_node, MerklePathSet, MerkleTree, SimpleSmt},
merkle::{digests_to_words, int_to_leaf, int_to_node, MerklePathSet, MerkleTree, SimpleSmt},
Felt, Word, WORD_SIZE, Felt, Word, WORD_SIZE,
}; };
@ -15,9 +15,9 @@ use std::error::Error;
// ================================================================================================ // ================================================================================================
const KEYS4: [u64; 4] = [0, 1, 2, 3]; const KEYS4: [u64; 4] = [0, 1, 2, 3];
const VALUES4: [Word; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
const VALUES4: [RpoDigest; 4] = [int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
const VALUES8: [Word; 8] = [
const VALUES8: [RpoDigest; 8] = [
int_to_node(1), int_to_node(1),
int_to_node(2), int_to_node(2),
int_to_node(3), int_to_node(3),
@ -33,7 +33,7 @@ const VALUES8: [Word; 8] = [
#[test] #[test]
fn test_root_not_in_store() -> Result<(), MerkleError> { fn test_root_not_in_store() -> Result<(), MerkleError> {
let mtree = MerkleTree::new(VALUES4.to_vec())?;
let mtree = MerkleTree::new(digests_to_words(&VALUES4))?;
let store = MerkleStore::from(&mtree); let store = MerkleStore::from(&mtree);
assert_eq!( assert_eq!(
store.get_node(VALUES4[0], NodeIndex::make(mtree.depth(), 0)), store.get_node(VALUES4[0], NodeIndex::make(mtree.depth(), 0)),
@ -51,7 +51,7 @@ fn test_root_not_in_store() -> Result<(), MerkleError> {
#[test] #[test]
fn test_merkle_tree() -> Result<(), MerkleError> { fn test_merkle_tree() -> Result<(), MerkleError> {
let mtree = MerkleTree::new(VALUES4.to_vec())?;
let mtree = MerkleTree::new(digests_to_words(&VALUES4))?;
let store = MerkleStore::from(&mtree); let store = MerkleStore::from(&mtree);
// STORE LEAVES ARE CORRECT ------------------------------------------------------------------- // STORE LEAVES ARE CORRECT -------------------------------------------------------------------
@ -152,12 +152,12 @@ fn test_merkle_tree() -> Result<(), MerkleError> {
#[test] #[test]
fn test_empty_roots() { fn test_empty_roots() {
let store = MerkleStore::default(); let store = MerkleStore::default();
let mut root = RpoDigest::new(EMPTY_WORD);
let mut root = RpoDigest::default();
for depth in 0..255 { for depth in 0..255 {
root = Rpo256::merge(&[root; 2]); root = Rpo256::merge(&[root; 2]);
assert!( assert!(
store.get_node(root.into(), NodeIndex::make(0, 0)).is_ok(),
store.get_node(root, NodeIndex::make(0, 0)).is_ok(),
"The root of the empty tree of depth {depth} must be registered" "The root of the empty tree of depth {depth} must be registered"
); );
} }
@ -176,13 +176,17 @@ 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!(store_path.value, EMPTY_WORD, "the leaf of an empty tree is always ZERO");
assert_eq!(
store_path.value,
RpoDigest::default(),
"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"
); );
assert_eq!( assert_eq!(
store_path.path.compute_root(depth.into(), EMPTY_WORD).unwrap(),
store_path.path.compute_root(depth.into(), RpoDigest::default()).unwrap(),
smt.root(), smt.root(),
"computed root from the path must match the empty tree root" "computed root from the path must match the empty tree root"
); );
@ -193,7 +197,8 @@ fn test_leaf_paths_for_empty_trees() -> Result<(), MerkleError> {
#[test] #[test]
fn test_get_invalid_node() { fn test_get_invalid_node() {
let mtree = MerkleTree::new(VALUES4.to_vec()).expect("creating a merkle tree must work");
let mtree =
MerkleTree::new(digests_to_words(&VALUES4)).expect("creating a merkle tree must work");
let store = MerkleStore::from(&mtree); let store = MerkleStore::from(&mtree);
let _ = store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3)); let _ = store.get_node(mtree.root(), NodeIndex::make(mtree.depth(), 3));
} }
@ -201,16 +206,16 @@ fn test_get_invalid_node() {
#[test] #[test]
fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> { fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> {
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_leaf(1), int_to_leaf(2)];
let smt = SimpleSmt::with_leaves(1, keys2.into_iter().zip(leaves2.into_iter())).unwrap(); let smt = SimpleSmt::with_leaves(1, keys2.into_iter().zip(leaves2.into_iter())).unwrap();
let store = MerkleStore::from(&smt); 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].into());
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); let idx = NodeIndex::make(1, 1);
assert_eq!(smt.get_node(idx).unwrap(), leaves2[1]);
assert_eq!(smt.get_node(idx).unwrap(), leaves2[1].into());
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(()) Ok(())
@ -218,9 +223,11 @@ fn test_add_sparse_merkle_tree_one_level() -> Result<(), MerkleError> {
#[test] #[test]
fn test_sparse_merkle_tree() -> Result<(), MerkleError> { fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
let smt =
SimpleSmt::with_leaves(SimpleSmt::MAX_DEPTH, KEYS4.into_iter().zip(VALUES4.into_iter()))
.unwrap();
let smt = SimpleSmt::with_leaves(
SimpleSmt::MAX_DEPTH,
KEYS4.into_iter().zip(digests_to_words(&VALUES4).into_iter()),
)
.unwrap();
let store = MerkleStore::from(&smt); let store = MerkleStore::from(&smt);
@ -248,7 +255,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
); );
assert_eq!( assert_eq!(
store.get_node(smt.root(), NodeIndex::make(smt.depth(), 4)), store.get_node(smt.root(), NodeIndex::make(smt.depth(), 4)),
Ok(EMPTY_WORD),
Ok(RpoDigest::default()),
"unmodified node 4 must be ZERO" "unmodified node 4 must be ZERO"
); );
@ -328,7 +335,8 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 4)).unwrap(); let result = store.get_path(smt.root(), NodeIndex::make(smt.depth(), 4)).unwrap();
assert_eq!( assert_eq!(
EMPTY_WORD, result.value,
RpoDigest::default(),
result.value,
"Value for merkle path at index 4 must match leaf value" "Value for merkle path at index 4 must match leaf value"
); );
assert_eq!( assert_eq!(
@ -342,7 +350,7 @@ fn test_sparse_merkle_tree() -> Result<(), MerkleError> {
#[test] #[test]
fn test_add_merkle_paths() -> Result<(), MerkleError> { fn test_add_merkle_paths() -> Result<(), MerkleError> {
let mtree = MerkleTree::new(VALUES4.to_vec())?;
let mtree = MerkleTree::new(digests_to_words(&VALUES4))?;
let i0 = 0; let i0 = 0;
let p0 = mtree.get_path(NodeIndex::make(2, i0)).unwrap(); let p0 = mtree.get_path(NodeIndex::make(2, i0)).unwrap();
@ -477,7 +485,6 @@ fn wont_open_to_different_depth_root() {
for depth in (1..=63).rev() { for depth in (1..=63).rev() {
root = Rpo256::merge(&[root, empty[depth]]); 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 // 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
@ -505,22 +512,22 @@ fn store_path_opens_from_leaf() {
let k = Rpo256::merge(&[e.into(), f.into()]); let k = Rpo256::merge(&[e.into(), f.into()]);
let l = Rpo256::merge(&[g.into(), h.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 m = Rpo256::merge(&[i, j]);
let n = Rpo256::merge(&[k, l]);
let root = Rpo256::merge(&[m.into(), n.into()]);
let root = Rpo256::merge(&[m, n]);
let mtree = MerkleTree::new(vec![a, b, c, d, e, f, g, h]).unwrap(); let mtree = MerkleTree::new(vec![a, b, c, d, e, f, g, h]).unwrap();
let store = MerkleStore::from(&mtree); let store = MerkleStore::from(&mtree);
let path = store.get_path(root.into(), NodeIndex::make(3, 1)).unwrap().path;
let path = store.get_path(root, 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, n].to_vec());
assert_eq!(path, expected); assert_eq!(path, expected);
} }
#[test] #[test]
fn test_set_node() -> Result<(), MerkleError> { fn test_set_node() -> Result<(), MerkleError> {
let mtree = MerkleTree::new(VALUES4.to_vec())?;
let mtree = MerkleTree::new(digests_to_words(&VALUES4))?;
let mut store = MerkleStore::from(&mtree); 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);
@ -532,7 +539,7 @@ fn test_set_node() -> Result<(), MerkleError> {
#[test] #[test]
fn test_constructors() -> Result<(), MerkleError> { fn test_constructors() -> Result<(), MerkleError> {
let mtree = MerkleTree::new(VALUES4.to_vec())?;
let mtree = MerkleTree::new(digests_to_words(&VALUES4))?;
let store = MerkleStore::from(&mtree); let store = MerkleStore::from(&mtree);
let depth = mtree.depth(); let depth = mtree.depth();
@ -544,7 +551,11 @@ fn test_constructors() -> Result<(), MerkleError> {
} }
let depth = 32; let depth = 32;
let smt = SimpleSmt::with_leaves(depth, KEYS4.into_iter().zip(VALUES4.into_iter())).unwrap();
let smt = SimpleSmt::with_leaves(
depth,
KEYS4.into_iter().zip(digests_to_words(&VALUES4).into_iter()),
)
.unwrap();
let store = MerkleStore::from(&smt); let store = MerkleStore::from(&smt);
let depth = smt.depth(); let depth = smt.depth();
@ -590,11 +601,11 @@ fn node_path_should_be_truncated_by_midtier_insert() {
let key = 0b11010010_11001100_11001100_11001100_11001100_11001100_11001100_11001100_u64; let key = 0b11010010_11001100_11001100_11001100_11001100_11001100_11001100_11001100_u64;
let mut store = MerkleStore::new(); let mut store = MerkleStore::new();
let root: Word = EmptySubtreeRoots::empty_hashes(64)[0].into();
let root: RpoDigest = EmptySubtreeRoots::empty_hashes(64)[0];
// insert first node - works as expected // insert first node - works as expected
let depth = 64; let depth = 64;
let node = [Felt::new(key); WORD_SIZE];
let node = RpoDigest::from([Felt::new(key); WORD_SIZE]);
let index = NodeIndex::new(depth, key).unwrap(); let index = NodeIndex::new(depth, key).unwrap();
let root = store.set_node(root, index, node).unwrap().root; let root = store.set_node(root, index, node).unwrap().root;
let result = store.get_node(root, index).unwrap(); let result = store.get_node(root, index).unwrap();
@ -607,7 +618,7 @@ fn node_path_should_be_truncated_by_midtier_insert() {
let key = key ^ (1 << 63); let key = key ^ (1 << 63);
let key = key >> 8; let key = key >> 8;
let depth = 56; let depth = 56;
let node = [Felt::new(key); WORD_SIZE];
let node = RpoDigest::from([Felt::new(key); WORD_SIZE]);
let index = NodeIndex::new(depth, key).unwrap(); let index = NodeIndex::new(depth, key).unwrap();
let root = store.set_node(root, index, node).unwrap().root; let root = store.set_node(root, index, node).unwrap().root;
let result = store.get_node(root, index).unwrap(); let result = store.get_node(root, index).unwrap();
@ -626,13 +637,13 @@ fn node_path_should_be_truncated_by_midtier_insert() {
#[test] #[test]
fn get_leaf_depth_works_depth_64() { fn get_leaf_depth_works_depth_64() {
let mut store = MerkleStore::new(); let mut store = MerkleStore::new();
let mut root: Word = EmptySubtreeRoots::empty_hashes(64)[0].into();
let mut root: RpoDigest = EmptySubtreeRoots::empty_hashes(64)[0];
let key = u64::MAX; let key = u64::MAX;
// this will create a rainbow tree and test all opening to depth 64 // this will create a rainbow tree and test all opening to depth 64
for d in 0..64 { for d in 0..64 {
let k = key & (u64::MAX >> d); let k = key & (u64::MAX >> d);
let node = [Felt::new(k); WORD_SIZE];
let node = RpoDigest::from([Felt::new(k); WORD_SIZE]);
let index = NodeIndex::new(64, k).unwrap(); let index = NodeIndex::new(64, k).unwrap();
// assert the leaf doesn't exist before the insert. the returned depth should always // assert the leaf doesn't exist before the insert. the returned depth should always
@ -649,14 +660,14 @@ fn get_leaf_depth_works_depth_64() {
#[test] #[test]
fn get_leaf_depth_works_with_incremental_depth() { fn get_leaf_depth_works_with_incremental_depth() {
let mut store = MerkleStore::new(); let mut store = MerkleStore::new();
let mut root: Word = EmptySubtreeRoots::empty_hashes(64)[0].into();
let mut root: RpoDigest = EmptySubtreeRoots::empty_hashes(64)[0];
// insert some path to the left of the root and assert it // insert some path to the left of the root and assert it
let key = 0b01001011_10110110_00001101_01110100_00111011_10101101_00000100_01000001_u64; let key = 0b01001011_10110110_00001101_01110100_00111011_10101101_00000100_01000001_u64;
assert_eq!(0, store.get_leaf_depth(root, 64, key).unwrap()); assert_eq!(0, store.get_leaf_depth(root, 64, key).unwrap());
let depth = 64; let depth = 64;
let index = NodeIndex::new(depth, key).unwrap(); let index = NodeIndex::new(depth, key).unwrap();
let node = [Felt::new(key); WORD_SIZE];
let node = RpoDigest::from([Felt::new(key); WORD_SIZE]);
root = store.set_node(root, index, node).unwrap().root; root = store.set_node(root, index, node).unwrap().root;
assert_eq!(depth, store.get_leaf_depth(root, 64, key).unwrap()); assert_eq!(depth, store.get_leaf_depth(root, 64, key).unwrap());
@ -665,7 +676,7 @@ fn get_leaf_depth_works_with_incremental_depth() {
assert_eq!(1, store.get_leaf_depth(root, 64, key).unwrap()); assert_eq!(1, store.get_leaf_depth(root, 64, key).unwrap());
let depth = 16; let depth = 16;
let index = NodeIndex::new(depth, key >> (64 - depth)).unwrap(); let index = NodeIndex::new(depth, key >> (64 - depth)).unwrap();
let node = [Felt::new(key); WORD_SIZE];
let node = RpoDigest::from([Felt::new(key); WORD_SIZE]);
root = store.set_node(root, index, node).unwrap().root; root = store.set_node(root, index, node).unwrap().root;
assert_eq!(depth, store.get_leaf_depth(root, 64, key).unwrap()); assert_eq!(depth, store.get_leaf_depth(root, 64, key).unwrap());
@ -673,7 +684,7 @@ fn get_leaf_depth_works_with_incremental_depth() {
let key = 0b11001011_10110111_00000000_00000000_00000000_00000000_00000000_00000000_u64; let key = 0b11001011_10110111_00000000_00000000_00000000_00000000_00000000_00000000_u64;
assert_eq!(16, store.get_leaf_depth(root, 64, key).unwrap()); assert_eq!(16, store.get_leaf_depth(root, 64, key).unwrap());
let index = NodeIndex::new(depth, key >> (64 - depth)).unwrap(); let index = NodeIndex::new(depth, key >> (64 - depth)).unwrap();
let node = [Felt::new(key); WORD_SIZE];
let node = RpoDigest::from([Felt::new(key); WORD_SIZE]);
root = store.set_node(root, index, node).unwrap().root; root = store.set_node(root, index, node).unwrap().root;
assert_eq!(depth, store.get_leaf_depth(root, 64, key).unwrap()); assert_eq!(depth, store.get_leaf_depth(root, 64, key).unwrap());
@ -682,7 +693,7 @@ fn get_leaf_depth_works_with_incremental_depth() {
assert_eq!(15, store.get_leaf_depth(root, 64, key).unwrap()); assert_eq!(15, store.get_leaf_depth(root, 64, key).unwrap());
let depth = 17; let depth = 17;
let index = NodeIndex::new(depth, key >> (64 - depth)).unwrap(); let index = NodeIndex::new(depth, key >> (64 - depth)).unwrap();
let node = [Felt::new(key); WORD_SIZE];
let node = RpoDigest::from([Felt::new(key); WORD_SIZE]);
root = store.set_node(root, index, node).unwrap().root; root = store.set_node(root, index, node).unwrap().root;
assert_eq!(depth, store.get_leaf_depth(root, 64, key).unwrap()); assert_eq!(depth, store.get_leaf_depth(root, 64, key).unwrap());
} }
@ -690,7 +701,7 @@ fn get_leaf_depth_works_with_incremental_depth() {
#[test] #[test]
fn get_leaf_depth_works_with_depth_8() { fn get_leaf_depth_works_with_depth_8() {
let mut store = MerkleStore::new(); let mut store = MerkleStore::new();
let mut root: Word = EmptySubtreeRoots::empty_hashes(8)[0].into();
let mut root: RpoDigest = EmptySubtreeRoots::empty_hashes(8)[0];
// insert some random, 8 depth keys. `a` diverges from the first bit // insert some random, 8 depth keys. `a` diverges from the first bit
let a = 0b01101001_u64; let a = 0b01101001_u64;
@ -700,7 +711,7 @@ fn get_leaf_depth_works_with_depth_8() {
for k in [a, b, c, d] { for k in [a, b, c, d] {
let index = NodeIndex::new(8, k).unwrap(); let index = NodeIndex::new(8, k).unwrap();
let node = [Felt::new(k); WORD_SIZE];
let node = RpoDigest::from([Felt::new(k); WORD_SIZE]);
root = store.set_node(root, index, node).unwrap().root; root = store.set_node(root, index, node).unwrap().root;
} }
@ -739,16 +750,16 @@ fn get_leaf_depth_works_with_depth_8() {
#[test] #[test]
fn mstore_subset() { fn mstore_subset() {
// add a Merkle tree of depth 3 to the store // add a Merkle tree of depth 3 to the store
let mtree = MerkleTree::new(VALUES8.to_vec()).unwrap();
let mtree = MerkleTree::new(digests_to_words(&VALUES8)).unwrap();
let mut store = MerkleStore::default(); let mut store = MerkleStore::default();
let empty_store_num_nodes = store.nodes.len(); let empty_store_num_nodes = store.nodes.len();
store.extend(mtree.inner_nodes()); store.extend(mtree.inner_nodes());
// build 3 subtrees contained within the above Merkle tree; note that subtree2 is a subset // build 3 subtrees contained within the above Merkle tree; note that subtree2 is a subset
// of subtree1 // of subtree1
let subtree1 = MerkleTree::new(VALUES8[..4].to_vec()).unwrap();
let subtree2 = MerkleTree::new(VALUES8[2..4].to_vec()).unwrap();
let subtree3 = MerkleTree::new(VALUES8[6..].to_vec()).unwrap();
let subtree1 = MerkleTree::new(digests_to_words(&VALUES8[..4])).unwrap();
let subtree2 = MerkleTree::new(digests_to_words(&VALUES8[2..4])).unwrap();
let subtree3 = MerkleTree::new(digests_to_words(&VALUES8[6..])).unwrap();
// --- extract all 3 subtrees --------------------------------------------- // --- extract all 3 subtrees ---------------------------------------------
@ -780,7 +791,7 @@ fn check_mstore_subtree(store: &MerkleStore, subtree: &MerkleTree) {
for (i, value) in subtree.leaves() { for (i, value) in subtree.leaves() {
let index = NodeIndex::new(subtree.depth(), i).unwrap(); let index = NodeIndex::new(subtree.depth(), i).unwrap();
let path1 = store.get_path(subtree.root(), index).unwrap(); let path1 = store.get_path(subtree.root(), index).unwrap();
assert_eq!(&path1.value, value);
assert_eq!(*path1.value, *value);
let path2 = subtree.get_path(index).unwrap(); let path2 = subtree.get_path(index).unwrap();
assert_eq!(path1.path, path2); assert_eq!(path1.path, path2);
@ -793,7 +804,7 @@ fn check_mstore_subtree(store: &MerkleStore, subtree: &MerkleTree) {
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[test] #[test]
fn test_serialization() -> Result<(), Box<dyn Error>> { fn test_serialization() -> Result<(), Box<dyn Error>> {
let mtree = MerkleTree::new(VALUES4.to_vec())?;
let mtree = MerkleTree::new(digests_to_words(&VALUES4))?;
let store = MerkleStore::from(&mtree); let store = MerkleStore::from(&mtree);
let decoded = MerkleStore::read_from_bytes(&store.to_bytes()).expect("deserialization failed"); let decoded = MerkleStore::read_from_bytes(&store.to_bytes()).expect("deserialization failed");
assert_eq!(store, decoded); assert_eq!(store, decoded);

+ 7
- 7
src/merkle/tiered_smt/mod.rs

@ -1,6 +1,6 @@
use super::{ use super::{
BTreeMap, BTreeSet, EmptySubtreeRoots, Felt, InnerNodeInfo, MerkleError, MerklePath, NodeIndex,
Rpo256, RpoDigest, StarkField, Vec, Word, EMPTY_WORD, ZERO,
empty_roots::EMPTY_WORD, BTreeMap, BTreeSet, EmptySubtreeRoots, Felt, InnerNodeInfo,
MerkleError, MerklePath, NodeIndex, Rpo256, RpoDigest, StarkField, Vec, Word, ZERO,
}; };
use core::cmp; use core::cmp;
@ -123,7 +123,7 @@ impl TieredSmt {
let mut path = Vec::with_capacity(index.depth() as usize); let mut path = Vec::with_capacity(index.depth() as usize);
for _ in 0..index.depth() { for _ in 0..index.depth() {
let node = self.get_node_unchecked(&index.sibling()); let node = self.get_node_unchecked(&index.sibling());
path.push(node.into());
path.push(node);
index.move_up(); index.move_up();
} }
@ -200,9 +200,9 @@ impl TieredSmt {
self.nodes.iter().filter_map(|(index, node)| { self.nodes.iter().filter_map(|(index, node)| {
if is_inner_node(index) { if is_inner_node(index) {
Some(InnerNodeInfo { Some(InnerNodeInfo {
value: node.into(),
left: self.get_node_unchecked(&index.left_child()).into(),
right: self.get_node_unchecked(&index.right_child()).into(),
value: *node,
left: self.get_node_unchecked(&index.left_child()),
right: self.get_node_unchecked(&index.right_child()),
}) })
} else { } else {
None None
@ -456,7 +456,7 @@ impl BottomLeaf {
let mut elements = Vec::with_capacity(self.values.len() * 2); let mut elements = Vec::with_capacity(self.values.len() * 2);
for (key, val) in self.values.iter() { for (key, val) in self.values.iter() {
key.iter().for_each(|&v| elements.push(Felt::new(v))); key.iter().for_each(|&v| elements.push(Felt::new(v)));
elements.extend_from_slice(val);
elements.extend_from_slice(val.as_slice());
} }
// TODO: hash in domain // TODO: hash in domain
Rpo256::hash_elements(&elements) Rpo256::hash_elements(&elements)

+ 22
- 22
src/merkle/tiered_smt/tests.rs

@ -17,11 +17,11 @@ fn tsmt_insert_one() {
// 16 most significant bits of the key // 16 most significant bits of the key
let index = NodeIndex::make(16, raw >> 48); let index = NodeIndex::make(16, raw >> 48);
let leaf_node = build_leaf_node(key, value, 16); let leaf_node = build_leaf_node(key, value, 16);
let tree_root = store.set_node(smt.root().into(), index, leaf_node.into()).unwrap().root;
let tree_root = store.set_node(smt.root(), index, leaf_node).unwrap().root;
smt.insert(key, value); smt.insert(key, value);
assert_eq!(smt.root(), tree_root.into());
assert_eq!(smt.root(), tree_root);
// make sure the value was inserted, and the node is at the expected index // make sure the value was inserted, and the node is at the expected index
assert_eq!(smt.get_value(key), value); assert_eq!(smt.get_value(key), value);
@ -66,15 +66,15 @@ fn tsmt_insert_two_16() {
let mut tree_root = get_init_root(); let mut tree_root = get_init_root();
let index_a = NodeIndex::make(32, raw_a >> 32); let index_a = NodeIndex::make(32, raw_a >> 32);
let leaf_node_a = build_leaf_node(key_a, val_a, 32); let leaf_node_a = build_leaf_node(key_a, val_a, 32);
tree_root = store.set_node(tree_root, index_a, leaf_node_a.into()).unwrap().root;
tree_root = store.set_node(tree_root, index_a, leaf_node_a).unwrap().root;
let index_b = NodeIndex::make(32, raw_b >> 32); let index_b = NodeIndex::make(32, raw_b >> 32);
let leaf_node_b = build_leaf_node(key_b, val_b, 32); let leaf_node_b = build_leaf_node(key_b, val_b, 32);
tree_root = store.set_node(tree_root, index_b, leaf_node_b.into()).unwrap().root;
tree_root = store.set_node(tree_root, index_b, leaf_node_b).unwrap().root;
// --- verify that data is consistent between store and tree -------------- // --- verify that data is consistent between store and tree --------------
assert_eq!(smt.root(), tree_root.into());
assert_eq!(smt.root(), tree_root);
assert_eq!(smt.get_value(key_a), val_a); assert_eq!(smt.get_value(key_a), val_a);
assert_eq!(smt.get_node(index_a).unwrap(), leaf_node_a); assert_eq!(smt.get_node(index_a).unwrap(), leaf_node_a);
@ -122,15 +122,15 @@ fn tsmt_insert_two_32() {
let mut tree_root = get_init_root(); let mut tree_root = get_init_root();
let index_a = NodeIndex::make(48, raw_a >> 16); let index_a = NodeIndex::make(48, raw_a >> 16);
let leaf_node_a = build_leaf_node(key_a, val_a, 48); let leaf_node_a = build_leaf_node(key_a, val_a, 48);
tree_root = store.set_node(tree_root, index_a, leaf_node_a.into()).unwrap().root;
tree_root = store.set_node(tree_root, index_a, leaf_node_a).unwrap().root;
let index_b = NodeIndex::make(48, raw_b >> 16); let index_b = NodeIndex::make(48, raw_b >> 16);
let leaf_node_b = build_leaf_node(key_b, val_b, 48); let leaf_node_b = build_leaf_node(key_b, val_b, 48);
tree_root = store.set_node(tree_root, index_b, leaf_node_b.into()).unwrap().root;
tree_root = store.set_node(tree_root, index_b, leaf_node_b).unwrap().root;
// --- verify that data is consistent between store and tree -------------- // --- verify that data is consistent between store and tree --------------
assert_eq!(smt.root(), tree_root.into());
assert_eq!(smt.root(), tree_root);
assert_eq!(smt.get_value(key_a), val_a); assert_eq!(smt.get_value(key_a), val_a);
assert_eq!(smt.get_node(index_a).unwrap(), leaf_node_a); assert_eq!(smt.get_node(index_a).unwrap(), leaf_node_a);
@ -181,19 +181,19 @@ fn tsmt_insert_three() {
let mut tree_root = get_init_root(); let mut tree_root = get_init_root();
let index_a = NodeIndex::make(32, raw_a >> 32); let index_a = NodeIndex::make(32, raw_a >> 32);
let leaf_node_a = build_leaf_node(key_a, val_a, 32); let leaf_node_a = build_leaf_node(key_a, val_a, 32);
tree_root = store.set_node(tree_root, index_a, leaf_node_a.into()).unwrap().root;
tree_root = store.set_node(tree_root, index_a, leaf_node_a).unwrap().root;
let index_b = NodeIndex::make(32, raw_b >> 32); let index_b = NodeIndex::make(32, raw_b >> 32);
let leaf_node_b = build_leaf_node(key_b, val_b, 32); let leaf_node_b = build_leaf_node(key_b, val_b, 32);
tree_root = store.set_node(tree_root, index_b, leaf_node_b.into()).unwrap().root;
tree_root = store.set_node(tree_root, index_b, leaf_node_b).unwrap().root;
let index_c = NodeIndex::make(32, raw_c >> 32); let index_c = NodeIndex::make(32, raw_c >> 32);
let leaf_node_c = build_leaf_node(key_c, val_c, 32); let leaf_node_c = build_leaf_node(key_c, val_c, 32);
tree_root = store.set_node(tree_root, index_c, leaf_node_c.into()).unwrap().root;
tree_root = store.set_node(tree_root, index_c, leaf_node_c).unwrap().root;
// --- verify that data is consistent between store and tree -------------- // --- verify that data is consistent between store and tree --------------
assert_eq!(smt.root(), tree_root.into());
assert_eq!(smt.root(), tree_root);
assert_eq!(smt.get_value(key_a), val_a); assert_eq!(smt.get_value(key_a), val_a);
assert_eq!(smt.get_node(index_a).unwrap(), leaf_node_a); assert_eq!(smt.get_node(index_a).unwrap(), leaf_node_a);
@ -236,9 +236,9 @@ fn tsmt_update() {
let mut tree_root = get_init_root(); let mut tree_root = get_init_root();
let index = NodeIndex::make(16, raw >> 48); let index = NodeIndex::make(16, raw >> 48);
let leaf_node = build_leaf_node(key, value_b, 16); let leaf_node = build_leaf_node(key, value_b, 16);
tree_root = store.set_node(tree_root, index, leaf_node.into()).unwrap().root;
tree_root = store.set_node(tree_root, index, leaf_node).unwrap().root;
assert_eq!(smt.root(), tree_root.into());
assert_eq!(smt.root(), tree_root);
assert_eq!(smt.get_value(key), value_b); assert_eq!(smt.get_value(key), value_b);
assert_eq!(smt.get_node(index).unwrap(), leaf_node); assert_eq!(smt.get_node(index).unwrap(), leaf_node);
@ -281,11 +281,11 @@ fn tsmt_bottom_tier() {
// key_b is smaller than key_a. // key_b is smaller than key_a.
let leaf_node = build_bottom_leaf_node(&[key_b, key_a], &[val_b, val_a]); let leaf_node = build_bottom_leaf_node(&[key_b, key_a], &[val_b, val_a]);
let mut tree_root = get_init_root(); let mut tree_root = get_init_root();
tree_root = store.set_node(tree_root, index, leaf_node.into()).unwrap().root;
tree_root = store.set_node(tree_root, index, leaf_node).unwrap().root;
// --- verify that data is consistent between store and tree -------------- // --- verify that data is consistent between store and tree --------------
assert_eq!(smt.root(), tree_root.into());
assert_eq!(smt.root(), tree_root);
assert_eq!(smt.get_value(key_a), val_a); assert_eq!(smt.get_value(key_a), val_a);
assert_eq!(smt.get_value(key_b), val_b); assert_eq!(smt.get_value(key_b), val_b);
@ -329,15 +329,15 @@ fn tsmt_bottom_tier_two() {
let mut tree_root = get_init_root(); let mut tree_root = get_init_root();
let index_a = NodeIndex::make(64, raw_a); let index_a = NodeIndex::make(64, raw_a);
let leaf_node_a = build_bottom_leaf_node(&[key_a], &[val_a]); let leaf_node_a = build_bottom_leaf_node(&[key_a], &[val_a]);
tree_root = store.set_node(tree_root, index_a, leaf_node_a.into()).unwrap().root;
tree_root = store.set_node(tree_root, index_a, leaf_node_a).unwrap().root;
let index_b = NodeIndex::make(64, raw_b); let index_b = NodeIndex::make(64, raw_b);
let leaf_node_b = build_bottom_leaf_node(&[key_b], &[val_b]); let leaf_node_b = build_bottom_leaf_node(&[key_b], &[val_b]);
tree_root = store.set_node(tree_root, index_b, leaf_node_b.into()).unwrap().root;
tree_root = store.set_node(tree_root, index_b, leaf_node_b).unwrap().root;
// --- verify that data is consistent between store and tree -------------- // --- verify that data is consistent between store and tree --------------
assert_eq!(smt.root(), tree_root.into());
assert_eq!(smt.root(), tree_root);
assert_eq!(smt.get_value(key_a), val_a); assert_eq!(smt.get_value(key_a), val_a);
assert_eq!(smt.get_node(index_a).unwrap(), leaf_node_a); assert_eq!(smt.get_node(index_a).unwrap(), leaf_node_a);
@ -406,8 +406,8 @@ fn tsmt_node_not_available() {
// HELPER FUNCTIONS // HELPER FUNCTIONS
// ================================================================================================ // ================================================================================================
fn get_init_root() -> Word {
EmptySubtreeRoots::empty_hashes(64)[0].into()
fn get_init_root() -> RpoDigest {
EmptySubtreeRoots::empty_hashes(64)[0]
} }
fn build_leaf_node(key: RpoDigest, value: Word, depth: u8) -> RpoDigest { fn build_leaf_node(key: RpoDigest, value: Word, depth: u8) -> RpoDigest {
@ -423,7 +423,7 @@ fn build_bottom_leaf_node(keys: &[RpoDigest], values: &[Word]) -> RpoDigest {
let mut key = Word::from(key); let mut key = Word::from(key);
key[3] = ZERO; key[3] = ZERO;
elements.extend_from_slice(&key); elements.extend_from_slice(&key);
elements.extend_from_slice(val);
elements.extend_from_slice(val.as_slice());
} }
Rpo256::hash_elements(&elements) Rpo256::hash_elements(&elements)

Loading…
Cancel
Save