Updated Makefile and Readme

This commit is contained in:
Paul-Henry Kajfasz
2024-08-16 15:07:27 -07:00
parent d92fae7f82
commit ad0f472708
50 changed files with 416 additions and 278 deletions

View File

@@ -33,22 +33,22 @@ impl fmt::Display for MerkleError {
DuplicateValuesForKey(key) => write!(f, "multiple values provided for key {key}"),
InvalidIndex { depth, value } => {
write!(f, "the index value {value} is not valid for the depth {depth}")
}
},
InvalidDepth { expected, provided } => {
write!(f, "the provided depth {provided} is not valid for {expected}")
}
},
InvalidSubtreeDepth { subtree_depth, tree_depth } => {
write!(f, "tried inserting a subtree of depth {subtree_depth} into a tree of depth {tree_depth}")
}
},
InvalidPath(_path) => write!(f, "the provided path is not valid"),
InvalidNumEntries(max) => write!(f, "number of entries exceeded the maximum: {max}"),
NodeNotInSet(index) => write!(f, "the node with index ({index}) is not in the set"),
NodeNotInStore(hash, index) => {
write!(f, "the node {hash:?} with index ({index}) is not in the store")
}
},
NumLeavesNotPowerOfTwo(leaves) => {
write!(f, "the leaves count {leaves} is not a power of 2")
}
},
RootNotInStore(root) => write!(f, "the root {:?} is not in the store", root),
SmtLeaf(smt_leaf_error) => write!(f, "smt leaf error: {smt_leaf_error}"),
}

View File

@@ -1,6 +1,7 @@
use super::super::RpoDigest;
use alloc::vec::Vec;
use super::super::RpoDigest;
/// Container for the update data of a [super::PartialMmr]
#[derive(Debug)]
pub struct MmrDelta {

View File

@@ -21,11 +21,11 @@ impl Display for MmrError {
MmrError::InvalidPeaks => write!(fmt, "Invalid peaks count"),
MmrError::InvalidPeak => {
write!(fmt, "Peak values does not match merkle path computed root")
}
},
MmrError::InvalidUpdate => write!(fmt, "Invalid mmr update"),
MmrError::UnknownPeak => {
write!(fmt, "Peak not in Mmr")
}
},
MmrError::MerkleError(err) => write!(fmt, "{}", err),
}
}

View File

@@ -10,13 +10,14 @@
//! 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
//! reestablished.
use alloc::vec::Vec;
use super::{
super::{InnerNodeInfo, MerklePath},
bit::TrueBitPositionIterator,
leaf_to_corresponding_tree, nodes_in_forest, MmrDelta, MmrError, MmrPeaks, MmrProof, Rpo256,
RpoDigest,
};
use alloc::vec::Vec;
// MMR
// ===============================================================================================
@@ -377,7 +378,8 @@ impl<'a> Iterator for MmrNodes<'a> {
// the next parent position is one above the position of the pair
let parent = self.last_right << 1;
// the left node has been paired and the current parent yielded, removed it from the forest
// the left node has been paired and the current parent yielded, removed it from the
// forest
self.forest ^= self.last_right;
if self.forest & parent == 0 {
// this iteration yielded the left parent node

View File

@@ -10,8 +10,6 @@ mod proof;
#[cfg(test)]
mod tests;
use super::{Felt, Rpo256, RpoDigest, Word};
// REEXPORTS
// ================================================================================================
pub use delta::MmrDelta;
@@ -22,6 +20,8 @@ pub use partial::PartialMmr;
pub use peaks::MmrPeaks;
pub use proof::MmrProof;
use super::{Felt, Rpo256, RpoDigest, Word};
// UTILITIES
// ===============================================================================================
@@ -42,8 +42,8 @@ const fn leaf_to_corresponding_tree(pos: usize, forest: usize) -> Option<u32> {
// - this means the first tree owns from `0` up to the `2^k_0` first positions, where `k_0`
// is the highest true bit position, the second tree from `2^k_0 + 1` up to `2^k_1` where
// `k_1` is the second highest bit, so on.
// - this means the highest bits work as a category marker, and the position is owned by
// the first tree which doesn't share a high bit with the position
// - this means the highest bits work as a category marker, and the position is owned by the
// first tree which doesn't share a high bit with the position
let before = forest & pos;
let after = forest ^ before;
let tree = after.ilog2();

View File

@@ -1,12 +1,13 @@
use alloc::{
collections::{BTreeMap, BTreeSet},
vec::Vec,
};
use super::{MmrDelta, MmrProof, Rpo256, RpoDigest};
use crate::merkle::{
mmr::{leaf_to_corresponding_tree, nodes_in_forest},
InOrderIndex, InnerNodeInfo, MerklePath, MmrError, MmrPeaks,
};
use alloc::{
collections::{BTreeMap, BTreeSet},
vec::Vec,
};
// TYPE ALIASES
// ================================================================================================
@@ -613,12 +614,13 @@ fn forest_to_rightmost_index(forest: usize) -> InOrderIndex {
#[cfg(test)]
mod tests {
use alloc::{collections::BTreeSet, vec::Vec};
use super::{
forest_to_rightmost_index, forest_to_root_index, InOrderIndex, MmrPeaks, PartialMmr,
RpoDigest,
};
use crate::merkle::{int_to_node, MerkleStore, Mmr, NodeIndex};
use alloc::{collections::BTreeSet, vec::Vec};
const LEAVES: [RpoDigest; 7] = [
int_to_node(0),

View File

@@ -1,6 +1,7 @@
use super::{super::ZERO, Felt, MmrError, MmrProof, Rpo256, RpoDigest, Word};
use alloc::vec::Vec;
use super::{super::ZERO, Felt, MmrError, MmrProof, Rpo256, RpoDigest, Word};
// MMR PEAKS
// ================================================================================================
@@ -18,12 +19,12 @@ pub struct MmrPeaks {
///
/// Examples:
///
/// - With 5 leaves, the binary `0b101`. The number of set bits is equal the number
/// of peaks, in this case there are 2 peaks. The 0-indexed least-significant position of
/// the bit determines the number of elements of a tree, so the rightmost tree has `2**0`
/// - With 5 leaves, the binary `0b101`. The number of set bits is equal the number of
/// peaks, in this case there are 2 peaks. The 0-indexed least-significant position of the
/// bit determines the number of elements of a tree, so the rightmost tree has `2**0`
/// elements and the left most has `2**2`.
/// - With 12 leaves, the binary is `0b1100`, this case also has 2 peaks, the
/// leftmost tree has `2**3=8` elements, and the right most has `2**2=4` elements.
/// - With 12 leaves, the binary is `0b1100`, this case also has 2 peaks, the leftmost tree
/// has `2**3=8` elements, and the right most has `2**2=4` elements.
num_leaves: usize,
/// All the peaks of every tree in the MMR forest. The peaks are always ordered by number of
@@ -94,16 +95,15 @@ impl MmrPeaks {
/// - Flatten the vector of Words into a vector of Felts.
/// - Pad the peaks with ZERO to an even number of words, this removes the need to handle RPO
/// padding.
/// - Pad the peaks to a minimum length of 16 words, which reduces the constant cost of
/// hashing.
/// - Pad the peaks to a minimum length of 16 words, which reduces the constant cost of hashing.
pub fn flatten_and_pad_peaks(&self) -> Vec<Felt> {
let num_peaks = self.peaks.len();
// To achieve the padding rules above we calculate the length of the final vector.
// This is calculated as the number of field elements. Each peak is 4 field elements.
// The length is calculated as follows:
// - If there are less than 16 peaks, the data is padded to 16 peaks and as such requires
// 64 field elements.
// - If there are less than 16 peaks, the data is padded to 16 peaks and as such requires 64
// field elements.
// - If there are more than 16 peaks and the number of peaks is odd, the data is padded to
// an even number of peaks and as such requires `(num_peaks + 1) * 4` field elements.
// - If there are more than 16 peaks and the number of peaks is even, the data is not padded

View File

@@ -1,3 +1,5 @@
use alloc::vec::Vec;
use super::{
super::{InnerNodeInfo, Rpo256, RpoDigest},
bit::TrueBitPositionIterator,
@@ -8,7 +10,6 @@ use crate::{
merkle::{int_to_node, InOrderIndex, MerklePath, MerkleTree, MmrProof, NodeIndex},
Felt, Word,
};
use alloc::vec::Vec;
#[test]
fn test_position_equal_or_higher_than_leafs_is_never_contained() {

View File

@@ -1,3 +1,5 @@
use alloc::{collections::BTreeMap, vec::Vec};
use super::{
super::{
digests_to_words, int_to_node, DefaultMerkleStore as MerkleStore, MerkleTree, NodeIndex,
@@ -5,7 +7,6 @@ use super::{
},
Deserializable, InnerNodeInfo, RpoDigest, Serializable, ValuePath,
};
use alloc::{collections::BTreeMap, vec::Vec};
// TEST DATA
// ================================================================================================
@@ -294,7 +295,8 @@ fn leaves() {
assert!(expected_leaves.eq(pmt.leaves()));
}
/// Checks that nodes of the PMT returned by `inner_nodes()` function are equal to the expected ones.
/// Checks that nodes of the PMT returned by `inner_nodes()` function are equal to the expected
/// ones.
#[test]
fn test_inner_node_iterator() {
let mt = MerkleTree::new(digests_to_words(&VALUES8)).unwrap();

View File

@@ -37,17 +37,17 @@ impl fmt::Display for SmtLeafError {
match self {
InvalidNumEntriesForMultiple(num_entries) => {
write!(f, "Multiple leaf requires 2 or more entries. Got: {num_entries}")
}
},
InconsistentKeys { entries, key_1, key_2 } => {
write!(f, "Multiple leaf requires all keys to map to the same leaf index. Offending keys: {key_1} and {key_2}. Entries: {entries:?}.")
}
},
SingleKeyInconsistentWithLeafIndex { key, leaf_index } => {
write!(
f,
"Single key in leaf inconsistent with leaf index. Key: {key}, leaf index: {}",
leaf_index.value()
)
}
},
MultipleKeysInconsistentWithLeafIndex {
leaf_index_from_keys,
leaf_index_supplied,
@@ -58,7 +58,7 @@ impl fmt::Display for SmtLeafError {
leaf_index_from_keys.value(),
leaf_index_supplied.value()
)
}
},
}
}
}
@@ -80,7 +80,7 @@ impl fmt::Display for SmtProofError {
match self {
InvalidPathLength(path_length) => {
write!(f, "Invalid Merkle path length. Expected {SMT_DEPTH}, got {path_length}")
}
},
}
}
}

View File

@@ -20,8 +20,8 @@ impl SmtLeaf {
///
/// # Errors
/// - Returns an error if 2 keys in `entries` map to a different leaf index
/// - Returns an error if 1 or more keys in `entries` map to a leaf index
/// different from `leaf_index`
/// - Returns an error if 1 or more keys in `entries` map to a leaf index different from
/// `leaf_index`
pub fn new(
entries: Vec<(RpoDigest, Word)>,
leaf_index: LeafIndex<SMT_DEPTH>,
@@ -39,7 +39,7 @@ impl SmtLeaf {
}
Ok(Self::new_single(key, value))
}
},
_ => {
let leaf = Self::new_multiple(entries)?;
@@ -53,7 +53,7 @@ impl SmtLeaf {
} else {
Ok(leaf)
}
}
},
}
}
@@ -118,7 +118,7 @@ impl SmtLeaf {
// Note: All keys are guaranteed to have the same leaf index
let (first_key, _) = entries[0];
first_key.into()
}
},
}
}
@@ -129,7 +129,7 @@ impl SmtLeaf {
SmtLeaf::Single(_) => 1,
SmtLeaf::Multiple(entries) => {
entries.len().try_into().expect("shouldn't have more than 2^64 entries")
}
},
}
}
@@ -141,7 +141,7 @@ impl SmtLeaf {
SmtLeaf::Multiple(kvs) => {
let elements: Vec<Felt> = kvs.iter().copied().flat_map(kv_to_elements).collect();
Rpo256::hash_elements(&elements)
}
},
}
}
@@ -182,7 +182,8 @@ impl SmtLeaf {
// HELPERS
// ---------------------------------------------------------------------------------------------
/// Returns the value associated with `key` in the leaf, or `None` if `key` maps to another leaf.
/// Returns the value associated with `key` in the leaf, or `None` if `key` maps to another
/// leaf.
pub(super) fn get_value(&self, key: &RpoDigest) -> Option<Word> {
// Ensure that `key` maps to this leaf
if self.index() != key.into() {
@@ -197,7 +198,7 @@ impl SmtLeaf {
} else {
Some(EMPTY_WORD)
}
}
},
SmtLeaf::Multiple(kv_pairs) => {
for (key_in_leaf, value_in_leaf) in kv_pairs {
if key == key_in_leaf {
@@ -206,7 +207,7 @@ impl SmtLeaf {
}
Some(EMPTY_WORD)
}
},
}
}
@@ -219,7 +220,7 @@ impl SmtLeaf {
SmtLeaf::Empty(_) => {
*self = SmtLeaf::new_single(key, value);
None
}
},
SmtLeaf::Single(kv_pair) => {
if kv_pair.0 == key {
// the key is already in this leaf. Update the value and return the previous
@@ -237,7 +238,7 @@ impl SmtLeaf {
None
}
}
},
SmtLeaf::Multiple(kv_pairs) => {
match kv_pairs.binary_search_by(|kv_pair| cmp_keys(kv_pair.0, key)) {
Ok(pos) => {
@@ -245,14 +246,14 @@ impl SmtLeaf {
kv_pairs[pos].1 = value;
Some(old_value)
}
},
Err(pos) => {
kv_pairs.insert(pos, (key, value));
None
}
},
}
}
},
}
}
@@ -277,7 +278,7 @@ impl SmtLeaf {
// another key is stored at leaf; nothing to update
(None, false)
}
}
},
SmtLeaf::Multiple(kv_pairs) => {
match kv_pairs.binary_search_by(|kv_pair| cmp_keys(kv_pair.0, key)) {
Ok(pos) => {
@@ -292,13 +293,13 @@ impl SmtLeaf {
}
(Some(old_value), false)
}
},
Err(_) => {
// other keys are stored at leaf; nothing to update
(None, false)
}
},
}
}
},
}
}
}

View File

@@ -1,13 +1,14 @@
use super::{
EmptySubtreeRoots, Felt, InnerNode, InnerNodeInfo, LeafIndex, MerkleError, MerklePath,
NodeIndex, Rpo256, RpoDigest, SparseMerkleTree, Word, EMPTY_WORD,
};
use alloc::{
collections::{BTreeMap, BTreeSet},
string::ToString,
vec::Vec,
};
use super::{
EmptySubtreeRoots, Felt, InnerNode, InnerNodeInfo, LeafIndex, MerkleError, MerklePath,
NodeIndex, Rpo256, RpoDigest, SparseMerkleTree, Word, EMPTY_WORD,
};
mod error;
pub use error::{SmtLeafError, SmtProofError};
@@ -32,8 +33,8 @@ pub const SMT_DEPTH: u8 = 64;
/// Sparse Merkle tree mapping 256-bit keys to 256-bit values. Both keys and values are represented
/// by 4 field elements.
///
/// All leaves sit at depth 64. The most significant element of the key is used to identify the leaf to
/// which the key maps.
/// All leaves sit at depth 64. The most significant element of the key is used to identify the leaf
/// to which the key maps.
///
/// A leaf is either empty, or holds one or more key-value pairs. An empty leaf hashes to the empty
/// word. Otherwise, a leaf hashes to the hash of its key-value pairs, ordered by key first, value
@@ -187,7 +188,7 @@ impl Smt {
self.leaves.insert(leaf_index.value(), SmtLeaf::Single((key, value)));
None
}
},
}
}

View File

@@ -1,6 +1,7 @@
use alloc::string::ToString;
use super::{MerklePath, RpoDigest, SmtLeaf, SmtProofError, Word, SMT_DEPTH};
use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
use alloc::string::ToString;
/// A proof which can be used to assert membership (or non-membership) of key-value pairs in a
/// [`super::Smt`].
@@ -57,7 +58,7 @@ impl SmtProof {
// make sure the Merkle path resolves to the correct root
self.compute_root() == *root
}
},
// If the key maps to a different leaf, the proof cannot verify membership of `value`
None => false,
}

View File

@@ -1,10 +1,11 @@
use alloc::vec::Vec;
use super::{Felt, LeafIndex, NodeIndex, Rpo256, RpoDigest, Smt, SmtLeaf, EMPTY_WORD, SMT_DEPTH};
use crate::{
merkle::{EmptySubtreeRoots, MerkleStore},
utils::{Deserializable, Serializable},
Word, ONE, WORD_SIZE,
};
use alloc::vec::Vec;
// SMT
// --------------------------------------------------------------------------------------------

View File

@@ -1,9 +1,10 @@
use alloc::vec::Vec;
use super::{EmptySubtreeRoots, InnerNodeInfo, MerkleError, MerklePath, NodeIndex};
use crate::{
hash::rpo::{Rpo256, RpoDigest},
Felt, Word, EMPTY_WORD,
};
use alloc::vec::Vec;
mod full;
pub use full::{Smt, SmtLeaf, SmtLeafError, SmtProof, SmtProofError, SMT_DEPTH};

View File

@@ -1,9 +1,10 @@
use alloc::collections::{BTreeMap, BTreeSet};
use super::{
super::ValuePath, EmptySubtreeRoots, InnerNode, InnerNodeInfo, LeafIndex, MerkleError,
MerklePath, NodeIndex, RpoDigest, SparseMerkleTree, Word, EMPTY_WORD, SMT_MAX_DEPTH,
SMT_MIN_DEPTH,
};
use alloc::collections::{BTreeMap, BTreeSet};
#[cfg(test)]
mod tests;

View File

@@ -1,3 +1,5 @@
use alloc::vec::Vec;
use super::{
super::{MerkleError, RpoDigest, SimpleSmt},
NodeIndex,
@@ -10,7 +12,6 @@ use crate::{
},
Word, EMPTY_WORD,
};
use alloc::vec::Vec;
// TEST DATA
// ================================================================================================

View File

@@ -127,8 +127,8 @@ impl<T: KvMap<RpoDigest, StoreNode>> MerkleStore<T> {
/// # Errors
/// This method can return the following errors:
/// - `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: RpoDigest, index: NodeIndex) -> Result<RpoDigest, MerkleError> {
let mut hash = root;
@@ -152,8 +152,8 @@ impl<T: KvMap<RpoDigest, StoreNode>> MerkleStore<T> {
/// # Errors
/// This method can return the following errors:
/// - `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: RpoDigest, index: NodeIndex) -> Result<ValuePath, MerkleError> {
let mut hash = root;
let mut path = Vec::with_capacity(index.depth().into());
@@ -421,8 +421,8 @@ impl<T: KvMap<RpoDigest, StoreNode>> MerkleStore<T> {
/// # Errors
/// This method can return the following errors:
/// - `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 set_node(
&mut self,
mut root: RpoDigest,

View File

@@ -1,4 +1,10 @@
use seq_macro::seq;
#[cfg(feature = "std")]
use {
super::{Deserializable, Serializable},
alloc::boxed::Box,
std::error::Error,
};
use super::{
DefaultMerkleStore as MerkleStore, EmptySubtreeRoots, MerkleError, MerklePath, NodeIndex,
@@ -11,13 +17,6 @@ use crate::{
Felt, Word, ONE, WORD_SIZE, ZERO,
};
#[cfg(feature = "std")]
use {
super::{Deserializable, Serializable},
alloc::boxed::Box,
std::error::Error,
};
// TEST DATA
// ================================================================================================