jf_merkle_tree/
lib.rs

1// Copyright (c) 2022 Espresso Systems (espressosys.com)
2// This file is part of the Jellyfish library.
3
4// You should have received a copy of the MIT License
5// along with the Jellyfish library. If not, see <https://mit-license.org/>.
6
7//! Merkle Tree traits and implementations
8
9#![cfg_attr(not(feature = "std"), no_std)]
10#![deny(missing_docs)]
11#[cfg(test)]
12extern crate std;
13
14#[cfg(any(not(feature = "std"), target_has_atomic = "ptr"))]
15#[doc(hidden)]
16extern crate alloc;
17
18pub mod append_only;
19pub mod errors;
20pub mod examples;
21#[cfg(feature = "gadgets")]
22pub mod gadgets;
23pub mod hasher;
24pub mod light_weight;
25pub mod macros;
26pub mod universal_merkle_tree;
27
28pub(crate) mod internal;
29
30pub mod prelude;
31pub use crate::errors::MerkleTreeError;
32
33use self::internal::MerkleTreeIter;
34use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
35use ark_std::{borrow::Borrow, fmt::Debug, hash::Hash, vec, vec::Vec};
36use num_bigint::BigUint;
37use num_traits::ToPrimitive;
38use serde::{Deserialize, Serialize};
39
40/// Glorified bool type
41pub(crate) type VerificationResult = Result<(), ()>;
42/// Glorified true
43pub const SUCCESS: VerificationResult = Ok(());
44/// Glorified false
45pub const FAIL: VerificationResult = Err(());
46
47#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
48/// The result of querying at an index in the tree
49/// Typically, F for element type, P for membership proof type and N for
50/// non-membership proof type
51pub enum LookupResult<F, P, N> {
52    /// The value at the given index, and a proof of validity
53    Ok(F, P),
54    /// The index is valid but we do not have the leaf in memory
55    NotInMemory,
56    /// The index is outside the occupied range in the tree, and a
57    /// non-membership proof
58    NotFound(N),
59}
60
61impl<F, P, N> LookupResult<F, P, N> {
62    /// Assert the lookup result is Ok. Return a tuple of element and membership
63    /// proof.
64    pub fn expect_ok(self) -> Result<(F, P), MerkleTreeError> {
65        match self {
66            LookupResult::Ok(x, proof) => Ok((x, proof)),
67            LookupResult::NotInMemory => Err(MerkleTreeError::ForgottenLeaf),
68            LookupResult::NotFound(_) => Err(MerkleTreeError::NotFound),
69        }
70    }
71
72    /// Assert the lookup result is NotFound. Return a non-membership proof.
73    pub fn expect_not_found(self) -> Result<N, MerkleTreeError> {
74        match self {
75            LookupResult::NotFound(n) => Ok(n),
76            LookupResult::Ok(..) => Err(MerkleTreeError::ExistingLeaf),
77            LookupResult::NotInMemory => Err(MerkleTreeError::ForgottenLeaf),
78        }
79    }
80
81    /// Assert the lookup result is NotInMemory.
82    pub fn expect_not_in_memory(self) -> Result<(), MerkleTreeError> {
83        match self {
84            LookupResult::NotInMemory => Ok(()),
85            LookupResult::Ok(..) => Err(MerkleTreeError::ExistingLeaf),
86            LookupResult::NotFound(..) => Err(MerkleTreeError::NotFound),
87        }
88    }
89}
90
91/// An element of a Merkle tree.
92pub trait Element: Clone + Eq + PartialEq + Hash {}
93impl<T: Clone + Eq + PartialEq + Hash> Element for T {}
94
95/// An index type of a leaf in a Merkle tree.
96pub trait Index: Debug + Eq + PartialEq + Hash + Ord + PartialOrd + Clone {}
97impl<T: Debug + Eq + PartialEq + Hash + Ord + PartialOrd + Clone> Index for T {}
98
99/// An internal node value type in a Merkle tree.
100pub trait NodeValue:
101    Default + Eq + PartialEq + Hash + Copy + Clone + Debug + CanonicalSerialize + CanonicalDeserialize
102{
103}
104impl<T> NodeValue for T where
105    T: Default
106        + Eq
107        + PartialEq
108        + Hash
109        + Copy
110        + Clone
111        + Debug
112        + CanonicalSerialize
113        + CanonicalDeserialize
114{
115}
116
117/// Merkle tree hash function
118/// WARN: it's important to domain separate the two digest functions. Otherwise,
119/// you may suffer from the length extension attack.
120pub trait DigestAlgorithm<E, I, T>
121where
122    E: Element,
123    I: Index,
124    T: NodeValue,
125{
126    /// Digest a list of values
127    fn digest(data: &[T]) -> Result<T, MerkleTreeError>;
128
129    /// Digest an indexed element
130    fn digest_leaf(pos: &I, elem: &E) -> Result<T, MerkleTreeError>;
131}
132
133/// A trait for Merkle tree index type.
134pub trait ToTraversalPath<const ARITY: usize> {
135    /// Convert the given index to a vector of branch indices given tree height
136    /// and ARITY.
137    fn to_traversal_path(&self, height: usize) -> Vec<usize>;
138}
139
140impl_to_traversal_path_primitives!(usize);
141impl_to_traversal_path_primitives!(u8);
142impl_to_traversal_path_primitives!(u16);
143impl_to_traversal_path_primitives!(u32);
144impl_to_traversal_path_primitives!(u64);
145impl_to_traversal_path_biguint!(u128);
146impl_to_traversal_path_biguint!(BigUint);
147impl_to_traversal_path_biguint!(ark_bn254::Fr);
148impl_to_traversal_path_biguint!(ark_bls12_377::Fr);
149impl_to_traversal_path_biguint!(ark_bls12_381::Fr);
150impl_to_traversal_path_biguint!(ark_bn254::Fq);
151impl_to_traversal_path_biguint!(ark_bls12_377::Fq);
152impl_to_traversal_path_biguint!(ark_bls12_381::Fq);
153
154/// Trait for a Merkle proof
155pub trait MerkleProof<T: NodeValue>:
156    Eq
157    + PartialEq
158    + Hash
159    + Clone
160    + CanonicalSerialize
161    + CanonicalDeserialize
162    + Serialize
163    + for<'a> Deserialize<'a>
164{
165    /// Expected height of the Merkle tree.
166    fn height(&self) -> usize;
167
168    /// Return all values of siblings of this Merkle path
169    fn path_values(&self) -> &[Vec<T>];
170}
171
172/// Basic functionalities for a merkle tree implementation. Abstracted as an
173/// accumulator for fixed-length array. Supports generating membership proof at
174/// a given position and verify a membership proof.
175pub trait MerkleTreeScheme: Sized {
176    /// Merkle tree element type
177    type Element: Element;
178    /// Index type for this merkle tree
179    type Index: Index;
180    /// Internal and root node value
181    type NodeValue: NodeValue;
182    /// Merkle proof
183    type MembershipProof: MerkleProof<Self::NodeValue>;
184    /// Batch proof
185    type BatchMembershipProof: Clone;
186    /// Merkle tree commitment
187    type Commitment: NodeValue;
188
189    /// Tree ARITY
190    const ARITY: usize;
191
192    /// Return the height of this merkle tree
193    fn height(&self) -> usize;
194    /// Return the maximum allowed number leaves
195    fn capacity(&self) -> BigUint;
196    /// Return the current number of leaves
197    fn num_leaves(&self) -> u64;
198
199    /// Return a merkle commitment
200    fn commitment(&self) -> Self::Commitment;
201
202    /// Returns the leaf value given a position
203    /// * `pos` - zero-based index of the leaf in the tree
204    /// * `returns` - Leaf value at the position along with a proof.
205    ///   LookupResult::EmptyLeaf if the leaf position is empty or invalid,
206    ///   LookupResult::NotInMemory if the leaf position has been forgotten.
207    fn lookup(
208        &self,
209        pos: impl Borrow<Self::Index>,
210    ) -> LookupResult<&Self::Element, Self::MembershipProof, ()>;
211
212    /// Verify an element is a leaf of a Merkle tree given the proof
213    /// * `commitment` - a merkle tree commitment
214    /// * `pos` - zero-based index of the leaf in the tree
215    /// * `element` - the leaf value
216    /// * `proof` - a membership proof for `element` at given `pos`
217    /// * `returns` - Ok(SUCCESS) if the proof is accepted, Ok(FAIL) if not.
218    ///   Err() if the proof is not well structured, E.g. not for this merkle
219    ///   tree.
220    fn verify(
221        commitment: impl Borrow<Self::Commitment>,
222        pos: impl Borrow<Self::Index>,
223        element: impl Borrow<Self::Element>,
224        proof: impl Borrow<Self::MembershipProof>,
225    ) -> Result<VerificationResult, MerkleTreeError>;
226
227    // fn batch_lookup(&self, pos: impl Iterator<Item = usize>) -> LookupResult<(),
228    // Self::BatchProof>; fn batch_verify(
229    //     &self,
230    //     pos: impl Iterator<Item = usize>,
231    //     proof: impl Borrow<Self::BatchProof>,
232    // ) -> Result<(), MerkleTreeError>;
233
234    /// Return an iterator that iterates through all element that are not
235    /// forgotten
236    fn iter(&'_ self) -> MerkleTreeIter<'_, Self::Element, Self::Index, Self::NodeValue>;
237}
238
239/// Merkle tree that supports generating range proofs
240pub trait RangeProofMerkleTreeScheme: MerkleTreeScheme {
241    /// Range proof for a given range
242    type RangeMembershipProof;
243
244    /// Generate a range proof for leaves in [start, end], inclusive.
245    /// * `start` - zero-based start index of the range (inclusive)
246    /// * `end` - zero-based end index of the range (inclusive)
247    /// * `returns` - Indexed leaf values in the range along with a range
248    ///   membership proof.
249    ///
250    /// NOTE: this interface will return `NotInMemory` or `NotFound` if any
251    /// of the leaves in the range are not in memory or not found.
252    #[allow(clippy::type_complexity)]
253    fn range_lookup(
254        &self,
255        start: impl Borrow<Self::Index>,
256        end: impl Borrow<Self::Index>,
257    ) -> LookupResult<(Vec<Self::Index>, Vec<Self::Element>), Self::RangeMembershipProof, ()>;
258
259    /// Verify a range proof for leaves in [start, end], inclusive.
260    /// * `commitment` - a merkle tree commitment
261    /// * `indices` - zero-based indices of the leaves in the tree
262    /// * `elements` - the leaf values in the range
263    /// * `proof` - a range membership proof for the given range
264    /// * `returns` - Ok(SUCCESS) if the proof is accepted, Ok(FAIL) if not.
265    ///   Err() if the proof is not well structured, E.g. not for this merkle
266    ///   tree.
267    ///
268    /// NOTE: all indices are needed here because we cannot generate them from
269    /// [start, end] under the current Index trait bound.
270    fn verify_range_proof(
271        commitment: impl Borrow<Self::Commitment>,
272        indices: &[impl Borrow<Self::Index>],
273        elements: &[impl Borrow<Self::Element>],
274        proof: impl Borrow<Self::RangeMembershipProof>,
275    ) -> Result<VerificationResult, MerkleTreeError>;
276}
277
278/// Merkle tree that allows insertion at back. Abstracted as a commitment for
279/// append-only vector.
280pub trait AppendableMerkleTreeScheme: MerkleTreeScheme<Index = u64> {
281    /// Insert a new value at the leftmost available slot
282    /// * `elem` - element to insert in the tree
283    /// * `returns` - Ok(()) if successful
284    fn push(&mut self, elem: impl Borrow<Self::Element>) -> Result<(), MerkleTreeError>;
285
286    /// Insert a list of new values at the leftmost available slots
287    /// * `elems` - elements to insert
288    /// * `returns` - Ok(()) if successful. If there are too many elements,
289    ///   insertions will be performed until the merkle tree is full, and will
290    ///   return an Err().
291    fn extend(
292        &mut self,
293        elems: impl IntoIterator<Item = impl Borrow<Self::Element>>,
294    ) -> Result<(), MerkleTreeError> {
295        for elem in elems {
296            self.push(elem)?;
297        }
298        Ok(())
299    }
300}
301
302/// A universal merkle tree is abstracted as a random-access array or a
303/// key-value map. It allows manipulation at any given position, and has ability
304/// to generate/verify a non-membership proof.
305pub trait UniversalMerkleTreeScheme: MerkleTreeScheme {
306    /// Non membership proof for a given index
307    type NonMembershipProof;
308    /// Batch non membership proof
309    type BatchNonMembershipProof;
310
311    /// Update the leaf value at a given position
312    /// * `pos` - zero-based index of the leaf in the tree
313    /// * `elem` - newly updated element
314    /// * `returns` - Err() if any error occurs internally or the given leaf is
315    ///   not in memory. Ok(result) if the update is success.
316    fn update(
317        &mut self,
318        pos: impl Borrow<Self::Index>,
319        elem: impl Borrow<Self::Element>,
320    ) -> Result<LookupResult<Self::Element, (), ()>, MerkleTreeError> {
321        self.update_with(pos, |_| Some(elem.borrow().clone()))
322    }
323
324    /// Remove a leaf at the given position
325    /// * `pos` - zero-based index of the leaf in the tree
326    /// * `returns` - Err() if any error occurs internally. Ok(result) if the
327    ///   update is success or the given leaf is not in memory.
328    fn remove(
329        &mut self,
330        pos: impl Borrow<Self::Index>,
331    ) -> Result<LookupResult<Self::Element, (), ()>, MerkleTreeError> {
332        self.update_with(pos, |_| None)
333    }
334
335    /// Apply an update function `f` at a given position
336    /// * `pos` - zero-based index of the leaf in the tree
337    /// * `f` - the update function, `None` means the given leaf doesn't exist
338    ///   or should be removed.
339    /// * `returns` - Err() if any error occurs internally. Ok(result) if the
340    ///   update is success or the given leaf is not in memory.
341    ///
342    /// # Example
343    /// ```ignore
344    /// merkle_tree.update_with(account, |balance| {
345    ///     Some(balance.cloned().unwrap_or_default().add(amount))
346    /// });
347    /// ```
348    fn update_with<F>(
349        &mut self,
350        pos: impl Borrow<Self::Index>,
351        f: F,
352    ) -> Result<LookupResult<Self::Element, (), ()>, MerkleTreeError>
353    where
354        F: FnOnce(Option<&Self::Element>) -> Option<Self::Element>;
355
356    /// Returns the leaf value given a position
357    /// * `pos` - zero-based index of the leaf in the tree
358    /// * `returns` - Leaf value at the position along with a proof.
359    ///   LookupResult::EmptyLeaf(p) if the leaf position is empty along with a
360    ///   proof p. LookupResult::NotInMemory if the leaf position has been
361    ///   forgotten.
362    fn universal_lookup(
363        &self,
364        pos: impl Borrow<Self::Index>,
365    ) -> LookupResult<&Self::Element, Self::MembershipProof, Self::NonMembershipProof>;
366
367    /// Verify an index is not in this merkle tree
368    /// * `pos` - zero-based index of the leaf in the tree
369    /// * `proof` - a merkle tree proof
370    /// * `returns` - Ok(SUCCESS) if the proof is accepted, Ok(FAIL) if not.
371    ///   Err() if the proof is not well structured, E.g. not for this merkle
372    ///   tree.
373    fn non_membership_verify(
374        commitment: impl Borrow<Self::Commitment>,
375        pos: impl Borrow<Self::Index>,
376        proof: impl Borrow<Self::NonMembershipProof>,
377    ) -> Result<VerificationResult, MerkleTreeError>;
378    // TODO(Chengyu): non-membership proof interfaces
379}
380
381/// Merkle tree that allows forget/remember elements from the memory
382pub trait ForgetableMerkleTreeScheme: MerkleTreeScheme {
383    /// Trim the leaf at position `i` from memory, if present.
384    /// Should not trim if position `i` is the last inserted leaf position.
385    /// Return is identical to result if `get_leaf(pos)` were called before this
386    /// call.
387    fn forget(
388        &mut self,
389        pos: impl Borrow<Self::Index>,
390    ) -> LookupResult<Self::Element, Self::MembershipProof, ()>;
391
392    /// "Re-insert" a leaf into the tree using its proof.
393    /// Returns Ok(()) if insertion is successful, or Err(err) if the
394    /// proof disagrees with the merkle tree
395    fn remember(
396        &mut self,
397        pos: impl Borrow<Self::Index>,
398        element: impl Borrow<Self::Element>,
399        proof: impl Borrow<Self::MembershipProof>,
400    ) -> Result<(), MerkleTreeError>;
401
402    /// Rebuild a merkle tree from a commitment.
403    /// Return a tree which is entirely forgotten.
404    fn from_commitment(
405        commitment: impl Borrow<Self::Commitment>,
406        height: usize,
407        num_leaves: u64,
408    ) -> Self;
409}
410
411/// Universal Merkle tree that allows forget/remember elements from the memory
412pub trait ForgetableUniversalMerkleTreeScheme:
413    ForgetableMerkleTreeScheme + UniversalMerkleTreeScheme
414{
415    /// Trim the leaf at position `pos` from memory.
416    ///
417    /// This is similar to [forget](ForgetableMerkleTreeScheme::forget), but it
418    /// may prune even an empty sub-tree at `pos` and will return a
419    /// non-membership proof for the pruned position if it does so. Note
420    /// that an implementation may choose _not_ to prune an empty sub-tree, as
421    /// it may be more efficient to represent an empty sub-tree than a
422    /// forgotten one. In this case,
423    /// [universal_lookup](UniversalMerkleTreeScheme::universal_lookup) may
424    /// return _either_ [LookupResult::NotInMemory] or
425    /// [LookupResult::NotFound] after a successful call to
426    /// [universal_forget](Self::universal_forget). In any case, if this
427    /// function is called for a `pos` which is in memory but not in the
428    /// tree, it will return a non-membership proof.
429    ///
430    /// The return value is the same as if
431    /// [universal_lookup](UniversalMerkleTreeScheme::universal_lookup) were
432    /// called before this call.
433    fn universal_forget(
434        &mut self,
435        pos: Self::Index,
436    ) -> LookupResult<Self::Element, Self::MembershipProof, Self::NonMembershipProof>;
437
438    /// "Re-insert" an empty leaf into the tree using its proof.
439    ///
440    /// Returns `Ok(())` if insertion is successful, or `Err(err)` if the proof
441    /// disagrees with the merkle tree
442    fn non_membership_remember(
443        &mut self,
444        pos: Self::Index,
445        proof: impl Borrow<Self::NonMembershipProof>,
446    ) -> Result<(), MerkleTreeError>;
447}
448
449/// A universal merkle tree that allows non destructive updates.
450/// A non destructive update doesn't directly modify the existing content, it
451/// creates a new copy about the update so that people could access both the old
452/// version and the new.
453pub trait PersistentUniversalMerkleTreeScheme: UniversalMerkleTreeScheme {
454    /// A non destructive update interface, check
455    /// [PersistentUniversalMerkleTreeScheme] and
456    /// [UniversalMerkleTreeScheme::update].
457    fn persistent_update(
458        &self,
459        pos: impl Borrow<Self::Index>,
460        elem: impl Borrow<Self::Element>,
461    ) -> Result<Self, MerkleTreeError> {
462        self.persistent_update_with(pos, |_| Some(elem.borrow().clone()))
463    }
464
465    /// A persistent remove interface, check
466    /// [PersistentUniversalMerkleTreeScheme] and
467    /// [UniversalMerkleTreeScheme::remove].
468    fn persistent_remove(&self, pos: Self::Index) -> Result<Self, MerkleTreeError> {
469        self.persistent_update_with(pos, |_| None)
470    }
471
472    /// A persistent update_with interface, check
473    /// [PersistentUniversalMerkleTreeScheme] and
474    /// [UniversalMerkleTreeScheme::update_with].
475    fn persistent_update_with<F>(
476        &self,
477        pos: impl Borrow<Self::Index>,
478        f: F,
479    ) -> Result<Self, MerkleTreeError>
480    where
481        F: FnOnce(Option<&Self::Element>) -> Option<Self::Element>;
482}