1use super::heap_impl::Heap;
17use super::resource::{Resource, ResourceId};
18use sha2::{Digest, Sha256};
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum Direction {
23 Left,
25 Right,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct ProofStep {
32 pub direction: Direction,
34 pub sibling_hash: [u8; 32],
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct MerkleProof {
43 pub leaf_hash: [u8; 32],
45 pub path: Vec<ProofStep>,
47 pub root: [u8; 32],
49}
50
51impl MerkleProof {
52 pub fn verify(&self) -> bool {
54 let computed_root =
55 self.path
56 .iter()
57 .fold(self.leaf_hash, |current, step| match step.direction {
58 Direction::Left => hash_pair(&step.sibling_hash, ¤t),
59 Direction::Right => hash_pair(¤t, &step.sibling_hash),
60 });
61 computed_root == self.root
62 }
63}
64
65fn hash_pair(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
67 let mut hasher = Sha256::new();
68 hasher.update(left);
69 hasher.update(right);
70 hasher.finalize().into()
71}
72
73fn hash_leaf(rid: &ResourceId, resource: &Resource) -> [u8; 32] {
75 let mut hasher = Sha256::new();
76 hasher.update(rid.hash());
77 hasher.update(resource.to_bytes());
78 hasher.finalize().into()
79}
80
81fn empty_root() -> [u8; 32] {
83 Sha256::digest([]).into()
84}
85
86#[derive(Debug, Clone)]
88pub struct MerkleTree {
89 pub root: [u8; 32],
91 leaves: Vec<[u8; 32]>,
93 levels: Vec<Vec<[u8; 32]>>,
96}
97
98impl MerkleTree {
99 pub fn from_leaves(leaves: Vec<[u8; 32]>) -> Self {
101 if leaves.is_empty() {
102 return Self {
103 root: empty_root(),
104 leaves: Vec::new(),
105 levels: Vec::new(),
106 };
107 }
108
109 let mut levels = vec![leaves.clone()];
110 let mut current_level = leaves.clone();
111
112 while current_level.len() > 1 {
113 if current_level.len() % 2 == 1 {
115 current_level.push(*current_level.last().expect("non-empty after len check"));
117 }
118
119 let next_level: Vec<[u8; 32]> = current_level
121 .chunks(2)
122 .map(|pair| hash_pair(&pair[0], &pair[1]))
123 .collect();
124
125 levels.push(next_level.clone());
126 current_level = next_level;
127 }
128
129 let root = current_level[0];
130
131 Self {
132 root,
133 leaves,
134 levels,
135 }
136 }
137
138 pub fn from_heap(heap: &Heap) -> Self {
140 let leaves: Vec<[u8; 32]> = heap
141 .active_resources()
142 .map(|(rid, resource)| hash_leaf(rid, resource))
143 .collect();
144 Self::from_leaves(leaves)
145 }
146
147 pub fn size(&self) -> usize {
149 self.leaves.len()
150 }
151
152 pub fn prove(&self, index: usize) -> Option<MerkleProof> {
154 if index >= self.leaves.len() {
155 return None;
156 }
157
158 let leaf_hash = self.leaves[index];
159 let mut path = Vec::new();
160 let mut current_index = index;
161
162 for level in &self.levels[..self.levels.len().saturating_sub(1)] {
163 let sibling_index = if current_index % 2 == 0 {
164 current_index + 1
165 } else {
166 current_index - 1
167 };
168
169 let sibling_hash = if sibling_index < level.len() {
171 level[sibling_index]
172 } else {
173 level[current_index]
174 };
175
176 let direction = if current_index % 2 == 0 {
177 Direction::Right
178 } else {
179 Direction::Left
180 };
181
182 path.push(ProofStep {
183 direction,
184 sibling_hash,
185 });
186
187 current_index /= 2;
188 }
189
190 Some(MerkleProof {
191 leaf_hash,
192 path,
193 root: self.root,
194 })
195 }
196}
197
198#[derive(Debug, Clone, PartialEq, Eq)]
200pub struct HeapCommitment {
201 pub resource_root: [u8; 32],
203 pub nullifier_root: [u8; 32],
205 pub counter: u64,
207}
208
209impl HeapCommitment {
210 pub fn from_heap(heap: &Heap) -> Self {
212 let resource_leaves: Vec<[u8; 32]> = heap
213 .active_resources()
214 .map(|(rid, resource)| hash_leaf(rid, resource))
215 .collect();
216 let resource_tree = MerkleTree::from_leaves(resource_leaves);
217
218 let nullifier_leaves: Vec<[u8; 32]> = heap.consumed_ids().map(|rid| rid.hash()).collect();
219 let nullifier_tree = MerkleTree::from_leaves(nullifier_leaves);
220
221 Self {
222 resource_root: resource_tree.root,
223 nullifier_root: nullifier_tree.root,
224 counter: heap.alloc_counter(),
225 }
226 }
227
228 pub fn hash(&self) -> [u8; 32] {
230 let mut hasher = Sha256::new();
231 hasher.update(self.resource_root);
232 hasher.update(self.nullifier_root);
233 hasher.update(self.counter.to_le_bytes());
234 hasher.finalize().into()
235 }
236}
237
238#[cfg(test)]
239mod tests {
240 use super::*;
241
242 #[test]
243 fn test_empty_tree() {
244 let tree = MerkleTree::from_leaves(vec![]);
245 assert_eq!(tree.root, empty_root());
246 assert_eq!(tree.size(), 0);
247 }
248
249 #[test]
250 fn test_single_leaf() {
251 let leaf = Sha256::digest(b"hello").into();
252 let tree = MerkleTree::from_leaves(vec![leaf]);
253 assert_eq!(tree.root, leaf);
254 assert_eq!(tree.size(), 1);
255 }
256
257 #[test]
258 fn test_two_leaves() {
259 let leaf1: [u8; 32] = Sha256::digest(b"hello").into();
260 let leaf2: [u8; 32] = Sha256::digest(b"world").into();
261 let tree = MerkleTree::from_leaves(vec![leaf1, leaf2]);
262
263 let expected_root = hash_pair(&leaf1, &leaf2);
264 assert_eq!(tree.root, expected_root);
265 assert_eq!(tree.size(), 2);
266 }
267
268 #[test]
269 fn test_four_leaves() {
270 let leaves: Vec<[u8; 32]> = (0_u8..4).map(|i| Sha256::digest([i]).into()).collect();
271 let tree = MerkleTree::from_leaves(leaves.clone());
272
273 let h01 = hash_pair(&leaves[0], &leaves[1]);
274 let h23 = hash_pair(&leaves[2], &leaves[3]);
275 let expected_root = hash_pair(&h01, &h23);
276
277 assert_eq!(tree.root, expected_root);
278 assert_eq!(tree.size(), 4);
279 }
280
281 #[test]
282 fn test_proof_generation_and_verification() {
283 let leaves: Vec<[u8; 32]> = (0_u8..4).map(|i| Sha256::digest([i]).into()).collect();
284 let tree = MerkleTree::from_leaves(leaves);
285
286 for i in 0..4 {
287 let proof = tree.prove(i).expect("should generate proof");
288 assert!(proof.verify(), "proof for leaf {} should verify", i);
289 }
290 }
291
292 #[test]
293 fn test_proof_for_out_of_bounds() {
294 let leaves: Vec<[u8; 32]> = (0_u8..4).map(|i| Sha256::digest([i]).into()).collect();
295 let tree = MerkleTree::from_leaves(leaves);
296
297 assert!(tree.prove(4).is_none());
298 assert!(tree.prove(100).is_none());
299 }
300
301 #[test]
302 fn test_odd_number_of_leaves() {
303 let leaves: Vec<[u8; 32]> = (0_u8..3).map(|i| Sha256::digest([i]).into()).collect();
304 let tree = MerkleTree::from_leaves(leaves);
305
306 for i in 0..3 {
308 let proof = tree.prove(i).expect("should generate proof");
309 assert!(proof.verify(), "proof for leaf {} should verify", i);
310 }
311 }
312
313 #[test]
314 fn test_heap_merkle_root() {
315 let heap = Heap::new();
316 let (_, heap) = heap.alloc_channel("Alice", "Bob");
317 let (_, heap) = heap.alloc_message("Alice", "Bob", "Hello", vec![], 0);
318
319 let root = MerkleTree::from_heap(&heap).root;
320 assert_ne!(root, empty_root());
321 }
322
323 #[test]
324 fn test_heap_commitment() {
325 let heap = Heap::new();
326 let (rid, heap) = heap.alloc_channel("Alice", "Bob");
327 let heap = heap.consume(&rid).unwrap();
328
329 let commitment = HeapCommitment::from_heap(&heap);
330
331 assert_eq!(commitment.counter, 1);
334 }
335
336 #[test]
337 fn test_commitment_determinism() {
338 let heap1 = Heap::new();
339 let (_, heap1) = heap1.alloc_channel("Alice", "Bob");
340
341 let heap2 = Heap::new();
342 let (_, heap2) = heap2.alloc_channel("Alice", "Bob");
343
344 let c1 = HeapCommitment::from_heap(&heap1);
345 let c2 = HeapCommitment::from_heap(&heap2);
346
347 assert_eq!(c1, c2);
348 assert_eq!(c1.hash(), c2.hash());
349 }
350}