diff --git a/plonky2/src/fri/proof.rs b/plonky2/src/fri/proof.rs index f96db781..bca7b8db 100644 --- a/plonky2/src/fri/proof.rs +++ b/plonky2/src/fri/proof.rs @@ -16,7 +16,7 @@ use crate::iop::ext_target::ExtensionTarget; use crate::iop::target::Target; use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::plonk_common::salt_size; -use crate::plonk::proof::{FriInferredElements, ProofChallenges}; +use crate::plonk::proof::{FriChallenges, FriInferredElements, ProofChallenges}; /// Evaluations and Merkle proof produced by the prover in a FRI query step. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] @@ -253,10 +253,10 @@ impl, H: Hasher, const D: usize> CompressedFriPr pow_witness, .. } = self; - let ProofChallenges { + let FriChallenges { fri_query_indices: indices, .. - } = challenges; + } = &challenges.fri_challenges; let mut fri_inferred_elements = fri_inferred_elements.0.into_iter(); let cap_height = params.config.cap_height; let reduction_arity_bits = ¶ms.reduction_arity_bits; diff --git a/plonky2/src/fri/verifier.rs b/plonky2/src/fri/verifier.rs index 40d1ab25..f41ae969 100644 --- a/plonky2/src/fri/verifier.rs +++ b/plonky2/src/fri/verifier.rs @@ -11,7 +11,7 @@ use crate::hash::hash_types::RichField; use crate::hash::merkle_proofs::verify_merkle_proof; use crate::hash::merkle_tree::MerkleCap; use crate::plonk::config::{GenericConfig, Hasher}; -use crate::plonk::proof::{OpeningSet, ProofChallenges}; +use crate::plonk::proof::{FriChallenges, OpeningSet, ProofChallenges}; use crate::util::reducing::ReducingFactor; use crate::util::reverse_bits; @@ -57,7 +57,7 @@ pub(crate) fn fri_verify_proof_of_work, const D: us Ok(()) } -pub(crate) fn verify_fri_proof< +pub fn verify_fri_proof< F: RichField + Extendable, C: GenericConfig, const D: usize, @@ -65,7 +65,7 @@ pub(crate) fn verify_fri_proof< instance: &FriInstanceInfo, // Openings of the PLONK polynomials. os: &OpeningSet, - challenges: &ProofChallenges, + challenges: &FriChallenges, initial_merkle_caps: &[MerkleCap], proof: &FriProof, params: &FriParams, @@ -171,7 +171,7 @@ fn fri_verifier_query_round< const D: usize, >( instance: &FriInstanceInfo, - challenges: &ProofChallenges, + challenges: &FriChallenges, precomputed_reduced_evals: &PrecomputedReducedOpenings, initial_merkle_caps: &[MerkleCap], proof: &FriProof, diff --git a/plonky2/src/plonk/get_challenges.rs b/plonky2/src/plonk/get_challenges.rs index d28f29da..440705ce 100644 --- a/plonky2/src/plonk/get_challenges.rs +++ b/plonky2/src/plonk/get_challenges.rs @@ -12,8 +12,8 @@ use crate::iop::challenger::Challenger; use crate::plonk::circuit_data::CommonCircuitData; use crate::plonk::config::{GenericConfig, Hasher}; use crate::plonk::proof::{ - CompressedProof, CompressedProofWithPublicInputs, FriInferredElements, OpeningSet, Proof, - ProofChallenges, ProofWithPublicInputs, + CompressedProof, CompressedProofWithPublicInputs, FriChallenges, FriInferredElements, + OpeningSet, Proof, ProofChallenges, ProofWithPublicInputs, }; use crate::util::reverse_bits; @@ -86,10 +86,12 @@ fn get_challenges, C: GenericConfig, cons plonk_gammas, plonk_alphas, plonk_zeta, - fri_alpha, - fri_betas, - fri_pow_response, - fri_query_indices, + fri_challenges: FriChallenges { + fri_alpha, + fri_betas, + fri_pow_response, + fri_query_indices, + }, }) } @@ -100,7 +102,10 @@ impl, C: GenericConfig, const D: usize> &self, common_data: &CommonCircuitData, ) -> anyhow::Result> { - Ok(self.get_challenges(common_data)?.fri_query_indices) + Ok(self + .get_challenges(common_data)? + .fri_challenges + .fri_query_indices) } /// Computes all Fiat-Shamir challenges used in the Plonk proof. @@ -179,9 +184,13 @@ impl, C: GenericConfig, const D: usize> ) -> FriInferredElements { let ProofChallenges { plonk_zeta, - fri_alpha, - fri_betas, - fri_query_indices, + fri_challenges: + FriChallenges { + fri_alpha, + fri_betas, + fri_query_indices, + .. + }, .. } = challenges; let mut fri_inferred_elements = Vec::new(); diff --git a/plonky2/src/plonk/mod.rs b/plonky2/src/plonk/mod.rs index b2d1ed03..4f2fa4e1 100644 --- a/plonky2/src/plonk/mod.rs +++ b/plonky2/src/plonk/mod.rs @@ -4,7 +4,7 @@ pub mod config; pub(crate) mod copy_constraint; mod get_challenges; pub(crate) mod permutation_argument; -pub(crate) mod plonk_common; +pub mod plonk_common; pub mod proof; pub mod prover; pub mod recursive_verifier; diff --git a/plonky2/src/plonk/plonk_common.rs b/plonky2/src/plonk/plonk_common.rs index 937f3ccd..94279d12 100644 --- a/plonky2/src/plonk/plonk_common.rs +++ b/plonky2/src/plonk/plonk_common.rs @@ -125,7 +125,7 @@ pub(crate) fn reduce_with_powers_multi< cumul } -pub(crate) fn reduce_with_powers<'a, P: PackedField, T: IntoIterator>( +pub fn reduce_with_powers<'a, P: PackedField, T: IntoIterator>( terms: T, alpha: P::Scalar, ) -> P diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index 7fbdc671..401b9f52 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -239,6 +239,10 @@ pub(crate) struct ProofChallenges, const D: usize> // Point at which the PLONK polynomials are opened. pub plonk_zeta: F::Extension, + pub fri_challenges: FriChallenges, +} + +pub struct FriChallenges, const D: usize> { // Scaling factor to combine polynomials. pub fri_alpha: F::Extension, diff --git a/plonky2/src/plonk/verifier.rs b/plonky2/src/plonk/verifier.rs index cbaec6d9..f0c976fa 100644 --- a/plonky2/src/plonk/verifier.rs +++ b/plonky2/src/plonk/verifier.rs @@ -92,7 +92,7 @@ pub(crate) fn verify_with_challenges< verify_fri_proof::( &common_data.get_fri_instance(challenges.plonk_zeta), &proof.openings, - &challenges, + &challenges.fri_challenges, merkle_caps, &proof.opening_proof, &common_data.fri_params, diff --git a/starky/src/get_challenges.rs b/starky/src/get_challenges.rs index f3c78701..927eef6c 100644 --- a/starky/src/get_challenges.rs +++ b/starky/src/get_challenges.rs @@ -77,14 +77,19 @@ fn get_challenges, C: GenericConfig, cons impl, C: GenericConfig, const D: usize> StarkProofWithPublicInputs { - pub(crate) fn fri_query_indices(&self, config: &StarkConfig) -> anyhow::Result> { - Ok(self.get_challenges(config)?.fri_query_indices) + pub(crate) fn fri_query_indices( + &self, + config: &StarkConfig, + degree_bits: usize, + ) -> anyhow::Result> { + Ok(self.get_challenges(config, degree_bits)?.fri_query_indices) } /// Computes all Fiat-Shamir challenges used in the Plonk proof. pub(crate) fn get_challenges( &self, config: &StarkConfig, + degree_bits: usize, ) -> Result> { let StarkProof { trace_cap, @@ -99,7 +104,7 @@ impl, C: GenericConfig, const D: usize> }, } = &self.proof; - get_challenges( + get_challenges::( trace_cap, quotient_polys_cap, openings, @@ -107,6 +112,7 @@ impl, C: GenericConfig, const D: usize> final_poly, *pow_witness, config, + degree_bits, ) } } diff --git a/starky/src/proof.rs b/starky/src/proof.rs index 4d81793e..fe4ac43d 100644 --- a/starky/src/proof.rs +++ b/starky/src/proof.rs @@ -108,7 +108,7 @@ impl, const D: usize> StarkOpeningSet { quotient_polys, } = self; for v in &[local_values, next_values, permutation_zs, quotient_polys] { - self.observe_extension_elements(v); + challenger.observe_extension_elements(v); } } } diff --git a/starky/src/prover.rs b/starky/src/prover.rs index 4ba09e22..a3f2cb2d 100644 --- a/starky/src/prover.rs +++ b/starky/src/prover.rs @@ -102,7 +102,7 @@ where ) ); let quotient_polys_cap = quotient_commitment.merkle_tree.cap; - challenger.observe_cap(quotient_polys_cap); + challenger.observe_cap("ient_polys_cap); let zeta = challenger.get_extension_challenge::(); // To avoid leaking witness data, we want to ensure that our opening locations, `zeta` and diff --git a/starky/src/verifier.rs b/starky/src/verifier.rs index cbde85c0..46dc948f 100644 --- a/starky/src/verifier.rs +++ b/starky/src/verifier.rs @@ -1,9 +1,11 @@ use anyhow::{ensure, Result}; -use plonky2::field::extension_field::Extendable; +use plonky2::field::extension_field::{Extendable, FieldExtension}; use plonky2::field::field_types::Field; +use plonky2::fri::verifier::verify_fri_proof; use plonky2::hash::hash_types::RichField; use plonky2::plonk::circuit_data::CommonCircuitData; use plonky2::plonk::config::GenericConfig; +use plonky2::plonk::plonk_common::reduce_with_powers; use plonky2::plonk::proof::ProofWithPublicInputs; use plonky2_util::log2_strict; @@ -19,11 +21,17 @@ pub(crate) fn verify< S: Stark, const D: usize, >( + stark: S, proof_with_pis: StarkProofWithPublicInputs, config: &StarkConfig, -) -> Result<()> { - let challenges = proof_with_pis.get_challenges(config)?; - verify_with_challenges(proof_with_pis, challenges, verifier_data, common_data) + degree_bits: usize, +) -> Result<()> +where + [(); S::COLUMNS]:, + [(); S::PUBLIC_INPUTS]:, +{ + let challenges = proof_with_pis.get_challenges(config, degree_bits)?; + verify_with_challenges(stark, proof_with_pis, challenges, config) } pub(crate) fn verify_with_challenges< @@ -36,15 +44,18 @@ pub(crate) fn verify_with_challenges< proof_with_pis: StarkProofWithPublicInputs, challenges: StarkProofChallenges, config: &StarkConfig, -) -> Result<()> { +) -> Result<()> +where + [(); S::COLUMNS]:, + [(); S::PUBLIC_INPUTS]:, +{ let StarkProofWithPublicInputs { proof, public_inputs, } = proof_with_pis; let degree = recover_degree(&proof, config); - let degree_log = log2_strict(degree); + let degree_bits = log2_strict(degree); - let local_constants = &proof.openings.constants; let local_values = &proof.openings.local_values; let next_values = &proof.openings.local_values; let StarkOpeningSet { @@ -54,24 +65,32 @@ pub(crate) fn verify_with_challenges< quotient_polys, } = &proof.openings; let vars = StarkEvaluationVars { - local_values, - next_values, - public_inputs: &public_inputs, + local_values: &local_values.to_vec().try_into().unwrap(), + next_values: &next_values.to_vec().try_into().unwrap(), + public_inputs: &public_inputs + .into_iter() + .map(F::Extension::from_basefield) + .collect::>() + .try_into() + .unwrap(), }; + let (l_1, l_last) = eval_l_1_and_l_last(degree_bits, challenges.stark_zeta); let mut consumer = ConstraintConsumer::::new( - challenges.stark_alphas, - lagrange_first.values[i], - lagrange_last.values[i], + challenges + .stark_alphas + .iter() + .map(|&alpha| F::Extension::from_basefield(alpha)) + .collect::>(), + l_1.into(), + l_last.into(), ); - let (l_1, l_n) = eval_l_1_and_l_last(degree_log, challenges.stark_zeta); - stark.eval_ext() + stark.eval_ext(vars, &mut consumer); + let acc = consumer.accumulators(); // Check each polynomial identity, of the form `vanishing(x) = Z_H(x) quotient(x)`, at zeta. let quotient_polys_zeta = &proof.openings.quotient_polys; - let zeta_pow_deg = challenges - .plonk_zeta - .exp_power_of_2(common_data.degree_bits); + let zeta_pow_deg = challenges.stark_zeta.exp_power_of_2(degree_bits); let z_h_zeta = zeta_pow_deg - F::Extension::ONE; // `quotient_polys_zeta` holds `num_challenges * quotient_degree_factor` evaluations. // Each chunk of `quotient_degree_factor` holds the evaluations of `t_0(zeta),...,t_{quotient_degree_factor-1}(zeta)` @@ -79,41 +98,52 @@ pub(crate) fn verify_with_challenges< // So to reconstruct `t(zeta)` we can compute `reduce_with_powers(chunk, zeta^n)` for each // `quotient_degree_factor`-sized chunk of the original evaluations. for (i, chunk) in quotient_polys_zeta - .chunks(common_data.quotient_degree_factor) + .chunks(config.fri_config.rate_bits) .enumerate() { - ensure!(vanishing_polys_zeta[i] == z_h_zeta * reduce_with_powers(chunk, zeta_pow_deg)); + ensure!(acc[i] == z_h_zeta * reduce_with_powers(chunk, zeta_pow_deg)); } - let merkle_caps = &[ - verifier_data.constants_sigmas_cap.clone(), - proof.wires_cap, - proof.plonk_zs_partial_products_cap, - proof.quotient_polys_cap, - ]; + let merkle_caps = &[proof.trace_cap, proof.quotient_polys_cap]; verify_fri_proof::( - &common_data.get_fri_instance(challenges.plonk_zeta), + &S::fri_instance( + challenges.stark_zeta, + F::primitive_root_of_unity(degree_bits).into(), + config.fri_config.rate_bits, + ), &proof.openings, &challenges, merkle_caps, &proof.opening_proof, - &common_data.fri_params, + &config.fri_params(degree_bits), )?; Ok(()) } /// Evaluate the Lagrange basis `L_1` and `L_n` at a point `x`. -fn eval_l_1_and_l_last(log_n: usize, x: F) -> (F,F) { +fn eval_l_1_and_l_last(log_n: usize, x: F) -> (F, F) { let n = 1 << log_n; let g = F::primitive_root_of_unity(log_n); let z_x = x.exp_power_of_2(log_n); - let invs = F::batch_multiplicative_inverse(&[F::from_canonical_usize(n) * (x - F::ONE), F::from_canonical_usize(n) * (g*x - F::ONE)]); + let invs = F::batch_multiplicative_inverse(&[ + F::from_canonical_usize(n) * (x - F::ONE), + F::from_canonical_usize(n) * (g * x - F::ONE), + ]); (z_x * invs[0], z_x * invs[1]) } -fn recover_degree, C: GenericConfig, const D: usize>(proof: &StarkProof, config: &StarkConfig) -> usize { - 1<<(proof.opening_proof.query_round_proofs[0].initial_trees_proof.evals_proofs[0].1.siblings.len() + config.fri_config.cap_height) -} \ No newline at end of file +fn recover_degree, C: GenericConfig, const D: usize>( + proof: &StarkProof, + config: &StarkConfig, +) -> usize { + 1 << (proof.opening_proof.query_round_proofs[0] + .initial_trees_proof + .evals_proofs[0] + .1 + .siblings + .len() + + config.fri_config.cap_height) +}