diff --git a/Cargo.toml b/Cargo.toml index 208769c..0d51733 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,8 @@ blake2-rfc = {version = "0.2.18", optional = true} [features] #default = ["multicore"] -default = ["multicore", "gm17", "sonic"] +default = ["multicore", "sonic"] +#default = ["multicore", "gm17", "sonic"] #default = ["wasm"] multicore = ["futures-cpupool", "num_cpus", "crossbeam"] sonic = ["tiny-keccak", "blake2-rfc"] diff --git a/src/sonic/cs/mod.rs b/src/sonic/cs/mod.rs index 9049731..d7ad271 100644 --- a/src/sonic/cs/mod.rs +++ b/src/sonic/cs/mod.rs @@ -57,7 +57,7 @@ pub trait Backend { fn new_linear_constraint(&mut self) -> Self::LinearConstraintIndex; /// Insert a term into a linear constraint. TODO: bad name of function - fn insert_coefficient(&mut self, _var: Variable, _coeff: Coeff, y: &Self::LinearConstraintIndex) { } + fn insert_coefficient(&mut self, _var: Variable, _coeff: Coeff, _y: &Self::LinearConstraintIndex) { } /// Compute a `LinearConstraintIndex` from `q`. fn get_for_q(&self, q: usize) -> Self::LinearConstraintIndex; diff --git a/src/sonic/helped/helper.rs b/src/sonic/helped/helper.rs index b9763f9..30a0a3a 100644 --- a/src/sonic/helped/helper.rs +++ b/src/sonic/helped/helper.rs @@ -106,8 +106,6 @@ pub fn create_aggregate_on_srs_using_information, S: Sy let value = compute_value::(&w, &s_poly_positive, &s_poly_negative); - println!("Helper s(z, w) = {}", value); - let opening = { let mut value = value; value.negate(); diff --git a/src/sonic/sonic/backends.rs b/src/sonic/sonic/backends.rs index 175d5e8..f8b3e48 100644 --- a/src/sonic/sonic/backends.rs +++ b/src/sonic/sonic/backends.rs @@ -18,7 +18,7 @@ pub struct Preprocess { impl<'a, E: Engine> Backend for &'a mut Preprocess { type LinearConstraintIndex = (); - fn get_for_q(&self, q: usize) -> Self::LinearConstraintIndex { () } + fn get_for_q(&self, _q: usize) -> Self::LinearConstraintIndex { () } fn new_k_power(&mut self, index: usize) { self.k_map.push(index); @@ -57,7 +57,8 @@ impl<'a, E: Engine> Backend for &'a mut Wires { fn new_linear_constraint(&mut self) -> Self::LinearConstraintIndex { () } - fn get_for_q(&self, q: usize) -> Self::LinearConstraintIndex { () } + fn get_for_q(&self, _q: usize) -> Self::LinearConstraintIndex { () } + fn new_multiplication_gate(&mut self) { self.a.push(E::Fr::zero()); self.b.push(E::Fr::zero()); @@ -118,7 +119,7 @@ pub struct CountNandQ { impl<'a, E: Engine, S: SynthesisDriver> Backend for &'a mut CountNandQ { type LinearConstraintIndex = (); - fn get_for_q(&self, q: usize) -> Self::LinearConstraintIndex { () } + fn get_for_q(&self, _q: usize) -> Self::LinearConstraintIndex { () } fn new_multiplication_gate(&mut self) { self.n += 1; @@ -151,7 +152,7 @@ impl<'a, E: Engine, S: SynthesisDriver> Backend for &'a mut CountN { fn new_linear_constraint(&mut self) -> Self::LinearConstraintIndex { () } - fn get_for_q(&self, q: usize) -> Self::LinearConstraintIndex { () } + fn get_for_q(&self, _q: usize) -> Self::LinearConstraintIndex { () } fn new_multiplication_gate(&mut self) { self.n += 1; diff --git a/src/sonic/tests/sonics.rs b/src/sonic/tests/sonics.rs index 63a2b09..9ec55f3 100644 --- a/src/sonic/tests/sonics.rs +++ b/src/sonic/tests/sonics.rs @@ -505,10 +505,9 @@ fn test_succinct_sonic_mimc() { use crate::sonic::cs::{Circuit, ConstraintSystem, LinearCombination, Coeff}; - // let perm_structure = create_permutation_structure::(&AdaptorCircuit(circuit.clone())); let perm_structure = create_permutation_structure::(&AdaptorCircuit(circuit.clone())); let s1_srs = perm_structure.create_permutation_special_reference(&srs); - let s2_srs = perm_structure.calculate_s2_commitment_value(&srs); + // let s2_srs = perm_structure.calculate_s2_commitment_value(&srs); let info = get_circuit_parameters_for_succinct_sonic::(circuit.clone()).expect("Must get circuit info"); println!("{:?}", info); @@ -529,8 +528,6 @@ fn test_succinct_sonic_mimc() { let aggregate = create_aggregate_on_srs::(&AdaptorCircuit(circuit.clone()), &proofs, &srs, &s1_srs); println!("done in {:?}", start.elapsed()); - - let _ = crate::sonic::helped::helper::create_aggregate_on_srs::(&AdaptorCircuit(circuit.clone()), &proofs, &srs); // { // let rng = thread_rng(); // let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); @@ -561,14 +558,7 @@ fn test_succinct_sonic_mimc() { { use rand::{XorShiftRng, SeedableRng, Rand, Rng}; - let mut rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - let start = Instant::now(); - - // let aggregate = - // let (perm_commitments, s_prime_challenges, perm_proof, perm_arg_proof, z_prime, num_poly, s1_naive) = perm_structure.create_permutation_arguments(aggregate.w, aggregate.z, &mut rng, &srs); - // let s2_proof = perm_structure.calculate_s2_proof(aggregate.z, aggregate.w, &srs); - - // println!("Permutation argument done in {:?}", start.elapsed()); + let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut verifier = SuccinctMultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); println!("verifying 100 proofs with succinct advice"); @@ -581,7 +571,6 @@ fn test_succinct_sonic_mimc() { &proofs, &aggregate, &srs, - &s1_srs ); assert_eq!(verifier.check_all(), true); // TODO } diff --git a/src/sonic/unhelped/aggregate.rs b/src/sonic/unhelped/aggregate.rs index 701059e..6b3647e 100644 --- a/src/sonic/unhelped/aggregate.rs +++ b/src/sonic/unhelped/aggregate.rs @@ -115,12 +115,8 @@ pub fn create_aggregate_on_srs_using_information, S: Sy // Open C at w let w: E::Fr = transcript.get_challenge_scalar(); - println!("Aggregate: Z = {}, W = {}", z, w); - let value = compute_value::(&w, &s_poly_positive, &s_poly_negative); - println!("Aggregate: S(z,w) = {}", value); - let opening = { let mut value = value; value.negate(); diff --git a/src/sonic/unhelped/grand_product_argument.rs b/src/sonic/unhelped/grand_product_argument.rs index 1df65e9..58a1b19 100644 --- a/src/sonic/unhelped/grand_product_argument.rs +++ b/src/sonic/unhelped/grand_product_argument.rs @@ -49,7 +49,6 @@ impl GrandProductArgument { z: E::Fr, srs: &SRS, ) -> GrandProductSignature { - println!("Making grand product argument for {} grand products", grand_products.len()); let mut a_commitments = vec![]; let mut b_commitments = vec![]; @@ -160,15 +159,18 @@ 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_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} let mut c_coeff = E::Fr::one(); c_poly.push(c_coeff); @@ -238,29 +240,41 @@ impl GrandProductArgument { let mut results = vec![]; for a_poly in self.a_polynomials.iter() { - let a = & a_poly[0..n]; - let b = & a_poly[(n+1)..]; - assert_eq!(a.len(), n); - assert_eq!(b.len(), n); - let mut val = evaluate_at_consequitive_powers(a, yz, yz); - { - let tmp = yz.pow([(n+2) as u64]); - let v = evaluate_at_consequitive_powers(b, tmp, yz); - val.add_assign(&v); - } + assert_eq!(a_poly[n], E::Fr::zero()); // there is no term for n+1 power + let val = evaluate_at_consequitive_powers(&a_poly[..], yz, yz); + + // let a = & a_poly[0..n]; // powers [1, n] + // let b = & a_poly[(n+1)..]; // there is no n+1 term (numerated as `n`), skip it and start b + // assert_eq!(a.len(), n); + // assert_eq!(b.len(), n); + // let mut val = evaluate_at_consequitive_powers(a, yz, yz); + // { + // let tmp = yz.pow([(n+2) as u64]); + // let v = evaluate_at_consequitive_powers(b, tmp, yz); + // val.add_assign(&v); + // } let mut constant_term = val; constant_term.negate(); - let opening = polynomial_commitment_opening( + let opening = polynomial_commitment_opening( 0, 2*n + 1, Some(constant_term).iter() - .chain_ext(a.iter()) - .chain_ext(Some(E::Fr::zero()).iter()) - .chain_ext(b.iter()), + .chain_ext(a_poly.iter()), yz, - &srs); + &srs + ); + + // let opening = polynomial_commitment_opening( + // 0, + // 2*n + 1, + // Some(constant_term).iter() + // .chain_ext(a.iter()) + // .chain_ext(Some(E::Fr::zero()).iter()) + // .chain_ext(b.iter()), + // yz, + // &srs); results.push((val, opening)); @@ -274,11 +288,14 @@ impl GrandProductArgument { let mut results = vec![]; - let n = self.c_polynomials[0].len(); + let two_n_plus_1 = self.c_polynomials[0].len(); for (p, v) in self.c_polynomials.iter().zip(self.v_elements.iter()) { + let n = self.n; + assert_eq!(p[n], E::Fr::one(), "C_(n+1) must be one"); + let c = multiexp( - srs.g_positive_x_alpha[0..n].iter(), + srs.g_positive_x_alpha[0..two_n_plus_1].iter(), p.iter() ).into_affine(); @@ -421,6 +438,8 @@ impl GrandProductArgument { let z_inv = z.inverse().unwrap(); + let mut t_subcomponent = E::Fr::zero(); + for (((a, c), challenge), v) in a_zy.iter() .zip(c_polynomials.into_iter()) .zip(challenges.iter()) @@ -455,6 +474,9 @@ impl GrandProductArgument { let mut ry = y; ry.mul_assign(challenge); + t_subcomponent.add_assign(&rc); + t_subcomponent.sub_assign(&challenge); + if e_polynomial.is_some() && f_polynomial.is_some() { if let Some(e_poly) = e_polynomial.as_mut() { if let Some(f_poly) = f_polynomial.as_mut() { @@ -502,15 +524,24 @@ impl GrandProductArgument { e_val.negate(); f_val.negate(); + t_subcomponent.add_assign(&e_val); + t_subcomponent.sub_assign(&f_val); + let mut t_poly = self.t_polynomial.unwrap(); assert_eq!(t_poly.len(), 4*n + 3); + assert!(t_poly[2*n + 1].is_zero()); + // largest negative power of t is -2n-1 let t_zy = { let tmp = z_inv.pow([(2*n+1) as u64]); evaluate_at_consequitive_powers(&t_poly, tmp, z) }; + assert_eq!(t_zy, t_subcomponent); + + assert!(t_poly[2*n + 1].is_zero()); + t_poly[2*n + 1].sub_assign(&t_zy); let t_opening = polynomial_commitment_opening( @@ -529,7 +560,8 @@ impl GrandProductArgument { } } - pub fn verify_ab_commitment(n: usize, + pub fn verify_ab_commitment( + n: usize, randomness: & Vec, a_commitments: &Vec, b_commitments: &Vec, @@ -550,7 +582,8 @@ impl GrandProductArgument { let h_alpha_precomp = srs.h_positive_x_alpha[0].prepare(); - let mut h_x_n_plus_one_precomp = srs.h_positive_x[n]; + // H^(x^(n+1)) is n+1 indexed + let mut h_x_n_plus_one_precomp = srs.h_positive_x[n+1]; h_x_n_plus_one_precomp.negate(); let h_x_n_plus_one_precomp = h_x_n_plus_one_precomp.prepare(); @@ -760,17 +793,38 @@ fn test_grand_product_argument() { let srs_x = Fr::from_str("23923").unwrap(); let srs_alpha = Fr::from_str("23728792").unwrap(); - let srs = SRS::::dummy(830564, srs_x, srs_alpha); + // let srs = SRS::::dummy(830564, srs_x, srs_alpha); + let srs = SRS::::new(128, srs_x, srs_alpha); - let n: usize = 1 << 8; + let n: usize = 1 << 5; let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - let coeffs = (0..n).map(|_| Fr::rand(rng)).collect::>(); + let coeffs = (1..=n).map(|_| Fr::rand(rng)).collect::>(); let mut permutation = coeffs.clone(); rng.shuffle(&mut permutation); + let coeffs_product = coeffs.iter().fold(Fr::one(), |mut sum, x| { + sum.mul_assign(&x); + + sum + }); + + let permutation_product = permutation.iter().fold(Fr::one(), |mut sum, x| { + sum.mul_assign(&x); + + sum + }); + + assert_eq!(coeffs_product, permutation_product); + assert!(!coeffs_product.is_zero()); + let a_commitment = multiexp(srs.g_positive_x_alpha[0..n].iter(), coeffs.iter()).into_affine(); let b_commitment = multiexp(srs.g_positive_x_alpha[0..n].iter(), permutation.iter()).into_affine(); + let (a, b) = GrandProductArgument::commit_for_individual_products(&coeffs[..], &permutation[..], &srs); + + assert_eq!(a_commitment, a); + assert_eq!(b_commitment, b); + let mut argument = GrandProductArgument::new(vec![(coeffs, permutation)]); let commitments_and_v_values = argument.commit_to_individual_c_polynomials(&srs); @@ -789,14 +843,16 @@ fn test_grand_product_argument() { let randomness = (0..1).map(|_| Fr::rand(rng)).collect::>(); - let valid = GrandProductArgument::verify_ab_commitment(n, + let valid = GrandProductArgument::verify_ab_commitment( + n, &randomness, &vec![a_commitment], &vec![b_commitment], &grand_product_openings, y, z, - &srs); + &srs + ); assert!(valid, "grand product commitments should be valid"); diff --git a/src/sonic/unhelped/mod.rs b/src/sonic/unhelped/mod.rs index 616d07d..454a48d 100644 --- a/src/sonic/unhelped/mod.rs +++ b/src/sonic/unhelped/mod.rs @@ -5,7 +5,7 @@ mod s2_proof; mod wellformed_argument; -mod grand_product_argument; +pub mod grand_product_argument; mod permutation_argument; mod verifier; pub mod permutation_structure; diff --git a/src/sonic/unhelped/permutation_argument.rs b/src/sonic/unhelped/permutation_argument.rs index c04f2ba..c634ac6 100644 --- a/src/sonic/unhelped/permutation_argument.rs +++ b/src/sonic/unhelped/permutation_argument.rs @@ -55,19 +55,19 @@ pub struct SignatureOfCorrectComputation { pub grand_product_signature: GrandProductSignature } -fn permute(coeffs: &[F], permutation: & [usize]) -> Vec{ - assert_eq!(coeffs.len(), permutation.len()); - let mut result: Vec = vec![F::zero(); coeffs.len()]; - for (i, j) in permutation.iter().enumerate() { - // if *j < 1 { - // // if permutation information is missing coefficient itself must be zero! - // assert!(coeffs[i].is_zero()); - // continue; - // } - result[*j - 1] = coeffs[i]; - } - result -} +// fn permute(coeffs: &[F], permutation: & [usize]) -> Vec{ +// assert_eq!(coeffs.len(), permutation.len()); +// let mut result: Vec = vec![F::zero(); coeffs.len()]; +// for (i, j) in permutation.iter().enumerate() { +// // if *j < 1 { +// // // if permutation information is missing coefficient itself must be zero! +// // assert!(coeffs[i].is_zero()); +// // continue; +// // } +// result[*j - 1] = coeffs[i]; +// } +// result +// } fn permute_inverse(permuted_coeffs: &[F], permutation: & [usize]) -> Vec{ assert_eq!(permuted_coeffs.len(), permutation.len()); @@ -174,7 +174,7 @@ impl PermutationArgument { let mut non_permuted_at_y_coefficients = vec![]; // let mut permuted_coefficients = vec![]; - let mut permuted_at_y_coefficients = vec![]; + // let mut permuted_at_y_coefficients = vec![]; let mut inverse_permuted_at_y_coefficients = vec![]; // naive algorithms @@ -218,7 +218,7 @@ impl PermutationArgument { 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; + // self.permuted_at_y_coefficients = permuted_at_y_coefficients; self.inverse_permuted_at_y_coefficients = inverse_permuted_at_y_coefficients; result @@ -293,7 +293,6 @@ impl PermutationArgument { _specialized_srs: &SpecializedSRS, srs: &SRS ) -> PermutationArgumentProof { - panic!(""); // 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 @@ -304,8 +303,7 @@ impl PermutationArgument { let mut s_polynomial: Option> = None; - for c in self.permuted_at_y_coefficients.iter() - // for c in self.inverse_permuted_at_y_coefficients.iter() + for c in self.inverse_permuted_at_y_coefficients.iter() { if s_polynomial.is_some() { if let Some(poly) = s_polynomial.as_mut() { @@ -319,8 +317,6 @@ impl PermutationArgument { // evaluate at z let s_zy = evaluate_at_consequitive_powers(& s_polynomial[..], z, z); - println!("S_zy = {}", s_zy); - let mut s_zy_neg = s_zy; s_zy_neg.negate(); @@ -345,10 +341,9 @@ impl PermutationArgument { let mut grand_products = vec![]; - for (((non_permuted, inv_permuted), permutation), permuted) in self.non_permuted_at_y_coefficients.into_iter() + for ((non_permuted, inv_permuted), permutation) in self.non_permuted_at_y_coefficients.into_iter() .zip(self.inverse_permuted_at_y_coefficients.into_iter()) .zip(self.permutations.into_iter()) - .zip(self.permuted_at_y_coefficients.into_iter()) { // in S combination at the place i there should be term coeff[sigma(i)] * Y^sigma(i), that we can take @@ -356,7 +351,7 @@ impl PermutationArgument { // let mut s_combination = permute_inverse(&non_permuted[..], &permutation); let mut s_combination = inv_permuted; { - let p_4_values: Vec = permutation.clone().into_iter().map(|el| { + let p_4_values: Vec = permutation.into_iter().map(|el| { let mut repr = <::Fr as PrimeField>::Repr::default(); repr.as_mut()[0] = el as u64; let fe = E::Fr::from_repr(repr).unwrap(); @@ -367,19 +362,6 @@ impl PermutationArgument { mul_add_polynomials(&mut s_combination[..], & p_1_values[..], gamma); } - let mut s_combination_may_be = permuted; - { - let p_4_values: Vec = permutation.clone().into_iter().map(|el| { - let mut repr = <::Fr as PrimeField>::Repr::default(); - repr.as_mut()[0] = el as u64; - let fe = E::Fr::from_repr(repr).unwrap(); - - fe - }).collect(); - mul_add_polynomials(&mut s_combination_may_be[..], & p_4_values[..], beta); - mul_add_polynomials(&mut s_combination_may_be[..], & p_1_values[..], gamma); - } - // combination of coeff[i]*Y^i + beta * i + gamma let mut s_prime_combination = non_permuted.clone(); { @@ -403,15 +385,6 @@ impl PermutationArgument { sum }); - let s_product_may_be = s_combination_may_be.iter().fold(E::Fr::one(), |mut sum, x| - { - sum.mul_assign(&x); - - sum - }); - - println!("S = {}, S may be = {}, S' = {}", s_product, s_product_may_be, s_prime_product); - assert_eq!(s_product, s_prime_product, "product of coefficients must be the same"); grand_products.push((s_combination, s_prime_combination)); @@ -487,7 +460,7 @@ impl PermutationArgument { } pub fn verify_s_prime_commitment( - n: usize, + _n: usize, randomness: & Vec, challenges: & Vec, commitments: &Vec, @@ -699,9 +672,7 @@ impl PermutationArgument { srs: &SRS ) -> (PermutationArgumentProof, GrandProductSignature, E::Fr, E::Fr) { let beta: E::Fr = transcript.get_challenge_scalar(); - println!("Beta in prover = {}", beta); let gamma: E::Fr = transcript.get_challenge_scalar(); - println!("Gamma in prover = {}", gamma); // 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 @@ -797,6 +768,7 @@ impl PermutationArgument { }); assert_eq!(s_product, s_prime_product, "product of coefficients must be the same"); + assert!(!s_product.is_zero(), "grand products must not be zero"); grand_products.push((s_combination, s_prime_combination)); } @@ -829,7 +801,7 @@ fn test_permutation_argument() { let srs_x = Fr::from_str("23923").unwrap(); let srs_alpha = Fr::from_str("23728792").unwrap(); // let srs = SRS::::dummy(830564, srs_x, srs_alpha); - let srs = SRS::::new(1024, srs_x, srs_alpha); + let srs = SRS::::new(128, srs_x, srs_alpha); let n: usize = 1 << 4; let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); diff --git a/src/sonic/unhelped/permutation_structure.rs b/src/sonic/unhelped/permutation_structure.rs index 5633132..9484be1 100644 --- a/src/sonic/unhelped/permutation_structure.rs +++ b/src/sonic/unhelped/permutation_structure.rs @@ -383,7 +383,7 @@ impl PermutationStructure { for i in 0..m { let mut fillers: Vec = (1..=(3*n+1)).map(|el| el).collect(); - for (p, c) in permutations[i].iter_mut().zip(non_permuted_coeffs[i].iter()) { + for (p, _c) in permutations[i].iter_mut().zip(non_permuted_coeffs[i].iter()) { if *p == 0 { continue; // assert!(c.is_zero()); @@ -638,7 +638,7 @@ fn test_simple_succinct_sonic() { { use rand::{XorShiftRng, SeedableRng, Rand, Rng}; - let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + let _rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); use crate::sonic::sonic::Basic; use crate::sonic::sonic::AdaptorCircuit; @@ -672,7 +672,7 @@ fn test_simple_succinct_sonic() { for i in 0..non_permuted_coeffs[j].len() { let sigma_i = permutations[j][i]; let coeff_i = non_permuted_coeffs[j][i]; - let coeff_sigma_i = non_permuted_coeffs[j][sigma_i - 1]; + // let coeff_sigma_i = non_permuted_coeffs[j][sigma_i - 1]; let y_power = y.pow([sigma_i as u64]); let x_power = z.pow([(i+1) as u64]); diff --git a/src/sonic/unhelped/verifier.rs b/src/sonic/unhelped/verifier.rs index 4d57d81..97b7415 100644 --- a/src/sonic/unhelped/verifier.rs +++ b/src/sonic/unhelped/verifier.rs @@ -73,8 +73,7 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier &mut self, proofs: &[(Proof, SxyAdvice)], aggregate: &SuccinctAggregate, - srs: &SRS, - specialized_srs: &SpecializedSRS + srs: &SRS ) { let mut transcript = Transcript::new(&[]); @@ -95,8 +94,6 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier let w: E::Fr = transcript.get_challenge_scalar(); - println!("Verifier: Z = {}, W = {}", z, w); - let szw = { // prover will supply s1 and s2, need to calculate // s(z, w) = X^-(N+1) * Y^N * s1 - X^N * s2 @@ -246,13 +243,13 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier // from already known elements let beta: E::Fr = transcript.get_challenge_scalar(); - println!("Beta in verifier = {}", beta); let gamma: E::Fr = transcript.get_challenge_scalar(); - println!("Gamma in verifier = {}", gamma); let mut a_commitments = vec![]; let mut b_commitments = vec![]; + let mut wellformedness_argument_commitments = vec![]; + use crate::pairing::CurveAffine; use crate::pairing::ff::PrimeField; @@ -283,8 +280,13 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier a_commitments.push(a); b_commitments.push(b); + wellformedness_argument_commitments.push(a); + wellformedness_argument_commitments.push(b); } + // commitments to invidvidual grand products are assembled, now check first part of a grand + // product argument + // Now perform an actual check { let randomness: Vec = (0..aggregate.signature.s_commitments.len()).map(|_| self.randomness_source.gen()).collect(); @@ -294,7 +296,7 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier let h_alpha_x_precomp = srs.h_positive_x_alpha[1].prepare(); let h_alpha_precomp = srs.h_positive_x_alpha[0].prepare(); - let mut h_x_n_plus_one_precomp = srs.h_positive_x[self.n]; + let mut h_x_n_plus_one_precomp = srs.h_positive_x[self.n+1]; h_x_n_plus_one_precomp.negate(); let h_x_n_plus_one_precomp = h_x_n_plus_one_precomp.prepare(); @@ -352,42 +354,175 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier ])).unwrap() == E::Fqk::one(); // TODO - // assert!(valid, "grand product arguments must be valid for individual commitments"); + assert!(valid, "grand product arguments must be valid for individual commitments"); } + // Now the second part of the grand product argument - // 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())); + { + let mut grand_product_challenges = vec![]; - // assert!(lhs.into_affine() == *a); + for _ in 0..aggregate.signature.grand_product_signature.c_commitments.len() { + let c: E::Fr = transcript.get_challenge_scalar(); + grand_product_challenges.push(c); + } + // first re-calculate cj and t(z,y) - // // Sj′(P3j)β(P1j)γ + let mut yz = w; + yz.mul_assign(&z); - // 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())); + let z_inv = z.inverse().unwrap(); - // assert!(rhs.into_affine() == *b); - // } + let mut t_zy = E::Fr::zero(); + + let mut commitments_points = vec![]; + let mut rc_vec = vec![]; + let mut ry_vec = vec![]; + + // in grand product arguments n is not a number of gates, but 3n+1 - number of variables + 1 + let three_n_plus_1 = 3*self.n + 1; + + for ((r, commitment), (a, _)) in grand_product_challenges.iter() + .zip(aggregate.signature.grand_product_signature.c_commitments.iter()) + .zip(aggregate.signature.grand_product_signature.grand_product_openings.iter()) + { + let (c, v) = commitment; + commitments_points.push(*c); + + // cj = ((aj + vj(yz)n+1)y + zn+2 + zn+1y − z2n+2y)z−1 + let mut c_zy = yz.pow([(three_n_plus_1 + 1) as u64]); + c_zy.mul_assign(v); + c_zy.add_assign(a); + c_zy.mul_assign(&w); + + let mut z_n_plus_1 = z.pow([(three_n_plus_1 + 1) as u64]); + + let mut z_n_plus_2 = z_n_plus_1; + z_n_plus_2.mul_assign(&z); + + let mut z_2n_plus_2 = z_n_plus_1; + z_2n_plus_2.square(); + z_2n_plus_2.mul_assign(&w); + + z_n_plus_1.mul_assign(&w); + + c_zy.add_assign(&z_n_plus_1); + c_zy.add_assign(&z_n_plus_2); + c_zy.sub_assign(&z_2n_plus_2); + + c_zy.mul_assign(&z_inv); + + let mut rc = c_zy; + rc.mul_assign(&r); + rc_vec.push(rc); + + let mut ry = w; + ry.mul_assign(&r); + ry_vec.push(ry); + + let mut val = rc; + val.sub_assign(&r); + t_zy.add_assign(&val); + } + + t_zy.add_assign(&aggregate.signature.grand_product_signature.proof.e_zinv); + t_zy.sub_assign(&aggregate.signature.grand_product_signature.proof.f_y); + + // t(z, y) is now calculated + + let c_rc = multiexp( + commitments_points.iter(), + rc_vec.iter(), + ).into_affine(); + + let c_ry = multiexp( + commitments_points.iter(), + ry_vec.iter(), + ).into_affine(); + + // e(E,h^alphax)e(E^-z^-1,h^alpha) = e(\sumCj^(rj*cj),h)e(g^-e,h^alpha) + + { + let random: E::Fr = self.randomness_source.gen(); + + self.batch.add_opening(aggregate.signature.grand_product_signature.proof.e_opening, random, z_inv); + self.batch.add_opening_value(random, aggregate.signature.grand_product_signature.proof.e_zinv); + self.batch.add_commitment(c_rc, random); + } + + // e(F,h^alphax)e(F^-y,h) = e(\sumCj^(rj&y),h)e(g^-f,h^alpha) + + { + let random: E::Fr = self.randomness_source.gen(); + + self.batch.add_opening(aggregate.signature.grand_product_signature.proof.f_opening, random, w); + self.batch.add_opening_value(random, aggregate.signature.grand_product_signature.proof.f_y); + self.batch.add_commitment(c_ry, random); + } + + // e(T′,hαx)e(T′−z,hα) = e(T,h)e(g−t(z,y),hα) + + { + let random: E::Fr = self.randomness_source.gen(); + + self.batch.add_opening(aggregate.signature.grand_product_signature.proof.t_opening, random, z); + self.batch.add_opening_value(random, t_zy); + self.batch.add_commitment(aggregate.signature.grand_product_signature.t_commitment, random); + } + } + + // finally check the wellformedness arguments + + { + let mut wellformedness_challenges = vec![]; + + for _ in 0..wellformedness_argument_commitments.len() { + let c: E::Fr = transcript.get_challenge_scalar(); + wellformedness_challenges.push(c); + } + + let d = srs.d; + let n = 3*self.n + 1; // same as for grand products + + let alpha_x_d_precomp = srs.h_positive_x_alpha[d].prepare(); + // TODO: not strictly required + assert!(n < d); + let d_minus_n = d - n; + let alpha_x_n_minus_d_precomp = srs.h_negative_x_alpha[d_minus_n].prepare(); + let mut h_prep = srs.h_positive_x[0]; + h_prep.negate(); + let h_prep = h_prep.prepare(); + + let a = multiexp( + wellformedness_argument_commitments.iter(), + wellformedness_challenges.iter(), + ).into_affine(); + + let r1: E::Fr = self.randomness_source.gen(); + let r2: E::Fr = self.randomness_source.gen(); + + let mut r = r1; + r.add_assign(&r2); + let l_r1 = aggregate.signature.grand_product_signature.wellformedness_signature.proof.l.mul(r1.into_repr()).into_affine(); + let r_r2 = aggregate.signature.grand_product_signature.wellformedness_signature.proof.r.mul(r2.into_repr()).into_affine(); + + let a_r = a.mul(r.into_repr()).into_affine(); + + let valid = E::final_exponentiation(&E::miller_loop(&[ + (&a_r.prepare(), &h_prep), + (&l_r1.prepare(), &alpha_x_d_precomp), + (&r_r2.prepare(), &alpha_x_n_minus_d_precomp) + ])).unwrap() == E::Fqk::one(); + + assert!(valid, "wellformedness argument must be valid"); + } } szw }; - println!("Verifier: S(z,w) = {}", szw); - { let random: E::Fr = self.randomness_source.gen(); diff --git a/src/sonic/unhelped/wellformed_argument.rs b/src/sonic/unhelped/wellformed_argument.rs index 8f47c97..2020aa0 100644 --- a/src/sonic/unhelped/wellformed_argument.rs +++ b/src/sonic/unhelped/wellformed_argument.rs @@ -34,7 +34,6 @@ impl WellformednessArgument { srs: &SRS ) -> WellformednessSignature { let j = all_polys.len(); - println!("Making wellformedness argument for {} polys", j); let wellformed_argument = WellformednessArgument::new(all_polys); // TODO: remove commitments let commitments = wellformed_argument.commit(&srs); @@ -108,18 +107,21 @@ impl WellformednessArgument { let d = srs.d; + // TODO: it's not necessary to have n < d, fix later + assert!(n < d); - // here the multiplier is x^-d, so largest negative power is -(d - 1), smallest negative power is -(d - n) + // here the multiplier is x^-d, so largest negative power is -(d - 1), smallest negative power is - (d - n) + // H^{x^k} are labeled from 0 power, so we need to use proper indexes let l = multiexp( - srs.g_negative_x[(d - n)..d].iter().rev(), + srs.g_negative_x[(d - n)..=(d - 1)].iter().rev(), p0.iter() ).into_affine(); // here the multiplier is x^d-n, so largest positive power is d, smallest positive power is d - n + 1 let r = multiexp( - srs.g_positive_x[(d - n + 1)..].iter().rev(), + srs.g_positive_x[(d - n + 1)..=d].iter(), p0.iter() ).into_affine(); @@ -133,7 +135,10 @@ impl WellformednessArgument { let d = srs.d; let alpha_x_d_precomp = srs.h_positive_x_alpha[d].prepare(); - let alpha_x_n_minus_d_precomp = srs.h_negative_x_alpha[d - n].prepare(); + // TODO: not strictly required + assert!(n < d); + let d_minus_n = d - n; + let alpha_x_n_minus_d_precomp = srs.h_negative_x_alpha[d_minus_n].prepare(); let mut h_prep = srs.h_positive_x[0]; h_prep.negate(); let h_prep = h_prep.prepare(); @@ -175,11 +180,12 @@ fn test_argument() { let srs_x = Fr::from_str("23923").unwrap(); let srs_alpha = Fr::from_str("23728792").unwrap(); - let srs = SRS::::dummy(830564, srs_x, srs_alpha); + // let srs = SRS::::dummy(830564, srs_x, srs_alpha); + let srs = SRS::::new(128, srs_x, srs_alpha); - let n: usize = 1 << 16; + let n: usize = 1 << 5; let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - let coeffs = (0..n).map(|_| Fr::rand(rng)).collect::>(); + let coeffs = (1..=n).map(|_| Fr::rand(rng)).collect::>(); let argument = WellformednessArgument::new(vec![coeffs]); let challenges = (0..1).map(|_| Fr::rand(rng)).collect::>(); @@ -205,12 +211,12 @@ fn test_argument_soundness() { let n: usize = 1 << 8; let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - let coeffs = (0..n).map(|_| Fr::rand(rng)).collect::>(); + let coeffs = (1..=n).map(|_| Fr::rand(rng)).collect::>(); let argument = WellformednessArgument::new(vec![coeffs]); let commitments = argument.commit(&srs); - let coeffs = (0..n).map(|_| Fr::rand(rng)).collect::>(); + let coeffs = (1..=n).map(|_| Fr::rand(rng)).collect::>(); let argument = WellformednessArgument::new(vec![coeffs]); let challenges = (0..1).map(|_| Fr::rand(rng)).collect::>(); diff --git a/src/sonic/util.rs b/src/sonic/util.rs index 45efc93..a91cfa8 100644 --- a/src/sonic/util.rs +++ b/src/sonic/util.rs @@ -116,7 +116,7 @@ pub fn polynomial_commitment_opening< I: IntoIterator >( largest_negative_power: usize, - largest_positive_power: usize, + _largest_positive_power: usize, polynomial_coefficients: I, point: E::Fr, srs: &'a SRS, @@ -221,7 +221,7 @@ pub fn mut_evaluate_at_consequitive_powers<'a, F: Field> ( let mut acc = F::zero(); - for mut p in coeffs { + for p in coeffs { p.mul_assign(¤t_power); acc.add_assign(&p); @@ -268,7 +268,7 @@ pub fn mut_distribute_consequitive_powers<'a, F: Field> ( let mut current_power = base.pow(&[(i*chunk) as u64]); current_power.mul_assign(&first_power); - for mut p in coeffs_chunk { + for p in coeffs_chunk { p.mul_assign(¤t_power); current_power.mul_assign(&base); @@ -464,7 +464,7 @@ where /// Divides polynomial `a` in `x` by `x - b` with /// no remainder using fft. -pub fn parallel_kate_divison<'a, E: Engine, I: IntoIterator>(a: I, mut b: E::Fr) -> Vec +pub fn parallel_kate_divison<'a, E: Engine, I: IntoIterator>(a: I, b: E::Fr) -> Vec where I::IntoIter: DoubleEndedIterator + ExactSizeIterator, { @@ -1002,7 +1002,7 @@ fn test_mut_eval_at_powers() { { let mut tmp = x.pow(&[n as u64]); - for mut coeff in a.iter_mut() { + for coeff in a.iter_mut() { coeff.mul_assign(&tmp); acc.add_assign(&coeff); tmp.mul_assign(&x); @@ -1033,7 +1033,7 @@ fn test_mut_distribute_powers() { { let mut tmp = x.pow(&[n as u64]); - for mut coeff in a.iter_mut() { + for coeff in a.iter_mut() { coeff.mul_assign(&tmp); tmp.mul_assign(&x); }