Add methods to `Smt` necessary for VM tests (#264) * Smt::inner_nodes * Add conversion Smt -> MerkleStore * add docstring to `Smt` * add to docstring * fmt * add `leaves()` method to `Smt` * add `kv_pairs` functions * rewrite `into_elements()` in terms of `into_kv_pairs()` * change docstring
Philippe Laferrière plafer@protonmail.com
Mon, 29 Jan 2024 10:13:52 -0500
2 files changed,
53 insertions(+),
4 deletions(-)
M
src/merkle/smt/full/mod.rs
→
src/merkle/smt/full/mod.rs
@@ -3,7 +3,7 @@
use winter_math::StarkField; use crate::hash::rpo::Rpo256; -use crate::merkle::EmptySubtreeRoots; +use crate::merkle::{EmptySubtreeRoots, InnerNodeInfo}; use crate::utils::{ collections::{BTreeMap, BTreeSet, Vec}, vec,@@ -25,6 +25,15 @@
// SMT // ================================================================================================ +/// 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. +/// +/// 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 +/// second. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Smt {@@ -111,6 +120,25 @@ pub fn open(&self, key: &RpoDigest) -> (MerklePath, SmtLeaf) {
<Self as SparseMerkleTree<SMT_DEPTH>>::open(self, key) } + // ITERATORS + // -------------------------------------------------------------------------------------------- + + /// Returns an iterator over the leaves of this [Smt]. + pub fn leaves(&self) -> impl Iterator<Item = (LeafIndex<SMT_DEPTH>, &SmtLeaf)> { + self.leaves + .iter() + .map(|(leaf_index, leaf)| (LeafIndex::new_max_depth(*leaf_index), leaf)) + } + + /// Returns an iterator over the inner nodes of this [Smt]. + pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ { + self.inner_nodes.values().map(|e| InnerNodeInfo { + value: e.hash(), + left: e.left, + right: e.right, + }) + } + // STATE MUTATORS // --------------------------------------------------------------------------------------------@@ -242,10 +270,24 @@ }
/// Converts a leaf to a list of field elements pub fn into_elements(self) -> Vec<Felt> { + self.into_kv_pairs().into_iter().flat_map(kv_to_elements).collect() + } + + /// Returns the key-value pairs in the leaf + pub fn kv_pairs(&self) -> Vec<&(RpoDigest, Word)> { match self { SmtLeaf::Empty => Vec::new(), - SmtLeaf::Single(kv_pair) => kv_to_elements(kv_pair).collect(), - SmtLeaf::Multiple(kv_pairs) => kv_pairs.into_iter().flat_map(kv_to_elements).collect(), + SmtLeaf::Single(kv_pair) => vec![kv_pair], + SmtLeaf::Multiple(kv_pairs) => kv_pairs.iter().collect(), + } + } + + /// Converts a leaf the key-value pairs in the leaf + pub fn into_kv_pairs(self) -> Vec<(RpoDigest, Word)> { + match self { + SmtLeaf::Empty => Vec::new(), + SmtLeaf::Single(kv_pair) => vec![kv_pair], + SmtLeaf::Multiple(kv_pairs) => kv_pairs, } }
M
src/merkle/store/mod.rs
→
src/merkle/store/mod.rs
@@ -1,7 +1,7 @@
use super::{ mmr::Mmr, BTreeMap, EmptySubtreeRoots, InnerNodeInfo, KvMap, MerkleError, MerklePath, MerkleTree, NodeIndex, PartialMerkleTree, RecordingMap, RootPath, Rpo256, RpoDigest, SimpleSmt, - TieredSmt, ValuePath, Vec, + Smt, TieredSmt, ValuePath, Vec, }; use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; use core::borrow::Borrow;@@ -492,6 +492,13 @@ }
impl<T: KvMap<RpoDigest, StoreNode>, const DEPTH: u8> From<&SimpleSmt<DEPTH>> for MerkleStore<T> { fn from(value: &SimpleSmt<DEPTH>) -> Self { + let nodes = combine_nodes_with_empty_hashes(value.inner_nodes()).collect(); + Self { nodes } + } +} + +impl<T: KvMap<RpoDigest, StoreNode>> From<&Smt> for MerkleStore<T> { + fn from(value: &Smt) -> Self { let nodes = combine_nodes_with_empty_hashes(value.inner_nodes()).collect(); Self { nodes } }