From d52246b5b7050186b8ae3e36b4e72ac722fdf0c2 Mon Sep 17 00:00:00 2001 From: noah figueras Date: Tue, 23 Jul 2024 06:58:58 +0200 Subject: [PATCH 1/3] added support for multiproof generation within Prover --- ssz-rs/src/merkleization/multiproofs.rs | 2 +- ssz-rs/src/merkleization/proofs.rs | 69 +++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/ssz-rs/src/merkleization/multiproofs.rs b/ssz-rs/src/merkleization/multiproofs.rs index 1882c13e..bf1f3ebd 100644 --- a/ssz-rs/src/merkleization/multiproofs.rs +++ b/ssz-rs/src/merkleization/multiproofs.rs @@ -30,7 +30,7 @@ fn get_path_indices(tree_index: GeneralizedIndex) -> Vec { result } -fn get_helper_indices(indices: &[GeneralizedIndex]) -> Vec { +pub fn get_helper_indices(indices: &[GeneralizedIndex]) -> Vec { let mut all_helper_indices = HashSet::new(); let mut all_path_indices = HashSet::new(); diff --git a/ssz-rs/src/merkleization/proofs.rs b/ssz-rs/src/merkleization/proofs.rs index abbc7244..2efc14aa 100644 --- a/ssz-rs/src/merkleization/proofs.rs +++ b/ssz-rs/src/merkleization/proofs.rs @@ -3,8 +3,8 @@ pub use crate::merkleization::generalized_index::log_2; use crate::{ lib::*, merkleization::{ - compute_merkle_tree, GeneralizedIndex, GeneralizedIndexable, MerkleizationError as Error, - Node, Path, + compute_merkle_tree, multiproofs, GeneralizedIndex, GeneralizedIndexable, + MerkleizationError as Error, Node, Path, }, }; use sha2::{Digest, Sha256}; @@ -165,6 +165,50 @@ pub trait Prove: GeneralizedIndexable { prover.compute_proof(self)?; Ok(prover.into()) } + + /// Compute a Multi Merkle proof of `Self` at the type's `paths`, along with the root of the Merkle + /// tree as a witness value. + fn multi_prove(&self, paths: &[Path]) -> Result<(MultiProof, Node), Error> { + let indices: Vec = + paths.iter().map(|x| Self::generalized_index(x).unwrap()).collect(); + let helpers = multiproofs::get_helper_indices(&indices); + let mut proof = MultiProof { leaves: vec![], branch: vec![], indices: vec![] }; + let mut witness: Node = Node::ZERO; + + for index in indices.iter() { + let mut prover = Prover::from(*index); + prover.compute_proof(self)?; + proof.leaves.push(prover.proof.leaf); + proof.indices.push(prover.proof.index); + witness = prover.witness; + } + + for helper in helpers.iter() { + let mut prover = Prover::from(*helper); + prover.compute_proof(self)?; + proof.branch.push(prover.proof.leaf); + } + + Ok((proof, witness)) + } +} + +/// Contains data necessary to verify `leaf` was included under some witness "root" node +/// at the generalized position `index`. +#[derive(Debug, PartialEq, Eq)] +pub struct MultiProof { + pub leaves: Vec, + pub branch: Vec, + pub indices: Vec, +} + +impl MultiProof { + /// Verify `self` against the provided `root` witness node. + /// This `root` is the hash tree root of the SSZ object that produced the proof. + /// See `Prover` for further information. + pub fn verify(&self, root: Node) -> Result<(), Error> { + multiproofs::verify_merkle_multiproof(&self.leaves, &self.branch, &self.indices, root) + } } /// Contains data necessary to verify `leaf` was included under some witness "root" node @@ -207,7 +251,7 @@ pub fn is_valid_merkle_branch( root: Node, ) -> Result<(), Error> { if branch.len() != depth { - return Err(Error::InvalidProof) + return Err(Error::InvalidProof); } let mut derived_root = leaf; @@ -336,4 +380,23 @@ pub(crate) mod tests { let data = false; compute_and_verify_proof_for_path(&data, &[]); } + + #[test] + fn test_generate_multi_proofs() { + #[derive(PartialEq, Eq, Debug, Default, SimpleSerialize)] + struct TestContainer { + a: u64, + b: List, + c: u8, + } + let data = TestContainer { + a: 18745094, + b: List::::try_from(vec![200, 50, 40, 80]).unwrap(), + c: 240, + }; + + let (proof, witness) = + data.multi_prove(&[&["a".into()], &["b".into(), 0.into()], &["c".into()]]).unwrap(); + assert!(proof.verify(witness).is_ok()); + } } From dadb9c3904ee33f9a5414a410a60991260414a14 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 30 Aug 2024 11:50:14 -0600 Subject: [PATCH 2/3] Update ssz-rs/src/merkleization/proofs.rs --- ssz-rs/src/merkleization/proofs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssz-rs/src/merkleization/proofs.rs b/ssz-rs/src/merkleization/proofs.rs index 2efc14aa..f87a8554 100644 --- a/ssz-rs/src/merkleization/proofs.rs +++ b/ssz-rs/src/merkleization/proofs.rs @@ -251,7 +251,7 @@ pub fn is_valid_merkle_branch( root: Node, ) -> Result<(), Error> { if branch.len() != depth { - return Err(Error::InvalidProof); + return Err(Error::InvalidProof) } let mut derived_root = leaf; From fdc545dc7d6083a3d1dfb3d053f4fab392ec4380 Mon Sep 17 00:00:00 2001 From: noah figueras Date: Wed, 11 Sep 2024 05:10:21 +0200 Subject: [PATCH 3/3] fix fmt --- ssz-rs/src/merkleization/proofs.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ssz-rs/src/merkleization/proofs.rs b/ssz-rs/src/merkleization/proofs.rs index f87a8554..a5629cd3 100644 --- a/ssz-rs/src/merkleization/proofs.rs +++ b/ssz-rs/src/merkleization/proofs.rs @@ -166,8 +166,8 @@ pub trait Prove: GeneralizedIndexable { Ok(prover.into()) } - /// Compute a Multi Merkle proof of `Self` at the type's `paths`, along with the root of the Merkle - /// tree as a witness value. + /// Compute a Multi Merkle proof of `Self` at the type's `paths`, along with the root of the + /// Merkle tree as a witness value. fn multi_prove(&self, paths: &[Path]) -> Result<(MultiProof, Node), Error> { let indices: Vec = paths.iter().map(|x| Self::generalized_index(x).unwrap()).collect(); @@ -251,7 +251,7 @@ pub fn is_valid_merkle_branch( root: Node, ) -> Result<(), Error> { if branch.len() != depth { - return Err(Error::InvalidProof) + return Err(Error::InvalidProof); } let mut derived_root = leaf;