diff --git a/src/merkle/smt/full/mod.rs b/src/merkle/smt/full/mod.rs index 1be483a..89d0702 100644 --- a/src/merkle/smt/full/mod.rs +++ b/src/merkle/smt/full/mod.rs @@ -351,6 +351,30 @@ impl SparseMerkleTree for Smt { fn path_and_leaf_to_opening(path: MerklePath, leaf: SmtLeaf) -> SmtProof { SmtProof::new_unchecked(path, leaf) } + + fn pairs_to_leaf(mut pairs: Vec<(RpoDigest, Word)>) -> SmtLeaf { + assert!(!pairs.is_empty()); + + // FIXME + if cfg!(debug_assertions) { + let mut control = pairs.clone(); + control.sort_by_key(|(key, _)| Self::key_to_leaf_index(key).index.value()); + assert_eq!(control, pairs); + } + + if pairs.len() > 1 { + SmtLeaf::new_multiple(pairs).unwrap() + } else { + let (key, value) = pairs.pop().unwrap(); + // FIXME: should we ever be constructing empty leaves from pairs? + if value == Self::EMPTY_VALUE { + let index = Self::key_to_leaf_index(&key); + SmtLeaf::new_empty(index) + } else { + SmtLeaf::new_single(key, value) + } + } + } } impl Default for Smt { diff --git a/src/merkle/smt/mod.rs b/src/merkle/smt/mod.rs index 063003b..c114ae9 100644 --- a/src/merkle/smt/mod.rs +++ b/src/merkle/smt/mod.rs @@ -341,6 +341,10 @@ pub(crate) trait SparseMerkleTree { /// Maps a key to a leaf index fn key_to_leaf_index(key: &Self::Key) -> LeafIndex; + /// Constructs a single leaf from an arbitrary amount of key-value pairs. + /// Those pairs must all have the same leaf index. + fn pairs_to_leaf(pairs: Vec<(Self::Key, Self::Value)>) -> Self::Leaf; + /// Maps a (MerklePath, Self::Leaf) to an opening. /// /// The length `path` is guaranteed to be equal to `DEPTH` diff --git a/src/merkle/smt/simple/mod.rs b/src/merkle/smt/simple/mod.rs index edd9849..04476a0 100644 --- a/src/merkle/smt/simple/mod.rs +++ b/src/merkle/smt/simple/mod.rs @@ -373,4 +373,11 @@ impl SparseMerkleTree for SimpleSmt { fn path_and_leaf_to_opening(path: MerklePath, leaf: Word) -> ValuePath { (path, leaf).into() } + + fn pairs_to_leaf(mut pairs: Vec<(LeafIndex, Word)>) -> Word { + // SimpleSmt can't have more than one value per key. + assert_eq!(pairs.len(), 1); + let (_key, value) = pairs.pop().unwrap(); + value + } }