winter_crypto/merkle/mod.rs
1// Copyright (c) Facebook, Inc. and its affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6use alloc::{
7 collections::{BTreeMap, BTreeSet},
8 vec::Vec,
9};
10use core::slice;
11
12mod proofs;
13pub use proofs::BatchMerkleProof;
14
15use crate::{Hasher, MerkleTreeError, VectorCommitment};
16
17#[cfg(feature = "concurrent")]
18pub mod concurrent;
19
20#[cfg(test)]
21mod tests;
22
23// TYPES AND INTERFACES
24// ================================================================================================
25
26/// A fully-balanced Merkle tree.
27///
28/// In this implementation, a Merkle tree consists of two types of nodes: leaves and internal nodes
29/// (one of which is a tree root). All nodes must be instances of the digest specified by the
30/// [Hasher] used to build the tree.
31///
32/// ```text
33/// * <- tree root
34/// / \
35/// / \
36/// * * <- internal nodes
37/// / \ / \
38/// o o o o <- leaves
39/// | | | |
40/// # # # # <- values
41/// ```
42///
43/// A tree can be built from a slice of leaves using [MerkleTree::new()] function. Thus, the user
44/// is responsible for performing the first level of hashing (i.e., hashing values into leaf
45/// nodes). The number of leaves must always be a power of two so that the tree is fully balanced,
46/// and a tree must contain at least two leaves.
47///
48/// The depth of a tree is zero-based. Thus, a tree with two leaves has depth 1, a tree with four
49/// leaves has depth 2 etc.
50///
51/// When the crate is compiled with `concurrent` feature enabled, tree construction will be
52/// performed in multiple threads (usually, as many threads as there are logical cores on the
53/// machine). The number of threads can be configured via `RAYON_NUM_THREADS` environment variable.
54///
55/// To generate an inclusion proof for a given leaf, [MerkleTree::prove()] method can be used.
56/// You can also use [MerkleTree::prove_batch()] method to generate inclusion proofs for multiple
57/// leaves. The advantage of the batch method is that redundant internal nodes are removed from
58/// the batch proof, thereby compressing it (we use a variation of the
59/// [Octopus](https://eprint.iacr.org/2017/933) algorithm).
60///
61/// To verify proofs, [MerkleTree::verify()] and [MerkleTree::verify_batch()] functions can be
62/// used respectively.
63///
64/// # Examples
65/// ```
66/// # use winter_crypto::{MerkleTree, Hasher, hashers::Blake3_256};
67/// # use math::fields::f128::BaseElement;
68/// type Blake3 = Blake3_256<BaseElement>;
69///
70/// // build a tree
71/// let leaves = [
72/// Blake3::hash(&[1u8]),
73/// Blake3::hash(&[2u8]),
74/// Blake3::hash(&[3u8]),
75/// Blake3::hash(&[4u8]),
76/// ];
77/// let tree = MerkleTree::<Blake3>::new(leaves.to_vec()).unwrap();
78/// assert_eq!(2, tree.depth());
79/// assert_eq!(leaves, tree.leaves());
80///
81/// // generate a proof
82/// let (leaf, proof) = tree.prove(2).unwrap();
83/// assert_eq!(2, proof.len());
84/// assert_eq!(leaves[2], leaf);
85///
86/// // verify proof
87/// assert!(MerkleTree::<Blake3>::verify(*tree.root(), 2, leaf, &proof).is_ok());
88/// assert!(MerkleTree::<Blake3>::verify(*tree.root(), 1, leaf, &proof).is_err());
89/// ```
90#[derive(Debug)]
91pub struct MerkleTree<H: Hasher> {
92 nodes: Vec<H::Digest>,
93 leaves: Vec<H::Digest>,
94}
95
96/// Merkle tree opening consisting of a leaf value and a Merkle path leading from this leaf
97/// up to the root (excluding the root itself).
98pub type MerkleTreeOpening<H> = (<H as Hasher>::Digest, Vec<<H as Hasher>::Digest>);
99
100// MERKLE TREE IMPLEMENTATION
101// ================================================================================================
102
103impl<H: Hasher> MerkleTree<H> {
104 // CONSTRUCTORS
105 // --------------------------------------------------------------------------------------------
106
107 /// Returns new Merkle tree built from the provide leaves using hash function specified by the
108 /// `H` generic parameter.
109 ///
110 /// When `concurrent` feature is enabled, the tree is built using multiple threads.
111 ///
112 /// # Errors
113 /// Returns an error if:
114 /// * Fewer than two leaves were provided.
115 /// * Number of leaves is not a power of two.
116 pub fn new(leaves: Vec<H::Digest>) -> Result<Self, MerkleTreeError> {
117 if leaves.len() < 2 {
118 return Err(MerkleTreeError::TooFewLeaves(2, leaves.len()));
119 }
120 if !leaves.len().is_power_of_two() {
121 return Err(MerkleTreeError::NumberOfLeavesNotPowerOfTwo(leaves.len()));
122 }
123
124 #[cfg(not(feature = "concurrent"))]
125 let nodes = build_merkle_nodes::<H>(&leaves);
126
127 #[cfg(feature = "concurrent")]
128 let nodes = if leaves.len() <= concurrent::MIN_CONCURRENT_LEAVES {
129 build_merkle_nodes::<H>(&leaves)
130 } else {
131 concurrent::build_merkle_nodes::<H>(&leaves)
132 };
133
134 Ok(MerkleTree { nodes, leaves })
135 }
136
137 /// Forms a MerkleTree from a list of nodes and leaves.
138 ///
139 /// Nodes are supplied as a vector where the root is stored at position 1.
140 ///
141 /// # Errors
142 /// Returns an error if:
143 /// * Fewer than two leaves were provided.
144 /// * Number of leaves is not a power of two.
145 ///
146 /// # Panics
147 /// Panics if nodes doesn't have the same length as leaves.
148 pub fn from_raw_parts(
149 nodes: Vec<H::Digest>,
150 leaves: Vec<H::Digest>,
151 ) -> Result<Self, MerkleTreeError> {
152 if leaves.len() < 2 {
153 return Err(MerkleTreeError::TooFewLeaves(2, leaves.len()));
154 }
155 if !leaves.len().is_power_of_two() {
156 return Err(MerkleTreeError::NumberOfLeavesNotPowerOfTwo(leaves.len()));
157 }
158 assert_eq!(nodes.len(), leaves.len());
159 Ok(MerkleTree { nodes, leaves })
160 }
161
162 // PUBLIC ACCESSORS
163 // --------------------------------------------------------------------------------------------
164
165 /// Returns the root of the tree.
166 pub fn root(&self) -> &H::Digest {
167 &self.nodes[1]
168 }
169
170 /// Returns depth of the tree.
171 ///
172 /// The depth of a tree is zero-based. Thus, a tree with two leaves has depth 1, a tree with
173 /// four leaves has depth 2 etc.
174 pub fn depth(&self) -> usize {
175 self.leaves.len().ilog2() as usize
176 }
177
178 /// Returns leaf nodes of the tree.
179 pub fn leaves(&self) -> &[H::Digest] {
180 &self.leaves
181 }
182
183 // PROVING METHODS
184 // --------------------------------------------------------------------------------------------
185
186 /// Returns a Merkle proof to a leaf at the specified `index`.
187 ///
188 /// The leaf itself will be the first element of the returned tuple.
189 ///
190 /// # Errors
191 /// Returns an error if the specified index is greater than or equal to the number of leaves
192 /// in the tree.
193 pub fn prove(&self, index: usize) -> Result<MerkleTreeOpening<H>, MerkleTreeError> {
194 if index >= self.leaves.len() {
195 return Err(MerkleTreeError::LeafIndexOutOfBounds(self.leaves.len(), index));
196 }
197 let leaf = self.leaves[index];
198 let mut proof = vec![self.leaves[index ^ 1]];
199
200 let mut index = (index + self.nodes.len()) >> 1;
201 while index > 1 {
202 proof.push(self.nodes[index ^ 1]);
203 index >>= 1;
204 }
205
206 Ok((leaf, proof))
207 }
208
209 /// Computes Merkle proofs for the provided indexes, compresses the proofs into a single batch
210 /// and returns the batch proof alongside the leaves at the provided indexes.
211 ///
212 /// # Errors
213 /// Returns an error if:
214 /// * No indexes were provided (i.e., `indexes` is an empty slice).
215 /// * Any of the provided indexes are greater than or equal to the number of leaves in the tree.
216 /// * List of indexes contains duplicates.
217 pub fn prove_batch(
218 &self,
219 indexes: &[usize],
220 ) -> Result<(Vec<H::Digest>, BatchMerkleProof<H>), MerkleTreeError> {
221 if indexes.is_empty() {
222 return Err(MerkleTreeError::TooFewLeafIndexes);
223 }
224
225 let index_map = map_indexes(indexes, self.depth())?;
226 let indexes = normalize_indexes(indexes);
227 let mut leaves = vec![H::Digest::default(); index_map.len()];
228 let mut nodes: Vec<Vec<H::Digest>> = Vec::with_capacity(indexes.len());
229
230 // populate the proof with leaf node values
231 let n = self.leaves.len();
232 let mut next_indexes: Vec<usize> = Vec::new();
233 for index in indexes {
234 let missing: Vec<H::Digest> = (index..index + 2)
235 .flat_map(|i| {
236 let v = self.leaves[i];
237 if let Some(idx) = index_map.get(&i) {
238 leaves[*idx] = v;
239 None
240 } else {
241 Some(v)
242 }
243 })
244 .collect();
245 nodes.push(missing);
246
247 next_indexes.push((index + n) >> 1);
248 }
249
250 // add required internal nodes to the proof, skipping redundancies
251 for _ in 1..self.depth() {
252 let indexes = next_indexes.clone();
253 next_indexes.truncate(0);
254
255 let mut i = 0;
256 while i < indexes.len() {
257 let sibling_index = indexes[i] ^ 1;
258 if i + 1 < indexes.len() && indexes[i + 1] == sibling_index {
259 i += 1;
260 } else {
261 nodes[i].push(self.nodes[sibling_index]);
262 }
263
264 // add parent index to the set of next indexes
265 next_indexes.push(sibling_index >> 1);
266
267 i += 1;
268 }
269 }
270
271 Ok((leaves, BatchMerkleProof { depth: self.depth() as u8, nodes }))
272 }
273
274 // VERIFICATION METHODS
275 // --------------------------------------------------------------------------------------------
276
277 /// Checks whether the `proof` for the given `leaf` at the specified `index` is valid.
278 ///
279 /// # Errors
280 /// Returns an error if the specified `proof` (which is a Merkle path) does not resolve to the
281 /// specified `root`.
282 pub fn verify(
283 root: H::Digest,
284 index: usize,
285 leaf: H::Digest,
286 proof: &[H::Digest],
287 ) -> Result<(), MerkleTreeError> {
288 let r = index & 1;
289 let mut v = if r == 0 {
290 H::merge(&[leaf, proof[0]])
291 } else {
292 H::merge(&[proof[0], leaf])
293 };
294
295 let mut index = (index + 2usize.pow((proof.len()) as u32)) >> 1;
296 for &p in proof.iter().skip(1) {
297 v = if index & 1 == 0 {
298 H::merge(&[v, p])
299 } else {
300 H::merge(&[p, v])
301 };
302 index >>= 1;
303 }
304
305 if v != root {
306 return Err(MerkleTreeError::InvalidProof);
307 }
308 Ok(())
309 }
310
311 /// Checks whether the batch `proof` contains Merkle proofs resolving to `root` for
312 /// the provided `leaves` at the specified `indexes`.
313 ///
314 /// # Errors
315 /// Returns an error if:
316 /// * No indexes were provided (i.e., `indexes` is an empty slice).
317 /// * Any of the specified `indexes` is greater than or equal to the number of leaves in the
318 /// tree from which the batch proof was generated.
319 /// * List of indexes contains duplicates.
320 /// * Any of the proofs in the batch proof does not resolve to the specified `root`.
321 pub fn verify_batch(
322 root: &H::Digest,
323 indexes: &[usize],
324 leaves: &[H::Digest],
325 proof: &BatchMerkleProof<H>,
326 ) -> Result<(), MerkleTreeError> {
327 if *root != proof.get_root(indexes, leaves)? {
328 return Err(MerkleTreeError::InvalidProof);
329 }
330 Ok(())
331 }
332}
333
334// HELPER FUNCTIONS
335// ================================================================================================
336
337/// Returns the internal nodes of a Merkle tree defined by the specified leaves.
338///
339/// The internal nodes are turned as a vector where the root is stored at position 1, its children
340/// are stored at positions 2, 3, their children are stored at positions 4, 5, 6, 7 etc.
341///
342/// This function is exposed primarily for benchmarking purposes. It is not intended to be used
343/// directly by the end users of the crate.
344pub fn build_merkle_nodes<H: Hasher>(leaves: &[H::Digest]) -> Vec<H::Digest> {
345 let n = leaves.len() / 2;
346
347 // create un-initialized array to hold all intermediate nodes
348 let mut nodes = unsafe { utils::uninit_vector::<H::Digest>(2 * n) };
349 nodes[0] = H::Digest::default();
350
351 // re-interpret leaves as an array of two leaves fused together
352 let two_leaves = unsafe { slice::from_raw_parts(leaves.as_ptr() as *const [H::Digest; 2], n) };
353
354 // build first row of internal nodes (parents of leaves)
355 for (i, j) in (0..n).zip(n..nodes.len()) {
356 nodes[j] = H::merge(&two_leaves[i]);
357 }
358
359 // re-interpret nodes as an array of two nodes fused together
360 let two_nodes = unsafe { slice::from_raw_parts(nodes.as_ptr() as *const [H::Digest; 2], n) };
361
362 // calculate all other tree nodes
363 for i in (1..n).rev() {
364 nodes[i] = H::merge(&two_nodes[i]);
365 }
366
367 nodes
368}
369
370fn map_indexes(
371 indexes: &[usize],
372 tree_depth: usize,
373) -> Result<BTreeMap<usize, usize>, MerkleTreeError> {
374 let num_leaves = 2usize.pow(tree_depth as u32);
375 let mut map = BTreeMap::new();
376 for (i, index) in indexes.iter().cloned().enumerate() {
377 map.insert(index, i);
378 if index >= num_leaves {
379 return Err(MerkleTreeError::LeafIndexOutOfBounds(num_leaves, index));
380 }
381 }
382
383 if indexes.len() != map.len() {
384 return Err(MerkleTreeError::DuplicateLeafIndex);
385 }
386
387 Ok(map)
388}
389
390fn normalize_indexes(indexes: &[usize]) -> Vec<usize> {
391 let mut set = BTreeSet::new();
392 for &index in indexes {
393 set.insert(index - (index & 1));
394 }
395 set.into_iter().collect()
396}
397
398// VECTOR COMMITMENT IMPLEMENTATION
399// ================================================================================================
400
401impl<H: Hasher> VectorCommitment<H> for MerkleTree<H> {
402 type Options = ();
403
404 type Proof = Vec<H::Digest>;
405
406 type MultiProof = BatchMerkleProof<H>;
407
408 type Error = MerkleTreeError;
409
410 fn with_options(items: Vec<H::Digest>, _options: Self::Options) -> Result<Self, Self::Error> {
411 MerkleTree::new(items)
412 }
413
414 fn commitment(&self) -> H::Digest {
415 *self.root()
416 }
417
418 fn domain_len(&self) -> usize {
419 1 << self.depth()
420 }
421
422 fn get_proof_domain_len(proof: &Self::Proof) -> usize {
423 1 << proof.len()
424 }
425
426 fn get_multiproof_domain_len(proof: &Self::MultiProof) -> usize {
427 1 << proof.depth
428 }
429
430 fn open(&self, index: usize) -> Result<(H::Digest, Self::Proof), Self::Error> {
431 self.prove(index)
432 }
433
434 fn open_many(
435 &self,
436 indexes: &[usize],
437 ) -> Result<(Vec<H::Digest>, Self::MultiProof), Self::Error> {
438 self.prove_batch(indexes)
439 }
440
441 fn verify(
442 commitment: H::Digest,
443 index: usize,
444 item: H::Digest,
445 proof: &Self::Proof,
446 ) -> Result<(), Self::Error> {
447 MerkleTree::<H>::verify(commitment, index, item, proof)
448 }
449
450 fn verify_many(
451 commitment: H::Digest,
452 indexes: &[usize],
453 items: &[H::Digest],
454 proof: &Self::MultiProof,
455 ) -> Result<(), Self::Error> {
456 MerkleTree::<H>::verify_batch(&commitment, indexes, items, proof)
457 }
458}