1#[rustfmt::skip]
10const K: [u32; 64] = [
11 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
12 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
13 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
14 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
15 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
16 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
17 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
18 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
19 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
20 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
21 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
22 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
23 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
24 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
25 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
26 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
27];
28
29const H0: [u32; 8] = [
31 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
32];
33
34pub fn sha256(data: &[u8]) -> [u8; 32] {
37 let bit_len = (data.len() as u64).wrapping_mul(8);
39 let mut msg = data.to_vec();
40 msg.push(0x80);
41 while msg.len() % 64 != 56 {
43 msg.push(0x00);
44 }
45 msg.extend_from_slice(&bit_len.to_be_bytes());
47
48 let mut h = H0;
50 for chunk in msg.chunks(64) {
51 let mut w = [0u32; 64];
53 for (i, word) in w.iter_mut().enumerate().take(16) {
54 let b = &chunk[i * 4..i * 4 + 4];
55 *word = u32::from_be_bytes([b[0], b[1], b[2], b[3]]);
56 }
57 for i in 16..64 {
58 let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
59 let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
60 w[i] = w[i - 16]
61 .wrapping_add(s0)
62 .wrapping_add(w[i - 7])
63 .wrapping_add(s1);
64 }
65
66 let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh] = h;
68 for i in 0..64 {
69 let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
70 let ch = (e & f) ^ ((!e) & g);
71 let temp1 = hh
72 .wrapping_add(s1)
73 .wrapping_add(ch)
74 .wrapping_add(K[i])
75 .wrapping_add(w[i]);
76 let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
77 let maj = (a & b) ^ (a & c) ^ (b & c);
78 let temp2 = s0.wrapping_add(maj);
79
80 hh = g;
81 g = f;
82 f = e;
83 e = d.wrapping_add(temp1);
84 d = c;
85 c = b;
86 b = a;
87 a = temp1.wrapping_add(temp2);
88 }
89
90 h[0] = h[0].wrapping_add(a);
91 h[1] = h[1].wrapping_add(b);
92 h[2] = h[2].wrapping_add(c);
93 h[3] = h[3].wrapping_add(d);
94 h[4] = h[4].wrapping_add(e);
95 h[5] = h[5].wrapping_add(f);
96 h[6] = h[6].wrapping_add(g);
97 h[7] = h[7].wrapping_add(hh);
98 }
99
100 let mut out = [0u8; 32];
102 for (i, &word) in h.iter().enumerate() {
103 out[i * 4..i * 4 + 4].copy_from_slice(&word.to_be_bytes());
104 }
105 out
106}
107
108fn fnv1a_64(data: &[u8]) -> u64 {
110 const FNV_OFFSET: u64 = 14_695_981_039_346_656_037;
111 const FNV_PRIME: u64 = 1_099_511_628_211;
112 let mut hash = FNV_OFFSET;
113 for &byte in data {
114 hash ^= byte as u64;
115 hash = hash.wrapping_mul(FNV_PRIME);
116 }
117 hash
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
124pub enum MerkleHashAlgo {
125 Sha256,
127 Blake3,
129 FnvXor,
132}
133
134#[derive(Debug, Clone, PartialEq, Eq)]
138pub struct MerkleNode {
139 pub hash: [u8; 32],
141 pub left: Option<Box<MerkleNode>>,
143 pub right: Option<Box<MerkleNode>>,
145}
146
147impl MerkleNode {
148 pub fn leaf(hash: [u8; 32]) -> Self {
150 Self {
151 hash,
152 left: None,
153 right: None,
154 }
155 }
156
157 pub fn internal(hash: [u8; 32], left: MerkleNode, right: MerkleNode) -> Self {
159 Self {
160 hash,
161 left: Some(Box::new(left)),
162 right: Some(Box::new(right)),
163 }
164 }
165}
166
167#[derive(Debug, Clone, PartialEq, Eq)]
173pub enum ProofStep {
174 Left([u8; 32]),
176 Right([u8; 32]),
178}
179
180#[derive(Debug, Clone, PartialEq, Eq)]
182pub struct MerkleProof {
183 pub leaf_hash: [u8; 32],
185 pub steps: Vec<ProofStep>,
187 pub root_hash: [u8; 32],
189 pub algo: MerkleHashAlgo,
191}
192
193#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct VerificationResult {
196 pub valid: bool,
198 pub computed_root: [u8; 32],
200 pub expected_root: [u8; 32],
202 pub steps_verified: usize,
204}
205
206impl VerificationResult {
207 #[inline]
209 pub fn is_valid(&self) -> bool {
210 self.valid
211 }
212}
213
214#[derive(Debug, Clone)]
216pub struct MerkleTree {
217 pub leaves: Vec<[u8; 32]>,
219 pub nodes: Vec<[u8; 32]>,
224 pub algo: MerkleHashAlgo,
226 pub depth: usize,
228}
229
230#[derive(Debug, Clone)]
236pub struct MerkleProofVerifier {
237 pub algo: MerkleHashAlgo,
239 pub verifications_done: u64,
241 pub failures: u64,
243}
244
245impl MerkleProofVerifier {
246 pub fn new(algo: MerkleHashAlgo) -> Self {
248 Self {
249 algo,
250 verifications_done: 0,
251 failures: 0,
252 }
253 }
254
255 pub fn hash_leaf(&self, data: &[u8]) -> [u8; 32] {
264 Self::hash_leaf_with_algo(data, self.algo)
265 }
266
267 fn hash_leaf_with_algo(data: &[u8], algo: MerkleHashAlgo) -> [u8; 32] {
268 match algo {
269 MerkleHashAlgo::Sha256 => sha256(data),
270 MerkleHashAlgo::Blake3 => {
271 let mut digest = sha256(data);
272 for byte in digest.iter_mut() {
273 *byte ^= 0xb3;
274 }
275 digest
276 }
277 MerkleHashAlgo::FnvXor => {
278 let fwd = fnv1a_64(data);
279 let rev = fnv1a_64(&data.iter().copied().rev().collect::<Vec<u8>>());
280 let mut out = [0u8; 32];
281 out[..8].copy_from_slice(&fwd.to_be_bytes());
282 let rev_bytes = rev.to_be_bytes();
284 for i in 0..8 {
285 out[i] ^= rev_bytes[i];
286 }
287 out
288 }
289 }
290 }
291
292 pub fn hash_pair(&self, left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
294 Self::hash_pair_with_algo(left, right, self.algo)
295 }
296
297 fn hash_pair_with_algo(left: &[u8; 32], right: &[u8; 32], algo: MerkleHashAlgo) -> [u8; 32] {
298 let mut combined = [0u8; 64];
299 combined[..32].copy_from_slice(left);
300 combined[32..].copy_from_slice(right);
301 Self::hash_leaf_with_algo(&combined, algo)
302 }
303
304 pub fn build_tree(&self, leaves: &[Vec<u8>]) -> MerkleTree {
311 if leaves.is_empty() {
312 return MerkleTree {
313 leaves: vec![],
314 nodes: vec![],
315 algo: self.algo,
316 depth: 0,
317 };
318 }
319
320 let mut leaf_hashes: Vec<[u8; 32]> = leaves.iter().map(|l| self.hash_leaf(l)).collect();
322
323 let n = leaf_hashes.len();
325 let padded_len = n.next_power_of_two();
326 if let Some(last) = leaf_hashes.last().copied() {
327 while leaf_hashes.len() < padded_len {
328 leaf_hashes.push(last);
329 }
330 }
331
332 let depth = if padded_len == 1 {
333 0
334 } else {
335 (padded_len as f64).log2() as usize
336 };
337
338 let total = 2 * padded_len - 1;
343 let mut nodes = vec![[0u8; 32]; total];
344
345 for (i, &hash) in leaf_hashes.iter().enumerate() {
347 nodes[padded_len - 1 + i] = hash;
348 }
349
350 if padded_len > 1 {
352 for i in (0..padded_len - 1).rev() {
353 let left = &nodes[2 * i + 1];
354 let right = &nodes[2 * i + 2];
355 nodes[i] = Self::hash_pair_with_algo(left, right, self.algo);
356 }
357 }
358
359 MerkleTree {
360 leaves: leaf_hashes,
361 nodes,
362 algo: self.algo,
363 depth,
364 }
365 }
366
367 pub fn generate_proof(&self, tree: &MerkleTree, leaf_index: usize) -> Option<MerkleProof> {
373 let padded_len = tree.leaves.len();
374 if padded_len == 0 || leaf_index >= padded_len {
375 return None;
376 }
377
378 let total = tree.nodes.len();
379 if total == 0 {
380 return None;
381 }
382
383 let leaf_hash = tree.leaves[leaf_index];
384 let root_hash = tree.nodes[0];
385 let mut steps = Vec::new();
386
387 let mut idx = padded_len - 1 + leaf_index;
389
390 while idx > 0 {
391 let is_left = (idx % 2) == 1; if is_left {
397 let sibling_idx = idx + 1;
399 if sibling_idx < total {
400 steps.push(ProofStep::Right(tree.nodes[sibling_idx]));
401 }
402 } else {
403 let sibling_idx = idx - 1;
405 steps.push(ProofStep::Left(tree.nodes[sibling_idx]));
406 }
407 idx = (idx - 1) / 2;
408 }
409
410 Some(MerkleProof {
411 leaf_hash,
412 steps,
413 root_hash,
414 algo: self.algo,
415 })
416 }
417
418 pub fn verify_proof(&mut self, proof: &MerkleProof) -> VerificationResult {
422 let mut current = proof.leaf_hash;
423 let mut steps_verified = 0;
424
425 for step in &proof.steps {
426 current = match step {
427 ProofStep::Left(sibling) => {
428 Self::hash_pair_with_algo(sibling, ¤t, proof.algo)
429 }
430 ProofStep::Right(sibling) => {
431 Self::hash_pair_with_algo(¤t, sibling, proof.algo)
432 }
433 };
434 steps_verified += 1;
435 }
436
437 let valid = current == proof.root_hash;
438 self.verifications_done += 1;
439 if !valid {
440 self.failures += 1;
441 }
442
443 VerificationResult {
444 valid,
445 computed_root: current,
446 expected_root: proof.root_hash,
447 steps_verified,
448 }
449 }
450
451 pub fn verify_batch(&mut self, proofs: &[MerkleProof]) -> Vec<VerificationResult> {
453 proofs.iter().map(|p| self.verify_proof(p)).collect()
454 }
455
456 pub fn root_of(&self, leaves: &[Vec<u8>]) -> [u8; 32] {
460 let tree = self.build_tree(leaves);
461 tree.nodes.first().copied().unwrap_or([0u8; 32])
462 }
463
464 pub fn verifier_stats(&self) -> (u64, u64) {
466 (self.verifications_done, self.failures)
467 }
468}
469
470#[cfg(test)]
473mod tests {
474 use crate::merkle_proof_verifier::{
475 fnv1a_64, sha256, MerkleHashAlgo, MerkleNode, MerkleProof, MerkleProofVerifier, MerkleTree,
476 ProofStep,
477 };
478
479 #[test]
483 fn test_sha256_empty() {
484 let digest = sha256(b"");
485 let expected =
486 hex_to_bytes("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
487 assert_eq!(digest, expected);
488 }
489
490 #[test]
494 fn test_sha256_abc() {
495 let digest = sha256(b"abc");
496 let expected =
497 hex_to_bytes("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
498 assert_eq!(digest, expected);
499 }
500
501 #[test]
503 fn test_sha256_deterministic() {
504 let a = sha256(b"hello world");
505 let b = sha256(b"hello world");
506 assert_eq!(a, b);
507 }
508
509 #[test]
511 fn test_sha256_distinct() {
512 let a = sha256(b"foo");
513 let b = sha256(b"bar");
514 assert_ne!(a, b);
515 }
516
517 #[test]
519 fn test_sha256_output_len() {
520 assert_eq!(sha256(b"test").len(), 32);
521 assert_eq!(sha256(b"").len(), 32);
522 assert_eq!(sha256(&[0u8; 1000]).len(), 32);
523 }
524
525 #[test]
529 fn test_fnv1a_known() {
530 assert_eq!(fnv1a_64(b""), 14_695_981_039_346_656_037_u64);
532 }
533
534 #[test]
536 fn test_fnv1a_deterministic() {
537 assert_eq!(fnv1a_64(b"hello"), fnv1a_64(b"hello"));
538 }
539
540 #[test]
542 fn test_fnv1a_distinct() {
543 assert_ne!(fnv1a_64(b"hello"), fnv1a_64(b"world"));
544 }
545
546 #[test]
550 fn test_hash_leaf_sha256_len() {
551 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
552 assert_eq!(v.hash_leaf(b"data").len(), 32);
553 }
554
555 #[test]
557 fn test_hash_leaf_blake3_differs_from_sha256() {
558 let vs = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
559 let vb = MerkleProofVerifier::new(MerkleHashAlgo::Blake3);
560 assert_ne!(vs.hash_leaf(b"data"), vb.hash_leaf(b"data"));
561 }
562
563 #[test]
565 fn test_hash_leaf_blake3_xor_correctness() {
566 let vb = MerkleProofVerifier::new(MerkleHashAlgo::Blake3);
567 let sha = sha256(b"test");
568 let blake = vb.hash_leaf(b"test");
569 for (s, b) in sha.iter().zip(blake.iter()) {
570 assert_eq!(s ^ 0xb3, *b);
571 }
572 }
573
574 #[test]
576 fn test_hash_leaf_fnvxor_deterministic() {
577 let v = MerkleProofVerifier::new(MerkleHashAlgo::FnvXor);
578 assert_eq!(v.hash_leaf(b"hello"), v.hash_leaf(b"hello"));
579 }
580
581 #[test]
583 fn test_hash_leaf_fnvxor_differs_from_sha256() {
584 let vs = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
585 let vf = MerkleProofVerifier::new(MerkleHashAlgo::FnvXor);
586 assert_ne!(vs.hash_leaf(b"data"), vf.hash_leaf(b"data"));
587 }
588
589 #[test]
593 fn test_hash_pair_not_commutative() {
594 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
595 let a = [1u8; 32];
596 let b = [2u8; 32];
597 assert_ne!(v.hash_pair(&a, &b), v.hash_pair(&b, &a));
598 }
599
600 #[test]
602 fn test_hash_pair_equal_inputs_deterministic() {
603 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
604 let h = [42u8; 32];
605 assert_eq!(v.hash_pair(&h, &h), v.hash_pair(&h, &h));
606 }
607
608 #[test]
612 fn test_merkle_node_leaf() {
613 let n = MerkleNode::leaf([0u8; 32]);
614 assert!(n.left.is_none());
615 assert!(n.right.is_none());
616 }
617
618 #[test]
620 fn test_merkle_node_internal() {
621 let l = MerkleNode::leaf([1u8; 32]);
622 let r = MerkleNode::leaf([2u8; 32]);
623 let parent = MerkleNode::internal([3u8; 32], l, r);
624 assert!(parent.left.is_some());
625 assert!(parent.right.is_some());
626 }
627
628 #[test]
632 fn test_build_tree_empty() {
633 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
634 let tree = v.build_tree(&[]);
635 assert!(tree.leaves.is_empty());
636 assert!(tree.nodes.is_empty());
637 }
638
639 #[test]
641 fn test_build_tree_single_leaf() {
642 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
643 let data = vec![b"hello".to_vec()];
644 let tree = v.build_tree(&data);
645 assert_eq!(tree.depth, 0);
646 assert_eq!(tree.nodes[0], v.hash_leaf(b"hello"));
649 }
650
651 #[test]
653 fn test_build_tree_padding() {
654 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
655 let data: Vec<Vec<u8>> = (0..3u8).map(|i| vec![i]).collect();
656 let tree = v.build_tree(&data);
657 assert_eq!(tree.leaves.len(), 4); }
659
660 #[test]
662 fn test_build_tree_four_leaves_depth() {
663 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
664 let data: Vec<Vec<u8>> = (0..4u8).map(|i| vec![i]).collect();
665 let tree = v.build_tree(&data);
666 assert_eq!(tree.depth, 2);
667 assert_eq!(tree.nodes.len(), 7); }
669
670 #[test]
672 fn test_build_tree_root_matches_root_of() {
673 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
674 let data: Vec<Vec<u8>> = (0..4u8).map(|i| vec![i]).collect();
675 let tree = v.build_tree(&data);
676 let root = v.root_of(&data);
677 assert_eq!(tree.nodes[0], root);
678 }
679
680 fn make_leaves(n: usize) -> Vec<Vec<u8>> {
683 (0..n).map(|i| format!("leaf-{i}").into_bytes()).collect()
684 }
685
686 fn round_trip(algo: MerkleHashAlgo, n_leaves: usize, leaf_idx: usize) -> bool {
687 let mut v = MerkleProofVerifier::new(algo);
688 let leaves = make_leaves(n_leaves);
689 let tree = v.build_tree(&leaves);
690 let proof = v.generate_proof(&tree, leaf_idx).expect("proof");
691 v.verify_proof(&proof).valid
692 }
693
694 #[test]
696 fn test_round_trip_sha256_4_leaf0() {
697 assert!(round_trip(MerkleHashAlgo::Sha256, 4, 0));
698 }
699
700 #[test]
702 fn test_round_trip_sha256_4_leaf3() {
703 assert!(round_trip(MerkleHashAlgo::Sha256, 4, 3));
704 }
705
706 #[test]
708 fn test_round_trip_blake3_8_leaf5() {
709 assert!(round_trip(MerkleHashAlgo::Blake3, 8, 5));
710 }
711
712 #[test]
714 fn test_round_trip_fnvxor_4_leaf2() {
715 assert!(round_trip(MerkleHashAlgo::FnvXor, 4, 2));
716 }
717
718 #[test]
720 fn test_round_trip_non_power_of_two() {
721 assert!(round_trip(MerkleHashAlgo::Sha256, 5, 2));
722 assert!(round_trip(MerkleHashAlgo::Sha256, 5, 4));
723 }
724
725 #[test]
727 fn test_tampered_leaf_fails() {
728 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
729 let leaves = make_leaves(4);
730 let tree = v.build_tree(&leaves);
731 let mut proof = v.generate_proof(&tree, 0).expect("proof");
732 proof.leaf_hash[0] ^= 0xff; let result = v.verify_proof(&proof);
734 assert!(!result.valid);
735 }
736
737 #[test]
739 fn test_tampered_step_fails() {
740 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
741 let leaves = make_leaves(4);
742 let tree = v.build_tree(&leaves);
743 let mut proof = v.generate_proof(&tree, 1).expect("proof");
744 if let Some(step) = proof.steps.first_mut() {
745 match step {
746 ProofStep::Left(h) | ProofStep::Right(h) => h[0] ^= 0xff,
747 }
748 }
749 let result = v.verify_proof(&proof);
750 assert!(!result.valid);
751 }
752
753 #[test]
755 fn test_tampered_root_fails() {
756 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
757 let leaves = make_leaves(4);
758 let tree = v.build_tree(&leaves);
759 let mut proof = v.generate_proof(&tree, 0).expect("proof");
760 proof.root_hash[0] ^= 0x01;
761 let result = v.verify_proof(&proof);
762 assert!(!result.valid);
763 }
764
765 #[test]
769 fn test_stats_initial() {
770 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
771 assert_eq!(v.verifier_stats(), (0, 0));
772 }
773
774 #[test]
776 fn test_stats_increments() {
777 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
778 let leaves = make_leaves(4);
779 let tree = v.build_tree(&leaves);
780 let proof = v.generate_proof(&tree, 0).expect("proof");
781 v.verify_proof(&proof);
782 v.verify_proof(&proof);
783 assert_eq!(v.verifier_stats(), (2, 0));
784 }
785
786 #[test]
788 fn test_stats_failures() {
789 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
790 let leaves = make_leaves(4);
791 let tree = v.build_tree(&leaves);
792 let mut proof = v.generate_proof(&tree, 0).expect("proof");
793 proof.root_hash[0] ^= 0x01;
794 v.verify_proof(&proof);
795 assert_eq!(v.verifier_stats(), (1, 1));
796 }
797
798 #[test]
802 fn test_verify_batch_count() {
803 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
804 let leaves = make_leaves(4);
805 let tree = v.build_tree(&leaves);
806 let proofs: Vec<MerkleProof> = (0..4).filter_map(|i| v.generate_proof(&tree, i)).collect();
807 let results = v.verify_batch(&proofs);
808 assert_eq!(results.len(), 4);
809 }
810
811 #[test]
813 fn test_verify_batch_all_valid() {
814 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
815 let leaves = make_leaves(8);
816 let tree = v.build_tree(&leaves);
817 let proofs: Vec<MerkleProof> = (0..8).filter_map(|i| v.generate_proof(&tree, i)).collect();
818 let results = v.verify_batch(&proofs);
819 assert!(results.iter().all(|r| r.valid));
820 }
821
822 #[test]
824 fn test_verify_batch_updates_stats() {
825 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
826 let leaves = make_leaves(4);
827 let tree = v.build_tree(&leaves);
828 let proofs: Vec<MerkleProof> = (0..4).filter_map(|i| v.generate_proof(&tree, i)).collect();
829 v.verify_batch(&proofs);
830 assert_eq!(v.verifications_done, 4);
831 }
832
833 #[test]
837 fn test_generate_proof_out_of_range() {
838 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
839 let leaves = make_leaves(4);
840 let tree = v.build_tree(&leaves);
841 assert!(v.generate_proof(&tree, 10).is_none());
842 }
843
844 #[test]
846 fn test_generate_proof_empty_tree() {
847 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
848 let empty_tree = MerkleTree {
849 leaves: vec![],
850 nodes: vec![],
851 algo: MerkleHashAlgo::Sha256,
852 depth: 0,
853 };
854 assert!(v.generate_proof(&empty_tree, 0).is_none());
855 }
856
857 #[test]
859 fn test_proof_single_leaf_no_steps() {
860 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
861 let leaves = vec![b"only".to_vec()];
862 let tree = v.build_tree(&leaves);
863 let proof = v.generate_proof(&tree, 0).expect("proof");
864 assert_eq!(proof.steps.len(), 0);
865 }
866
867 #[test]
869 fn test_proof_steps_count_depth2() {
870 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
871 let leaves = make_leaves(4);
872 let tree = v.build_tree(&leaves);
873 let proof = v.generate_proof(&tree, 0).expect("proof");
874 assert_eq!(proof.steps.len(), 2);
875 }
876
877 #[test]
881 fn test_verification_result_roots_match_on_valid() {
882 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
883 let leaves = make_leaves(4);
884 let tree = v.build_tree(&leaves);
885 let proof = v.generate_proof(&tree, 1).expect("proof");
886 let res = v.verify_proof(&proof);
887 assert_eq!(res.computed_root, res.expected_root);
888 assert!(res.is_valid());
889 }
890
891 #[test]
893 fn test_verification_result_steps_verified() {
894 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
895 let leaves = make_leaves(4);
896 let tree = v.build_tree(&leaves);
897 let proof = v.generate_proof(&tree, 2).expect("proof");
898 let n_steps = proof.steps.len();
899 let res = v.verify_proof(&proof);
900 assert_eq!(res.steps_verified, n_steps);
901 }
902
903 #[test]
907 fn test_different_algo_different_roots() {
908 let vs = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
909 let vb = MerkleProofVerifier::new(MerkleHashAlgo::Blake3);
910 let leaves = make_leaves(4);
911 assert_ne!(vs.root_of(&leaves), vb.root_of(&leaves));
912 }
913
914 #[test]
916 fn test_cross_algo_proof_fails() {
917 let vs = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
918 let leaves = make_leaves(4);
919 let sha_tree = vs.build_tree(&leaves);
920 let sha_proof = vs.generate_proof(&sha_tree, 0).expect("proof");
921
922 let mut blake_proof = sha_proof.clone();
924 blake_proof.algo = MerkleHashAlgo::Blake3;
925
926 let mut vb = MerkleProofVerifier::new(MerkleHashAlgo::Blake3);
927 let result = vb.verify_proof(&blake_proof);
928 assert!(!result.valid);
930 }
931
932 #[test]
936 fn test_large_tree_round_trip() {
937 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
938 let leaves: Vec<Vec<u8>> = (0u32..1024).map(|i| i.to_le_bytes().to_vec()).collect();
939 let tree = v.build_tree(&leaves);
940 assert_eq!(tree.depth, 10);
941 for &idx in &[0, 1, 511, 512, 1023] {
942 let proof = v.generate_proof(&tree, idx).expect("proof");
943 let res = v.verify_proof(&proof);
944 assert!(res.valid, "failed at leaf {idx}");
945 }
946 }
947
948 #[test]
950 fn test_all_leaves_8() {
951 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
952 let leaves = make_leaves(8);
953 let tree = v.build_tree(&leaves);
954 for i in 0..8 {
955 let proof = v.generate_proof(&tree, i).expect("proof");
956 assert!(v.verify_proof(&proof).valid, "leaf {i} failed");
957 }
958 }
959
960 #[test]
964 fn test_root_of_empty() {
965 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
966 assert_eq!(v.root_of(&[]), [0u8; 32]);
967 }
968
969 #[test]
971 fn test_root_of_consistent() {
972 let v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
973 let leaves = make_leaves(4);
974 assert_eq!(v.root_of(&leaves), v.root_of(&leaves));
975 }
976
977 #[test]
981 fn test_proof_step_pattern_match() {
982 let h = [7u8; 32];
983 let step_l = ProofStep::Left(h);
984 let step_r = ProofStep::Right(h);
985 match step_l {
986 ProofStep::Left(inner) => assert_eq!(inner, h),
987 ProofStep::Right(_) => panic!("wrong variant"),
988 }
989 match step_r {
990 ProofStep::Right(inner) => assert_eq!(inner, h),
991 ProofStep::Left(_) => panic!("wrong variant"),
992 }
993 }
994
995 #[test]
999 fn test_proof_clone_verifies() {
1000 let mut v = MerkleProofVerifier::new(MerkleHashAlgo::Sha256);
1001 let leaves = make_leaves(4);
1002 let tree = v.build_tree(&leaves);
1003 let proof = v.generate_proof(&tree, 2).expect("proof");
1004 let proof2 = proof.clone();
1005 assert!(v.verify_proof(&proof2).valid);
1006 }
1007
1008 fn hex_to_bytes(hex: &str) -> [u8; 32] {
1011 let mut out = [0u8; 32];
1012 for (i, chunk) in hex.as_bytes().chunks(2).enumerate() {
1013 if i >= 32 {
1014 break;
1015 }
1016 let hi = hex_nibble(chunk[0]);
1017 let lo = hex_nibble(chunk.get(1).copied().unwrap_or(b'0'));
1018 out[i] = (hi << 4) | lo;
1019 }
1020 out
1021 }
1022
1023 fn hex_nibble(b: u8) -> u8 {
1024 match b {
1025 b'0'..=b'9' => b - b'0',
1026 b'a'..=b'f' => b - b'a' + 10,
1027 b'A'..=b'F' => b - b'A' + 10,
1028 _ => 0,
1029 }
1030 }
1031}