diff options
| author | Santo Cariotti <santo@dcariotti.me> | 2025-06-25 08:31:21 +0000 |
|---|---|---|
| committer | Santo Cariotti <santo@dcariotti.me> | 2025-06-25 08:31:21 +0000 |
| commit | c402255ea5ef6510a583b79e49f4246dc618c362 (patch) | |
| tree | 1ad4a10d8aaabce31877d4f750c596c24a3537b2 | |
| parent | 7bdb59e386b93c37cdc2c2b88fc2945ab0e64d57 (diff) | |
Proofer uses self hasher on `verify`
| -rw-r--r-- | README.md | 15 | ||||
| -rw-r--r-- | benches/bigfile.rs | 4 | ||||
| -rw-r--r-- | examples/proofer_blake3.rs | 5 | ||||
| -rw-r--r-- | src/lib.rs | 9 | ||||
| -rw-r--r-- | src/proof.rs | 45 |
5 files changed, 41 insertions, 37 deletions
@@ -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<H> Proofer for FooProfer<H> +where + H: Hasher, +{ fn generate(&self, index: usize) -> Option<MerkleProof> { // ... } - fn verify<T>(&self, proof: &MerkleProof, data: T, root_hash: &str, hasher: &dyn Hasher) -> bool + fn verify<T>(&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<String>) -> std::io::Result<()> { fn test_merkle_tree<H: Hasher + Clone + 'static>(hasher: H, files: &Vec<Vec<u8>>) { 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[..] ) ); } @@ -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<T>(&self, proof: &MerkleProof, data: T, root_hash: &str, hasher: &dyn Hasher) -> bool + fn verify<T>(&self, proof: &MerkleProof, data: T, root_hash: &str) -> bool where T: AsRef<[u8]>; } -pub struct DefaultProofer<'a> { - hasher: &'a dyn Hasher, +pub struct DefaultProofer<H: Hasher> { + hasher: H, leaves: Vec<Node>, } -impl<'a> DefaultProofer<'a> { - pub fn new(hasher: &'a dyn Hasher, leaves: Vec<Node>) -> Self { +impl<H> DefaultProofer<H> +where + H: Hasher, +{ + pub fn new(hasher: H, leaves: Vec<Node>) -> Self { Self { hasher, leaves } } } -impl Proofer for DefaultProofer<'_> { +impl<H> Proofer for DefaultProofer<H> +where + H: Hasher, +{ fn generate(&self, index: usize) -> Option<MerkleProof> { if index >= self.leaves.len() { return None; @@ -122,12 +127,12 @@ impl Proofer for DefaultProofer<'_> { }) } - fn verify<T>(&self, proof: &MerkleProof, data: T, root_hash: &str, hasher: &dyn Hasher) -> bool + fn verify<T>(&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())); } } |
