Skip to main content

miden_crypto/merkle/smt/full/
leaf.rs

1use alloc::{string::ToString, vec::Vec};
2use core::cmp::Ordering;
3
4use super::{EMPTY_WORD, Felt, LeafIndex, MAX_LEAF_ENTRIES, Rpo256, SMT_DEPTH, SmtLeafError, Word};
5use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
6
7/// Represents a leaf node in the Sparse Merkle Tree.
8///
9/// A leaf can be empty, hold a single key-value pair, or multiple key-value pairs.
10#[derive(Clone, Debug, PartialEq, Eq)]
11#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
12pub enum SmtLeaf {
13    /// An empty leaf at the specified index.
14    Empty(LeafIndex<SMT_DEPTH>),
15    /// A leaf containing a single key-value pair.
16    Single((Word, Word)),
17    /// A leaf containing multiple key-value pairs.
18    Multiple(Vec<(Word, Word)>),
19}
20
21impl SmtLeaf {
22    // CONSTRUCTORS
23    // ---------------------------------------------------------------------------------------------
24
25    /// Returns a new leaf with the specified entries
26    ///
27    /// # Errors
28    ///   - Returns an error if 2 keys in `entries` map to a different leaf index
29    ///   - Returns an error if 1 or more keys in `entries` map to a leaf index different from
30    ///     `leaf_index`
31    pub fn new(
32        entries: Vec<(Word, Word)>,
33        leaf_index: LeafIndex<SMT_DEPTH>,
34    ) -> Result<Self, SmtLeafError> {
35        match entries.len() {
36            0 => Ok(Self::new_empty(leaf_index)),
37            1 => {
38                let (key, value) = entries[0];
39
40                let computed_index = LeafIndex::<SMT_DEPTH>::from(key);
41                if computed_index != leaf_index {
42                    return Err(SmtLeafError::InconsistentSingleLeafIndices {
43                        key,
44                        expected_leaf_index: leaf_index,
45                        actual_leaf_index: computed_index,
46                    });
47                }
48
49                Ok(Self::new_single(key, value))
50            },
51            _ => {
52                let leaf = Self::new_multiple(entries)?;
53
54                // `new_multiple()` checked that all keys map to the same leaf index. We still need
55                // to ensure that leaf index is `leaf_index`.
56                if leaf.index() != leaf_index {
57                    Err(SmtLeafError::InconsistentMultipleLeafIndices {
58                        leaf_index_from_keys: leaf.index(),
59                        leaf_index_supplied: leaf_index,
60                    })
61                } else {
62                    Ok(leaf)
63                }
64            },
65        }
66    }
67
68    /// Returns a new empty leaf with the specified leaf index
69    pub fn new_empty(leaf_index: LeafIndex<SMT_DEPTH>) -> Self {
70        Self::Empty(leaf_index)
71    }
72
73    /// Returns a new single leaf with the specified entry. The leaf index is derived from the
74    /// entry's key.
75    pub fn new_single(key: Word, value: Word) -> Self {
76        Self::Single((key, value))
77    }
78
79    /// Returns a new multiple leaf with the specified entries. The leaf index is derived from the
80    /// entries' keys.
81    ///
82    /// # Errors
83    ///   - Returns an error if 2 keys in `entries` map to a different leaf index
84    ///   - Returns an error if the number of entries exceeds [`MAX_LEAF_ENTRIES`]
85    pub fn new_multiple(entries: Vec<(Word, Word)>) -> Result<Self, SmtLeafError> {
86        if entries.len() < 2 {
87            return Err(SmtLeafError::MultipleLeafRequiresTwoEntries(entries.len()));
88        }
89
90        if entries.len() > MAX_LEAF_ENTRIES {
91            return Err(SmtLeafError::TooManyLeafEntries { actual: entries.len() });
92        }
93
94        // Check that all keys map to the same leaf index
95        {
96            let mut keys = entries.iter().map(|(key, _)| key);
97
98            let first_key = *keys.next().expect("ensured at least 2 entries");
99            let first_leaf_index: LeafIndex<SMT_DEPTH> = first_key.into();
100
101            for &next_key in keys {
102                let next_leaf_index: LeafIndex<SMT_DEPTH> = next_key.into();
103
104                if next_leaf_index != first_leaf_index {
105                    return Err(SmtLeafError::InconsistentMultipleLeafKeys {
106                        key_1: first_key,
107                        key_2: next_key,
108                    });
109                }
110            }
111        }
112
113        Ok(Self::Multiple(entries))
114    }
115
116    // PUBLIC ACCESSORS
117    // ---------------------------------------------------------------------------------------------
118
119    /// Returns true if the leaf is empty
120    pub fn is_empty(&self) -> bool {
121        matches!(self, Self::Empty(_))
122    }
123
124    /// Returns the leaf's index in the [`super::Smt`]
125    pub fn index(&self) -> LeafIndex<SMT_DEPTH> {
126        match self {
127            SmtLeaf::Empty(leaf_index) => *leaf_index,
128            SmtLeaf::Single((key, _)) => (*key).into(),
129            SmtLeaf::Multiple(entries) => {
130                // Note: All keys are guaranteed to have the same leaf index
131                let (first_key, _) = entries[0];
132                first_key.into()
133            },
134        }
135    }
136
137    /// Returns the number of entries stored in the leaf
138    pub fn num_entries(&self) -> usize {
139        match self {
140            SmtLeaf::Empty(_) => 0,
141            SmtLeaf::Single(_) => 1,
142            SmtLeaf::Multiple(entries) => entries.len(),
143        }
144    }
145
146    /// Computes the hash of the leaf
147    pub fn hash(&self) -> Word {
148        match self {
149            SmtLeaf::Empty(_) => EMPTY_WORD,
150            SmtLeaf::Single((key, value)) => Rpo256::merge(&[*key, *value]),
151            SmtLeaf::Multiple(kvs) => {
152                let elements: Vec<Felt> = kvs.iter().copied().flat_map(kv_to_elements).collect();
153                Rpo256::hash_elements(&elements)
154            },
155        }
156    }
157
158    // ITERATORS
159    // ---------------------------------------------------------------------------------------------
160
161    /// Returns a slice with key-value pairs in the leaf.
162    pub fn entries(&self) -> &[(Word, Word)] {
163        match self {
164            SmtLeaf::Empty(_) => &[],
165            SmtLeaf::Single(kv_pair) => core::slice::from_ref(kv_pair),
166            SmtLeaf::Multiple(kv_pairs) => kv_pairs,
167        }
168    }
169
170    // CONVERSIONS
171    // ---------------------------------------------------------------------------------------------
172
173    /// Converts a leaf to a list of field elements
174    pub fn to_elements(&self) -> Vec<Felt> {
175        self.clone().into_elements()
176    }
177
178    pub fn to_entries(&self) -> impl Iterator<Item = (&Word, &Word)> {
179        self.entries().iter().map(|(k, v)| (k, v))
180    }
181
182    /// Converts a leaf to a list of field elements
183    pub fn into_elements(self) -> Vec<Felt> {
184        self.into_entries().into_iter().flat_map(kv_to_elements).collect()
185    }
186
187    /// Converts a leaf the key-value pairs in the leaf
188    pub fn into_entries(self) -> Vec<(Word, Word)> {
189        match self {
190            SmtLeaf::Empty(_) => Vec::new(),
191            SmtLeaf::Single(kv_pair) => vec![kv_pair],
192            SmtLeaf::Multiple(kv_pairs) => kv_pairs,
193        }
194    }
195
196    // HELPERS
197    // ---------------------------------------------------------------------------------------------
198
199    /// Returns the value associated with `key` in the leaf, or `None` if `key` maps to another
200    /// leaf.
201    pub(in crate::merkle::smt) fn get_value(&self, key: &Word) -> Option<Word> {
202        // Ensure that `key` maps to this leaf
203        if self.index() != (*key).into() {
204            return None;
205        }
206
207        match self {
208            SmtLeaf::Empty(_) => Some(EMPTY_WORD),
209            SmtLeaf::Single((key_in_leaf, value_in_leaf)) => {
210                if key == key_in_leaf {
211                    Some(*value_in_leaf)
212                } else {
213                    Some(EMPTY_WORD)
214                }
215            },
216            SmtLeaf::Multiple(kv_pairs) => {
217                for (key_in_leaf, value_in_leaf) in kv_pairs {
218                    if key == key_in_leaf {
219                        return Some(*value_in_leaf);
220                    }
221                }
222
223                Some(EMPTY_WORD)
224            },
225        }
226    }
227
228    /// Inserts key-value pair into the leaf; returns the previous value associated with `key`, if
229    /// any.
230    ///
231    /// The caller needs to ensure that `key` has the same leaf index as all other keys in the leaf
232    ///
233    /// # Errors
234    /// Returns an error if inserting the key-value pair would exceed [`MAX_LEAF_ENTRIES`] (1024
235    /// entries) in the leaf.
236    pub(in crate::merkle::smt) fn insert(
237        &mut self,
238        key: Word,
239        value: Word,
240    ) -> Result<Option<Word>, SmtLeafError> {
241        match self {
242            SmtLeaf::Empty(_) => {
243                *self = SmtLeaf::new_single(key, value);
244                Ok(None)
245            },
246            SmtLeaf::Single(kv_pair) => {
247                if kv_pair.0 == key {
248                    // the key is already in this leaf. Update the value and return the previous
249                    // value
250                    let old_value = kv_pair.1;
251                    kv_pair.1 = value;
252                    Ok(Some(old_value))
253                } else {
254                    // Another entry is present in this leaf. Transform the entry into a list
255                    // entry, and make sure the key-value pairs are sorted by key
256                    // This stays within MAX_LEAF_ENTRIES limit. We're only adding one entry to a
257                    // single leaf
258                    let mut pairs = vec![*kv_pair, (key, value)];
259                    pairs.sort_by(|(key_1, _), (key_2, _)| cmp_keys(*key_1, *key_2));
260                    *self = SmtLeaf::Multiple(pairs);
261                    Ok(None)
262                }
263            },
264            SmtLeaf::Multiple(kv_pairs) => {
265                match kv_pairs.binary_search_by(|kv_pair| cmp_keys(kv_pair.0, key)) {
266                    Ok(pos) => {
267                        let old_value = kv_pairs[pos].1;
268                        kv_pairs[pos].1 = value;
269                        Ok(Some(old_value))
270                    },
271                    Err(pos) => {
272                        if kv_pairs.len() >= MAX_LEAF_ENTRIES {
273                            return Err(SmtLeafError::TooManyLeafEntries {
274                                actual: kv_pairs.len() + 1,
275                            });
276                        }
277                        kv_pairs.insert(pos, (key, value));
278                        Ok(None)
279                    },
280                }
281            },
282        }
283    }
284
285    /// Removes key-value pair from the leaf stored at key; returns the previous value associated
286    /// with `key`, if any. Also returns an `is_empty` flag, indicating whether the leaf became
287    /// empty, and must be removed from the data structure it is contained in.
288    pub(in crate::merkle::smt) fn remove(&mut self, key: Word) -> (Option<Word>, bool) {
289        match self {
290            SmtLeaf::Empty(_) => (None, false),
291            SmtLeaf::Single((key_at_leaf, value_at_leaf)) => {
292                if *key_at_leaf == key {
293                    // our key was indeed stored in the leaf, so we return the value that was stored
294                    // in it, and indicate that the leaf should be removed
295                    let old_value = *value_at_leaf;
296
297                    // Note: this is not strictly needed, since the caller is expected to drop this
298                    // `SmtLeaf` object.
299                    *self = SmtLeaf::new_empty(key.into());
300
301                    (Some(old_value), true)
302                } else {
303                    // another key is stored at leaf; nothing to update
304                    (None, false)
305                }
306            },
307            SmtLeaf::Multiple(kv_pairs) => {
308                match kv_pairs.binary_search_by(|kv_pair| cmp_keys(kv_pair.0, key)) {
309                    Ok(pos) => {
310                        let old_value = kv_pairs[pos].1;
311
312                        kv_pairs.remove(pos);
313                        debug_assert!(!kv_pairs.is_empty());
314
315                        if kv_pairs.len() == 1 {
316                            // convert the leaf into `Single`
317                            *self = SmtLeaf::Single(kv_pairs[0]);
318                        }
319
320                        (Some(old_value), false)
321                    },
322                    Err(_) => {
323                        // other keys are stored at leaf; nothing to update
324                        (None, false)
325                    },
326                }
327            },
328        }
329    }
330}
331
332impl Serializable for SmtLeaf {
333    fn write_into<W: ByteWriter>(&self, target: &mut W) {
334        // Write: num entries
335        self.num_entries().write_into(target);
336
337        // Write: leaf index
338        let leaf_index: u64 = self.index().value();
339        leaf_index.write_into(target);
340
341        // Write: entries
342        for (key, value) in self.entries() {
343            key.write_into(target);
344            value.write_into(target);
345        }
346    }
347}
348
349impl Deserializable for SmtLeaf {
350    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
351        // Read: num entries
352        let num_entries = source.read_usize()?;
353
354        // Read: leaf index
355        let leaf_index: LeafIndex<SMT_DEPTH> = {
356            let value = source.read_u64()?;
357            LeafIndex::new_max_depth(value)
358        };
359
360        // Read: entries
361        let mut entries: Vec<(Word, Word)> = Vec::new();
362        for _ in 0..num_entries {
363            let key: Word = source.read()?;
364            let value: Word = source.read()?;
365
366            entries.push((key, value));
367        }
368
369        Self::new(entries, leaf_index)
370            .map_err(|err| DeserializationError::InvalidValue(err.to_string()))
371    }
372}
373
374// HELPER FUNCTIONS
375// ================================================================================================
376
377/// Converts a key-value tuple to an iterator of `Felt`s
378pub(crate) fn kv_to_elements((key, value): (Word, Word)) -> impl Iterator<Item = Felt> {
379    let key_elements = key.into_iter();
380    let value_elements = value.into_iter();
381
382    key_elements.chain(value_elements)
383}
384
385/// Compares two keys, compared element-by-element using their integer representations starting with
386/// the most significant element.
387pub(crate) fn cmp_keys(key_1: Word, key_2: Word) -> Ordering {
388    for (v1, v2) in key_1.iter().zip(key_2.iter()).rev() {
389        let v1 = v1.as_int();
390        let v2 = v2.as_int();
391        if v1 != v2 {
392            return v1.cmp(&v2);
393        }
394    }
395
396    Ordering::Equal
397}