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