diff --git a/w3f-plonk-common/src/domain.rs b/w3f-plonk-common/src/domain.rs index 34e0eb1..e08a39a 100644 --- a/w3f-plonk-common/src/domain.rs +++ b/w3f-plonk-common/src/domain.rs @@ -185,6 +185,7 @@ pub struct EvaluatedDomain { pub l_first: F, pub l_last: F, pub vanishing_polynomial_inv: F, + pub z_n: F, // z^n } impl EvaluatedDomain { @@ -224,6 +225,7 @@ impl EvaluatedDomain { l_first, l_last, vanishing_polynomial_inv, + z_n, } } diff --git a/w3f-plonk-common/src/kzg_acc.rs b/w3f-plonk-common/src/kzg_acc.rs index 0b7bbeb..fa51a5b 100644 --- a/w3f-plonk-common/src/kzg_acc.rs +++ b/w3f-plonk-common/src/kzg_acc.rs @@ -109,9 +109,17 @@ impl KzgAccumulator { .map(|c| c.0) .collect::>(), ); - self.acc_points.push(proof.quotient_commitment.clone().0); + let mut r_nus = challenges.nus.iter().map(|nu| r * nu); self.acc_scalars - .extend(challenges.nus.iter().map(|nu| *nu * r).collect::>()); // numbers should match here + .extend(r_nus.by_ref().take(Piop::N_COLUMNS)); + self.acc_points + .extend(proof.quotient_commitment.iter().map(|c| c.0)); + let r_nu_last = r_nus.next().unwrap(); + self.acc_scalars.extend( + piop.chunk_coeffs() + .map(|c| r_nu_last * c) + .take(proof.quotient_commitment.len()), + ); self.acc_points.push(proof.agg_at_zeta_proof); self.acc_scalars.push(zeta * r); diff --git a/w3f-plonk-common/src/lib.rs b/w3f-plonk-common/src/lib.rs index 7f0f89d..1fcca3b 100644 --- a/w3f-plonk-common/src/lib.rs +++ b/w3f-plonk-common/src/lib.rs @@ -103,7 +103,7 @@ where { pub column_commitments: Commitments, pub columns_at_zeta: Evaluations, - pub quotient_commitment: CS::C, + pub quotient_commitment: Vec, pub lin_at_zeta_omega: F, pub agg_at_zeta_proof: CS::Proof, pub lin_at_zeta_omega_proof: CS::Proof, @@ -120,7 +120,7 @@ where { pub column_commitments: Commitments, pub columns_at_zeta: Evaluations, - pub quotient_commitment: C, + pub quotient_commitment: Vec, pub lin_at_zeta_omega: F, } diff --git a/w3f-plonk-common/src/piop.rs b/w3f-plonk-common/src/piop.rs index 81e5333..a1c6a28 100644 --- a/w3f-plonk-common/src/piop.rs +++ b/w3f-plonk-common/src/piop.rs @@ -1,14 +1,16 @@ -use ark_ff::PrimeField; +use crate::domain::{Domain, EvaluatedDomain}; +use crate::{ColumnsCommited, ColumnsEvaluated}; +use ark_ff::{FftField, PrimeField}; use ark_poly::univariate::DensePolynomial; -use ark_poly::Evaluations; +use ark_poly::{DenseUVPolynomial, EvaluationDomain, Evaluations}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::vec::Vec; use w3f_pcs::pcs::Commitment; - -use crate::domain::{Domain, EvaluatedDomain}; -use crate::{ColumnsCommited, ColumnsEvaluated}; +use w3f_pcs::utils; pub trait ProverPiop> { + const N_CONSTRAINTS: usize; + type Commitments: ColumnsCommited; type Evaluations: ColumnsEvaluated; type Instance: CanonicalSerialize + CanonicalDeserialize; @@ -29,6 +31,43 @@ pub trait ProverPiop> { // Constraint polynomials in evaluation form. fn constraints(&self) -> Vec>; + fn quotient(&self, alphas: &[F]) -> DensePolynomial { + let constraint_polys = self.constraints(); + // Aggregate constraint polynomials in evaluation form... + let agg_constraint_poly = aggregate_evaluations(&constraint_polys, &alphas); + // ...and then interpolate (to save some FFTs). + let agg_constraint_poly = agg_constraint_poly.interpolate(); + let quotient_poly = self.domain().divide_by_vanishing_poly(&agg_constraint_poly); + quotient_poly + } + + fn split_quotient(&self, q: DensePolynomial) -> Vec> { + let n = self.domain().domains.x1.size(); + let chunks: Vec> = q + .coeffs + .chunks(n) + .map(|coeffs| DensePolynomial::from_coefficients_slice(coeffs)) + .collect(); + chunks + } + + fn quotient_chunks(&self, alphas: &[F]) -> Vec> { + let q = self.quotient(alphas); + self.split_quotient(q) + } + + fn folded_quotient(&self, chunks: &[DensePolynomial], zeta: F) -> DensePolynomial { + let n = self.domain().domains.x1.size() as u64; + let zn = zeta.pow([n]); + let folded = chunks + .iter() + .zip(utils::powers(zn)) + .map(|(chunk, coeff)| chunk * coeff) + .reduce(|acc, new| acc + new) + .unwrap(); + folded + } + // 'Linearized' parts of constraint polynomials. // For a constraint of the form C = C(c1(X),...,ck(X),c1(wX),...,ck(wX)), where ci's are of degree n, // and an evaluation point z, it is a degree n polynomial r = C(c1(z),...,ck(z),c1(X),...,ck(X)). @@ -41,6 +80,16 @@ pub trait ProverPiop> { fn result(&self) -> Self::Instance; } +fn aggregate_evaluations(polys: &[Evaluations], coeffs: &[F]) -> Evaluations { + assert_eq!(coeffs.len(), polys.len()); + polys + .iter() + .zip(coeffs.iter()) + .map(|(p, &c)| p * c) + .reduce(|acc, p| &acc + &p) + .unwrap() +} + pub trait VerifierPiop> { const N_CONSTRAINTS: usize; const N_COLUMNS: usize; @@ -71,5 +120,19 @@ pub trait VerifierPiop> { // Commitment to the aggregated linearization polynomial without the constant term. fn lin_poly_commitment(&self, agg_coeffs: &[F]) -> (Vec, Vec); + fn chunk_coeffs(&self) -> impl Iterator { + let zn = self.domain_evaluated().z_n; + utils::powers(zn) + } + + fn quotient_commitment(&self, chunks: &[C]) -> C { + let quotient = chunks + .iter() + .zip(self.chunk_coeffs()) + .map(|(chunk, coeff)| chunk.mul(coeff)) + .sum(); + quotient + } + fn domain_evaluated(&self) -> &EvaluatedDomain; } diff --git a/w3f-plonk-common/src/prover.rs b/w3f-plonk-common/src/prover.rs index 1233922..3296f9a 100644 --- a/w3f-plonk-common/src/prover.rs +++ b/w3f-plonk-common/src/prover.rs @@ -1,11 +1,10 @@ use ark_ff::PrimeField; use ark_poly::univariate::DensePolynomial; -use ark_poly::{Evaluations, Polynomial}; +use ark_poly::Polynomial; use ark_serialize::CanonicalSerialize; use ark_std::format; use ark_std::vec::Vec; use ark_std::{end_timer, start_timer, vec}; - use w3f_pcs::aggregation::single::aggregate_polys; use w3f_pcs::pcs::PCS; @@ -62,21 +61,22 @@ impl, T: PlonkTranscript> PlonkProver transcript.add_committed_cols(&column_commitments); // ROUND 2 - let constraint_polys = piop.constraints(); - let alphas = transcript.get_constraints_aggregation_coeffs(constraint_polys.len()); - // Aggregate constraint polynomials in evaluation form... - let agg_constraint_poly = Self::aggregate_evaluations(&constraint_polys, &alphas); - // ...and then interpolate (to save some FFTs). - let agg_constraint_poly = agg_constraint_poly.interpolate(); - let quotient_poly = piop.domain().divide_by_vanishing_poly(&agg_constraint_poly); + let alphas = transcript.get_constraints_aggregation_coeffs(P::N_CONSTRAINTS); + // let quotient_poly = piop.quotient(&alphas); // The prover commits to the quotient polynomial... - let quotient_commitment = CS::commit(&self.pcs_ck, "ient_poly).unwrap(); - transcript.add_quotient_commitment("ient_commitment); - + let quotient_chunks = piop.quotient_chunks(&alphas); + let chunks_committed: Vec<_> = quotient_chunks + .iter() + .map(|qi| CS::commit(&self.pcs_ck, qi).unwrap()) + .collect(); + for qi_committed in chunks_committed.iter() { + transcript.add_quotient_commitment(&qi_committed); + } // and receives the evaluation point in response // ROUND 3 let zeta = transcript.get_evaluation_point(); + let q_folded = piop.folded_quotient("ient_chunks, zeta); let columns_to_open = piop.columns(); let columns_at_zeta = piop.columns_evaluated(&zeta); let constraint_polys_linearized = piop.constraints_lin(&zeta); @@ -87,11 +87,11 @@ impl, T: PlonkTranscript> PlonkProver transcript.add_evaluations(&columns_at_zeta, &lin_at_zeta_omega); let piop_proof = PiopProof { column_commitments, - quotient_commitment, + quotient_commitment: chunks_committed, columns_at_zeta, lin_at_zeta_omega, }; - let polys_at_zeta = [columns_to_open, vec![quotient_poly]].concat(); + let polys_at_zeta = [columns_to_open, vec![q_folded]].concat(); let pcs_openings = PcsOpeningAt2Points { polys_at_zeta, polys_at_zeta_omega: vec![lin], @@ -137,14 +137,4 @@ impl, T: PlonkTranscript> PlonkProver lin_at_zeta_omega_proof, } } - - pub fn aggregate_evaluations(polys: &[Evaluations], coeffs: &[F]) -> Evaluations { - assert_eq!(coeffs.len(), polys.len()); - polys - .iter() - .zip(coeffs.iter()) - .map(|(p, &c)| p * c) - .reduce(|acc, p| &acc + &p) - .unwrap() - } } diff --git a/w3f-plonk-common/src/verifier.rs b/w3f-plonk-common/src/verifier.rs index 4561559..3929a9e 100644 --- a/w3f-plonk-common/src/verifier.rs +++ b/w3f-plonk-common/src/verifier.rs @@ -53,7 +53,7 @@ impl, T: PlonkTranscript> PlonkVerifier, T: PlonkTranscript> PlonkVerifier>(2usize.pow(9), 1); + _test_ring_proof::>(2usize.pow(12), 1); } #[test] diff --git a/w3f-ring-proof/src/piop/prover.rs b/w3f-ring-proof/src/piop/prover.rs index ca06cea..f7fe2ba 100644 --- a/w3f-ring-proof/src/piop/prover.rs +++ b/w3f-ring-proof/src/piop/prover.rs @@ -144,6 +144,8 @@ where C: Commitment, Curve: TECurveConfig, { + const N_CONSTRAINTS: usize = 7; + type Commitments = RingCommitments; type Evaluations = RingEvaluations; type Instance = TeAffine; @@ -204,6 +206,8 @@ where C: Commitment, Curve: SWCurveConfig, { + const N_CONSTRAINTS: usize = 7; + type Commitments = RingCommitments; type Evaluations = RingEvaluations; type Instance = SwAffine;