diff --git a/plonky2/src/fri/verifier.rs b/plonky2/src/fri/verifier.rs index 47f10b8a..49cfa053 100644 --- a/plonky2/src/fri/verifier.rs +++ b/plonky2/src/fri/verifier.rs @@ -86,7 +86,7 @@ pub fn verify_fri_proof< ); let precomputed_reduced_evals = - PrecomputedReducedOpenings::from_os_and_alpha(&openings, challenges.fri_alpha); + PrecomputedReducedOpenings::from_os_and_alpha(openings, challenges.fri_alpha); for (&x_index, round_proof) in challenges .fri_query_indices .iter() diff --git a/starky/src/fibonacci_stark.rs b/starky/src/fibonacci_stark.rs index 1d760455..dc6d676a 100644 --- a/starky/src/fibonacci_stark.rs +++ b/starky/src/fibonacci_stark.rs @@ -120,6 +120,6 @@ mod tests { &mut TimingTree::default(), )?; - verify(stark, proof, &config, 5) + verify(stark, proof, &config) } } diff --git a/starky/src/get_challenges.rs b/starky/src/get_challenges.rs index 9d9b808e..79e1c032 100644 --- a/starky/src/get_challenges.rs +++ b/starky/src/get_challenges.rs @@ -10,6 +10,7 @@ use plonky2::plonk::config::GenericConfig; use crate::config::StarkConfig; use crate::proof::{StarkOpeningSet, StarkProof, StarkProofChallenges, StarkProofWithPublicInputs}; +#[allow(clippy::too_many_arguments)] fn get_challenges, C: GenericConfig, const D: usize>( trace_cap: &MerkleCap, quotient_polys_cap: &MerkleCap, @@ -61,7 +62,7 @@ impl, C: GenericConfig, const D: usize> .fri_query_indices) } - /// Computes all Fiat-Shamir challenges used in the Plonk proof. + /// Computes all Fiat-Shamir challenges used in the STARK proof. pub(crate) fn get_challenges( &self, config: &StarkConfig, @@ -93,6 +94,7 @@ impl, C: GenericConfig, const D: usize> } } +// TODO: Deal with the compressed stuff. // impl, C: GenericConfig, const D: usize> // CompressedProofWithPublicInputs // { diff --git a/starky/src/proof.rs b/starky/src/proof.rs index c2d2ac67..50ef21bc 100644 --- a/starky/src/proof.rs +++ b/starky/src/proof.rs @@ -25,7 +25,7 @@ pub struct StarkProofWithPublicInputs< const D: usize, > { pub proof: StarkProof, - // TODO: Maybe make it generic over a `S: Start` and replace with `[F; S::PUBLIC_INPUTS]`. + // TODO: Maybe make it generic over a `S: Stark` and replace with `[F; S::PUBLIC_INPUTS]`. pub public_inputs: Vec, } diff --git a/starky/src/prover.rs b/starky/src/prover.rs index 1c5310e4..d6543dae 100644 --- a/starky/src/prover.rs +++ b/starky/src/prover.rs @@ -20,7 +20,6 @@ use crate::proof::{StarkOpeningSet, StarkProof, StarkProofWithPublicInputs}; use crate::stark::Stark; use crate::vars::StarkEvaluationVars; -// TODO: Deal with public inputs. pub fn prove( stark: S, config: &StarkConfig, @@ -184,6 +183,7 @@ where let get_at_index = |comm: &PolynomialBatch, i: usize| -> [F; S::COLUMNS] { comm.get_lde_values(i).try_into().unwrap() }; + // Last element of the subgroup. let last = F::primitive_root_of_unity(degree_bits).inverse(); let coset = F::cyclic_subgroup_coset_known_order( F::primitive_root_of_unity(degree_bits + rate_bits), @@ -211,6 +211,8 @@ where stark.eval_packed_base(vars, &mut consumer); // TODO: Fix this once we use a genuine `PackedField`. let mut constraints_evals = consumer.accumulators(); + // We divide the constraints evaluations by `Z_H(x) / x - last`, i.e., the vanishing + // polynomial of `H` without it's last element. let denominator_inv = z_h_on_coset.eval_inverse(i); let z_last = coset[i] - last; for eval in &mut constraints_evals { diff --git a/starky/src/verifier.rs b/starky/src/verifier.rs index 298e4797..6a4464e1 100644 --- a/starky/src/verifier.rs +++ b/starky/src/verifier.rs @@ -13,7 +13,7 @@ use crate::proof::{StarkOpeningSet, StarkProof, StarkProofChallenges, StarkProof use crate::stark::Stark; use crate::vars::StarkEvaluationVars; -pub(crate) fn verify< +pub fn verify< F: RichField + Extendable, C: GenericConfig, S: Stark, @@ -22,14 +22,14 @@ pub(crate) fn verify< stark: S, proof_with_pis: StarkProofWithPublicInputs, config: &StarkConfig, - degree_bits: usize, ) -> Result<()> where [(); S::COLUMNS]:, [(); S::PUBLIC_INPUTS]:, { + let degree_bits = log2_strict(recover_degree(&proof_with_pis.proof, config)); let challenges = proof_with_pis.get_challenges(config, degree_bits)?; - verify_with_challenges(stark, proof_with_pis, challenges, config) + verify_with_challenges(stark, proof_with_pis, challenges, degree_bits, config) } pub(crate) fn verify_with_challenges< @@ -41,6 +41,7 @@ pub(crate) fn verify_with_challenges< stark: S, proof_with_pis: StarkProofWithPublicInputs, challenges: StarkProofChallenges, + degree_bits: usize, config: &StarkConfig, ) -> Result<()> where @@ -51,9 +52,6 @@ where proof, public_inputs, } = proof_with_pis; - let degree = recover_degree(&proof, config); - let degree_bits = log2_strict(degree); - let local_values = &proof.openings.local_values; let next_values = &proof.openings.local_values; let StarkOpeningSet { @@ -80,17 +78,16 @@ where .iter() .map(|&alpha| F::Extension::from_basefield(alpha)) .collect::>(), - l_1.into(), - l_last.into(), + l_1, + l_last, ); 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. + // Check each polynomial identity, of the form `vanishing(x) = Z_H(x) quotient(x) / (x - last)`, at zeta. let quotient_polys_zeta = &proof.openings.quotient_polys; let zeta_pow_deg = challenges.stark_zeta.exp_power_of_2(degree_bits); let z_h_zeta = zeta_pow_deg - F::Extension::ONE; - let g = F::primitive_root_of_unity(degree_bits + config.fri_config.rate_bits); let last = F::primitive_root_of_unity(degree_bits).inverse(); let z_last = challenges.stark_zeta - last.into(); // `quotient_polys_zeta` holds `num_challenges * quotient_degree_factor` evaluations. @@ -124,7 +121,9 @@ where Ok(()) } -/// Evaluate the Lagrange basis `L_1` and `L_n` at a point `x`. +/// Evaluate the Lagrange polynomials `L_1` and `L_n` at a point `x`. +/// `L_1(x) = (x^n - 1)/(n * (x - 1))` +/// `L_n(x) = (x^n - 1)/(n * (g * x - 1))`, with `g` the first element of the subgroup. 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); @@ -137,6 +136,7 @@ fn eval_l_1_and_l_last(log_n: usize, x: F) -> (F, F) { (z_x * invs[0], z_x * invs[1]) } +/// Recover the length of the trace from a STARK proof and a STARK config. fn recover_degree, C: GenericConfig, const D: usize>( proof: &StarkProof, config: &StarkConfig, diff --git a/system_zero/src/system_zero.rs b/system_zero/src/system_zero.rs index 38326b68..31b8434f 100644 --- a/system_zero/src/system_zero.rs +++ b/system_zero/src/system_zero.rs @@ -16,6 +16,7 @@ use crate::public_input_layout::NUM_PUBLIC_INPUTS; /// We require at least 2^16 rows as it helps support efficient 16-bit range checks. const MIN_TRACE_ROWS: usize = 1 << 16; +#[derive(Copy, Clone)] pub struct SystemZero, const D: usize> { _phantom: PhantomData, } @@ -92,6 +93,7 @@ mod tests { use starky::config::StarkConfig; use starky::prover::prove; use starky::stark::Stark; + use starky::verifier::verify; use crate::system_zero::SystemZero; @@ -108,8 +110,8 @@ mod tests { let config = StarkConfig::standard_fast_config(); let mut timing = TimingTree::new("prove", Level::Debug); let trace = system.generate_trace(); - prove::(system, &config, trace, public_inputs, &mut timing)?; + let proof = prove::(system, &config, trace, public_inputs, &mut timing)?; - Ok(()) + verify(system, proof, &config) } }