light_indexed_merkle_tree/
reference.rs1use std::marker::PhantomData;
2
3use light_bounded_vec::{BoundedVec, BoundedVecError};
4use light_concurrent_merkle_tree::light_hasher::{errors::HasherError, Hasher};
5use light_merkle_tree_reference::{MerkleTree, ReferenceMerkleTreeError};
6use light_utils::bigint::bigint_to_be_bytes_array;
7use num_bigint::BigUint;
8use num_traits::{CheckedAdd, CheckedSub, Num, ToBytes, Unsigned};
9use thiserror::Error;
10
11use crate::{
12 array::{IndexedArray, IndexedElement},
13 errors::IndexedMerkleTreeError,
14 HIGHEST_ADDRESS_PLUS_ONE,
15};
16
17#[derive(Debug, Error)]
18pub enum IndexedReferenceMerkleTreeError {
19 #[error(transparent)]
20 Indexed(#[from] IndexedMerkleTreeError),
21 #[error(transparent)]
22 Reference(#[from] ReferenceMerkleTreeError),
23 #[error(transparent)]
24 Hasher(#[from] HasherError),
25}
26
27#[derive(Debug, Clone)]
28#[repr(C)]
29pub struct IndexedMerkleTree<H, I>
30where
31 H: Hasher,
32 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
33{
34 pub merkle_tree: MerkleTree<H>,
35 _index: PhantomData<I>,
36}
37
38impl<H, I> IndexedMerkleTree<H, I>
39where
40 H: Hasher,
41 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
42 usize: From<I>,
43{
44 pub fn new(
45 height: usize,
46 canopy_depth: usize,
47 ) -> Result<Self, IndexedReferenceMerkleTreeError> {
48 let mut merkle_tree = MerkleTree::new(height, canopy_depth);
49
50 merkle_tree.append(&H::zero_indexed_leaf())?;
55
56 Ok(Self {
57 merkle_tree,
58 _index: PhantomData,
59 })
60 }
61
62 pub fn init(&mut self) -> Result<(), IndexedReferenceMerkleTreeError> {
66 let mut indexed_array = IndexedArray::<H, I>::default();
67 let init_value = BigUint::from_str_radix(HIGHEST_ADDRESS_PLUS_ONE, 10).unwrap();
68 let nullifier_bundle = indexed_array.append(&init_value)?;
69 let new_low_leaf = nullifier_bundle
70 .new_low_element
71 .hash::<H>(&nullifier_bundle.new_element.value)?;
72
73 self.merkle_tree.update(&new_low_leaf, 0)?;
74 let new_leaf = nullifier_bundle
75 .new_element
76 .hash::<H>(&nullifier_bundle.new_element_next_value)?;
77 self.merkle_tree.append(&new_leaf)?;
78 Ok(())
79 }
80
81 pub fn get_path_of_leaf(
82 &self,
83 index: usize,
84 full: bool,
85 ) -> Result<BoundedVec<[u8; 32]>, BoundedVecError> {
86 self.merkle_tree.get_path_of_leaf(index, full)
87 }
88
89 pub fn get_proof_of_leaf(
90 &self,
91 index: usize,
92 full: bool,
93 ) -> Result<BoundedVec<[u8; 32]>, BoundedVecError> {
94 self.merkle_tree.get_proof_of_leaf(index, full)
95 }
96
97 pub fn root(&self) -> [u8; 32] {
98 self.merkle_tree.root()
99 }
100
101 pub fn update(
103 &mut self,
104 new_low_element: &IndexedElement<I>,
105 new_element: &IndexedElement<I>,
106 new_element_next_value: &BigUint,
107 ) -> Result<(), IndexedReferenceMerkleTreeError> {
108 let new_low_leaf = new_low_element.hash::<H>(&new_element.value)?;
110 self.merkle_tree
111 .update(&new_low_leaf, usize::from(new_low_element.index))?;
112
113 let new_leaf = new_element.hash::<H>(new_element_next_value)?;
115 self.merkle_tree.append(&new_leaf)?;
116
117 Ok(())
118 }
119
120 pub fn append(
122 &mut self,
123 value: &BigUint,
124 indexed_array: &mut IndexedArray<H, I>,
125 ) -> Result<(), IndexedReferenceMerkleTreeError> {
126 let nullifier_bundle = indexed_array.append(value).unwrap();
127 self.update(
128 &nullifier_bundle.new_low_element,
129 &nullifier_bundle.new_element,
130 &nullifier_bundle.new_element_next_value,
131 )?;
132
133 Ok(())
134 }
135
136 pub fn get_non_inclusion_proof(
137 &self,
138 value: &BigUint,
139 indexed_array: &IndexedArray<H, I>,
140 ) -> Result<NonInclusionProof, IndexedReferenceMerkleTreeError> {
141 let (low_element, _next_value) = indexed_array.find_low_element_for_nonexistent(value)?;
142 let merkle_proof = self
143 .get_proof_of_leaf(usize::from(low_element.index), true)
144 .unwrap();
145 let higher_range_value = indexed_array
146 .get(low_element.next_index())
147 .unwrap()
148 .value
149 .clone();
150 Ok(NonInclusionProof {
151 root: self.root(),
152 value: bigint_to_be_bytes_array::<32>(value).unwrap(),
153 leaf_lower_range_value: bigint_to_be_bytes_array::<32>(&low_element.value).unwrap(),
154 leaf_higher_range_value: bigint_to_be_bytes_array::<32>(&higher_range_value).unwrap(),
155 leaf_index: low_element.index.into(),
156 next_index: low_element.next_index(),
157 merkle_proof,
158 })
159 }
160
161 pub fn verify_non_inclusion_proof(
162 &self,
163 proof: &NonInclusionProof,
164 ) -> Result<(), IndexedReferenceMerkleTreeError> {
165 let array_element = IndexedElement::<usize> {
166 value: BigUint::from_bytes_be(&proof.value),
167 index: proof.leaf_index,
168 next_index: proof.next_index,
169 };
170 let leaf_hash =
171 array_element.hash::<H>(&BigUint::from_bytes_be(&proof.leaf_higher_range_value))?;
172 self.merkle_tree
173 .verify(&leaf_hash, &proof.merkle_proof, proof.leaf_index)
174 .unwrap();
175 Ok(())
176 }
177}
178
179#[derive(Debug)]
184pub struct NonInclusionProof {
185 pub root: [u8; 32],
186 pub value: [u8; 32],
187 pub leaf_lower_range_value: [u8; 32],
188 pub leaf_higher_range_value: [u8; 32],
189 pub leaf_index: usize,
190 pub next_index: usize,
191 pub merkle_proof: BoundedVec<[u8; 32]>,
192}