diff --git a/starky2/src/cross_table_lookup.rs b/starky2/src/cross_table_lookup.rs index 9c7b8e03..de58273f 100644 --- a/starky2/src/cross_table_lookup.rs +++ b/starky2/src/cross_table_lookup.rs @@ -173,29 +173,19 @@ impl<'a, F: RichField + Extendable, const D: usize> let mut ctl_zs = proofs .iter() .zip(num_permutation_zs) - .map(|(p, &num_permutation)| -> Box> { - if p.proof.openings.permutation_ctl_zs.is_some() { - Box::new( + .map(|(p, &num_permutation)| { + p.proof + .openings + .permutation_ctl_zs + .iter() + .skip(num_permutation) + .zip( p.proof .openings - .permutation_ctl_zs - .as_ref() - .unwrap() + .permutation_ctl_zs_right .iter() - .skip(num_permutation) - .zip( - p.proof - .openings - .permutation_ctl_zs_right - .as_ref() - .unwrap() - .iter() - .skip(num_permutation), - ), + .skip(num_permutation), ) - } else { - Box::new(std::iter::empty()) - } }) .collect::>(); diff --git a/starky2/src/get_challenges.rs b/starky2/src/get_challenges.rs index c7931ebf..ecde68ee 100644 --- a/starky2/src/get_challenges.rs +++ b/starky2/src/get_challenges.rs @@ -21,7 +21,7 @@ use crate::stark::Stark; fn get_challenges( challenger: &mut Challenger, stark: &S, - permutation_ctl_zs_cap: Option<&MerkleCap>, + permutation_ctl_zs_cap: &MerkleCap, quotient_polys_cap: &MerkleCap, openings: &StarkOpeningSet, commit_phase_merkle_caps: &[MerkleCap], @@ -45,9 +45,7 @@ where ) }); - if let Some(cap) = permutation_ctl_zs_cap { - challenger.observe_cap(cap); - } + challenger.observe_cap(permutation_ctl_zs_cap); let stark_alphas = challenger.get_n_challenges(num_challenges); @@ -146,7 +144,7 @@ where get_challenges::( challenger, stark, - permutation_ctl_zs_cap.as_ref(), + permutation_ctl_zs_cap, quotient_polys_cap, openings, commit_phase_merkle_caps, diff --git a/starky2/src/proof.rs b/starky2/src/proof.rs index f206f23f..c04ff9dc 100644 --- a/starky2/src/proof.rs +++ b/starky2/src/proof.rs @@ -40,7 +40,7 @@ pub struct StarkProof, C: GenericConfig, /// Merkle cap of LDEs of trace values. pub trace_cap: MerkleCap, /// Merkle cap of LDEs of permutation Z values. - pub permutation_ctl_zs_cap: Option>, + pub permutation_ctl_zs_cap: MerkleCap, /// Merkle cap of LDEs of trace values. pub quotient_polys_cap: MerkleCap, /// Purported values of each polynomial at the challenge point. @@ -147,9 +147,9 @@ pub struct StarkOpeningSet, const D: usize> { /// Openings of trace polynomials at `g * zeta`. pub next_values: Vec, /// Openings of permutations and cross-table lookups `Z` polynomials at `zeta`. - pub permutation_ctl_zs: Option>, + pub permutation_ctl_zs: Vec, /// Openings of permutations and cross-table lookups `Z` polynomials at `g * zeta`. - pub permutation_ctl_zs_right: Option>, + pub permutation_ctl_zs_right: Vec, /// Openings of cross-table lookups `Z` polynomials at `g^-1`. pub ctl_zs_last: Vec, /// Openings of quotient polynomials at `zeta`. @@ -161,7 +161,7 @@ impl, const D: usize> StarkOpeningSet { zeta: F::Extension, g: F, trace_commitment: &PolynomialBatch, - permutation_ctl_zs_commitment: Option<&PolynomialBatch>, + permutation_ctl_zs_commitment: &PolynomialBatch, quotient_commitment: &PolynomialBatch, degree_bits: usize, num_permutation_zs: usize, @@ -182,16 +182,13 @@ impl, const D: usize> StarkOpeningSet { Self { local_values: eval_commitment(zeta, trace_commitment), next_values: eval_commitment(zeta_right, trace_commitment), - permutation_ctl_zs: permutation_ctl_zs_commitment.map(|c| eval_commitment(zeta, c)), - permutation_ctl_zs_right: permutation_ctl_zs_commitment - .map(|c| eval_commitment(zeta_right, c)), - ctl_zs_last: permutation_ctl_zs_commitment - .map(|c| { - eval_commitment_base(F::primitive_root_of_unity(degree_bits).inverse(), c) - [num_permutation_zs..] - .to_vec() - }) - .unwrap_or_default(), + permutation_ctl_zs: eval_commitment(zeta, permutation_ctl_zs_commitment), + permutation_ctl_zs_right: eval_commitment(zeta_right, permutation_ctl_zs_commitment), + ctl_zs_last: eval_commitment_base( + F::primitive_root_of_unity(degree_bits).inverse(), + permutation_ctl_zs_commitment, + )[num_permutation_zs..] + .to_vec(), quotient_polys: eval_commitment(zeta, quotient_commitment), } } @@ -201,7 +198,7 @@ impl, const D: usize> StarkOpeningSet { values: self .local_values .iter() - .chain(self.permutation_ctl_zs.iter().flatten()) + .chain(&self.permutation_ctl_zs) .chain(&self.quotient_polys) .copied() .collect_vec(), @@ -210,7 +207,7 @@ impl, const D: usize> StarkOpeningSet { values: self .next_values .iter() - .chain(self.permutation_ctl_zs_right.iter().flatten()) + .chain(&self.permutation_ctl_zs_right) .copied() .collect_vec(), }; diff --git a/starky2/src/prover.rs b/starky2/src/prover.rs index 4fc602c1..c9f2f0ab 100644 --- a/starky2/src/prover.rs +++ b/starky2/src/prover.rs @@ -1,7 +1,4 @@ -use std::iter::once; - use anyhow::{ensure, Result}; -use itertools::Itertools; use plonky2::field::extension_field::Extendable; use plonky2::field::field_types::Field; use plonky2::field::packable::Packable; @@ -175,30 +172,26 @@ where permutation_zs } }; + assert!(!z_polys.is_empty(), "No CTL?"); - let permutation_ctl_zs_commitment = (!z_polys.is_empty()).then(|| { - PolynomialBatch::from_values( - z_polys, - rate_bits, - false, - config.fri_config.cap_height, - timing, - None, - ) - }); - let permutation_ctl_zs_cap = permutation_ctl_zs_commitment - .as_ref() - .map(|commit| commit.merkle_tree.cap.clone()); - if let Some(cap) = &permutation_ctl_zs_cap { - challenger.observe_cap(cap); - } + let permutation_ctl_zs_commitment = PolynomialBatch::from_values( + z_polys, + rate_bits, + false, + config.fri_config.cap_height, + timing, + None, + ); + + let permutation_ctl_zs_cap = permutation_ctl_zs_commitment.merkle_tree.cap.clone(); + challenger.observe_cap(&permutation_ctl_zs_cap); let alphas = challenger.get_n_challenges(config.num_challenges); if cfg!(test) { check_constraints( stark, trace_commitment, - permutation_ctl_zs_commitment.as_ref(), + &permutation_ctl_zs_commitment, permutation_challenges.as_ref(), ctl_data, public_inputs, @@ -211,7 +204,7 @@ where let quotient_polys = compute_quotient_polys::::Packing, C, S, D>( stark, trace_commitment, - permutation_ctl_zs_commitment.as_ref(), + &permutation_ctl_zs_commitment, permutation_challenges.as_ref(), ctl_data, public_inputs, @@ -259,17 +252,18 @@ where zeta, g, trace_commitment, - permutation_ctl_zs_commitment.as_ref(), + &permutation_ctl_zs_commitment, "ient_commitment, degree_bits, stark.num_permutation_batches(config), ); challenger.observe_openings(&openings.to_fri_openings()); - let initial_merkle_trees = once(trace_commitment) - .chain(&permutation_ctl_zs_commitment) - .chain(once("ient_commitment)) - .collect_vec(); + let initial_merkle_trees = vec![ + trace_commitment, + &permutation_ctl_zs_commitment, + "ient_commitment, + ]; let opening_proof = timed!( timing, @@ -301,7 +295,7 @@ where fn compute_quotient_polys<'a, F, P, C, S, const D: usize>( stark: &S, trace_commitment: &'a PolynomialBatch, - permutation_ctl_zs_commitment: Option<&'a PolynomialBatch>, + permutation_ctl_zs_commitment: &'a PolynomialBatch, permutation_challenges: Option<&'a Vec>>, ctl_data: &CtlData, public_inputs: [F; S::PUBLIC_INPUTS], @@ -381,33 +375,25 @@ where next_values: &get_trace_values_packed(i_next_start), public_inputs: &public_inputs, }; - let permutation_check_data = - if let (Some(permutation_zs_commitment), Some(permutation_challenge_sets)) = - (permutation_ctl_zs_commitment, permutation_challenges) - { - Some(PermutationCheckVars { - local_zs: permutation_zs_commitment.get_lde_values_packed(i_start, step) - [..num_permutation_zs] - .to_vec(), - next_zs: permutation_zs_commitment - .get_lde_values_packed(i_next_start, step)[..num_permutation_zs] - .to_vec(), - permutation_challenge_sets: permutation_challenge_sets.to_vec(), - }) - } else { - None - }; + let permutation_check_vars = + permutation_challenges.map(|permutation_challenge_sets| PermutationCheckVars { + local_zs: permutation_ctl_zs_commitment.get_lde_values_packed(i_start, step) + [..num_permutation_zs] + .to_vec(), + next_zs: permutation_ctl_zs_commitment + .get_lde_values_packed(i_next_start, step)[..num_permutation_zs] + .to_vec(), + permutation_challenge_sets: permutation_challenge_sets.to_vec(), + }); let ctl_vars = ctl_data .zs_columns .iter() .enumerate() .map(|(i, (_, columns))| CtlCheckVars:: { - local_z: permutation_ctl_zs_commitment - .unwrap() - .get_lde_values_packed(i_start, step)[num_permutation_zs + i], - next_z: permutation_ctl_zs_commitment - .unwrap() - .get_lde_values_packed(i_next_start, step)[num_permutation_zs + i], + local_z: permutation_ctl_zs_commitment.get_lde_values_packed(i_start, step) + [num_permutation_zs + i], + next_z: permutation_ctl_zs_commitment.get_lde_values_packed(i_next_start, step) + [num_permutation_zs + i], challenges: ctl_data.challenges.challenges[i % config.num_challenges], columns, }) @@ -416,7 +402,7 @@ where stark, config, vars, - permutation_check_data, + permutation_check_vars, &ctl_vars, &mut consumer, ); @@ -442,7 +428,7 @@ where fn check_constraints<'a, F, C, S, const D: usize>( stark: &S, trace_commitment: &'a PolynomialBatch, - permutation_ctl_zs_commitment: Option<&'a PolynomialBatch>, + permutation_ctl_zs_commitment: &'a PolynomialBatch, permutation_challenges: Option<&'a Vec>>, ctl_data: &CtlData, public_inputs: [F; S::PUBLIC_INPUTS], @@ -503,30 +489,25 @@ fn check_constraints<'a, F, C, S, const D: usize>( .unwrap(), public_inputs: &public_inputs, }; - let permutation_check_data = - if let (Some(permutation_zs_commitment), Some(permutation_challenge_sets)) = - (permutation_ctl_zs_commitment, permutation_challenges) - { - Some(PermutationCheckVars { - local_zs: get_comm_values(permutation_zs_commitment, i) - [..num_permutation_zs] - .to_vec(), - next_zs: get_comm_values(permutation_zs_commitment, i_next) - [..num_permutation_zs] - .to_vec(), - permutation_challenge_sets: permutation_challenge_sets.to_vec(), - }) - } else { - None - }; + let permutation_check_vars = + permutation_challenges.map(|permutation_challenge_sets| PermutationCheckVars { + local_zs: permutation_ctl_zs_commitment.get_lde_values_packed(i, step) + [..num_permutation_zs] + .to_vec(), + next_zs: permutation_ctl_zs_commitment.get_lde_values_packed(i_next, step) + [..num_permutation_zs] + .to_vec(), + permutation_challenge_sets: permutation_challenge_sets.to_vec(), + }); + let ctl_vars = ctl_data .zs_columns .iter() .enumerate() .map(|(iii, (_, columns))| CtlCheckVars:: { - local_z: get_comm_values(permutation_ctl_zs_commitment.unwrap(), i) + local_z: get_comm_values(permutation_ctl_zs_commitment, i) [num_permutation_zs + iii], - next_z: get_comm_values(permutation_ctl_zs_commitment.unwrap(), i_next) + next_z: get_comm_values(permutation_ctl_zs_commitment, i_next) [num_permutation_zs + iii], challenges: ctl_data.challenges.challenges[iii % config.num_challenges], columns, @@ -536,7 +517,7 @@ fn check_constraints<'a, F, C, S, const D: usize>( stark, config, vars, - permutation_check_data, + permutation_check_vars, &ctl_vars, &mut consumer, ); diff --git a/starky2/src/recursive_verifier.rs b/starky2/src/recursive_verifier.rs index 6dcc7a7e..b0021ac6 100644 --- a/starky2/src/recursive_verifier.rs +++ b/starky2/src/recursive_verifier.rs @@ -301,11 +301,8 @@ pub fn set_stark_proof_target, W, const D: usize>( &proof.openings.to_fri_openings(), ); - if let (Some(permutation_zs_cap_target), Some(permutation_zs_cap)) = ( - &proof_target.permutation_zs_cap, - &proof.permutation_ctl_zs_cap, - ) { - witness.set_cap_target(permutation_zs_cap_target, permutation_zs_cap); + if let Some(permutation_zs_cap_target) = &proof_target.permutation_zs_cap { + witness.set_cap_target(permutation_zs_cap_target, &proof.permutation_ctl_zs_cap); } set_fri_proof_target(witness, &proof_target.opening_proof, &proof.opening_proof); diff --git a/starky2/src/verifier.rs b/starky2/src/verifier.rs index a5411386..d8f24e97 100644 --- a/starky2/src/verifier.rs +++ b/starky2/src/verifier.rs @@ -1,7 +1,4 @@ -use std::iter::once; - use anyhow::{ensure, Result}; -use itertools::Itertools; use plonky2::field::extension_field::{Extendable, FieldExtension}; use plonky2::field::field_types::Field; use plonky2::fri::verifier::verify_fri_proof; @@ -93,8 +90,6 @@ where [(); S::PUBLIC_INPUTS]:, [(); C::Hasher::HASH_SIZE]:, { - // TODO: Fix this to take CTLs into account - // check_permutation_options(&stark, proof_with_pis, &challenges)?; let StarkProofWithPublicInputs { proof, public_inputs, @@ -135,8 +130,8 @@ where ); let num_permutation_zs = stark.num_permutation_batches(config); let permutation_data = stark.uses_permutation_args().then(|| PermutationCheckVars { - local_zs: permutation_ctl_zs.as_ref().unwrap()[..num_permutation_zs].to_vec(), - next_zs: permutation_ctl_zs_right.as_ref().unwrap()[..num_permutation_zs].to_vec(), + local_zs: permutation_ctl_zs[..num_permutation_zs].to_vec(), + next_zs: permutation_ctl_zs_right[..num_permutation_zs].to_vec(), permutation_challenge_sets: challenges.permutation_challenge_sets.unwrap(), }); eval_vanishing_poly::( @@ -167,10 +162,11 @@ where ); } - let merkle_caps = once(proof.trace_cap.clone()) - .chain(proof.permutation_ctl_zs_cap.clone()) - .chain(once(proof.quotient_polys_cap.clone())) - .collect_vec(); + let merkle_caps = vec![ + proof.trace_cap.clone(), + proof.permutation_ctl_zs_cap.clone(), + proof.quotient_polys_cap.clone(), + ]; verify_fri_proof::( &stark.fri_instance( @@ -202,38 +198,6 @@ fn eval_l_1_and_l_last(log_n: usize, x: F) -> (F, F) { (z_x * invs[0], z_x * invs[1]) } -/// Utility function to check that all permutation data wrapped in `Option`s are `Some` iff -/// the Stark uses a permutation argument. -#[allow(dead_code)] -fn check_permutation_options< - F: RichField + Extendable, - C: GenericConfig, - S: Stark, - const D: usize, ->( - stark: &S, - proof_with_pis: &StarkProofWithPublicInputs, - challenges: &StarkProofChallenges, -) -> Result<()> { - let options_is_some = [ - proof_with_pis.proof.permutation_ctl_zs_cap.is_some(), - proof_with_pis.proof.openings.permutation_ctl_zs.is_some(), - proof_with_pis - .proof - .openings - .permutation_ctl_zs_right - .is_some(), - challenges.permutation_challenge_sets.is_some(), - ]; - ensure!( - options_is_some - .into_iter() - .all(|b| b == stark.uses_permutation_args()), - "Permutation data doesn't match with Stark configuration." - ); - Ok(()) -} - #[cfg(test)] mod tests { use plonky2::field::field_types::Field;