From 1aadcb83064905972a66bac8dcb90bf4a5b81aa1 Mon Sep 17 00:00:00 2001 From: Irfan Bozkurt Date: Tue, 7 Nov 2023 00:49:02 +0300 Subject: [PATCH] improvements over plonk --- provers/plonk/src/prover.rs | 33 +++++++------ provers/plonk/src/setup.rs | 2 +- provers/plonk/src/test_utils/circuit_1.rs | 3 +- provers/plonk/src/test_utils/circuit_2.rs | 2 +- provers/plonk/src/test_utils/circuit_json.rs | 3 +- provers/plonk/src/test_utils/utils.rs | 50 +++++++++++--------- 6 files changed, 50 insertions(+), 43 deletions(-) diff --git a/provers/plonk/src/prover.rs b/provers/plonk/src/prover.rs index c8bee0666..b50aaccc1 100644 --- a/provers/plonk/src/prover.rs +++ b/provers/plonk/src/prover.rs @@ -341,33 +341,38 @@ where fn round_2( &self, witness: &Witness, - common_preprocessed_input: &CommonPreprocessedInput, + cpi: &CommonPreprocessedInput, beta: FieldElement, gamma: FieldElement, ) -> Round2Result { - let cpi = common_preprocessed_input; - let mut coefficients: Vec> = vec![FieldElement::one()]; + let mut z_evaluations: Vec> = vec![FieldElement::one()]; let (s1, s2, s3) = (&cpi.s1_lagrange, &cpi.s2_lagrange, &cpi.s3_lagrange); let k2 = &cpi.k1 * &cpi.k1; let lp = |w: &FieldElement, eta: &FieldElement| w + &beta * eta + γ + let z_nums: Vec<_> = (0..&cpi.n - 1) + .map(|i| { + lp(&witness.a[i], &cpi.domain[i]) + * lp(&witness.b[i], &(&cpi.domain[i] * &cpi.k1)) + * lp(&witness.c[i], &(&cpi.domain[i] * &k2)) + }) + .collect(); + let mut z_denoms: Vec<_> = (0..&cpi.n - 1) + .map(|i| { + lp(&witness.a[i], &s1[i]) * lp(&witness.b[i], &s2[i]) * lp(&witness.c[i], &s3[i]) + }) + .collect(); + FieldElement::inplace_batch_inverse(&mut z_denoms).unwrap(); + for i in 0..&cpi.n - 1 { - let (a_i, b_i, c_i) = (&witness.a[i], &witness.b[i], &witness.c[i]); - let num = lp(a_i, &cpi.domain[i]) - * lp(b_i, &(&cpi.domain[i] * &cpi.k1)) - * lp(c_i, &(&cpi.domain[i] * &k2)); - let den = lp(a_i, &s1[i]) * lp(b_i, &s2[i]) * lp(c_i, &s3[i]); - let new_factor = num / den; - let new_term = coefficients.last().unwrap() * &new_factor; - coefficients.push(new_term); + z_evaluations.push(z_evaluations.last().unwrap() * (&z_nums[i] * &z_denoms[i])); } - let p_z = Polynomial::interpolate_fft(&coefficients) + let p_z = Polynomial::interpolate_fft(&z_evaluations) .expect("xs and ys have equal length and xs are unique"); - let z_h = Polynomial::new_monomial(FieldElement::one(), common_preprocessed_input.n) - - FieldElement::one(); + let z_h = Polynomial::new_monomial(FieldElement::one(), cpi.n) - FieldElement::one(); let p_z = self.blind_polynomial(&p_z, &z_h, 3); let z_1 = self.commitment_scheme.commit(&p_z); Round2Result { diff --git a/provers/plonk/src/setup.rs b/provers/plonk/src/setup.rs index 974c50e3f..19f633c26 100644 --- a/provers/plonk/src/setup.rs +++ b/provers/plonk/src/setup.rs @@ -75,7 +75,7 @@ impl CommonPreprocessedInput { let permutation = get_permutation(&lro); let permuted = - generate_permutation_coefficients(&omega, n, &permutation, order_r_minus_1_root_unity); + generate_permutation_coefficients(&domain, &permutation, order_r_minus_1_root_unity); let s1_lagrange: Vec<_> = permuted[..n].to_vec(); let s2_lagrange: Vec<_> = permuted[n..2 * n].to_vec(); diff --git a/provers/plonk/src/test_utils/circuit_1.rs b/provers/plonk/src/test_utils/circuit_1.rs index bc95c8962..bdc9aa7fa 100644 --- a/provers/plonk/src/test_utils/circuit_1.rs +++ b/provers/plonk/src/test_utils/circuit_1.rs @@ -24,8 +24,7 @@ pub fn test_common_preprocessed_input_1() -> CommonPreprocessedInput { let omega = FrField::get_primitive_root_of_unity(2).unwrap(); let domain = generate_domain(&omega, n); let permuted = generate_permutation_coefficients( - &omega, - n, + &domain, &[11, 3, 0, 1, 2, 4, 6, 10, 5, 8, 7, 9], &ORDER_R_MINUS_1_ROOT_UNITY, ); diff --git a/provers/plonk/src/test_utils/circuit_2.rs b/provers/plonk/src/test_utils/circuit_2.rs index b47eafbef..4454ba9c6 100644 --- a/provers/plonk/src/test_utils/circuit_2.rs +++ b/provers/plonk/src/test_utils/circuit_2.rs @@ -28,7 +28,7 @@ pub fn test_common_preprocessed_input_2() -> CommonPreprocessedInput { 23, 4, 0, 18, 1, 2, 5, 6, 7, 8, 10, 9, 19, 11, 13, 14, 15, 16, 3, 12, 17, 20, 21, 22, ]; let permuted = - generate_permutation_coefficients(&omega, n, permutation, &ORDER_R_MINUS_1_ROOT_UNITY); + generate_permutation_coefficients(&domain, permutation, &ORDER_R_MINUS_1_ROOT_UNITY); let s1_lagrange: Vec = permuted[..8].to_vec(); let s2_lagrange: Vec = permuted[8..16].to_vec(); diff --git a/provers/plonk/src/test_utils/circuit_json.rs b/provers/plonk/src/test_utils/circuit_json.rs index 13aea759e..b0878678b 100644 --- a/provers/plonk/src/test_utils/circuit_json.rs +++ b/provers/plonk/src/test_utils/circuit_json.rs @@ -40,8 +40,7 @@ pub fn common_preprocessed_input_from_json( let omega = FrField::get_primitive_root_of_unity(n.trailing_zeros() as u64).unwrap(); let domain = generate_domain(&omega, n); let permuted = generate_permutation_coefficients( - &omega, - n, + &domain, &json_input.Permutation, &ORDER_R_MINUS_1_ROOT_UNITY, ); diff --git a/provers/plonk/src/test_utils/utils.rs b/provers/plonk/src/test_utils/utils.rs index cecd0f1b0..ae1afeb86 100644 --- a/provers/plonk/src/test_utils/utils.rs +++ b/provers/plonk/src/test_utils/utils.rs @@ -34,9 +34,12 @@ pub fn test_srs(n: usize) -> StructuredReferenceString { let g1 = ::generator(); let g2 = ::generator(); - let powers_main_group: Vec = (0..n + 3) - .map(|exp| g1.operate_with_self(s.pow(exp as u64).representative())) - .collect(); + let powers_main_group: Vec = + core::iter::successors(Some(FieldElement::from(1)), |acc| Some(acc * &s)) + .take(n + 3) + .map(|power| power.representative()) + .map(|power| g1.operate_with_self(power)) + .collect(); let powers_secondary_group = [g2.clone(), g2.operate_with_self(s.representative())]; StructuredReferenceString::new(&powers_main_group, &powers_secondary_group) @@ -44,41 +47,42 @@ pub fn test_srs(n: usize) -> StructuredReferenceString { /// Generates a domain to interpolate: 1, omega, omega², ..., omega^size pub fn generate_domain(omega: &FieldElement, size: usize) -> Vec> { - (1..size).fold(vec![FieldElement::one()], |mut acc, _| { - acc.push(acc.last().unwrap() * omega); - acc - }) + core::iter::successors(Some(FieldElement::one()), |prev| Some(prev * omega)) + .take(size) + .collect() } /// Generates the permutation coefficients for the copy constraints. /// polynomials S1, S2, S3. pub fn generate_permutation_coefficients( - omega: &FieldElement, - n: usize, + domain: &[FieldElement], permutation: &[usize], order_r_minus_1_root_unity: &FieldElement, ) -> Vec> { - let identity = identity_permutation(omega, n, order_r_minus_1_root_unity); - let permuted: Vec> = (0..n * 3) - .map(|i| identity[permutation[i]].clone()) - .collect(); - permuted + let identity = identity_permutation(domain, order_r_minus_1_root_unity); + permutation + .iter() + .map(|perm| identity[*perm].clone()) + .collect() } /// The identity permutation, auxiliary function to generate the copy constraints. fn identity_permutation( - w: &FieldElement, - n: usize, + domain: &[FieldElement], order_r_minus_1_root_unity: &FieldElement, ) -> Vec> { let u = order_r_minus_1_root_unity; - let mut result: Vec> = vec![]; - for index_column in 0..=2 { - for index_row in 0..n { - result.push(w.pow(index_row) * u.pow(index_column as u64)); - } - } - result + let u_powers = [&FieldElement::one(), &u, &(u * u)]; + + (0..=2) + .map(|col| { + domain + .iter() + .map(|elem| elem * u_powers[col]) + .collect::>() + }) + .collect::>() + .concat() } /// A mock of a random number generator, to have deterministic tests.