From ea69a873389d82242cdd797a605f07b342d40bc9 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 11 Oct 2021 16:40:31 +0200 Subject: [PATCH] Working --- src/fri/proof.rs | 18 +++++++++++++++--- src/fri/verifier.rs | 33 ++++++++++++++------------------- src/plonk/get_challenges.rs | 37 +++++++++++++++++++++++++++++-------- src/plonk/proof.rs | 17 +++++++++++++++-- src/util/serialization.rs | 9 ++++++--- 5 files changed, 79 insertions(+), 35 deletions(-) diff --git a/src/fri/proof.rs b/src/fri/proof.rs index 130cf57d..3cbfaa0a 100644 --- a/src/fri/proof.rs +++ b/src/fri/proof.rs @@ -249,8 +249,8 @@ impl, const D: usize> CompressedFriProof { fri_query_inferred_elements, .. } = challenges; - let fri_query_inferred_elements = if let Some(v) = fri_query_inferred_elements { - v + let mut fri_query_inferred_elements = if let Some(v) = fri_query_inferred_elements { + v.iter().copied() } else { panic!() }; @@ -281,6 +281,10 @@ impl, const D: usize> CompressedFriProof { }) .collect::>(); + let mut evals_by_depth = vec![ + HashMap::>::new(); + common_data.fri_params.reduction_arity_bits.len() + ]; 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 @@ -298,7 +302,15 @@ impl, const D: usize> CompressedFriProof { merkle_proof, } = query_round_proofs.steps[i][&index].clone(); steps_indices[i].push(index); - evals.insert(index_within_coset, fri_query_inferred_elements[round][i]); + if let Some(v) = evals_by_depth[i].get(&index) { + evals = v.to_vec(); + } else { + evals.insert( + index_within_coset, + fri_query_inferred_elements.next().unwrap(), + ); + evals_by_depth[i].insert(index, evals.clone()); + } 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 23739639..c1d97118 100644 --- a/src/fri/verifier.rs +++ b/src/fri/verifier.rs @@ -120,14 +120,14 @@ fn fri_verify_initial_proof( /// Holds the reduced (by `alpha`) evaluations at `zeta` for the polynomial opened just at /// zeta, for `Z` at zeta and for `Z` at `g*zeta`. #[derive(Copy, Clone, Debug)] -struct PrecomputedReducedEvals, const D: usize> { +pub(crate) struct PrecomputedReducedEvals, const D: usize> { pub single: F::Extension, pub zs: F::Extension, pub zs_right: F::Extension, } impl, const D: usize> PrecomputedReducedEvals { - fn from_os_and_alpha(os: &OpeningSet, alpha: F::Extension) -> Self { + pub(crate) fn from_os_and_alpha(os: &OpeningSet, alpha: F::Extension) -> Self { let mut alpha = ReducingFactor::new(alpha); let single = alpha.reduce( os.constants @@ -148,7 +148,7 @@ impl, const D: usize> PrecomputedReducedEvals { } } -fn fri_combine_initial, const D: usize>( +pub(crate) fn fri_combine_initial, const D: usize>( proof: &FriInitialTreeProof, alpha: F::Extension, zeta: F::Extension, @@ -159,10 +159,10 @@ fn fri_combine_initial, const D: usize>( let config = &common_data.config; assert!(D > 1, "Not implemented for D=1."); let degree_log = common_data.degree_bits; - debug_assert_eq!( - degree_log, - common_data.config.cap_height + proof.evals_proofs[0].1.siblings.len() - config.rate_bits - ); + // debug_assert_eq!( + // degree_log, + // common_data.config.cap_height + proof.evals_proofs[0].1.siblings.len() - config.rate_bits + // ); let subgroup_x = F::Extension::from_basefield(subgroup_x); let mut alpha = ReducingFactor::new(alpha); let mut sum = F::Extension::ZERO; @@ -262,18 +262,13 @@ 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 = 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], - ) - }; + old_eval = 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 e3fa54c8..97907138 100644 --- a/src/plonk/get_challenges.rs +++ b/src/plonk/get_challenges.rs @@ -1,6 +1,8 @@ +use std::collections::HashSet; + use crate::field::extension_field::Extendable; use crate::field::field_types::{Field, RichField}; -use crate::fri::verifier::compute_evaluation; +use crate::fri::verifier::{compute_evaluation, fri_combine_initial, PrecomputedReducedEvals}; use crate::hash::hashing::hash_n_to_1; use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; @@ -157,36 +159,55 @@ impl, const D: usize> CompressedProofWithPublicInpu .map(|_| challenger.get_challenge().to_canonical_u64() as usize % lde_size) .collect::>(); + let mut seen_indices_by_depth = + vec![HashSet::new(); common_data.fri_params.reduction_arity_bits.len()]; + let precomputed_reduced_evals = + PrecomputedReducedEvals::from_os_and_alpha(&self.proof.openings, fri_alpha); let mut fri_query_inferred_elements = Vec::new(); let log_n = common_data.degree_bits + common_data.config.rate_bits; for query_round in 0..common_data.config.fri_config.num_query_rounds { - let mut query_round_inferred_elements = Vec::new(); 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 mut old_eval = fri_combine_initial( + &self + .proof + .opening_proof + .query_round_proofs + .initial_trees_proofs[&x_index], + fri_alpha, + plonk_zeta, + subgroup_x, + precomputed_reduced_evals, + common_data, + ); for (i, &arity_bits) in common_data .fri_params .reduction_arity_bits .iter() .enumerate() { + if !seen_indices_by_depth[i].insert(x_index >> arity_bits) { + break; + } + fri_query_inferred_elements.push(old_eval); let arity = 1 << arity_bits; - let evals = &self.proof.opening_proof.query_round_proofs.steps[i] + let mut evals = self.proof.opening_proof.query_round_proofs.steps[i] [&(x_index >> arity_bits)] - .evals; + .evals + .clone(); let x_index_within_coset = x_index & (arity - 1); - let elmt = compute_evaluation( + evals.insert(x_index_within_coset, old_eval); + old_eval = compute_evaluation( subgroup_x, x_index_within_coset, arity_bits, - evals, + &evals, fri_betas[i], ); - query_round_inferred_elements.push(elmt); subgroup_x = subgroup_x.exp_power_of_2(arity_bits); x_index >>= arity_bits; } - fri_query_inferred_elements.push(query_round_inferred_elements); } Ok(ProofChallenges { diff --git a/src/plonk/proof.rs b/src/plonk/proof.rs index 0bc8ef96..ecc4e3a4 100644 --- a/src/plonk/proof.rs +++ b/src/plonk/proof.rs @@ -224,7 +224,7 @@ pub(crate) struct ProofChallenges, const D: usize> pub fri_query_indices: Vec, - pub fri_query_inferred_elements: Option>>, + pub fri_query_inferred_elements: Option>, } pub struct ProofWithPublicInputsTarget { @@ -307,7 +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.reduction_strategy = FriReductionStrategy::Fixed(vec![2, 1]); config.fri_config.num_query_rounds = 50; let pw = PartialWitness::new(); @@ -324,10 +324,23 @@ mod tests { builder.connect(zt, comp_zt); let data = builder.build(); let proof = data.prove(pw)?; + verify(proof.clone(), &data.verifier_only, &data.common)?; // Verify that `decompress ∘ compress = identity`. let compressed_proof = proof.clone().compress(&data.common)?; let decompressed_compressed_proof = compressed_proof.clone().decompress(&data.common)?; + for i in 0..proof.proof.opening_proof.query_round_proofs.len() { + let qrp = proof.proof.opening_proof.query_round_proofs[i].clone(); + let dqrp = decompressed_compressed_proof + .proof + .opening_proof + .query_round_proofs[i] + .clone(); + for j in 0..qrp.steps.len() { + dbg!(&qrp.steps[j].evals); + dbg!(&dqrp.steps[j].evals); + } + } assert_eq!(proof, decompressed_compressed_proof); verify(proof, &data.verifier_only, &data.common)?; diff --git a/src/util/serialization.rs b/src/util/serialization.rs index d4a4ea1e..e9164687 100644 --- a/src/util/serialization.rs +++ b/src/util/serialization.rs @@ -242,14 +242,17 @@ impl Buffer { &mut self, fqs: &FriQueryStep, ) -> Result<()> { + dbg!(self.0.position()); self.write_field_ext_vec::(&fqs.evals)?; self.write_merkle_proof(&fqs.merkle_proof) } fn read_fri_query_step, const D: usize>( &mut self, arity: usize, + compressed: bool, ) -> Result> { - let evals = self.read_field_ext_vec::(arity)?; + dbg!(self.0.position()); + let evals = self.read_field_ext_vec::(arity - if compressed { 1 } else { 0 })?; let merkle_proof = self.read_merkle_proof()?; Ok(FriQueryStep { evals, @@ -281,7 +284,7 @@ impl Buffer { .fri_params .reduction_arity_bits .iter() - .map(|&ar| self.read_fri_query_step(1 << ar)) + .map(|&ar| self.read_fri_query_step(1 << ar, false)) .collect::>()?; fqrs.push(FriQueryRound { initial_trees_proof, @@ -424,7 +427,7 @@ impl Buffer { }); indices.dedup(); let query_steps = (0..indices.len()) - .map(|_| self.read_fri_query_step(1 << a)) + .map(|_| self.read_fri_query_step(1 << a, true)) .collect::>>()?; steps.push( indices