From d2a5e679803e6d215f9c5d90cf53aac1287237cb Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 7 Oct 2021 19:30:39 +0200 Subject: [PATCH] Somewhat working --- src/fri/proof.rs | 33 ++++++++++++++++++++++------- src/fri/verifier.rs | 26 +++++++++++++++-------- src/plonk/get_challenges.rs | 17 ++++++++++----- src/plonk/proof.rs | 41 +++++++++++++++++++++++++++++-------- src/plonk/verifier.rs | 14 ++++++++++--- 5 files changed, 99 insertions(+), 32 deletions(-) diff --git a/src/fri/proof.rs b/src/fri/proof.rs index 793d0798..130cf57d 100644 --- a/src/fri/proof.rs +++ b/src/fri/proof.rs @@ -14,6 +14,7 @@ use crate::hash::path_compression::{compress_merkle_proofs, decompress_merkle_pr use crate::iop::target::Target; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::plonk_common::PolynomialsIndexBlinding; +use crate::plonk::proof::ProofChallenges; use crate::polynomial::polynomial::PolynomialCoeffs; /// Evaluations and Merkle proof produced by the prover in a FRI query step. @@ -164,9 +165,12 @@ impl, const D: usize> FriProof { initial_trees_proofs[i].push(proof); } for (i, query_step) in steps.into_iter().enumerate() { + let index_within_coset = index & ((1 << reduction_arity_bits[i]) - 1); index >>= reduction_arity_bits[i]; steps_indices[i].push(index); - steps_evals[i].push(query_step.evals); + let mut evals = query_step.evals; + evals.remove(index_within_coset); + steps_evals[i].push(evals); steps_proofs[i].push(query_step.merkle_proof); } } @@ -228,9 +232,9 @@ impl, const D: usize> FriProof { impl, const D: usize> CompressedFriProof { /// Decompress all the Merkle paths in the FRI proof and reinsert duplicate indices. - pub fn decompress( + pub(crate) fn decompress( self, - indices: &[usize], + challenges: &ProofChallenges, common_data: &CommonCircuitData, ) -> FriProof { let CompressedFriProof { @@ -240,6 +244,16 @@ impl, const D: usize> CompressedFriProof { pow_witness, .. } = self; + let ProofChallenges { + fri_query_indices: indices, + fri_query_inferred_elements, + .. + } = challenges; + let fri_query_inferred_elements = if let Some(v) = fri_query_inferred_elements { + v + } else { + panic!() + }; let cap_height = common_data.config.cap_height; let reduction_arity_bits = &common_data.fri_params.reduction_arity_bits; let num_reductions = reduction_arity_bits.len(); @@ -267,7 +281,7 @@ impl, const D: usize> CompressedFriProof { }) .collect::>(); - for mut index in indices.iter().copied() { + for (round, mut index) in indices.iter().copied().enumerate() { let initial_trees_proof = query_round_proofs.initial_trees_proofs[&index].clone(); for (i, (leaves_data, proof)) in initial_trees_proof.evals_proofs.into_iter().enumerate() @@ -277,11 +291,16 @@ impl, const D: usize> CompressedFriProof { initial_trees_proofs[i].push(proof); } for i in 0..num_reductions { + let index_within_coset = index & ((1 << reduction_arity_bits[i]) - 1); index >>= reduction_arity_bits[i]; - let query_step = query_round_proofs.steps[i][&index].clone(); + let FriQueryStep { + mut evals, + merkle_proof, + } = query_round_proofs.steps[i][&index].clone(); steps_indices[i].push(index); - steps_evals[i].push(flatten(&query_step.evals)); - steps_proofs[i].push(query_step.merkle_proof); + evals.insert(index_within_coset, fri_query_inferred_elements[round][i]); + steps_evals[i].push(flatten(&evals)); + steps_proofs[i].push(merkle_proof); } } diff --git a/src/fri/verifier.rs b/src/fri/verifier.rs index 0aae124d..23739639 100644 --- a/src/fri/verifier.rs +++ b/src/fri/verifier.rs @@ -15,7 +15,7 @@ use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place}; /// Computes P'(x^arity) from {P(x*g^i)}_(i=0..arity), where g is a `arity`-th root of unity /// and P' is the FRI reduced polynomial. -fn compute_evaluation, const D: usize>( +pub(crate) fn compute_evaluation, const D: usize>( x: F, x_index_within_coset: usize, arity_bits: usize, @@ -83,10 +83,11 @@ pub(crate) fn verify_fri_proof, const D: usize>( let precomputed_reduced_evals = PrecomputedReducedEvals::from_os_and_alpha(os, challenges.fri_alpha); - for (&x_index, round_proof) in challenges + for (round, (&x_index, round_proof)) in challenges .fri_query_indices .iter() .zip(&proof.query_round_proofs) + .enumerate() { fri_verifier_query_round( challenges, @@ -95,6 +96,7 @@ pub(crate) fn verify_fri_proof, const D: usize>( &proof, x_index, n, + round, round_proof, common_data, )?; @@ -218,6 +220,7 @@ fn fri_verifier_query_round, const D: usize>( proof: &FriProof, mut x_index: usize, n: usize, + round: usize, round_proof: &FriQueryRound, common_data: &CommonCircuitData, ) -> Result<()> { @@ -259,13 +262,18 @@ fn fri_verifier_query_round, const D: usize>( ensure!(evals[x_index_within_coset] == old_eval); // Infer P(y) from {P(x)}_{x^arity=y}. - old_eval = compute_evaluation( - subgroup_x, - x_index_within_coset, - arity_bits, - evals, - challenges.fri_betas[i], - ); + old_eval = if let Some(v) = &challenges.fri_query_inferred_elements { + dbg!("yo"); + v[round][i] + } else { + compute_evaluation( + subgroup_x, + x_index_within_coset, + arity_bits, + evals, + challenges.fri_betas[i], + ) + }; verify_merkle_proof( flatten(evals), diff --git a/src/plonk/get_challenges.rs b/src/plonk/get_challenges.rs index 5815774f..e3fa54c8 100644 --- a/src/plonk/get_challenges.rs +++ b/src/plonk/get_challenges.rs @@ -138,7 +138,7 @@ impl, const D: usize> CompressedProofWithPublicInpu challenger.observe_cap(cap); challenger.get_extension_challenge() }) - .collect(); + .collect::>(); challenger.observe_extension_elements(&self.proof.opening_proof.final_poly.coeffs); @@ -155,7 +155,7 @@ impl, const D: usize> CompressedProofWithPublicInpu let fri_query_indices = (0..num_fri_queries) .map(|_| challenger.get_challenge().to_canonical_u64() as usize % lde_size) - .collect(); + .collect::>(); let mut fri_query_inferred_elements = Vec::new(); let log_n = common_data.degree_bits + common_data.config.rate_bits; @@ -164,16 +164,23 @@ impl, const D: usize> CompressedProofWithPublicInpu let mut x_index = fri_query_indices[query_round]; let mut subgroup_x = F::MULTIPLICATIVE_GROUP_GENERATOR * F::primitive_root_of_unity(log_n).exp_u64(reverse_bits(x_index, log_n) as u64); - let evals = &self.proof.opening_proof..steps[query_round].evals; - for &arity_bits in &common_data.config.fri_config.reduction_strategy { + for (i, &arity_bits) in common_data + .fri_params + .reduction_arity_bits + .iter() + .enumerate() + { let arity = 1 << arity_bits; + let evals = &self.proof.opening_proof.query_round_proofs.steps[i] + [&(x_index >> arity_bits)] + .evals; let x_index_within_coset = x_index & (arity - 1); let elmt = compute_evaluation( subgroup_x, x_index_within_coset, arity_bits, evals, - challenges.fri_betas[i], + fri_betas[i], ); query_round_inferred_elements.push(elmt); subgroup_x = subgroup_x.exp_power_of_2(arity_bits); diff --git a/src/plonk/proof.rs b/src/plonk/proof.rs index 4021f3cb..0bc8ef96 100644 --- a/src/plonk/proof.rs +++ b/src/plonk/proof.rs @@ -10,7 +10,8 @@ use crate::hash::hash_types::{HashOut, MerkleCapTarget}; use crate::hash::hashing::hash_n_to_hash; use crate::hash::merkle_tree::MerkleCap; use crate::iop::target::Target; -use crate::plonk::circuit_data::CommonCircuitData; +use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; +use crate::plonk::verifier::verify_with_challenges; use crate::util::serialization::Buffer; #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] @@ -118,9 +119,9 @@ pub struct CompressedProof, const D: usize> { impl, const D: usize> CompressedProof { /// Decompress the proof. - pub fn decompress( + pub(crate) fn decompress( self, - indices: &[usize], + challenges: &ProofChallenges, common_data: &CommonCircuitData, ) -> Proof { let CompressedProof { @@ -136,7 +137,7 @@ impl, const D: usize> CompressedProof { plonk_zs_partial_products_cap, quotient_polys_cap, openings, - opening_proof: opening_proof.decompress(indices, common_data), + opening_proof: opening_proof.decompress(challenges, common_data), } } } @@ -153,14 +154,33 @@ impl, const D: usize> CompressedProofWithPublicInpu self, common_data: &CommonCircuitData, ) -> anyhow::Result> { - let indices = self.fri_query_indices(common_data)?; - let compressed_proof = self.proof.decompress(&indices, common_data); + let challenges = self.get_challenges(common_data)?; + let compressed_proof = self.proof.decompress(&challenges, common_data); Ok(ProofWithPublicInputs { public_inputs: self.public_inputs, proof: compressed_proof, }) } + pub(crate) fn verify( + self, + verifier_data: &VerifierOnlyCircuitData, + common_data: &CommonCircuitData, + ) -> anyhow::Result<()> { + let challenges = self.get_challenges(common_data)?; + dbg!(&challenges.fri_query_inferred_elements); + let compressed_proof = self.proof.decompress(&challenges, common_data); + verify_with_challenges( + ProofWithPublicInputs { + public_inputs: self.public_inputs, + proof: compressed_proof, + }, + challenges, + verifier_data, + common_data, + ) + } + pub(crate) fn get_public_inputs_hash(&self) -> HashOut { hash_n_to_hash(self.public_inputs.clone(), true) } @@ -203,6 +223,8 @@ pub(crate) struct ProofChallenges, const D: usize> pub fri_pow_response: F, pub fri_query_indices: Vec, + + pub fri_query_inferred_elements: Option>>, } pub struct ProofWithPublicInputsTarget { @@ -273,6 +295,7 @@ mod tests { use crate::field::crandall_field::CrandallField; use crate::field::field_types::Field; + use crate::fri::reduction_strategies::FriReductionStrategy; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; @@ -284,6 +307,7 @@ mod tests { const D: usize = 4; let mut config = CircuitConfig::large_config(); + config.fri_config.reduction_strategy = FriReductionStrategy::Fixed(vec![1]); config.fri_config.num_query_rounds = 50; let pw = PartialWitness::new(); @@ -303,9 +327,10 @@ mod tests { // Verify that `decompress ∘ compress = identity`. let compressed_proof = proof.clone().compress(&data.common)?; - let decompressed_compressed_proof = compressed_proof.decompress(&data.common)?; + let decompressed_compressed_proof = compressed_proof.clone().decompress(&data.common)?; assert_eq!(proof, decompressed_compressed_proof); - verify(proof, &data.verifier_only, &data.common) + verify(proof, &data.verifier_only, &data.common)?; + compressed_proof.verify(&data.verifier_only, &data.common) } } diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index 0ce9e3d0..e21fe328 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -5,7 +5,7 @@ use crate::field::field_types::{Field, RichField}; use crate::fri::verifier::verify_fri_proof; use crate::plonk::circuit_data::{CommonCircuitData, VerifierOnlyCircuitData}; use crate::plonk::plonk_common::reduce_with_powers; -use crate::plonk::proof::ProofWithPublicInputs; +use crate::plonk::proof::{ProofChallenges, ProofWithPublicInputs}; use crate::plonk::vanishing_poly::eval_vanishing_poly; use crate::plonk::vars::EvaluationVars; @@ -14,9 +14,17 @@ pub(crate) fn verify, const D: usize>( verifier_data: &VerifierOnlyCircuitData, common_data: &CommonCircuitData, ) -> Result<()> { - let public_inputs_hash = &proof_with_pis.get_public_inputs_hash(); - let challenges = proof_with_pis.get_challenges(common_data)?; + verify_with_challenges(proof_with_pis, challenges, verifier_data, common_data) +} + +pub(crate) fn verify_with_challenges, const D: usize>( + proof_with_pis: ProofWithPublicInputs, + challenges: ProofChallenges, + verifier_data: &VerifierOnlyCircuitData, + common_data: &CommonCircuitData, +) -> Result<()> { + let public_inputs_hash = &proof_with_pis.get_public_inputs_hash(); let ProofWithPublicInputs { proof, .. } = proof_with_pis;