miden_crypto/merkle/partial_mt/
mod.rs

1use alloc::{
2    collections::{BTreeMap, BTreeSet},
3    string::String,
4    vec::Vec,
5};
6use core::fmt;
7
8use super::{
9    EMPTY_WORD, InnerNodeInfo, MerkleError, MerklePath, MerkleProof, NodeIndex, Rpo256, Word,
10};
11use crate::utils::{
12    ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, word_to_hex,
13};
14
15#[cfg(test)]
16mod tests;
17
18// CONSTANTS
19// ================================================================================================
20
21/// Index of the root node.
22const ROOT_INDEX: NodeIndex = NodeIndex::root();
23
24/// An Word consisting of 4 ZERO elements.
25const EMPTY_DIGEST: Word = EMPTY_WORD;
26
27// PARTIAL MERKLE TREE
28// ================================================================================================
29
30/// A partial Merkle tree with NodeIndex keys and 4-element [Word] leaf values. Partial Merkle
31/// Tree allows to create Merkle Tree by providing Merkle paths of different lengths.
32///
33/// The root of the tree is recomputed on each new leaf update.
34#[derive(Debug, Clone, PartialEq, Eq)]
35#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
36pub struct PartialMerkleTree {
37    max_depth: u8,
38    nodes: BTreeMap<NodeIndex, Word>,
39    leaves: BTreeSet<NodeIndex>,
40}
41
42impl Default for PartialMerkleTree {
43    fn default() -> Self {
44        Self::new()
45    }
46}
47
48impl PartialMerkleTree {
49    // CONSTANTS
50    // --------------------------------------------------------------------------------------------
51
52    /// Minimum supported depth.
53    pub const MIN_DEPTH: u8 = 1;
54
55    /// Maximum supported depth.
56    pub const MAX_DEPTH: u8 = 64;
57
58    // CONSTRUCTORS
59    // --------------------------------------------------------------------------------------------
60
61    /// Returns a new empty [PartialMerkleTree].
62    pub fn new() -> Self {
63        PartialMerkleTree {
64            max_depth: 0,
65            nodes: BTreeMap::new(),
66            leaves: BTreeSet::new(),
67        }
68    }
69
70    /// Appends the provided paths iterator into the set.
71    ///
72    /// Analogous to [Self::add_path].
73    pub fn with_paths<I>(paths: I) -> Result<Self, MerkleError>
74    where
75        I: IntoIterator<Item = (u64, Word, MerklePath)>,
76    {
77        // create an empty tree
78        let tree = PartialMerkleTree::new();
79
80        paths.into_iter().try_fold(tree, |mut tree, (index, value, path)| {
81            tree.add_path(index, value, path)?;
82            Ok(tree)
83        })
84    }
85
86    /// Returns a new [PartialMerkleTree] instantiated with leaves map as specified by the provided
87    /// entries.
88    ///
89    /// # Errors
90    /// Returns an error if:
91    /// - If the depth is 0 or is greater than 64.
92    /// - The number of entries exceeds the maximum tree capacity, that is 2^{depth}.
93    /// - The provided entries contain an insufficient set of nodes.
94    pub fn with_leaves<R, I>(entries: R) -> Result<Self, MerkleError>
95    where
96        R: IntoIterator<IntoIter = I>,
97        I: Iterator<Item = (NodeIndex, Word)> + ExactSizeIterator,
98    {
99        let mut layers: BTreeMap<u8, Vec<u64>> = BTreeMap::new();
100        let mut leaves = BTreeSet::new();
101        let mut nodes = BTreeMap::new();
102
103        // add data to the leaves and nodes maps and also fill layers map, where the key is the
104        // depth of the node and value is its index.
105        for (node_index, hash) in entries.into_iter() {
106            leaves.insert(node_index);
107            nodes.insert(node_index, hash);
108            layers
109                .entry(node_index.depth())
110                .and_modify(|layer_vec| layer_vec.push(node_index.value()))
111                .or_insert(vec![node_index.value()]);
112        }
113
114        // check if the number of leaves can be accommodated by the tree's depth; we use a min
115        // depth of 63 because we consider passing in a vector of size 2^64 infeasible.
116        let max = 2usize.pow(63);
117        if layers.len() > max {
118            return Err(MerkleError::TooManyEntries(max));
119        }
120
121        // Get maximum depth
122        let max_depth = *layers.keys().next_back().unwrap_or(&0);
123
124        // fill layers without nodes with empty vector
125        for depth in 0..max_depth {
126            layers.entry(depth).or_default();
127        }
128
129        let mut layer_iter = layers.into_values().rev();
130        let mut parent_layer = layer_iter.next().unwrap();
131        let mut current_layer;
132
133        for depth in (1..max_depth + 1).rev() {
134            // set current_layer = parent_layer and parent_layer = layer_iter.next()
135            current_layer = layer_iter.next().unwrap();
136            core::mem::swap(&mut current_layer, &mut parent_layer);
137
138            for index_value in current_layer {
139                // get the parent node index
140                let parent_node = NodeIndex::new(depth - 1, index_value / 2)?;
141
142                // Check if the parent hash was already calculated. In about half of the cases, we
143                // don't need to do anything.
144                if !parent_layer.contains(&parent_node.value()) {
145                    // create current node index
146                    let index = NodeIndex::new(depth, index_value)?;
147
148                    // get hash of the current node
149                    let node =
150                        nodes.get(&index).ok_or(MerkleError::NodeIndexNotFoundInTree(index))?;
151                    // get hash of the sibling node
152                    let sibling = nodes
153                        .get(&index.sibling())
154                        .ok_or(MerkleError::NodeIndexNotFoundInTree(index.sibling()))?;
155                    // get parent hash
156                    let parent = Rpo256::merge(&index.build_node(*node, *sibling));
157
158                    // add index value of the calculated node to the parents layer
159                    parent_layer.push(parent_node.value());
160                    // add index and hash to the nodes map
161                    nodes.insert(parent_node, parent);
162                }
163            }
164        }
165
166        Ok(PartialMerkleTree { max_depth, nodes, leaves })
167    }
168
169    // PUBLIC ACCESSORS
170    // --------------------------------------------------------------------------------------------
171
172    /// Returns the root of this Merkle tree.
173    pub fn root(&self) -> Word {
174        self.nodes.get(&ROOT_INDEX).cloned().unwrap_or(EMPTY_DIGEST)
175    }
176
177    /// Returns the depth of this Merkle tree.
178    pub fn max_depth(&self) -> u8 {
179        self.max_depth
180    }
181
182    /// Returns a node at the specified NodeIndex.
183    ///
184    /// # Errors
185    /// Returns an error if the specified NodeIndex is not contained in the nodes map.
186    pub fn get_node(&self, index: NodeIndex) -> Result<Word, MerkleError> {
187        self.nodes
188            .get(&index)
189            .ok_or(MerkleError::NodeIndexNotFoundInTree(index))
190            .copied()
191    }
192
193    /// Returns true if provided index contains in the leaves set, false otherwise.
194    pub fn is_leaf(&self, index: NodeIndex) -> bool {
195        self.leaves.contains(&index)
196    }
197
198    /// Returns a vector of paths from every leaf to the root.
199    pub fn to_paths(&self) -> Vec<(NodeIndex, MerkleProof)> {
200        let mut paths = Vec::new();
201        self.leaves.iter().for_each(|&leaf| {
202            paths.push((
203                leaf,
204                MerkleProof {
205                    value: self.get_node(leaf).expect("Failed to get leaf node"),
206                    path: self.get_path(leaf).expect("Failed to get path"),
207                },
208            ));
209        });
210        paths
211    }
212
213    /// Returns a Merkle path from the node at the specified index to the root.
214    ///
215    /// The node itself is not included in the path.
216    ///
217    /// # Errors
218    /// Returns an error if:
219    /// - the specified index has depth set to 0 or the depth is greater than the depth of this
220    ///   Merkle tree.
221    /// - the specified index is not contained in the nodes map.
222    pub fn get_path(&self, mut index: NodeIndex) -> Result<MerklePath, MerkleError> {
223        if index.is_root() {
224            return Err(MerkleError::DepthTooSmall(index.depth()));
225        } else if index.depth() > self.max_depth() {
226            return Err(MerkleError::DepthTooBig(index.depth() as u64));
227        }
228
229        if !self.nodes.contains_key(&index) {
230            return Err(MerkleError::NodeIndexNotFoundInTree(index));
231        }
232
233        let mut path = Vec::new();
234        for _ in 0..index.depth() {
235            let sibling_index = index.sibling();
236            index.move_up();
237            let sibling =
238                self.nodes.get(&sibling_index).cloned().expect("Sibling node not in the map");
239            path.push(sibling);
240        }
241        Ok(MerklePath::new(path))
242    }
243
244    // ITERATORS
245    // --------------------------------------------------------------------------------------------
246
247    /// Returns an iterator over the leaves of this [PartialMerkleTree].
248    pub fn leaves(&self) -> impl Iterator<Item = (NodeIndex, Word)> + '_ {
249        self.leaves.iter().map(|&leaf| {
250            (
251                leaf,
252                self.get_node(leaf)
253                    .unwrap_or_else(|_| panic!("Leaf with {leaf} is not in the nodes map")),
254            )
255        })
256    }
257
258    /// Returns an iterator over the inner nodes of this Merkle tree.
259    pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
260        let inner_nodes = self.nodes.iter().filter(|(index, _)| !self.leaves.contains(index));
261        inner_nodes.map(|(index, digest)| {
262            let left_hash =
263                self.nodes.get(&index.left_child()).expect("Failed to get left child hash");
264            let right_hash =
265                self.nodes.get(&index.right_child()).expect("Failed to get right child hash");
266            InnerNodeInfo {
267                value: *digest,
268                left: *left_hash,
269                right: *right_hash,
270            }
271        })
272    }
273
274    // STATE MUTATORS
275    // --------------------------------------------------------------------------------------------
276
277    /// Adds the nodes of the specified Merkle path to this [PartialMerkleTree]. The `index_value`
278    /// and `value` parameters specify the leaf node at which the path starts.
279    ///
280    /// # Errors
281    /// Returns an error if:
282    /// - The depth of the specified node_index is greater than 64 or smaller than 1.
283    /// - The specified path is not consistent with other paths in the set (i.e., resolves to a
284    ///   different root).
285    pub fn add_path(
286        &mut self,
287        index_value: u64,
288        value: Word,
289        path: MerklePath,
290    ) -> Result<(), MerkleError> {
291        let index_value = NodeIndex::new(path.len() as u8, index_value)?;
292
293        Self::check_depth(index_value.depth())?;
294        self.update_depth(index_value.depth());
295
296        // add provided node and its sibling to the leaves set
297        self.leaves.insert(index_value);
298        let sibling_node_index = index_value.sibling();
299        self.leaves.insert(sibling_node_index);
300
301        // add provided node and its sibling to the nodes map
302        self.nodes.insert(index_value, value);
303        self.nodes.insert(sibling_node_index, path[0]);
304
305        // traverse to the root, updating the nodes
306        let mut index_value = index_value;
307        let node = Rpo256::merge(&index_value.build_node(value, path[0]));
308        let root = path.iter().skip(1).copied().fold(node, |node, hash| {
309            index_value.move_up();
310            // insert calculated node to the nodes map
311            self.nodes.insert(index_value, node);
312
313            // if the calculated node was a leaf, remove it from leaves set.
314            self.leaves.remove(&index_value);
315
316            let sibling_node = index_value.sibling();
317
318            // Insert node from Merkle path to the nodes map. This sibling node becomes a leaf only
319            // if it is a new node (it wasn't in nodes map).
320            // Node can be in 3 states: internal node, leaf of the tree and not a tree node at all.
321            // - Internal node can only stay in this state -- addition of a new path can't make it
322            // a leaf or remove it from the tree.
323            // - Leaf node can stay in the same state (remain a leaf) or can become an internal
324            // node. In the first case we don't need to do anything, and the second case is handled
325            // by the call of `self.leaves.remove(&index_value);`
326            // - New node can be a calculated node or a "sibling" node from a Merkle Path:
327            // --- Calculated node, obviously, never can be a leaf.
328            // --- Sibling node can be only a leaf, because otherwise it is not a new node.
329            if self.nodes.insert(sibling_node, hash).is_none() {
330                self.leaves.insert(sibling_node);
331            }
332
333            Rpo256::merge(&index_value.build_node(node, hash))
334        });
335
336        // if the path set is empty (the root is all ZEROs), set the root to the root of the added
337        // path; otherwise, the root of the added path must be identical to the current root
338        if self.root() == EMPTY_DIGEST {
339            self.nodes.insert(ROOT_INDEX, root);
340        } else if self.root() != root {
341            return Err(MerkleError::ConflictingRoots {
342                expected_root: self.root(),
343                actual_root: root,
344            });
345        }
346
347        Ok(())
348    }
349
350    /// Updates value of the leaf at the specified index returning the old leaf value.
351    ///
352    /// By default the specified index is assumed to belong to the deepest layer. If the considered
353    /// node does not belong to the tree, the first node on the way to the root will be changed.
354    ///
355    /// This also recomputes all hashes between the leaf and the root, updating the root itself.
356    ///
357    /// # Errors
358    /// Returns an error if:
359    /// - No entry exists at the specified index.
360    /// - The specified index is greater than the maximum number of nodes on the deepest layer.
361    pub fn update_leaf(&mut self, index: u64, value: Word) -> Result<Word, MerkleError> {
362        let mut node_index = NodeIndex::new(self.max_depth(), index)?;
363
364        // proceed to the leaf
365        for _ in 0..node_index.depth() {
366            if !self.leaves.contains(&node_index) {
367                node_index.move_up();
368            }
369        }
370
371        // add node value to the nodes Map
372        let old_value = self
373            .nodes
374            .insert(node_index, value)
375            .ok_or(MerkleError::NodeIndexNotFoundInTree(node_index))?;
376
377        // if the old value and new value are the same, there is nothing to update
378        if value == old_value {
379            return Ok(old_value);
380        }
381
382        let mut value = value;
383        for _ in 0..node_index.depth() {
384            let sibling = self.nodes.get(&node_index.sibling()).expect("sibling should exist");
385            value = Rpo256::merge(&node_index.build_node(value, *sibling));
386            node_index.move_up();
387            self.nodes.insert(node_index, value);
388        }
389
390        Ok(old_value)
391    }
392
393    // UTILITY FUNCTIONS
394    // --------------------------------------------------------------------------------------------
395
396    /// Utility to visualize a [PartialMerkleTree] in text.
397    pub fn print(&self) -> Result<String, fmt::Error> {
398        let indent = "  ";
399        let mut s = String::new();
400        s.push_str("root: ");
401        s.push_str(&word_to_hex(&self.root())?);
402        s.push('\n');
403        for d in 1..=self.max_depth() {
404            let entries = 2u64.pow(d.into());
405            for i in 0..entries {
406                let index = NodeIndex::new(d, i).expect("The index must always be valid");
407                let node = self.get_node(index);
408                let node = match node {
409                    Err(_) => continue,
410                    Ok(node) => node,
411                };
412
413                for _ in 0..d {
414                    s.push_str(indent);
415                }
416                s.push_str(&format!("({}, {}): ", index.depth(), index.value()));
417                s.push_str(&word_to_hex(&node)?);
418                s.push('\n');
419            }
420        }
421
422        Ok(s)
423    }
424
425    // HELPER METHODS
426    // --------------------------------------------------------------------------------------------
427
428    /// Updates depth value with the maximum of current and provided depth.
429    fn update_depth(&mut self, new_depth: u8) {
430        self.max_depth = new_depth.max(self.max_depth);
431    }
432
433    /// Returns an error if the depth is 0 or is greater than 64.
434    fn check_depth(depth: u8) -> Result<(), MerkleError> {
435        // validate the range of the depth.
436        if depth < Self::MIN_DEPTH {
437            return Err(MerkleError::DepthTooSmall(depth));
438        } else if Self::MAX_DEPTH < depth {
439            return Err(MerkleError::DepthTooBig(depth as u64));
440        }
441        Ok(())
442    }
443}
444
445// SERIALIZATION
446// ================================================================================================
447
448impl Serializable for PartialMerkleTree {
449    fn write_into<W: ByteWriter>(&self, target: &mut W) {
450        // write leaf nodes
451        target.write_u64(self.leaves.len() as u64);
452        for leaf_index in self.leaves.iter() {
453            leaf_index.write_into(target);
454            self.get_node(*leaf_index).expect("Leaf hash not found").write_into(target);
455        }
456    }
457}
458
459impl Deserializable for PartialMerkleTree {
460    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
461        let leaves_len = source.read_u64()? as usize;
462        let mut leaf_nodes = Vec::with_capacity(leaves_len);
463
464        // add leaf nodes to the vector
465        for _ in 0..leaves_len {
466            let index = NodeIndex::read_from(source)?;
467            let hash = Word::read_from(source)?;
468            leaf_nodes.push((index, hash));
469        }
470
471        let pmt = PartialMerkleTree::with_leaves(leaf_nodes).map_err(|_| {
472            DeserializationError::InvalidValue("Invalid data for PartialMerkleTree creation".into())
473        })?;
474
475        Ok(pmt)
476    }
477}