Skip to main content

miden_crypto/merkle/
path.rs

1use alloc::vec::Vec;
2use core::{
3    num::NonZero,
4    ops::{Deref, DerefMut},
5};
6
7use super::{InnerNodeInfo, MerkleError, NodeIndex, Poseidon2, Word};
8use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
9
10// MERKLE PATH
11// ================================================================================================
12
13/// A merkle path container, composed of a sequence of nodes of a Merkle tree.
14///
15/// Indexing into this type starts at the deepest part of the path and gets shallower. That is,
16/// the node at index `0` is deeper than the node at index `self.len() - 1`.
17#[derive(Clone, Debug, Default, PartialEq, Eq)]
18pub struct MerklePath {
19    nodes: Vec<Word>,
20}
21
22impl MerklePath {
23    // CONSTRUCTORS
24    // --------------------------------------------------------------------------------------------
25
26    /// Creates a new Merkle path from a list of nodes.
27    ///
28    /// The list must be in order of deepest to shallowest.
29    ///
30    /// # Panics
31    ///
32    /// Panics if more than 255 nodes are provided.
33    pub fn new(nodes: Vec<Word>) -> Self {
34        assert!(nodes.len() <= u8::MAX.into(), "MerklePath may have at most 255 items");
35        Self { nodes }
36    }
37
38    // PROVIDERS
39    // --------------------------------------------------------------------------------------------
40
41    /// Returns a reference to the path node at the specified depth.
42    ///
43    /// The `depth` parameter is defined in terms of `self.depth()`. Merkle paths conventionally do
44    /// not include the root, so the shallowest depth is `1`, and the deepest depth is
45    /// `self.depth()`.
46    pub fn at_depth(&self, depth: NonZero<u8>) -> Option<Word> {
47        let index = u8::checked_sub(self.depth(), depth.get())?;
48        self.nodes.get(index as usize).copied()
49    }
50
51    /// Returns the depth in which this Merkle path proof is valid.
52    pub fn depth(&self) -> u8 {
53        u8::try_from(self.nodes.len()).expect("MerklePath may have at most 255 items")
54    }
55
56    /// Returns a reference to the [MerklePath]'s nodes, in order of deepest to shallowest.
57    pub fn nodes(&self) -> &[Word] {
58        &self.nodes
59    }
60
61    /// Computes the merkle root for this opening.
62    pub fn compute_root(&self, index: u64, node: Word) -> Result<Word, MerkleError> {
63        let mut index = NodeIndex::new(self.depth(), index)?;
64        let root = self.nodes.iter().copied().fold(node, |node, sibling| {
65            // compute the node and move to the next iteration.
66            let input = index.build_node(node, sibling);
67            index.move_up();
68            Poseidon2::merge(&input)
69        });
70        Ok(root)
71    }
72
73    /// Verifies the Merkle opening proof towards the provided root.
74    ///
75    /// # Errors
76    /// Returns an error if:
77    /// - provided node index is invalid.
78    /// - root calculated during the verification differs from the provided one.
79    pub fn verify(&self, index: u64, node: Word, root: &Word) -> Result<(), MerkleError> {
80        let computed_root = self.compute_root(index, node)?;
81        if &computed_root != root {
82            return Err(MerkleError::ConflictingRoots {
83                expected_root: *root,
84                actual_root: computed_root,
85            });
86        }
87
88        Ok(())
89    }
90
91    /// Given the node this path opens to, return an iterator of all the nodes that are known via
92    /// this path.
93    ///
94    /// Each item in the iterator is an [InnerNodeInfo], containing the hash of a node as `.value`,
95    /// and its two children as `.left` and `.right`. The very first item in that iterator will be
96    /// the parent of `node_to_prove`, either `left` or `right` will be `node_to_prove` itself, and
97    /// the other child will be `node_to_prove` as stored in this [MerklePath].
98    ///
99    /// From there, the iterator will continue to yield every further parent and both of its
100    /// children, up to and including the root node.
101    ///
102    /// If `node_to_prove` is not the node this path is an opening to, or `index` is not the
103    /// correct index for that node, the returned nodes will be meaningless.
104    ///
105    /// # Errors
106    /// Returns an error if the specified index is not valid for this path.
107    pub fn authenticated_nodes(
108        &self,
109        index: u64,
110        node_to_prove: Word,
111    ) -> Result<InnerNodeIterator<'_>, MerkleError> {
112        Ok(InnerNodeIterator {
113            nodes: &self.nodes,
114            index: NodeIndex::new(self.depth(), index)?,
115            value: node_to_prove,
116        })
117    }
118}
119
120// CONVERSIONS
121// ================================================================================================
122
123impl From<MerklePath> for Vec<Word> {
124    fn from(path: MerklePath) -> Self {
125        path.nodes
126    }
127}
128
129impl From<Vec<Word>> for MerklePath {
130    fn from(path: Vec<Word>) -> Self {
131        Self::new(path)
132    }
133}
134
135impl From<&[Word]> for MerklePath {
136    fn from(path: &[Word]) -> Self {
137        path.iter().copied().collect()
138    }
139}
140
141impl Deref for MerklePath {
142    type Target = [Word];
143
144    fn deref(&self) -> &Self::Target {
145        &self.nodes
146    }
147}
148
149impl DerefMut for MerklePath {
150    fn deref_mut(&mut self) -> &mut Self::Target {
151        &mut self.nodes
152    }
153}
154
155// ITERATORS
156// ================================================================================================
157
158impl FromIterator<Word> for MerklePath {
159    fn from_iter<T: IntoIterator<Item = Word>>(iter: T) -> Self {
160        Self::new(iter.into_iter().take(usize::from(u8::MAX) + 1).collect())
161    }
162}
163
164impl IntoIterator for MerklePath {
165    type Item = Word;
166    type IntoIter = alloc::vec::IntoIter<Word>;
167
168    fn into_iter(self) -> Self::IntoIter {
169        self.nodes.into_iter()
170    }
171}
172
173/// An iterator over internal nodes of a [MerklePath]. See [`MerklePath::authenticated_nodes()`]
174pub struct InnerNodeIterator<'a> {
175    nodes: &'a [Word],
176    index: NodeIndex,
177    value: Word,
178}
179
180impl Iterator for InnerNodeIterator<'_> {
181    type Item = InnerNodeInfo;
182
183    fn next(&mut self) -> Option<Self::Item> {
184        if !self.index.is_root() {
185            let sibling_pos = self.nodes.len() - self.index.depth() as usize;
186            let (left, right) = if self.index.is_position_odd() {
187                (self.nodes[sibling_pos], self.value)
188            } else {
189                (self.value, self.nodes[sibling_pos])
190            };
191
192            self.value = Poseidon2::merge(&[left, right]);
193            self.index.move_up();
194
195            Some(InnerNodeInfo { value: self.value, left, right })
196        } else {
197            None
198        }
199    }
200}
201
202// MERKLE PATH CONTAINERS
203// ================================================================================================
204
205/// A container for a [crate::Word] value and its [MerklePath] opening.
206#[derive(Clone, Debug, Default, PartialEq, Eq)]
207pub struct MerkleProof {
208    /// The node value opening for `path`.
209    pub value: Word,
210    /// The path from `value` to `root` (exclusive).
211    pub path: MerklePath,
212}
213
214impl MerkleProof {
215    /// Returns a new [MerkleProof] instantiated from the specified value and path.
216    pub fn new(value: Word, path: MerklePath) -> Self {
217        Self { value, path }
218    }
219}
220
221impl From<(MerklePath, Word)> for MerkleProof {
222    fn from((path, value): (MerklePath, Word)) -> Self {
223        MerkleProof::new(value, path)
224    }
225}
226
227/// A container for a [MerklePath] and its [crate::Word] root.
228///
229/// This structure does not provide any guarantees regarding the correctness of the path to the
230/// root. For more information, check [MerklePath::verify].
231#[derive(Clone, Debug, Default, PartialEq, Eq)]
232pub struct RootPath {
233    /// The node value opening for `path`.
234    pub root: Word,
235    /// The path from `value` to `root` (exclusive).
236    pub path: MerklePath,
237}
238
239// SERIALIZATION
240// ================================================================================================
241
242impl Serializable for MerklePath {
243    fn write_into<W: ByteWriter>(&self, target: &mut W) {
244        // Keep the wire-format length prefix safe if an internal construction path ever violates
245        // the type invariant.
246        assert!(self.nodes.len() <= u8::MAX.into(), "MerklePath may have at most 255 items");
247        target.write_u8(self.nodes.len() as u8);
248        target.write_many(&self.nodes);
249    }
250}
251
252impl Deserializable for MerklePath {
253    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
254        let count = source.read_u8()?.into();
255        let nodes: Vec<Word> = source.read_many_iter(count)?.collect::<Result<_, _>>()?;
256        Ok(Self { nodes })
257    }
258}
259
260impl Serializable for MerkleProof {
261    fn write_into<W: ByteWriter>(&self, target: &mut W) {
262        self.value.write_into(target);
263        self.path.write_into(target);
264    }
265}
266
267impl Deserializable for MerkleProof {
268    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
269        let value = Word::read_from(source)?;
270        let path = MerklePath::read_from(source)?;
271        Ok(Self { value, path })
272    }
273}
274
275impl Serializable for RootPath {
276    fn write_into<W: ByteWriter>(&self, target: &mut W) {
277        self.root.write_into(target);
278        self.path.write_into(target);
279    }
280}
281
282impl Deserializable for RootPath {
283    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
284        let root = Word::read_from(source)?;
285        let path = MerklePath::read_from(source)?;
286        Ok(Self { root, path })
287    }
288}
289
290// TESTS
291// ================================================================================================
292
293#[cfg(test)]
294mod tests {
295    use crate::{
296        merkle::{MerklePath, int_to_node},
297        utils::Serializable,
298    };
299
300    #[test]
301    #[should_panic(expected = "MerklePath may have at most 255 items")]
302    fn new_rejects_more_than_255_nodes() {
303        let _ = MerklePath::new(vec![int_to_node(0); u8::MAX as usize + 1]);
304    }
305
306    #[test]
307    #[should_panic(expected = "MerklePath may have at most 255 items")]
308    fn from_iter_caps_allocation_and_rejects_excess_nodes() {
309        // Model an attacker-controlled size hint without materializing the input.
310        let nodes = (0..usize::MAX).map(|_| int_to_node(0));
311        let _ = MerklePath::from_iter(nodes);
312    }
313
314    #[test]
315    #[should_panic(expected = "MerklePath may have at most 255 items")]
316    fn depth_rejects_an_internally_invalid_length() {
317        // Public construction rejects this state; construct it directly to exercise the
318        // defense-in-depth check in `depth()`.
319        let path = MerklePath {
320            nodes: vec![int_to_node(0); u8::MAX as usize + 1],
321        };
322        let _ = path.depth();
323    }
324
325    #[test]
326    #[should_panic(expected = "MerklePath may have at most 255 items")]
327    fn serialization_rejects_an_internally_invalid_length() {
328        let path = MerklePath {
329            nodes: vec![int_to_node(0); u8::MAX as usize + 1],
330        };
331        let _ = path.to_bytes();
332    }
333
334    #[test]
335    fn test_inner_nodes() {
336        let nodes = vec![int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
337        let merkle_path = MerklePath::new(nodes);
338
339        let index = 6;
340        let node = int_to_node(5);
341        let root = merkle_path.compute_root(index, node).unwrap();
342
343        let inner_root =
344            merkle_path.authenticated_nodes(index, node).unwrap().last().unwrap().value;
345
346        assert_eq!(root, inner_root);
347    }
348}