diff --git a/src/sonic/tests/sonics.rs b/src/sonic/tests/sonics.rs index ebb8609..91dc9b1 100644 --- a/src/sonic/tests/sonics.rs +++ b/src/sonic/tests/sonics.rs @@ -31,7 +31,7 @@ use crate::{ SynthesisError }; -const MIMC_ROUNDS: usize = 2; +const MIMC_ROUNDS: usize = 322; fn mimc( mut xl: E::Fr, @@ -544,8 +544,8 @@ fn test_succinct_sonic_mimc() { let s1_srs = perm_structure.create_permutation_special_reference(&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); + let info = get_circuit_parameters_for_succinct_sonic::(circuit.clone()).expect("Must get circuit info"); + println!("{:?}", info); println!("creating proof"); let start = Instant::now(); @@ -609,36 +609,38 @@ 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 (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); - let n = perm_structure.n; - let z = aggregate.z; - let y = aggregate.w; - let z_inv = z.inverse().unwrap(); - let z_inv_n_plus_1 = z_inv.pow([(n+1) as u64]); - let z_n = z.pow([n as u64]); - let y_n = y.pow([n as u64]); + println!("Permutation argument done in {:?}", start.elapsed()); - println!("S_1 naive = {}", s1_naive); + // let n = perm_structure.n; + // let z = aggregate.z; + // let y = aggregate.w; + // let z_inv = z.inverse().unwrap(); + // let z_inv_n_plus_1 = z_inv.pow([(n+1) as u64]); + // let z_n = z.pow([n as u64]); + // let y_n = y.pow([n as u64]); - let mut s_1 = s1_naive; - s_1.mul_assign(&z_inv_n_plus_1); - s_1.mul_assign(&y_n); + // println!("S_1 naive = {}", s1_naive); - println!("S_1 multiplied = {}", s_1); + // let mut s_1 = s1_naive; + // s_1.mul_assign(&z_inv_n_plus_1); + // s_1.mul_assign(&y_n); - let mut s_2 = s2_proof.c_value; - s_2.add_assign(&s2_proof.d_value); - s_2.mul_assign(&z_n); + // println!("S_1 multiplied = {}", s_1); - s_1.sub_assign(&s_2); - println!("S naive = {}", s_1); + // let mut s_2 = s2_proof.c_value; + // s_2.add_assign(&s2_proof.d_value); + // s_2.mul_assign(&z_n); + + // s_1.sub_assign(&s_2); + // println!("S naive = {}", s_1); let mut verifier = SuccinctMultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying 100 proofs with advice"); + println!("verifying 100 proofs with succinct advice"); let start = Instant::now(); { for (ref proof, ref advice) in &proofs { diff --git a/src/sonic/unhelped/grand_product_argument.rs b/src/sonic/unhelped/grand_product_argument.rs index 1fd2b7c..808b95c 100644 --- a/src/sonic/unhelped/grand_product_argument.rs +++ b/src/sonic/unhelped/grand_product_argument.rs @@ -8,6 +8,8 @@ use std::marker::PhantomData; use crate::sonic::srs::SRS; use crate::sonic::util::*; +use crate::sonic::transcript::{Transcript, TranscriptProtocol}; +use super::wellformed_argument::{WellformednessSignature, WellformednessArgument}; #[derive(Clone)] pub struct GrandProductArgument { @@ -27,7 +29,82 @@ pub struct GrandProductProof { f_opening: E::G1Affine, } +#[derive(Clone)] +pub struct GrandProductSignature { + pub a_commitments: Vec, + pub b_commitments: Vec, + pub c_commitments: Vec<(E::G1Affine, E::Fr)>, + pub t_commitment: E::G1Affine, + pub grand_product_openings: Vec<(E::Fr, E::G1Affine)>, + // pub a_zy: Vec, + pub proof: GrandProductProof, + pub wellformedness_signature: WellformednessSignature, +} + impl GrandProductArgument { + pub fn create_signature( + grand_products: Vec<(Vec, Vec)>, + y: E::Fr, + z: E::Fr, + srs: &SRS, + ) -> GrandProductSignature { + let mut a_commitments = vec![]; + let mut b_commitments = vec![]; + + let mut transcript = Transcript::new(&[]); + let mut grand_product_challenges = vec![]; + + 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); + } + + let mut all_polys = vec![]; + for p in grand_products.iter() { + let (a, b) = p; + all_polys.push(a.clone()); + all_polys.push(b.clone()); + } + + let wellformedness_signature = WellformednessArgument::create_signature( + all_polys, + &srs + ); + + + let mut grand_product_argument = GrandProductArgument::new(grand_products); + let c_commitments = grand_product_argument.commit_to_individual_c_polynomials(&srs); + let t_commitment = grand_product_argument.commit_to_t_polynomial(&grand_product_challenges, y, &srs); + let grand_product_openings = grand_product_argument.open_commitments_for_grand_product(y, z, &srs); + let a_zy: Vec = grand_product_openings.iter().map(|el| el.0.clone()).collect(); + let proof = grand_product_argument.make_argument(&a_zy, &grand_product_challenges, y, z, &srs); + + GrandProductSignature { + a_commitments, + b_commitments, + c_commitments, + t_commitment, + grand_product_openings, + // a_zy, + proof, + wellformedness_signature + } + + } + + pub fn new(polynomials: Vec<(Vec, Vec)>) -> Self { assert!(polynomials.len() > 0); diff --git a/src/sonic/unhelped/permutation_argument.rs b/src/sonic/unhelped/permutation_argument.rs index 2ddbfad..bc8044f 100644 --- a/src/sonic/unhelped/permutation_argument.rs +++ b/src/sonic/unhelped/permutation_argument.rs @@ -9,7 +9,9 @@ use std::marker::PhantomData; use crate::sonic::srs::SRS; use crate::sonic::util::*; use super::wellformed_argument::{WellformednessArgument, WellformednessProof}; -use super::grand_product_argument::{GrandProductArgument, GrandProductProof}; +use super::grand_product_argument::{GrandProductArgument, GrandProductSignature}; + +use crate::sonic::transcript::{Transcript, TranscriptProtocol}; #[derive(Clone)] pub struct SpecializedSRS { @@ -43,6 +45,15 @@ pub struct PermutationArgumentProof { pub s_zy: E::Fr } +#[derive(Clone)] +pub struct SignatureOfCorrectComputation { + pub s_commitments: Vec, + pub s_prime_commitments: Vec, + pub perm_argument_proof: PermutationArgumentProof, + pub perm_proof: PermutationProof, + 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()]; @@ -158,7 +169,6 @@ impl PermutationArgument { let mut permuted_coefficients = vec![]; let mut permuted_at_y_coefficients = vec![]; - // naive algorithms // for every permutation poly // -- go throught all variable_idx @@ -311,8 +321,6 @@ impl PermutationArgument { let s_polynomial = s_polynomial.unwrap(); // evaluate at z let s_zy = evaluate_at_consequitive_powers(& s_polynomial[..], z, z); - println!("In permutation argument S1_(z, y) = {}", s_zy); - let mut s_zy_neg = s_zy; s_zy_neg.negate(); @@ -449,82 +457,6 @@ impl PermutationArgument { assert_eq!(randomness.len(), 2); assert_eq!(challenges.len(), commitments.len()); - // let g = srs.g_positive_x[0]; - - // 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_prep = srs.h_positive_x[0]; - // h_prep.negate(); - // let h_prep = h_prep.prepare(); - - // let value = proof.v_zy; - // let g_v = g.mul(value.into_repr()); - - // { - - // let mut minus_z_prime = z_prime; - // minus_z_prime.negate(); - - // let e_z = proof.e_opening.mul(minus_z_prime.into_repr()); - - // let mut h_alpha_term = e_z; - - // h_alpha_term.add_assign(&g_v); - - // let h_alpha_x_term = proof.e_opening; - - // let s_r = multiexp( - // commitments.iter(), - // challenges.iter() - // ).into_affine(); - - // let h_term = s_r; - - // let valid = E::final_exponentiation(&E::miller_loop(&[ - // (&h_alpha_x_term.prepare(), &h_alpha_x_precomp), - // (&h_alpha_term.into_affine().prepare(), &h_alpha_precomp), - // (&h_term.prepare(), &h_prep), - // ])).unwrap() == E::Fqk::one(); - - // if !valid { - // return false; - // } - // } - // { - // let mut minus_yz = z_prime; - // minus_yz.mul_assign(&y); - // minus_yz.negate(); - - // let f_yz = proof.f_opening.mul(minus_yz.into_repr()); - - // let p2_r = multiexp( - // specialized_srs.p_2.iter(), - // challenges.iter() - // ).into_affine(); - - // let mut h_alpha_term = f_yz; - - // h_alpha_term.add_assign(&g_v); - - // let h_alpha_x_term = proof.f_opening; - - // let h_term = p2_r; - - // let valid = E::final_exponentiation(&E::miller_loop(&[ - // (&h_alpha_x_term.prepare(), &h_alpha_x_precomp), - // (&h_alpha_term.into_affine().prepare(), &h_alpha_precomp), - // (&h_term.prepare(), &h_prep), - // ])).unwrap() == E::Fqk::one(); - - // if !valid { - // return false; - // } - // } - - // true - // e(E,hαx)e(E−z′,hα) = e(􏰗Mj=1Sj′rj,h)e(g−v,hα) // e(F,hαx)e(F−yz′,hα) = e(􏰗Mj=1P2jrj,h)e(g−v,hα) @@ -635,6 +567,162 @@ impl PermutationArgument { (&h_term.prepare(), &h_prep), ])).unwrap() == E::Fqk::one() } + + pub fn make_signature( + coefficients: Vec>, + permutations: Vec>, + y: E::Fr, + z: E::Fr, + srs: &SRS + ) -> SignatureOfCorrectComputation { + let mut argument = PermutationArgument::new(coefficients, permutations); + let commitments = argument.commit(y, &srs); + let mut transcript = Transcript::new(&[]); + + let mut s_commitments = vec![]; + let mut s_prime_commitments = vec![]; + let mut challenges = vec![]; + for (s, s_prime) in commitments.into_iter() { + { + let mut transcript = Transcript::new(&[]); + transcript.commit_point(&s); + transcript.commit_point(&s_prime); + let challenge = transcript.get_challenge_scalar(); + challenges.push(challenge); + } + transcript.commit_point(&s); + transcript.commit_point(&s_prime); + s_commitments.push(s); + s_prime_commitments.push(s_prime); + } + + 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 + ); + + SignatureOfCorrectComputation { + s_commitments, + s_prime_commitments, + perm_argument_proof: proof, + perm_proof: s_prime_commitments_opening, + grand_product_signature + } + + } + + // 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, + y: E::Fr, + z: E::Fr, + srs: &SRS + ) -> (PermutationArgumentProof, GrandProductSignature) { + // 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 + + let n = self.n; + let j = self.non_permuted_coefficients.len(); + + let mut s_polynomial: Option> = None; + + for c in self.permuted_at_y_coefficients.iter() + { + if s_polynomial.is_some() { + if let Some(poly) = s_polynomial.as_mut() { + add_polynomials(&mut poly[..], & c[..]); + } + } else { + s_polynomial = Some(c.clone()); + } + } + let s_polynomial = s_polynomial.unwrap(); + // evaluate at z + let s_zy = evaluate_at_consequitive_powers(& s_polynomial[..], z, z); + + let mut s_zy_neg = s_zy; + s_zy_neg.negate(); + + let s_zy_opening = polynomial_commitment_opening( + 0, + n, + Some(s_zy_neg).iter().chain_ext(s_polynomial.iter()), + z, + &srs + ); + + // Sj(P4j)^β (P1j)^γ is equal to the product of the coefficients of Sj′(P3j)^β (P1j)^γ + + let p_1_values = vec![E::Fr::one(); n]; + let p_3_values: Vec = (1..=n).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(); + + let mut grand_products = vec![]; + + for (i, ((non_permuted, permuted), permutation)) in self.non_permuted_coefficients.into_iter() + .zip(self.permuted_coefficients.into_iter()) + .zip(self.permutations.into_iter()).enumerate() + + { + // \prod si+βσi+γ = \prod s'i + β*i + γ + let mut s_j_combination = non_permuted; + { + 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(); + + fe + }).collect(); + mul_add_polynomials(&mut s_j_combination[..], & p_4_values[..], beta); + mul_add_polynomials(&mut s_j_combination[..], & p_1_values[..], gamma); + } + + let mut s_prime_j_combination = permuted; + { + mul_add_polynomials(&mut s_prime_j_combination[..], & p_3_values[..], beta); + mul_add_polynomials(&mut s_prime_j_combination[..], & p_1_values[..], gamma); + } + + grand_products.push((s_j_combination, s_prime_j_combination)); + } + + let grand_product_signature = GrandProductArgument::create_signature( + grand_products, + y, + z, + &srs + ); + + let proof = PermutationArgumentProof { + j: j, + s_opening: s_zy_opening, + s_zy: s_zy + }; + + (proof, grand_product_signature) + } + } #[test] diff --git a/src/sonic/unhelped/permutation_structure.rs b/src/sonic/unhelped/permutation_structure.rs index 2f48981..323bcf1 100644 --- a/src/sonic/unhelped/permutation_structure.rs +++ b/src/sonic/unhelped/permutation_structure.rs @@ -56,7 +56,7 @@ pub fn create_permutation_structure>( let n = backend.n; let q = backend.q; - println!("Will have {} gates and {} linear constraints", n, q); + // println!("Will have {} gates and {} linear constraints", n, q); PermutationStructure:: { n: n, @@ -369,8 +369,6 @@ impl PermutationStructure { } } - println!("naive s eval = {}", s_contrib); - let mut argument = PermutationArgument::new(non_permuted_coeffs, permutations); let challenges = (0..m).map(|_| E::Fr::rand(rng)).collect::>(); diff --git a/src/sonic/unhelped/wellformed_argument.rs b/src/sonic/unhelped/wellformed_argument.rs index 57b6e01..4eaaf32 100644 --- a/src/sonic/unhelped/wellformed_argument.rs +++ b/src/sonic/unhelped/wellformed_argument.rs @@ -7,6 +7,7 @@ use std::marker::PhantomData; use crate::sonic::srs::SRS; use crate::sonic::util::*; +use crate::sonic::transcript::{Transcript, TranscriptProtocol}; #[derive(Clone)] pub struct WellformednessArgument { @@ -15,11 +16,44 @@ pub struct WellformednessArgument { #[derive(Clone)] pub struct WellformednessProof { - l: E::G1Affine, - r: E::G1Affine + pub l: E::G1Affine, + pub r: E::G1Affine +} + +#[derive(Clone)] +pub struct WellformednessSignature { + pub commitments: Vec, + pub proof: WellformednessProof } impl WellformednessArgument { + + pub fn create_signature( + all_polys: 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); + } + + for _ in 0..j { + let challenge = transcript.get_challenge_scalar(); + wellformed_challenges.push(challenge); + } + + let proof = wellformed_argument.make_argument(wellformed_challenges, &srs); + + WellformednessSignature { + commitments, + proof + } + } + pub fn new(polynomials: Vec>) -> Self { assert!(polynomials.len() > 0);