From eaaff874fc17de7c266ad675d9ed5f92becdcacb Mon Sep 17 00:00:00 2001 From: Alex Vlasov Date: Fri, 7 Jun 2019 20:07:01 +0300 Subject: [PATCH] start eliminating excessive commitments --- src/sonic/unhelped/grand_product_argument.rs | 63 ++++++++----- src/sonic/unhelped/permutation_argument.rs | 98 ++++++++++++++++---- src/sonic/unhelped/permutation_structure.rs | 25 ++++- src/sonic/unhelped/wellformed_argument.rs | 18 ++-- 4 files changed, 150 insertions(+), 54 deletions(-) diff --git a/src/sonic/unhelped/grand_product_argument.rs b/src/sonic/unhelped/grand_product_argument.rs index 808b95c..8b6eed0 100644 --- a/src/sonic/unhelped/grand_product_argument.rs +++ b/src/sonic/unhelped/grand_product_argument.rs @@ -22,11 +22,11 @@ pub struct GrandProductArgument { #[derive(Clone)] pub struct GrandProductProof { - t_opening: E::G1Affine, - e_zinv: E::Fr, - e_opening: E::G1Affine, - f_y: E::Fr, - f_opening: E::G1Affine, + pub t_opening: E::G1Affine, + pub e_zinv: E::Fr, + pub e_opening: E::G1Affine, + pub f_y: E::Fr, + pub f_opening: E::G1Affine, } #[derive(Clone)] @@ -43,6 +43,7 @@ pub struct GrandProductSignature { impl GrandProductArgument { pub fn create_signature( + transcript: &mut Transcript, grand_products: Vec<(Vec, Vec)>, y: E::Fr, z: E::Fr, @@ -51,27 +52,27 @@ impl GrandProductArgument { let mut a_commitments = vec![]; let mut b_commitments = vec![]; - let mut transcript = Transcript::new(&[]); let mut grand_product_challenges = vec![]; + // TODO: Remove for (a, b) in grand_products.iter() { let (c_a, c_b) = GrandProductArgument::commit_for_individual_products(& a[..], & b[..], &srs); - { - let mut transcript = Transcript::new(&[]); - transcript.commit_point(&c_a); - let challenge = transcript.get_challenge_scalar(); - grand_product_challenges.push(challenge); - transcript.commit_point(&c_b); - let challenge = transcript.get_challenge_scalar(); - grand_product_challenges.push(challenge); - } a_commitments.push(c_a); b_commitments.push(c_b); - transcript.commit_point(&c_a); - transcript.commit_point(&c_b); + } + + for _ in 0..grand_products.len() { + let c = transcript.get_challenge_scalar(); + grand_product_challenges.push(c); } let mut all_polys = vec![]; + let mut wellformed_challenges = vec![]; + for c in 0..(grand_products.len()*2) { + let c = transcript.get_challenge_scalar(); + wellformed_challenges.push(c); + } + for p in grand_products.iter() { let (a, b) = p; all_polys.push(a.clone()); @@ -80,9 +81,22 @@ impl GrandProductArgument { let wellformedness_signature = WellformednessArgument::create_signature( all_polys, + wellformed_challenges, &srs ); + // sanity check + for (j, (a, b)) in a_commitments.iter() + .zip(b_commitments.iter()) + .enumerate() + { + let a_corr = wellformedness_signature.commitments[2*j]; + let b_corr = wellformedness_signature.commitments[2*j + 1]; + + assert!(a_corr == *a); + assert!(b_corr == *b); + } + let mut grand_product_argument = GrandProductArgument::new(grand_products); let c_commitments = grand_product_argument.commit_to_individual_c_polynomials(&srs); @@ -121,7 +135,7 @@ impl GrandProductArgument { // c_3 = a_3 * c_2 = a_3 * a_2 * a_1 // ... // c_n = a_n * c_{n-1} = \prod a_i - // a_{n+1} = c_{n-1}^-1 + // a_{n+1} = c_{n}^-1 // c_{n+1} = 1 // c_{n+1} = a_{n+2} * c_{n+1} = a_{n+2} // ... @@ -144,8 +158,14 @@ impl GrandProductArgument { } assert_eq!(c_poly.len(), n); a_poly.extend(p0); + assert_eq!(a_poly.len(), n); // v = a_{n+1} = c_{n}^-1 - let v = c_poly[n-1].inverse().unwrap(); + // let v = c_poly[n-1].inverse().unwrap(); + let v = c_coeff.inverse().unwrap(); + // ! IMPORTANT + // This line is indeed assigning a_{n+1} to zero instead of v + // for the practical purpose later we manually evaluate T polynomial + // and assign v to the term X^{n+1} a_poly.push(E::Fr::zero()); // a_poly.push(v); // add c_{n+1} @@ -160,6 +180,7 @@ impl GrandProductArgument { a_poly.extend(p1); assert_eq!(c_poly[n-1], c_poly[2*n]); + assert_eq!(c_poly[n], E::Fr::one()); a_polynomials.push(a_poly); c_polynomials.push(c_poly); @@ -280,7 +301,7 @@ impl GrandProductArgument { .zip(challenges.iter()) { let mut a_xy = a.clone(); - let mut c_xy = c.clone(); + let c_xy = c.clone(); let v = *v; assert_eq!(a_xy.len(), 2*n + 1); @@ -356,7 +377,7 @@ impl GrandProductArgument { val.add_assign(&E::Fr::one()); - // subtract at constant term + // subtract a constant term assert_eq!(t[2*n+1], val); t[2*n+1].sub_assign(&val); diff --git a/src/sonic/unhelped/permutation_argument.rs b/src/sonic/unhelped/permutation_argument.rs index bc8044f..f3fca7b 100644 --- a/src/sonic/unhelped/permutation_argument.rs +++ b/src/sonic/unhelped/permutation_argument.rs @@ -25,6 +25,7 @@ pub struct SpecializedSRS { #[derive(Clone)] pub struct PermutationArgument { non_permuted_coefficients: Vec>, + non_permuted_at_y_coefficients: Vec>, permuted_coefficients: Vec>, permuted_at_y_coefficients: Vec>, permutations: Vec>, @@ -96,6 +97,7 @@ impl PermutationArgument { PermutationArgument { non_permuted_coefficients: coefficients, + non_permuted_at_y_coefficients: vec![vec![]], permuted_coefficients: vec![vec![]], permuted_at_y_coefficients: vec![vec![]], permutations: permutations, @@ -166,6 +168,7 @@ impl PermutationArgument { let n = self.non_permuted_coefficients[0].len(); + let mut non_permuted_at_y_coefficients = vec![]; let mut permuted_coefficients = vec![]; let mut permuted_at_y_coefficients = vec![]; @@ -206,7 +209,6 @@ impl PermutationArgument { mut_distribute_consequitive_powers(&mut non_permuted_at_y[..], y, y); // and commit to S' let s_prime = multiexp(srs.g_positive_x_alpha[0..n].iter(), non_permuted_at_y.iter()).into_affine(); - drop(non_permuted_at_y); // this construction has already moved coeff[i] to the corresponding constraint k, so term is coeff[i]*Y^{K} for place K mut_distribute_consequitive_powers(&mut permuted_at_y[..], y, y); @@ -219,10 +221,12 @@ impl PermutationArgument { result.push((s, s_prime)); + non_permuted_at_y_coefficients.push(non_permuted_at_y); permuted_coefficients.push(permuted); permuted_at_y_coefficients.push(permuted_at_y); } + self.non_permuted_at_y_coefficients = non_permuted_at_y_coefficients; self.permuted_coefficients = permuted_coefficients; self.permuted_at_y_coefficients = permuted_at_y_coefficients; @@ -573,7 +577,8 @@ impl PermutationArgument { permutations: Vec>, y: E::Fr, z: E::Fr, - srs: &SRS + srs: &SRS, + specialized_srs: &SpecializedSRS, ) -> SignatureOfCorrectComputation { let mut argument = PermutationArgument::new(coefficients, permutations); let commitments = argument.commit(y, &srs); @@ -597,23 +602,45 @@ impl PermutationArgument { } let z_prime = transcript.get_challenge_scalar(); - // TODO: create better way to get few distinct challenges from the transcript - let mut transcript = Transcript::new(&[]); - transcript.commit_scalar(&z_prime); - let beta: E::Fr = transcript.get_challenge_scalar(); - let mut transcript = Transcript::new(&[]); - transcript.commit_scalar(&beta); - let gamma: E::Fr = transcript.get_challenge_scalar(); let s_prime_commitments_opening = argument.open_commitments_to_s_prime(&challenges, y, z_prime, &srs); - let (proof, grand_product_signature) = argument.make_argument_with_transcript( - beta, - gamma, - y, - z, - &srs - ); + let (proof, grand_product_signature) = { + // TODO: create better way to get few distinct challenges from the transcript + + let (proof, grand_product_signature) = argument.make_argument_with_transcript( + &mut transcript, + y, + z, + &srs + ); + + (proof, grand_product_signature) + }; + + // TODO: sanity check for now, + // later eliminate a and b commitments + // for (j, (((a, b), s), s_prime)) in grand_product_signature.a_commitments.iter() + // .zip(grand_product_signature.b_commitments.iter()) + // .zip(s_commitments.iter()) + // .zip(s_prime_commitments.iter()) + // .enumerate() + // { + // // Sj(P4j)β(P1j)γ + // let mut lhs = s.into_projective(); + // lhs.add_assign(&specialized_srs.p_4[j].mul(beta.into_repr())); + // lhs.add_assign(&specialized_srs.p_1.mul(gamma.into_repr())); + + // assert!(lhs.into_affine() == *a); + + // // Sj′(P3j)β(P1j)γ + + // let mut rhs = s_prime.into_projective(); + // rhs.add_assign(&specialized_srs.p_3.mul(beta.into_repr())); + // rhs.add_assign(&specialized_srs.p_1.mul(gamma.into_repr())); + + // assert!(rhs.into_affine() == *b); + // } SignatureOfCorrectComputation { s_commitments, @@ -627,12 +654,14 @@ impl PermutationArgument { // Argument a permutation argument. Current implementation consumes, cause extra arguments are required pub fn make_argument_with_transcript(self, - beta: E::Fr, - gamma: E::Fr, + transcript: &mut Transcript, y: E::Fr, z: E::Fr, srs: &SRS ) -> (PermutationArgumentProof, GrandProductSignature) { + let beta: E::Fr = transcript.get_challenge_scalar(); + let gamma: E::Fr = transcript.get_challenge_scalar(); + // Sj(P4j)β(P1j)γ is equal to the product of the coefficients of Sj′(P3j)β(P1j)γ // also open s = \sum self.permuted_coefficients(X, y) at z @@ -679,13 +708,22 @@ impl PermutationArgument { let mut grand_products = vec![]; - for (i, ((non_permuted, permuted), permutation)) in self.non_permuted_coefficients.into_iter() + // TODO: Check the validity! + + for ((non_permuted, permuted), permutation) in self.non_permuted_coefficients.into_iter() .zip(self.permuted_coefficients.into_iter()) - .zip(self.permutations.into_iter()).enumerate() + .zip(self.permutations.into_iter()) + + // for ((non_permuted, permuted), permutation) in self.non_permuted_at_y_coefficients.into_iter() + // .zip(self.permuted_at_y_coefficients.into_iter()) + // .zip(self.permutations.into_iter()) { // \prod si+βσi+γ = \prod s'i + β*i + γ + + // s combination is coeff[sigma(i)]*Y^{sigma(i)} + beta*sigma(i) + gamma let mut s_j_combination = non_permuted; + // let mut s_j_combination = permuted; { let p_4_values: Vec = permutation.into_iter().map(|el| { let mut repr = <::Fr as PrimeField>::Repr::default(); @@ -699,15 +737,35 @@ impl PermutationArgument { } let mut s_prime_j_combination = permuted; + // let mut s_prime_j_combination = non_permuted; + // s' combination is coeff[i]*Y^{i} + beta*i + gamma + { mul_add_polynomials(&mut s_prime_j_combination[..], & p_3_values[..], beta); mul_add_polynomials(&mut s_prime_j_combination[..], & p_1_values[..], gamma); } + // Sanity check + let product = s_j_combination.iter().fold(E::Fr::one(), |mut sum, x| + { + sum.mul_assign(&x); + + sum + }); + let product_prime = s_prime_j_combination.iter().fold(E::Fr::one(), |mut sum, x| + { + sum.mul_assign(&x); + + sum + }); + + assert_eq!(product, product_prime); + grand_products.push((s_j_combination, s_prime_j_combination)); } let grand_product_signature = GrandProductArgument::create_signature( + transcript, grand_products, y, z, diff --git a/src/sonic/unhelped/permutation_structure.rs b/src/sonic/unhelped/permutation_structure.rs index 323bcf1..70bed44 100644 --- a/src/sonic/unhelped/permutation_structure.rs +++ b/src/sonic/unhelped/permutation_structure.rs @@ -335,6 +335,25 @@ impl PermutationStructure { specialized_srs } + pub fn make_signature(&self, y: E::Fr, z: E::Fr, srs: &SRS) { + let (non_permuted_coeffs, permutations) = self.create_permutation_vectors(); + + let specialized_srs = PermutationArgument::make_specialized_srs( + &non_permuted_coeffs, + &permutations, + &srs + ); + + let signature = PermutationArgument::make_signature( + non_permuted_coeffs, + permutations, + y, + z, + &srs, + &specialized_srs + ); + } + pub fn create_permutation_arguments(&self, y: E::Fr, z: E::Fr, rng: &mut R, srs: &SRS) -> (Vec<(E::G1Affine, E::G1Affine)>, Vec, PermutationProof, PermutationArgumentProof, E::Fr, usize, E::Fr) { @@ -496,6 +515,7 @@ fn test_simple_succinct_sonic() { let perm_structure = create_permutation_structure::(&MyCircuit); perm_structure.create_permutation_arguments(x, y, rng, &srs); + perm_structure.make_signature(x, y, &srs); let s2 = S2Eval::new(perm_structure.n); let s2 = s2.evaluate(x, y, &srs); let mut s2_value = s2.c_value; @@ -521,13 +541,8 @@ fn test_simple_succinct_sonic() { expected_s2_value.add_assign(&p2); - println!("s2 value = {}", s2_value); - println!("expected s2 value = {}", expected_s2_value); - assert!(expected_s2_value == s2_value); - - println!("N = {}, Q = {}", perm_structure.n, perm_structure.q); } } \ No newline at end of file diff --git a/src/sonic/unhelped/wellformed_argument.rs b/src/sonic/unhelped/wellformed_argument.rs index 4eaaf32..df8ca61 100644 --- a/src/sonic/unhelped/wellformed_argument.rs +++ b/src/sonic/unhelped/wellformed_argument.rs @@ -30,21 +30,23 @@ impl WellformednessArgument { pub fn create_signature( all_polys: Vec>, + wellformed_challenges: Vec, srs: &SRS ) -> WellformednessSignature { let j = all_polys.len(); let mut transcript = Transcript::new(&[]); let wellformed_argument = WellformednessArgument::new(all_polys); let commitments = wellformed_argument.commit(&srs); - let mut wellformed_challenges = vec![]; - for c in commitments.iter() { - transcript.commit_point(c); - } + // let mut wellformed_challenges = vec![]; + // for c in commitments.iter() { + // transcript.commit_point(c); + // } - for _ in 0..j { - let challenge = transcript.get_challenge_scalar(); - wellformed_challenges.push(challenge); - } + // // TODO + // for _ in 0..j { + // let challenge = transcript.get_challenge_scalar(); + // wellformed_challenges.push(challenge); + // } let proof = wellformed_argument.make_argument(wellformed_challenges, &srs);