Skip to main content

ipfrs_storage/
merkle_proof_verifier.rs

1//! Merkle tree construction and proof verification.
2//!
3//! Provides [`MerkleProofVerifier`] for building complete binary Merkle trees,
4//! generating inclusion proofs, and verifying those proofs — all using a pure-Rust
5//! FNV-1a 64-bit hash function with domain separation between leaf and internal nodes.
6//!
7//! # Layout
8//! Nodes are stored in a 1-indexed flat `Vec`:
9//! - index `1` = root
10//! - left child of `i` = `2 * i`
11//! - right child of `i` = `2 * i + 1`
12//!
13//! The tree is always padded to the next power of two.
14
15use std::fmt;
16
17// ---------------------------------------------------------------------------
18// Hash primitives (pure Rust, FNV-1a 64-bit, no external hash crates)
19// ---------------------------------------------------------------------------
20
21#[inline]
22fn fnv1a_64(data: &[u8]) -> u64 {
23    let mut h: u64 = 14_695_981_039_346_656_037;
24    for &b in data {
25        h ^= b as u64;
26        h = h.wrapping_mul(1_099_511_628_211);
27    }
28    h
29}
30
31#[cfg(test)]
32#[inline]
33fn hash_pair(left: &[u8; 8], right: &[u8; 8]) -> [u8; 8] {
34    let mut combined = [0u8; 16];
35    combined[..8].copy_from_slice(left);
36    combined[8..].copy_from_slice(right);
37    fnv1a_64(&combined).to_le_bytes()
38}
39
40#[inline]
41fn hash_leaf(data: &[u8]) -> [u8; 8] {
42    // prefix 0x00 to distinguish leaves from internal nodes
43    let mut input = Vec::with_capacity(1 + data.len());
44    input.push(0x00);
45    input.extend_from_slice(data);
46    fnv1a_64(&input).to_le_bytes()
47}
48
49#[inline]
50fn hash_internal(left: &[u8; 8], right: &[u8; 8]) -> [u8; 8] {
51    // prefix 0x01 to distinguish internal nodes from leaves
52    let mut input = Vec::with_capacity(17);
53    input.push(0x01);
54    input.extend_from_slice(left);
55    input.extend_from_slice(right);
56    fnv1a_64(&input).to_le_bytes()
57}
58
59// ---------------------------------------------------------------------------
60// Core types
61// ---------------------------------------------------------------------------
62
63/// A 64-bit Merkle hash (8 bytes, FNV-1a based).
64#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
65pub struct MerkleHash([u8; 8]);
66
67impl MerkleHash {
68    /// Construct from raw bytes.
69    #[inline]
70    pub fn from_bytes(bytes: [u8; 8]) -> Self {
71        Self(bytes)
72    }
73
74    /// Return the inner byte array.
75    #[inline]
76    pub fn as_bytes(&self) -> &[u8; 8] {
77        &self.0
78    }
79
80    /// The zero / default hash (all bytes zero).
81    #[inline]
82    pub fn zero() -> Self {
83        Self([0u8; 8])
84    }
85}
86
87impl fmt::Display for MerkleHash {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        for b in &self.0 {
90            write!(f, "{b:02x}")?;
91        }
92        Ok(())
93    }
94}
95
96impl Default for MerkleHash {
97    fn default() -> Self {
98        Self::zero()
99    }
100}
101
102/// A leaf node in the Merkle tree.
103#[derive(Clone, Debug, PartialEq, Eq)]
104pub struct MerkleLeaf {
105    /// Zero-based logical position in the original dataset.
106    pub index: usize,
107    /// Raw leaf data.
108    pub data: Vec<u8>,
109    /// Computed hash of the leaf (`hash_leaf(data)`).
110    pub hash: MerkleHash,
111}
112
113/// One step in a Merkle inclusion proof path.
114#[derive(Clone, Debug, PartialEq, Eq)]
115pub struct ProofStep {
116    /// Hash of the sibling node at this level.
117    pub sibling_hash: MerkleHash,
118    /// `true` if the sibling is on the *left*, `false` if on the *right*.
119    pub is_left: bool,
120}
121
122/// A complete inclusion proof for a single leaf.
123#[derive(Clone, Debug, PartialEq, Eq)]
124pub struct MerkleProof {
125    /// Zero-based index of the proven leaf.
126    pub leaf_index: usize,
127    /// Hash of the leaf itself.
128    pub leaf_hash: MerkleHash,
129    /// Sibling-hash path from leaf level up to (but not including) the root.
130    pub path: Vec<ProofStep>,
131    /// Expected root after replaying the path.
132    pub root: MerkleHash,
133}
134
135/// Summary statistics for a built Merkle tree.
136#[derive(Clone, Debug, PartialEq, Eq)]
137pub struct TreeStats {
138    /// Number of *logical* (original) leaves (before padding).
139    pub leaf_count: usize,
140    /// Height of the tree (number of levels, including the root level).
141    pub tree_height: usize,
142    /// Root hash.
143    pub root_hash: MerkleHash,
144    /// Total node count stored (including padding leaves).
145    pub total_nodes: usize,
146}
147
148/// Proof that a single leaf was updated in a Merkle tree.
149#[derive(Clone, Debug, PartialEq, Eq)]
150pub struct UpdateProof {
151    /// Inclusion proof before the update.
152    pub old_proof: MerkleProof,
153    /// Inclusion proof after the update.
154    pub new_proof: MerkleProof,
155    /// Zero-based index of the changed leaf.
156    pub changed_index: usize,
157}
158
159/// Errors returned by [`MerkleProofVerifier`] operations.
160#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
161pub enum VerifierError {
162    /// Cannot build or query an empty tree.
163    #[error("empty tree: at least one leaf is required")]
164    EmptyTree,
165
166    /// The requested leaf index exceeds the logical leaf count.
167    #[error("leaf index {0} is out of bounds")]
168    LeafIndexOutOfBounds(usize),
169
170    /// A proof's recomputed root does not match the stored root.
171    #[error("proof invalid: expected root {expected_root}, computed root {computed_root}")]
172    ProofInvalid {
173        expected_root: MerkleHash,
174        computed_root: MerkleHash,
175    },
176
177    /// The hash stored in the proof's leaf does not match the recomputed hash.
178    #[error("hash mismatch at leaf index {index}")]
179    HashMismatch {
180        /// Leaf index where the mismatch was detected.
181        index: usize,
182    },
183
184    /// The tree structure is internally inconsistent.
185    #[error("invalid tree structure: {0}")]
186    InvalidTreeStructure(String),
187}
188
189// ---------------------------------------------------------------------------
190// MerkleProofVerifier
191// ---------------------------------------------------------------------------
192
193/// Production-quality Merkle tree with proof generation and verification.
194///
195/// Internally stores all node hashes in a 1-indexed flat `Vec`.
196/// The tree is always padded to the next power of two.
197#[derive(Debug)]
198pub struct MerkleProofVerifier {
199    /// 1-indexed flat array: index 1 = root, left(i) = 2i, right(i) = 2i+1.
200    /// `nodes[0]` is unused.
201    nodes: Vec<MerkleHash>,
202    /// Number of *padded* leaves (always a power of two).
203    padded_leaf_count: usize,
204    /// Number of *original* (logical) leaves supplied by the caller.
205    logical_leaf_count: usize,
206    /// Height of the tree (number of levels including root and leaves).
207    height: usize,
208    /// Cached leaves including their data (for update operations).
209    leaf_data: Vec<Vec<u8>>,
210}
211
212impl MerkleProofVerifier {
213    // -----------------------------------------------------------------------
214    // Construction
215    // -----------------------------------------------------------------------
216
217    /// Build a complete Merkle tree from raw leaf data.
218    ///
219    /// If `leaves` is not a power of two, empty leaves (`[]`) are appended as
220    /// padding so the tree remains a complete binary tree.
221    ///
222    /// Returns [`VerifierError::EmptyTree`] when `leaves` is empty.
223    pub fn new(leaves: Vec<Vec<u8>>) -> Result<Self, VerifierError> {
224        if leaves.is_empty() {
225            return Err(VerifierError::EmptyTree);
226        }
227
228        let logical_leaf_count = leaves.len();
229        let padded_leaf_count = next_power_of_two(logical_leaf_count);
230        let height = padded_leaf_count.trailing_zeros() as usize + 1; // e.g. 4 leaves → height 3
231
232        // Total nodes in a 1-indexed complete binary tree with `padded_leaf_count` leaves:
233        // internal nodes: padded_leaf_count - 1,  leaves: padded_leaf_count
234        // total = 2 * padded_leaf_count
235        let total_nodes = 2 * padded_leaf_count;
236
237        // Allocate and fill with zero hashes.
238        let mut nodes = vec![MerkleHash::zero(); total_nodes + 1]; // +1 because 1-indexed
239
240        // Leaf offset: leaves occupy indices [padded_leaf_count .. 2*padded_leaf_count)
241        let leaf_offset = padded_leaf_count;
242
243        // Pad leaf data and compute leaf hashes.
244        let mut leaf_data = leaves;
245        leaf_data.resize(padded_leaf_count, Vec::new());
246
247        for (i, data) in leaf_data.iter().enumerate() {
248            let raw_hash = hash_leaf(data);
249            nodes[leaf_offset + i] = MerkleHash::from_bytes(raw_hash);
250        }
251
252        // Build internal nodes bottom-up.
253        for i in (1..padded_leaf_count).rev() {
254            let left = nodes[2 * i];
255            let right = nodes[2 * i + 1];
256            let raw_hash = hash_internal(left.as_bytes(), right.as_bytes());
257            nodes[i] = MerkleHash::from_bytes(raw_hash);
258        }
259
260        Ok(Self {
261            nodes,
262            padded_leaf_count,
263            logical_leaf_count,
264            height,
265            leaf_data,
266        })
267    }
268
269    // -----------------------------------------------------------------------
270    // Accessors
271    // -----------------------------------------------------------------------
272
273    /// Return the root hash of the tree.
274    #[inline]
275    pub fn root(&self) -> MerkleHash {
276        self.nodes[1]
277    }
278
279    /// Return the number of *logical* (original) leaves.
280    #[inline]
281    pub fn leaf_count(&self) -> usize {
282        self.logical_leaf_count
283    }
284
285    /// Return summary statistics.
286    pub fn stats(&self) -> TreeStats {
287        let total_nodes = self.nodes.len().saturating_sub(1); // exclude index-0 slot
288        TreeStats {
289            leaf_count: self.logical_leaf_count,
290            tree_height: self.height,
291            root_hash: self.root(),
292            total_nodes,
293        }
294    }
295
296    // -----------------------------------------------------------------------
297    // Proof generation
298    // -----------------------------------------------------------------------
299
300    /// Generate an inclusion proof for the leaf at `index`.
301    ///
302    /// Returns [`VerifierError::LeafIndexOutOfBounds`] when `index >= leaf_count()`.
303    pub fn generate_proof(&self, index: usize) -> Result<MerkleProof, VerifierError> {
304        if index >= self.logical_leaf_count {
305            return Err(VerifierError::LeafIndexOutOfBounds(index));
306        }
307
308        let leaf_hash = self.nodes[self.padded_leaf_count + index];
309        let mut path = Vec::with_capacity(self.height.saturating_sub(1));
310
311        let mut node_index = self.padded_leaf_count + index;
312        while node_index > 1 {
313            let is_right_child = node_index % 2 == 1;
314            let sibling_index = if is_right_child {
315                node_index - 1
316            } else {
317                node_index + 1
318            };
319            path.push(ProofStep {
320                sibling_hash: self.nodes[sibling_index],
321                // is_left: sibling is on the left when *we* are the right child
322                is_left: is_right_child,
323            });
324            node_index /= 2;
325        }
326
327        Ok(MerkleProof {
328            leaf_index: index,
329            leaf_hash,
330            path,
331            root: self.root(),
332        })
333    }
334
335    /// Generate inclusion proofs for every leaf in `[start, end)`.
336    ///
337    /// Returns [`VerifierError::LeafIndexOutOfBounds`] when `end > leaf_count()`.
338    pub fn generate_range_proof(
339        &self,
340        start: usize,
341        end: usize,
342    ) -> Result<Vec<MerkleProof>, VerifierError> {
343        if end > self.logical_leaf_count {
344            return Err(VerifierError::LeafIndexOutOfBounds(end.saturating_sub(1)));
345        }
346        if start >= end {
347            return Ok(Vec::new());
348        }
349        let mut proofs = Vec::with_capacity(end - start);
350        for i in start..end {
351            proofs.push(self.generate_proof(i)?);
352        }
353        Ok(proofs)
354    }
355
356    // -----------------------------------------------------------------------
357    // Verification
358    // -----------------------------------------------------------------------
359
360    /// Verify an inclusion proof against the tree's own root.
361    ///
362    /// Returns `true` when the proof is valid, `false` otherwise.
363    /// Returns an error only when the proof is structurally inconsistent.
364    pub fn verify_proof(&self, proof: &MerkleProof) -> Result<bool, VerifierError> {
365        self.verify_against_root(proof, &self.root())
366    }
367
368    /// Verify an inclusion proof against an *externally* supplied root.
369    pub fn verify_against_root(
370        &self,
371        proof: &MerkleProof,
372        expected_root: &MerkleHash,
373    ) -> Result<bool, VerifierError> {
374        let computed_root = recompute_root(proof)?;
375        if computed_root != *expected_root {
376            return Ok(false);
377        }
378        if computed_root != proof.root {
379            return Ok(false);
380        }
381        Ok(true)
382    }
383
384    /// Verify that all proofs in `proofs` share the same root and are individually valid.
385    ///
386    /// Returns `true` when every proof is valid and they all share a consistent root.
387    pub fn verify_range(&self, proofs: &[MerkleProof]) -> Result<bool, VerifierError> {
388        if proofs.is_empty() {
389            return Ok(true);
390        }
391        let shared_root = proofs[0].root;
392        for proof in proofs {
393            if proof.root != shared_root {
394                return Ok(false);
395            }
396            let computed = recompute_root(proof)?;
397            if computed != shared_root {
398                return Ok(false);
399            }
400        }
401        Ok(true)
402    }
403
404    // -----------------------------------------------------------------------
405    // Updates
406    // -----------------------------------------------------------------------
407
408    /// Replace the leaf at `index` with `new_data`, update all nodes on the
409    /// path to the root in O(log n), and return an [`UpdateProof`].
410    ///
411    /// Returns [`VerifierError::LeafIndexOutOfBounds`] when `index >= leaf_count()`.
412    pub fn update_leaf(
413        &mut self,
414        index: usize,
415        new_data: Vec<u8>,
416    ) -> Result<UpdateProof, VerifierError> {
417        if index >= self.logical_leaf_count {
418            return Err(VerifierError::LeafIndexOutOfBounds(index));
419        }
420
421        // Capture the old proof before mutation.
422        let old_proof = self.generate_proof(index)?;
423
424        // Update the leaf hash.
425        let new_leaf_raw = hash_leaf(&new_data);
426        let leaf_node_index = self.padded_leaf_count + index;
427        self.nodes[leaf_node_index] = MerkleHash::from_bytes(new_leaf_raw);
428        self.leaf_data[index] = new_data;
429
430        // Recompute the path from the updated leaf up to the root — O(log n).
431        let mut current = leaf_node_index / 2;
432        while current >= 1 {
433            let left = self.nodes[2 * current];
434            let right = self.nodes[2 * current + 1];
435            let raw = hash_internal(left.as_bytes(), right.as_bytes());
436            self.nodes[current] = MerkleHash::from_bytes(raw);
437            if current == 1 {
438                break;
439            }
440            current /= 2;
441        }
442
443        let new_proof = self.generate_proof(index)?;
444
445        Ok(UpdateProof {
446            old_proof,
447            new_proof,
448            changed_index: index,
449        })
450    }
451
452    /// Verify that both sides of an [`UpdateProof`] are internally consistent.
453    ///
454    /// Specifically:
455    /// 1. `old_proof.root` ≠ `new_proof.root` (they should differ after an update,
456    ///    unless the new data happens to hash identically, which is still accepted).
457    /// 2. Both proofs replicate to their respective roots correctly.
458    /// 3. `old_proof.leaf_index == new_proof.leaf_index == update.changed_index`.
459    pub fn verify_update(&self, update: &UpdateProof) -> Result<bool, VerifierError> {
460        // Index consistency.
461        if update.old_proof.leaf_index != update.changed_index
462            || update.new_proof.leaf_index != update.changed_index
463        {
464            return Ok(false);
465        }
466
467        // Verify both proofs replay to their own roots.
468        let old_root_ok = {
469            let computed = recompute_root(&update.old_proof)?;
470            computed == update.old_proof.root
471        };
472        let new_root_ok = {
473            let computed = recompute_root(&update.new_proof)?;
474            computed == update.new_proof.root
475        };
476
477        Ok(old_root_ok && new_root_ok)
478    }
479}
480
481// ---------------------------------------------------------------------------
482// Helper: replay a proof path to compute the root
483// ---------------------------------------------------------------------------
484
485fn recompute_root(proof: &MerkleProof) -> Result<MerkleHash, VerifierError> {
486    let mut current = *proof.leaf_hash.as_bytes();
487
488    for step in &proof.path {
489        let raw = if step.is_left {
490            // sibling is on the left
491            hash_internal(step.sibling_hash.as_bytes(), &current)
492        } else {
493            // sibling is on the right
494            hash_internal(&current, step.sibling_hash.as_bytes())
495        };
496        current = raw;
497    }
498
499    Ok(MerkleHash::from_bytes(current))
500}
501
502// ---------------------------------------------------------------------------
503// Utility
504// ---------------------------------------------------------------------------
505
506/// Round `n` up to the next power of two (or return `n` if it already is one).
507#[inline]
508fn next_power_of_two(n: usize) -> usize {
509    if n == 0 {
510        return 1;
511    }
512    if n.is_power_of_two() {
513        return n;
514    }
515    n.next_power_of_two()
516}
517
518// ---------------------------------------------------------------------------
519// Tests
520// ---------------------------------------------------------------------------
521
522#[cfg(test)]
523mod tests {
524    use super::*;
525
526    // -----------------------------------------------------------------------
527    // Helpers
528    // -----------------------------------------------------------------------
529
530    fn make_leaves(n: usize) -> Vec<Vec<u8>> {
531        (0..n).map(|i| format!("leaf-{i}").into_bytes()).collect()
532    }
533
534    fn single_leaf_tree() -> MerkleProofVerifier {
535        MerkleProofVerifier::new(vec![b"hello".to_vec()]).expect("single leaf")
536    }
537
538    // -----------------------------------------------------------------------
539    // Hash primitives
540    // -----------------------------------------------------------------------
541
542    #[test]
543    fn test_fnv1a_known_empty() {
544        // FNV-1a offset basis for empty input is 14695981039346656037
545        assert_eq!(fnv1a_64(&[]), 14_695_981_039_346_656_037u64);
546    }
547
548    #[test]
549    fn test_hash_leaf_domain_separation() {
550        let h_leaf = hash_leaf(b"data");
551        // Must differ from hash_pair applied to the same bytes (no 0x00 prefix there)
552        let h_pair = hash_pair(&[0u8; 8], &[0u8; 8]);
553        assert_ne!(h_leaf, h_pair);
554    }
555
556    #[test]
557    fn test_hash_internal_domain_separation_from_leaf() {
558        let left = hash_leaf(b"left");
559        let right = hash_leaf(b"right");
560        let internal = hash_internal(&left, &right);
561        // If domain separation works, hashing the raw concat should differ
562        let naive = hash_pair(&left, &right);
563        assert_ne!(internal, naive);
564    }
565
566    #[test]
567    fn test_hash_internal_not_commutative() {
568        let a = [1u8; 8];
569        let b = [2u8; 8];
570        assert_ne!(hash_internal(&a, &b), hash_internal(&b, &a));
571    }
572
573    // -----------------------------------------------------------------------
574    // MerkleHash display
575    // -----------------------------------------------------------------------
576
577    #[test]
578    fn test_merkle_hash_display_len() {
579        let h = MerkleHash::from_bytes([0xde, 0xad, 0xbe, 0xef, 0x00, 0x11, 0x22, 0x33]);
580        let s = h.to_string();
581        assert_eq!(s.len(), 16);
582        assert_eq!(s, "deadbeef00112233");
583    }
584
585    #[test]
586    fn test_merkle_hash_zero_display() {
587        let h = MerkleHash::zero();
588        assert_eq!(h.to_string(), "0000000000000000");
589    }
590
591    #[test]
592    fn test_merkle_hash_eq() {
593        let a = MerkleHash::from_bytes([1u8; 8]);
594        let b = MerkleHash::from_bytes([1u8; 8]);
595        let c = MerkleHash::from_bytes([2u8; 8]);
596        assert_eq!(a, b);
597        assert_ne!(a, c);
598    }
599
600    // -----------------------------------------------------------------------
601    // Empty tree
602    // -----------------------------------------------------------------------
603
604    #[test]
605    fn test_empty_tree_returns_error() {
606        let result = MerkleProofVerifier::new(vec![]);
607        assert_eq!(result.unwrap_err(), VerifierError::EmptyTree);
608    }
609
610    // -----------------------------------------------------------------------
611    // Single-leaf tree
612    // -----------------------------------------------------------------------
613
614    #[test]
615    fn test_single_leaf_root_non_zero() {
616        let verifier = single_leaf_tree();
617        assert_ne!(verifier.root(), MerkleHash::zero());
618    }
619
620    #[test]
621    fn test_single_leaf_leaf_count() {
622        let verifier = single_leaf_tree();
623        assert_eq!(verifier.leaf_count(), 1);
624    }
625
626    #[test]
627    fn test_single_leaf_generate_proof() {
628        let verifier = single_leaf_tree();
629        let proof = verifier.generate_proof(0).expect("proof");
630        assert_eq!(proof.leaf_index, 0);
631        assert_eq!(proof.root, verifier.root());
632    }
633
634    #[test]
635    fn test_single_leaf_proof_verification() {
636        let verifier = single_leaf_tree();
637        let proof = verifier.generate_proof(0).expect("proof");
638        assert!(verifier.verify_proof(&proof).expect("verify"));
639    }
640
641    #[test]
642    fn test_single_leaf_out_of_bounds() {
643        let verifier = single_leaf_tree();
644        let err = verifier.generate_proof(1).unwrap_err();
645        assert_eq!(err, VerifierError::LeafIndexOutOfBounds(1));
646    }
647
648    // -----------------------------------------------------------------------
649    // Power-of-two sizes
650    // -----------------------------------------------------------------------
651
652    #[test]
653    fn test_two_leaves() {
654        let verifier = MerkleProofVerifier::new(make_leaves(2)).expect("2 leaves");
655        assert_eq!(verifier.leaf_count(), 2);
656        for i in 0..2 {
657            let proof = verifier.generate_proof(i).expect("proof");
658            assert!(verifier.verify_proof(&proof).expect("verify"));
659        }
660    }
661
662    #[test]
663    fn test_four_leaves() {
664        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
665        assert_eq!(verifier.leaf_count(), 4);
666        for i in 0..4 {
667            let proof = verifier.generate_proof(i).expect("proof");
668            assert!(verifier.verify_proof(&proof).expect("verify"));
669        }
670    }
671
672    #[test]
673    fn test_eight_leaves() {
674        let verifier = MerkleProofVerifier::new(make_leaves(8)).expect("8 leaves");
675        assert_eq!(verifier.leaf_count(), 8);
676        for i in 0..8 {
677            let proof = verifier.generate_proof(i).expect("proof");
678            assert!(verifier.verify_proof(&proof).expect("verify"));
679        }
680    }
681
682    #[test]
683    fn test_sixteen_leaves() {
684        let verifier = MerkleProofVerifier::new(make_leaves(16)).expect("16 leaves");
685        for i in 0..16 {
686            let proof = verifier.generate_proof(i).expect("proof");
687            assert!(verifier.verify_proof(&proof).expect("verify"));
688        }
689    }
690
691    #[test]
692    fn test_large_power_of_two_128() {
693        let verifier = MerkleProofVerifier::new(make_leaves(128)).expect("128 leaves");
694        let proof_first = verifier.generate_proof(0).expect("proof 0");
695        let proof_last = verifier.generate_proof(127).expect("proof 127");
696        assert!(verifier.verify_proof(&proof_first).expect("verify"));
697        assert!(verifier.verify_proof(&proof_last).expect("verify"));
698    }
699
700    // -----------------------------------------------------------------------
701    // Non-power-of-two padding
702    // -----------------------------------------------------------------------
703
704    #[test]
705    fn test_three_leaves_padded_to_four() {
706        let verifier = MerkleProofVerifier::new(make_leaves(3)).expect("3 leaves");
707        assert_eq!(verifier.leaf_count(), 3);
708        // All three logical leaves must have valid proofs.
709        for i in 0..3 {
710            let proof = verifier.generate_proof(i).expect("proof");
711            assert!(verifier.verify_proof(&proof).expect("verify"));
712        }
713        // Index 3 is a padding leaf — out of bounds from caller perspective.
714        assert!(verifier.generate_proof(3).is_err());
715    }
716
717    #[test]
718    fn test_five_leaves_padded_to_eight() {
719        let verifier = MerkleProofVerifier::new(make_leaves(5)).expect("5 leaves");
720        assert_eq!(verifier.leaf_count(), 5);
721        for i in 0..5 {
722            let proof = verifier.generate_proof(i).expect("proof");
723            assert!(verifier.verify_proof(&proof).expect("verify"));
724        }
725    }
726
727    #[test]
728    fn test_seven_leaves() {
729        let verifier = MerkleProofVerifier::new(make_leaves(7)).expect("7 leaves");
730        for i in 0..7 {
731            let proof = verifier.generate_proof(i).expect("proof");
732            assert!(verifier.verify_proof(&proof).expect("verify"));
733        }
734    }
735
736    #[test]
737    fn test_ten_leaves_padded_to_sixteen() {
738        let verifier = MerkleProofVerifier::new(make_leaves(10)).expect("10 leaves");
739        assert_eq!(verifier.leaf_count(), 10);
740        for i in 0..10 {
741            let proof = verifier.generate_proof(i).expect("proof");
742            assert!(verifier.verify_proof(&proof).expect("verify"));
743        }
744    }
745
746    #[test]
747    fn test_100_leaves() {
748        let verifier = MerkleProofVerifier::new(make_leaves(100)).expect("100 leaves");
749        assert_eq!(verifier.leaf_count(), 100);
750        for i in [0, 1, 50, 99] {
751            let proof = verifier.generate_proof(i).expect("proof");
752            assert!(verifier.verify_proof(&proof).expect("verify"));
753        }
754    }
755
756    // -----------------------------------------------------------------------
757    // Proof path length
758    // -----------------------------------------------------------------------
759
760    #[test]
761    fn test_proof_path_length_power_of_two() {
762        // For a tree with 8 leaves, height = 4, path length = 3.
763        let verifier = MerkleProofVerifier::new(make_leaves(8)).expect("8 leaves");
764        for i in 0..8 {
765            let proof = verifier.generate_proof(i).expect("proof");
766            assert_eq!(proof.path.len(), 3, "leaf {i}");
767        }
768    }
769
770    #[test]
771    fn test_proof_path_length_padded() {
772        // For 5 leaves padded to 8, still height 4, path length 3.
773        let verifier = MerkleProofVerifier::new(make_leaves(5)).expect("5 leaves");
774        for i in 0..5 {
775            let proof = verifier.generate_proof(i).expect("proof");
776            assert_eq!(proof.path.len(), 3, "leaf {i}");
777        }
778    }
779
780    #[test]
781    fn test_proof_path_length_single_leaf() {
782        // Single leaf: padded to 1, height 1, path length 0.
783        let verifier = single_leaf_tree();
784        let proof = verifier.generate_proof(0).expect("proof");
785        assert_eq!(proof.path.len(), 0);
786    }
787
788    #[test]
789    fn test_proof_path_length_two_leaves() {
790        let verifier = MerkleProofVerifier::new(make_leaves(2)).expect("2 leaves");
791        for i in 0..2 {
792            let proof = verifier.generate_proof(i).expect("proof");
793            assert_eq!(proof.path.len(), 1, "leaf {i}");
794        }
795    }
796
797    // -----------------------------------------------------------------------
798    // Root consistency across all proofs
799    // -----------------------------------------------------------------------
800
801    #[test]
802    fn test_all_proofs_share_root() {
803        let verifier = MerkleProofVerifier::new(make_leaves(6)).expect("6 leaves");
804        let root = verifier.root();
805        for i in 0..6 {
806            let proof = verifier.generate_proof(i).expect("proof");
807            assert_eq!(proof.root, root);
808        }
809    }
810
811    // -----------------------------------------------------------------------
812    // Invalid proof detection
813    // -----------------------------------------------------------------------
814
815    #[test]
816    fn test_tampered_leaf_hash_fails() {
817        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
818        let mut proof = verifier.generate_proof(0).expect("proof");
819        // Tamper with the leaf hash.
820        proof.leaf_hash = MerkleHash::from_bytes([0xff; 8]);
821        assert!(!verifier.verify_proof(&proof).expect("verify"));
822    }
823
824    #[test]
825    fn test_tampered_path_step_fails() {
826        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
827        let mut proof = verifier.generate_proof(2).expect("proof");
828        if let Some(step) = proof.path.first_mut() {
829            step.sibling_hash = MerkleHash::from_bytes([0xaa; 8]);
830        }
831        assert!(!verifier.verify_proof(&proof).expect("verify"));
832    }
833
834    #[test]
835    fn test_flipped_is_left_fails() {
836        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
837        let mut proof = verifier.generate_proof(1).expect("proof");
838        if let Some(step) = proof.path.first_mut() {
839            step.is_left = !step.is_left;
840        }
841        // After flipping, the recomputed root will be different from the stored root.
842        assert!(!verifier.verify_proof(&proof).expect("verify"));
843    }
844
845    #[test]
846    fn test_wrong_root_in_proof_fails() {
847        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
848        let mut proof = verifier.generate_proof(0).expect("proof");
849        proof.root = MerkleHash::from_bytes([0x00; 8]);
850        assert!(!verifier.verify_proof(&proof).expect("verify"));
851    }
852
853    // -----------------------------------------------------------------------
854    // verify_against_root
855    // -----------------------------------------------------------------------
856
857    #[test]
858    fn test_verify_against_correct_root() {
859        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
860        let proof = verifier.generate_proof(1).expect("proof");
861        let root = verifier.root();
862        assert!(verifier.verify_against_root(&proof, &root).expect("verify"));
863    }
864
865    #[test]
866    fn test_verify_against_wrong_root() {
867        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
868        let proof = verifier.generate_proof(1).expect("proof");
869        let bad_root = MerkleHash::from_bytes([0x12; 8]);
870        assert!(!verifier
871            .verify_against_root(&proof, &bad_root)
872            .expect("verify"));
873    }
874
875    #[test]
876    fn test_proof_from_one_tree_fails_against_another_root() {
877        let v1 = MerkleProofVerifier::new(make_leaves(4)).expect("v1");
878        let v2 = MerkleProofVerifier::new(make_leaves(4)).expect("v2");
879        // Both trees have different data, so roots differ.
880        // A proof from v1 verified against v2's root should fail.
881        let proof = v1.generate_proof(0).expect("proof");
882        let v2_root = v2.root();
883        if v1.root() != v2_root {
884            assert!(!v1.verify_against_root(&proof, &v2_root).expect("verify"));
885        }
886    }
887
888    // -----------------------------------------------------------------------
889    // Range proofs
890    // -----------------------------------------------------------------------
891
892    #[test]
893    fn test_range_proof_full() {
894        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
895        let proofs = verifier.generate_range_proof(0, 4).expect("range");
896        assert_eq!(proofs.len(), 4);
897        assert!(verifier.verify_range(&proofs).expect("verify_range"));
898    }
899
900    #[test]
901    fn test_range_proof_partial() {
902        let verifier = MerkleProofVerifier::new(make_leaves(8)).expect("8 leaves");
903        let proofs = verifier.generate_range_proof(2, 6).expect("range");
904        assert_eq!(proofs.len(), 4);
905        assert!(verifier.verify_range(&proofs).expect("verify_range"));
906    }
907
908    #[test]
909    fn test_range_proof_single() {
910        let verifier = MerkleProofVerifier::new(make_leaves(8)).expect("8 leaves");
911        let proofs = verifier.generate_range_proof(3, 4).expect("range");
912        assert_eq!(proofs.len(), 1);
913        assert!(verifier.verify_range(&proofs).expect("verify_range"));
914    }
915
916    #[test]
917    fn test_range_proof_empty_range() {
918        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
919        let proofs = verifier.generate_range_proof(2, 2).expect("empty range");
920        assert_eq!(proofs.len(), 0);
921        assert!(verifier.verify_range(&proofs).expect("verify empty"));
922    }
923
924    #[test]
925    fn test_range_proof_out_of_bounds() {
926        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
927        let err = verifier.generate_range_proof(0, 5).unwrap_err();
928        assert_eq!(err, VerifierError::LeafIndexOutOfBounds(4));
929    }
930
931    #[test]
932    fn test_verify_range_tampered_root_fails() {
933        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
934        let mut proofs = verifier.generate_range_proof(0, 4).expect("range");
935        // Tamper one proof's stored root.
936        proofs[2].root = MerkleHash::from_bytes([0xdd; 8]);
937        assert!(!verifier.verify_range(&proofs).expect("verify_range"));
938    }
939
940    // -----------------------------------------------------------------------
941    // Update proofs
942    // -----------------------------------------------------------------------
943
944    #[test]
945    fn test_update_leaf_changes_root() {
946        let mut verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
947        let old_root = verifier.root();
948        verifier
949            .update_leaf(1, b"new-data".to_vec())
950            .expect("update");
951        assert_ne!(verifier.root(), old_root);
952    }
953
954    #[test]
955    fn test_update_leaf_proof_valid_after_update() {
956        let mut verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
957        verifier
958            .update_leaf(2, b"changed".to_vec())
959            .expect("update");
960        let proof = verifier.generate_proof(2).expect("proof");
961        assert!(verifier.verify_proof(&proof).expect("verify"));
962    }
963
964    #[test]
965    fn test_update_leaf_old_proof_invalid_against_new_root() {
966        let mut verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
967        let old_proof = verifier.generate_proof(0).expect("old proof");
968        verifier
969            .update_leaf(0, b"new-leaf-0".to_vec())
970            .expect("update");
971        // Old proof root no longer matches the verifier's current root.
972        assert!(!verifier.verify_proof(&old_proof).expect("verify old"));
973    }
974
975    #[test]
976    fn test_update_proof_verify_update() {
977        let mut verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
978        let update = verifier
979            .update_leaf(1, b"new-leaf-1".to_vec())
980            .expect("update");
981        assert!(verifier.verify_update(&update).expect("verify_update"));
982    }
983
984    #[test]
985    fn test_update_proof_old_and_new_roots_differ() {
986        let mut verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
987        let update = verifier
988            .update_leaf(3, b"updated".to_vec())
989            .expect("update");
990        assert_ne!(update.old_proof.root, update.new_proof.root);
991    }
992
993    #[test]
994    fn test_update_leaf_out_of_bounds() {
995        let mut verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
996        let err = verifier.update_leaf(4, b"x".to_vec()).unwrap_err();
997        assert_eq!(err, VerifierError::LeafIndexOutOfBounds(4));
998    }
999
1000    #[test]
1001    fn test_update_non_overlapping_leaves_independent() {
1002        let mut verifier = MerkleProofVerifier::new(make_leaves(8)).expect("8 leaves");
1003        // Update leaf 0.
1004        let update0 = verifier
1005            .update_leaf(0, b"leaf0-new".to_vec())
1006            .expect("update 0");
1007        // Proofs for leaf 7 should still be valid.
1008        let proof7 = verifier.generate_proof(7).expect("proof 7");
1009        assert!(verifier.verify_proof(&proof7).expect("verify 7"));
1010        // The update proof for leaf 0 should be valid.
1011        assert!(verifier.verify_update(&update0).expect("verify update0"));
1012    }
1013
1014    #[test]
1015    fn test_multiple_sequential_updates() {
1016        let mut verifier = MerkleProofVerifier::new(make_leaves(8)).expect("8 leaves");
1017        for i in 0..8 {
1018            let data = format!("update-{i}").into_bytes();
1019            let update = verifier.update_leaf(i, data).expect("update");
1020            assert!(verifier.verify_update(&update).expect("verify_update"));
1021        }
1022        // All leaves now have valid proofs against the current root.
1023        for i in 0..8 {
1024            let proof = verifier.generate_proof(i).expect("proof");
1025            assert!(verifier.verify_proof(&proof).expect("verify"));
1026        }
1027    }
1028
1029    // -----------------------------------------------------------------------
1030    // Stats
1031    // -----------------------------------------------------------------------
1032
1033    #[test]
1034    fn test_stats_single_leaf() {
1035        let verifier = single_leaf_tree();
1036        let stats = verifier.stats();
1037        assert_eq!(stats.leaf_count, 1);
1038        // height: 1-leaf tree pads to 1 (power of two already), height = trailing_zeros(1)+1 = 0+1 = 1
1039        // ... but with a single leaf there is only the root.
1040        assert!(stats.tree_height >= 1);
1041        assert_ne!(stats.root_hash, MerkleHash::zero());
1042        // total_nodes for 1 padded leaf: 2*1 = 2 nodes; our array is 3 (idx 0 unused) so
1043        // stored nodes = len - 1 = 2.
1044        assert_eq!(stats.total_nodes, 2);
1045    }
1046
1047    #[test]
1048    fn test_stats_four_leaves() {
1049        let verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
1050        let stats = verifier.stats();
1051        assert_eq!(stats.leaf_count, 4);
1052        assert_eq!(stats.tree_height, 3); // root + 1 internal level + leaf level
1053        assert_eq!(stats.total_nodes, 8); // 2*4 = 8
1054    }
1055
1056    #[test]
1057    fn test_stats_eight_leaves() {
1058        let verifier = MerkleProofVerifier::new(make_leaves(8)).expect("8 leaves");
1059        let stats = verifier.stats();
1060        assert_eq!(stats.leaf_count, 8);
1061        assert_eq!(stats.tree_height, 4);
1062        assert_eq!(stats.total_nodes, 16);
1063    }
1064
1065    #[test]
1066    fn test_stats_root_matches_verifier() {
1067        let verifier = MerkleProofVerifier::new(make_leaves(6)).expect("6 leaves");
1068        assert_eq!(verifier.stats().root_hash, verifier.root());
1069    }
1070
1071    // -----------------------------------------------------------------------
1072    // Determinism
1073    // -----------------------------------------------------------------------
1074
1075    #[test]
1076    fn test_same_data_same_root() {
1077        let leaves = make_leaves(8);
1078        let v1 = MerkleProofVerifier::new(leaves.clone()).expect("v1");
1079        let v2 = MerkleProofVerifier::new(leaves).expect("v2");
1080        assert_eq!(v1.root(), v2.root());
1081    }
1082
1083    #[test]
1084    fn test_different_data_different_root() {
1085        let v1 = MerkleProofVerifier::new(vec![b"data-a".to_vec()]).expect("v1");
1086        let v2 = MerkleProofVerifier::new(vec![b"data-b".to_vec()]).expect("v2");
1087        assert_ne!(v1.root(), v2.root());
1088    }
1089
1090    #[test]
1091    fn test_order_matters_for_root() {
1092        let leaves_ab = vec![b"a".to_vec(), b"b".to_vec()];
1093        let leaves_ba = vec![b"b".to_vec(), b"a".to_vec()];
1094        let v_ab = MerkleProofVerifier::new(leaves_ab).expect("ab");
1095        let v_ba = MerkleProofVerifier::new(leaves_ba).expect("ba");
1096        assert_ne!(v_ab.root(), v_ba.root());
1097    }
1098
1099    // -----------------------------------------------------------------------
1100    // Edge cases
1101    // -----------------------------------------------------------------------
1102
1103    #[test]
1104    fn test_empty_leaf_data() {
1105        // A tree containing a single empty leaf should work.
1106        let verifier = MerkleProofVerifier::new(vec![vec![]]).expect("empty leaf");
1107        assert_ne!(verifier.root(), MerkleHash::zero());
1108        let proof = verifier.generate_proof(0).expect("proof");
1109        assert!(verifier.verify_proof(&proof).expect("verify"));
1110    }
1111
1112    #[test]
1113    fn test_all_identical_leaves() {
1114        let leaves = vec![b"same".to_vec(); 4];
1115        let verifier = MerkleProofVerifier::new(leaves).expect("identical leaves");
1116        for i in 0..4 {
1117            let proof = verifier.generate_proof(i).expect("proof");
1118            assert!(verifier.verify_proof(&proof).expect("verify"));
1119        }
1120    }
1121
1122    #[test]
1123    fn test_large_leaf_data() {
1124        let big = vec![0xffu8; 4096];
1125        let verifier = MerkleProofVerifier::new(vec![big]).expect("big leaf");
1126        let proof = verifier.generate_proof(0).expect("proof");
1127        assert!(verifier.verify_proof(&proof).expect("verify"));
1128    }
1129
1130    #[test]
1131    fn test_binary_leaf_data() {
1132        let leaves: Vec<Vec<u8>> = (0u8..8)
1133            .map(|i| vec![i, i.wrapping_add(1), i.wrapping_add(2)])
1134            .collect();
1135        let verifier = MerkleProofVerifier::new(leaves).expect("binary leaves");
1136        for i in 0..8 {
1137            let proof = verifier.generate_proof(i).expect("proof");
1138            assert!(verifier.verify_proof(&proof).expect("verify"));
1139        }
1140    }
1141
1142    #[test]
1143    fn test_update_to_same_data_preserves_root() {
1144        let mut verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
1145        let old_root = verifier.root();
1146        // Update leaf 0 with the same data it already has.
1147        let data = "leaf-0".to_string().into_bytes();
1148        verifier.update_leaf(0, data).expect("update");
1149        assert_eq!(verifier.root(), old_root);
1150    }
1151
1152    #[test]
1153    fn test_next_power_of_two() {
1154        assert_eq!(next_power_of_two(1), 1);
1155        assert_eq!(next_power_of_two(2), 2);
1156        assert_eq!(next_power_of_two(3), 4);
1157        assert_eq!(next_power_of_two(4), 4);
1158        assert_eq!(next_power_of_two(5), 8);
1159        assert_eq!(next_power_of_two(7), 8);
1160        assert_eq!(next_power_of_two(8), 8);
1161        assert_eq!(next_power_of_two(9), 16);
1162        assert_eq!(next_power_of_two(100), 128);
1163    }
1164
1165    #[test]
1166    fn test_verify_update_tampered_new_hash_fails() {
1167        let mut verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
1168        let mut update = verifier.update_leaf(0, b"new".to_vec()).expect("update");
1169        // Tamper the new proof's leaf hash.
1170        update.new_proof.leaf_hash = MerkleHash::from_bytes([0xab; 8]);
1171        assert!(!verifier.verify_update(&update).expect("verify_update"));
1172    }
1173
1174    #[test]
1175    fn test_verify_update_tampered_changed_index_fails() {
1176        let mut verifier = MerkleProofVerifier::new(make_leaves(4)).expect("4 leaves");
1177        let mut update = verifier.update_leaf(1, b"new".to_vec()).expect("update");
1178        // Mismatch the changed_index.
1179        update.changed_index = 2;
1180        assert!(!verifier.verify_update(&update).expect("verify_update"));
1181    }
1182
1183    #[test]
1184    fn test_proof_leaf_hash_matches_data() {
1185        let leaves = make_leaves(4);
1186        let verifier = MerkleProofVerifier::new(leaves.clone()).expect("4 leaves");
1187        for (i, data) in leaves.iter().enumerate() {
1188            let proof = verifier.generate_proof(i).expect("proof");
1189            let expected_hash = MerkleHash::from_bytes(hash_leaf(data));
1190            assert_eq!(proof.leaf_hash, expected_hash, "leaf {i}");
1191        }
1192    }
1193}