From 987b30739546956d6adc6f1a59d45dfd5a68bf19 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Thu, 27 Jun 2024 17:30:24 +0200 Subject: [PATCH 01/11] Make Round 4 match with paper --- src/compiler/prover.rs | 65 +++++++++++++++++++------- src/fft/polynomial.rs | 2 +- src/proof_system/linearization_poly.rs | 47 +++++++++---------- src/proof_system/proof.rs | 38 ++++++++------- 4 files changed, 90 insertions(+), 62 deletions(-) diff --git a/src/compiler/prover.rs b/src/compiler/prover.rs index 0b0d09ca..70a75756 100644 --- a/src/compiler/prover.rs +++ b/src/compiler/prover.rs @@ -394,6 +394,45 @@ impl Prover { // compute evaluation challenge 'z' let z_challenge = transcript.challenge_scalar(b"z_challenge"); + // compute opening evaluations + let a_eval = a_w_poly.evaluate(&z_challenge); + let b_eval = b_w_poly.evaluate(&z_challenge); + let o_eval = o_w_poly.evaluate(&z_challenge); + let d_eval = d_w_poly.evaluate(&z_challenge); + + let s_sigma_1_eval = self + .prover_key + .permutation + .s_sigma_1 + .0 + .evaluate(&z_challenge); + let s_sigma_2_eval = self + .prover_key + .permutation + .s_sigma_2 + .0 + .evaluate(&z_challenge); + let s_sigma_3_eval = self + .prover_key + .permutation + .s_sigma_3 + .0 + .evaluate(&z_challenge); + + let perm_eval = z_poly.evaluate(&(z_challenge * domain.group_gen)); + + // add opening evaluations to transcript. + transcript.append_scalar(b"a_eval", &a_eval); + transcript.append_scalar(b"b_eval", &b_eval); + transcript.append_scalar(b"o_eval", &o_eval); + transcript.append_scalar(b"d_eval", &d_eval); + + transcript.append_scalar(b"s_sigma_1_eval", &s_sigma_1_eval); + transcript.append_scalar(b"s_sigma_2_eval", &s_sigma_2_eval); + transcript.append_scalar(b"s_sigma_3_eval", &s_sigma_3_eval); + + transcript.append_scalar(b"perm_eval", &perm_eval); + // round 5 // compute linearization polynomial let (r_poly, evaluations) = linearization_poly::compute( @@ -411,41 +450,31 @@ impl Prover { ), &a_w_poly, &b_w_poly, - &o_w_poly, &d_w_poly, &t_poly, &z_poly, + &a_eval, + &b_eval, + &o_eval, + &d_eval, + &s_sigma_1_eval, + &s_sigma_2_eval, + &s_sigma_3_eval, + &perm_eval, ); // add evaluations to transcript. - transcript.append_scalar(b"a_eval", &evaluations.proof.a_eval); - transcript.append_scalar(b"b_eval", &evaluations.proof.b_eval); - transcript.append_scalar(b"o_eval", &evaluations.proof.o_eval); - transcript.append_scalar(b"d_eval", &evaluations.proof.d_eval); transcript .append_scalar(b"a_next_eval", &evaluations.proof.a_next_eval); transcript .append_scalar(b"b_next_eval", &evaluations.proof.b_next_eval); transcript .append_scalar(b"d_next_eval", &evaluations.proof.d_next_eval); - transcript.append_scalar( - b"s_sigma_1_eval", - &evaluations.proof.s_sigma_1_eval, - ); - transcript.append_scalar( - b"s_sigma_2_eval", - &evaluations.proof.s_sigma_2_eval, - ); - transcript.append_scalar( - b"s_sigma_3_eval", - &evaluations.proof.s_sigma_3_eval, - ); transcript .append_scalar(b"q_arith_eval", &evaluations.proof.q_arith_eval); transcript.append_scalar(b"q_c_eval", &evaluations.proof.q_c_eval); transcript.append_scalar(b"q_l_eval", &evaluations.proof.q_l_eval); transcript.append_scalar(b"q_r_eval", &evaluations.proof.q_r_eval); - transcript.append_scalar(b"perm_eval", &evaluations.proof.perm_eval); transcript.append_scalar(b"t_eval", &evaluations.t_eval); transcript.append_scalar(b"r_eval", &evaluations.proof.r_poly_eval); diff --git a/src/fft/polynomial.rs b/src/fft/polynomial.rs index 68fdfb7b..e718ffe5 100644 --- a/src/fft/polynomial.rs +++ b/src/fft/polynomial.rs @@ -128,7 +128,7 @@ impl Polynomial { let powers = util::powers_of(value, self.len()); // Multiply the powers of the value by the coefficients - let mul_coeff = self.iter().zip(powers.into_iter()).map(|(c, p)| p * c); + let mul_coeff = self.iter().zip(powers).map(|(c, p)| p * c); // Sum it all up let mut sum = BlsScalar::zero(); diff --git a/src/proof_system/linearization_poly.rs b/src/proof_system/linearization_poly.rs index 03f9cc3a..f760336f 100644 --- a/src/proof_system/linearization_poly.rs +++ b/src/proof_system/linearization_poly.rs @@ -195,24 +195,20 @@ pub(crate) fn compute( ), a_w_poly: &Polynomial, b_w_poly: &Polynomial, - o_w_poly: &Polynomial, d_w_poly: &Polynomial, t_x_poly: &Polynomial, z_poly: &Polynomial, + a_eval: &BlsScalar, + b_eval: &BlsScalar, + o_eval: &BlsScalar, + d_eval: &BlsScalar, + s_sigma_1_eval: &BlsScalar, + s_sigma_2_eval: &BlsScalar, + s_sigma_3_eval: &BlsScalar, + perm_eval: &BlsScalar, ) -> (Polynomial, Evaluations) { // Compute evaluations let t_eval = t_x_poly.evaluate(z_challenge); - let a_eval = a_w_poly.evaluate(z_challenge); - let b_eval = b_w_poly.evaluate(z_challenge); - let o_eval = o_w_poly.evaluate(z_challenge); - let d_eval = d_w_poly.evaluate(z_challenge); - - let s_sigma_1_eval = - prover_key.permutation.s_sigma_1.0.evaluate(z_challenge); - let s_sigma_2_eval = - prover_key.permutation.s_sigma_2.0.evaluate(z_challenge); - let s_sigma_3_eval = - prover_key.permutation.s_sigma_3.0.evaluate(z_challenge); let q_arith_eval = prover_key.arithmetic.q_arith.0.evaluate(z_challenge); let q_c_eval = prover_key.logic.q_c.0.evaluate(z_challenge); @@ -222,7 +218,6 @@ pub(crate) fn compute( let a_next_eval = a_w_poly.evaluate(&(z_challenge * domain.group_gen)); let b_next_eval = b_w_poly.evaluate(&(z_challenge * domain.group_gen)); let d_next_eval = d_w_poly.evaluate(&(z_challenge * domain.group_gen)); - let perm_eval = z_poly.evaluate(&(z_challenge * domain.group_gen)); let f_1 = compute_circuit_satisfiability( ( @@ -231,10 +226,10 @@ pub(crate) fn compute( fixed_base_separation_challenge, var_base_separation_challenge, ), - &a_eval, - &b_eval, - &o_eval, - &d_eval, + a_eval, + b_eval, + o_eval, + d_eval, &a_next_eval, &b_next_eval, &d_next_eval, @@ -250,7 +245,7 @@ pub(crate) fn compute( (alpha, beta, gamma), (&a_eval, &b_eval, &o_eval, &d_eval), (&s_sigma_1_eval, &s_sigma_2_eval, &s_sigma_3_eval), - &perm_eval, + perm_eval, z_poly, ); @@ -263,10 +258,10 @@ pub(crate) fn compute( r_poly, Evaluations { proof: ProofEvaluations { - a_eval, - b_eval, - o_eval, - d_eval, + a_eval: *a_eval, + b_eval: *b_eval, + o_eval: *o_eval, + d_eval: *d_eval, a_next_eval, b_next_eval, d_next_eval, @@ -274,11 +269,11 @@ pub(crate) fn compute( q_c_eval, q_l_eval, q_r_eval, - s_sigma_1_eval, - s_sigma_2_eval, - s_sigma_3_eval, + s_sigma_1_eval: *s_sigma_1_eval, + s_sigma_2_eval: *s_sigma_2_eval, + s_sigma_3_eval: *s_sigma_3_eval, r_poly_eval, - perm_eval, + perm_eval: *perm_eval, }, t_eval, }, diff --git a/src/proof_system/proof.rs b/src/proof_system/proof.rs index da7036a9..f68de226 100644 --- a/src/proof_system/proof.rs +++ b/src/proof_system/proof.rs @@ -245,6 +245,27 @@ pub(crate) mod alloc { // Compute evaluation challenge z let z_challenge = transcript.challenge_scalar(b"z_challenge"); + // Add opening evaluations to transcript + transcript.append_scalar(b"a_eval", &self.evaluations.a_eval); + transcript.append_scalar(b"b_eval", &self.evaluations.b_eval); + transcript.append_scalar(b"o_eval", &self.evaluations.o_eval); + transcript.append_scalar(b"d_eval", &self.evaluations.d_eval); + + transcript.append_scalar( + b"s_sigma_1_eval", + &self.evaluations.s_sigma_1_eval, + ); + transcript.append_scalar( + b"s_sigma_2_eval", + &self.evaluations.s_sigma_2_eval, + ); + transcript.append_scalar( + b"s_sigma_3_eval", + &self.evaluations.s_sigma_3_eval, + ); + + transcript.append_scalar(b"perm_eval", &self.evaluations.perm_eval); + // Compute zero polynomial evaluated at challenge `z` let z_h_eval = domain.evaluate_vanishing_polynomial(&z_challenge); @@ -275,34 +296,17 @@ pub(crate) mod alloc { self.compute_quotient_commitment(&z_challenge, domain.size()); // Add evaluations to transcript - transcript.append_scalar(b"a_eval", &self.evaluations.a_eval); - transcript.append_scalar(b"b_eval", &self.evaluations.b_eval); - transcript.append_scalar(b"o_eval", &self.evaluations.o_eval); - transcript.append_scalar(b"d_eval", &self.evaluations.d_eval); transcript .append_scalar(b"a_next_eval", &self.evaluations.a_next_eval); transcript .append_scalar(b"b_next_eval", &self.evaluations.b_next_eval); transcript .append_scalar(b"d_next_eval", &self.evaluations.d_next_eval); - transcript.append_scalar( - b"s_sigma_1_eval", - &self.evaluations.s_sigma_1_eval, - ); - transcript.append_scalar( - b"s_sigma_2_eval", - &self.evaluations.s_sigma_2_eval, - ); - transcript.append_scalar( - b"s_sigma_3_eval", - &self.evaluations.s_sigma_3_eval, - ); transcript .append_scalar(b"q_arith_eval", &self.evaluations.q_arith_eval); transcript.append_scalar(b"q_c_eval", &self.evaluations.q_c_eval); transcript.append_scalar(b"q_l_eval", &self.evaluations.q_l_eval); transcript.append_scalar(b"q_r_eval", &self.evaluations.q_r_eval); - transcript.append_scalar(b"perm_eval", &self.evaluations.perm_eval); transcript.append_scalar(b"t_eval", &t_eval); transcript.append_scalar(b"r_eval", &self.evaluations.r_poly_eval); From eae261b00165d10f5affe4f233393a2b0a77c105 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Thu, 27 Jun 2024 17:39:34 +0200 Subject: [PATCH 02/11] Rename perm_eval to z_eval --- src/compiler/prover.rs | 6 +++--- src/proof_system/linearization_poly.rs | 14 +++++++------- src/proof_system/proof.rs | 8 ++++---- src/proof_system/widget/permutation/verifierkey.rs | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/compiler/prover.rs b/src/compiler/prover.rs index 70a75756..ad62d532 100644 --- a/src/compiler/prover.rs +++ b/src/compiler/prover.rs @@ -419,7 +419,7 @@ impl Prover { .0 .evaluate(&z_challenge); - let perm_eval = z_poly.evaluate(&(z_challenge * domain.group_gen)); + let z_eval = z_poly.evaluate(&(z_challenge * domain.group_gen)); // add opening evaluations to transcript. transcript.append_scalar(b"a_eval", &a_eval); @@ -431,7 +431,7 @@ impl Prover { transcript.append_scalar(b"s_sigma_2_eval", &s_sigma_2_eval); transcript.append_scalar(b"s_sigma_3_eval", &s_sigma_3_eval); - transcript.append_scalar(b"perm_eval", &perm_eval); + transcript.append_scalar(b"z_eval", &z_eval); // round 5 // compute linearization polynomial @@ -460,7 +460,7 @@ impl Prover { &s_sigma_1_eval, &s_sigma_2_eval, &s_sigma_3_eval, - &perm_eval, + &z_eval, ); // add evaluations to transcript. diff --git a/src/proof_system/linearization_poly.rs b/src/proof_system/linearization_poly.rs index f760336f..46074fe4 100644 --- a/src/proof_system/linearization_poly.rs +++ b/src/proof_system/linearization_poly.rs @@ -91,7 +91,7 @@ pub(crate) struct ProofEvaluations { // (Shifted) Evaluation of the permutation polynomial at `z * root of // unity` #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) perm_eval: BlsScalar, + pub(crate) z_eval: BlsScalar, } // The struct ProofEvaluations has 16 BlsScalars @@ -119,7 +119,7 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { writer.write(&self.s_sigma_2_eval.to_bytes()); writer.write(&self.s_sigma_3_eval.to_bytes()); writer.write(&self.r_poly_eval.to_bytes()); - writer.write(&self.perm_eval.to_bytes()); + writer.write(&self.z_eval.to_bytes()); buf } @@ -143,7 +143,7 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { let s_sigma_2_eval = BlsScalar::from_reader(&mut buffer)?; let s_sigma_3_eval = BlsScalar::from_reader(&mut buffer)?; let r_poly_eval = BlsScalar::from_reader(&mut buffer)?; - let perm_eval = BlsScalar::from_reader(&mut buffer)?; + let z_eval = BlsScalar::from_reader(&mut buffer)?; Ok(ProofEvaluations { a_eval, @@ -161,7 +161,7 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { s_sigma_2_eval, s_sigma_3_eval, r_poly_eval, - perm_eval, + z_eval, }) } } @@ -205,7 +205,7 @@ pub(crate) fn compute( s_sigma_1_eval: &BlsScalar, s_sigma_2_eval: &BlsScalar, s_sigma_3_eval: &BlsScalar, - perm_eval: &BlsScalar, + z_eval: &BlsScalar, ) -> (Polynomial, Evaluations) { // Compute evaluations let t_eval = t_x_poly.evaluate(z_challenge); @@ -245,7 +245,7 @@ pub(crate) fn compute( (alpha, beta, gamma), (&a_eval, &b_eval, &o_eval, &d_eval), (&s_sigma_1_eval, &s_sigma_2_eval, &s_sigma_3_eval), - perm_eval, + z_eval, z_poly, ); @@ -273,7 +273,7 @@ pub(crate) fn compute( s_sigma_2_eval: *s_sigma_2_eval, s_sigma_3_eval: *s_sigma_3_eval, r_poly_eval, - perm_eval: *perm_eval, + z_eval: *z_eval, }, t_eval, }, diff --git a/src/proof_system/proof.rs b/src/proof_system/proof.rs index f68de226..a303a3f6 100644 --- a/src/proof_system/proof.rs +++ b/src/proof_system/proof.rs @@ -264,7 +264,7 @@ pub(crate) mod alloc { &self.evaluations.s_sigma_3_eval, ); - transcript.append_scalar(b"perm_eval", &self.evaluations.perm_eval); + transcript.append_scalar(b"z_eval", &self.evaluations.z_eval); // Compute zero polynomial evaluated at challenge `z` let z_h_eval = domain.evaluate_vanishing_polynomial(&z_challenge); @@ -286,7 +286,7 @@ pub(crate) mod alloc { &z_challenge, &z_h_eval, &l1_eval, - &self.evaluations.perm_eval, + &self.evaluations.z_eval, ); // Compute commitment to quotient polynomial @@ -363,7 +363,7 @@ pub(crate) mod alloc { let mut shifted_aggregate_proof = AggregateProof::with_witness(self.w_z_chall_w_comm); shifted_aggregate_proof - .add_part((self.evaluations.perm_eval, self.z_comm)); + .add_part((self.evaluations.z_eval, self.z_comm)); shifted_aggregate_proof .add_part((self.evaluations.a_next_eval, self.a_comm)); shifted_aggregate_proof @@ -625,7 +625,7 @@ mod proof_tests { s_sigma_2_eval: BlsScalar::random(&mut OsRng), s_sigma_3_eval: BlsScalar::random(&mut OsRng), r_poly_eval: BlsScalar::random(&mut OsRng), - perm_eval: BlsScalar::random(&mut OsRng), + z_eval: BlsScalar::random(&mut OsRng), }, }; diff --git a/src/proof_system/widget/permutation/verifierkey.rs b/src/proof_system/widget/permutation/verifierkey.rs index 3052aee0..b1f2c5bf 100644 --- a/src/proof_system/widget/permutation/verifierkey.rs +++ b/src/proof_system/widget/permutation/verifierkey.rs @@ -94,7 +94,7 @@ mod alloc { let beta_sigma_3 = beta * evaluations.s_sigma_3_eval; let q_2 = evaluations.o_eval + beta_sigma_3 + gamma; - let q_3 = beta * evaluations.perm_eval * alpha; + let q_3 = beta * evaluations.z_eval * alpha; -(q_0 * q_1 * q_2 * q_3) }; From 7e6e4a27064ace5259e40b699a832c58ba837fb5 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Tue, 2 Jul 2024 12:27:44 +0200 Subject: [PATCH 03/11] Remove self from compute_aggregate_witness --- src/commitment_scheme/kzg10/key.rs | 8 +++++--- src/compiler/prover.rs | 13 ++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/commitment_scheme/kzg10/key.rs b/src/commitment_scheme/kzg10/key.rs index 457a8521..f6f4391b 100644 --- a/src/commitment_scheme/kzg10/key.rs +++ b/src/commitment_scheme/kzg10/key.rs @@ -191,7 +191,6 @@ impl CommitKey { /// We apply the same optimization mentioned in when computing each witness; /// removing f(z). pub(crate) fn compute_aggregate_witness( - &self, polynomials: &[Polynomial], point: &BlsScalar, transcript: &mut Transcript, @@ -392,8 +391,11 @@ mod test { } // Compute the aggregate witness for polynomials - let witness_poly = - ck.compute_aggregate_witness(polynomials, point, transcript); + let witness_poly = CommitKey::compute_aggregate_witness( + polynomials, + point, + transcript, + ); // Commit to witness polynomial let witness_commitment = ck.commit(&witness_poly)?; diff --git a/src/compiler/prover.rs b/src/compiler/prover.rs index ad62d532..918e2138 100644 --- a/src/compiler/prover.rs +++ b/src/compiler/prover.rs @@ -493,7 +493,7 @@ impl Prover { // compute aggregate witness to polynomials evaluated at the evaluation // challenge z. The challenge v is selected inside - let aggregate_witness = self.commit_key.compute_aggregate_witness( + let aggregate_witness = CommitKey::compute_aggregate_witness( &[ quot, r_poly, @@ -512,12 +512,11 @@ impl Prover { // compute aggregate witness to polynomials evaluated at the shifted // evaluation challenge - let shifted_aggregate_witness = - self.commit_key.compute_aggregate_witness( - &[z_poly, a_w_poly, b_w_poly, d_w_poly], - &(z_challenge * domain.group_gen), - &mut transcript, - ); + let shifted_aggregate_witness = CommitKey::compute_aggregate_witness( + &[z_poly, a_w_poly, b_w_poly, d_w_poly], + &(z_challenge * domain.group_gen), + &mut transcript, + ); let w_z_chall_w_comm = self.commit_key.commit(&shifted_aggregate_witness)?; From 6ca931747aa21da95e4c8e6f6ceb121a6858aa16 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Tue, 2 Jul 2024 13:26:03 +0200 Subject: [PATCH 04/11] Select v_challenge according to the paper --- src/commitment_scheme/kzg10/key.rs | 17 ++++++++++------- src/commitment_scheme/kzg10/proof.rs | 9 ++------- src/compiler/prover.rs | 17 +++++++++++------ src/proof_system/proof.rs | 11 +++++++++-- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/commitment_scheme/kzg10/key.rs b/src/commitment_scheme/kzg10/key.rs index f6f4391b..1f802e94 100644 --- a/src/commitment_scheme/kzg10/key.rs +++ b/src/commitment_scheme/kzg10/key.rs @@ -193,10 +193,9 @@ impl CommitKey { pub(crate) fn compute_aggregate_witness( polynomials: &[Polynomial], point: &BlsScalar, - transcript: &mut Transcript, + v_challenge: &BlsScalar, ) -> Polynomial { - let v_challenge = transcript.challenge_scalar(b"v_challenge"); - let powers = util::powers_of(&v_challenge, polynomials.len() - 1); + let powers = util::powers_of(v_challenge, polynomials.len() - 1); assert_eq!(powers.len(), polynomials.len()); @@ -390,11 +389,13 @@ mod test { polynomial_commitments.push(ck.commit(poly)?) } + let v_challenge = transcript.challenge_scalar(b"v_challenge"); + // Compute the aggregate witness for polynomials let witness_poly = CommitKey::compute_aggregate_witness( polynomials, point, - transcript, + &v_challenge, ); // Commit to witness polynomial @@ -498,8 +499,9 @@ mod test { // Verifier's View let ok = { - let flattened_proof = - aggregated_proof.flatten(&mut Transcript::new(b"agg_flatten")); + let transcript = &mut Transcript::new(b"agg_flatten"); + let v_challenge = transcript.challenge_scalar(b"v_challenge"); + let flattened_proof = aggregated_proof.flatten(&v_challenge); check(&opening_key, point, flattened_proof) }; @@ -546,7 +548,8 @@ mod test { // Verifier's View let mut transcript = Transcript::new(b"agg_batch"); - let flattened_proof = aggregated_proof.flatten(&mut transcript); + let v_challenge = transcript.challenge_scalar(b"v_challenge"); + let flattened_proof = aggregated_proof.flatten(&v_challenge); opening_key.batch_check( &[point_a, point_b], diff --git a/src/commitment_scheme/kzg10/proof.rs b/src/commitment_scheme/kzg10/proof.rs index afd7fa5d..1fae715a 100644 --- a/src/commitment_scheme/kzg10/proof.rs +++ b/src/commitment_scheme/kzg10/proof.rs @@ -24,12 +24,10 @@ pub(crate) struct Proof { #[cfg(feature = "alloc")] pub(crate) mod alloc { use super::*; - use crate::transcript::TranscriptProtocol; use crate::util::powers_of; #[rustfmt::skip] use ::alloc::vec::Vec; use dusk_bls12_381::G1Projective; - use merlin::Transcript; #[cfg(feature = "std")] use rayon::prelude::*; @@ -65,12 +63,9 @@ pub(crate) mod alloc { } /// Flattens an `AggregateProof` into a `Proof`. - /// The transcript must have the same view as the transcript that was - /// used to aggregate the witness in the proving stage. - pub(crate) fn flatten(&self, transcript: &mut Transcript) -> Proof { - let v_challenge = transcript.challenge_scalar(b"v_challenge"); + pub(crate) fn flatten(&self, v_challenge: &BlsScalar) -> Proof { let powers = powers_of( - &v_challenge, + v_challenge, self.commitments_to_polynomials.len() - 1, ); diff --git a/src/compiler/prover.rs b/src/compiler/prover.rs index 918e2138..fbd1ad97 100644 --- a/src/compiler/prover.rs +++ b/src/compiler/prover.rs @@ -434,6 +434,9 @@ impl Prover { transcript.append_scalar(b"z_eval", &z_eval); // round 5 + // compute the challenge 'v' + let v_challenge = transcript.challenge_scalar(b"v_challenge"); + // compute linearization polynomial let (r_poly, evaluations) = linearization_poly::compute( &domain, @@ -491,8 +494,7 @@ impl Prover { let quot = &abc + &d; - // compute aggregate witness to polynomials evaluated at the evaluation - // challenge z. The challenge v is selected inside + // compute the opening proof polynomial 'W_z(X)' let aggregate_witness = CommitKey::compute_aggregate_witness( &[ quot, @@ -506,16 +508,19 @@ impl Prover { self.prover_key.permutation.s_sigma_3.0.clone(), ], &z_challenge, - &mut transcript, + &v_challenge, ); let w_z_chall_comm = self.commit_key.commit(&aggregate_witness)?; - // compute aggregate witness to polynomials evaluated at the shifted - // evaluation challenge + // compute the shifted challenge 'v' + let v_challenge_shifted = + transcript.challenge_scalar(b"v_challenge_shifted"); + + // compute the shifted opening proof polynomial 'W_zw(X)' let shifted_aggregate_witness = CommitKey::compute_aggregate_witness( &[z_poly, a_w_poly, b_w_poly, d_w_poly], &(z_challenge * domain.group_gen), - &mut transcript, + &v_challenge_shifted, ); let w_z_chall_w_comm = self.commit_key.commit(&shifted_aggregate_witness)?; diff --git a/src/proof_system/proof.rs b/src/proof_system/proof.rs index a303a3f6..bdbbf05d 100644 --- a/src/proof_system/proof.rs +++ b/src/proof_system/proof.rs @@ -266,6 +266,8 @@ pub(crate) mod alloc { transcript.append_scalar(b"z_eval", &self.evaluations.z_eval); + let v_challenge = transcript.challenge_scalar(b"v_challenge"); + // Compute zero polynomial evaluated at challenge `z` let z_h_eval = domain.evaluate_vanishing_polynomial(&z_challenge); @@ -357,7 +359,7 @@ pub(crate) mod alloc { verifier_key.permutation.s_sigma_3, )); // Flatten proof with opening challenge - let flattened_proof_a = aggregate_proof.flatten(transcript); + let flattened_proof_a = aggregate_proof.flatten(&v_challenge); // Compose the shifted aggregate proof let mut shifted_aggregate_proof = @@ -371,10 +373,15 @@ pub(crate) mod alloc { shifted_aggregate_proof .add_part((self.evaluations.d_next_eval, self.d_comm)); - let flattened_proof_b = shifted_aggregate_proof.flatten(transcript); + let v_challenge_shifted = + transcript.challenge_scalar(b"v_challenge_shifted"); + let flattened_proof_b = + shifted_aggregate_proof.flatten(&v_challenge_shifted); + // Add commitment to openings to transcript transcript.append_commitment(b"w_z", &self.w_z_chall_comm); transcript.append_commitment(b"w_z_w", &self.w_z_chall_w_comm); + // Batch check if opening_key .batch_check( From e3f8a7e2b0c6371da047bfd50ce7750b73536970 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Wed, 3 Jul 2024 15:16:18 +0200 Subject: [PATCH 05/11] Rename wire 'o' to 'c' --- src/commitment_scheme/kzg10/key.rs | 16 +++---- src/compiler/prover.rs | 24 +++++----- src/composer/permutation.rs | 48 +++++++++---------- src/proof_system/linearization_poly.rs | 28 +++++------ src/proof_system/proof.rs | 22 ++++----- src/proof_system/quotient_poly.rs | 28 +++++------ .../widget/arithmetic/proverkey.rs | 14 +++--- .../widget/arithmetic/verifierkey.rs | 2 +- .../widget/ecc/curve_addition/proverkey.rs | 8 ++-- .../widget/ecc/curve_addition/verifierkey.rs | 2 +- .../ecc/scalar_mul/fixed_base/proverkey.rs | 8 ++-- .../ecc/scalar_mul/fixed_base/verifierkey.rs | 2 +- src/proof_system/widget/logic/proverkey.rs | 8 ++-- src/proof_system/widget/logic/verifierkey.rs | 2 +- .../widget/permutation/proverkey.rs | 44 ++++++++--------- .../widget/permutation/verifierkey.rs | 8 ++-- src/proof_system/widget/range/proverkey.rs | 14 +++--- src/proof_system/widget/range/verifierkey.rs | 4 +- 18 files changed, 141 insertions(+), 141 deletions(-) diff --git a/src/commitment_scheme/kzg10/key.rs b/src/commitment_scheme/kzg10/key.rs index 1f802e94..78430198 100644 --- a/src/commitment_scheme/kzg10/key.rs +++ b/src/commitment_scheme/kzg10/key.rs @@ -485,13 +485,13 @@ mod test { let poly_b = Polynomial::rand(26 + 1, &mut OsRng); let poly_b_eval = poly_b.evaluate(&point); - let poly_o = Polynomial::rand(27, &mut OsRng); - let poly_o_eval = poly_o.evaluate(&point); + let poly_c = Polynomial::rand(27, &mut OsRng); + let poly_c_eval = poly_c.evaluate(&point); open_multiple( &ck, - &[poly_a, poly_b, poly_o], - vec![poly_a_eval, poly_b_eval, poly_o_eval], + &[poly_a, poly_b, poly_c], + vec![poly_a_eval, poly_b_eval, poly_c_eval], &point, &mut Transcript::new(b"agg_flatten"), )? @@ -525,16 +525,16 @@ mod test { let poly_b = Polynomial::rand(26, &mut OsRng); let poly_b_eval = poly_b.evaluate(&point_a); - let poly_o = Polynomial::rand(27, &mut OsRng); - let poly_o_eval = poly_o.evaluate(&point_a); + let poly_c = Polynomial::rand(27, &mut OsRng); + let poly_c_eval = poly_c.evaluate(&point_a); let poly_d = Polynomial::rand(28, &mut OsRng); let poly_d_eval = poly_d.evaluate(&point_b); let aggregated_proof = open_multiple( &ck, - &[poly_a, poly_b, poly_o], - vec![poly_a_eval, poly_b_eval, poly_o_eval], + &[poly_a, poly_b, poly_c], + vec![poly_a_eval, poly_b_eval, poly_c_eval], &point_a, &mut Transcript::new(b"agg_batch"), )?; diff --git a/src/compiler/prover.rs b/src/compiler/prover.rs index fbd1ad97..1e5ffe35 100644 --- a/src/compiler/prover.rs +++ b/src/compiler/prover.rs @@ -256,32 +256,32 @@ impl Prover { // convert wires to padded scalars let mut a_w_scalar = vec![BlsScalar::zero(); size]; let mut b_w_scalar = vec![BlsScalar::zero(); size]; - let mut o_w_scalar = vec![BlsScalar::zero(); size]; + let mut c_w_scalar = vec![BlsScalar::zero(); size]; let mut d_w_scalar = vec![BlsScalar::zero(); size]; prover.constraints.iter().enumerate().for_each(|(i, c)| { a_w_scalar[i] = prover[c.w_a]; b_w_scalar[i] = prover[c.w_b]; - o_w_scalar[i] = prover[c.w_o]; + c_w_scalar[i] = prover[c.w_o]; d_w_scalar[i] = prover[c.w_d]; }); let a_w_poly = Self::blind_poly(rng, &a_w_scalar, 1, &domain); let b_w_poly = Self::blind_poly(rng, &b_w_scalar, 1, &domain); - let o_w_poly = Self::blind_poly(rng, &o_w_scalar, 1, &domain); + let c_w_poly = Self::blind_poly(rng, &c_w_scalar, 1, &domain); let d_w_poly = Self::blind_poly(rng, &d_w_scalar, 1, &domain); // commit to wire polynomials // ([a(x)]_1, [b(x)]_1, [c(x)]_1, [d(x)]_1) let a_w_poly_commit = self.commit_key.commit(&a_w_poly)?; let b_w_poly_commit = self.commit_key.commit(&b_w_poly)?; - let o_w_poly_commit = self.commit_key.commit(&o_w_poly)?; + let c_w_poly_commit = self.commit_key.commit(&c_w_poly)?; let d_w_poly_commit = self.commit_key.commit(&d_w_poly)?; // Add wire polynomial commitments to transcript transcript.append_commitment(b"a_w", &a_w_poly_commit); transcript.append_commitment(b"b_w", &b_w_poly_commit); - transcript.append_commitment(b"o_w", &o_w_poly_commit); + transcript.append_commitment(b"c_w", &c_w_poly_commit); transcript.append_commitment(b"d_w", &d_w_poly_commit); // round 2 @@ -299,7 +299,7 @@ impl Prover { let wires = [ a_w_scalar.as_slice(), b_w_scalar.as_slice(), - o_w_scalar.as_slice(), + c_w_scalar.as_slice(), d_w_scalar.as_slice(), ]; let permutation = prover @@ -327,7 +327,7 @@ impl Prover { let pi_poly = Polynomial::from_coefficients_vec(pi_poly); // compute quotient polynomial - let wires = (&a_w_poly, &b_w_poly, &o_w_poly, &d_w_poly); + let wires = (&a_w_poly, &b_w_poly, &c_w_poly, &d_w_poly); let args = &( alpha, beta, @@ -397,7 +397,7 @@ impl Prover { // compute opening evaluations let a_eval = a_w_poly.evaluate(&z_challenge); let b_eval = b_w_poly.evaluate(&z_challenge); - let o_eval = o_w_poly.evaluate(&z_challenge); + let c_eval = c_w_poly.evaluate(&z_challenge); let d_eval = d_w_poly.evaluate(&z_challenge); let s_sigma_1_eval = self @@ -424,7 +424,7 @@ impl Prover { // add opening evaluations to transcript. transcript.append_scalar(b"a_eval", &a_eval); transcript.append_scalar(b"b_eval", &b_eval); - transcript.append_scalar(b"o_eval", &o_eval); + transcript.append_scalar(b"c_eval", &c_eval); transcript.append_scalar(b"d_eval", &d_eval); transcript.append_scalar(b"s_sigma_1_eval", &s_sigma_1_eval); @@ -458,7 +458,7 @@ impl Prover { &z_poly, &a_eval, &b_eval, - &o_eval, + &c_eval, &d_eval, &s_sigma_1_eval, &s_sigma_2_eval, @@ -501,7 +501,7 @@ impl Prover { r_poly, a_w_poly.clone(), b_w_poly.clone(), - o_w_poly, + c_w_poly, d_w_poly.clone(), self.prover_key.permutation.s_sigma_1.0.clone(), self.prover_key.permutation.s_sigma_2.0.clone(), @@ -528,7 +528,7 @@ impl Prover { let proof = Proof { a_comm: a_w_poly_commit, b_comm: b_w_poly_commit, - o_comm: o_w_poly_commit, + c_comm: c_w_poly_commit, d_comm: d_w_poly_commit, z_comm: z_poly_commit, diff --git a/src/composer/permutation.rs b/src/composer/permutation.rs index 32f5fc81..4db92efb 100644 --- a/src/composer/permutation.rs +++ b/src/composer/permutation.rs @@ -223,7 +223,7 @@ impl Permutation { let ks = vec![BlsScalar::one(), K1, K2, K3]; // Transpose wires and sigma values to get "rows" in the form [a_w_i, - // b_w_i, o_w_i, d_w_i] where each row contains the wire and sigma + // b_w_i, c_w_i, d_w_i] where each row contains the wire and sigma // values for a single gate let gatewise_wires = izip!(wires[0], wires[1], wires[2], wires[3]) .map(|(w0, w1, w2, w3)| vec![w0, w1, w2, w3]); @@ -311,7 +311,7 @@ mod test { domain: &EvaluationDomain, a_w: &[BlsScalar], b_w: &[BlsScalar], - o_w: &[BlsScalar], + c_w: &[BlsScalar], d_w: &[BlsScalar], beta: &BlsScalar, gamma: &BlsScalar, @@ -362,7 +362,7 @@ mod test { let b_w_gamma: Vec<_> = b_w.iter().map(|b_w| b_w + gamma).collect(); // Compute out_wire + gamma - let o_w_gamma: Vec<_> = o_w.iter().map(|o_w| o_w + gamma).collect(); + let c_w_gamma: Vec<_> = c_w.iter().map(|c_w| c_w + gamma).collect(); // Compute fourth_wire + gamma let d_w_gamma: Vec<_> = d_w.iter().map(|d_w| d_w + gamma).collect(); @@ -372,7 +372,7 @@ mod test { let accumulator_components_without_l1: Vec<_> = izip!( a_w_gamma, b_w_gamma, - o_w_gamma, + c_w_gamma, d_w_gamma, common_roots, beta_roots_k1, @@ -387,7 +387,7 @@ mod test { |( a_w_gamma, b_w_gamma, - o_w_gamma, + c_w_gamma, d_w_gamma, beta_root, beta_root_k1, @@ -405,7 +405,7 @@ mod test { let ac2 = b_w_gamma + beta_root_k1; // w_{2n+j} + beta * K2 * root^j-1 + gamma - let ac3 = o_w_gamma + beta_root_k2; + let ac3 = c_w_gamma + beta_root_k2; // w_{3n+j} + beta * K3 * root^j-1 + gamma let ac4 = d_w_gamma + beta_root_k3; @@ -417,7 +417,7 @@ mod test { let ac6 = (b_w_gamma + beta_s_sigma_2).invert().unwrap(); // 1 / w_{2n+j} + beta * sigma(2n+j) + gamma - let ac7 = (o_w_gamma + beta_s_sigma_3).invert().unwrap(); + let ac7 = (c_w_gamma + beta_s_sigma_3).invert().unwrap(); // 1 / w_{3n+j} + beta * sigma(3n+j) + gamma let ac8 = (d_w_gamma + beta_s_sigma_4).invert().unwrap(); @@ -472,7 +472,7 @@ mod test { domain: &EvaluationDomain, a_w: I, b_w: I, - o_w: I, + c_w: I, d_w: I, beta: &BlsScalar, gamma: &BlsScalar, @@ -522,7 +522,7 @@ mod test { let b_w_gamma: Vec<_> = b_w.map(|w| w + gamma).collect(); // Compute out_wire + gamma - let o_w_gamma: Vec<_> = o_w.map(|w| w + gamma).collect(); + let c_w_gamma: Vec<_> = c_w.map(|w| w + gamma).collect(); // Compute fourth_wire + gamma let d_w_gamma: Vec<_> = d_w.map(|w| w + gamma).collect(); @@ -544,7 +544,7 @@ mod test { for ( a_w_gamma, b_w_gamma, - o_w_gamma, + c_w_gamma, d_w_gamma, beta_root, beta_root_k1, @@ -553,7 +553,7 @@ mod test { ) in izip!( a_w_gamma.iter(), b_w_gamma.iter(), - o_w_gamma.iter(), + c_w_gamma.iter(), d_w_gamma.iter(), beta_roots_iter, beta_roots_k1_iter, @@ -566,8 +566,8 @@ mod test { // (b_w + beta * root * k_1 + gamma) let prod_b = beta_root_k1 + b_w_gamma; - // (o_w + beta * root * k_2 + gamma) - let prod_c = beta_root_k2 + o_w_gamma; + // (c_w + beta * root * k_2 + gamma) + let prod_c = beta_root_k2 + c_w_gamma; // (d_w + beta * root * k_3 + gamma) let prod_d = beta_root_k3 + d_w_gamma; @@ -585,7 +585,7 @@ mod test { for ( a_w_gamma, b_w_gamma, - o_w_gamma, + c_w_gamma, d_w_gamma, beta_s_sigma_1, beta_s_sigma_2, @@ -594,7 +594,7 @@ mod test { ) in izip!( a_w_gamma, b_w_gamma, - o_w_gamma, + c_w_gamma, d_w_gamma, beta_s_sigma_1_iter, beta_s_sigma_2_iter, @@ -607,8 +607,8 @@ mod test { // (b_w + beta * s_sigma_2 + gamma) let prod_b = beta_s_sigma_2 + b_w_gamma; - // (o_w + beta * s_sigma_3 + gamma) - let prod_c = beta_s_sigma_3 + o_w_gamma; + // (c_w + beta * s_sigma_3 + gamma) + let prod_c = beta_s_sigma_3 + c_w_gamma; // (d_w + beta * s_sigma_4 + gamma) let prod_d = beta_s_sigma_4 + d_w_gamma; @@ -809,7 +809,7 @@ mod test { BlsScalar::one(), BlsScalar::one(), ]; - let o_w = vec![ + let c_w = vec![ BlsScalar::one(), BlsScalar::one(), BlsScalar::one(), @@ -828,7 +828,7 @@ mod test { &domain, a_w, b_w, - o_w, + c_w, d_w, ); } @@ -955,7 +955,7 @@ mod test { let a_w: Vec<_> = vec![BlsScalar::one(), BlsScalar::from(3)]; let b_w: Vec<_> = vec![BlsScalar::from(2), BlsScalar::from(2)]; - let o_w: Vec<_> = vec![BlsScalar::from(3), BlsScalar::one()]; + let c_w: Vec<_> = vec![BlsScalar::from(3), BlsScalar::one()]; let d_w: Vec<_> = vec![BlsScalar::one(), BlsScalar::one()]; test_correct_permutation_poly( @@ -964,7 +964,7 @@ mod test { &domain, a_w, b_w, - o_w, + c_w, d_w, ); } @@ -983,7 +983,7 @@ mod test { domain: &EvaluationDomain, a_w: Vec, b_w: Vec, - o_w: Vec, + c_w: Vec, d_w: Vec, ) { // 0. Generate beta and gamma challenges @@ -1000,7 +1000,7 @@ mod test { domain, a_w.clone().into_iter(), b_w.clone().into_iter(), - o_w.clone().into_iter(), + c_w.clone().into_iter(), d_w.clone().into_iter(), &beta, &gamma, @@ -1016,7 +1016,7 @@ mod test { domain, &a_w, &b_w, - &o_w, + &c_w, &d_w, &beta, &gamma, diff --git a/src/proof_system/linearization_poly.rs b/src/proof_system/linearization_poly.rs index 46074fe4..a1597e6e 100644 --- a/src/proof_system/linearization_poly.rs +++ b/src/proof_system/linearization_poly.rs @@ -47,7 +47,7 @@ pub(crate) struct ProofEvaluations { pub(crate) b_eval: BlsScalar, // Evaluation of the witness polynomial for the output wire at `z` #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) o_eval: BlsScalar, + pub(crate) c_eval: BlsScalar, // Evaluation of the witness polynomial for the fourth wire at `z` #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub(crate) d_eval: BlsScalar, @@ -106,7 +106,7 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { let mut writer = &mut buf[..]; writer.write(&self.a_eval.to_bytes()); writer.write(&self.b_eval.to_bytes()); - writer.write(&self.o_eval.to_bytes()); + writer.write(&self.c_eval.to_bytes()); writer.write(&self.d_eval.to_bytes()); writer.write(&self.a_next_eval.to_bytes()); writer.write(&self.b_next_eval.to_bytes()); @@ -130,7 +130,7 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { let mut buffer = &buf[..]; let a_eval = BlsScalar::from_reader(&mut buffer)?; let b_eval = BlsScalar::from_reader(&mut buffer)?; - let o_eval = BlsScalar::from_reader(&mut buffer)?; + let c_eval = BlsScalar::from_reader(&mut buffer)?; let d_eval = BlsScalar::from_reader(&mut buffer)?; let a_next_eval = BlsScalar::from_reader(&mut buffer)?; let b_next_eval = BlsScalar::from_reader(&mut buffer)?; @@ -148,7 +148,7 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { Ok(ProofEvaluations { a_eval, b_eval, - o_eval, + c_eval, d_eval, a_next_eval, b_next_eval, @@ -200,7 +200,7 @@ pub(crate) fn compute( z_poly: &Polynomial, a_eval: &BlsScalar, b_eval: &BlsScalar, - o_eval: &BlsScalar, + c_eval: &BlsScalar, d_eval: &BlsScalar, s_sigma_1_eval: &BlsScalar, s_sigma_2_eval: &BlsScalar, @@ -228,7 +228,7 @@ pub(crate) fn compute( ), a_eval, b_eval, - o_eval, + c_eval, d_eval, &a_next_eval, &b_next_eval, @@ -243,7 +243,7 @@ pub(crate) fn compute( let f_2 = prover_key.permutation.compute_linearization( z_challenge, (alpha, beta, gamma), - (&a_eval, &b_eval, &o_eval, &d_eval), + (&a_eval, &b_eval, &c_eval, &d_eval), (&s_sigma_1_eval, &s_sigma_2_eval, &s_sigma_3_eval), z_eval, z_poly, @@ -260,7 +260,7 @@ pub(crate) fn compute( proof: ProofEvaluations { a_eval: *a_eval, b_eval: *b_eval, - o_eval: *o_eval, + c_eval: *c_eval, d_eval: *d_eval, a_next_eval, b_next_eval, @@ -290,7 +290,7 @@ fn compute_circuit_satisfiability( ): (&BlsScalar, &BlsScalar, &BlsScalar, &BlsScalar), a_eval: &BlsScalar, b_eval: &BlsScalar, - o_eval: &BlsScalar, + c_eval: &BlsScalar, d_eval: &BlsScalar, a_next_eval: &BlsScalar, b_next_eval: &BlsScalar, @@ -304,7 +304,7 @@ fn compute_circuit_satisfiability( let a = prover_key.arithmetic.compute_linearization( a_eval, b_eval, - o_eval, + c_eval, d_eval, q_arith_eval, ); @@ -313,7 +313,7 @@ fn compute_circuit_satisfiability( range_separation_challenge, a_eval, b_eval, - o_eval, + c_eval, d_eval, d_next_eval, ); @@ -324,7 +324,7 @@ fn compute_circuit_satisfiability( a_next_eval, b_eval, b_next_eval, - o_eval, + c_eval, d_eval, d_next_eval, q_c_eval, @@ -336,7 +336,7 @@ fn compute_circuit_satisfiability( a_next_eval, b_eval, b_next_eval, - o_eval, + c_eval, d_eval, d_next_eval, q_l_eval, @@ -350,7 +350,7 @@ fn compute_circuit_satisfiability( a_next_eval, b_eval, b_next_eval, - o_eval, + c_eval, d_eval, d_next_eval, ); diff --git a/src/proof_system/proof.rs b/src/proof_system/proof.rs index bdbbf05d..fd15b2de 100644 --- a/src/proof_system/proof.rs +++ b/src/proof_system/proof.rs @@ -49,7 +49,7 @@ pub struct Proof { pub(crate) b_comm: Commitment, /// Commitment to the witness polynomial for the output wires. #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) o_comm: Commitment, + pub(crate) c_comm: Commitment, /// Commitment to the witness polynomial for the fourth wires. #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub(crate) d_comm: Commitment, @@ -92,7 +92,7 @@ impl CheckBytes for ArchivedProof { ) -> Result<&'a Self, Self::Error> { check_field(&(*value).a_comm, context, "a_comm")?; check_field(&(*value).b_comm, context, "b_comm")?; - check_field(&(*value).o_comm, context, "o_comm")?; + check_field(&(*value).c_comm, context, "c_comm")?; check_field(&(*value).d_comm, context, "d_comm")?; check_field(&(*value).z_comm, context, "z_comm")?; @@ -124,7 +124,7 @@ impl Serializable<{ 11 * Commitment::SIZE + ProofEvaluations::SIZE }> let mut writer = &mut buf[..]; writer.write(&self.a_comm.to_bytes()); writer.write(&self.b_comm.to_bytes()); - writer.write(&self.o_comm.to_bytes()); + writer.write(&self.c_comm.to_bytes()); writer.write(&self.d_comm.to_bytes()); writer.write(&self.z_comm.to_bytes()); writer.write(&self.t_low_comm.to_bytes()); @@ -143,7 +143,7 @@ impl Serializable<{ 11 * Commitment::SIZE + ProofEvaluations::SIZE }> let a_comm = Commitment::from_reader(&mut buffer)?; let b_comm = Commitment::from_reader(&mut buffer)?; - let o_comm = Commitment::from_reader(&mut buffer)?; + let c_comm = Commitment::from_reader(&mut buffer)?; let d_comm = Commitment::from_reader(&mut buffer)?; let z_comm = Commitment::from_reader(&mut buffer)?; let t_low_comm = Commitment::from_reader(&mut buffer)?; @@ -157,7 +157,7 @@ impl Serializable<{ 11 * Commitment::SIZE + ProofEvaluations::SIZE }> Ok(Proof { a_comm, b_comm, - o_comm, + c_comm, d_comm, z_comm, t_low_comm, @@ -214,7 +214,7 @@ pub(crate) mod alloc { // Add commitment to witness polynomials to transcript transcript.append_commitment(b"a_w", &self.a_comm); transcript.append_commitment(b"b_w", &self.b_comm); - transcript.append_commitment(b"o_w", &self.o_comm); + transcript.append_commitment(b"c_w", &self.c_comm); transcript.append_commitment(b"d_w", &self.d_comm); // Compute beta and gamma challenges @@ -248,7 +248,7 @@ pub(crate) mod alloc { // Add opening evaluations to transcript transcript.append_scalar(b"a_eval", &self.evaluations.a_eval); transcript.append_scalar(b"b_eval", &self.evaluations.b_eval); - transcript.append_scalar(b"o_eval", &self.evaluations.o_eval); + transcript.append_scalar(b"c_eval", &self.evaluations.c_eval); transcript.append_scalar(b"d_eval", &self.evaluations.d_eval); transcript.append_scalar( @@ -344,7 +344,7 @@ pub(crate) mod alloc { aggregate_proof.add_part((self.evaluations.r_poly_eval, r_comm)); aggregate_proof.add_part((self.evaluations.a_eval, self.a_comm)); aggregate_proof.add_part((self.evaluations.b_eval, self.b_comm)); - aggregate_proof.add_part((self.evaluations.o_eval, self.o_comm)); + aggregate_proof.add_part((self.evaluations.c_eval, self.c_comm)); aggregate_proof.add_part((self.evaluations.d_eval, self.d_comm)); aggregate_proof.add_part(( self.evaluations.s_sigma_1_eval, @@ -430,7 +430,7 @@ pub(crate) mod alloc { // o + beta * sigma_3 + gamma let beta_sig3 = beta * self.evaluations.s_sigma_3_eval; - let b_2 = self.evaluations.o_eval + beta_sig3 + gamma; + let b_2 = self.evaluations.c_eval + beta_sig3 + gamma; // ((d + gamma) * z_hat) * alpha_0 let b_3 = (self.evaluations.d_eval + gamma) * z_hat_eval * alpha; @@ -607,7 +607,7 @@ mod proof_tests { let proof = Proof { a_comm: Commitment::default(), b_comm: Commitment::default(), - o_comm: Commitment::default(), + c_comm: Commitment::default(), d_comm: Commitment::default(), z_comm: Commitment::default(), t_low_comm: Commitment::default(), @@ -619,7 +619,7 @@ mod proof_tests { evaluations: ProofEvaluations { a_eval: BlsScalar::random(&mut OsRng), b_eval: BlsScalar::random(&mut OsRng), - o_eval: BlsScalar::random(&mut OsRng), + c_eval: BlsScalar::random(&mut OsRng), d_eval: BlsScalar::random(&mut OsRng), a_next_eval: BlsScalar::random(&mut OsRng), b_next_eval: BlsScalar::random(&mut OsRng), diff --git a/src/proof_system/quotient_poly.rs b/src/proof_system/quotient_poly.rs index c22c6a45..e7eea787 100644 --- a/src/proof_system/quotient_poly.rs +++ b/src/proof_system/quotient_poly.rs @@ -20,7 +20,7 @@ pub(crate) fn compute( domain: &EvaluationDomain, prover_key: &ProverKey, z_poly: &Polynomial, - (a_w_poly, b_w_poly, o_w_poly, d_w_poly): ( + (a_w_poly, b_w_poly, c_w_poly, d_w_poly): ( &Polynomial, &Polynomial, &Polynomial, @@ -52,14 +52,14 @@ pub(crate) fn compute( let mut a_w_eval_8n = domain_8n.coset_fft(a_w_poly); let mut b_w_eval_8n = domain_8n.coset_fft(b_w_poly); - let o_w_eval_8n = domain_8n.coset_fft(o_w_poly); + let c_w_eval_8n = domain_8n.coset_fft(c_w_poly); let mut d_w_eval_8n = domain_8n.coset_fft(d_w_poly); for i in 0..8 { z_eval_8n.push(z_eval_8n[i]); a_w_eval_8n.push(a_w_eval_8n[i]); b_w_eval_8n.push(b_w_eval_8n[i]); - // o_w_eval_8n push not required + // c_w_eval_8n push not required d_w_eval_8n.push(d_w_eval_8n[i]); } @@ -72,14 +72,14 @@ pub(crate) fn compute( var_base_challenge, ), prover_key, - (&a_w_eval_8n, &b_w_eval_8n, &o_w_eval_8n, &d_w_eval_8n), + (&a_w_eval_8n, &b_w_eval_8n, &c_w_eval_8n, &d_w_eval_8n), public_inputs_poly, ); let t_2 = compute_permutation_checks( domain, prover_key, - (&a_w_eval_8n, &b_w_eval_8n, &o_w_eval_8n, &d_w_eval_8n), + (&a_w_eval_8n, &b_w_eval_8n, &c_w_eval_8n, &d_w_eval_8n), &z_eval_8n, (alpha, beta, gamma), ); @@ -114,7 +114,7 @@ fn compute_circuit_satisfiability_equation( var_base_challenge, ): (&BlsScalar, &BlsScalar, &BlsScalar, &BlsScalar), prover_key: &ProverKey, - (a_w_eval_8n, b_w_eval_8n, o_w_eval_8n, d_w_eval_8n): ( + (a_w_eval_8n, b_w_eval_8n, c_w_eval_8n, d_w_eval_8n): ( &[BlsScalar], &[BlsScalar], &[BlsScalar], @@ -135,7 +135,7 @@ fn compute_circuit_satisfiability_equation( .map(|i| { let a_w = &a_w_eval_8n[i]; let b_w = &b_w_eval_8n[i]; - let o_w = &o_w_eval_8n[i]; + let c_w = &c_w_eval_8n[i]; let d_w = &d_w_eval_8n[i]; let a_w_next = &a_w_eval_8n[i + 8]; let b_w_next = &b_w_eval_8n[i + 8]; @@ -144,14 +144,14 @@ fn compute_circuit_satisfiability_equation( let a = prover_key .arithmetic - .compute_quotient_i(i, a_w, b_w, o_w, d_w); + .compute_quotient_i(i, a_w, b_w, c_w, d_w); let b = prover_key.range.compute_quotient_i( i, range_challenge, a_w, b_w, - o_w, + c_w, d_w, d_w_next, ); @@ -163,7 +163,7 @@ fn compute_circuit_satisfiability_equation( a_w_next, b_w, b_w_next, - o_w, + c_w, d_w, d_w_next, ); @@ -175,7 +175,7 @@ fn compute_circuit_satisfiability_equation( a_w_next, b_w, b_w_next, - o_w, + c_w, d_w, d_w_next, ); @@ -187,7 +187,7 @@ fn compute_circuit_satisfiability_equation( a_w_next, b_w, b_w_next, - o_w, + c_w, d_w, d_w_next, ); @@ -201,7 +201,7 @@ fn compute_circuit_satisfiability_equation( fn compute_permutation_checks( domain: &EvaluationDomain, prover_key: &ProverKey, - (a_w_eval_8n, b_w_eval_8n, o_w_eval_8n, d_w_eval_8n): ( + (a_w_eval_8n, b_w_eval_8n, c_w_eval_8n, d_w_eval_8n): ( &[BlsScalar], &[BlsScalar], &[BlsScalar], @@ -227,7 +227,7 @@ fn compute_permutation_checks( i, &a_w_eval_8n[i], &b_w_eval_8n[i], - &o_w_eval_8n[i], + &c_w_eval_8n[i], &d_w_eval_8n[i], &z_eval_8n[i], &z_eval_8n[i + 8], diff --git a/src/proof_system/widget/arithmetic/proverkey.rs b/src/proof_system/widget/arithmetic/proverkey.rs index 3bb5d943..da573311 100644 --- a/src/proof_system/widget/arithmetic/proverkey.rs +++ b/src/proof_system/widget/arithmetic/proverkey.rs @@ -45,7 +45,7 @@ impl ProverKey { index: usize, a_w_i: &BlsScalar, b_w_i: &BlsScalar, - o_w_i: &BlsScalar, + c_w_i: &BlsScalar, d_w_i: &BlsScalar, ) -> BlsScalar { let q_m_i = &self.q_m.1[index]; @@ -56,13 +56,13 @@ impl ProverKey { let q_c_i = &self.q_c.1[index]; let q_arith_i = &self.q_arith.1[index]; - // (a(x)b(x)q_M(x) + a(x)q_L(x) + b(X)q_R(x) + o(X)q_O(X) + d(x)q_4(X) + + // (a(x)b(x)q_M(x) + a(x)q_L(x) + b(X)q_R(x) + c(X)q_O(X) + d(x)q_4(X) + // Q_C(X)) * Q_Arith(X) // let a_1 = a_w_i * b_w_i * q_m_i; let a_2 = a_w_i * q_l_i; let a_3 = b_w_i * q_r_i; - let a_4 = o_w_i * q_o_i; + let a_4 = c_w_i * q_o_i; let a_5 = d_w_i * q_4_i; let a_6 = q_c_i; (a_1 + a_2 + a_3 + a_4 + a_5 + a_6) * q_arith_i @@ -72,7 +72,7 @@ impl ProverKey { &self, a_eval: &BlsScalar, b_eval: &BlsScalar, - o_eval: &BlsScalar, + c_eval: &BlsScalar, d_eval: &BlsScalar, q_arith_eval: &BlsScalar, ) -> Polynomial { @@ -83,7 +83,7 @@ impl ProverKey { let q_4_poly = &self.q_4.0; let q_c_poly = &self.q_c.0; - // (a_eval * b_eval * q_m_poly + a_eval * q_l + b_eval * q_r + o_eval + // (a_eval * b_eval * q_m_poly + a_eval * q_l + b_eval * q_r + c_eval // * q_o + d_eval * q_4 + q_c) * q_arith_eval // // a_eval * b_eval * q_m_poly @@ -96,8 +96,8 @@ impl ProverKey { // b_eval * q_r let a_2 = q_r_poly * b_eval; - //o_eval * q_o - let a_3 = q_o_poly * o_eval; + //c_eval * q_o + let a_3 = q_o_poly * c_eval; // d_eval * q_4 let a_4 = q_4_poly * d_eval; diff --git a/src/proof_system/widget/arithmetic/verifierkey.rs b/src/proof_system/widget/arithmetic/verifierkey.rs index d8d28c6a..b67c3457 100644 --- a/src/proof_system/widget/arithmetic/verifierkey.rs +++ b/src/proof_system/widget/arithmetic/verifierkey.rs @@ -107,7 +107,7 @@ mod alloc { scalars.push(evaluations.b_eval * q_arith_eval); points.push(self.q_r.0); - scalars.push(evaluations.o_eval * q_arith_eval); + scalars.push(evaluations.c_eval * q_arith_eval); points.push(self.q_o.0); scalars.push(evaluations.d_eval * q_arith_eval); diff --git a/src/proof_system/widget/ecc/curve_addition/proverkey.rs b/src/proof_system/widget/ecc/curve_addition/proverkey.rs index a8c40d58..e1ded404 100644 --- a/src/proof_system/widget/ecc/curve_addition/proverkey.rs +++ b/src/proof_system/widget/ecc/curve_addition/proverkey.rs @@ -37,7 +37,7 @@ impl ProverKey { a_w_i_next: &BlsScalar, // x_3 b_w_i: &BlsScalar, // y_1 b_w_i_next: &BlsScalar, // y_3 - o_w_i: &BlsScalar, // x_2 + c_w_i: &BlsScalar, // x_2 d_w_i: &BlsScalar, // y_2 d_w_i_next: &BlsScalar, // x_1 * y_2 ) -> BlsScalar { @@ -49,7 +49,7 @@ impl ProverKey { let x_3 = a_w_i_next; let y_1 = b_w_i; let y_3 = b_w_i_next; - let x_2 = o_w_i; + let x_2 = c_w_i; let y_2 = d_w_i; let x1_y2 = d_w_i_next; @@ -84,7 +84,7 @@ impl ProverKey { a_next_eval: &BlsScalar, b_eval: &BlsScalar, b_next_eval: &BlsScalar, - o_eval: &BlsScalar, + c_eval: &BlsScalar, d_eval: &BlsScalar, d_next_eval: &BlsScalar, ) -> Polynomial { @@ -96,7 +96,7 @@ impl ProverKey { let x_3 = a_next_eval; let y_1 = b_eval; let y_3 = b_next_eval; - let x_2 = o_eval; + let x_2 = c_eval; let y_2 = d_eval; let x1_y2 = d_next_eval; diff --git a/src/proof_system/widget/ecc/curve_addition/verifierkey.rs b/src/proof_system/widget/ecc/curve_addition/verifierkey.rs index 52187883..b9ba063d 100644 --- a/src/proof_system/widget/ecc/curve_addition/verifierkey.rs +++ b/src/proof_system/widget/ecc/curve_addition/verifierkey.rs @@ -49,7 +49,7 @@ mod alloc { let x_3 = evaluations.a_next_eval; let y_1 = evaluations.b_eval; let y_3 = evaluations.b_next_eval; - let x_2 = evaluations.o_eval; + let x_2 = evaluations.c_eval; let y_2 = evaluations.d_eval; let x1_y2 = evaluations.d_next_eval; diff --git a/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs b/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs index fbf4c8ad..30f0d734 100644 --- a/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs +++ b/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs @@ -43,7 +43,7 @@ impl ProverKey { a_w_i_next: &BlsScalar, // // next_x b_w_i: &BlsScalar, // acc_y or curr_y b_w_i_next: &BlsScalar, // next_y - o_w_i: &BlsScalar, // xy_alpha + c_w_i: &BlsScalar, // xy_alpha d_w_i: &BlsScalar, // accumulated_bit d_w_i_next: &BlsScalar, // accumulated_bit_next ) -> BlsScalar { @@ -62,7 +62,7 @@ impl ProverKey { let acc_y = b_w_i; let acc_y_next = b_w_i_next; - let xy_alpha = o_w_i; + let xy_alpha = c_w_i; let accumulated_bit = d_w_i; let accumulated_bit_next = d_w_i_next; @@ -108,7 +108,7 @@ impl ProverKey { a_next_eval: &BlsScalar, b_eval: &BlsScalar, b_next_eval: &BlsScalar, - o_eval: &BlsScalar, + c_eval: &BlsScalar, d_eval: &BlsScalar, d_next_eval: &BlsScalar, q_l_eval: &BlsScalar, @@ -129,7 +129,7 @@ impl ProverKey { let acc_y = b_eval; let acc_y_next = b_next_eval; - let xy_alpha = o_eval; + let xy_alpha = c_eval; let accumulated_bit = d_eval; let accumulated_bit_next = d_next_eval; diff --git a/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs b/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs index 05c7fdfe..8b0adbea 100644 --- a/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs +++ b/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs @@ -62,7 +62,7 @@ mod alloc { let acc_y = evaluations.b_eval; let acc_y_next = evaluations.b_next_eval; - let xy_alpha = evaluations.o_eval; + let xy_alpha = evaluations.c_eval; let accumulated_bit = evaluations.d_eval; let accumulated_bit_next = evaluations.d_next_eval; diff --git a/src/proof_system/widget/logic/proverkey.rs b/src/proof_system/widget/logic/proverkey.rs index be2b070a..4a77070c 100644 --- a/src/proof_system/widget/logic/proverkey.rs +++ b/src/proof_system/widget/logic/proverkey.rs @@ -39,7 +39,7 @@ impl ProverKey { a_w_i_next: &BlsScalar, b_w_i: &BlsScalar, b_w_i_next: &BlsScalar, - o_w_i: &BlsScalar, + c_w_i: &BlsScalar, d_w_i: &BlsScalar, d_w_i_next: &BlsScalar, ) -> BlsScalar { @@ -62,7 +62,7 @@ impl ProverKey { let d = d_w_i_next - four * d_w_i; let o_2 = delta(d) * kappa_sq; - let w = o_w_i; + let w = c_w_i; let o_3 = (w - a * b) * kappa_cu; let o_4 = delta_xor_and(&a, &b, w, &d, q_c_i) * kappa_qu; @@ -77,7 +77,7 @@ impl ProverKey { a_next_eval: &BlsScalar, b_eval: &BlsScalar, b_next_eval: &BlsScalar, - o_eval: &BlsScalar, + c_eval: &BlsScalar, d_eval: &BlsScalar, d_next_eval: &BlsScalar, q_c_eval: &BlsScalar, @@ -99,7 +99,7 @@ impl ProverKey { let d = d_next_eval - four * d_eval; let o_2 = delta(d) * kappa_sq; - let w = o_eval; + let w = c_eval; let o_3 = (w - a * b) * kappa_cu; let o_4 = delta_xor_and(&a, &b, w, &d, q_c_eval) * kappa_qu; diff --git a/src/proof_system/widget/logic/verifierkey.rs b/src/proof_system/widget/logic/verifierkey.rs index 77604d52..22773ad4 100644 --- a/src/proof_system/widget/logic/verifierkey.rs +++ b/src/proof_system/widget/logic/verifierkey.rs @@ -61,7 +61,7 @@ mod alloc { let d = evaluations.d_next_eval - four * evaluations.d_eval; let o_2 = delta(d) * kappa_sq; - let o = evaluations.o_eval; + let o = evaluations.c_eval; let o_3 = (o - a * b) * kappa_cu; let o_4 = diff --git a/src/proof_system/widget/permutation/proverkey.rs b/src/proof_system/widget/permutation/proverkey.rs index 8f1d0d3c..47ed6841 100644 --- a/src/proof_system/widget/permutation/proverkey.rs +++ b/src/proof_system/widget/permutation/proverkey.rs @@ -48,7 +48,7 @@ impl ProverKey { index: usize, a_w_i: &BlsScalar, b_w_i: &BlsScalar, - o_w_i: &BlsScalar, + c_w_i: &BlsScalar, d_w_i: &BlsScalar, z_i: &BlsScalar, z_i_next: &BlsScalar, @@ -58,10 +58,10 @@ impl ProverKey { gamma: &BlsScalar, ) -> BlsScalar { let a = self.compute_quotient_identity_range_check_i( - index, a_w_i, b_w_i, o_w_i, d_w_i, z_i, alpha, beta, gamma, + index, a_w_i, b_w_i, c_w_i, d_w_i, z_i, alpha, beta, gamma, ); let b = self.compute_quotient_copy_range_check_i( - index, a_w_i, b_w_i, o_w_i, d_w_i, z_i_next, alpha, beta, gamma, + index, a_w_i, b_w_i, c_w_i, d_w_i, z_i_next, alpha, beta, gamma, ); let c = self.compute_quotient_term_check_one_i(z_i, l1_alpha_sq); a + b + c @@ -73,7 +73,7 @@ impl ProverKey { index: usize, a_w_i: &BlsScalar, b_w_i: &BlsScalar, - o_w_i: &BlsScalar, + c_w_i: &BlsScalar, d_w_i: &BlsScalar, z_i: &BlsScalar, alpha: &BlsScalar, @@ -84,7 +84,7 @@ impl ProverKey { (a_w_i + (beta * x) + gamma) * (b_w_i + (beta * K1 * x) + gamma) - * (o_w_i + (beta * K2 * x) + gamma) + * (c_w_i + (beta * K2 * x) + gamma) * (d_w_i + (beta * K3 * x) + gamma) * z_i * alpha @@ -97,7 +97,7 @@ impl ProverKey { index: usize, a_w_i: &BlsScalar, b_w_i: &BlsScalar, - o_w_i: &BlsScalar, + c_w_i: &BlsScalar, d_w_i: &BlsScalar, z_i_next: &BlsScalar, alpha: &BlsScalar, @@ -111,7 +111,7 @@ impl ProverKey { let product = (a_w_i + (beta * s_sigma_1_eval) + gamma) * (b_w_i + (beta * s_sigma_2_eval) + gamma) - * (o_w_i + (beta * s_sigma_3_eval) + gamma) + * (c_w_i + (beta * s_sigma_3_eval) + gamma) * (d_w_i + (beta * s_sigma_4_eval) + gamma) * z_i_next * alpha; @@ -131,7 +131,7 @@ impl ProverKey { &self, z_challenge: &BlsScalar, (alpha, beta, gamma): (&BlsScalar, &BlsScalar, &BlsScalar), - (a_eval, b_eval, o_eval, d_eval): ( + (a_eval, b_eval, c_eval, d_eval): ( &BlsScalar, &BlsScalar, &BlsScalar, @@ -146,13 +146,13 @@ impl ProverKey { z_poly: &Polynomial, ) -> Polynomial { let a = self.compute_linearizer_identity_range_check( - (a_eval, b_eval, o_eval, d_eval), + (a_eval, b_eval, c_eval, d_eval), z_challenge, (alpha, beta, gamma), z_poly, ); let b = self.compute_linearizer_copy_range_check( - (a_eval, b_eval, o_eval), + (a_eval, b_eval, c_eval), z_eval, sigma_1_eval, sigma_2_eval, @@ -172,10 +172,10 @@ impl ProverKey { &(&a + &b) + &c } // (a_eval + beta * z_challenge + gamma)(b_eval + beta * K1 * z_challenge + - // gamma)(o_eval + beta * K2 * z_challenge + gamma) * alpha z(X) + // gamma)(c_eval + beta * K2 * z_challenge + gamma) * alpha z(X) fn compute_linearizer_identity_range_check( &self, - (a_eval, b_eval, o_eval, d_eval): ( + (a_eval, b_eval, c_eval, d_eval): ( &BlsScalar, &BlsScalar, &BlsScalar, @@ -196,9 +196,9 @@ impl ProverKey { let mut a_1 = b_eval + beta_z_k1; a_1 += gamma; - // o_eval + beta * K2 * z_challenge + gamma + // c_eval + beta * K2 * z_challenge + gamma let beta_z_k2 = K2 * beta_z; - let mut a_2 = o_eval + beta_z_k2; + let mut a_2 = c_eval + beta_z_k2; a_2 += gamma; // d_eval + beta * K3 * z_challenge + gamma @@ -210,17 +210,17 @@ impl ProverKey { a *= a_2; a *= a_3; a *= alpha; // (a_eval + beta * z_challenge + gamma)(b_eval + beta * K1 * - // z_challenge + gamma)(o_eval + beta * K2 * z_challenge + gamma)(d_eval + // z_challenge + gamma)(c_eval + beta * K2 * z_challenge + gamma)(d_eval // + beta * K3 * z_challenge + gamma) * alpha z_poly * &a // (a_eval + beta * z_challenge + gamma)(b_eval + beta * K1 - // * z_challenge + gamma)(o_eval + beta * K2 * z_challenge + + // * z_challenge + gamma)(c_eval + beta * K2 * z_challenge + // gamma) * alpha z(X) } // -(a_eval + beta * sigma_1 + gamma)(b_eval + beta * sigma_2 + gamma) - // (o_eval + beta * sigma_3 + gamma) * beta *z_eval * alpha^2 * Sigma_4(X) + // (c_eval + beta * sigma_3 + gamma) * beta *z_eval * alpha^2 * Sigma_4(X) fn compute_linearizer_copy_range_check( &self, - (a_eval, b_eval, o_eval): (&BlsScalar, &BlsScalar, &BlsScalar), + (a_eval, b_eval, c_eval): (&BlsScalar, &BlsScalar, &BlsScalar), z_eval: &BlsScalar, sigma_1_eval: &BlsScalar, sigma_2_eval: &BlsScalar, @@ -238,9 +238,9 @@ impl ProverKey { let mut a_1 = b_eval + beta_sigma_2; a_1 += gamma; - // o_eval + beta * sigma_3 + gamma + // c_eval + beta * sigma_3 + gamma let beta_sigma_3 = beta * sigma_3_eval; - let mut a_2 = o_eval + beta_sigma_3; + let mut a_2 = c_eval + beta_sigma_3; a_2 += gamma; let beta_z_eval = beta * z_eval; @@ -248,10 +248,10 @@ impl ProverKey { let mut a = a_0 * a_1 * a_2; a *= beta_z_eval; a *= alpha; // (a_eval + beta * sigma_1 + gamma)(b_eval + beta * sigma_2 + - // gamma)(o_eval + beta * sigma_3 + gamma) * beta * z_eval * alpha + // gamma)(c_eval + beta * sigma_3 + gamma) * beta * z_eval * alpha s_sigma_4_poly * &-a // -(a_eval + beta * sigma_1 + gamma)(b_eval + - // beta * sigma_2 + gamma) (o_eval + beta * + // beta * sigma_2 + gamma) (c_eval + beta * // sigma_3 + gamma) * beta * z_eval * alpha^2 * // Sigma_4(X) } diff --git a/src/proof_system/widget/permutation/verifierkey.rs b/src/proof_system/widget/permutation/verifierkey.rs index b1f2c5bf..e143069f 100644 --- a/src/proof_system/widget/permutation/verifierkey.rs +++ b/src/proof_system/widget/permutation/verifierkey.rs @@ -56,7 +56,7 @@ mod alloc { // (a_eval + beta * z + gamma) // * (b_eval + beta * z * k1 + gamma) - // * (o_eval + beta * k2 * z + gamma) + // * (c_eval + beta * k2 * z + gamma) // * (d_eval + beta * k3 * z + gamma) * alpha let x = { let beta_z = beta * z_challenge; @@ -66,7 +66,7 @@ mod alloc { let q_1 = evaluations.b_eval + beta_k1_z + gamma; let beta_k2_z = beta * K2 * z_challenge; - let q_2 = evaluations.o_eval + beta_k2_z + gamma; + let q_2 = evaluations.c_eval + beta_k2_z + gamma; let beta_k3_z = beta * K3 * z_challenge; let q_3 = (evaluations.d_eval + beta_k3_z + gamma) * alpha; @@ -82,7 +82,7 @@ mod alloc { // -1 * (a_eval + beta * sigma_1_eval + gamma) // * (b_eval + beta * sigma_2_eval + gamma) - // * (o_eval + beta * sigma_3_eval + gamma) + // * (c_eval + beta * sigma_3_eval + gamma) // * alpha^2 let y = { let beta_sigma_1 = beta * evaluations.s_sigma_1_eval; @@ -92,7 +92,7 @@ mod alloc { let q_1 = evaluations.b_eval + beta_sigma_2 + gamma; let beta_sigma_3 = beta * evaluations.s_sigma_3_eval; - let q_2 = evaluations.o_eval + beta_sigma_3 + gamma; + let q_2 = evaluations.c_eval + beta_sigma_3 + gamma; let q_3 = beta * evaluations.z_eval * alpha; diff --git a/src/proof_system/widget/range/proverkey.rs b/src/proof_system/widget/range/proverkey.rs index 1c54ae40..d3f6f8fd 100644 --- a/src/proof_system/widget/range/proverkey.rs +++ b/src/proof_system/widget/range/proverkey.rs @@ -34,7 +34,7 @@ impl ProverKey { range_separation_challenge: &BlsScalar, a_w_i: &BlsScalar, b_w_i: &BlsScalar, - o_w_i: &BlsScalar, + c_w_i: &BlsScalar, d_w_i: &BlsScalar, d_w_i_next: &BlsScalar, ) -> BlsScalar { @@ -48,8 +48,8 @@ impl ProverKey { // Delta([o(X) - 4 * d(X)]) + Delta([b(X) - 4 * o(X)]) + Delta([a(X) - 4 // * b(X)]) + Delta([d(Xg) - 4 * a(X)]) * Q_Range(X) // - let b_1 = delta(o_w_i - four * d_w_i); - let b_2 = delta(b_w_i - four * o_w_i) * kappa; + let b_1 = delta(c_w_i - four * d_w_i); + let b_2 = delta(b_w_i - four * c_w_i) * kappa; let b_3 = delta(a_w_i - four * b_w_i) * kappa_sq; let b_4 = delta(d_w_i_next - four * a_w_i) * kappa_cu; (b_1 + b_2 + b_3 + b_4) * q_range_i * range_separation_challenge @@ -60,7 +60,7 @@ impl ProverKey { range_separation_challenge: &BlsScalar, a_eval: &BlsScalar, b_eval: &BlsScalar, - o_eval: &BlsScalar, + c_eval: &BlsScalar, d_eval: &BlsScalar, d_next_eval: &BlsScalar, ) -> Polynomial { @@ -71,11 +71,11 @@ impl ProverKey { let kappa_sq = kappa.square(); let kappa_cu = kappa_sq * kappa; - // Delta([o_eval - 4 * d_eval]) + Delta([b_eval - 4 * o_eval]) + + // Delta([c_eval - 4 * d_eval]) + Delta([b_eval - 4 * c_eval]) + // Delta([a_eval - 4 * b_eval]) + Delta([d_next_eval - 4 * a_eval]) * // Q_Range(X) - let b_1 = delta(o_eval - four * d_eval); - let b_2 = delta(b_eval - four * o_eval) * kappa; + let b_1 = delta(c_eval - four * d_eval); + let b_2 = delta(b_eval - four * c_eval) * kappa; let b_3 = delta(a_eval - four * b_eval) * kappa_sq; let b_4 = delta(d_next_eval - four * a_eval) * kappa_cu; diff --git a/src/proof_system/widget/range/verifierkey.rs b/src/proof_system/widget/range/verifierkey.rs index 6398688a..43af8041 100644 --- a/src/proof_system/widget/range/verifierkey.rs +++ b/src/proof_system/widget/range/verifierkey.rs @@ -49,9 +49,9 @@ mod alloc { let kappa_sq = kappa.square(); let kappa_cu = kappa_sq * kappa; - let b_1 = delta(evaluations.o_eval - (four * evaluations.d_eval)); + let b_1 = delta(evaluations.c_eval - (four * evaluations.d_eval)); let b_2 = - delta(evaluations.b_eval - four * evaluations.o_eval) * kappa; + delta(evaluations.b_eval - four * evaluations.c_eval) * kappa; let b_3 = delta(evaluations.a_eval - four * evaluations.b_eval) * kappa_sq; let b_4 = From 31fb6779bc622de0d9c842f2c00cc8c8ce2d0df4 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Thu, 4 Jul 2024 16:38:32 +0200 Subject: [PATCH 06/11] Update linearization polynomial computation --- src/compiler/prover.rs | 95 ++++---- src/proof_system/linearization_poly.rs | 208 ++++++------------ src/proof_system/proof.rs | 160 +++++--------- .../widget/arithmetic/proverkey.rs | 19 +- .../widget/ecc/curve_addition/proverkey.rs | 23 +- .../ecc/scalar_mul/fixed_base/proverkey.rs | 34 ++- src/proof_system/widget/logic/proverkey.rs | 21 +- src/proof_system/widget/range/proverkey.rs | 17 +- 8 files changed, 215 insertions(+), 362 deletions(-) diff --git a/src/compiler/prover.rs b/src/compiler/prover.rs index 1e5ffe35..b3d29eff 100644 --- a/src/compiler/prover.rs +++ b/src/compiler/prover.rs @@ -14,11 +14,11 @@ use merlin::Transcript; use rand_core::{CryptoRng, RngCore}; use crate::commitment_scheme::CommitKey; +use crate::compiler::prover::linearization_poly::ProofEvaluations; use crate::error::Error; use crate::fft::{EvaluationDomain, Polynomial}; -use crate::proof_system::proof::Proof; use crate::proof_system::{ - linearization_poly, quotient_poly, ProverKey, VerifierKey, + linearization_poly, proof::Proof, quotient_poly, ProverKey, VerifierKey, }; use crate::transcript::TranscriptProtocol; @@ -433,13 +433,50 @@ impl Prover { transcript.append_scalar(b"z_eval", &z_eval); + // Compute extra evaluations + let a_next_eval = a_w_poly.evaluate(&(z_challenge * domain.group_gen)); + let b_next_eval = b_w_poly.evaluate(&(z_challenge * domain.group_gen)); + let d_next_eval = d_w_poly.evaluate(&(z_challenge * domain.group_gen)); + + let q_arith_eval = + self.prover_key.arithmetic.q_arith.0.evaluate(&z_challenge); + let q_c_eval = self.prover_key.logic.q_c.0.evaluate(&z_challenge); + let q_l_eval = self.prover_key.fixed_base.q_l.0.evaluate(&z_challenge); + let q_r_eval = self.prover_key.fixed_base.q_r.0.evaluate(&z_challenge); + + // add extra evaluations to transcript. + transcript.append_scalar(b"a_next_eval", &a_next_eval); + transcript.append_scalar(b"b_next_eval", &b_next_eval); + transcript.append_scalar(b"d_next_eval", &d_next_eval); + transcript.append_scalar(b"q_arith_eval", &q_arith_eval); + transcript.append_scalar(b"q_c_eval", &q_c_eval); + transcript.append_scalar(b"q_l_eval", &q_l_eval); + transcript.append_scalar(b"q_r_eval", &q_r_eval); + + let evaluations = ProofEvaluations { + a_eval, + b_eval, + c_eval, + d_eval, + a_next_eval, + b_next_eval, + d_next_eval, + q_arith_eval, + q_c_eval, + q_l_eval, + q_r_eval, + s_sigma_1_eval, + s_sigma_2_eval, + s_sigma_3_eval, + z_eval, + }; + // round 5 // compute the challenge 'v' let v_challenge = transcript.challenge_scalar(b"v_challenge"); // compute linearization polynomial - let (r_poly, evaluations) = linearization_poly::compute( - &domain, + let r_poly = linearization_poly::compute( &self.prover_key, &( alpha, @@ -451,53 +488,19 @@ impl Prover { var_base_sep_challenge, z_challenge, ), - &a_w_poly, - &b_w_poly, - &d_w_poly, - &t_poly, &z_poly, - &a_eval, - &b_eval, - &c_eval, - &d_eval, - &s_sigma_1_eval, - &s_sigma_2_eval, - &s_sigma_3_eval, - &z_eval, + &evaluations, + &domain, + &t_low_poly, + &t_mid_poly, + &t_high_poly, + &t_4_poly, + &public_inputs, ); - // add evaluations to transcript. - transcript - .append_scalar(b"a_next_eval", &evaluations.proof.a_next_eval); - transcript - .append_scalar(b"b_next_eval", &evaluations.proof.b_next_eval); - transcript - .append_scalar(b"d_next_eval", &evaluations.proof.d_next_eval); - transcript - .append_scalar(b"q_arith_eval", &evaluations.proof.q_arith_eval); - transcript.append_scalar(b"q_c_eval", &evaluations.proof.q_c_eval); - transcript.append_scalar(b"q_l_eval", &evaluations.proof.q_l_eval); - transcript.append_scalar(b"q_r_eval", &evaluations.proof.q_r_eval); - transcript.append_scalar(b"t_eval", &evaluations.t_eval); - transcript.append_scalar(b"r_eval", &evaluations.proof.r_poly_eval); - - // compute Openings using KZG10 - let z_n = z_challenge.pow(&[domain_size as u64, 0, 0, 0]); - let z_two_n = z_challenge.pow(&[2 * domain_size as u64, 0, 0, 0]); - let z_three_n = z_challenge.pow(&[3 * domain_size as u64, 0, 0, 0]); - - let a = &t_low_poly; - let b = &t_mid_poly * &z_n; - let c = &t_high_poly * &z_two_n; - let d = &t_4_poly * &z_three_n; - let abc = &(a + &b) + &c; - - let quot = &abc + &d; - // compute the opening proof polynomial 'W_z(X)' let aggregate_witness = CommitKey::compute_aggregate_witness( &[ - quot, r_poly, a_w_poly.clone(), b_w_poly.clone(), @@ -541,7 +544,7 @@ impl Prover { w_z_chall_comm, w_z_chall_w_comm, - evaluations: evaluations.proof, + evaluations, }; Ok((proof, public_inputs)) diff --git a/src/proof_system/linearization_poly.rs b/src/proof_system/linearization_poly.rs index a1597e6e..72d0da26 100644 --- a/src/proof_system/linearization_poly.rs +++ b/src/proof_system/linearization_poly.rs @@ -7,7 +7,7 @@ #[cfg(feature = "alloc")] use crate::{ fft::{EvaluationDomain, Polynomial}, - proof_system::ProverKey, + proof_system::{proof, ProverKey}, }; use dusk_bls12_381::BlsScalar; @@ -21,14 +21,6 @@ use rkyv::{ Archive, Deserialize, Serialize, }; -/// Evaluations at points `z` or and `z * root of unity` -#[allow(dead_code)] -pub(crate) struct Evaluations { - pub(crate) proof: ProofEvaluations, - // Evaluation of the linearization sigma polynomial at `z` - pub(crate) t_eval: BlsScalar, -} - /// Subset of all of the evaluations. These evaluations /// are added to the [`Proof`](super::Proof). #[derive(Debug, Eq, PartialEq, Clone, Default)] @@ -84,18 +76,14 @@ pub(crate) struct ProofEvaluations { #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub(crate) s_sigma_3_eval: BlsScalar, - // Evaluation of the linearization sigma polynomial at `z` - #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) r_poly_eval: BlsScalar, - // (Shifted) Evaluation of the permutation polynomial at `z * root of // unity` #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub(crate) z_eval: BlsScalar, } -// The struct ProofEvaluations has 16 BlsScalars -impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { +// The struct ProofEvaluations has 15 BlsScalars +impl Serializable<{ 15 * BlsScalar::SIZE }> for ProofEvaluations { type Error = dusk_bytes::Error; #[allow(unused_must_use)] @@ -118,7 +106,6 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { writer.write(&self.s_sigma_1_eval.to_bytes()); writer.write(&self.s_sigma_2_eval.to_bytes()); writer.write(&self.s_sigma_3_eval.to_bytes()); - writer.write(&self.r_poly_eval.to_bytes()); writer.write(&self.z_eval.to_bytes()); buf @@ -142,7 +129,6 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { let s_sigma_1_eval = BlsScalar::from_reader(&mut buffer)?; let s_sigma_2_eval = BlsScalar::from_reader(&mut buffer)?; let s_sigma_3_eval = BlsScalar::from_reader(&mut buffer)?; - let r_poly_eval = BlsScalar::from_reader(&mut buffer)?; let z_eval = BlsScalar::from_reader(&mut buffer)?; Ok(ProofEvaluations { @@ -160,7 +146,6 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { s_sigma_1_eval, s_sigma_2_eval, s_sigma_3_eval, - r_poly_eval, z_eval, }) } @@ -172,7 +157,6 @@ impl Serializable<{ 16 * BlsScalar::SIZE }> for ProofEvaluations { // TODO: Improve the method signature #[allow(clippy::type_complexity)] pub(crate) fn compute( - domain: &EvaluationDomain, prover_key: &ProverKey, ( alpha, @@ -193,32 +177,15 @@ pub(crate) fn compute( BlsScalar, BlsScalar, ), - a_w_poly: &Polynomial, - b_w_poly: &Polynomial, - d_w_poly: &Polynomial, - t_x_poly: &Polynomial, z_poly: &Polynomial, - a_eval: &BlsScalar, - b_eval: &BlsScalar, - c_eval: &BlsScalar, - d_eval: &BlsScalar, - s_sigma_1_eval: &BlsScalar, - s_sigma_2_eval: &BlsScalar, - s_sigma_3_eval: &BlsScalar, - z_eval: &BlsScalar, -) -> (Polynomial, Evaluations) { - // Compute evaluations - let t_eval = t_x_poly.evaluate(z_challenge); - - let q_arith_eval = prover_key.arithmetic.q_arith.0.evaluate(z_challenge); - let q_c_eval = prover_key.logic.q_c.0.evaluate(z_challenge); - let q_l_eval = prover_key.fixed_base.q_l.0.evaluate(z_challenge); - let q_r_eval = prover_key.fixed_base.q_r.0.evaluate(z_challenge); - - let a_next_eval = a_w_poly.evaluate(&(z_challenge * domain.group_gen)); - let b_next_eval = b_w_poly.evaluate(&(z_challenge * domain.group_gen)); - let d_next_eval = d_w_poly.evaluate(&(z_challenge * domain.group_gen)); - + evaluations: &ProofEvaluations, + domain: &EvaluationDomain, + t_low_poly: &Polynomial, + t_mid_poly: &Polynomial, + t_high_poly: &Polynomial, + t_4_poly: &Polynomial, + pub_inputs: &[BlsScalar], +) -> Polynomial { let f_1 = compute_circuit_satisfiability( ( range_separation_challenge, @@ -226,58 +193,55 @@ pub(crate) fn compute( fixed_base_separation_challenge, var_base_separation_challenge, ), - a_eval, - b_eval, - c_eval, - d_eval, - &a_next_eval, - &b_next_eval, - &d_next_eval, - &q_arith_eval, - &q_c_eval, - &q_l_eval, - &q_r_eval, + evaluations, prover_key, ); + let pi_eval = + proof::alloc::compute_barycentric_eval(pub_inputs, z_challenge, domain); + + let f_1 = &f_1 + &pi_eval; + let f_2 = prover_key.permutation.compute_linearization( z_challenge, (alpha, beta, gamma), - (&a_eval, &b_eval, &c_eval, &d_eval), - (&s_sigma_1_eval, &s_sigma_2_eval, &s_sigma_3_eval), - z_eval, + ( + &evaluations.a_eval, + &evaluations.b_eval, + &evaluations.c_eval, + &evaluations.d_eval, + ), + ( + &evaluations.s_sigma_1_eval, + &evaluations.s_sigma_2_eval, + &evaluations.s_sigma_3_eval, + ), + &evaluations.z_eval, z_poly, ); - let r_poly = &f_1 + &f_2; + let domain_size = domain.size(); - // Evaluate linearization polynomial at challenge `z` - let r_poly_eval = r_poly.evaluate(z_challenge); + let z_n = z_challenge.pow(&[domain_size as u64, 0, 0, 0]); + let z_two_n = z_challenge.pow(&[2 * domain_size as u64, 0, 0, 0]); + let z_three_n = z_challenge.pow(&[3 * domain_size as u64, 0, 0, 0]); - ( - r_poly, - Evaluations { - proof: ProofEvaluations { - a_eval: *a_eval, - b_eval: *b_eval, - c_eval: *c_eval, - d_eval: *d_eval, - a_next_eval, - b_next_eval, - d_next_eval, - q_arith_eval, - q_c_eval, - q_l_eval, - q_r_eval, - s_sigma_1_eval: *s_sigma_1_eval, - s_sigma_2_eval: *s_sigma_2_eval, - s_sigma_3_eval: *s_sigma_3_eval, - r_poly_eval, - z_eval: *z_eval, - }, - t_eval, - }, - ) + let a = t_low_poly; + let b = t_mid_poly * &z_n; + let c = t_high_poly * &z_two_n; + let d = t_4_poly * &z_three_n; + let abc = &(a + &b) + &c; + + let quot = &abc + &d; + + let z_h_eval = -domain.evaluate_vanishing_polynomial(z_challenge); + + let quot = " * &z_h_eval; + + let f = &f_1 + &f_2; + + // r_poly + &f + " } #[cfg(feature = "alloc")] @@ -288,72 +252,26 @@ fn compute_circuit_satisfiability( fixed_base_separation_challenge, var_base_separation_challenge, ): (&BlsScalar, &BlsScalar, &BlsScalar, &BlsScalar), - a_eval: &BlsScalar, - b_eval: &BlsScalar, - c_eval: &BlsScalar, - d_eval: &BlsScalar, - a_next_eval: &BlsScalar, - b_next_eval: &BlsScalar, - d_next_eval: &BlsScalar, - q_arith_eval: &BlsScalar, - q_c_eval: &BlsScalar, - q_l_eval: &BlsScalar, - q_r_eval: &BlsScalar, + evaluations: &ProofEvaluations, prover_key: &ProverKey, ) -> Polynomial { - let a = prover_key.arithmetic.compute_linearization( - a_eval, - b_eval, - c_eval, - d_eval, - q_arith_eval, - ); + let a = prover_key.arithmetic.compute_linearization(evaluations); - let b = prover_key.range.compute_linearization( - range_separation_challenge, - a_eval, - b_eval, - c_eval, - d_eval, - d_next_eval, - ); + let b = prover_key + .range + .compute_linearization(range_separation_challenge, evaluations); - let c = prover_key.logic.compute_linearization( - logic_separation_challenge, - a_eval, - a_next_eval, - b_eval, - b_next_eval, - c_eval, - d_eval, - d_next_eval, - q_c_eval, - ); + let c = prover_key + .logic + .compute_linearization(logic_separation_challenge, evaluations); - let d = prover_key.fixed_base.compute_linearization( - fixed_base_separation_challenge, - a_eval, - a_next_eval, - b_eval, - b_next_eval, - c_eval, - d_eval, - d_next_eval, - q_l_eval, - q_r_eval, - q_c_eval, - ); + let d = prover_key + .fixed_base + .compute_linearization(fixed_base_separation_challenge, evaluations); - let e = prover_key.variable_base.compute_linearization( - var_base_separation_challenge, - a_eval, - a_next_eval, - b_eval, - b_next_eval, - c_eval, - d_eval, - d_next_eval, - ); + let e = prover_key + .variable_base + .compute_linearization(var_base_separation_challenge, evaluations); let mut linearization_poly = &a + &b; linearization_poly += &c; diff --git a/src/proof_system/proof.rs b/src/proof_system/proof.rs index fd15b2de..10a39030 100644 --- a/src/proof_system/proof.rs +++ b/src/proof_system/proof.rs @@ -266,38 +266,7 @@ pub(crate) mod alloc { transcript.append_scalar(b"z_eval", &self.evaluations.z_eval); - let v_challenge = transcript.challenge_scalar(b"v_challenge"); - - // Compute zero polynomial evaluated at challenge `z` - let z_h_eval = domain.evaluate_vanishing_polynomial(&z_challenge); - - // Compute first lagrange polynomial evaluated at challenge `z` - let l1_eval = compute_first_lagrange_evaluation( - &domain, - &z_h_eval, - &z_challenge, - ); - - // Compute quotient polynomial evaluated at challenge `z` - let t_eval = self.compute_quotient_evaluation( - &domain, - pub_inputs, - &alpha, - &beta, - &gamma, - &z_challenge, - &z_h_eval, - &l1_eval, - &self.evaluations.z_eval, - ); - - // Compute commitment to quotient polynomial - // This method is necessary as we pass the `un-splitted` variation - // to our commitment scheme - let t_comm = - self.compute_quotient_commitment(&z_challenge, domain.size()); - - // Add evaluations to transcript + // Add extra evaluations to transcript transcript .append_scalar(b"a_next_eval", &self.evaluations.a_next_eval); transcript @@ -309,8 +278,18 @@ pub(crate) mod alloc { transcript.append_scalar(b"q_c_eval", &self.evaluations.q_c_eval); transcript.append_scalar(b"q_l_eval", &self.evaluations.q_l_eval); transcript.append_scalar(b"q_r_eval", &self.evaluations.q_r_eval); - transcript.append_scalar(b"t_eval", &t_eval); - transcript.append_scalar(b"r_eval", &self.evaluations.r_poly_eval); + + let v_challenge = transcript.challenge_scalar(b"v_challenge"); + + // Compute zero polynomial evaluated at challenge `z` + let z_h_eval = domain.evaluate_vanishing_polynomial(&z_challenge); + + // Compute first lagrange polynomial evaluated at challenge `z` + let l1_eval = compute_first_lagrange_evaluation( + &domain, + &z_h_eval, + &z_challenge, + ); // Compute linearization commitment let r_comm = self.compute_linearization_commitment( @@ -326,8 +305,27 @@ pub(crate) mod alloc { &z_challenge, l1_eval, verifier_key, + &domain, ); + let pi_eval = + compute_barycentric_eval(pub_inputs, &z_challenge, &domain); + + let r_0_eval = pi_eval + - l1_eval * alpha.square() + - alpha + * (self.evaluations.a_eval + + beta * self.evaluations.s_sigma_1_eval + + gamma) + * (self.evaluations.b_eval + + beta * self.evaluations.s_sigma_2_eval + + gamma) + * (self.evaluations.c_eval + + beta * self.evaluations.s_sigma_3_eval + + gamma) + * (self.evaluations.d_eval + gamma) + * self.evaluations.z_eval; + // Commitment Scheme // Now we delegate computation to the commitment scheme by batch // checking two proofs The `AggregateProof`, which is a @@ -340,8 +338,7 @@ pub(crate) mod alloc { // let mut aggregate_proof = AggregateProof::with_witness(self.w_z_chall_comm); - aggregate_proof.add_part((t_eval, t_comm)); - aggregate_proof.add_part((self.evaluations.r_poly_eval, r_comm)); + aggregate_proof.add_part((-r_0_eval, r_comm)); aggregate_proof.add_part((self.evaluations.a_eval, self.a_comm)); aggregate_proof.add_part((self.evaluations.b_eval, self.b_comm)); aggregate_proof.add_part((self.evaluations.c_eval, self.c_comm)); @@ -397,71 +394,6 @@ pub(crate) mod alloc { Ok(()) } - #[allow(clippy::too_many_arguments)] - fn compute_quotient_evaluation( - &self, - domain: &EvaluationDomain, - pub_inputs: &[BlsScalar], - alpha: &BlsScalar, - beta: &BlsScalar, - gamma: &BlsScalar, - z_challenge: &BlsScalar, - z_h_eval: &BlsScalar, - l1_eval: &BlsScalar, - z_hat_eval: &BlsScalar, - ) -> BlsScalar { - // Compute the public input polynomial evaluated at challenge `z` - let pi_eval = - compute_barycentric_eval(pub_inputs, z_challenge, domain); - - // Compute powers of alpha_0 - let alpha_sq = alpha.square(); - - // r + PI(z) - let a = self.evaluations.r_poly_eval + pi_eval; - - // a + beta * sigma_1 + gamma - let beta_sig1 = beta * self.evaluations.s_sigma_1_eval; - let b_0 = self.evaluations.a_eval + beta_sig1 + gamma; - - // b + beta * sigma_2 + gamma - let beta_sig2 = beta * self.evaluations.s_sigma_2_eval; - let b_1 = self.evaluations.b_eval + beta_sig2 + gamma; - - // o + beta * sigma_3 + gamma - let beta_sig3 = beta * self.evaluations.s_sigma_3_eval; - let b_2 = self.evaluations.c_eval + beta_sig3 + gamma; - - // ((d + gamma) * z_hat) * alpha_0 - let b_3 = (self.evaluations.d_eval + gamma) * z_hat_eval * alpha; - - let b = b_0 * b_1 * b_2 * b_3; - - // l_1(z) * alpha_0^2 - let c = l1_eval * alpha_sq; - - // Return t_eval - ( - a - b - c - //+ d - ) * z_h_eval.invert().unwrap() - } - - fn compute_quotient_commitment( - &self, - z_challenge: &BlsScalar, - n: usize, - ) -> Commitment { - let z_n = z_challenge.pow(&[n as u64, 0, 0, 0]); - let z_two_n = z_challenge.pow(&[2 * n as u64, 0, 0, 0]); - let z_three_n = z_challenge.pow(&[3 * n as u64, 0, 0, 0]); - let t_comm = self.t_low_comm.0 - + self.t_mid_comm.0 * z_n - + self.t_high_comm.0 * z_two_n - + self.t_4_comm.0 * z_three_n; - Commitment::from(t_comm) - } - // Commitment to [r]_1 #[allow(clippy::too_many_arguments)] fn compute_linearization_commitment( @@ -478,6 +410,7 @@ pub(crate) mod alloc { z_challenge: &BlsScalar, l1_eval: BlsScalar, verifier_key: &VerifierKey, + domain: &EvaluationDomain, ) -> Commitment { let mut scalars: Vec<_> = Vec::with_capacity(6); let mut points: Vec = Vec::with_capacity(6); @@ -526,6 +459,28 @@ pub(crate) mod alloc { self.z_comm.0, ); + let domain_size = domain.size(); + let z_h_eval = -domain.evaluate_vanishing_polynomial(z_challenge); + + let z_n = + z_challenge.pow(&[domain_size as u64, 0, 0, 0]) * z_h_eval; + let z_two_n = + z_challenge.pow(&[2 * domain_size as u64, 0, 0, 0]) * z_h_eval; + let z_three_n = + z_challenge.pow(&[3 * domain_size as u64, 0, 0, 0]) * z_h_eval; + + scalars.push(z_h_eval); + points.push(self.t_low_comm.0); + + scalars.push(z_n); + points.push(self.t_mid_comm.0); + + scalars.push(z_two_n); + points.push(self.t_high_comm.0); + + scalars.push(z_three_n); + points.push(self.t_4_comm.0); + Commitment::from(msm_variable_base(&points, &scalars)) } } @@ -540,7 +495,7 @@ pub(crate) mod alloc { z_h_eval * denom.invert().unwrap() } - fn compute_barycentric_eval( + pub(crate) fn compute_barycentric_eval( evaluations: &[BlsScalar], point: &BlsScalar, domain: &EvaluationDomain, @@ -631,7 +586,6 @@ mod proof_tests { s_sigma_1_eval: BlsScalar::random(&mut OsRng), s_sigma_2_eval: BlsScalar::random(&mut OsRng), s_sigma_3_eval: BlsScalar::random(&mut OsRng), - r_poly_eval: BlsScalar::random(&mut OsRng), z_eval: BlsScalar::random(&mut OsRng), }, }; diff --git a/src/proof_system/widget/arithmetic/proverkey.rs b/src/proof_system/widget/arithmetic/proverkey.rs index da573311..1a964303 100644 --- a/src/proof_system/widget/arithmetic/proverkey.rs +++ b/src/proof_system/widget/arithmetic/proverkey.rs @@ -5,6 +5,7 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use crate::fft::{Evaluations, Polynomial}; +use crate::proof_system::linearization_poly::ProofEvaluations; use dusk_bls12_381::BlsScalar; #[cfg(feature = "rkyv-impl")] @@ -70,11 +71,7 @@ impl ProverKey { pub(crate) fn compute_linearization( &self, - a_eval: &BlsScalar, - b_eval: &BlsScalar, - c_eval: &BlsScalar, - d_eval: &BlsScalar, - q_arith_eval: &BlsScalar, + evaluations: &ProofEvaluations, ) -> Polynomial { let q_m_poly = &self.q_m.0; let q_l_poly = &self.q_l.0; @@ -87,27 +84,27 @@ impl ProverKey { // * q_o + d_eval * q_4 + q_c) * q_arith_eval // // a_eval * b_eval * q_m_poly - let ab = a_eval * b_eval; + let ab = evaluations.a_eval * evaluations.b_eval; let a_0 = q_m_poly * &ab; // a_eval * q_l - let a_1 = q_l_poly * a_eval; + let a_1 = q_l_poly * &evaluations.a_eval; // b_eval * q_r - let a_2 = q_r_poly * b_eval; + let a_2 = q_r_poly * &evaluations.b_eval; //c_eval * q_o - let a_3 = q_o_poly * c_eval; + let a_3 = q_o_poly * &evaluations.c_eval; // d_eval * q_4 - let a_4 = q_4_poly * d_eval; + let a_4 = q_4_poly * &evaluations.d_eval; let mut a = &a_0 + &a_1; a = &a + &a_2; a = &a + &a_3; a = &a + &a_4; a = &a + q_c_poly; - a = &a * q_arith_eval; + a = &a * &evaluations.q_arith_eval; a } diff --git a/src/proof_system/widget/ecc/curve_addition/proverkey.rs b/src/proof_system/widget/ecc/curve_addition/proverkey.rs index e1ded404..c23ce1a1 100644 --- a/src/proof_system/widget/ecc/curve_addition/proverkey.rs +++ b/src/proof_system/widget/ecc/curve_addition/proverkey.rs @@ -5,6 +5,7 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use crate::fft::{Evaluations, Polynomial}; +use crate::proof_system::linearization_poly::ProofEvaluations; use dusk_bls12_381::BlsScalar; use dusk_jubjub::EDWARDS_D; @@ -80,25 +81,19 @@ impl ProverKey { pub(crate) fn compute_linearization( &self, curve_add_separation_challenge: &BlsScalar, - a_eval: &BlsScalar, - a_next_eval: &BlsScalar, - b_eval: &BlsScalar, - b_next_eval: &BlsScalar, - c_eval: &BlsScalar, - d_eval: &BlsScalar, - d_next_eval: &BlsScalar, + evaluations: &ProofEvaluations, ) -> Polynomial { let q_variable_group_add_poly = &self.q_variable_group_add.0; let kappa = curve_add_separation_challenge.square(); - let x_1 = a_eval; - let x_3 = a_next_eval; - let y_1 = b_eval; - let y_3 = b_next_eval; - let x_2 = c_eval; - let y_2 = d_eval; - let x1_y2 = d_next_eval; + let x_1 = evaluations.a_eval; + let x_3 = evaluations.a_next_eval; + let y_1 = evaluations.b_eval; + let y_3 = evaluations.b_next_eval; + let x_2 = evaluations.c_eval; + let y_2 = evaluations.d_eval; + let x1_y2 = evaluations.d_next_eval; // Checks // diff --git a/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs b/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs index 30f0d734..93cf85a5 100644 --- a/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs +++ b/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs @@ -5,6 +5,7 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use crate::fft::{Evaluations, Polynomial}; +use crate::proof_system::linearization_poly::ProofEvaluations; use dusk_bls12_381::BlsScalar; use dusk_jubjub::EDWARDS_D; @@ -104,16 +105,7 @@ impl ProverKey { pub(crate) fn compute_linearization( &self, ecc_separation_challenge: &BlsScalar, - a_eval: &BlsScalar, - a_next_eval: &BlsScalar, - b_eval: &BlsScalar, - b_next_eval: &BlsScalar, - c_eval: &BlsScalar, - d_eval: &BlsScalar, - d_next_eval: &BlsScalar, - q_l_eval: &BlsScalar, - q_r_eval: &BlsScalar, - q_c_eval: &BlsScalar, + evaluations: &ProofEvaluations, ) -> Polynomial { let q_fixed_group_add_poly = &self.q_fixed_group_add.0; @@ -121,19 +113,19 @@ impl ProverKey { let kappa_sq = kappa.square(); let kappa_cu = kappa_sq * kappa; - let x_beta_eval = q_l_eval; - let y_beta_eval = q_r_eval; + let x_beta_eval = evaluations.q_l_eval; + let y_beta_eval = evaluations.q_r_eval; - let acc_x = a_eval; - let acc_x_next = a_next_eval; - let acc_y = b_eval; - let acc_y_next = b_next_eval; + let acc_x = evaluations.a_eval; + let acc_x_next = evaluations.a_next_eval; + let acc_y = evaluations.b_eval; + let acc_y_next = evaluations.b_next_eval; - let xy_alpha = c_eval; + let xy_alpha = evaluations.c_eval; - let accumulated_bit = d_eval; - let accumulated_bit_next = d_next_eval; - let bit = extract_bit(accumulated_bit, accumulated_bit_next); + let accumulated_bit = evaluations.d_eval; + let accumulated_bit_next = evaluations.d_next_eval; + let bit = extract_bit(&accumulated_bit, &accumulated_bit_next); // Check bit consistency let bit_consistency = check_bit_consistency(bit); @@ -144,7 +136,7 @@ impl ProverKey { let x_alpha = x_beta_eval * bit; // xy_alpha consistency check - let xy_consistency = ((bit * q_c_eval) - xy_alpha) * kappa; + let xy_consistency = ((bit * evaluations.q_c_eval) - xy_alpha) * kappa; // x accumulator consistency check let x_3 = acc_x_next; diff --git a/src/proof_system/widget/logic/proverkey.rs b/src/proof_system/widget/logic/proverkey.rs index 4a77070c..38973517 100644 --- a/src/proof_system/widget/logic/proverkey.rs +++ b/src/proof_system/widget/logic/proverkey.rs @@ -5,6 +5,7 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use crate::fft::{Evaluations, Polynomial}; +use crate::proof_system::linearization_poly::ProofEvaluations; use dusk_bls12_381::BlsScalar; @@ -73,14 +74,7 @@ impl ProverKey { pub(crate) fn compute_linearization( &self, logic_separation_challenge: &BlsScalar, - a_eval: &BlsScalar, - a_next_eval: &BlsScalar, - b_eval: &BlsScalar, - b_next_eval: &BlsScalar, - c_eval: &BlsScalar, - d_eval: &BlsScalar, - d_next_eval: &BlsScalar, - q_c_eval: &BlsScalar, + evaluations: &ProofEvaluations, ) -> Polynomial { let four = BlsScalar::from(4); let q_logic_poly = &self.q_logic.0; @@ -90,19 +84,20 @@ impl ProverKey { let kappa_cu = kappa_sq * kappa; let kappa_qu = kappa_cu * kappa; - let a = a_next_eval - four * a_eval; + let a = evaluations.a_next_eval - four * evaluations.a_eval; let o_0 = delta(a); - let b = b_next_eval - four * b_eval; + let b = evaluations.b_next_eval - four * evaluations.b_eval; let o_1 = delta(b) * kappa; - let d = d_next_eval - four * d_eval; + let d = evaluations.d_next_eval - four * evaluations.d_eval; let o_2 = delta(d) * kappa_sq; - let w = c_eval; + let w = evaluations.c_eval; let o_3 = (w - a * b) * kappa_cu; - let o_4 = delta_xor_and(&a, &b, w, &d, q_c_eval) * kappa_qu; + let o_4 = + delta_xor_and(&a, &b, &w, &d, &evaluations.q_c_eval) * kappa_qu; let t = (o_0 + o_1 + o_2 + o_3 + o_4) * logic_separation_challenge; diff --git a/src/proof_system/widget/range/proverkey.rs b/src/proof_system/widget/range/proverkey.rs index d3f6f8fd..507d8bf4 100644 --- a/src/proof_system/widget/range/proverkey.rs +++ b/src/proof_system/widget/range/proverkey.rs @@ -5,6 +5,7 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use crate::fft::{Evaluations, Polynomial}; +use crate::proof_system::linearization_poly::ProofEvaluations; use dusk_bls12_381::BlsScalar; #[cfg(feature = "rkyv-impl")] @@ -58,11 +59,7 @@ impl ProverKey { pub(crate) fn compute_linearization( &self, range_separation_challenge: &BlsScalar, - a_eval: &BlsScalar, - b_eval: &BlsScalar, - c_eval: &BlsScalar, - d_eval: &BlsScalar, - d_next_eval: &BlsScalar, + evaluations: &ProofEvaluations, ) -> Polynomial { let four = BlsScalar::from(4); let q_range_poly = &self.q_range.0; @@ -74,10 +71,12 @@ impl ProverKey { // Delta([c_eval - 4 * d_eval]) + Delta([b_eval - 4 * c_eval]) + // Delta([a_eval - 4 * b_eval]) + Delta([d_next_eval - 4 * a_eval]) * // Q_Range(X) - let b_1 = delta(c_eval - four * d_eval); - let b_2 = delta(b_eval - four * c_eval) * kappa; - let b_3 = delta(a_eval - four * b_eval) * kappa_sq; - let b_4 = delta(d_next_eval - four * a_eval) * kappa_cu; + let b_1 = delta(evaluations.c_eval - four * evaluations.d_eval); + let b_2 = delta(evaluations.b_eval - four * evaluations.c_eval) * kappa; + let b_3 = + delta(evaluations.a_eval - four * evaluations.b_eval) * kappa_sq; + let b_4 = delta(evaluations.d_next_eval - four * evaluations.a_eval) + * kappa_cu; let t = (b_1 + b_2 + b_3 + b_4) * range_separation_challenge; From 27219ab6f94fdb548db5292b4cee39da76f0e590 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Mon, 8 Jul 2024 00:08:28 +0200 Subject: [PATCH 07/11] Update verifier to match the last Plonk paper --- src/commitment_scheme/kzg10/key.rs | 27 +-- src/commitment_scheme/kzg10/proof.rs | 2 + src/commitment_scheme/kzg10/srs.rs | 4 +- src/compiler/prover.rs | 7 +- src/proof_system/proof.rs | 219 ++++++++++++------ .../widget/permutation/verifierkey.rs | 3 +- 6 files changed, 166 insertions(+), 96 deletions(-) diff --git a/src/commitment_scheme/kzg10/key.rs b/src/commitment_scheme/kzg10/key.rs index 78430198..82078b79 100644 --- a/src/commitment_scheme/kzg10/key.rs +++ b/src/commitment_scheme/kzg10/key.rs @@ -225,15 +225,15 @@ pub struct OpeningKey { /// The generator of G2. #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub(crate) h: G2Affine, - /// \beta times the above generator of G2. + /// 'x' times the above generator of G2. #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) beta_h: G2Affine, + pub(crate) x_h: G2Affine, /// The generator of G2, prepared for use in pairings. #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub(crate) prepared_h: G2Prepared, - /// \beta times the above generator of G2, prepared for use in pairings. + /// 'x' times the above generator of G2, prepared for use in pairings. #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) prepared_beta_h: G2Prepared, + pub(crate) prepared_x_h: G2Prepared, } impl Serializable<{ G1Affine::SIZE + G2Affine::SIZE * 2 }> for OpeningKey { @@ -246,7 +246,7 @@ impl Serializable<{ G1Affine::SIZE + G2Affine::SIZE * 2 }> for OpeningKey { // This can't fail therefore we don't care about the Result nor use it. writer.write(&self.g.to_bytes()); writer.write(&self.h.to_bytes()); - writer.write(&self.beta_h.to_bytes()); + writer.write(&self.x_h.to_bytes()); buf } @@ -262,24 +262,21 @@ impl Serializable<{ G1Affine::SIZE + G2Affine::SIZE * 2 }> for OpeningKey { } impl OpeningKey { - pub(crate) fn new( - g: G1Affine, - h: G2Affine, - beta_h: G2Affine, - ) -> OpeningKey { + pub(crate) fn new(g: G1Affine, h: G2Affine, x_h: G2Affine) -> OpeningKey { let prepared_h = G2Prepared::from(h); - let prepared_beta_h = G2Prepared::from(beta_h); + let prepared_x_h = G2Prepared::from(x_h); OpeningKey { g, h, - beta_h, + x_h, prepared_h, - prepared_beta_h, + prepared_x_h, } } /// Checks whether a batch of polynomials evaluated at different points, /// returned their specified value. + #[allow(dead_code)] pub(crate) fn batch_check( &self, points: &[BlsScalar], @@ -313,7 +310,7 @@ impl OpeningKey { let affine_total_c = G1Affine::from(total_c); let pairing = dusk_bls12_381::multi_miller_loop(&[ - (&affine_total_w, &self.prepared_beta_h), + (&affine_total_w, &self.prepared_x_h), (&affine_total_c, &self.prepared_h), ]) .final_exponentiation(); @@ -343,7 +340,7 @@ mod test { - (op_key.g * proof.evaluated_point)) .into(); - let inner_b: G2Affine = (op_key.beta_h - (op_key.h * point)).into(); + let inner_b: G2Affine = (op_key.x_h - (op_key.h * point)).into(); let prepared_inner_b = G2Prepared::from(-inner_b); let pairing = dusk_bls12_381::multi_miller_loop(&[ diff --git a/src/commitment_scheme/kzg10/proof.rs b/src/commitment_scheme/kzg10/proof.rs index 1fae715a..58fffb63 100644 --- a/src/commitment_scheme/kzg10/proof.rs +++ b/src/commitment_scheme/kzg10/proof.rs @@ -34,6 +34,7 @@ pub(crate) mod alloc { /// Proof that multiple polynomials were correctly evaluated at a point `z`, /// each producing their respective evaluated points p_i(z). #[derive(Debug)] + #[allow(dead_code)] pub(crate) struct AggregateProof { /// This is a commitment to the aggregated witness polynomial. pub(crate) commitment_to_witness: Commitment, @@ -45,6 +46,7 @@ pub(crate) mod alloc { pub(crate) commitments_to_polynomials: Vec, } + #[allow(dead_code)] impl AggregateProof { /// Initializes an `AggregatedProof` with the commitment to the witness. pub(crate) fn with_witness(witness: Commitment) -> AggregateProof { diff --git a/src/commitment_scheme/kzg10/srs.rs b/src/commitment_scheme/kzg10/srs.rs index 55a18595..709df97c 100644 --- a/src/commitment_scheme/kzg10/srs.rs +++ b/src/commitment_scheme/kzg10/srs.rs @@ -230,7 +230,7 @@ mod test { assert_eq!(got_pp.commit_key.powers_of_g, pp.commit_key.powers_of_g); assert_eq!(got_pp.opening_key.g, pp.opening_key.g); assert_eq!(got_pp.opening_key.h, pp.opening_key.h); - assert_eq!(got_pp.opening_key.beta_h, pp.opening_key.beta_h); + assert_eq!(got_pp.opening_key.x_h, pp.opening_key.x_h); } #[test] @@ -245,6 +245,6 @@ mod test { assert_eq!(pp.commit_key, pp_p.commit_key); assert_eq!(pp.opening_key.g, pp_p.opening_key.g); assert_eq!(pp.opening_key.h, pp_p.opening_key.h); - assert_eq!(pp.opening_key.beta_h, pp_p.opening_key.beta_h); + assert_eq!(pp.opening_key.x_h, pp_p.opening_key.x_h); } } diff --git a/src/compiler/prover.rs b/src/compiler/prover.rs index b3d29eff..68bf956b 100644 --- a/src/compiler/prover.rs +++ b/src/compiler/prover.rs @@ -515,15 +515,14 @@ impl Prover { ); let w_z_chall_comm = self.commit_key.commit(&aggregate_witness)?; - // compute the shifted challenge 'v' - let v_challenge_shifted = - transcript.challenge_scalar(b"v_challenge_shifted"); + // compute the shifted challenge 'v_w' + let v_w_challenge = transcript.challenge_scalar(b"v_w_challenge"); // compute the shifted opening proof polynomial 'W_zw(X)' let shifted_aggregate_witness = CommitKey::compute_aggregate_witness( &[z_poly, a_w_poly, b_w_poly, d_w_poly], &(z_challenge * domain.group_gen), - &v_challenge_shifted, + &v_w_challenge, ); let w_z_chall_w_comm = self.commit_key.commit(&shifted_aggregate_witness)?; diff --git a/src/proof_system/proof.rs b/src/proof_system/proof.rs index 10a39030..10111aa8 100644 --- a/src/proof_system/proof.rs +++ b/src/proof_system/proof.rs @@ -12,6 +12,11 @@ use crate::commitment_scheme::Commitment; use dusk_bytes::{DeserializableSlice, Serializable}; +#[cfg(feature = "std")] +use rayon::prelude::*; + +const V_MAX_DEGREE: usize = 7; + #[cfg(feature = "rkyv-impl")] use crate::util::check_field; #[cfg(feature = "rkyv-impl")] @@ -172,6 +177,7 @@ impl Serializable<{ 11 * Commitment::SIZE + ProofEvaluations::SIZE }> } #[cfg(feature = "alloc")] +#[allow(unused_imports)] pub(crate) mod alloc { use super::*; use crate::{ @@ -185,7 +191,7 @@ pub(crate) mod alloc { #[rustfmt::skip] use ::alloc::vec::Vec; use dusk_bls12_381::{ - multiscalar_mul::msm_variable_base, BlsScalar, G1Affine, + multiscalar_mul::msm_variable_base, BlsScalar, G1Affine, G1Projective, }; use merlin::Transcript; #[cfg(feature = "std")] @@ -193,6 +199,7 @@ pub(crate) mod alloc { impl Proof { /// Performs the verification of a [`Proof`] returning a boolean result. + #[allow(non_snake_case)] pub(crate) fn verify( &self, verifier_key: &VerifierKey, @@ -280,6 +287,14 @@ pub(crate) mod alloc { transcript.append_scalar(b"q_r_eval", &self.evaluations.q_r_eval); let v_challenge = transcript.challenge_scalar(b"v_challenge"); + let v_w_challenge = transcript.challenge_scalar(b"v_w_challenge"); + + // Add commitment to openings to transcript + transcript.append_commitment(b"w_z", &self.w_z_chall_comm); + transcript.append_commitment(b"w_z_w", &self.w_z_chall_w_comm); + + // Compute the challenge 'u' + let u_challenge = transcript.challenge_scalar(b"u_challenge"); // Compute zero polynomial evaluated at challenge `z` let z_h_eval = domain.evaluate_vanishing_polynomial(&z_challenge); @@ -291,26 +306,31 @@ pub(crate) mod alloc { &z_challenge, ); - // Compute linearization commitment - let r_comm = self.compute_linearization_commitment( - &alpha, - &beta, - &gamma, - ( - &range_sep_challenge, - &logic_sep_challenge, - &fixed_base_sep_challenge, - &var_base_sep_challenge, - ), - &z_challenge, - l1_eval, - verifier_key, - &domain, - ); + // Compute '[D]_1' + let D = self + .compute_linearization_commitment( + &alpha, + &beta, + &gamma, + ( + &range_sep_challenge, + &logic_sep_challenge, + &fixed_base_sep_challenge, + &var_base_sep_challenge, + ), + &z_challenge, + &u_challenge, + l1_eval, + verifier_key, + &domain, + ) + .0; + // Evaluate public inputs let pi_eval = compute_barycentric_eval(pub_inputs, &z_challenge, &domain); + // Compute r_0 let r_0_eval = pi_eval - l1_eval * alpha.square() - alpha @@ -326,70 +346,119 @@ pub(crate) mod alloc { * (self.evaluations.d_eval + gamma) * self.evaluations.z_eval; - // Commitment Scheme - // Now we delegate computation to the commitment scheme by batch - // checking two proofs The `AggregateProof`, which is a - // proof that all the necessary polynomials evaluated at - // challenge `z` are correct and a `SingleProof` which - // is proof that the permutation polynomial evaluated at the shifted - // root of unity is correct + // Coefficients to compute [E]_1 + let mut v_coeffs_E = vec![v_challenge]; - // Compose the Aggregated Proof - // - let mut aggregate_proof = - AggregateProof::with_witness(self.w_z_chall_comm); - aggregate_proof.add_part((-r_0_eval, r_comm)); - aggregate_proof.add_part((self.evaluations.a_eval, self.a_comm)); - aggregate_proof.add_part((self.evaluations.b_eval, self.b_comm)); - aggregate_proof.add_part((self.evaluations.c_eval, self.c_comm)); - aggregate_proof.add_part((self.evaluations.d_eval, self.d_comm)); - aggregate_proof.add_part(( + // Compute the powers of the v_challenge + for i in 1..V_MAX_DEGREE { + v_coeffs_E.push(v_coeffs_E[i - 1] * v_challenge); + } + + // Compute the powers of the v_challenge multiplied by u_challenge + v_coeffs_E.push(v_w_challenge * u_challenge); + v_coeffs_E.push(v_coeffs_E[V_MAX_DEGREE] * v_w_challenge); + v_coeffs_E.push(v_coeffs_E[V_MAX_DEGREE + 1] * v_w_challenge); + + // Coefficients to compute [F]_1 + let mut v_coeffs_F = v_coeffs_E[..V_MAX_DEGREE].to_vec(); + + // As we include the shifted coefficients when computing [F]_1, + // we group them to save scalar multiplications when multiplying + // by [a]_1, [b]_1, and [d]_1 + v_coeffs_F[0] += v_coeffs_E[V_MAX_DEGREE]; + v_coeffs_F[1] += v_coeffs_E[V_MAX_DEGREE + 1]; + v_coeffs_F[3] += v_coeffs_E[V_MAX_DEGREE + 2]; + + // Commitments to compute [F]_1 + let F_comms = vec![ + self.a_comm.0, + self.b_comm.0, + self.c_comm.0, + self.d_comm.0, + verifier_key.permutation.s_sigma_1.0, + verifier_key.permutation.s_sigma_2.0, + verifier_key.permutation.s_sigma_3.0, + ]; + + // Compute '[F]_1' in single-core + #[cfg(not(feature = "std"))] + let mut F: G1Projective = F_comms + .iter() + .zip(v_coeffs_F.iter()) + .map(|(poly, coeff)| poly * coeff) + .sum(); + + // Compute '[F]_1' in multi-core + #[cfg(feature = "std")] + let mut F: G1Projective = F_comms + .par_iter() + .zip(v_coeffs_F.par_iter()) + .map(|(poly, coeff)| poly * coeff) + .sum(); + + // [F]_1 = [D]_1 + (v)[a]_1 + (v^2)[b]_1 + (v^3)[c]_1 + (v^4)[d]_1 + + // + (v^5)[s_sigma_1]_1 + (v^6)[s_sigma_2]_1 + (v^7)[s_sigma_3]_1 + + // + (u * v_w)[a]_1 + (u * v_w^2)[b]_1 + (u * v_w^3)[d]_1 + F += D; + + // Evaluations to compute [E]_1 + let E_evals = vec![ + self.evaluations.a_eval, + self.evaluations.b_eval, + self.evaluations.c_eval, + self.evaluations.d_eval, self.evaluations.s_sigma_1_eval, - verifier_key.permutation.s_sigma_1, - )); - aggregate_proof.add_part(( self.evaluations.s_sigma_2_eval, - verifier_key.permutation.s_sigma_2, - )); - aggregate_proof.add_part(( self.evaluations.s_sigma_3_eval, - verifier_key.permutation.s_sigma_3, - )); - // Flatten proof with opening challenge - let flattened_proof_a = aggregate_proof.flatten(&v_challenge); - - // Compose the shifted aggregate proof - let mut shifted_aggregate_proof = - AggregateProof::with_witness(self.w_z_chall_w_comm); - shifted_aggregate_proof - .add_part((self.evaluations.z_eval, self.z_comm)); - shifted_aggregate_proof - .add_part((self.evaluations.a_next_eval, self.a_comm)); - shifted_aggregate_proof - .add_part((self.evaluations.b_next_eval, self.b_comm)); - shifted_aggregate_proof - .add_part((self.evaluations.d_next_eval, self.d_comm)); - - let v_challenge_shifted = - transcript.challenge_scalar(b"v_challenge_shifted"); - let flattened_proof_b = - shifted_aggregate_proof.flatten(&v_challenge_shifted); + self.evaluations.a_next_eval, + self.evaluations.b_next_eval, + self.evaluations.d_next_eval, + ]; + + // Compute '[E]_1' = (-r_0 + (v)a + (v^2)b + (v^3)c + (v^4)d + + // + (v^5)s_sigma_1 + (v^6)s_sigma_2 + (v^7)s_sigma_3 + + // + (u)z_w + (u * v_w)a_w + (u * v_w^2)b_w + (u * v_w^3)d_w) + let mut E: BlsScalar = E_evals + .iter() + .zip(v_coeffs_E.iter()) + .map(|(eval, coeff)| eval * coeff) + .sum(); + E += -r_0_eval + (u_challenge * self.evaluations.z_eval); + + let E = E * opening_key.g; + + // Compute the G_1 element of the first pairing: + // [W_z]_1 + u * [W_zw]_1 + // + // Note that we negate this value to be able to subtract + // the pairings later on, using the multi Miller loop + let left = G1Affine::from( + -(self.w_z_chall_comm.0 + + u_challenge * self.w_z_chall_w_comm.0), + ); - // Add commitment to openings to transcript - transcript.append_commitment(b"w_z", &self.w_z_chall_comm); - transcript.append_commitment(b"w_z_w", &self.w_z_chall_w_comm); + // Compute the G_1 element of the second pairing: + // z * [W_z]_1 + (u * z * w) * [W_zw]_1 + [F]_1 - [E]_1 + let right = G1Affine::from( + z_challenge * self.w_z_chall_comm.0 + + (u_challenge * z_challenge * domain.group_gen) + * self.w_z_chall_w_comm.0 + + F + - E, + ); - // Batch check - if opening_key - .batch_check( - &[z_challenge, (z_challenge * domain.group_gen)], - &[flattened_proof_a, flattened_proof_b], - transcript, - ) - .is_err() - { + // Compute the two pairings and subtract them + let pairing = dusk_bls12_381::multi_miller_loop(&[ + (&left, &opening_key.prepared_x_h), + (&right, &opening_key.prepared_h), + ]) + .final_exponentiation(); + + // Return 'ProofVerificationError' if the two + // pairings are not equal, continue otherwise + if pairing != dusk_bls12_381::Gt::identity() { return Err(Error::ProofVerificationError); - } + }; Ok(()) } @@ -408,6 +477,7 @@ pub(crate) mod alloc { var_base_sep_challenge, ): (&BlsScalar, &BlsScalar, &BlsScalar, &BlsScalar), z_challenge: &BlsScalar, + u_challenge: &BlsScalar, l1_eval: BlsScalar, verifier_key: &VerifierKey, domain: &EvaluationDomain, @@ -454,6 +524,7 @@ pub(crate) mod alloc { &mut points, &self.evaluations, z_challenge, + u_challenge, (alpha, beta, gamma), &l1_eval, self.z_comm.0, diff --git a/src/proof_system/widget/permutation/verifierkey.rs b/src/proof_system/widget/permutation/verifierkey.rs index e143069f..f5c21e5f 100644 --- a/src/proof_system/widget/permutation/verifierkey.rs +++ b/src/proof_system/widget/permutation/verifierkey.rs @@ -48,6 +48,7 @@ mod alloc { points: &mut Vec, evaluations: &ProofEvaluations, z_challenge: &BlsScalar, + u_challenge: &BlsScalar, (alpha, beta, gamma): (&BlsScalar, &BlsScalar, &BlsScalar), l1_eval: &BlsScalar, z_comm: G1Affine, @@ -77,7 +78,7 @@ mod alloc { // l1(z) * alpha^2 let r = l1_eval * alpha_sq; - scalars.push(x + r); + scalars.push(x + r + u_challenge); points.push(z_comm); // -1 * (a_eval + beta * sigma_1_eval + gamma) From 205263303aabcc90f0a0682d4c4b0d1f10f4a5f7 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Mon, 8 Jul 2024 14:27:54 +0200 Subject: [PATCH 08/11] Update CHANGELOG.md --- CHANGELOG.md | 10 +++++++++- README.md | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b2f2e1..70d05fc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Changed +### Changed + +- Modify the prover to match the paper [#831] +- Modify the verifier to match the paper [#831] +- Rename some variables to match the paper [#831] + +### Removed - Remove docs [#819] +- Remove unused `Evaluations` struct ## [0.19.2] - 2024-03-27 @@ -585,6 +592,7 @@ is necessary since `rkyv/validation` was required as a bound. - Proof system module. +[#831]: https://github.com/dusk-network/plonk/issues/831 [#819]: https://github.com/dusk-network/plonk/issues/819 [#818]: https://github.com/dusk-network/plonk/issues/818 [#815]: https://github.com/dusk-network/plonk/issues/815 diff --git a/README.md b/README.md index 9c946cfd..0a4f2b77 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ as the documentation regarding the data structures that it exports. To check thi Benchmarks taken on `Apple M1`, for a circuit-size of `2^16` constraints: - Proving time: `7.871s` -- Verification time: `7.643ms` **(This time does not vary depending on the circuit-size.)** +- Verification time: `3.732ms` **(This time does not vary depending on the circuit-size.)** For more results, please run `cargo bench` to get a full report of benchmarks in respect of constraint numbers. From 568f9d975ce4d5ed6826a153c10249ac666544eb Mon Sep 17 00:00:00 2001 From: xevisalle Date: Tue, 23 Jul 2024 17:10:17 +0200 Subject: [PATCH 09/11] Make variable names match the specs --- src/compiler.rs | 113 +++++------ src/compiler/prover.rs | 148 +++++++------- src/composer.rs | 72 +++---- src/composer/compress.rs | 64 +++--- src/composer/constraint_system/constraint.rs | 24 +-- src/composer/gate.rs | 10 +- src/composer/permutation.rs | 188 +++++++++--------- src/debugger.rs | 167 ++++++++-------- src/proof_system/linearization_poly.rs | 28 +-- src/proof_system/preprocess.rs | 7 +- src/proof_system/proof.rs | 61 +++--- src/proof_system/quotient_poly.rs | 98 ++++----- src/proof_system/widget.rs | 32 +-- .../widget/arithmetic/proverkey.rs | 34 ++-- .../widget/arithmetic/verifierkey.rs | 10 +- .../widget/ecc/curve_addition/proverkey.rs | 34 ++-- .../widget/ecc/curve_addition/verifierkey.rs | 6 +- .../ecc/scalar_mul/fixed_base/proverkey.rs | 55 +++-- .../ecc/scalar_mul/fixed_base/verifierkey.rs | 12 +- src/proof_system/widget/logic/proverkey.rs | 52 ++--- src/proof_system/widget/logic/verifierkey.rs | 22 +- .../widget/permutation/proverkey.rs | 50 ++--- src/proof_system/widget/range/proverkey.rs | 24 +-- src/proof_system/widget/range/verifierkey.rs | 5 +- tests/append_gate.rs | 76 +++---- 25 files changed, 695 insertions(+), 697 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 8dbfe431..e1dacf26 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -108,7 +108,7 @@ impl Compiler { let mut q_l = vec![BlsScalar::zero(); size]; let mut q_r = vec![BlsScalar::zero(); size]; let mut q_o = vec![BlsScalar::zero(); size]; - let mut q_4 = vec![BlsScalar::zero(); size]; + let mut q_f = vec![BlsScalar::zero(); size]; let mut q_c = vec![BlsScalar::zero(); size]; let mut q_arith = vec![BlsScalar::zero(); size]; let mut q_range = vec![BlsScalar::zero(); size]; @@ -116,25 +116,29 @@ impl Compiler { let mut q_fixed_group_add = vec![BlsScalar::zero(); size]; let mut q_variable_group_add = vec![BlsScalar::zero(); size]; - prover.constraints.iter().enumerate().for_each(|(i, c)| { - q_m[i] = c.q_m; - q_l[i] = c.q_l; - q_r[i] = c.q_r; - q_o[i] = c.q_o; - q_4[i] = c.q_4; - q_c[i] = c.q_c; - q_arith[i] = c.q_arith; - q_range[i] = c.q_range; - q_logic[i] = c.q_logic; - q_fixed_group_add[i] = c.q_fixed_group_add; - q_variable_group_add[i] = c.q_variable_group_add; - }); + prover + .constraints + .iter() + .enumerate() + .for_each(|(i, constraint)| { + q_m[i] = constraint.q_m; + q_l[i] = constraint.q_l; + q_r[i] = constraint.q_r; + q_o[i] = constraint.q_o; + q_f[i] = constraint.q_f; + q_c[i] = constraint.q_c; + q_arith[i] = constraint.q_arith; + q_range[i] = constraint.q_range; + q_logic[i] = constraint.q_logic; + q_fixed_group_add[i] = constraint.q_fixed_group_add; + q_variable_group_add[i] = constraint.q_variable_group_add; + }); let q_m_poly = domain.ifft(&q_m); let q_l_poly = domain.ifft(&q_l); let q_r_poly = domain.ifft(&q_r); let q_o_poly = domain.ifft(&q_o); - let q_4_poly = domain.ifft(&q_4); + let q_f_poly = domain.ifft(&q_f); let q_c_poly = domain.ifft(&q_c); let q_arith_poly = domain.ifft(&q_arith); let q_range_poly = domain.ifft(&q_range); @@ -146,7 +150,7 @@ impl Compiler { let q_l_poly = Polynomial::from_coefficients_vec(q_l_poly); let q_r_poly = Polynomial::from_coefficients_vec(q_r_poly); let q_o_poly = Polynomial::from_coefficients_vec(q_o_poly); - let q_4_poly = Polynomial::from_coefficients_vec(q_4_poly); + let q_f_poly = Polynomial::from_coefficients_vec(q_f_poly); let q_c_poly = Polynomial::from_coefficients_vec(q_c_poly); let q_arith_poly = Polynomial::from_coefficients_vec(q_arith_poly); let q_range_poly = Polynomial::from_coefficients_vec(q_range_poly); @@ -160,72 +164,69 @@ impl Compiler { let [s_sigma_1_poly, s_sigma_2_poly, s_sigma_3_poly, s_sigma_4_poly] = perm.compute_sigma_polynomials(size, &domain); - let q_m_poly_commit = commit_key.commit(&q_m_poly).unwrap_or_default(); - let q_l_poly_commit = commit_key.commit(&q_l_poly).unwrap_or_default(); - let q_r_poly_commit = commit_key.commit(&q_r_poly).unwrap_or_default(); - let q_o_poly_commit = commit_key.commit(&q_o_poly).unwrap_or_default(); - let q_4_poly_commit = commit_key.commit(&q_4_poly).unwrap_or_default(); - let q_c_poly_commit = commit_key.commit(&q_c_poly).unwrap_or_default(); - let q_arith_poly_commit = - commit_key.commit(&q_arith_poly).unwrap_or_default(); - let q_range_poly_commit = - commit_key.commit(&q_range_poly).unwrap_or_default(); - let q_logic_poly_commit = - commit_key.commit(&q_logic_poly).unwrap_or_default(); - let q_fixed_group_add_poly_commit = commit_key + let q_m_comm = commit_key.commit(&q_m_poly).unwrap_or_default(); + let q_l_comm = commit_key.commit(&q_l_poly).unwrap_or_default(); + let q_r_comm = commit_key.commit(&q_r_poly).unwrap_or_default(); + let q_o_comm = commit_key.commit(&q_o_poly).unwrap_or_default(); + let q_f_comm = commit_key.commit(&q_f_poly).unwrap_or_default(); + let q_c_comm = commit_key.commit(&q_c_poly).unwrap_or_default(); + let q_arith_comm = commit_key.commit(&q_arith_poly).unwrap_or_default(); + let q_range_comm = commit_key.commit(&q_range_poly).unwrap_or_default(); + let q_logic_comm = commit_key.commit(&q_logic_poly).unwrap_or_default(); + let q_fixed_group_add_comm = commit_key .commit(&q_fixed_group_add_poly) .unwrap_or_default(); - let q_variable_group_add_poly_commit = commit_key + let q_variable_group_add_comm = commit_key .commit(&q_variable_group_add_poly) .unwrap_or_default(); - let s_sigma_1_poly_commit = commit_key.commit(&s_sigma_1_poly)?; - let s_sigma_2_poly_commit = commit_key.commit(&s_sigma_2_poly)?; - let s_sigma_3_poly_commit = commit_key.commit(&s_sigma_3_poly)?; - let s_sigma_4_poly_commit = commit_key.commit(&s_sigma_4_poly)?; + let s_sigma_1_comm = commit_key.commit(&s_sigma_1_poly)?; + let s_sigma_2_comm = commit_key.commit(&s_sigma_2_poly)?; + let s_sigma_3_comm = commit_key.commit(&s_sigma_3_poly)?; + let s_sigma_4_comm = commit_key.commit(&s_sigma_4_poly)?; // verifier Key for arithmetic circuits let arithmetic_verifier_key = widget::arithmetic::VerifierKey { - q_m: q_m_poly_commit, - q_l: q_l_poly_commit, - q_r: q_r_poly_commit, - q_o: q_o_poly_commit, - q_4: q_4_poly_commit, - q_c: q_c_poly_commit, - q_arith: q_arith_poly_commit, + q_m: q_m_comm, + q_l: q_l_comm, + q_r: q_r_comm, + q_o: q_o_comm, + q_f: q_f_comm, + q_c: q_c_comm, + q_arith: q_arith_comm, }; // verifier Key for range circuits let range_verifier_key = widget::range::VerifierKey { - q_range: q_range_poly_commit, + q_range: q_range_comm, }; // verifier Key for logic circuits let logic_verifier_key = widget::logic::VerifierKey { - q_c: q_c_poly_commit, - q_logic: q_logic_poly_commit, + q_c: q_c_comm, + q_logic: q_logic_comm, }; // verifier Key for ecc circuits let ecc_verifier_key = widget::ecc::scalar_mul::fixed_base::VerifierKey { - q_l: q_l_poly_commit, - q_r: q_r_poly_commit, - q_fixed_group_add: q_fixed_group_add_poly_commit, + q_l: q_l_comm, + q_r: q_r_comm, + q_fixed_group_add: q_fixed_group_add_comm, }; // verifier Key for curve addition circuits let curve_addition_verifier_key = widget::ecc::curve_addition::VerifierKey { - q_variable_group_add: q_variable_group_add_poly_commit, + q_variable_group_add: q_variable_group_add_comm, }; // verifier Key for permutation argument let permutation_verifier_key = widget::permutation::VerifierKey { - s_sigma_1: s_sigma_1_poly_commit, - s_sigma_2: s_sigma_2_poly_commit, - s_sigma_3: s_sigma_3_poly_commit, - s_sigma_4: s_sigma_4_poly_commit, + s_sigma_1: s_sigma_1_comm, + s_sigma_2: s_sigma_2_comm, + s_sigma_3: s_sigma_3_comm, + s_sigma_4: s_sigma_4_comm, }; let verifier_key = widget::VerifierKey { @@ -243,7 +244,7 @@ impl Compiler { q_l: q_l_poly, q_r: q_r_poly, q_o: q_o_poly, - q_4: q_4_poly, + q_f: q_f_poly, q_c: q_c_poly, q_arith: q_arith_poly, q_range: q_range_poly, @@ -282,8 +283,8 @@ impl Compiler { domain_8n.coset_fft(&selectors.q_c), domain_8n, ); - let q_4_eval_8n = Evaluations::from_vec_and_domain( - domain_8n.coset_fft(&selectors.q_4), + let q_f_eval_8n = Evaluations::from_vec_and_domain( + domain_8n.coset_fft(&selectors.q_f), domain_8n, ); let q_arith_eval_8n = Evaluations::from_vec_and_domain( @@ -334,7 +335,7 @@ impl Compiler { q_l: (selectors.q_l.clone(), q_l_eval_8n.clone()), q_r: (selectors.q_r.clone(), q_r_eval_8n.clone()), q_o: (selectors.q_o, q_o_eval_8n), - q_4: (selectors.q_4, q_4_eval_8n), + q_f: (selectors.q_f, q_f_eval_8n), q_c: (selectors.q_c.clone(), q_c_eval_8n.clone()), q_arith: (selectors.q_arith, q_arith_eval_8n), }; diff --git a/src/compiler/prover.rs b/src/compiler/prover.rs index 68bf956b..42e665f9 100644 --- a/src/compiler/prover.rs +++ b/src/compiler/prover.rs @@ -254,35 +254,39 @@ impl Prover { // round 1 // convert wires to padded scalars - let mut a_w_scalar = vec![BlsScalar::zero(); size]; - let mut b_w_scalar = vec![BlsScalar::zero(); size]; - let mut c_w_scalar = vec![BlsScalar::zero(); size]; - let mut d_w_scalar = vec![BlsScalar::zero(); size]; - - prover.constraints.iter().enumerate().for_each(|(i, c)| { - a_w_scalar[i] = prover[c.w_a]; - b_w_scalar[i] = prover[c.w_b]; - c_w_scalar[i] = prover[c.w_o]; - d_w_scalar[i] = prover[c.w_d]; - }); - - let a_w_poly = Self::blind_poly(rng, &a_w_scalar, 1, &domain); - let b_w_poly = Self::blind_poly(rng, &b_w_scalar, 1, &domain); - let c_w_poly = Self::blind_poly(rng, &c_w_scalar, 1, &domain); - let d_w_poly = Self::blind_poly(rng, &d_w_scalar, 1, &domain); + let mut a_scalars = vec![BlsScalar::zero(); size]; + let mut b_scalars = vec![BlsScalar::zero(); size]; + let mut c_scalars = vec![BlsScalar::zero(); size]; + let mut d_scalars = vec![BlsScalar::zero(); size]; + + prover + .constraints + .iter() + .enumerate() + .for_each(|(i, constraint)| { + a_scalars[i] = prover[constraint.a]; + b_scalars[i] = prover[constraint.b]; + c_scalars[i] = prover[constraint.c]; + d_scalars[i] = prover[constraint.d]; + }); + + let a_poly = Self::blind_poly(rng, &a_scalars, 1, &domain); + let b_poly = Self::blind_poly(rng, &b_scalars, 1, &domain); + let c_poly = Self::blind_poly(rng, &c_scalars, 1, &domain); + let d_poly = Self::blind_poly(rng, &d_scalars, 1, &domain); // commit to wire polynomials // ([a(x)]_1, [b(x)]_1, [c(x)]_1, [d(x)]_1) - let a_w_poly_commit = self.commit_key.commit(&a_w_poly)?; - let b_w_poly_commit = self.commit_key.commit(&b_w_poly)?; - let c_w_poly_commit = self.commit_key.commit(&c_w_poly)?; - let d_w_poly_commit = self.commit_key.commit(&d_w_poly)?; + let a_comm = self.commit_key.commit(&a_poly)?; + let b_comm = self.commit_key.commit(&b_poly)?; + let c_comm = self.commit_key.commit(&c_poly)?; + let d_comm = self.commit_key.commit(&d_poly)?; // Add wire polynomial commitments to transcript - transcript.append_commitment(b"a_w", &a_w_poly_commit); - transcript.append_commitment(b"b_w", &b_w_poly_commit); - transcript.append_commitment(b"c_w", &c_w_poly_commit); - transcript.append_commitment(b"d_w", &d_w_poly_commit); + transcript.append_commitment(b"a_comm", &a_comm); + transcript.append_commitment(b"b_comm", &b_comm); + transcript.append_commitment(b"c_comm", &c_comm); + transcript.append_commitment(b"d_comm", &d_comm); // round 2 // permutation challenges @@ -297,18 +301,18 @@ impl Prover { &self.prover_key.permutation.s_sigma_4.0, ]; let wires = [ - a_w_scalar.as_slice(), - b_w_scalar.as_slice(), - c_w_scalar.as_slice(), - d_w_scalar.as_slice(), + a_scalars.as_slice(), + b_scalars.as_slice(), + c_scalars.as_slice(), + d_scalars.as_slice(), ]; let permutation = prover .perm .compute_permutation_vec(&domain, wires, &beta, &gamma, sigma); let z_poly = Self::blind_poly(rng, &permutation, 2, &domain); - let z_poly_commit = self.commit_key.commit(&z_poly)?; - transcript.append_commitment(b"z", &z_poly_commit); + let z_comm = self.commit_key.commit(&z_poly)?; + transcript.append_commitment(b"z_comm", &z_comm); // round 3 // compute quotient challenge alpha @@ -327,7 +331,7 @@ impl Prover { let pi_poly = Polynomial::from_coefficients_vec(pi_poly); // compute quotient polynomial - let wires = (&a_w_poly, &b_w_poly, &c_w_poly, &d_w_poly); + let wires = (&a_poly, &b_poly, &c_poly, &d_poly); let args = &( alpha, beta, @@ -352,7 +356,7 @@ impl Prover { let mut t_low_vec = t_poly[0..domain_size].to_vec(); let mut t_mid_vec = t_poly[domain_size..2 * domain_size].to_vec(); let mut t_high_vec = t_poly[2 * domain_size..3 * domain_size].to_vec(); - let mut t_4_vec = t_poly[3 * domain_size..].to_vec(); + let mut t_fourth_vec = t_poly[3 * domain_size..].to_vec(); // select 3 blinding factors for the quotient splitted polynomials let b_10 = BlsScalar::random(&mut *rng); @@ -370,35 +374,35 @@ impl Prover { t_high_vec[0] -= b_11; t_high_vec.push(b_12); - // t_4'(X) - b_12 - t_4_vec[0] -= b_12; + // t_fourth'(X) - b_12 + t_fourth_vec[0] -= b_12; let t_low_poly = Polynomial::from_coefficients_vec(t_low_vec); let t_mid_poly = Polynomial::from_coefficients_vec(t_mid_vec); let t_high_poly = Polynomial::from_coefficients_vec(t_high_vec); - let t_4_poly = Polynomial::from_coefficients_vec(t_4_vec); + let t_fourth_poly = Polynomial::from_coefficients_vec(t_fourth_vec); // commit to split quotient polynomial - let t_low_commit = self.commit_key.commit(&t_low_poly)?; - let t_mid_commit = self.commit_key.commit(&t_mid_poly)?; - let t_high_commit = self.commit_key.commit(&t_high_poly)?; - let t_4_commit = self.commit_key.commit(&t_4_poly)?; + let t_low_comm = self.commit_key.commit(&t_low_poly)?; + let t_mid_comm = self.commit_key.commit(&t_mid_poly)?; + let t_high_comm = self.commit_key.commit(&t_high_poly)?; + let t_fourth_comm = self.commit_key.commit(&t_fourth_poly)?; // add quotient polynomial commitments to transcript - transcript.append_commitment(b"t_low", &t_low_commit); - transcript.append_commitment(b"t_mid", &t_mid_commit); - transcript.append_commitment(b"t_high", &t_high_commit); - transcript.append_commitment(b"t_4", &t_4_commit); + transcript.append_commitment(b"t_low_comm", &t_low_comm); + transcript.append_commitment(b"t_mid_comm", &t_mid_comm); + transcript.append_commitment(b"t_high_comm", &t_high_comm); + transcript.append_commitment(b"t_fourth_comm", &t_fourth_comm); // round 4 // compute evaluation challenge 'z' let z_challenge = transcript.challenge_scalar(b"z_challenge"); // compute opening evaluations - let a_eval = a_w_poly.evaluate(&z_challenge); - let b_eval = b_w_poly.evaluate(&z_challenge); - let c_eval = c_w_poly.evaluate(&z_challenge); - let d_eval = d_w_poly.evaluate(&z_challenge); + let a_eval = a_poly.evaluate(&z_challenge); + let b_eval = b_poly.evaluate(&z_challenge); + let c_eval = c_poly.evaluate(&z_challenge); + let d_eval = d_poly.evaluate(&z_challenge); let s_sigma_1_eval = self .prover_key @@ -433,10 +437,10 @@ impl Prover { transcript.append_scalar(b"z_eval", &z_eval); - // Compute extra evaluations - let a_next_eval = a_w_poly.evaluate(&(z_challenge * domain.group_gen)); - let b_next_eval = b_w_poly.evaluate(&(z_challenge * domain.group_gen)); - let d_next_eval = d_w_poly.evaluate(&(z_challenge * domain.group_gen)); + // Compute shifted evaluations + let a_w_eval = a_poly.evaluate(&(z_challenge * domain.group_gen)); + let b_w_eval = b_poly.evaluate(&(z_challenge * domain.group_gen)); + let d_w_eval = d_poly.evaluate(&(z_challenge * domain.group_gen)); let q_arith_eval = self.prover_key.arithmetic.q_arith.0.evaluate(&z_challenge); @@ -445,9 +449,9 @@ impl Prover { let q_r_eval = self.prover_key.fixed_base.q_r.0.evaluate(&z_challenge); // add extra evaluations to transcript. - transcript.append_scalar(b"a_next_eval", &a_next_eval); - transcript.append_scalar(b"b_next_eval", &b_next_eval); - transcript.append_scalar(b"d_next_eval", &d_next_eval); + transcript.append_scalar(b"a_w_eval", &a_w_eval); + transcript.append_scalar(b"b_w_eval", &b_w_eval); + transcript.append_scalar(b"d_w_eval", &d_w_eval); transcript.append_scalar(b"q_arith_eval", &q_arith_eval); transcript.append_scalar(b"q_c_eval", &q_c_eval); transcript.append_scalar(b"q_l_eval", &q_l_eval); @@ -458,9 +462,9 @@ impl Prover { b_eval, c_eval, d_eval, - a_next_eval, - b_next_eval, - d_next_eval, + a_w_eval, + b_w_eval, + d_w_eval, q_arith_eval, q_c_eval, q_l_eval, @@ -494,7 +498,7 @@ impl Prover { &t_low_poly, &t_mid_poly, &t_high_poly, - &t_4_poly, + &t_fourth_poly, &public_inputs, ); @@ -502,10 +506,10 @@ impl Prover { let aggregate_witness = CommitKey::compute_aggregate_witness( &[ r_poly, - a_w_poly.clone(), - b_w_poly.clone(), - c_w_poly, - d_w_poly.clone(), + a_poly.clone(), + b_poly.clone(), + c_poly, + d_poly.clone(), self.prover_key.permutation.s_sigma_1.0.clone(), self.prover_key.permutation.s_sigma_2.0.clone(), self.prover_key.permutation.s_sigma_3.0.clone(), @@ -520,7 +524,7 @@ impl Prover { // compute the shifted opening proof polynomial 'W_zw(X)' let shifted_aggregate_witness = CommitKey::compute_aggregate_witness( - &[z_poly, a_w_poly, b_w_poly, d_w_poly], + &[z_poly, a_poly, b_poly, d_poly], &(z_challenge * domain.group_gen), &v_w_challenge, ); @@ -528,17 +532,17 @@ impl Prover { self.commit_key.commit(&shifted_aggregate_witness)?; let proof = Proof { - a_comm: a_w_poly_commit, - b_comm: b_w_poly_commit, - c_comm: c_w_poly_commit, - d_comm: d_w_poly_commit, + a_comm, + b_comm, + c_comm, + d_comm, - z_comm: z_poly_commit, + z_comm, - t_low_comm: t_low_commit, - t_mid_comm: t_mid_commit, - t_high_comm: t_high_commit, - t_4_comm: t_4_commit, + t_low_comm, + t_mid_comm, + t_high_comm, + t_fourth_comm, w_z_chall_comm, w_z_chall_w_comm, diff --git a/src/composer.rs b/src/composer.rs index 6a441d5b..45227ed6 100644 --- a/src/composer.rs +++ b/src/composer.rs @@ -103,16 +103,16 @@ impl Composer { fn append_custom_gate_internal(&mut self, constraint: Constraint) { let n = self.constraints.len(); - let w_a = constraint.witness(WiredWitness::A); - let w_b = constraint.witness(WiredWitness::B); - let w_o = constraint.witness(WiredWitness::O); - let w_d = constraint.witness(WiredWitness::D); + let a = constraint.witness(WiredWitness::A); + let b = constraint.witness(WiredWitness::B); + let c = constraint.witness(WiredWitness::C); + let d = constraint.witness(WiredWitness::D); let q_m = *constraint.coeff(Selector::Multiplication); let q_l = *constraint.coeff(Selector::Left); let q_r = *constraint.coeff(Selector::Right); let q_o = *constraint.coeff(Selector::Output); - let q_4 = *constraint.coeff(Selector::Fourth); + let q_f = *constraint.coeff(Selector::Fourth); let q_c = *constraint.coeff(Selector::Constant); let q_arith = *constraint.coeff(Selector::Arithmetic); @@ -127,17 +127,17 @@ impl Composer { q_l, q_r, q_o, - q_4, + q_f, q_c, q_arith, q_range, q_logic, q_fixed_group_add, q_variable_group_add, - w_a, - w_b, - w_o, - w_d, + a, + b, + c, + d, }; self.constraints.push(gate); @@ -148,7 +148,7 @@ impl Composer { self.public_inputs.insert(n, pi); } - self.perm.add_witnesses_to_map(w_a, w_b, w_o, w_d, n); + self.perm.add_witnesses_to_map(a, b, c, d, n); } /// PLONK runtime controller @@ -204,7 +204,7 @@ impl Composer { .a(six) .b(seven) .d(one) - .o(min_twenty); + .c(min_twenty); self.append_gate(constraint); @@ -218,7 +218,7 @@ impl Composer { .output(1) .a(min_twenty) .b(six) - .o(seven); + .c(seven); self.append_gate(constraint); } @@ -345,7 +345,7 @@ impl Composer { let wit_c = self.append_witness(prod_quad_bls); let wit_d = self.append_witness(out_acc); - constraint = constraint.o(wit_c); + constraint = constraint.c(wit_c); self.append_custom_gate(constraint); @@ -494,7 +494,7 @@ impl Composer { .constant(wnaf_round.xy_beta) .a(wnaf_round.acc_x) .b(wnaf_round.acc_y) - .o(wnaf_round.xy_alpha) + .c(wnaf_round.xy_alpha) .d(wnaf_round.accumulated_bit); self.append_custom_gate(constraint) @@ -528,7 +528,7 @@ impl Composer { /// Append a new width-4 gate/constraint. /// /// The constraint added will enforce the following: - /// `q_m · a · b + q_l · a + q_r · b + q_o · o + q_4 · d + q_c + PI = 0`. + /// `q_M · a · b + q_L · a + q_R · b + q_O · o + q_F · d + q_C + PI = 0`. pub fn append_gate(&mut self, constraint: Constraint) { let constraint = Constraint::arithmetic(&constraint); @@ -553,18 +553,18 @@ impl Composer { let qm = s.coeff(Selector::Multiplication); let ql = s.coeff(Selector::Left); let qr = s.coeff(Selector::Right); - let qd = s.coeff(Selector::Fourth); + let qf = s.coeff(Selector::Fourth); let qc = s.coeff(Selector::Constant); let pi = s.coeff(Selector::PublicInput); - let x = qm * a * b + ql * a + qr * b + qd * d + qc + pi; + let x = qm * a * b + ql * a + qr * b + qf * d + qc + pi; let y = s.coeff(Selector::Output); - // Invert is an expensive operation; in most cases, `qo` is going to be + // Invert is an expensive operation; in most cases, `q_O` is going to be // either 1 or -1, so we can optimize these #[allow(dead_code)] - let o = { + let c = { const ONE: BlsScalar = BlsScalar::one(); const MINUS_ONE: BlsScalar = BlsScalar([ 0xfffffffd00000003, @@ -584,7 +584,7 @@ impl Composer { } }; - o.map(|o| self.append_witness(o)) + c.map(|c| self.append_witness(c)) } /// Constrain a scalar into the circuit description and return an allocated @@ -780,7 +780,7 @@ impl Composer { let y_3 = self.append_witness(y_3); // Add the rest of the prepared points into the composer - let constraint = Constraint::new().a(x_1).b(y_1).o(x_2).d(y_2); + let constraint = Constraint::new().a(x_1).b(y_1).c(x_2).d(y_2); let constraint = Constraint::group_add_variable_base(&constraint); self.append_custom_gate(constraint); @@ -806,7 +806,7 @@ impl Composer { .output(-BlsScalar::one()) .a(a) .b(a) - .o(a) + .c(a) .d(zero); self.append_gate(constraint); @@ -956,7 +956,7 @@ impl Composer { .constant(1) .a(bit) .b(value) - .o(f_x); + .c(f_x); self.append_gate(constraint); @@ -1077,7 +1077,7 @@ impl Composer { let idx = i / 4; let witness = match i % 4 { 0 => WiredWitness::D, - 1 => WiredWitness::O, + 1 => WiredWitness::C, 2 => WiredWitness::B, 3 => WiredWitness::A, _ => unreachable!(), @@ -1117,36 +1117,36 @@ impl Composer { /// Evaluate and return `o` by appending a new constraint into the circuit. /// - /// Set `q_o = (-1)` and override the output of the constraint with: - /// `o := q_l · a + q_r · b + q_4 · d + q_c + PI` + /// Set `q_O = (-1)` and override the output of the constraint with: + /// `c := q_L · a + q_R · b + q_F · d + q_C + PI` pub fn gate_add(&mut self, s: Constraint) -> Witness { let s = Constraint::arithmetic(&s).output(-BlsScalar::one()); - let o = self + let c = self .append_evaluated_output(s) .expect("output selector is -1"); - let s = s.o(o); + let s = s.c(c); self.append_gate(s); - o + c } - /// Evaluate and return `o` by appending a new constraint into the circuit. + /// Evaluate and return `c` by appending a new constraint into the circuit. /// - /// Set `q_o = (-1)` and override the output of the constraint with: - /// `o := q_m · a · b + q_4 · d + q_c + PI` + /// Set `q_O = (-1)` and override the output of the constraint with: + /// `c := q_M · a · b + q_F · d + q_C + PI` pub fn gate_mul(&mut self, s: Constraint) -> Witness { let s = Constraint::arithmetic(&s).output(-BlsScalar::one()); - let o = self + let c = self .append_evaluated_output(s) .expect("output selector is -1"); - let s = s.o(o); + let s = s.c(c); self.append_gate(s); - o + c } /// Prove a circuit with a composer initialized with dummy gates diff --git a/src/composer/compress.rs b/src/composer/compress.rs index 58030296..e442a305 100644 --- a/src/composer/compress.rs +++ b/src/composer/compress.rs @@ -19,10 +19,10 @@ mod hades; )] pub struct CompressedConstraint { pub polynomial: usize, - pub w_a: usize, - pub w_b: usize, - pub w_o: usize, - pub w_d: usize, + pub a: usize, + pub b: usize, + pub c: usize, + pub d: usize, } #[derive( @@ -33,7 +33,7 @@ pub struct CompressedPolynomial { pub q_l: usize, pub q_r: usize, pub q_o: usize, - pub q_4: usize, + pub q_f: usize, pub q_c: usize, pub q_arith: usize, pub q_range: usize, @@ -99,17 +99,17 @@ impl CompressedCircuit { q_l, q_r, q_o, - q_4, + q_f, q_c, q_arith, q_range, q_logic, q_fixed_group_add, q_variable_group_add, - w_a, - w_b, - w_o, - w_d, + a, + b, + c, + d, }| { let len = scalars.len(); let q_m = *scalars.entry(q_m).or_insert(len); @@ -120,7 +120,7 @@ impl CompressedCircuit { let len = scalars.len(); let q_o = *scalars.entry(q_o).or_insert(len); let len = scalars.len(); - let q_4 = *scalars.entry(q_4).or_insert(len); + let q_f = *scalars.entry(q_f).or_insert(len); let len = scalars.len(); let q_c = *scalars.entry(q_c).or_insert(len); let len = scalars.len(); @@ -140,7 +140,7 @@ impl CompressedCircuit { q_l, q_r, q_o, - q_4, + q_f, q_c, q_arith, q_range, @@ -155,10 +155,10 @@ impl CompressedCircuit { CompressedConstraint { polynomial, - w_a: w_a.index(), - w_b: w_b.index(), - w_o: w_o.index(), - w_d: w_d.index(), + a: a.index(), + b: b.index(), + c: c.index(), + d: d.index(), } }, ) @@ -241,10 +241,10 @@ impl CompressedCircuit { i, CompressedConstraint { polynomial, - w_a, - w_b, - w_o, - w_d, + a, + b, + c, + d, }, ) in constraints.into_iter().enumerate() { @@ -253,7 +253,7 @@ impl CompressedCircuit { q_l, q_r, q_o, - q_4, + q_f, q_c, q_arith, q_range, @@ -281,8 +281,8 @@ impl CompressedCircuit { .get(q_o) .copied() .ok_or(Error::InvalidCompressedCircuit)?; - let q_4 = scalars - .get(q_4) + let q_f = scalars + .get(q_f) .copied() .ok_or(Error::InvalidCompressedCircuit)?; let q_c = scalars @@ -310,27 +310,27 @@ impl CompressedCircuit { .copied() .ok_or(Error::InvalidCompressedCircuit)?; - let w_a = Witness::new(w_a); - let w_b = Witness::new(w_b); - let w_o = Witness::new(w_o); - let w_d = Witness::new(w_d); + let a = Witness::new(a); + let b = Witness::new(b); + let c = Witness::new(c); + let d = Witness::new(d); let mut constraint = Constraint::default() .set(Selector::Multiplication, q_m) .set(Selector::Left, q_l) .set(Selector::Right, q_r) .set(Selector::Output, q_o) - .set(Selector::Fourth, q_4) + .set(Selector::Fourth, q_f) .set(Selector::Constant, q_c) .set(Selector::Arithmetic, q_arith) .set(Selector::Range, q_range) .set(Selector::Logic, q_logic) .set(Selector::GroupAddFixedBase, q_fixed_group_add) .set(Selector::GroupAddVariableBase, q_variable_group_add) - .a(w_a) - .b(w_b) - .o(w_o) - .d(w_d); + .a(a) + .b(b) + .c(c) + .d(d); if let Some(idx) = public_inputs.get(pi) { if idx == &i { diff --git a/src/composer/constraint_system/constraint.rs b/src/composer/constraint_system/constraint.rs index 11b6e23f..4f8bb961 100644 --- a/src/composer/constraint_system/constraint.rs +++ b/src/composer/constraint_system/constraint.rs @@ -10,19 +10,19 @@ use dusk_bls12_381::BlsScalar; /// Selectors used to address a coefficient inside of a [`Constraint`] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum Selector { - /// Multiplication coefficient `q_m` + /// Multiplication coefficient `q_M` Multiplication = 0x00, - /// Left coefficient `q_l` + /// Left coefficient `q_L` Left = 0x01, - /// Right coefficient `q_r` + /// Right coefficient `q_R` Right = 0x02, - /// Output coefficient `q_o` + /// Output coefficient `q_O` Output = 0x03, - /// Fourth advice coefficient `q_4` + /// Fourth advice coefficient `q_F` Fourth = 0x04, - /// Constant expression `q_c` + /// Constant expression `q_C` Constant = 0x05, - /// Public input `pi` + /// Public input `PI` PublicInput = 0x06, /// Arithmetic coefficient (internal use) @@ -44,8 +44,8 @@ pub(crate) enum WiredWitness { A = 0x00, /// `B` witness B = 0x01, - /// `O` witness - O = 0x02, + /// `C` witness + C = 0x02, /// `D` witness D = 0x03, } @@ -196,9 +196,9 @@ impl Constraint { self } - /// Set witness `o` wired to `qO` - pub fn o(mut self, w: Witness) -> Self { - self.set_witness(WiredWitness::O, w); + /// Set witness `c` wired to `qO` + pub fn c(mut self, w: Witness) -> Self { + self.set_witness(WiredWitness::C, w); self } diff --git a/src/composer/gate.rs b/src/composer/gate.rs index 31d6dab6..a47069e2 100644 --- a/src/composer/gate.rs +++ b/src/composer/gate.rs @@ -21,7 +21,7 @@ pub struct Gate { /// Output wire selector pub(crate) q_o: BlsScalar, /// Fourth wire selector - pub(crate) q_4: BlsScalar, + pub(crate) q_f: BlsScalar, /// Constant wire selector pub(crate) q_c: BlsScalar, /// Arithmetic wire selector @@ -36,11 +36,11 @@ pub struct Gate { pub(crate) q_variable_group_add: BlsScalar, /// Left wire witness. - pub(crate) w_a: Witness, + pub(crate) a: Witness, /// Right wire witness. - pub(crate) w_b: Witness, + pub(crate) b: Witness, /// Output wire witness. - pub(crate) w_o: Witness, + pub(crate) c: Witness, /// Fourth wire witness. - pub(crate) w_d: Witness, + pub(crate) d: Witness, } diff --git a/src/composer/permutation.rs b/src/composer/permutation.rs index 4db92efb..f5494c26 100644 --- a/src/composer/permutation.rs +++ b/src/composer/permutation.rs @@ -222,8 +222,8 @@ impl Permutation { // Constants defining cosets H, k1H, k2H, etc let ks = vec![BlsScalar::one(), K1, K2, K3]; - // Transpose wires and sigma values to get "rows" in the form [a_w_i, - // b_w_i, c_w_i, d_w_i] where each row contains the wire and sigma + // Transpose wires and sigma values to get "rows" in the form [a_i, + // b_i, c_i, d_i] where each row contains the wire and sigma // values for a single gate let gatewise_wires = izip!(wires[0], wires[1], wires[2], wires[3]) .map(|(w0, w1, w2, w3)| vec![w0, w1, w2, w3]); @@ -309,10 +309,10 @@ mod test { #[allow(dead_code)] fn compute_fast_permutation_poly( domain: &EvaluationDomain, - a_w: &[BlsScalar], - b_w: &[BlsScalar], - c_w: &[BlsScalar], - d_w: &[BlsScalar], + a: &[BlsScalar], + b: &[BlsScalar], + c: &[BlsScalar], + d: &[BlsScalar], beta: &BlsScalar, gamma: &BlsScalar, (s_sigma_1_poly, s_sigma_2_poly, s_sigma_3_poly, s_sigma_4_poly): ( @@ -356,24 +356,24 @@ mod test { common_roots.iter().map(|x| x * K3).collect(); // Compute left_wire + gamma - let a_w_gamma: Vec<_> = a_w.iter().map(|a_w| a_w + gamma).collect(); + let a_gamma: Vec<_> = a.iter().map(|a| a + gamma).collect(); // Compute right_wire + gamma - let b_w_gamma: Vec<_> = b_w.iter().map(|b_w| b_w + gamma).collect(); + let b_gamma: Vec<_> = b.iter().map(|b| b + gamma).collect(); // Compute out_wire + gamma - let c_w_gamma: Vec<_> = c_w.iter().map(|c_w| c_w + gamma).collect(); + let c_gamma: Vec<_> = c.iter().map(|c| c + gamma).collect(); // Compute fourth_wire + gamma - let d_w_gamma: Vec<_> = d_w.iter().map(|d_w| d_w + gamma).collect(); + let d_gamma: Vec<_> = d.iter().map(|d| d + gamma).collect(); // Compute 6 accumulator components // Parallelizable let accumulator_components_without_l1: Vec<_> = izip!( - a_w_gamma, - b_w_gamma, - c_w_gamma, - d_w_gamma, + a_gamma, + b_gamma, + c_gamma, + d_gamma, common_roots, beta_roots_k1, beta_roots_k2, @@ -385,10 +385,10 @@ mod test { ) .map( |( - a_w_gamma, - b_w_gamma, - c_w_gamma, - d_w_gamma, + a_gamma, + b_gamma, + c_gamma, + d_gamma, beta_root, beta_root_k1, beta_root_k2, @@ -399,28 +399,28 @@ mod test { beta_s_sigma_4, )| { // w_j + beta * root^j-1 + gamma - let ac1 = a_w_gamma + beta_root; + let ac1 = a_gamma + beta_root; // w_{n+j} + beta * K1 * root^j-1 + gamma - let ac2 = b_w_gamma + beta_root_k1; + let ac2 = b_gamma + beta_root_k1; // w_{2n+j} + beta * K2 * root^j-1 + gamma - let ac3 = c_w_gamma + beta_root_k2; + let ac3 = c_gamma + beta_root_k2; // w_{3n+j} + beta * K3 * root^j-1 + gamma - let ac4 = d_w_gamma + beta_root_k3; + let ac4 = d_gamma + beta_root_k3; // 1 / w_j + beta * sigma(j) + gamma - let ac5 = (a_w_gamma + beta_s_sigma_1).invert().unwrap(); + let ac5 = (a_gamma + beta_s_sigma_1).invert().unwrap(); // 1 / w_{n+j} + beta * sigma(n+j) + gamma - let ac6 = (b_w_gamma + beta_s_sigma_2).invert().unwrap(); + let ac6 = (b_gamma + beta_s_sigma_2).invert().unwrap(); // 1 / w_{2n+j} + beta * sigma(2n+j) + gamma - let ac7 = (c_w_gamma + beta_s_sigma_3).invert().unwrap(); + let ac7 = (c_gamma + beta_s_sigma_3).invert().unwrap(); // 1 / w_{3n+j} + beta * sigma(3n+j) + gamma - let ac8 = (d_w_gamma + beta_s_sigma_4).invert().unwrap(); + let ac8 = (d_gamma + beta_s_sigma_4).invert().unwrap(); [ac1, ac2, ac3, ac4, ac5, ac6, ac7, ac8] }, @@ -470,10 +470,10 @@ mod test { fn compute_slow_permutation_poly( domain: &EvaluationDomain, - a_w: I, - b_w: I, - c_w: I, - d_w: I, + a: I, + b: I, + c: I, + d: I, beta: &BlsScalar, gamma: &BlsScalar, (s_sigma_1_poly, s_sigma_2_poly, s_sigma_3_poly, s_sigma_4_poly): ( @@ -516,16 +516,16 @@ mod test { let beta_roots_k3_iter = domain.elements().map(|root| K3 * beta * root); // Compute left_wire + gamma - let a_w_gamma: Vec<_> = a_w.map(|w| w + gamma).collect(); + let a_gamma: Vec<_> = a.map(|w| w + gamma).collect(); // Compute right_wire + gamma - let b_w_gamma: Vec<_> = b_w.map(|w| w + gamma).collect(); + let b_gamma: Vec<_> = b.map(|w| w + gamma).collect(); // Compute out_wire + gamma - let c_w_gamma: Vec<_> = c_w.map(|w| w + gamma).collect(); + let c_gamma: Vec<_> = c.map(|w| w + gamma).collect(); // Compute fourth_wire + gamma - let d_w_gamma: Vec<_> = d_w.map(|w| w + gamma).collect(); + let d_gamma: Vec<_> = d.map(|w| w + gamma).collect(); let mut numerator_partial_components: Vec = Vec::with_capacity(n); @@ -542,35 +542,35 @@ mod test { // Compute numerator coefficients for ( - a_w_gamma, - b_w_gamma, - c_w_gamma, - d_w_gamma, + a_gamma, + b_gamma, + c_gamma, + d_gamma, beta_root, beta_root_k1, beta_root_k2, beta_root_k3, ) in izip!( - a_w_gamma.iter(), - b_w_gamma.iter(), - c_w_gamma.iter(), - d_w_gamma.iter(), + a_gamma.iter(), + b_gamma.iter(), + c_gamma.iter(), + d_gamma.iter(), beta_roots_iter, beta_roots_k1_iter, beta_roots_k2_iter, beta_roots_k3_iter, ) { - // (a_w + beta * root + gamma) - let prod_a = beta_root + a_w_gamma; + // (a + beta * root + gamma) + let prod_a = beta_root + a_gamma; - // (b_w + beta * root * k_1 + gamma) - let prod_b = beta_root_k1 + b_w_gamma; + // (b + beta * root * k_1 + gamma) + let prod_b = beta_root_k1 + b_gamma; - // (c_w + beta * root * k_2 + gamma) - let prod_c = beta_root_k2 + c_w_gamma; + // (c + beta * root * k_2 + gamma) + let prod_c = beta_root_k2 + c_gamma; - // (d_w + beta * root * k_3 + gamma) - let prod_d = beta_root_k3 + d_w_gamma; + // (d + beta * root * k_3 + gamma) + let prod_d = beta_root_k3 + d_gamma; let mut prod = prod_a * prod_b * prod_c * prod_d; @@ -583,35 +583,35 @@ mod test { // Compute denominator coefficients for ( - a_w_gamma, - b_w_gamma, - c_w_gamma, - d_w_gamma, + a_gamma, + b_gamma, + c_gamma, + d_gamma, beta_s_sigma_1, beta_s_sigma_2, beta_s_sigma_3, beta_s_sigma_4, ) in izip!( - a_w_gamma, - b_w_gamma, - c_w_gamma, - d_w_gamma, + a_gamma, + b_gamma, + c_gamma, + d_gamma, beta_s_sigma_1_iter, beta_s_sigma_2_iter, beta_s_sigma_3_iter, beta_s_sigma_4_iter, ) { - // (a_w + beta * s_sigma_1 + gamma) - let prod_a = beta_s_sigma_1 + a_w_gamma; + // (a + beta * s_sigma_1 + gamma) + let prod_a = beta_s_sigma_1 + a_gamma; - // (b_w + beta * s_sigma_2 + gamma) - let prod_b = beta_s_sigma_2 + b_w_gamma; + // (b + beta * s_sigma_2 + gamma) + let prod_b = beta_s_sigma_2 + b_gamma; - // (c_w + beta * s_sigma_3 + gamma) - let prod_c = beta_s_sigma_3 + c_w_gamma; + // (c + beta * s_sigma_3 + gamma) + let prod_c = beta_s_sigma_3 + c_gamma; - // (d_w + beta * s_sigma_4 + gamma) - let prod_d = beta_s_sigma_4 + d_w_gamma; + // (d + beta * s_sigma_4 + gamma) + let prod_d = beta_s_sigma_4 + d_gamma; let mut prod = prod_a * prod_b * prod_c * prod_d; @@ -797,25 +797,25 @@ mod test { assert_eq!(encoded_s_sigma_4[2], w_cubed * K3); assert_eq!(encoded_s_sigma_4[3], K3); - let a_w = vec![ + let a = vec![ BlsScalar::from(2), BlsScalar::from(2), BlsScalar::from(2), BlsScalar::from(2), ]; - let b_w = vec![ + let b = vec![ BlsScalar::from(2), BlsScalar::one(), BlsScalar::one(), BlsScalar::one(), ]; - let c_w = vec![ + let c = vec![ BlsScalar::one(), BlsScalar::one(), BlsScalar::one(), BlsScalar::one(), ]; - let d_w = vec![ + let d = vec![ BlsScalar::one(), BlsScalar::one(), BlsScalar::one(), @@ -826,10 +826,10 @@ mod test { num_wire_mappings, perm, &domain, - a_w, - b_w, - c_w, - d_w, + a, + b, + c, + d, ); } @@ -953,19 +953,19 @@ mod test { perm.add_witnesses_to_map(var_one, var_two, var_three, var_four, 0); perm.add_witnesses_to_map(var_three, var_two, var_one, var_four, 1); - let a_w: Vec<_> = vec![BlsScalar::one(), BlsScalar::from(3)]; - let b_w: Vec<_> = vec![BlsScalar::from(2), BlsScalar::from(2)]; - let c_w: Vec<_> = vec![BlsScalar::from(3), BlsScalar::one()]; - let d_w: Vec<_> = vec![BlsScalar::one(), BlsScalar::one()]; + let a: Vec<_> = vec![BlsScalar::one(), BlsScalar::from(3)]; + let b: Vec<_> = vec![BlsScalar::from(2), BlsScalar::from(2)]; + let c: Vec<_> = vec![BlsScalar::from(3), BlsScalar::one()]; + let d: Vec<_> = vec![BlsScalar::one(), BlsScalar::one()]; test_correct_permutation_poly( num_wire_mappings, perm, &domain, - a_w, - b_w, - c_w, - d_w, + a, + b, + c, + d, ); } @@ -981,10 +981,10 @@ mod test { n: usize, mut perm: Permutation, domain: &EvaluationDomain, - a_w: Vec, - b_w: Vec, - c_w: Vec, - d_w: Vec, + a: Vec, + b: Vec, + c: Vec, + d: Vec, ) { // 0. Generate beta and gamma challenges // @@ -998,10 +998,10 @@ mod test { let (z_vec, numerator_components, denominator_components) = compute_slow_permutation_poly( domain, - a_w.clone().into_iter(), - b_w.clone().into_iter(), - c_w.clone().into_iter(), - d_w.clone().into_iter(), + a.clone().into_iter(), + b.clone().into_iter(), + c.clone().into_iter(), + d.clone().into_iter(), &beta, &gamma, ( @@ -1014,10 +1014,10 @@ mod test { let fast_z_vec = compute_fast_permutation_poly( domain, - &a_w, - &b_w, - &c_w, - &d_w, + &a, + &b, + &c, + &d, &beta, &gamma, ( diff --git a/src/debugger.rs b/src/debugger.rs index 5131e35d..c426cc33 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -80,89 +80,90 @@ impl Debugger { EncodableWitness::new(id, None, value, source) }); - let constraints = - self.constraints - .iter() - .enumerate() - .map(|(id, (source, c))| { - let source = source.clone(); - - let qm = c.coeff(Selector::Multiplication); - let ql = c.coeff(Selector::Left); - let qr = c.coeff(Selector::Right); - let qd = c.coeff(Selector::Fourth); - let qc = c.coeff(Selector::Constant); - let qo = c.coeff(Selector::Output); - let pi = c.coeff(Selector::PublicInput); - let qarith = c.coeff(Selector::Arithmetic); - let qlogic = c.coeff(Selector::Logic); - let qrange = c.coeff(Selector::Range); - let qgroup_variable = - c.coeff(Selector::GroupAddVariableBase); - let qfixed_add = c.coeff(Selector::GroupAddFixedBase); - - let witnesses = WiredWitnesses { - a: c.witness(WiredWitness::A).index(), - b: c.witness(WiredWitness::B).index(), - d: c.witness(WiredWitness::D).index(), - o: c.witness(WiredWitness::O).index(), - }; - - let wa = self - .witnesses - .get(witnesses.a) - .map(|(_, _, v)| *v) - .unwrap_or_default(); - - let wb = self - .witnesses - .get(witnesses.b) - .map(|(_, _, v)| *v) - .unwrap_or_default(); - - let wd = self - .witnesses - .get(witnesses.d) - .map(|(_, _, v)| *v) - .unwrap_or_default(); - - let wo = self - .witnesses - .get(witnesses.o) - .map(|(_, _, v)| *v) - .unwrap_or_default(); - - // TODO check arith, range, logic & ecc wires - let evaluation = qm * wa * wb - + ql * wa - + qr * wb - + qd * wd - + qo * wo - + qc - + pi; - - let evaluation = evaluation == BlsScalar::zero(); - - let selectors = Selectors { - qm: qm.to_bytes().into(), - ql: ql.to_bytes().into(), - qr: qr.to_bytes().into(), - qd: qd.to_bytes().into(), - qc: qc.to_bytes().into(), - qo: qo.to_bytes().into(), - pi: pi.to_bytes().into(), - qarith: qarith.to_bytes().into(), - qlogic: qlogic.to_bytes().into(), - qrange: qrange.to_bytes().into(), - qgroup_variable: qgroup_variable.to_bytes().into(), - qfixed_add: qfixed_add.to_bytes().into(), - }; - - let polynomial = - Polynomial::new(selectors, witnesses, evaluation); - - EncodableConstraint::new(id, polynomial, source) - }); + let constraints = self.constraints.iter().enumerate().map( + |(id, (source, constraint))| { + let source = source.clone(); + + let qm = constraint.coeff(Selector::Multiplication); + let ql = constraint.coeff(Selector::Left); + let qr = constraint.coeff(Selector::Right); + let qo = constraint.coeff(Selector::Output); + let qf = constraint.coeff(Selector::Fourth); + let qc = constraint.coeff(Selector::Constant); + let pi = constraint.coeff(Selector::PublicInput); + let qarith = constraint.coeff(Selector::Arithmetic); + let qlogic = constraint.coeff(Selector::Logic); + let qrange = constraint.coeff(Selector::Range); + let qgroup_variable = + constraint.coeff(Selector::GroupAddVariableBase); + let qfixed_add = constraint.coeff(Selector::GroupAddFixedBase); + + let witnesses = WiredWitnesses { + a: constraint.witness(WiredWitness::A).index(), + b: constraint.witness(WiredWitness::B).index(), + // TODO: change by 'c' in debugger crate + o: constraint.witness(WiredWitness::C).index(), + d: constraint.witness(WiredWitness::D).index(), + }; + + let wa = self + .witnesses + .get(witnesses.a) + .map(|(_, _, v)| *v) + .unwrap_or_default(); + + let wb = self + .witnesses + .get(witnesses.b) + .map(|(_, _, v)| *v) + .unwrap_or_default(); + + let wc = self + .witnesses + // TODO: change by 'c' in debugger crate + .get(witnesses.o) + .map(|(_, _, v)| *v) + .unwrap_or_default(); + + let wd = self + .witnesses + .get(witnesses.d) + .map(|(_, _, v)| *v) + .unwrap_or_default(); + + // TODO check arith, range, logic & ecc wires + let evaluation = qm * wa * wb + + ql * wa + + qr * wb + + qo * wc + + qf * wd + + qc + + pi; + + let evaluation = evaluation == BlsScalar::zero(); + + let selectors = Selectors { + qm: qm.to_bytes().into(), + ql: ql.to_bytes().into(), + qr: qr.to_bytes().into(), + qo: qo.to_bytes().into(), + // TODO: change by 'qf' in debugger crate + qd: qf.to_bytes().into(), + qc: qc.to_bytes().into(), + pi: pi.to_bytes().into(), + qarith: qarith.to_bytes().into(), + qlogic: qlogic.to_bytes().into(), + qrange: qrange.to_bytes().into(), + qgroup_variable: qgroup_variable.to_bytes().into(), + qfixed_add: qfixed_add.to_bytes().into(), + }; + + let polynomial = + Polynomial::new(selectors, witnesses, evaluation); + + EncodableConstraint::new(id, polynomial, source) + }, + ); if let Err(e) = Config::load() .and_then(|config| { diff --git a/src/proof_system/linearization_poly.rs b/src/proof_system/linearization_poly.rs index 72d0da26..7d095a35 100644 --- a/src/proof_system/linearization_poly.rs +++ b/src/proof_system/linearization_poly.rs @@ -45,14 +45,14 @@ pub(crate) struct ProofEvaluations { pub(crate) d_eval: BlsScalar, // #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) a_next_eval: BlsScalar, + pub(crate) a_w_eval: BlsScalar, // #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) b_next_eval: BlsScalar, + pub(crate) b_w_eval: BlsScalar, // Evaluation of the witness polynomial for the fourth wire at `z * root of // unity` #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) d_next_eval: BlsScalar, + pub(crate) d_w_eval: BlsScalar, // Evaluation of the arithmetic selector polynomial at `z` #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub(crate) q_arith_eval: BlsScalar, @@ -96,9 +96,9 @@ impl Serializable<{ 15 * BlsScalar::SIZE }> for ProofEvaluations { writer.write(&self.b_eval.to_bytes()); writer.write(&self.c_eval.to_bytes()); writer.write(&self.d_eval.to_bytes()); - writer.write(&self.a_next_eval.to_bytes()); - writer.write(&self.b_next_eval.to_bytes()); - writer.write(&self.d_next_eval.to_bytes()); + writer.write(&self.a_w_eval.to_bytes()); + writer.write(&self.b_w_eval.to_bytes()); + writer.write(&self.d_w_eval.to_bytes()); writer.write(&self.q_arith_eval.to_bytes()); writer.write(&self.q_c_eval.to_bytes()); writer.write(&self.q_l_eval.to_bytes()); @@ -119,9 +119,9 @@ impl Serializable<{ 15 * BlsScalar::SIZE }> for ProofEvaluations { let b_eval = BlsScalar::from_reader(&mut buffer)?; let c_eval = BlsScalar::from_reader(&mut buffer)?; let d_eval = BlsScalar::from_reader(&mut buffer)?; - let a_next_eval = BlsScalar::from_reader(&mut buffer)?; - let b_next_eval = BlsScalar::from_reader(&mut buffer)?; - let d_next_eval = BlsScalar::from_reader(&mut buffer)?; + let a_w_eval = BlsScalar::from_reader(&mut buffer)?; + let b_w_eval = BlsScalar::from_reader(&mut buffer)?; + let d_w_eval = BlsScalar::from_reader(&mut buffer)?; let q_arith_eval = BlsScalar::from_reader(&mut buffer)?; let q_c_eval = BlsScalar::from_reader(&mut buffer)?; let q_l_eval = BlsScalar::from_reader(&mut buffer)?; @@ -136,9 +136,9 @@ impl Serializable<{ 15 * BlsScalar::SIZE }> for ProofEvaluations { b_eval, c_eval, d_eval, - a_next_eval, - b_next_eval, - d_next_eval, + a_w_eval, + b_w_eval, + d_w_eval, q_arith_eval, q_c_eval, q_l_eval, @@ -183,7 +183,7 @@ pub(crate) fn compute( t_low_poly: &Polynomial, t_mid_poly: &Polynomial, t_high_poly: &Polynomial, - t_4_poly: &Polynomial, + t_fourth_poly: &Polynomial, pub_inputs: &[BlsScalar], ) -> Polynomial { let f_1 = compute_circuit_satisfiability( @@ -229,7 +229,7 @@ pub(crate) fn compute( let a = t_low_poly; let b = t_mid_poly * &z_n; let c = t_high_poly * &z_two_n; - let d = t_4_poly * &z_three_n; + let d = t_fourth_poly * &z_three_n; let abc = &(a + &b) + &c; let quot = &abc + &d; diff --git a/src/proof_system/preprocess.rs b/src/proof_system/preprocess.rs index 91560f80..72c8a34c 100644 --- a/src/proof_system/preprocess.rs +++ b/src/proof_system/preprocess.rs @@ -15,12 +15,9 @@ pub(crate) struct Polynomials { pub(crate) q_l: Polynomial, pub(crate) q_r: Polynomial, pub(crate) q_o: Polynomial, + pub(crate) q_f: Polynomial, // for 3-input gates pub(crate) q_c: Polynomial, - // additional selector for 3-input gates added for efficiency of - // implementation - pub(crate) q_4: Polynomial, - // additional selectors for different kinds of circuits added for // efficiency of implementation pub(crate) q_arith: Polynomial, // arithmetic circuits @@ -33,5 +30,5 @@ pub(crate) struct Polynomials { pub(crate) s_sigma_1: Polynomial, pub(crate) s_sigma_2: Polynomial, pub(crate) s_sigma_3: Polynomial, - pub(crate) s_sigma_4: Polynomial, // for q_4 + pub(crate) s_sigma_4: Polynomial, // for q_F } diff --git a/src/proof_system/proof.rs b/src/proof_system/proof.rs index 10111aa8..e434eb28 100644 --- a/src/proof_system/proof.rs +++ b/src/proof_system/proof.rs @@ -74,7 +74,7 @@ pub struct Proof { pub(crate) t_high_comm: Commitment, /// Commitment to the quotient polynomial. #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub(crate) t_4_comm: Commitment, + pub(crate) t_fourth_comm: Commitment, /// Commitment to the opening polynomial. #[cfg_attr(feature = "rkyv-impl", omit_bounds)] @@ -105,7 +105,7 @@ impl CheckBytes for ArchivedProof { check_field(&(*value).t_low_comm, context, "t_low_comm")?; check_field(&(*value).t_mid_comm, context, "t_mid_comm")?; check_field(&(*value).t_high_comm, context, "t_high_comm")?; - check_field(&(*value).t_4_comm, context, "t_4_comm")?; + check_field(&(*value).t_fourth_comm, context, "t_fourth_comm")?; check_field(&(*value).w_z_chall_comm, context, "w_z_chall_comm")?; check_field(&(*value).w_z_chall_w_comm, context, "w_z_chall_w_comm")?; @@ -135,7 +135,7 @@ impl Serializable<{ 11 * Commitment::SIZE + ProofEvaluations::SIZE }> writer.write(&self.t_low_comm.to_bytes()); writer.write(&self.t_mid_comm.to_bytes()); writer.write(&self.t_high_comm.to_bytes()); - writer.write(&self.t_4_comm.to_bytes()); + writer.write(&self.t_fourth_comm.to_bytes()); writer.write(&self.w_z_chall_comm.to_bytes()); writer.write(&self.w_z_chall_w_comm.to_bytes()); writer.write(&self.evaluations.to_bytes()); @@ -154,7 +154,7 @@ impl Serializable<{ 11 * Commitment::SIZE + ProofEvaluations::SIZE }> let t_low_comm = Commitment::from_reader(&mut buffer)?; let t_mid_comm = Commitment::from_reader(&mut buffer)?; let t_high_comm = Commitment::from_reader(&mut buffer)?; - let t_4_comm = Commitment::from_reader(&mut buffer)?; + let t_fourth_comm = Commitment::from_reader(&mut buffer)?; let w_z_chall_comm = Commitment::from_reader(&mut buffer)?; let w_z_chall_w_comm = Commitment::from_reader(&mut buffer)?; let evaluations = ProofEvaluations::from_reader(&mut buffer)?; @@ -168,7 +168,7 @@ impl Serializable<{ 11 * Commitment::SIZE + ProofEvaluations::SIZE }> t_low_comm, t_mid_comm, t_high_comm, - t_4_comm, + t_fourth_comm, w_z_chall_comm, w_z_chall_w_comm, evaluations, @@ -219,10 +219,10 @@ pub(crate) mod alloc { // same challenges // // Add commitment to witness polynomials to transcript - transcript.append_commitment(b"a_w", &self.a_comm); - transcript.append_commitment(b"b_w", &self.b_comm); - transcript.append_commitment(b"c_w", &self.c_comm); - transcript.append_commitment(b"d_w", &self.d_comm); + transcript.append_commitment(b"a_comm", &self.a_comm); + transcript.append_commitment(b"b_comm", &self.b_comm); + transcript.append_commitment(b"c_comm", &self.c_comm); + transcript.append_commitment(b"d_comm", &self.d_comm); // Compute beta and gamma challenges let beta = transcript.challenge_scalar(b"beta"); @@ -230,7 +230,7 @@ pub(crate) mod alloc { let gamma = transcript.challenge_scalar(b"gamma"); // Add commitment to permutation polynomial to transcript - transcript.append_commitment(b"z", &self.z_comm); + transcript.append_commitment(b"z_comm", &self.z_comm); // Compute quotient challenge let alpha = transcript.challenge_scalar(b"alpha"); @@ -244,10 +244,10 @@ pub(crate) mod alloc { .challenge_scalar(b"variable base separation challenge"); // Add commitment to quotient polynomial to transcript - transcript.append_commitment(b"t_low", &self.t_low_comm); - transcript.append_commitment(b"t_mid", &self.t_mid_comm); - transcript.append_commitment(b"t_high", &self.t_high_comm); - transcript.append_commitment(b"t_4", &self.t_4_comm); + transcript.append_commitment(b"t_low_comm", &self.t_low_comm); + transcript.append_commitment(b"t_mid_comm", &self.t_mid_comm); + transcript.append_commitment(b"t_high_comm", &self.t_high_comm); + transcript.append_commitment(b"t_fourth_comm", &self.t_fourth_comm); // Compute evaluation challenge z let z_challenge = transcript.challenge_scalar(b"z_challenge"); @@ -273,13 +273,10 @@ pub(crate) mod alloc { transcript.append_scalar(b"z_eval", &self.evaluations.z_eval); - // Add extra evaluations to transcript - transcript - .append_scalar(b"a_next_eval", &self.evaluations.a_next_eval); - transcript - .append_scalar(b"b_next_eval", &self.evaluations.b_next_eval); - transcript - .append_scalar(b"d_next_eval", &self.evaluations.d_next_eval); + // Add extra shifted evaluations to transcript + transcript.append_scalar(b"a_w_eval", &self.evaluations.a_w_eval); + transcript.append_scalar(b"b_w_eval", &self.evaluations.b_w_eval); + transcript.append_scalar(b"d_w_eval", &self.evaluations.d_w_eval); transcript .append_scalar(b"q_arith_eval", &self.evaluations.q_arith_eval); transcript.append_scalar(b"q_c_eval", &self.evaluations.q_c_eval); @@ -290,8 +287,10 @@ pub(crate) mod alloc { let v_w_challenge = transcript.challenge_scalar(b"v_w_challenge"); // Add commitment to openings to transcript - transcript.append_commitment(b"w_z", &self.w_z_chall_comm); - transcript.append_commitment(b"w_z_w", &self.w_z_chall_w_comm); + transcript + .append_commitment(b"w_z_chall_comm", &self.w_z_chall_comm); + transcript + .append_commitment(b"w_z_chall_w_comm", &self.w_z_chall_w_comm); // Compute the challenge 'u' let u_challenge = transcript.challenge_scalar(b"u_challenge"); @@ -410,9 +409,9 @@ pub(crate) mod alloc { self.evaluations.s_sigma_1_eval, self.evaluations.s_sigma_2_eval, self.evaluations.s_sigma_3_eval, - self.evaluations.a_next_eval, - self.evaluations.b_next_eval, - self.evaluations.d_next_eval, + self.evaluations.a_w_eval, + self.evaluations.b_w_eval, + self.evaluations.d_w_eval, ]; // Compute '[E]_1' = (-r_0 + (v)a + (v^2)b + (v^3)c + (v^4)d + @@ -550,7 +549,7 @@ pub(crate) mod alloc { points.push(self.t_high_comm.0); scalars.push(z_three_n); - points.push(self.t_4_comm.0); + points.push(self.t_fourth_comm.0); Commitment::from(msm_variable_base(&points, &scalars)) } @@ -639,7 +638,7 @@ mod proof_tests { t_low_comm: Commitment::default(), t_mid_comm: Commitment::default(), t_high_comm: Commitment::default(), - t_4_comm: Commitment::default(), + t_fourth_comm: Commitment::default(), w_z_chall_comm: Commitment::default(), w_z_chall_w_comm: Commitment::default(), evaluations: ProofEvaluations { @@ -647,9 +646,9 @@ mod proof_tests { b_eval: BlsScalar::random(&mut OsRng), c_eval: BlsScalar::random(&mut OsRng), d_eval: BlsScalar::random(&mut OsRng), - a_next_eval: BlsScalar::random(&mut OsRng), - b_next_eval: BlsScalar::random(&mut OsRng), - d_next_eval: BlsScalar::random(&mut OsRng), + a_w_eval: BlsScalar::random(&mut OsRng), + b_w_eval: BlsScalar::random(&mut OsRng), + d_w_eval: BlsScalar::random(&mut OsRng), q_arith_eval: BlsScalar::random(&mut OsRng), q_c_eval: BlsScalar::random(&mut OsRng), q_l_eval: BlsScalar::random(&mut OsRng), diff --git a/src/proof_system/quotient_poly.rs b/src/proof_system/quotient_poly.rs index e7eea787..b635c041 100644 --- a/src/proof_system/quotient_poly.rs +++ b/src/proof_system/quotient_poly.rs @@ -20,7 +20,7 @@ pub(crate) fn compute( domain: &EvaluationDomain, prover_key: &ProverKey, z_poly: &Polynomial, - (a_w_poly, b_w_poly, c_w_poly, d_w_poly): ( + (a_poly, b_poly, c_poly, d_poly): ( &Polynomial, &Polynomial, &Polynomial, @@ -50,17 +50,17 @@ pub(crate) fn compute( let mut z_eval_8n = domain_8n.coset_fft(z_poly); - let mut a_w_eval_8n = domain_8n.coset_fft(a_w_poly); - let mut b_w_eval_8n = domain_8n.coset_fft(b_w_poly); - let c_w_eval_8n = domain_8n.coset_fft(c_w_poly); - let mut d_w_eval_8n = domain_8n.coset_fft(d_w_poly); + let mut a_eval_8n = domain_8n.coset_fft(a_poly); + let mut b_eval_8n = domain_8n.coset_fft(b_poly); + let c_eval_8n = domain_8n.coset_fft(c_poly); + let mut d_eval_8n = domain_8n.coset_fft(d_poly); for i in 0..8 { z_eval_8n.push(z_eval_8n[i]); - a_w_eval_8n.push(a_w_eval_8n[i]); - b_w_eval_8n.push(b_w_eval_8n[i]); - // c_w_eval_8n push not required - d_w_eval_8n.push(d_w_eval_8n[i]); + a_eval_8n.push(a_eval_8n[i]); + b_eval_8n.push(b_eval_8n[i]); + // c_eval_8n push not required + d_eval_8n.push(d_eval_8n[i]); } let t_1 = compute_circuit_satisfiability_equation( @@ -72,14 +72,14 @@ pub(crate) fn compute( var_base_challenge, ), prover_key, - (&a_w_eval_8n, &b_w_eval_8n, &c_w_eval_8n, &d_w_eval_8n), + (&a_eval_8n, &b_eval_8n, &c_eval_8n, &d_eval_8n), public_inputs_poly, ); let t_2 = compute_permutation_checks( domain, prover_key, - (&a_w_eval_8n, &b_w_eval_8n, &c_w_eval_8n, &d_w_eval_8n), + (&a_eval_8n, &b_eval_8n, &c_eval_8n, &d_eval_8n), &z_eval_8n, (alpha, beta, gamma), ); @@ -103,7 +103,6 @@ pub(crate) fn compute( Ok(Polynomial::from_coefficients_vec(coset)) } -// Ensures that the circuit is satisfied // Ensures that the circuit is satisfied fn compute_circuit_satisfiability_equation( domain: &EvaluationDomain, @@ -114,7 +113,7 @@ fn compute_circuit_satisfiability_equation( var_base_challenge, ): (&BlsScalar, &BlsScalar, &BlsScalar, &BlsScalar), prover_key: &ProverKey, - (a_w_eval_8n, b_w_eval_8n, c_w_eval_8n, d_w_eval_8n): ( + (a_eval_8n, b_eval_8n, c_eval_8n, d_eval_8n): ( &[BlsScalar], &[BlsScalar], &[BlsScalar], @@ -133,66 +132,67 @@ fn compute_circuit_satisfiability_equation( let t: Vec<_> = range .map(|i| { - let a_w = &a_w_eval_8n[i]; - let b_w = &b_w_eval_8n[i]; - let c_w = &c_w_eval_8n[i]; - let d_w = &d_w_eval_8n[i]; - let a_w_next = &a_w_eval_8n[i + 8]; - let b_w_next = &b_w_eval_8n[i + 8]; - let d_w_next = &d_w_eval_8n[i + 8]; + let a = &a_eval_8n[i]; + let b = &b_eval_8n[i]; + let c = &c_eval_8n[i]; + let d = &d_eval_8n[i]; + let a_w = &a_eval_8n[i + 8]; + let b_w = &b_eval_8n[i + 8]; + let d_w = &d_eval_8n[i + 8]; let pi = &public_eval_8n[i]; - let a = prover_key - .arithmetic - .compute_quotient_i(i, a_w, b_w, c_w, d_w); + let t_arith = + prover_key.arithmetic.compute_quotient_i(i, a, b, c, d); - let b = prover_key.range.compute_quotient_i( + let t_range = prover_key.range.compute_quotient_i( i, range_challenge, - a_w, - b_w, - c_w, + a, + b, + c, + d, d_w, - d_w_next, ); - let c = prover_key.logic.compute_quotient_i( + let t_logic = prover_key.logic.compute_quotient_i( i, logic_challenge, + a, a_w, - a_w_next, + b, b_w, - b_w_next, - c_w, + c, + d, d_w, - d_w_next, ); - let d = prover_key.fixed_base.compute_quotient_i( + let t_fixed = prover_key.fixed_base.compute_quotient_i( i, fixed_base_challenge, + a, a_w, - a_w_next, + b, b_w, - b_w_next, - c_w, + c, + d, d_w, - d_w_next, ); - let e = prover_key.variable_base.compute_quotient_i( + let t_var = prover_key.variable_base.compute_quotient_i( i, var_base_challenge, + a, a_w, - a_w_next, + b, b_w, - b_w_next, - c_w, + c, + d, d_w, - d_w_next, ); - (a + pi) + b + c + d + e + // Multiplication by selectors and challenges + // has already been done + t_arith + t_range + t_logic + t_fixed + t_var + pi }) .collect(); t @@ -201,7 +201,7 @@ fn compute_circuit_satisfiability_equation( fn compute_permutation_checks( domain: &EvaluationDomain, prover_key: &ProverKey, - (a_w_eval_8n, b_w_eval_8n, c_w_eval_8n, d_w_eval_8n): ( + (a_eval_8n, b_eval_8n, c_eval_8n, d_eval_8n): ( &[BlsScalar], &[BlsScalar], &[BlsScalar], @@ -225,10 +225,10 @@ fn compute_permutation_checks( .map(|i| { prover_key.permutation.compute_quotient_i( i, - &a_w_eval_8n[i], - &b_w_eval_8n[i], - &c_w_eval_8n[i], - &d_w_eval_8n[i], + &a_eval_8n[i], + &b_eval_8n[i], + &c_eval_8n[i], + &d_eval_8n[i], &z_eval_8n[i], &z_eval_8n[i + 8], alpha, diff --git a/src/proof_system/widget.rs b/src/proof_system/widget.rs index f1c48846..dda20b16 100644 --- a/src/proof_system/widget.rs +++ b/src/proof_system/widget.rs @@ -91,7 +91,7 @@ impl Serializable<{ 20 * Commitment::SIZE + u64::SIZE }> for VerifierKey { writer.write(&self.arithmetic.q_l.to_bytes()); writer.write(&self.arithmetic.q_r.to_bytes()); writer.write(&self.arithmetic.q_o.to_bytes()); - writer.write(&self.arithmetic.q_4.to_bytes()); + writer.write(&self.arithmetic.q_f.to_bytes()); writer.write(&self.arithmetic.q_c.to_bytes()); writer.write(&self.arithmetic.q_arith.to_bytes()); writer.write(&self.logic.q_logic.to_bytes()); @@ -140,7 +140,7 @@ impl VerifierKey { q_l: Commitment, q_r: Commitment, q_o: Commitment, - q_4: Commitment, + q_f: Commitment, q_c: Commitment, q_arith: Commitment, q_logic: Commitment, @@ -157,7 +157,7 @@ impl VerifierKey { q_l, q_r, q_o, - q_4, + q_f, q_c, q_arith, }; @@ -213,7 +213,7 @@ pub(crate) mod alloc { transcript.append_commitment(b"q_r", &self.arithmetic.q_r); transcript.append_commitment(b"q_o", &self.arithmetic.q_o); transcript.append_commitment(b"q_c", &self.arithmetic.q_c); - transcript.append_commitment(b"q_4", &self.arithmetic.q_4); + transcript.append_commitment(b"q_f", &self.arithmetic.q_f); transcript.append_commitment(b"q_arith", &self.arithmetic.q_arith); transcript.append_commitment(b"q_range", &self.range.q_range); transcript.append_commitment(b"q_logic", &self.logic.q_logic); @@ -286,7 +286,7 @@ pub(crate) mod alloc { /// Returns the size of the ProverKey for serialization. /// /// Note: - /// Duplicate polynomials of the ProverKey (e.g. `q_l`, `q_r` and `q_c`) + /// Duplicate polynomials of the ProverKey (e.g. `q_L`, `q_R` and `q_C`) /// are only counted once. fn serialization_size(&self) -> usize { // Fetch size in bytes of each Polynomial @@ -344,9 +344,9 @@ pub(crate) mod alloc { writer.write(&self.arithmetic.q_o.0.to_var_bytes()); writer.write(&self.arithmetic.q_o.1.to_var_bytes()); - writer.write(&(self.arithmetic.q_4.0.len() as u64).to_bytes()); - writer.write(&self.arithmetic.q_4.0.to_var_bytes()); - writer.write(&self.arithmetic.q_4.1.to_var_bytes()); + writer.write(&(self.arithmetic.q_f.0.len() as u64).to_bytes()); + writer.write(&self.arithmetic.q_f.0.to_var_bytes()); + writer.write(&self.arithmetic.q_f.1.to_var_bytes()); writer.write(&(self.arithmetic.q_c.0.len() as u64).to_bytes()); writer.write(&self.arithmetic.q_c.0.to_var_bytes()); @@ -464,9 +464,9 @@ pub(crate) mod alloc { let q_o_evals = evals_from_reader(&mut buffer)?; let q_o = (q_o_poly, q_o_evals); - let q_4_poly = poly_from_reader(&mut buffer)?; - let q_4_evals = evals_from_reader(&mut buffer)?; - let q_4 = (q_4_poly, q_4_evals); + let q_f_poly = poly_from_reader(&mut buffer)?; + let q_f_evals = evals_from_reader(&mut buffer)?; + let q_f = (q_f_poly, q_f_evals); let q_c_poly = poly_from_reader(&mut buffer)?; let q_c_evals = evals_from_reader(&mut buffer)?; @@ -520,7 +520,7 @@ pub(crate) mod alloc { q_r: q_r.clone(), q_o, q_c: q_c.clone(), - q_4, + q_f, q_arith, }; @@ -604,7 +604,7 @@ mod test { let q_r = rand_poly_eval(n); let q_o = rand_poly_eval(n); let q_c = rand_poly_eval(n); - let q_4 = rand_poly_eval(n); + let q_f = rand_poly_eval(n); let q_arith = rand_poly_eval(n); let q_logic = rand_poly_eval(n); @@ -629,7 +629,7 @@ mod test { q_r: q_r.clone(), q_o, q_c: q_c.clone(), - q_4, + q_f, q_arith, }; @@ -689,7 +689,7 @@ mod test { let q_r = Commitment(G1Affine::generator()); let q_o = Commitment(G1Affine::generator()); let q_c = Commitment(G1Affine::generator()); - let q_4 = Commitment(G1Affine::generator()); + let q_f = Commitment(G1Affine::generator()); let q_arith = Commitment(G1Affine::generator()); let q_range = Commitment(G1Affine::generator()); @@ -710,7 +710,7 @@ mod test { q_r, q_o, q_c, - q_4, + q_f, q_arith, }; diff --git a/src/proof_system/widget/arithmetic/proverkey.rs b/src/proof_system/widget/arithmetic/proverkey.rs index 1a964303..75288834 100644 --- a/src/proof_system/widget/arithmetic/proverkey.rs +++ b/src/proof_system/widget/arithmetic/proverkey.rs @@ -33,7 +33,7 @@ pub(crate) struct ProverKey { #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub q_o: (Polynomial, Evaluations), #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub q_4: (Polynomial, Evaluations), + pub q_f: (Polynomial, Evaluations), #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub q_c: (Polynomial, Evaluations), #[cfg_attr(feature = "rkyv-impl", omit_bounds)] @@ -44,27 +44,27 @@ impl ProverKey { pub(crate) fn compute_quotient_i( &self, index: usize, - a_w_i: &BlsScalar, - b_w_i: &BlsScalar, - c_w_i: &BlsScalar, - d_w_i: &BlsScalar, + a_i: &BlsScalar, + b_i: &BlsScalar, + c_i: &BlsScalar, + d_i: &BlsScalar, ) -> BlsScalar { let q_m_i = &self.q_m.1[index]; let q_l_i = &self.q_l.1[index]; let q_r_i = &self.q_r.1[index]; let q_o_i = &self.q_o.1[index]; - let q_4_i = &self.q_4.1[index]; + let q_f_i = &self.q_f.1[index]; let q_c_i = &self.q_c.1[index]; let q_arith_i = &self.q_arith.1[index]; - // (a(x)b(x)q_M(x) + a(x)q_L(x) + b(X)q_R(x) + c(X)q_O(X) + d(x)q_4(X) + - // Q_C(X)) * Q_Arith(X) + // (a(x)b(x)q_M(x) + a(x)q_L(x) + b(X)q_R(x) + c(X)q_O(X) + d(x)q_F(X) + + // q_C(X)) * q_arith(X) // - let a_1 = a_w_i * b_w_i * q_m_i; - let a_2 = a_w_i * q_l_i; - let a_3 = b_w_i * q_r_i; - let a_4 = c_w_i * q_o_i; - let a_5 = d_w_i * q_4_i; + let a_1 = a_i * b_i * q_m_i; + let a_2 = a_i * q_l_i; + let a_3 = b_i * q_r_i; + let a_4 = c_i * q_o_i; + let a_5 = d_i * q_f_i; let a_6 = q_c_i; (a_1 + a_2 + a_3 + a_4 + a_5 + a_6) * q_arith_i } @@ -77,11 +77,11 @@ impl ProverKey { let q_l_poly = &self.q_l.0; let q_r_poly = &self.q_r.0; let q_o_poly = &self.q_o.0; - let q_4_poly = &self.q_4.0; + let q_f_poly = &self.q_f.0; let q_c_poly = &self.q_c.0; // (a_eval * b_eval * q_m_poly + a_eval * q_l + b_eval * q_r + c_eval - // * q_o + d_eval * q_4 + q_c) * q_arith_eval + // * q_o + d_eval * q_f + q_c) * q_arith_eval // // a_eval * b_eval * q_m_poly let ab = evaluations.a_eval * evaluations.b_eval; @@ -96,8 +96,8 @@ impl ProverKey { //c_eval * q_o let a_3 = q_o_poly * &evaluations.c_eval; - // d_eval * q_4 - let a_4 = q_4_poly * &evaluations.d_eval; + // d_eval * q_f + let a_4 = q_f_poly * &evaluations.d_eval; let mut a = &a_0 + &a_1; a = &a + &a_2; diff --git a/src/proof_system/widget/arithmetic/verifierkey.rs b/src/proof_system/widget/arithmetic/verifierkey.rs index b67c3457..8bd3506c 100644 --- a/src/proof_system/widget/arithmetic/verifierkey.rs +++ b/src/proof_system/widget/arithmetic/verifierkey.rs @@ -32,7 +32,7 @@ pub(crate) struct VerifierKey { #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub q_o: Commitment, #[cfg_attr(feature = "rkyv-impl", omit_bounds)] - pub q_4: Commitment, + pub q_f: Commitment, #[cfg_attr(feature = "rkyv-impl", omit_bounds)] pub q_c: Commitment, #[cfg_attr(feature = "rkyv-impl", omit_bounds)] @@ -51,7 +51,7 @@ impl Serializable<{ 7 * Commitment::SIZE }> for VerifierKey { writer.write(&self.q_l.to_bytes()); writer.write(&self.q_r.to_bytes()); writer.write(&self.q_o.to_bytes()); - writer.write(&self.q_4.to_bytes()); + writer.write(&self.q_f.to_bytes()); writer.write(&self.q_c.to_bytes()); writer.write(&self.q_arith.to_bytes()); @@ -64,7 +64,7 @@ impl Serializable<{ 7 * Commitment::SIZE }> for VerifierKey { let q_l = Commitment::from_reader(&mut buffer)?; let q_r = Commitment::from_reader(&mut buffer)?; let q_o = Commitment::from_reader(&mut buffer)?; - let q_4 = Commitment::from_reader(&mut buffer)?; + let q_f = Commitment::from_reader(&mut buffer)?; let q_c = Commitment::from_reader(&mut buffer)?; let q_arith = Commitment::from_reader(&mut buffer)?; @@ -73,7 +73,7 @@ impl Serializable<{ 7 * Commitment::SIZE }> for VerifierKey { q_l, q_r, q_o, - q_4, + q_f, q_c, q_arith, }) @@ -111,7 +111,7 @@ mod alloc { points.push(self.q_o.0); scalars.push(evaluations.d_eval * q_arith_eval); - points.push(self.q_4.0); + points.push(self.q_f.0); scalars.push(q_arith_eval); points.push(self.q_c.0); diff --git a/src/proof_system/widget/ecc/curve_addition/proverkey.rs b/src/proof_system/widget/ecc/curve_addition/proverkey.rs index c23ce1a1..1c80afc4 100644 --- a/src/proof_system/widget/ecc/curve_addition/proverkey.rs +++ b/src/proof_system/widget/ecc/curve_addition/proverkey.rs @@ -34,25 +34,25 @@ impl ProverKey { &self, index: usize, curve_add_separation_challenge: &BlsScalar, - a_w_i: &BlsScalar, // x_1 - a_w_i_next: &BlsScalar, // x_3 - b_w_i: &BlsScalar, // y_1 - b_w_i_next: &BlsScalar, // y_3 - c_w_i: &BlsScalar, // x_2 - d_w_i: &BlsScalar, // y_2 - d_w_i_next: &BlsScalar, // x_1 * y_2 + a_i: &BlsScalar, // x_1 + a_i_w: &BlsScalar, // x_3 + b_i: &BlsScalar, // y_1 + b_i_w: &BlsScalar, // y_3 + c_i: &BlsScalar, // x_2 + d_i: &BlsScalar, // y_2 + d_i_w: &BlsScalar, // x_1 * y_2 ) -> BlsScalar { let q_variable_group_add_i = &self.q_variable_group_add.1[index]; let kappa = curve_add_separation_challenge.square(); - let x_1 = a_w_i; - let x_3 = a_w_i_next; - let y_1 = b_w_i; - let y_3 = b_w_i_next; - let x_2 = c_w_i; - let y_2 = d_w_i; - let x1_y2 = d_w_i_next; + let x_1 = a_i; + let x_3 = a_i_w; + let y_1 = b_i; + let y_3 = b_i_w; + let x_2 = c_i; + let y_2 = d_i; + let x1_y2 = d_i_w; // Checks // @@ -88,12 +88,12 @@ impl ProverKey { let kappa = curve_add_separation_challenge.square(); let x_1 = evaluations.a_eval; - let x_3 = evaluations.a_next_eval; + let x_3 = evaluations.a_w_eval; let y_1 = evaluations.b_eval; - let y_3 = evaluations.b_next_eval; + let y_3 = evaluations.b_w_eval; let x_2 = evaluations.c_eval; let y_2 = evaluations.d_eval; - let x1_y2 = evaluations.d_next_eval; + let x1_y2 = evaluations.d_w_eval; // Checks // diff --git a/src/proof_system/widget/ecc/curve_addition/verifierkey.rs b/src/proof_system/widget/ecc/curve_addition/verifierkey.rs index b9ba063d..2453d743 100644 --- a/src/proof_system/widget/ecc/curve_addition/verifierkey.rs +++ b/src/proof_system/widget/ecc/curve_addition/verifierkey.rs @@ -46,12 +46,12 @@ mod alloc { let kappa = curve_add_separation_challenge.square(); let x_1 = evaluations.a_eval; - let x_3 = evaluations.a_next_eval; + let x_3 = evaluations.a_w_eval; let y_1 = evaluations.b_eval; - let y_3 = evaluations.b_next_eval; + let y_3 = evaluations.b_w_eval; let x_2 = evaluations.c_eval; let y_2 = evaluations.d_eval; - let x1_y2 = evaluations.d_next_eval; + let x1_y2 = evaluations.d_w_eval; // Checks // diff --git a/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs b/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs index 93cf85a5..f83b845e 100644 --- a/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs +++ b/src/proof_system/widget/ecc/scalar_mul/fixed_base/proverkey.rs @@ -40,13 +40,13 @@ impl ProverKey { &self, index: usize, ecc_separation_challenge: &BlsScalar, - a_w_i: &BlsScalar, // acc_x or curr_x - a_w_i_next: &BlsScalar, // // next_x - b_w_i: &BlsScalar, // acc_y or curr_y - b_w_i_next: &BlsScalar, // next_y - c_w_i: &BlsScalar, // xy_alpha - d_w_i: &BlsScalar, // accumulated_bit - d_w_i_next: &BlsScalar, // accumulated_bit_next + a_i: &BlsScalar, // acc_x or curr_x + a_i_w: &BlsScalar, // shifted x + b_i: &BlsScalar, // acc_y or curr_y + b_i_w: &BlsScalar, // shifted y + c_i: &BlsScalar, // xy_alpha + d_i: &BlsScalar, // accumulated_bit + d_i_w: &BlsScalar, // accumulated_bit_w ) -> BlsScalar { let q_fixed_group_add_i = &self.q_fixed_group_add.1[index]; let q_c_i = &self.q_c.1[index]; @@ -58,16 +58,16 @@ impl ProverKey { let x_beta = &self.q_l.1[index]; let y_beta = &self.q_r.1[index]; - let acc_x = a_w_i; - let acc_x_next = a_w_i_next; - let acc_y = b_w_i; - let acc_y_next = b_w_i_next; + let acc_x = a_i; + let acc_x_w = a_i_w; + let acc_y = b_i; + let acc_y_w = b_i_w; - let xy_alpha = c_w_i; + let xy_alpha = c_i; - let accumulated_bit = d_w_i; - let accumulated_bit_next = d_w_i_next; - let bit = extract_bit(accumulated_bit, accumulated_bit_next); + let accumulated_bit = d_i; + let accumulated_bit_w = d_i_w; + let bit = extract_bit(accumulated_bit, accumulated_bit_w); // Checks // @@ -83,13 +83,13 @@ impl ProverKey { let xy_consistency = ((bit * q_c_i) - xy_alpha) * kappa; // x accumulator consistency check - let x_3 = acc_x_next; + let x_3 = acc_x_w; let lhs = x_3 + (x_3 * xy_alpha * acc_x * acc_y * EDWARDS_D); let rhs = (acc_x * y_alpha) + (acc_y * x_alpha); let x_acc_consistency = (lhs - rhs) * kappa_sq; // y accumulator consistency check - let y_3 = acc_y_next; + let y_3 = acc_y_w; let lhs = y_3 - (y_3 * xy_alpha * acc_x * acc_y * EDWARDS_D); let rhs = (acc_y * y_alpha) + (acc_x * x_alpha); let y_acc_consistency = (lhs - rhs) * kappa_cu; @@ -117,15 +117,15 @@ impl ProverKey { let y_beta_eval = evaluations.q_r_eval; let acc_x = evaluations.a_eval; - let acc_x_next = evaluations.a_next_eval; + let acc_x_w = evaluations.a_w_eval; let acc_y = evaluations.b_eval; - let acc_y_next = evaluations.b_next_eval; + let acc_y_w = evaluations.b_w_eval; let xy_alpha = evaluations.c_eval; let accumulated_bit = evaluations.d_eval; - let accumulated_bit_next = evaluations.d_next_eval; - let bit = extract_bit(&accumulated_bit, &accumulated_bit_next); + let accumulated_bit_w = evaluations.d_w_eval; + let bit = extract_bit(&accumulated_bit, &accumulated_bit_w); // Check bit consistency let bit_consistency = check_bit_consistency(bit); @@ -139,13 +139,13 @@ impl ProverKey { let xy_consistency = ((bit * evaluations.q_c_eval) - xy_alpha) * kappa; // x accumulator consistency check - let x_3 = acc_x_next; + let x_3 = acc_x_w; let lhs = x_3 + (x_3 * xy_alpha * acc_x * acc_y * EDWARDS_D); let rhs = (x_alpha * acc_y) + (y_alpha * acc_x); let x_acc_consistency = (lhs - rhs) * kappa_sq; // y accumulator consistency check - let y_3 = acc_y_next; + let y_3 = acc_y_w; let lhs = y_3 - (y_3 * xy_alpha * acc_x * acc_y * EDWARDS_D); let rhs = (x_alpha * acc_x) + (y_alpha * acc_y); let y_acc_consistency = (lhs - rhs) * kappa_cu; @@ -159,12 +159,9 @@ impl ProverKey { } } -pub(crate) fn extract_bit( - curr_acc: &BlsScalar, - next_acc: &BlsScalar, -) -> BlsScalar { - // Next - 2 * current - next_acc - curr_acc - curr_acc +pub(crate) fn extract_bit(acc: &BlsScalar, acc_w: &BlsScalar) -> BlsScalar { + // acc_w - 2 * acc + acc_w - acc - acc } // Ensures that the bit is either +1, -1 or 0 diff --git a/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs b/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs index 8b0adbea..8b1e8bc2 100644 --- a/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs +++ b/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs @@ -58,15 +58,15 @@ mod alloc { let y_beta_eval = evaluations.q_r_eval; let acc_x = evaluations.a_eval; - let acc_x_next = evaluations.a_next_eval; + let acc_x_w = evaluations.a_w_eval; let acc_y = evaluations.b_eval; - let acc_y_next = evaluations.b_next_eval; + let acc_y_w = evaluations.b_w_eval; let xy_alpha = evaluations.c_eval; let accumulated_bit = evaluations.d_eval; - let accumulated_bit_next = evaluations.d_next_eval; - let bit = extract_bit(&accumulated_bit, &accumulated_bit_next); + let accumulated_bit_w = evaluations.d_w_eval; + let bit = extract_bit(&accumulated_bit, &accumulated_bit_w); // Check bit consistency let bit_consistency = check_bit_consistency(bit); @@ -81,13 +81,13 @@ mod alloc { ((bit * evaluations.q_c_eval) - xy_alpha) * kappa; // x accumulator consistency check - let x_3 = acc_x_next; + let x_3 = acc_x_w; let lhs = x_3 + (x_3 * xy_alpha * acc_x * acc_y * EDWARDS_D); let rhs = (x_alpha * acc_y) + (y_alpha * acc_x); let x_acc_consistency = (lhs - rhs) * kappa_sq; // y accumulator consistency check - let y_3 = acc_y_next; + let y_3 = acc_y_w; let lhs = y_3 - (y_3 * xy_alpha * acc_x * acc_y * EDWARDS_D); let rhs = (x_alpha * acc_x) + (y_alpha * acc_y); let y_acc_consistency = (lhs - rhs) * kappa_cu; diff --git a/src/proof_system/widget/logic/proverkey.rs b/src/proof_system/widget/logic/proverkey.rs index 38973517..72865c54 100644 --- a/src/proof_system/widget/logic/proverkey.rs +++ b/src/proof_system/widget/logic/proverkey.rs @@ -36,13 +36,13 @@ impl ProverKey { &self, index: usize, logic_separation_challenge: &BlsScalar, - a_w_i: &BlsScalar, - a_w_i_next: &BlsScalar, - b_w_i: &BlsScalar, - b_w_i_next: &BlsScalar, - c_w_i: &BlsScalar, - d_w_i: &BlsScalar, - d_w_i_next: &BlsScalar, + a_i: &BlsScalar, + a_i_w: &BlsScalar, + b_i: &BlsScalar, + b_i_w: &BlsScalar, + c_i: &BlsScalar, + d_i: &BlsScalar, + d_i_w: &BlsScalar, ) -> BlsScalar { let four = BlsScalar::from(4); @@ -54,21 +54,21 @@ impl ProverKey { let kappa_cu = kappa_sq * kappa; let kappa_qu = kappa_cu * kappa; - let a = a_w_i_next - four * a_w_i; - let o_0 = delta(a); + let a = a_i_w - four * a_i; + let c_0 = delta(a); - let b = b_w_i_next - four * b_w_i; - let o_1 = delta(b) * kappa; + let b = b_i_w - four * b_i; + let c_1 = delta(b) * kappa; - let d = d_w_i_next - four * d_w_i; - let o_2 = delta(d) * kappa_sq; + let d = d_i_w - four * d_i; + let c_2 = delta(d) * kappa_sq; - let w = c_w_i; - let o_3 = (w - a * b) * kappa_cu; + let w = c_i; + let c_3 = (w - a * b) * kappa_cu; - let o_4 = delta_xor_and(&a, &b, w, &d, q_c_i) * kappa_qu; + let c_4 = delta_xor_and(&a, &b, w, &d, q_c_i) * kappa_qu; - q_logic_i * (o_3 + o_0 + o_1 + o_2 + o_4) * logic_separation_challenge + q_logic_i * (c_3 + c_0 + c_1 + c_2 + c_4) * logic_separation_challenge } pub(crate) fn compute_linearization( @@ -84,22 +84,22 @@ impl ProverKey { let kappa_cu = kappa_sq * kappa; let kappa_qu = kappa_cu * kappa; - let a = evaluations.a_next_eval - four * evaluations.a_eval; - let o_0 = delta(a); + let a = evaluations.a_w_eval - four * evaluations.a_eval; + let c_0 = delta(a); - let b = evaluations.b_next_eval - four * evaluations.b_eval; - let o_1 = delta(b) * kappa; + let b = evaluations.b_w_eval - four * evaluations.b_eval; + let c_1 = delta(b) * kappa; - let d = evaluations.d_next_eval - four * evaluations.d_eval; - let o_2 = delta(d) * kappa_sq; + let d = evaluations.d_w_eval - four * evaluations.d_eval; + let c_2 = delta(d) * kappa_sq; let w = evaluations.c_eval; - let o_3 = (w - a * b) * kappa_cu; + let c_3 = (w - a * b) * kappa_cu; - let o_4 = + let c_4 = delta_xor_and(&a, &b, &w, &d, &evaluations.q_c_eval) * kappa_qu; - let t = (o_0 + o_1 + o_2 + o_3 + o_4) * logic_separation_challenge; + let t = (c_0 + c_1 + c_2 + c_3 + c_4) * logic_separation_challenge; q_logic_poly * &t } diff --git a/src/proof_system/widget/logic/verifierkey.rs b/src/proof_system/widget/logic/verifierkey.rs index 22773ad4..ec8aa626 100644 --- a/src/proof_system/widget/logic/verifierkey.rs +++ b/src/proof_system/widget/logic/verifierkey.rs @@ -52,22 +52,22 @@ mod alloc { let kappa_cu = kappa_sq * kappa; let kappa_qu = kappa_cu * kappa; - let a = evaluations.a_next_eval - four * evaluations.a_eval; - let o_0 = delta(a); + let a = evaluations.a_w_eval - four * evaluations.a_eval; + let c_0 = delta(a); - let b = evaluations.b_next_eval - four * evaluations.b_eval; - let o_1 = delta(b) * kappa; + let b = evaluations.b_w_eval - four * evaluations.b_eval; + let c_1 = delta(b) * kappa; - let d = evaluations.d_next_eval - four * evaluations.d_eval; - let o_2 = delta(d) * kappa_sq; + let d = evaluations.d_w_eval - four * evaluations.d_eval; + let c_2 = delta(d) * kappa_sq; - let o = evaluations.c_eval; - let o_3 = (o - a * b) * kappa_cu; + let w = evaluations.c_eval; + let c_3 = (w - a * b) * kappa_cu; - let o_4 = - delta_xor_and(&a, &b, &o, &d, &evaluations.q_c_eval) * kappa_qu; + let c_4 = + delta_xor_and(&a, &b, &w, &d, &evaluations.q_c_eval) * kappa_qu; scalars.push( - (o_0 + o_1 + o_2 + o_3 + o_4) * logic_separation_challenge, + (c_0 + c_1 + c_2 + c_3 + c_4) * logic_separation_challenge, ); points.push(self.q_logic.0); } diff --git a/src/proof_system/widget/permutation/proverkey.rs b/src/proof_system/widget/permutation/proverkey.rs index 47ed6841..8da74f10 100644 --- a/src/proof_system/widget/permutation/proverkey.rs +++ b/src/proof_system/widget/permutation/proverkey.rs @@ -46,22 +46,22 @@ impl ProverKey { pub(crate) fn compute_quotient_i( &self, index: usize, - a_w_i: &BlsScalar, - b_w_i: &BlsScalar, - c_w_i: &BlsScalar, - d_w_i: &BlsScalar, + a_i: &BlsScalar, + b_i: &BlsScalar, + c_i: &BlsScalar, + d_i: &BlsScalar, z_i: &BlsScalar, - z_i_next: &BlsScalar, + z_i_w: &BlsScalar, alpha: &BlsScalar, l1_alpha_sq: &BlsScalar, beta: &BlsScalar, gamma: &BlsScalar, ) -> BlsScalar { let a = self.compute_quotient_identity_range_check_i( - index, a_w_i, b_w_i, c_w_i, d_w_i, z_i, alpha, beta, gamma, + index, a_i, b_i, c_i, d_i, z_i, alpha, beta, gamma, ); let b = self.compute_quotient_copy_range_check_i( - index, a_w_i, b_w_i, c_w_i, d_w_i, z_i_next, alpha, beta, gamma, + index, a_i, b_i, c_i, d_i, z_i_w, alpha, beta, gamma, ); let c = self.compute_quotient_term_check_one_i(z_i, l1_alpha_sq); a + b + c @@ -71,10 +71,10 @@ impl ProverKey { fn compute_quotient_identity_range_check_i( &self, index: usize, - a_w_i: &BlsScalar, - b_w_i: &BlsScalar, - c_w_i: &BlsScalar, - d_w_i: &BlsScalar, + a_i: &BlsScalar, + b_i: &BlsScalar, + c_i: &BlsScalar, + d_i: &BlsScalar, z_i: &BlsScalar, alpha: &BlsScalar, beta: &BlsScalar, @@ -82,10 +82,10 @@ impl ProverKey { ) -> BlsScalar { let x = self.linear_evaluations[index]; - (a_w_i + (beta * x) + gamma) - * (b_w_i + (beta * K1 * x) + gamma) - * (c_w_i + (beta * K2 * x) + gamma) - * (d_w_i + (beta * K3 * x) + gamma) + (a_i + (beta * x) + gamma) + * (b_i + (beta * K1 * x) + gamma) + * (c_i + (beta * K2 * x) + gamma) + * (d_i + (beta * K3 * x) + gamma) * z_i * alpha } @@ -95,11 +95,11 @@ impl ProverKey { fn compute_quotient_copy_range_check_i( &self, index: usize, - a_w_i: &BlsScalar, - b_w_i: &BlsScalar, - c_w_i: &BlsScalar, - d_w_i: &BlsScalar, - z_i_next: &BlsScalar, + a_i: &BlsScalar, + b_i: &BlsScalar, + c_i: &BlsScalar, + d_i: &BlsScalar, + z_i_w: &BlsScalar, alpha: &BlsScalar, beta: &BlsScalar, gamma: &BlsScalar, @@ -109,11 +109,11 @@ impl ProverKey { let s_sigma_3_eval = self.s_sigma_3.1[index]; let s_sigma_4_eval = self.s_sigma_4.1[index]; - let product = (a_w_i + (beta * s_sigma_1_eval) + gamma) - * (b_w_i + (beta * s_sigma_2_eval) + gamma) - * (c_w_i + (beta * s_sigma_3_eval) + gamma) - * (d_w_i + (beta * s_sigma_4_eval) + gamma) - * z_i_next + let product = (a_i + (beta * s_sigma_1_eval) + gamma) + * (b_i + (beta * s_sigma_2_eval) + gamma) + * (c_i + (beta * s_sigma_3_eval) + gamma) + * (d_i + (beta * s_sigma_4_eval) + gamma) + * z_i_w * alpha; -product diff --git a/src/proof_system/widget/range/proverkey.rs b/src/proof_system/widget/range/proverkey.rs index 507d8bf4..2a99efc5 100644 --- a/src/proof_system/widget/range/proverkey.rs +++ b/src/proof_system/widget/range/proverkey.rs @@ -33,11 +33,11 @@ impl ProverKey { &self, index: usize, range_separation_challenge: &BlsScalar, - a_w_i: &BlsScalar, - b_w_i: &BlsScalar, - c_w_i: &BlsScalar, - d_w_i: &BlsScalar, - d_w_i_next: &BlsScalar, + a_i: &BlsScalar, + b_i: &BlsScalar, + c_i: &BlsScalar, + d_i: &BlsScalar, + d_i_w: &BlsScalar, ) -> BlsScalar { let four = BlsScalar::from(4); let q_range_i = &self.q_range.1[index]; @@ -49,10 +49,10 @@ impl ProverKey { // Delta([o(X) - 4 * d(X)]) + Delta([b(X) - 4 * o(X)]) + Delta([a(X) - 4 // * b(X)]) + Delta([d(Xg) - 4 * a(X)]) * Q_Range(X) // - let b_1 = delta(c_w_i - four * d_w_i); - let b_2 = delta(b_w_i - four * c_w_i) * kappa; - let b_3 = delta(a_w_i - four * b_w_i) * kappa_sq; - let b_4 = delta(d_w_i_next - four * a_w_i) * kappa_cu; + let b_1 = delta(c_i - four * d_i); + let b_2 = delta(b_i - four * c_i) * kappa; + let b_3 = delta(a_i - four * b_i) * kappa_sq; + let b_4 = delta(d_i_w - four * a_i) * kappa_cu; (b_1 + b_2 + b_3 + b_4) * q_range_i * range_separation_challenge } @@ -69,14 +69,14 @@ impl ProverKey { let kappa_cu = kappa_sq * kappa; // Delta([c_eval - 4 * d_eval]) + Delta([b_eval - 4 * c_eval]) + - // Delta([a_eval - 4 * b_eval]) + Delta([d_next_eval - 4 * a_eval]) * + // Delta([a_eval - 4 * b_eval]) + Delta([d_w_eval - 4 * a_eval]) * // Q_Range(X) let b_1 = delta(evaluations.c_eval - four * evaluations.d_eval); let b_2 = delta(evaluations.b_eval - four * evaluations.c_eval) * kappa; let b_3 = delta(evaluations.a_eval - four * evaluations.b_eval) * kappa_sq; - let b_4 = delta(evaluations.d_next_eval - four * evaluations.a_eval) - * kappa_cu; + let b_4 = + delta(evaluations.d_w_eval - four * evaluations.a_eval) * kappa_cu; let t = (b_1 + b_2 + b_3 + b_4) * range_separation_challenge; diff --git a/src/proof_system/widget/range/verifierkey.rs b/src/proof_system/widget/range/verifierkey.rs index 43af8041..e32ebb68 100644 --- a/src/proof_system/widget/range/verifierkey.rs +++ b/src/proof_system/widget/range/verifierkey.rs @@ -54,9 +54,8 @@ mod alloc { delta(evaluations.b_eval - four * evaluations.c_eval) * kappa; let b_3 = delta(evaluations.a_eval - four * evaluations.b_eval) * kappa_sq; - let b_4 = - delta(evaluations.d_next_eval - (four * evaluations.a_eval)) - * kappa_cu; + let b_4 = delta(evaluations.d_w_eval - (four * evaluations.a_eval)) + * kappa_cu; scalars.push((b_1 + b_2 + b_3 + b_4) * range_separation_challenge); points.push(self.q_range.0); diff --git a/tests/append_gate.rs b/tests/append_gate.rs index 77e75ff6..9a06f210 100644 --- a/tests/append_gate.rs +++ b/tests/append_gate.rs @@ -18,7 +18,7 @@ fn append_gate() { pub struct TestCircuit { a: BlsScalar, b: BlsScalar, - o: BlsScalar, + c: BlsScalar, d: BlsScalar, public: BlsScalar, } @@ -27,20 +27,20 @@ fn append_gate() { pub fn new( a: BlsScalar, b: BlsScalar, - o: BlsScalar, + c: BlsScalar, d: BlsScalar, public: BlsScalar, ) -> Self { - Self { a, b, o, d, public } + Self { a, b, c, d, public } } } impl Circuit for TestCircuit { fn circuit(&self, composer: &mut Composer) -> Result<(), Error> { - let w_a = composer.append_witness(self.a); - let w_b = composer.append_witness(self.b); - let w_o = composer.append_witness(self.o); - let w_d = composer.append_witness(self.d); + let a = composer.append_witness(self.a); + let b = composer.append_witness(self.b); + let c = composer.append_witness(self.c); + let d = composer.append_witness(self.d); let constraint = Constraint::new() .left(1) @@ -48,10 +48,10 @@ fn append_gate() { .mult(1) .fourth(1) .output(1) - .a(w_a) - .b(w_b) - .o(w_o) - .d(w_d) + .a(a) + .b(b) + .c(c) + .d(d) .public(self.public) .constant(BlsScalar::zero()); @@ -71,10 +71,10 @@ fn append_gate() { let public = BlsScalar::zero(); let a = BlsScalar::zero(); let b = BlsScalar::zero(); - let o = BlsScalar::zero(); + let c = BlsScalar::zero(); let d = BlsScalar::zero(); let pi = vec![public]; - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); let pp = PublicParameters::setup(capacity, &mut rng) .expect("Creation of public parameter shouldn't fail"); let (prover, verifier) = Compiler::compile::(&pp, label) @@ -85,95 +85,95 @@ fn append_gate() { check_satisfied_circuit(&prover, &verifier, &pi, &circuit, &mut rng, &msg); // Test satisfied circuit: - // q_l·a + q_r·b + q_m·a·b + q_o·o + q_4·d + public + constant = 0 + // q_l·a + q_r·b + q_m·a·b + q_o·c + q_4·d + public + constant = 0 let msg = "Verification of satisfied circuit should pass"; let a = BlsScalar::one(); let b = BlsScalar::one(); - let o = -BlsScalar::from(4); + let c = -BlsScalar::from(4); let d = BlsScalar::one(); - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); check_satisfied_circuit(&prover, &verifier, &pi, &circuit, &mut rng, &msg); // Test satisfied circuit: - // q_l·a + q_r·b + q_m·a·b + q_o·o + q_4·d + public + constant = 0 + // q_l·a + q_r·b + q_m·a·b + q_o·c + q_4·d + public + constant = 0 let msg = "Verification of satisfied circuit should pass"; let a = BlsScalar::one(); let b = BlsScalar::zero(); - let o = -BlsScalar::one(); + let c = -BlsScalar::one(); let d = BlsScalar::zero(); - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); check_satisfied_circuit(&prover, &verifier, &pi, &circuit, &mut rng, &msg); // Test satisfied circuit: - // q_l·a + q_r·b + q_m·a·b + q_o·o + q_4·d + public + constant = 0 + // q_l·a + q_r·b + q_m·a·b + q_o·c + q_4·d + public + constant = 0 let msg = "Verification of satisfied circuit should pass"; let a = BlsScalar::zero(); let b = BlsScalar::one(); - let o = -BlsScalar::one(); + let c = -BlsScalar::one(); let d = BlsScalar::zero(); - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); check_satisfied_circuit(&prover, &verifier, &pi, &circuit, &mut rng, &msg); // Test satisfied circuit: - // q_l·a + q_r·b + q_m·a·b + q_o·o + q_4·d + public + constant = 0 + // q_l·a + q_r·b + q_m·a·b + q_o·c + q_4·d + public + constant = 0 let msg = "Verification of satisfied circuit should pass"; let a = BlsScalar::one(); let b = BlsScalar::one(); - let o = -BlsScalar::from(3u64); + let c = -BlsScalar::from(3u64); let d = BlsScalar::zero(); - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); check_satisfied_circuit(&prover, &verifier, &pi, &circuit, &mut rng, &msg); // Test satisfied circuit: - // q_l·a + q_r·b + q_m·a·b + q_o·o + q_4·d + public + constant = 0 + // q_l·a + q_r·b + q_m·a·b + q_o·c + q_4·d + public + constant = 0 let msg = "Verification of satisfied circuit should pass"; let a = -BlsScalar::one(); let b = BlsScalar::zero(); - let o = BlsScalar::zero(); + let c = BlsScalar::zero(); let d = BlsScalar::one(); - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); check_satisfied_circuit(&prover, &verifier, &pi, &circuit, &mut rng, &msg); // Test satisfied circuit: - // q_l·a + q_r·b + q_m·a·b + q_o·o + q_4·d + public + constant = 0 + // q_l·a + q_r·b + q_m·a·b + q_o·c + q_4·d + public + constant = 0 let msg = "Verification of satisfied circuit should pass"; let a = BlsScalar::random(&mut rng); let b = BlsScalar::random(&mut rng); let d = BlsScalar::random(&mut rng); let public = BlsScalar::from(42); - let o = -(a + b + a * b + d + public); + let c = -(a + b + a * b + d + public); let pi = vec![public]; - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); check_satisfied_circuit(&prover, &verifier, &pi, &circuit, &mut rng, &msg); // Test unsatisfied circuit: let msg = "Proof creation of unsatisfied circuit should fail"; let a = BlsScalar::random(&mut rng); let b = BlsScalar::random(&mut rng); - let o = BlsScalar::random(&mut rng); + let c = BlsScalar::random(&mut rng); let d = BlsScalar::random(&mut rng); let public = BlsScalar::random(&mut rng); - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); check_unsatisfied_circuit(&prover, &circuit, &mut rng, &msg); // Test unsatisfied circuit: - // q_l·a + q_r·b + q_m·a·b + q_o·o + q_4·d + public + constant = 0 + // q_l·a + q_r·b + q_m·a·b + q_o·c + q_4·d + public + constant = 0 let msg = "Proof creation of unsatisfied circuit should fail"; let a = BlsScalar::one(); let b = BlsScalar::one(); - let o = BlsScalar::one(); + let c = BlsScalar::one(); let d = BlsScalar::one(); let public = BlsScalar::one(); - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); check_unsatisfied_circuit(&prover, &circuit, &mut rng, &msg); // Test unsatisfied circuit let msg = "Verification of unsatisfied circuit should pass"; let a = BlsScalar::one(); let b = BlsScalar::one(); - let o = BlsScalar::one(); + let c = BlsScalar::one(); let d = BlsScalar::one(); let public = BlsScalar::one(); - let circuit = TestCircuit::new(a, b, o, d, public); + let circuit = TestCircuit::new(a, b, c, d, public); check_unsatisfied_circuit(&prover, &circuit, &mut rng, &msg); } From 3ab789c34dd7ab02610f59795f06b89fe448a022 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Tue, 30 Jul 2024 15:29:23 +0200 Subject: [PATCH 10/11] Rename blinders --- src/compiler/prover.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/compiler/prover.rs b/src/compiler/prover.rs index 42e665f9..b3f5152c 100644 --- a/src/compiler/prover.rs +++ b/src/compiler/prover.rs @@ -359,23 +359,23 @@ impl Prover { let mut t_fourth_vec = t_poly[3 * domain_size..].to_vec(); // select 3 blinding factors for the quotient splitted polynomials - let b_10 = BlsScalar::random(&mut *rng); - let b_11 = BlsScalar::random(&mut *rng); let b_12 = BlsScalar::random(&mut *rng); + let b_13 = BlsScalar::random(&mut *rng); + let b_14 = BlsScalar::random(&mut *rng); - // t_low'(X) + b_10*X^n - t_low_vec.push(b_10); + // t_low'(X) + b_12*X^n + t_low_vec.push(b_12); - // t_mid'(X) - b_10 + b_11*X^n - t_mid_vec[0] -= b_10; - t_mid_vec.push(b_11); + // t_mid'(X) - b_12 + b_13*X^n + t_mid_vec[0] -= b_12; + t_mid_vec.push(b_13); - // t_high'(X) - b_11 + b_12*X^n - t_high_vec[0] -= b_11; - t_high_vec.push(b_12); + // t_high'(X) - b_13 + b_14*X^n + t_high_vec[0] -= b_13; + t_high_vec.push(b_14); - // t_fourth'(X) - b_12 - t_fourth_vec[0] -= b_12; + // t_fourth'(X) - b_14 + t_fourth_vec[0] -= b_14; let t_low_poly = Polynomial::from_coefficients_vec(t_low_vec); let t_mid_poly = Polynomial::from_coefficients_vec(t_mid_vec); @@ -437,21 +437,24 @@ impl Prover { transcript.append_scalar(b"z_eval", &z_eval); - // Compute shifted evaluations + // compute shifted evaluations let a_w_eval = a_poly.evaluate(&(z_challenge * domain.group_gen)); let b_w_eval = b_poly.evaluate(&(z_challenge * domain.group_gen)); let d_w_eval = d_poly.evaluate(&(z_challenge * domain.group_gen)); + // compute selector evaluations let q_arith_eval = self.prover_key.arithmetic.q_arith.0.evaluate(&z_challenge); let q_c_eval = self.prover_key.logic.q_c.0.evaluate(&z_challenge); let q_l_eval = self.prover_key.fixed_base.q_l.0.evaluate(&z_challenge); let q_r_eval = self.prover_key.fixed_base.q_r.0.evaluate(&z_challenge); - // add extra evaluations to transcript. + // add shifted evaluations to transcript transcript.append_scalar(b"a_w_eval", &a_w_eval); transcript.append_scalar(b"b_w_eval", &b_w_eval); transcript.append_scalar(b"d_w_eval", &d_w_eval); + + // add selector evaluations to transcript. transcript.append_scalar(b"q_arith_eval", &q_arith_eval); transcript.append_scalar(b"q_c_eval", &q_c_eval); transcript.append_scalar(b"q_l_eval", &q_l_eval); From 883ace4cfb3d62b05606ac749d53623643cd9584 Mon Sep 17 00:00:00 2001 From: xevisalle Date: Tue, 6 Aug 2024 17:46:39 +0200 Subject: [PATCH 11/11] Add specs --- README.md | 2 +- docs/dusk-plonk-specs.pdf | Bin 0 -> 273155 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/dusk-plonk-specs.pdf diff --git a/README.md b/README.md index 0a4f2b77..4cc6acc3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ _This is a pure Rust implementation of the PLONK proving system over BLS12-381._ -This library contains a modular implementation of KZG10 as the default polynomial commitment scheme. +This library contains a modular implementation of KZG10 as the default polynomial commitment scheme. Moreover, it includes custom gates for efficiency purposes. The details on our specific implementation can be found [here](docs/dusk-plonk-specs.pdf). **DISCLAIMER**: This library is currently unstable and still needs to undergo an exhaustive security analysis. Use at your own risk. diff --git a/docs/dusk-plonk-specs.pdf b/docs/dusk-plonk-specs.pdf new file mode 100644 index 0000000000000000000000000000000000000000..378d592ea157b3e5a937bb57d94745e0369497ad GIT binary patch literal 273155 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�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ÐzGno66l1@~-8f46oUU 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

pCK(@mE!>If<|z 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 literal 0 HcmV?d00001