mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 06:13:07 +00:00
Tweak Merkle proof API and make it public (#588)
- Add `_to_cap` to existing methods for clarity - Add variants which deal with Merkle roots instead of caps - Simplify `verify_merkle_proof_to_cap` - it can call `verify_merkle_proof_to_cap_with_cap_index` - Make them all public except `verify_merkle_proof_to_cap_with_cap_index`, which is pretty niche
This commit is contained in:
parent
e3834a5335
commit
dec0765fb5
@ -208,7 +208,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
with_context!(
|
||||
self,
|
||||
&format!("verify {}'th initial Merkle proof", i),
|
||||
self.verify_merkle_proof_with_cap_index::<H>(
|
||||
self.verify_merkle_proof_to_cap_with_cap_index::<H>(
|
||||
evals.clone(),
|
||||
x_index_bits,
|
||||
cap_index,
|
||||
@ -351,7 +351,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
with_context!(
|
||||
self,
|
||||
"verify FRI round Merkle proof.",
|
||||
self.verify_merkle_proof_with_cap_index::<C::Hasher>(
|
||||
self.verify_merkle_proof_to_cap_with_cap_index::<C::Hasher>(
|
||||
flatten_target(evals),
|
||||
&coset_index_bits,
|
||||
cap_index,
|
||||
|
||||
@ -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::<F, H>(evals.clone(), x_index, cap, merkle_proof)?;
|
||||
verify_merkle_proof_to_cap::<F, H>(evals.clone(), x_index, cap, merkle_proof)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -224,7 +224,7 @@ where
|
||||
challenges.fri_betas[i],
|
||||
);
|
||||
|
||||
verify_merkle_proof::<F, C::Hasher>(
|
||||
verify_merkle_proof_to_cap::<F, C::Hasher>(
|
||||
flatten(evals),
|
||||
coset_index,
|
||||
&proof.commit_phase_merkle_caps[i],
|
||||
|
||||
@ -13,7 +13,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// 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<BoolTarget> {
|
||||
pub fn split_le(&mut self, integer: Target, num_bits: usize) -> Vec<BoolTarget> {
|
||||
if num_bits == 0 {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
@ -23,9 +23,24 @@ pub struct MerkleProofTarget {
|
||||
pub siblings: Vec<HashOutTarget>,
|
||||
}
|
||||
|
||||
/// 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<F: RichField, H: Hasher<F>>(
|
||||
leaf_data: Vec<F>,
|
||||
leaf_index: usize,
|
||||
merkle_root: H::Hash,
|
||||
proof: &MerkleProof<F, H>,
|
||||
) -> 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<F: RichField, H: Hasher<F>>(
|
||||
pub fn verify_merkle_proof_to_cap<F: RichField, H: Hasher<F>>(
|
||||
leaf_data: Vec<F>,
|
||||
leaf_index: usize,
|
||||
merkle_cap: &MerkleCap<F, H>,
|
||||
@ -55,37 +70,40 @@ where
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// 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<H: AlgebraicHasher<F>>(
|
||||
/// given root. The index is given by its little-endian bits.
|
||||
pub fn verify_merkle_proof<H: AlgebraicHasher<F>>(
|
||||
&mut self,
|
||||
leaf_data: Vec<Target>,
|
||||
leaf_index_bits: &[BoolTarget],
|
||||
merkle_root: HashOutTarget,
|
||||
proof: &MerkleProofTarget,
|
||||
) {
|
||||
let merkle_cap = MerkleCapTarget(vec![merkle_root]);
|
||||
self.verify_merkle_proof_to_cap::<H>(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<H: AlgebraicHasher<F>>(
|
||||
&mut self,
|
||||
leaf_data: Vec<Target>,
|
||||
leaf_index_bits: &[BoolTarget],
|
||||
merkle_cap: &MerkleCapTarget,
|
||||
proof: &MerkleProofTarget,
|
||||
) {
|
||||
let zero = self.zero();
|
||||
let mut state: HashOutTarget = self.hash_or_noop::<H>(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::<H>(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::<H>(
|
||||
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<H: AlgebraicHasher<F>>(
|
||||
/// 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<H: AlgebraicHasher<F>>(
|
||||
&mut self,
|
||||
leaf_data: Vec<Target>,
|
||||
leaf_index_bits: &[BoolTarget],
|
||||
@ -176,7 +194,7 @@ mod tests {
|
||||
pw.set_target(data[j], tree.leaves[i][j]);
|
||||
}
|
||||
|
||||
builder.verify_merkle_proof::<<C as GenericConfig<D>>::InnerHasher>(
|
||||
builder.verify_merkle_proof_to_cap::<<C as GenericConfig<D>>::InnerHasher>(
|
||||
data, &i_bits, &cap_t, &proof_t,
|
||||
);
|
||||
|
||||
|
||||
@ -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<F: RichField>(n: usize, k: usize) -> Vec<Vec<F>> {
|
||||
@ -226,7 +226,7 @@ mod tests {
|
||||
let tree = MerkleTree::<F, C::Hasher>::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(())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user