miden-crypto/src/merkle/path.rs
src/merkle/path.rsRaw
1use super::{vec, InnerNodeInfo, MerkleError, NodeIndex, Rpo256, RpoDigest, Vec};
2use core::ops::{Deref, DerefMut};
3
4// MERKLE PATH
5// ================================================================================================
6
7/// A merkle path container, composed of a sequence of nodes of a Merkle tree.
8#[derive(Clone, Debug, Default, PartialEq, Eq)]
9#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
10pub struct MerklePath {
11 nodes: Vec<RpoDigest>,
12}
13
14impl MerklePath {
15 // CONSTRUCTORS
16 // --------------------------------------------------------------------------------------------
17
18 /// Creates a new Merkle path from a list of nodes.
19 pub fn new(nodes: Vec<RpoDigest>) -> Self {
20 Self { nodes }
21 }
22
23 // PROVIDERS
24 // --------------------------------------------------------------------------------------------
25
26 /// Returns the depth in which this Merkle path proof is valid.
27 pub fn depth(&self) -> u8 {
28 self.nodes.len() as u8
29 }
30
31 /// Returns a reference to the [MerklePath]'s nodes.
32 pub fn nodes(&self) -> &[RpoDigest] {
33 &self.nodes
34 }
35
36 /// Computes the merkle root for this opening.
37 pub fn compute_root(&self, index: u64, node: RpoDigest) -> Result<RpoDigest, MerkleError> {
38 let mut index = NodeIndex::new(self.depth(), index)?;
39 let root = self.nodes.iter().copied().fold(node, |node, sibling| {
40 // compute the node and move to the next iteration.
41 let input = index.build_node(node, sibling);
42 index.move_up();
43 Rpo256::merge(&input)
44 });
45 Ok(root)
46 }
47
48 /// Verifies the Merkle opening proof towards the provided root.
49 ///
50 /// Returns `true` if `node` exists at `index` in a Merkle tree with `root`.
51 pub fn verify(&self, index: u64, node: RpoDigest, root: &RpoDigest) -> bool {
52 match self.compute_root(index, node) {
53 Ok(computed_root) => root == &computed_root,
54 Err(_) => false,
55 }
56 }
57
58 /// Returns an iterator over every inner node of this [MerklePath].
59 ///
60 /// The iteration order is unspecified.
61 ///
62 /// # Errors
63 /// Returns an error if the specified index is not valid for this path.
64 pub fn inner_nodes(
65 &self,
66 index: u64,
67 node: RpoDigest,
68 ) -> Result<InnerNodeIterator, MerkleError> {
69 Ok(InnerNodeIterator {
70 nodes: &self.nodes,
71 index: NodeIndex::new(self.depth(), index)?,
72 value: node,
73 })
74 }
75}
76
77// CONVERSIONS
78// ================================================================================================
79
80impl From<MerklePath> for Vec<RpoDigest> {
81 fn from(path: MerklePath) -> Self {
82 path.nodes
83 }
84}
85
86impl From<Vec<RpoDigest>> for MerklePath {
87 fn from(path: Vec<RpoDigest>) -> Self {
88 Self::new(path)
89 }
90}
91
92impl From<&[RpoDigest]> for MerklePath {
93 fn from(path: &[RpoDigest]) -> Self {
94 Self::new(path.to_vec())
95 }
96}
97
98impl Deref for MerklePath {
99 // we use `Vec` here instead of slice so we can call vector mutation methods directly from the
100 // merkle path (example: `Vec::remove`).
101 type Target = Vec<RpoDigest>;
102
103 fn deref(&self) -> &Self::Target {
104 &self.nodes
105 }
106}
107
108impl DerefMut for MerklePath {
109 fn deref_mut(&mut self) -> &mut Self::Target {
110 &mut self.nodes
111 }
112}
113
114// ITERATORS
115// ================================================================================================
116
117impl FromIterator<RpoDigest> for MerklePath {
118 fn from_iter<T: IntoIterator<Item = RpoDigest>>(iter: T) -> Self {
119 Self::new(iter.into_iter().collect())
120 }
121}
122
123impl IntoIterator for MerklePath {
124 type Item = RpoDigest;
125 type IntoIter = vec::IntoIter<RpoDigest>;
126
127 fn into_iter(self) -> Self::IntoIter {
128 self.nodes.into_iter()
129 }
130}
131
132/// An iterator over internal nodes of a [MerklePath].
133pub struct InnerNodeIterator<'a> {
134 nodes: &'a Vec<RpoDigest>,
135 index: NodeIndex,
136 value: RpoDigest,
137}
138
139impl<'a> Iterator for InnerNodeIterator<'a> {
140 type Item = InnerNodeInfo;
141
142 fn next(&mut self) -> Option<Self::Item> {
143 if !self.index.is_root() {
144 let sibling_pos = self.nodes.len() - self.index.depth() as usize;
145 let (left, right) = if self.index.is_value_odd() {
146 (self.nodes[sibling_pos], self.value)
147 } else {
148 (self.value, self.nodes[sibling_pos])
149 };
150
151 self.value = Rpo256::merge(&[left, right]);
152 self.index.move_up();
153
154 Some(InnerNodeInfo { value: self.value, left, right })
155 } else {
156 None
157 }
158 }
159}
160
161// MERKLE PATH CONTAINERS
162// ================================================================================================
163
164/// A container for a [Word] value and its [MerklePath] opening.
165#[derive(Clone, Debug, Default, PartialEq, Eq)]
166pub struct ValuePath {
167 /// The node value opening for `path`.
168 pub value: RpoDigest,
169 /// The path from `value` to `root` (exclusive).
170 pub path: MerklePath,
171}
172
173impl ValuePath {
174 /// Returns a new [ValuePath] instantiated from the specified value and path.
175 pub fn new(value: RpoDigest, path: Vec<RpoDigest>) -> Self {
176 Self { value, path: MerklePath::new(path) }
177 }
178}
179
180/// A container for a [MerklePath] and its [Word] root.
181///
182/// This structure does not provide any guarantees regarding the correctness of the path to the
183/// root. For more information, check [MerklePath::verify].
184#[derive(Clone, Debug, Default, PartialEq, Eq)]
185pub struct RootPath {
186 /// The node value opening for `path`.
187 pub root: RpoDigest,
188 /// The path from `value` to `root` (exclusive).
189 pub path: MerklePath,
190}
191
192// TESTS
193// ================================================================================================
194
195#[cfg(test)]
196mod tests {
197 use crate::merkle::{int_to_node, MerklePath};
198
199 #[test]
200 fn test_inner_nodes() {
201 let nodes = vec![int_to_node(1), int_to_node(2), int_to_node(3), int_to_node(4)];
202 let merkle_path = MerklePath::new(nodes);
203
204 let index = 6;
205 let node = int_to_node(5);
206 let root = merkle_path.compute_root(index, node).unwrap();
207
208 let inner_root = merkle_path.inner_nodes(index, node).unwrap().last().unwrap().value;
209
210 assert_eq!(root, inner_root);
211 }
212}