From c402255ea5ef6510a583b79e49f4246dc618c362 Mon Sep 17 00:00:00 2001 From: Santo Cariotti Date: Wed, 25 Jun 2025 10:31:21 +0200 Subject: Proofer uses self hasher on `verify` --- README.md | 15 +++++++++------ benches/bigfile.rs | 4 ++-- examples/proofer_blake3.rs | 5 ++--- src/lib.rs | 9 +++------ src/proof.rs | 45 +++++++++++++++++++++++++-------------------- 5 files changed, 41 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 4f1e734..9ed364a 100644 --- a/README.md +++ b/README.md @@ -54,11 +54,11 @@ fn main() { let hasher = Blake3Hasher::new(); let tree = MerkleTree::new(hasher.clone(), file_contents.clone()); - let proofer = DefaultProofer::new(&hasher, tree.leaves()); + let proofer = DefaultProofer::new(hasher, tree.leaves()); let proof = proofer.generate(0).expect("Couldn't generate proof"); assert!(tree.root().hash() == root_hash); - assert!(proofer.verify(&proof, std::fs::read(&filenames[0]).unwrap(), tree.root().hash(), &hasher)); + assert!(proofer.verify(&proof, std::fs::read(&filenames[0]).unwrap(), tree.root().hash())); } ``` @@ -86,12 +86,15 @@ use mt_rs::proof::Proofer; pub struct FooProofer; -impl Proofer for FooProofer { +impl Proofer for FooProfer +where + H: Hasher, +{ fn generate(&self, index: usize) -> Option { // ... } - fn verify(&self, proof: &MerkleProof, data: T, root_hash: &str, hasher: &dyn Hasher) -> bool + fn verify(&self, proof: &MerkleProof, data: T, root_hash: &str) -> bool where T: AsRef<[u8]>, { @@ -110,10 +113,10 @@ let tree = MerkleTree::new(hasher.clone(), data); println!("{}", tree.root().hash()); -let proofer = FooProofer::new(&hasher, tree.leaves().clone()); +let proofer = FooProofer::new(hasher, tree.leaves().clone()); let proof = proofer.generate(0).unwrap(); -assert!(proofer.verify(&proof, data[0], tree.root().hash(), &hasher)); +assert!(proofer.verify(&proof, data[0], tree.root().hash())); ``` ## Configuration diff --git a/benches/bigfile.rs b/benches/bigfile.rs index b2b013d..3d2088d 100644 --- a/benches/bigfile.rs +++ b/benches/bigfile.rs @@ -48,13 +48,13 @@ fn cleanup_files(filenames: &Vec) -> std::io::Result<()> { fn test_merkle_tree(hasher: H, files: &Vec>) { let tree = MerkleTree::new(hasher.clone(), files); - let proofer = DefaultProofer::new(&hasher, tree.leaves().clone()); + let proofer = DefaultProofer::new(hasher, tree.leaves().clone()); let root = tree.root(); let root_hash = root.hash(); for i in 0..files.len() { let proof = proofer.generate(i).expect("proof generation failed"); - assert!(proofer.verify(&proof, &files[i], root_hash, &hasher)); + assert!(proofer.verify(&proof, &files[i], root_hash)); } } diff --git a/examples/proofer_blake3.rs b/examples/proofer_blake3.rs index 62d1429..ca38d6f 100644 --- a/examples/proofer_blake3.rs +++ b/examples/proofer_blake3.rs @@ -33,7 +33,7 @@ fn main() { } let hasher = Blake3Hasher::new(); - let proofer = DefaultProofer::new(&hasher, nodes); + let proofer = DefaultProofer::new(hasher, nodes); let proof = proofer.generate(0).expect("Couldn't generate proof"); println!( @@ -41,8 +41,7 @@ fn main() { proofer.verify( &proof, std::fs::read(&filenames[0]).unwrap(), - &root_hash[..], - &hasher + &root_hash[..] ) ); } diff --git a/src/lib.rs b/src/lib.rs index 497dbac..b23f7d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,22 +26,20 @@ //! "a08c44656fb3f561619b8747a0d1dabe97126d9ed6e0cafbd7ce08ebe12d55ca" //! ); //! -//! let proofer = DefaultProofer::new(&hasher, tree.leaves().clone()); +//! let proofer = DefaultProofer::new(hasher, tree.leaves().clone()); //! //! let proof = proofer.generate(0).expect("proof generation failed"); //! //! assert!(proofer.verify( //! &proof, //! &files[0], -//! "a08c44656fb3f561619b8747a0d1dabe97126d9ed6e0cafbd7ce08ebe12d55ca", -//! &hasher +//! "a08c44656fb3f561619b8747a0d1dabe97126d9ed6e0cafbd7ce08ebe12d55ca" //! )); //! //! assert!(!proofer.verify( //! &proof, //! &files[0], -//! "a08c44656fb3f561619b87_NOT_VALID_HASH_9ed6e0cafbd7ce08ebe12d55ca", -//! &hasher +//! "a08c44656fb3f561619b87_NOT_VALID_HASH_9ed6e0cafbd7ce08ebe12d55ca" //! )); //! //! let proof = proofer.generate(1).expect("proof generation failed"); @@ -50,7 +48,6 @@ //! &proof, //! &files[1], //! "a08c44656fb3f561619b8747a0d1dabe97126d9ed6e0cafbd7ce08ebe12d55ca", -//! &hasher //! )); //! //! ``` diff --git a/src/proof.rs b/src/proof.rs index c893b08..d835b87 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -42,28 +42,33 @@ pub trait Proofer { /// * `proof` - The Merkle proof. /// * `data` - The original data to verify. /// * `root_hash` - The expected root hash of the tree. - /// * `hasher` - The hasher used to construct the tree. /// /// # Returns /// /// `true` if the proof is valid and the data exists in the tree, `false` otherwise. - fn verify(&self, proof: &MerkleProof, data: T, root_hash: &str, hasher: &dyn Hasher) -> bool + fn verify(&self, proof: &MerkleProof, data: T, root_hash: &str) -> bool where T: AsRef<[u8]>; } -pub struct DefaultProofer<'a> { - hasher: &'a dyn Hasher, +pub struct DefaultProofer { + hasher: H, leaves: Vec, } -impl<'a> DefaultProofer<'a> { - pub fn new(hasher: &'a dyn Hasher, leaves: Vec) -> Self { +impl DefaultProofer +where + H: Hasher, +{ + pub fn new(hasher: H, leaves: Vec) -> Self { Self { hasher, leaves } } } -impl Proofer for DefaultProofer<'_> { +impl Proofer for DefaultProofer +where + H: Hasher, +{ fn generate(&self, index: usize) -> Option { if index >= self.leaves.len() { return None; @@ -122,12 +127,12 @@ impl Proofer for DefaultProofer<'_> { }) } - fn verify(&self, proof: &MerkleProof, data: T, root_hash: &str, hasher: &dyn Hasher) -> bool + fn verify(&self, proof: &MerkleProof, data: T, root_hash: &str) -> bool where T: AsRef<[u8]>, { // Start with the hash of the data - let mut current_hash = hasher.hash(data.as_ref()); + let mut current_hash = self.hasher.hash(data.as_ref()); // Walk up the tree using the proof path for proof_node in &proof.path { @@ -135,7 +140,7 @@ impl Proofer for DefaultProofer<'_> { NodeChildType::Left => format!("{}{}", proof_node.hash, current_hash), NodeChildType::Right => format!("{}{}", current_hash, proof_node.hash), }; - current_hash = hasher.hash(combined.as_bytes()); + current_hash = self.hasher.hash(combined.as_bytes()); } // Check if the computed root matches the expected root @@ -154,12 +159,12 @@ mod tests { let hasher = DummyHasher; let data = vec!["a", "b", "c", "d"]; let tree = MerkleTree::new(hasher.clone(), data.clone()); - let proofer = DefaultProofer::new(&hasher, tree.leaves()); + let proofer = DefaultProofer::new(hasher, tree.leaves()); for (index, item) in data.iter().enumerate() { let proof = proofer.generate(index).unwrap(); - assert!(proofer.verify(&proof, item, tree.root().hash(), &hasher)); + assert!(proofer.verify(&proof, item, tree.root().hash())); } } @@ -168,12 +173,12 @@ mod tests { let hasher = SHA256Hasher::new(); let data = vec!["a", "b", "c", "d"]; let tree = MerkleTree::new(hasher.clone(), data.clone()); - let proofer = DefaultProofer::new(&hasher, tree.leaves().clone()); + let proofer = DefaultProofer::new(hasher, tree.leaves().clone()); for (index, item) in data.iter().enumerate() { let proof = proofer.generate(index).unwrap(); - assert!(proofer.verify(&proof, item, tree.root().hash(), &hasher)); + assert!(proofer.verify(&proof, item, tree.root().hash())); } } @@ -182,15 +187,15 @@ mod tests { let hasher = SHA256Hasher::new(); let data = vec!["a", "b", "c", "d"]; let tree = MerkleTree::new(hasher.clone(), data.clone()); - let proofer = DefaultProofer::new(&hasher, tree.leaves().clone()); + let proofer = DefaultProofer::new(hasher, tree.leaves().clone()); let proof = proofer.generate(0).unwrap(); - assert!(proofer.verify(&proof, b"a", tree.root().hash(), &hasher)); - assert!(!proofer.verify(&proof, b"b", tree.root().hash(), &hasher)); - assert!(!proofer.verify(&proof, b"c", tree.root().hash(), &hasher)); - assert!(!proofer.verify(&proof, b"d", tree.root().hash(), &hasher)); + assert!(proofer.verify(&proof, b"a", tree.root().hash())); + assert!(!proofer.verify(&proof, b"b", tree.root().hash())); + assert!(!proofer.verify(&proof, b"c", tree.root().hash())); + assert!(!proofer.verify(&proof, b"d", tree.root().hash())); - assert!(!proofer.verify(&proof, b"e", tree.root().hash(), &hasher)); + assert!(!proofer.verify(&proof, b"e", tree.root().hash())); } } -- cgit v1.2.3-71-g8e6c