diff --git a/plonky2/src/fri/recursive_verifier.rs b/plonky2/src/fri/recursive_verifier.rs index 2da264c7..1a3739b4 100644 --- a/plonky2/src/fri/recursive_verifier.rs +++ b/plonky2/src/fri/recursive_verifier.rs @@ -208,7 +208,7 @@ impl, const D: usize> CircuitBuilder { with_context!( self, &format!("verify {}'th initial Merkle proof", i), - self.verify_merkle_proof_with_cap_index::( + self.verify_merkle_proof_to_cap_with_cap_index::( evals.clone(), x_index_bits, cap_index, @@ -351,7 +351,7 @@ impl, const D: usize> CircuitBuilder { with_context!( self, "verify FRI round Merkle proof.", - self.verify_merkle_proof_with_cap_index::( + self.verify_merkle_proof_to_cap_with_cap_index::( flatten_target(evals), &coset_index_bits, cap_index, diff --git a/plonky2/src/fri/verifier.rs b/plonky2/src/fri/verifier.rs index 551c2c0f..ed44f0c4 100644 --- a/plonky2/src/fri/verifier.rs +++ b/plonky2/src/fri/verifier.rs @@ -8,7 +8,7 @@ use crate::fri::proof::{FriChallenges, FriInitialTreeProof, FriProof, FriQueryRo use crate::fri::structure::{FriBatchInfo, FriInstanceInfo, FriOpenings}; use crate::fri::{FriConfig, FriParams}; use crate::hash::hash_types::RichField; -use crate::hash::merkle_proofs::verify_merkle_proof; +use crate::hash::merkle_proofs::verify_merkle_proof_to_cap; use crate::hash::merkle_tree::MerkleCap; use crate::plonk::config::{GenericConfig, Hasher}; use crate::util::reducing::ReducingFactor; @@ -116,7 +116,7 @@ where [(); H::HASH_SIZE]:, { for ((evals, merkle_proof), cap) in proof.evals_proofs.iter().zip(initial_merkle_caps) { - verify_merkle_proof::(evals.clone(), x_index, cap, merkle_proof)?; + verify_merkle_proof_to_cap::(evals.clone(), x_index, cap, merkle_proof)?; } Ok(()) @@ -224,7 +224,7 @@ where challenges.fri_betas[i], ); - verify_merkle_proof::( + verify_merkle_proof_to_cap::( flatten(evals), coset_index, &proof.commit_phase_merkle_caps[i], diff --git a/plonky2/src/gadgets/split_join.rs b/plonky2/src/gadgets/split_join.rs index dff91bf6..cd2bbc93 100644 --- a/plonky2/src/gadgets/split_join.rs +++ b/plonky2/src/gadgets/split_join.rs @@ -13,7 +13,7 @@ impl, const D: usize> CircuitBuilder { /// bit of the integer, with little-endian ordering. /// Verifies that the decomposition is correct by using `k` `BaseSum<2>` gates /// with `k` such that `k * num_routed_wires >= num_bits`. - pub(crate) fn split_le(&mut self, integer: Target, num_bits: usize) -> Vec { + pub fn split_le(&mut self, integer: Target, num_bits: usize) -> Vec { if num_bits == 0 { return Vec::new(); } diff --git a/plonky2/src/hash/merkle_proofs.rs b/plonky2/src/hash/merkle_proofs.rs index 6ba1b817..90d55ce1 100644 --- a/plonky2/src/hash/merkle_proofs.rs +++ b/plonky2/src/hash/merkle_proofs.rs @@ -23,9 +23,24 @@ pub struct MerkleProofTarget { pub siblings: Vec, } +/// Verifies that the given leaf data is present at the given index in the Merkle tree with the +/// given root. +pub fn verify_merkle_proof>( + leaf_data: Vec, + leaf_index: usize, + merkle_root: H::Hash, + proof: &MerkleProof, +) -> Result<()> +where + [(); H::HASH_SIZE]:, +{ + let merkle_cap = MerkleCap(vec![merkle_root]); + verify_merkle_proof_to_cap(leaf_data, leaf_index, &merkle_cap, proof) +} + /// Verifies that the given leaf data is present at the given index in the Merkle tree with the /// given cap. -pub(crate) fn verify_merkle_proof>( +pub fn verify_merkle_proof_to_cap>( leaf_data: Vec, leaf_index: usize, merkle_cap: &MerkleCap, @@ -55,37 +70,40 @@ where impl, const D: usize> CircuitBuilder { /// Verifies that the given leaf data is present at the given index in the Merkle tree with the - /// given cap. The index is given by it's little-endian bits. - #[cfg(test)] - pub(crate) fn verify_merkle_proof>( + /// given root. The index is given by its little-endian bits. + pub fn verify_merkle_proof>( + &mut self, + leaf_data: Vec, + leaf_index_bits: &[BoolTarget], + merkle_root: HashOutTarget, + proof: &MerkleProofTarget, + ) { + let merkle_cap = MerkleCapTarget(vec![merkle_root]); + self.verify_merkle_proof_to_cap::(leaf_data, leaf_index_bits, &merkle_cap, proof); + } + + /// Verifies that the given leaf data is present at the given index in the Merkle tree with the + /// given cap. The index is given by its little-endian bits. + pub fn verify_merkle_proof_to_cap>( &mut self, leaf_data: Vec, leaf_index_bits: &[BoolTarget], merkle_cap: &MerkleCapTarget, proof: &MerkleProofTarget, ) { - let zero = self.zero(); - let mut state: HashOutTarget = self.hash_or_noop::(leaf_data); - - for (&bit, &sibling) in leaf_index_bits.iter().zip(&proof.siblings) { - let mut perm_inputs = [zero; SPONGE_WIDTH]; - perm_inputs[..4].copy_from_slice(&state.elements); - perm_inputs[4..8].copy_from_slice(&sibling.elements); - let outputs = self.permute_swapped::(perm_inputs, bit); - state = HashOutTarget::from_vec(outputs[0..4].to_vec()); - } - - let index = self.le_sum(leaf_index_bits[proof.siblings.len()..].iter().copied()); - - for i in 0..4 { - let result = - self.random_access(index, merkle_cap.0.iter().map(|h| h.elements[i]).collect()); - self.connect(result, state.elements[i]); - } + let cap_index = self.le_sum(leaf_index_bits[proof.siblings.len()..].iter().copied()); + self.verify_merkle_proof_to_cap_with_cap_index::( + leaf_data, + leaf_index_bits, + cap_index, + merkle_cap, + proof, + ); } - /// Same as `verify_merkle_proof` but with the final "cap index" as extra parameter. - pub(crate) fn verify_merkle_proof_with_cap_index>( + /// Same as `verify_merkle_proof_to_cap`, except with the final "cap index" as separate parameter, + /// rather than being contained in `leaf_index_bits`. + pub(crate) fn verify_merkle_proof_to_cap_with_cap_index>( &mut self, leaf_data: Vec, leaf_index_bits: &[BoolTarget], @@ -176,7 +194,7 @@ mod tests { pw.set_target(data[j], tree.leaves[i][j]); } - builder.verify_merkle_proof::<>::InnerHasher>( + builder.verify_merkle_proof_to_cap::<>::InnerHasher>( data, &i_bits, &cap_t, &proof_t, ); diff --git a/plonky2/src/hash/merkle_tree.rs b/plonky2/src/hash/merkle_tree.rs index 0c6b223c..69cf2ef9 100644 --- a/plonky2/src/hash/merkle_tree.rs +++ b/plonky2/src/hash/merkle_tree.rs @@ -209,7 +209,7 @@ mod tests { use plonky2_field::extension::Extendable; use super::*; - use crate::hash::merkle_proofs::verify_merkle_proof; + use crate::hash::merkle_proofs::verify_merkle_proof_to_cap; use crate::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; fn random_data(n: usize, k: usize) -> Vec> { @@ -226,7 +226,7 @@ mod tests { let tree = MerkleTree::::new(leaves.clone(), cap_height); for (i, leaf) in leaves.into_iter().enumerate() { let proof = tree.prove(i); - verify_merkle_proof(leaf, i, &tree.cap, &proof)?; + verify_merkle_proof_to_cap(leaf, i, &tree.cap, &proof)?; } Ok(()) }