diff --git a/plonky2/src/fri/challenges.rs b/plonky2/src/fri/challenges.rs index be73a8c241..6af3183f00 100644 --- a/plonky2/src/fri/challenges.rs +++ b/plonky2/src/fri/challenges.rs @@ -1,10 +1,12 @@ +use plonky2_field::types::Field; + use crate::field::extension::Extendable; use crate::field::polynomial::PolynomialCoeffs; use crate::fri::proof::{FriChallenges, FriChallengesTarget}; use crate::fri::structure::{FriOpenings, FriOpeningsTarget}; use crate::fri::FriConfig; use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; -use crate::hash::hash_types::{MerkleCapTarget, RichField}; +use crate::hash::hash_types::{MerkleCapTarget, RichField, NUM_HASH_OUT_ELTS}; use crate::hash::merkle_tree::MerkleCap; use crate::iop::challenger::{Challenger, RecursiveChallenger}; use crate::iop::target::Target; @@ -28,6 +30,8 @@ impl> Challenger { pow_witness: F, degree_bits: usize, config: &FriConfig, + final_poly_coeff_len: Option, + query_round_step_count: Option, ) -> FriChallenges where F: RichField + Extendable, @@ -46,7 +50,26 @@ impl> Challenger { }) .collect(); + // When this proof was generated in a circuit with a different number of query steps, + // the challenger needs to observe the additional hash caps. + if let Some(step_count) = query_round_step_count { + let cap_len = (1 << config.cap_height) * NUM_HASH_OUT_ELTS; + let zero_cap = vec![F::ZERO; cap_len]; + for _ in commit_phase_merkle_caps.len()..step_count { + self.observe_elements(&zero_cap); + self.get_extension_challenge::(); + } + } + self.observe_extension_elements(&final_poly.coeffs); + // When this proof was generated in a circuit with a different final polynomial length, + // the challenger needs to observe the full length of the final polynomial. + if let Some(len) = final_poly_coeff_len { + let current_len = final_poly.coeffs.len(); + for _ in current_len..len { + self.observe_extension_element(&F::Extension::ZERO); + } + } self.observe_element(pow_witness); let fri_pow_response = self.get_challenge(); diff --git a/plonky2/src/plonk/get_challenges.rs b/plonky2/src/plonk/get_challenges.rs index 45d79f99aa..5872cf6953 100644 --- a/plonky2/src/plonk/get_challenges.rs +++ b/plonky2/src/plonk/get_challenges.rs @@ -85,6 +85,8 @@ fn get_challenges, C: GenericConfig, cons pow_witness, common_data.degree_bits(), &config.fri_config, + None, + None, ), }) } diff --git a/starky/src/fibonacci_stark.rs b/starky/src/fibonacci_stark.rs index 56f60af430..201ae62f32 100644 --- a/starky/src/fibonacci_stark.rs +++ b/starky/src/fibonacci_stark.rs @@ -186,7 +186,7 @@ mod tests { &mut TimingTree::default(), )?; - verify_stark_proof(stark, proof, &config) + verify_stark_proof(stark, proof, &config, None) } #[test] @@ -223,7 +223,7 @@ mod tests { None, &mut TimingTree::default(), )?; - verify_stark_proof(stark, proof.clone(), &config)?; + verify_stark_proof(stark, proof.clone(), &config, None)?; assert_eq!(degree_bits, proof.proof.recover_degree_bits(&config)); recursive_proof::(stark, proof, &config, true) @@ -304,8 +304,12 @@ mod tests { // Configure the circuit for recursive verification let num_rows = 1 << verifier_degree_bits; let stark = S::new(num_rows); - let circuit_config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(circuit_config); + for p in proofs.clone() { + verify_stark_proof(stark, p, &stark_config, Some(verifier_fri_params.clone()))?; + } + + let recursive_verification_circuit_config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(recursive_verification_circuit_config); let zero = builder.zero(); // Set up proof verification within the circuit diff --git a/starky/src/get_challenges.rs b/starky/src/get_challenges.rs index 1d9b55b437..fd50d5068e 100644 --- a/starky/src/get_challenges.rs +++ b/starky/src/get_challenges.rs @@ -1,6 +1,8 @@ use plonky2::field::extension::Extendable; use plonky2::field::polynomial::PolynomialCoeffs; use plonky2::fri::proof::{FriProof, FriProofTarget}; +use plonky2::fri::prover::final_poly_coeff_len; +use plonky2::fri::FriParams; use plonky2::gadgets::polynomial::PolynomialCoeffsExtTarget; use plonky2::hash::hash_types::{MerkleCapTarget, RichField}; use plonky2::hash::merkle_tree::MerkleCap; @@ -35,6 +37,7 @@ fn get_challenges( pow_witness: F, config: &StarkConfig, degree_bits: usize, + verifier_circuit_fri_params: Option, ) -> StarkProofChallenges where F: RichField + Extendable, @@ -67,6 +70,19 @@ where challenger.observe_openings(&openings.to_fri_openings()); + let (final_poly_coeff_len, query_round_step_count) = + if let Some(verifier_circuit_fri_params) = verifier_circuit_fri_params { + ( + Some(final_poly_coeff_len( + verifier_circuit_fri_params.degree_bits, + &verifier_circuit_fri_params.reduction_arity_bits, + )), + Some(verifier_circuit_fri_params.reduction_arity_bits.len()), + ) + } else { + (None, None) + }; + StarkProofChallenges { lookup_challenge_set, stark_alphas, @@ -77,6 +93,8 @@ where pow_witness, degree_bits, &config.fri_config, + final_poly_coeff_len, + query_round_step_count, ), } } @@ -99,6 +117,7 @@ where challenges: Option<&GrandProductChallengeSet>, ignore_trace_cap: bool, config: &StarkConfig, + verifier_circuit_fri_params: Option, ) -> StarkProofChallenges { let degree_bits = self.recover_degree_bits(config); @@ -134,6 +153,7 @@ where *pow_witness, config, degree_bits, + verifier_circuit_fri_params, ) } } @@ -156,10 +176,16 @@ where challenges: Option<&GrandProductChallengeSet>, ignore_trace_cap: bool, config: &StarkConfig, + verifier_circuit_fri_params: Option, ) -> StarkProofChallenges { challenger.observe_elements(&self.public_inputs); - self.proof - .get_challenges(challenger, challenges, ignore_trace_cap, config) + self.proof.get_challenges( + challenger, + challenges, + ignore_trace_cap, + config, + verifier_circuit_fri_params, + ) } } diff --git a/starky/src/permutation_stark.rs b/starky/src/permutation_stark.rs index 81a0897f5f..e656554104 100644 --- a/starky/src/permutation_stark.rs +++ b/starky/src/permutation_stark.rs @@ -145,7 +145,7 @@ mod tests { &mut TimingTree::default(), )?; - verify_stark_proof(stark, proof, &config) + verify_stark_proof(stark, proof, &config, None) } #[test] @@ -194,7 +194,7 @@ mod tests { None, &mut TimingTree::default(), )?; - verify_stark_proof(stark, proof.clone(), &config)?; + verify_stark_proof(stark, proof.clone(), &config, None)?; recursive_proof::(stark, proof, &config, true) } diff --git a/starky/src/unconstrained_stark.rs b/starky/src/unconstrained_stark.rs index 08f52d692a..ec6045c4bc 100644 --- a/starky/src/unconstrained_stark.rs +++ b/starky/src/unconstrained_stark.rs @@ -117,7 +117,7 @@ mod tests { let proof = prove::(stark, &config, trace, &[], None, &mut TimingTree::default())?; - verify_stark_proof(stark, proof, &config) + verify_stark_proof(stark, proof, &config, None) } #[test] @@ -159,7 +159,7 @@ mod tests { let trace = stark.generate_trace(); let proof = prove::(stark, &config, trace, &[], None, &mut TimingTree::default())?; - verify_stark_proof(stark, proof.clone(), &config)?; + verify_stark_proof(stark, proof.clone(), &config, None)?; recursive_proof::(stark, proof, &config, true) } diff --git a/starky/src/verifier.rs b/starky/src/verifier.rs index d56072ad3a..7bf43a4e0e 100644 --- a/starky/src/verifier.rs +++ b/starky/src/verifier.rs @@ -10,6 +10,7 @@ use itertools::Itertools; use plonky2::field::extension::{Extendable, FieldExtension}; use plonky2::field::types::Field; use plonky2::fri::verifier::verify_fri_proof; +use plonky2::fri::FriParams; use plonky2::hash::hash_types::RichField; use plonky2::hash::merkle_tree::MerkleCap; use plonky2::iop::challenger::Challenger; @@ -35,11 +36,18 @@ pub fn verify_stark_proof< stark: S, proof_with_pis: StarkProofWithPublicInputs, config: &StarkConfig, + verifier_circuit_fri_params: Option, ) -> Result<()> { ensure!(proof_with_pis.public_inputs.len() == S::PUBLIC_INPUTS); let mut challenger = Challenger::::new(); - let challenges = proof_with_pis.get_challenges(&mut challenger, None, false, config); + let challenges = proof_with_pis.get_challenges( + &mut challenger, + None, + false, + config, + verifier_circuit_fri_params, + ); verify_stark_proof_with_challenges( &stark,