diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index b8d2b9c4..7d3bb137 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -230,7 +230,7 @@ impl, const D: usize> CircuitBuilder { } } - fn constant_polys(&self, gates: &[PrefixedGate]) -> Vec> { + fn constant_polys(&self, gates: &[PrefixedGate]) -> (Vec>, usize) { let num_constants = gates .iter() .map(|gate| gate.gate.0.num_constants() + gate.prefix.len()) @@ -253,10 +253,13 @@ impl, const D: usize> CircuitBuilder { }) .collect::>(); - transpose(&constants_per_gate) - .into_iter() - .map(PolynomialValues::new) - .collect() + ( + transpose(&constants_per_gate) + .into_iter() + .map(PolynomialValues::new) + .collect(), + num_constants, + ) } fn sigma_vecs(&self, k_is: &[F], subgroup: &[F]) -> Vec> { @@ -300,26 +303,26 @@ impl, const D: usize> CircuitBuilder { let degree_bits = log2_strict(degree); let subgroup = F::two_adic_subgroup(degree_bits); - let constant_vecs = self.constant_polys(&prefixed_gates); - let constants_commitment = - ListPolynomialCommitment::new(constant_vecs, self.config.fri_config.rate_bits, false); + let (constant_vecs, num_constants) = self.constant_polys(&prefixed_gates); let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires); let sigma_vecs = self.sigma_vecs(&k_is, &subgroup); - let sigmas_commitment = - ListPolynomialCommitment::new(sigma_vecs, self.config.fri_config.rate_bits, false); - let constants_root = constants_commitment.merkle_tree.root; - let sigmas_root = sigmas_commitment.merkle_tree.root; + let constants_sigmas_vecs = [constant_vecs, sigma_vecs].concat(); + let constants_sigmas_commitment = ListPolynomialCommitment::new( + constants_sigmas_vecs, + self.config.fri_config.rate_bits, + false, + ); + + let constants_sigmas_root = constants_sigmas_commitment.merkle_tree.root; let verifier_only = VerifierOnlyCircuitData { - constants_root, - sigmas_root, + constants_sigmas_root, }; let prover_only = ProverOnlyCircuitData { generators: self.generators, - constants_commitment, - sigmas_commitment, + constants_sigmas_commitment, subgroup, copy_constraints: self.copy_constraints, gate_instances: self.gate_instances, @@ -337,8 +340,7 @@ impl, const D: usize> CircuitBuilder { .expect("No gates?"); // TODO: This should also include an encoding of gate constraints. - let circuit_digest_parts = [constants_root.elements, sigmas_root.elements]; - let circuit_digest = hash_n_to_hash(circuit_digest_parts.concat(), false); + let circuit_digest = hash_n_to_hash(constants_sigmas_root.elements.to_vec(), false); let common = CommonCircuitData { config: self.config, @@ -346,6 +348,7 @@ impl, const D: usize> CircuitBuilder { gates: prefixed_gates, max_filtered_constraint_degree_bits: 3, // TODO: compute this correctly once filters land. num_gate_constraints, + num_constants, k_is, circuit_digest, }; diff --git a/src/circuit_data.rs b/src/circuit_data.rs index 4ec9c0d9..e46b0c41 100644 --- a/src/circuit_data.rs +++ b/src/circuit_data.rs @@ -1,3 +1,5 @@ +use std::ops::Range; + use anyhow::Result; use crate::field::extension_field::Extendable; @@ -116,10 +118,8 @@ impl, const D: usize> VerifierCircuitData { /// Circuit data required by the prover, but not the verifier. pub(crate) struct ProverOnlyCircuitData, const D: usize> { pub generators: Vec>>, - /// Commitments to the constants polynomial. - pub constants_commitment: ListPolynomialCommitment, - /// Commitments to the sigma polynomial. - pub sigmas_commitment: ListPolynomialCommitment, + /// Commitments to the constants polynomials and sigma polynomials. + pub constants_sigmas_commitment: ListPolynomialCommitment, /// Subgroup of order `degree`. pub subgroup: Vec, /// The circuit's copy constraints. @@ -130,15 +130,12 @@ pub(crate) struct ProverOnlyCircuitData, const D: usize> { /// Circuit data required by the verifier, but not the prover. pub(crate) struct VerifierOnlyCircuitData { - /// A commitment to each constant polynomial. - pub(crate) constants_root: Hash, - - /// A commitment to each permutation polynomial. - pub(crate) sigmas_root: Hash, + /// A commitment to each constant polynomial and each permutation polynomial. + pub(crate) constants_sigmas_root: Hash, } /// Circuit data required by both the prover and the verifier. -pub(crate) struct CommonCircuitData, const D: usize> { +pub struct CommonCircuitData, const D: usize> { pub(crate) config: CircuitConfig, pub(crate) degree_bits: usize, @@ -152,6 +149,9 @@ pub(crate) struct CommonCircuitData, const D: usize> { /// The largest number of constraints imposed by any gate. pub(crate) num_gate_constraints: usize, + /// The number of constant wires. + pub(crate) num_constants: usize, + /// The `{k_i}` valued used in `S_ID_i` in Plonk's permutation argument. pub(crate) k_is: Vec, @@ -189,6 +189,17 @@ impl, const D: usize> CommonCircuitData { // 2 constraints for each Z check. self.config.num_challenges * 2 + self.num_gate_constraints } + + /// Range of the constant polynomials in the `constants_sigmas_commitment`. + pub fn constants_range(&self) -> Range { + 0..self.num_constants + } + + /// Range of the sigma polynomials in the `constants_sigmas_commitment`. + pub fn sigmas_range(&self) -> Range { + // `self.k_is.len() = num_routed_wires` is the number of sigma polynomials. + self.num_constants..self.num_constants + self.k_is.len() + } } /// The `Target` version of `VerifierCircuitData`, for use inside recursive circuits. Note that this diff --git a/src/fri/recursive_verifier.rs b/src/fri/recursive_verifier.rs index 7c04d4a2..fc320f31 100644 --- a/src/fri/recursive_verifier.rs +++ b/src/fri/recursive_verifier.rs @@ -159,8 +159,7 @@ impl, const D: usize> CircuitBuilder { // Polynomials opened at `x`, i.e., the constants, sigmas and quotient polynomials. let single_evals = [ - PlonkPolynomials::CONSTANTS, - PlonkPolynomials::SIGMAS, + PlonkPolynomials::CONSTANTS_SIGMAS, PlonkPolynomials::QUOTIENT, ] .iter() diff --git a/src/fri/verifier.rs b/src/fri/verifier.rs index d88e8e0b..3db4f6f5 100644 --- a/src/fri/verifier.rs +++ b/src/fri/verifier.rs @@ -162,8 +162,7 @@ fn fri_combine_initial, const D: usize>( // Polynomials opened at `x`, i.e., the constants, sigmas and quotient polynomials. let single_evals = [ - PlonkPolynomials::CONSTANTS, - PlonkPolynomials::SIGMAS, + PlonkPolynomials::CONSTANTS_SIGMAS, PlonkPolynomials::QUOTIENT, ] .iter() diff --git a/src/plonk_common.rs b/src/plonk_common.rs index 59961384..62dbb487 100644 --- a/src/plonk_common.rs +++ b/src/plonk_common.rs @@ -29,34 +29,29 @@ impl PolynomialsIndexBlinding { /// Holds the indices and blinding flags of the Plonk polynomials. pub struct PlonkPolynomials; impl PlonkPolynomials { - pub const CONSTANTS: PolynomialsIndexBlinding = PolynomialsIndexBlinding { + pub const CONSTANTS_SIGMAS: PolynomialsIndexBlinding = PolynomialsIndexBlinding { index: 0, blinding: false, }; - pub const SIGMAS: PolynomialsIndexBlinding = PolynomialsIndexBlinding { - index: 1, - blinding: false, - }; pub const WIRES: PolynomialsIndexBlinding = PolynomialsIndexBlinding { - index: 2, + index: 1, blinding: true, }; pub const ZS: PolynomialsIndexBlinding = PolynomialsIndexBlinding { - index: 3, + index: 2, blinding: true, }; pub const QUOTIENT: PolynomialsIndexBlinding = PolynomialsIndexBlinding { - index: 4, + index: 3, blinding: true, }; pub fn polynomials(i: usize) -> PolynomialsIndexBlinding { match i { - 0 => Self::CONSTANTS, - 1 => Self::SIGMAS, - 2 => Self::WIRES, - 3 => Self::ZS, - 4 => Self::QUOTIENT, + 0 => Self::CONSTANTS_SIGMAS, + 1 => Self::WIRES, + 2 => Self::ZS, + 3 => Self::QUOTIENT, _ => panic!("There are only 5 sets of polynomials in Plonk."), } } diff --git a/src/polynomial/commitment.rs b/src/polynomial/commitment.rs index b0666a2f..d90b295b 100644 --- a/src/polynomial/commitment.rs +++ b/src/polynomial/commitment.rs @@ -1,6 +1,7 @@ use anyhow::Result; use rayon::prelude::*; +use crate::circuit_data::CommonCircuitData; use crate::field::extension_field::Extendable; use crate::field::extension_field::{FieldExtension, Frobenius}; use crate::field::field::Field; @@ -119,14 +120,15 @@ impl ListPolynomialCommitment { /// Takes the commitments to the constants - sigmas - wires - zs - quotient — polynomials, /// and an opening point `zeta` and produces a batched opening proof + opening set. pub fn open_plonk( - commitments: &[&Self; 5], + commitments: &[&Self; 4], zeta: F::Extension, challenger: &mut Challenger, - config: &FriConfig, + common_data: &CommonCircuitData, ) -> (OpeningProof, OpeningSet) where F: Extendable, { + let config = &common_data.config.fri_config; assert!(D > 1, "Not implemented for D=1."); let degree_log = commitments[0].degree_log; let g = F::Extension::primitive_root_of_unity(degree_log); @@ -145,7 +147,7 @@ impl ListPolynomialCommitment { commitments[1], commitments[2], commitments[3], - commitments[4], + common_data, ); challenger.observe_opening_set(&os); @@ -157,8 +159,7 @@ impl ListPolynomialCommitment { // Polynomials opened at a single point. let single_polys = [ - PlonkPolynomials::CONSTANTS, - PlonkPolynomials::SIGMAS, + PlonkPolynomials::CONSTANTS_SIGMAS, PlonkPolynomials::QUOTIENT, ] .iter() @@ -291,6 +292,7 @@ mod tests { use anyhow::Result; use super::*; + use crate::circuit_data::CircuitConfig; use crate::plonk_common::PlonkPolynomials; fn gen_random_test_case, const D: usize>( @@ -318,7 +320,7 @@ mod tests { } fn check_batch_polynomial_commitment, const D: usize>() -> Result<()> { - let ks = [1, 2, 3, 5, 8]; + let ks = [10, 2, 3, 8]; let degree_log = 11; let fri_config = FriConfig { proof_of_work_bits: 2, @@ -326,12 +328,26 @@ mod tests { reduction_arity_bits: vec![2, 3, 1, 2], num_query_rounds: 3, }; + // We only care about `fri_config, num_constants`, and the length of `k_is` here. + let common_data = CommonCircuitData { + config: CircuitConfig { + fri_config, + ..CircuitConfig::large_config() + }, + degree_bits: 0, + gates: vec![], + max_filtered_constraint_degree_bits: 0, + num_gate_constraints: 0, + num_constants: 4, + k_is: vec![F::ONE; 6], + circuit_digest: Hash::from_partial(vec![]), + }; - let lpcs = (0..5) + let lpcs = (0..4) .map(|i| { ListPolynomialCommitment::::new( gen_random_test_case(ks[i], degree_log), - fri_config.rate_bits, + common_data.config.fri_config.rate_bits, PlonkPolynomials::polynomials(i).blinding, ) }) @@ -339,10 +355,10 @@ mod tests { let zeta = gen_random_point::(degree_log); let (proof, os) = ListPolynomialCommitment::open_plonk::( - &[&lpcs[0], &lpcs[1], &lpcs[2], &lpcs[3], &lpcs[4]], + &[&lpcs[0], &lpcs[1], &lpcs[2], &lpcs[3]], zeta, &mut Challenger::new(), - &fri_config, + &common_data, ); proof.verify( @@ -353,10 +369,9 @@ mod tests { lpcs[1].merkle_tree.root, lpcs[2].merkle_tree.root, lpcs[3].merkle_tree.root, - lpcs[4].merkle_tree.root, ], &mut Challenger::new(), - &fri_config, + &common_data.config.fri_config, ) } diff --git a/src/proof.rs b/src/proof.rs index 7536f3ee..47b67c9c 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -1,5 +1,6 @@ use std::convert::TryInto; +use crate::circuit_data::CommonCircuitData; use crate::field::extension_field::target::ExtensionTarget; use crate::field::extension_field::Extendable; use crate::field::field::Field; @@ -160,11 +161,11 @@ impl, const D: usize> OpeningSet { pub fn new( z: F::Extension, g: F::Extension, - constant_commitment: &ListPolynomialCommitment, - plonk_sigmas_commitment: &ListPolynomialCommitment, + constants_sigmas_commitment: &ListPolynomialCommitment, wires_commitment: &ListPolynomialCommitment, plonk_zs_commitment: &ListPolynomialCommitment, quotient_polys_commitment: &ListPolynomialCommitment, + common_data: &CommonCircuitData, ) -> Self { let eval_commitment = |z: F::Extension, c: &ListPolynomialCommitment| { c.polynomials @@ -172,9 +173,10 @@ impl, const D: usize> OpeningSet { .map(|p| p.to_extension().eval(z)) .collect::>() }; + let constants_sigmas_eval = eval_commitment(z, constants_sigmas_commitment); Self { - constants: eval_commitment(z, constant_commitment), - plonk_s_sigmas: eval_commitment(z, plonk_sigmas_commitment), + constants: constants_sigmas_eval[common_data.constants_range()].to_vec(), + plonk_s_sigmas: constants_sigmas_eval[common_data.sigmas_range()].to_vec(), wires: eval_commitment(z, wires_commitment), plonk_zs: eval_commitment(z, plonk_zs_commitment), plonk_zs_right: eval_commitment(g * z, plonk_zs_commitment), diff --git a/src/prover.rs b/src/prover.rs index 42e5db98..728c17e5 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -134,15 +134,14 @@ pub(crate) fn prove, const D: usize>( let (opening_proof, openings) = timed!( ListPolynomialCommitment::open_plonk( &[ - &prover_data.constants_commitment, - &prover_data.sigmas_commitment, + &prover_data.constants_sigmas_commitment, &wires_commitment, &plonk_zs_commitment, "ient_polys_commitment, ], zeta, &mut challenger, - &common_data.config.fri_config + common_data, ), "to compute opening proofs" ); @@ -187,7 +186,9 @@ fn compute_z, const D: usize>( let x = subgroup[i - 1]; let mut numerator = F::ONE; let mut denominator = F::ONE; - let s_sigmas = prover_data.sigmas_commitment.original_values(i - 1); + let s_sigmas = &prover_data + .constants_sigmas_commitment + .original_values(i - 1)[common_data.sigmas_range()]; for j in 0..common_data.config.num_routed_wires { let wire_value = witness.get_wire(i - 1, j); let k_i = k_is[j]; @@ -247,8 +248,9 @@ fn compute_quotient_polys<'a, F: Extendable, const D: usize>( .map(|(i, x)| { let shifted_x = F::coset_shift() * x; let i_next = (i + next_step) % lde_size; - let local_constants = get_at_index(&prover_data.constants_commitment, i); - let s_sigmas = get_at_index(&prover_data.sigmas_commitment, i); + let local_constants_sigmas = get_at_index(&prover_data.constants_sigmas_commitment, i); + let local_constants = &local_constants_sigmas[common_data.constants_range()]; + let s_sigmas = &local_constants_sigmas[common_data.sigmas_range()]; let local_wires = get_at_index(wires_commitment, i); let local_plonk_zs = get_at_index(plonk_zs_commitment, i); let next_plonk_zs = get_at_index(plonk_zs_commitment, i_next); diff --git a/src/verifier.rs b/src/verifier.rs index a2750421..57bad7cf 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -64,8 +64,7 @@ pub(crate) fn verify, const D: usize>( let evaluations = proof.openings.clone(); let merkle_roots = &[ - verifier_data.constants_root, - verifier_data.sigmas_root, + verifier_data.constants_sigmas_root, proof.wires_root, proof.plonk_zs_root, proof.quotient_polys_root,