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(true) if the proof is accepted, Ok(false) if not. Err()
218 /// if the proof is not well structured, E.g. not for this merkle tree.
219 fn verify(
220 commitment: impl Borrow<Self::Commitment>,
221 pos: impl Borrow<Self::Index>,
222 element: impl Borrow<Self::Element>,
223 proof: impl Borrow<Self::MembershipProof>,
224 ) -> Result<VerificationResult, MerkleTreeError>;
225
226 // fn batch_lookup(&self, pos: impl Iterator<Item = usize>) -> LookupResult<(),
227 // Self::BatchProof>; fn batch_verify(
228 // &self,
229 // pos: impl Iterator<Item = usize>,
230 // proof: impl Borrow<Self::BatchProof>,
231 // ) -> Result<(), MerkleTreeError>;
232
233 /// Return an iterator that iterates through all element that are not
234 /// forgotten
235 fn iter(&'_ self) -> MerkleTreeIter<'_, Self::Element, Self::Index, Self::NodeValue>;
236}
237
238/// Merkle tree that allows insertion at back. Abstracted as a commitment for
239/// append-only vector.
240pub trait AppendableMerkleTreeScheme: MerkleTreeScheme<Index = u64> {
241 /// Insert a new value at the leftmost available slot
242 /// * `elem` - element to insert in the tree
243 /// * `returns` - Ok(()) if successful
244 fn push(&mut self, elem: impl Borrow<Self::Element>) -> Result<(), MerkleTreeError>;
245
246 /// Insert a list of new values at the leftmost available slots
247 /// * `elems` - elements to insert
248 /// * `returns` - Ok(()) if successful. If there are too many elements,
249 /// insertions will be performed until the merkle tree is full, and will
250 /// return an Err().
251 fn extend(
252 &mut self,
253 elems: impl IntoIterator<Item = impl Borrow<Self::Element>>,
254 ) -> Result<(), MerkleTreeError> {
255 for elem in elems {
256 self.push(elem)?;
257 }
258 Ok(())
259 }
260}
261
262/// A universal merkle tree is abstracted as a random-access array or a
263/// key-value map. It allows manipulation at any given position, and has ability
264/// to generate/verify a non-membership proof.
265pub trait UniversalMerkleTreeScheme: MerkleTreeScheme {
266 /// Non membership proof for a given index
267 type NonMembershipProof;
268 /// Batch non membership proof
269 type BatchNonMembershipProof;
270
271 /// Update the leaf value at a given position
272 /// * `pos` - zero-based index of the leaf in the tree
273 /// * `elem` - newly updated element
274 /// * `returns` - Err() if any error occurs internally or the given leaf is
275 /// not in memory. Ok(result) if the update is success.
276 fn update(
277 &mut self,
278 pos: impl Borrow<Self::Index>,
279 elem: impl Borrow<Self::Element>,
280 ) -> Result<LookupResult<Self::Element, (), ()>, MerkleTreeError> {
281 self.update_with(pos, |_| Some(elem.borrow().clone()))
282 }
283
284 /// Remove a leaf at the given position
285 /// * `pos` - zero-based index of the leaf in the tree
286 /// * `returns` - Err() if any error occurs internally. Ok(result) if the
287 /// update is success or the given leaf is not in memory.
288 fn remove(
289 &mut self,
290 pos: impl Borrow<Self::Index>,
291 ) -> Result<LookupResult<Self::Element, (), ()>, MerkleTreeError> {
292 self.update_with(pos, |_| None)
293 }
294
295 /// Apply an update function `f` at a given position
296 /// * `pos` - zero-based index of the leaf in the tree
297 /// * `f` - the update function, `None` means the given leaf doesn't exist
298 /// or should be removed.
299 /// * `returns` - Err() if any error occurs internally. Ok(result) if the
300 /// update is success or the given leaf is not in memory.
301 ///
302 /// # Example
303 /// ```ignore
304 /// merkle_tree.update_with(account, |balance| {
305 /// Some(balance.cloned().unwrap_or_default().add(amount))
306 /// });
307 /// ```
308 fn update_with<F>(
309 &mut self,
310 pos: impl Borrow<Self::Index>,
311 f: F,
312 ) -> Result<LookupResult<Self::Element, (), ()>, MerkleTreeError>
313 where
314 F: FnOnce(Option<&Self::Element>) -> Option<Self::Element>;
315
316 /// Returns the leaf value given a position
317 /// * `pos` - zero-based index of the leaf in the tree
318 /// * `returns` - Leaf value at the position along with a proof.
319 /// LookupResult::EmptyLeaf(p) if the leaf position is empty along with a
320 /// proof p. LookupResult::NotInMemory if the leaf position has been
321 /// forgotten.
322 fn universal_lookup(
323 &self,
324 pos: impl Borrow<Self::Index>,
325 ) -> LookupResult<&Self::Element, Self::MembershipProof, Self::NonMembershipProof>;
326
327 /// Verify an index is not in this merkle tree
328 /// * `pos` - zero-based index of the leaf in the tree
329 /// * `proof` - a merkle tree proof
330 /// * `returns` - Ok(true) if the proof is accepted, Ok(false) if not. Err()
331 /// if the proof is not well structured, E.g. not for this merkle tree.
332 fn non_membership_verify(
333 commitment: impl Borrow<Self::Commitment>,
334 pos: impl Borrow<Self::Index>,
335 proof: impl Borrow<Self::NonMembershipProof>,
336 ) -> Result<VerificationResult, MerkleTreeError>;
337 // TODO(Chengyu): non-membership proof interfaces
338}
339
340/// Merkle tree that allows forget/remember elements from the memory
341pub trait ForgetableMerkleTreeScheme: MerkleTreeScheme {
342 /// Trim the leaf at position `i` from memory, if present.
343 /// Should not trim if position `i` is the last inserted leaf position.
344 /// Return is identical to result if `get_leaf(pos)` were called before this
345 /// call.
346 fn forget(
347 &mut self,
348 pos: impl Borrow<Self::Index>,
349 ) -> LookupResult<Self::Element, Self::MembershipProof, ()>;
350
351 /// "Re-insert" a leaf into the tree using its proof.
352 /// Returns Ok(()) if insertion is successful, or Err(err) if the
353 /// proof disagrees with the merkle tree
354 fn remember(
355 &mut self,
356 pos: impl Borrow<Self::Index>,
357 element: impl Borrow<Self::Element>,
358 proof: impl Borrow<Self::MembershipProof>,
359 ) -> Result<(), MerkleTreeError>;
360
361 /// Rebuild a merkle tree from a commitment.
362 /// Return a tree which is entirely forgotten.
363 fn from_commitment(
364 commitment: impl Borrow<Self::Commitment>,
365 height: usize,
366 num_leaves: u64,
367 ) -> Self;
368}
369
370/// Universal Merkle tree that allows forget/remember elements from the memory
371pub trait ForgetableUniversalMerkleTreeScheme:
372 ForgetableMerkleTreeScheme + UniversalMerkleTreeScheme
373{
374 /// Trim the leaf at position `pos` from memory.
375 ///
376 /// This is similar to [forget](ForgetableMerkleTreeScheme::forget), but it
377 /// may prune even an empty sub-tree at `pos` and will return a
378 /// non-membership proof for the pruned position if it does so. Note
379 /// that an implementation may choose _not_ to prune an empty sub-tree, as
380 /// it may be more efficient to represent an empty sub-tree than a
381 /// forgotten one. In this case,
382 /// [universal_lookup](UniversalMerkleTreeScheme::universal_lookup) may
383 /// return _either_ [LookupResult::NotInMemory] or
384 /// [LookupResult::NotFound] after a successful call to
385 /// [universal_forget](Self::universal_forget). In any case, if this
386 /// function is called for a `pos` which is in memory but not in the
387 /// tree, it will return a non-membership proof.
388 ///
389 /// The return value is the same as if
390 /// [universal_lookup](UniversalMerkleTreeScheme::universal_lookup) were
391 /// called before this call.
392 fn universal_forget(
393 &mut self,
394 pos: Self::Index,
395 ) -> LookupResult<Self::Element, Self::MembershipProof, Self::NonMembershipProof>;
396
397 /// "Re-insert" an empty leaf into the tree using its proof.
398 ///
399 /// Returns `Ok(())` if insertion is successful, or `Err(err)` if the proof
400 /// disagrees with the merkle tree
401 fn non_membership_remember(
402 &mut self,
403 pos: Self::Index,
404 proof: impl Borrow<Self::NonMembershipProof>,
405 ) -> Result<(), MerkleTreeError>;
406}
407
408/// A universal merkle tree that allows non destructive updates.
409/// A non destructive update doesn't directly modify the existing content, it
410/// creates a new copy about the update so that people could access both the old
411/// version and the new.
412pub trait PersistentUniversalMerkleTreeScheme: UniversalMerkleTreeScheme {
413 /// A non destructive update interface, check
414 /// [PersistentUniversalMerkleTreeScheme] and
415 /// [UniversalMerkleTreeScheme::update].
416 fn persistent_update(
417 &self,
418 pos: impl Borrow<Self::Index>,
419 elem: impl Borrow<Self::Element>,
420 ) -> Result<Self, MerkleTreeError> {
421 self.persistent_update_with(pos, |_| Some(elem.borrow().clone()))
422 }
423
424 /// A persistent remove interface, check
425 /// [PersistentUniversalMerkleTreeScheme] and
426 /// [UniversalMerkleTreeScheme::remove].
427 fn persistent_remove(&self, pos: Self::Index) -> Result<Self, MerkleTreeError> {
428 self.persistent_update_with(pos, |_| None)
429 }
430
431 /// A persistent update_with interface, check
432 /// [PersistentUniversalMerkleTreeScheme] and
433 /// [UniversalMerkleTreeScheme::update_with].
434 fn persistent_update_with<F>(
435 &self,
436 pos: impl Borrow<Self::Index>,
437 f: F,
438 ) -> Result<Self, MerkleTreeError>
439 where
440 F: FnOnce(Option<&Self::Element>) -> Option<Self::Element>;
441}