permutation argument is complete

This commit is contained in:
Alex Vlasov 2019-02-28 20:37:33 +03:00
parent 0a2ed705dc
commit 04454890b9
3 changed files with 372 additions and 449 deletions

@ -112,6 +112,24 @@ impl<E: Engine> GrandProductArgument<E> {
).into_affine() ).into_affine()
} }
// Make a commitment to a polynomial in a form A*B^{x+1} = [a_1...a_{n}, 0, b_1...b_{n}]
pub fn commit_for_individual_products(a: &[E::Fr], b: &[E::Fr], srs: &SRS<E>) -> (E::G1Affine, E::G1Affine) {
assert_eq!(a.len(), b.len());
let n = a.len();
let a = multiexp(
srs.g_positive_x_alpha[0..n].iter(),
a.iter()).into_affine();
let b = multiexp(
srs.g_positive_x_alpha[0..n].iter(),
b.iter()).into_affine();
(a, b)
}
pub fn open_commitments_for_grand_product(&self, y: E::Fr, z: E::Fr, srs: &SRS<E>) -> Vec<(E::Fr, E::G1Affine)> { pub fn open_commitments_for_grand_product(&self, y: E::Fr, z: E::Fr, srs: &SRS<E>) -> Vec<(E::Fr, E::G1Affine)> {
let n = self.n; let n = self.n;
@ -288,7 +306,6 @@ impl<E: Engine> GrandProductArgument<E> {
c c
} }
// Argument is based on an approach of main SONIC construction, but with a custom S(X,Y) polynomial of a simple form // Argument is based on an approach of main SONIC construction, but with a custom S(X,Y) polynomial of a simple form
pub fn make_argument(self, a_zy: & Vec<E::Fr>, challenges: & Vec<E::Fr>, y: E::Fr, z: E::Fr, srs: &SRS<E>) -> GrandProductProof<E> { pub fn make_argument(self, a_zy: & Vec<E::Fr>, challenges: & Vec<E::Fr>, y: E::Fr, z: E::Fr, srs: &SRS<E>) -> GrandProductProof<E> {
assert_eq!(a_zy.len(), self.a_polynomials.len()); assert_eq!(a_zy.len(), self.a_polynomials.len());

@ -8,6 +8,8 @@ use std::marker::PhantomData;
use crate::sonic::srs::SRS; use crate::sonic::srs::SRS;
use crate::sonic::util::*; use crate::sonic::util::*;
use super::wellformed_argument::{WellformednessArgument, WellformednessProof};
use super::grand_product_argument::{GrandProductArgument, GrandProductProof};
#[derive(Clone)] #[derive(Clone)]
pub struct SpecializedSRS<E: Engine> { pub struct SpecializedSRS<E: Engine> {
@ -22,6 +24,7 @@ pub struct SpecializedSRS<E: Engine> {
pub struct PermutationArgument<E: Engine> { pub struct PermutationArgument<E: Engine> {
non_permuted_coefficients: Vec<Vec<E::Fr>>, non_permuted_coefficients: Vec<Vec<E::Fr>>,
permuted_coefficients: Vec<Vec<E::Fr>>, permuted_coefficients: Vec<Vec<E::Fr>>,
permuted_at_y_coefficients: Vec<Vec<E::Fr>>,
permutations: Vec<Vec<usize>>, permutations: Vec<Vec<usize>>,
n: usize n: usize
} }
@ -33,12 +36,20 @@ pub struct PermutationProof<E: Engine> {
f_opening: E::G1Affine, f_opening: E::G1Affine,
} }
#[derive(Clone)]
pub struct Proof<E: Engine> {
j: usize,
s_opening: E::G1Affine,
s_zy: E::Fr
}
fn permute<F: Field>(coeffs: &[F], permutation: & [usize]) -> Vec<F>{ fn permute<F: Field>(coeffs: &[F], permutation: & [usize]) -> Vec<F>{
assert_eq!(coeffs.len(), permutation.len()); assert_eq!(coeffs.len(), permutation.len());
let mut result: Vec<F> = vec![F::zero(); coeffs.len()]; let mut result: Vec<F> = vec![F::zero(); coeffs.len()];
for (i, j) in permutation.iter().enumerate() { for (i, j) in permutation.iter().enumerate() {
result[*j] = coeffs[i]; result[*j - 1] = coeffs[i];
} }
result result
} }
@ -58,6 +69,7 @@ impl<E: Engine> PermutationArgument<E> {
PermutationArgument { PermutationArgument {
non_permuted_coefficients: coefficients, non_permuted_coefficients: coefficients,
permuted_coefficients: vec![vec![]], permuted_coefficients: vec![vec![]],
permuted_at_y_coefficients: vec![vec![]],
permutations: permutations, permutations: permutations,
n: n n: n
} }
@ -128,6 +140,7 @@ impl<E: Engine> PermutationArgument<E> {
let n = self.non_permuted_coefficients[0].len(); let n = self.non_permuted_coefficients[0].len();
let mut permuted_coefficients = vec![]; let mut permuted_coefficients = vec![];
let mut permuted_at_y_coefficients = vec![];
for (c, p) in self.non_permuted_coefficients.iter().zip(self.permutations.iter()) { for (c, p) in self.non_permuted_coefficients.iter().zip(self.permutations.iter()) {
let mut non_permuted = c.clone(); let mut non_permuted = c.clone();
@ -144,14 +157,22 @@ impl<E: Engine> PermutationArgument<E> {
result.push((s, s_prime)); result.push((s, s_prime));
permuted_coefficients.push(permuted); permuted_coefficients.push(permuted);
permuted_at_y_coefficients.push(permuted_at_y);
} }
self.permuted_coefficients = permuted_coefficients; self.permuted_coefficients = permuted_coefficients;
self.permuted_at_y_coefficients = permuted_at_y_coefficients;
result result
} }
pub fn open_commitments_to_s(&self, challenges: &Vec<E::Fr>, y: E::Fr, z_prime: E::Fr, srs: &SRS<E>) -> PermutationProof<E> { pub fn open_commitments_to_s_prime(
&self,
challenges: &Vec<E::Fr>,
y: E::Fr,
z_prime: E::Fr,
srs: &SRS<E>
) -> PermutationProof<E> {
let n = self.non_permuted_coefficients[0].len(); let n = self.non_permuted_coefficients[0].len();
let mut yz = y; let mut yz = y;
@ -168,7 +189,7 @@ impl<E: Engine> PermutationArgument<E> {
} else { } else {
let mut poly = p.clone(); let mut poly = p.clone();
mul_polynomial_by_scalar(&mut poly[..], *r); mul_polynomial_by_scalar(&mut poly[..], *r);
polynomial = Some(poly);
} }
} }
@ -178,7 +199,7 @@ impl<E: Engine> PermutationArgument<E> {
let mut v_neg = v; let mut v_neg = v;
v_neg.negate(); v_neg.negate();
let e = polynomial_commitment_opening( let f = polynomial_commitment_opening(
0, 0,
n, n,
Some(v_neg).iter().chain_ext(polynomial.iter()), Some(v_neg).iter().chain_ext(polynomial.iter()),
@ -188,7 +209,7 @@ impl<E: Engine> PermutationArgument<E> {
mut_distribute_consequitive_powers(&mut polynomial[..], y, y); mut_distribute_consequitive_powers(&mut polynomial[..], y, y);
let f = polynomial_commitment_opening( let e = polynomial_commitment_opening(
0, 0,
n, n,
Some(v_neg).iter().chain_ext(polynomial.iter()), Some(v_neg).iter().chain_ext(polynomial.iter()),
@ -203,268 +224,164 @@ impl<E: Engine> PermutationArgument<E> {
} }
} }
// // Make a commitment for the begining of the protocol, returns commitment and `v` scalar // Argument a permutation argument. Current implementation consumes, cause extra arguments are required
// pub fn commit_to_individual_c_polynomials(&self, srs: &SRS<E>) -> Vec<(E::G1Affine, E::Fr)> { pub fn make_argument(self,
beta: E::Fr,
// let mut results = vec![]; gamma: E::Fr,
grand_product_challenges: & Vec<E::Fr>,
// let n = self.c_polynomials[0].len(); wellformed_challenges: & Vec<E::Fr>,
y: E::Fr,
// for (p, v) in self.c_polynomials.iter().zip(self.v_elements.iter()) { z: E::Fr,
// let c = multiexp( specialized_srs: &SpecializedSRS<E>,
// srs.g_positive_x_alpha[0..n].iter(), srs: &SRS<E>
// p.iter() ) -> Proof<E> {
// ).into_affine(); // 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
// results.push((c, *v));
// } let n = self.n;
let j = self.non_permuted_coefficients.len();
// results assert_eq!(j, grand_product_challenges.len());
// } assert_eq!(2*j, wellformed_challenges.len());
// // Argument is based on an approach of main SONIC construction, but with a custom S(X,Y) polynomial of a simple form let mut s_polynomial: Option<Vec<E::Fr>> = None;
// pub fn commit_to_t_polynomial(&mut self, challenges: & Vec<E::Fr>, y: E::Fr, srs: &SRS<E>) -> E::G1Affine {
// assert_eq!(challenges.len(), self.a_polynomials.len()); for c in self.permuted_at_y_coefficients.iter()
{
// let n = self.n; if s_polynomial.is_some() {
if let Some(poly) = s_polynomial.as_mut() {
// let mut t_polynomial: Option<Vec<E::Fr>> = None; add_polynomials(&mut poly[..], & c[..]);
}
// for (((a, c), v), challenge) in self.a_polynomials.iter() } else {
// .zip(self.c_polynomials.iter()) s_polynomial = Some(c.clone());
// .zip(self.v_elements.iter()) }
// .zip(challenges.iter()) }
// { let mut s_polynomial = s_polynomial.unwrap();
// let mut a_xy = a.clone(); // evaluate at z
// let mut c_xy = c.clone(); let s_zy = evaluate_at_consequitive_powers(& s_polynomial[..], z, z);
// let v = *v;
let mut s_zy_neg = s_zy;
// assert_eq!(a_xy.len(), 2*n + 1); s_zy_neg.negate();
// assert_eq!(c_xy.len(), 2*n + 1);
let s_zy_opening = polynomial_commitment_opening(
// // make a T polynomial 0,
n,
// let r: Vec<E::Fr> = { Some(s_zy_neg).iter().chain_ext(s_polynomial.iter()),
// // p_a(X,Y)*Y z,
// let mut tmp = y; &srs
// tmp.square(); );
// mut_distribute_consequitive_powers(&mut a_xy[..], tmp, y);
// Sj(P4j)^β (P1j)^γ is equal to the product of the coefficients of Sj(P3j)^β (P1j)^γ
// // add extra terms
// //v*(XY)^{n+1}*Y + X^{n+2} + X^{n+1}Y X^{2n+2}*Y let p_1_values = vec![E::Fr::one(); n];
let p_3_values: Vec<E::Fr> = (1..=n).map(|el| {
// // n+1 term v*(XY)^{n+1}*Y + X^{n+1}Y let mut repr = <<E as ScalarEngine>::Fr as PrimeField>::Repr::default();
// let tmp = y.pow(&[(n+2) as u64]); repr.as_mut()[0] = el as u64;
// let mut x_n_plus_one_term = v; let fe = E::Fr::from_repr(repr).unwrap();
// x_n_plus_one_term.mul_assign(&tmp);
// x_n_plus_one_term.add_assign(&y); fe
// a_xy[n].add_assign(&x_n_plus_one_term); }).collect();
// // n+2 term let mut grand_products = vec![];
// a_xy[n+1].add_assign(&E::Fr::one());
for (i, ((non_permuted, permuted), permutation)) in self.non_permuted_coefficients.into_iter()
// // 2n+2 term .zip(self.permuted_coefficients.into_iter())
// let mut tmp = y; .zip(self.permutations.into_iter()).enumerate()
// tmp.negate();
{
// a_xy.push(tmp); // \prod si+βσi+γ = \prod s'i + β*i + γ
let mut s_j_combination = non_permuted;
// assert_eq!(a_xy.len(), 2*n + 2); {
let p_4_values: Vec<E::Fr> = permutation.into_iter().map(|el| {
// let mut r = vec![E::Fr::zero(); 2*n + 3]; let mut repr = <<E as ScalarEngine>::Fr as PrimeField>::Repr::default();
// r.extend(a_xy); repr.as_mut()[0] = el as u64;
let fe = E::Fr::from_repr(repr).unwrap();
// r
// }; fe
}).collect();
// let r_prime: Vec<E::Fr> = { mul_add_polynomials(&mut s_j_combination[..], & p_4_values[..], beta);
// let mut c_prime: Vec<E::Fr> = c_xy.iter().rev().map(|el| *el).collect(); mul_add_polynomials(&mut s_j_combination[..], & p_1_values[..], gamma);
// c_prime.push(E::Fr::one()); }
// c_prime.push(E::Fr::zero());
let mut s_prime_j_combination = permuted;
// assert_eq!(c_prime.len(), 2*n + 3); {
mul_add_polynomials(&mut s_prime_j_combination[..], & p_3_values[..], beta);
// c_prime mul_add_polynomials(&mut s_prime_j_combination[..], & p_1_values[..], gamma);
// }; }
// // multiply polynomials with powers [-2n-2, -1] and [1, 2n+2], grand_products.push((s_j_combination, s_prime_j_combination));
// // expect result to be [-2n+1, 2n+1] }
// let mut t: Vec<E::Fr> = multiply_polynomials::<E>(r, r_prime);
let mut a_commitments = vec![];
// assert_eq!(t.len(), 6*n + 7); let mut b_commitments = vec![];
// // drain first powers due to the padding and last element due to requirement of being zero for (a, b) in grand_products.iter() {
// for (i, el) in t[0..(2*n+3)].iter().enumerate() { let (c_a, c_b) = GrandProductArgument::commit_for_individual_products(& a[..], & b[..], &srs);
// assert_eq!(*el, E::Fr::zero(), "{}", format!("Element {} is non-zero", i)); a_commitments.push(c_a);
// } b_commitments.push(c_b);
}
// t.drain(0..(2*n+3));
// let last = t.pop(); {
// assert_eq!(last.unwrap(), E::Fr::zero(), "last element should be zero"); let mut all_polys = vec![];
for p in grand_products.iter() {
// assert_eq!(t.len(), 4*n + 3); let (a, b) = p;
all_polys.push(a.clone());
// let mut val = { all_polys.push(b.clone());
// let mut tmp = y; }
// tmp.square();
// evaluate_at_consequitive_powers(&c_xy, tmp, y) let wellformed_argument = WellformednessArgument::new(all_polys);
// }; let commitments = wellformed_argument.commit(&srs);
let proof = wellformed_argument.make_argument(wellformed_challenges.clone(), &srs);
// val.add_assign(&E::Fr::one()); let valid = WellformednessArgument::verify(n, &wellformed_challenges, &commitments, &proof, &srs);
// // subtract at constant term assert!(valid, "wellformedness argument must be valid");
// assert_eq!(t[2*n+1], val); }
// t[2*n+1].sub_assign(&val); let mut grand_product_argument = GrandProductArgument::new(grand_products);
let c_commitments = grand_product_argument.commit_to_individual_c_polynomials(&srs);
// if t_polynomial.is_some() { let t_commitment = grand_product_argument.commit_to_t_polynomial(&grand_product_challenges, y, &srs);
// if let Some(t_poly) = t_polynomial.as_mut() { let grand_product_openings = grand_product_argument.open_commitments_for_grand_product(y, z, &srs);
// mul_add_polynomials(&mut t_poly[..], &t, *challenge); let a_zy: Vec<E::Fr> = 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);
// } else {
// mul_polynomial_by_scalar(&mut t, *challenge); {
// t_polynomial = Some(t); use rand::{XorShiftRng, SeedableRng, Rand, Rng};
// } let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
// } let randomness = (0..j).map(|_| E::Fr::rand(rng)).collect::<Vec<_>>();
// let t_polynomial = t_polynomial.unwrap(); let valid = GrandProductArgument::verify_ab_commitment(n,
&randomness,
// let c = multiexp(srs.g_negative_x_alpha[0..(2*n+1)].iter().rev() &a_commitments,
// .chain_ext(srs.g_positive_x_alpha[0..(2*n+1)].iter()), & b_commitments,
// t_polynomial[0..(2*n+1)].iter() &grand_product_openings,
// .chain_ext(t_polynomial[(2*n+2)..].iter())).into_affine(); y,
z,
// self.t_polynomial = Some(t_polynomial); &srs);
assert!(valid, "ab part of grand product argument must be valid");
// c
// } let randomness = (0..3).map(|_| E::Fr::rand(rng)).collect::<Vec<_>>();
let valid = GrandProductArgument::verify(n,
&randomness,
// // Argument is based on an approach of main SONIC construction, but with a custom S(X,Y) polynomial of a simple form &a_zy,
// pub fn make_argument(self, a_zy: & Vec<E::Fr>, challenges: & Vec<E::Fr>, y: E::Fr, z: E::Fr, srs: &SRS<E>) -> GrandProductProof<E> { &grand_product_challenges,
// assert_eq!(a_zy.len(), self.a_polynomials.len()); t_commitment,
// assert_eq!(challenges.len(), self.a_polynomials.len()); &c_commitments,
&proof,
// let n = self.n; y,
z,
// let c_polynomials = self.c_polynomials; &srs);
// let mut e_polynomial: Option<Vec<E::Fr>> = None;
// let mut f_polynomial: Option<Vec<E::Fr>> = None; assert!(valid, "grand product argument must be valid");
}
// let mut yz = y;
// yz.mul_assign(&z); Proof {
j: j,
// let z_inv = z.inverse().unwrap(); s_opening: s_zy_opening,
s_zy: s_zy
// for (((a, c), challenge), v) in a_zy.iter() }
// .zip(c_polynomials.into_iter()) }
// .zip(challenges.iter())
// .zip(self.v_elements.iter()) pub fn verify_s_prime_commitment(
// { n: usize,
// // cj = ((aj + vj(yz)n+1)y + zn+2 + zn+1y z2n+2y)z1
// let mut c_zy = yz.pow([(n + 1) as u64]);
// c_zy.mul_assign(v);
// c_zy.add_assign(a);
// c_zy.mul_assign(&y);
// let mut z_n_plus_1 = z.pow([(n + 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(&y);
// z_n_plus_1.mul_assign(&y);
// 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(challenge);
// let mut ry = y;
// ry.mul_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() {
// mul_add_polynomials(&mut e_poly[..], &c, rc);
// mul_add_polynomials(&mut f_poly[..], &c, ry);
// }
// }
// } else {
// let mut e = c.clone();
// let mut f = c;
// mul_polynomial_by_scalar(&mut e, rc);
// mul_polynomial_by_scalar(&mut f, ry);
// e_polynomial = Some(e);
// f_polynomial = Some(f);
// }
// }
// let e_polynomial = e_polynomial.unwrap();
// let f_polynomial = f_polynomial.unwrap();
// // evaluate e at z^-1
// let mut e_val = evaluate_at_consequitive_powers(&e_polynomial, z_inv, z_inv);
// e_val.negate();
// // evaluate f at y
// let mut f_val = evaluate_at_consequitive_powers(&f_polynomial, y, y);
// f_val.negate();
// let e_opening = polynomial_commitment_opening(
// 0,
// 2*n + 1,
// Some(e_val).iter().chain_ext(e_polynomial.iter()),
// z_inv,
// srs);
// let f_opening = polynomial_commitment_opening(
// 0,
// 2*n + 1,
// Some(f_val).iter().chain_ext(f_polynomial.iter()),
// y,
// srs);
// e_val.negate();
// f_val.negate();
// let mut t_poly = self.t_polynomial.unwrap();
// assert_eq!(t_poly.len(), 4*n + 3);
// // 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)
// };
// t_poly[2*n + 1].sub_assign(&t_zy);
// let t_opening = polynomial_commitment_opening(
// 2*n + 1,
// 2*n + 1,
// t_poly.iter(),
// z,
// srs);
// GrandProductProof {
// t_opening: t_opening,
// e_zinv: e_val,
// e_opening: e_opening,
// f_y: f_val,
// f_opening: f_opening,
// }
// }
pub fn verify_s_prime_commitment(n: usize,
randomness: & Vec<E::Fr>, randomness: & Vec<E::Fr>,
challenges: & Vec<E::Fr>, challenges: & Vec<E::Fr>,
commitments: &Vec<E::G1Affine>, commitments: &Vec<E::G1Affine>,
@ -477,6 +394,82 @@ impl<E: Engine> PermutationArgument<E> {
assert_eq!(randomness.len(), 2); assert_eq!(randomness.len(), 2);
assert_eq!(challenges.len(), commitments.len()); 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(Ez,hα) = e(􏰗Mj=1Sjrj,h)e(gv,hα) // e(E,hαx)e(Ez,hα) = e(􏰗Mj=1Sjrj,h)e(gv,hα)
// e(F,hαx)e(Fyz,hα) = e(􏰗Mj=1P2jrj,h)e(gv,hα) // e(F,hαx)e(Fyz,hα) = e(􏰗Mj=1P2jrj,h)e(gv,hα)
@ -545,217 +538,129 @@ impl<E: Engine> PermutationArgument<E> {
])).unwrap() == E::Fqk::one() ])).unwrap() == E::Fqk::one()
} }
// pub fn verify( pub fn verify(
// n: usize, s_commitments: &Vec<E::G1Affine>,
// randomness: & Vec<E::Fr>, proof: &Proof<E>,
// a_zy: & Vec<E::Fr>, z: E::Fr,
// challenges: &Vec<E::Fr>, srs: &SRS<E>
// t_commitment: E::G1Affine, ) -> bool {
// commitments: &Vec<(E::G1Affine, E::Fr)>,
// proof: &GrandProductProof<E>,
// y: E::Fr,
// z: E::Fr,
// srs: &SRS<E>
// ) -> bool {
// assert_eq!(randomness.len(), 3);
// assert_eq!(a_zy.len(), challenges.len());
// assert_eq!(commitments.len(), challenges.len());
// let d = srs.d; let g = srs.g_positive_x[0];
// let g = srs.g_positive_x[0]; let h_alpha_x_precomp = srs.h_positive_x_alpha[1].prepare();
// let h_alpha_x_precomp = srs.h_positive_x_alpha[1].prepare(); let h_alpha_precomp = srs.h_positive_x_alpha[0].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 mut h_prep = srs.h_positive_x[0]; let mut minus_z = z;
// h_prep.negate(); minus_z.negate();
// let h_prep = h_prep.prepare();
// // first re-calculate cj and t(z,y) let opening_z = proof.s_opening.mul(minus_z.into_repr());
// let mut yz = y; let mut h_alpha_term = opening_z;
// yz.mul_assign(&z); let g_s = g.mul(proof.s_zy.into_repr());
// let z_inv = z.inverse().unwrap(); h_alpha_term.add_assign(&g_s);
// let mut t_zy = E::Fr::zero(); let h_alpha_x_term = proof.s_opening;
// t_zy.add_assign(&proof.e_zinv);
// t_zy.sub_assign(&proof.f_y);
// let mut commitments_points = vec![]; let mut s = E::G1::zero();
// let mut rc_vec = vec![]; for p in s_commitments {
// let mut ry_vec = vec![]; s.add_assign_mixed(&p);
}
// for ((r, commitment), a) in challenges.iter() let h_term = s.into_affine();
// .zip(commitments.iter())
// .zip(a_zy.iter()) {
// let (c, v) = commitment;
// commitments_points.push(c.clone());
// // cj = ((aj + vj(yz)n+1)y + zn+2 + zn+1y z2n+2y)z1 E::final_exponentiation(&E::miller_loop(&[
// let mut c_zy = yz.pow([(n + 1) as u64]); (&h_alpha_x_term.prepare(), &h_alpha_x_precomp),
// c_zy.mul_assign(v); (&h_alpha_term.into_affine().prepare(), &h_alpha_precomp),
// c_zy.add_assign(a); (&h_term.prepare(), &h_prep),
// c_zy.mul_assign(&y); ])).unwrap() == E::Fqk::one()
}
// let mut z_n_plus_1 = z.pow([(n + 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(&y);
// z_n_plus_1.mul_assign(&y);
// 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 = y;
// ry.mul_assign(&r);
// ry_vec.push(ry);
// let mut val = rc;
// val.sub_assign(r);
// t_zy.add_assign(&val);
// }
// let c_rc = multiexp(
// commitments_points.iter(),
// rc_vec.iter(),
// ).into_affine();
// let c_ry = multiexp(
// commitments_points.iter(),
// ry_vec.iter(),
// ).into_affine();
// let mut minus_y = y;
// minus_y.negate();
// let mut f_y = proof.f_opening.mul(minus_y.into_repr());
// let g_f = g.mul(proof.f_y.into_repr());
// f_y.add_assign(&g_f);
// let mut minus_z = z;
// minus_z.negate();
// let mut t_z = proof.t_opening.mul(minus_z.into_repr());
// let g_tzy = g.mul(t_zy.into_repr());
// t_z.add_assign(&g_tzy);
// let mut minus_z_inv = z_inv;
// minus_z_inv.negate();
// let mut e_z_inv = proof.e_opening.mul(minus_z_inv.into_repr());
// let g_e = g.mul(proof.e_zinv.into_repr());
// e_z_inv.add_assign(&g_e);
// let h_alpha_term = multiexp(
// vec![e_z_inv.into_affine(), f_y.into_affine(), t_z.into_affine()].iter(),
// randomness.iter(),
// ).into_affine();
// let h_alpha_x_term = multiexp(
// Some(proof.e_opening).iter()
// .chain_ext(Some(proof.f_opening).iter())
// .chain_ext(Some(proof.t_opening).iter()),
// randomness.iter(),
// ).into_affine();
// let h_term = multiexp(
// Some(c_rc).iter()
// .chain_ext(Some(c_ry).iter())
// .chain_ext(Some(t_commitment).iter()),
// randomness.iter(),
// ).into_affine();
// E::final_exponentiation(&E::miller_loop(&[
// (&h_alpha_x_term.prepare(), &h_alpha_x_precomp),
// (&h_alpha_term.prepare(), &h_alpha_precomp),
// (&h_term.prepare(), &h_prep),
// ])).unwrap() == E::Fqk::one()
// }
} }
// #[test] #[test]
// fn test_grand_product_argument() { fn test_permutation_argument() {
// use pairing::bls12_381::{Fr, G1Affine, G1, Bls12}; use pairing::bls12_381::{Fr, G1Affine, G1, Bls12};
// use rand::{XorShiftRng, SeedableRng, Rand, Rng}; use rand::{XorShiftRng, SeedableRng, Rand, Rng};
// use crate::sonic::srs::SRS; use crate::sonic::srs::SRS;
// let srs_x = Fr::from_str("23923").unwrap(); let srs_x = Fr::from_str("23923").unwrap();
// let srs_alpha = Fr::from_str("23728792").unwrap(); let srs_alpha = Fr::from_str("23728792").unwrap();
// let srs = SRS::<Bls12>::dummy(830564, srs_x, srs_alpha); let srs = SRS::<Bls12>::dummy(830564, srs_x, srs_alpha);
// let n: usize = 1 << 8; let n: usize = 1 << 1;
// let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
// let coeffs = (0..n).map(|_| Fr::rand(rng)).collect::<Vec<_>>(); // let coeffs = (0..n).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
// let mut permutation = coeffs.clone(); // let mut permutation = (0..n).collect::<Vec<_>>();
// rng.shuffle(&mut permutation); // rng.shuffle(&mut permutation);
// let a_commitment = multiexp(srs.g_positive_x_alpha[0..n].iter(), coeffs.iter()).into_affine(); let coeffs = vec![Fr::from_str("3").unwrap(), Fr::from_str("4").unwrap()];
// let b_commitment = multiexp(srs.g_positive_x_alpha[0..n].iter(), permutation.iter()).into_affine(); let permutation = vec![2, 1];
// let mut argument = GrandProductArgument::new(vec![(coeffs, permutation)]); let coeffs = vec![coeffs];
let permutations = vec![permutation];
// let commitments_and_v_values = argument.commit_to_individual_c_polynomials(&srs); let specialized_srs = PermutationArgument::make_specialized_srs(&coeffs, &permutations, &srs);
// assert_eq!(commitments_and_v_values.len(), 1); let mut argument = PermutationArgument::new(coeffs, permutations);
// let y : Fr = rng.gen(); let y : Fr = rng.gen();
let y : Fr = Fr::one();
let y : Fr = Fr::from_str("2").unwrap();
// let challenges = (0..1).map(|_| Fr::rand(rng)).collect::<Vec<_>>(); // let challenges = (0..1).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
// let t_commitment = argument.commit_to_t_polynomial(&challenges, y, &srs); let challenges = vec![Fr::one()];
// let z : Fr = rng.gen(); let commitments = argument.commit(y, &srs);
let mut s_commitments = vec![];
let mut s_prime_commitments = vec![];
for (s, s_prime) in commitments.into_iter() {
s_commitments.push(s);
s_prime_commitments.push(s_prime);
}
// let grand_product_openings = argument.open_commitments_for_grand_product(y, z, &srs); let z_prime : Fr = rng.gen();
let z_prime : Fr = Fr::one();
// let randomness = (0..1).map(|_| Fr::rand(rng)).collect::<Vec<_>>(); let opening = argument.open_commitments_to_s_prime(&challenges, y, z_prime, &srs);
// let valid = GrandProductArgument::verify_ab_commitment(n, let randomness = (0..2).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
// &randomness,
// &vec![a_commitment],
// &vec![b_commitment],
// &grand_product_openings,
// y,
// z,
// &srs);
// assert!(valid, "grand product commitments should be valid"); let valid = PermutationArgument::verify_s_prime_commitment(n,
&randomness,
&challenges,
&s_prime_commitments,
&opening,
y,
z_prime,
&specialized_srs,
&srs);
// let a_zy: Vec<Fr> = grand_product_openings.iter().map(|el| el.0.clone()).collect(); assert!(valid, "s' commitment must be valid");
// let proof = argument.make_argument(&a_zy, &challenges, y, z, &srs); let beta : Fr = rng.gen();
let gamma : Fr = rng.gen();
// let randomness = (0..3).map(|_| Fr::rand(rng)).collect::<Vec<_>>(); let grand_product_challenges = (0..1).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
let wellformed_challenges = (0..2).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
// let valid = GrandProductArgument::verify( let z : Fr = rng.gen();
// n,
// &randomness,
// &a_zy,
// &challenges,
// t_commitment,
// &commitments_and_v_values,
// &proof,
// y,
// z,
// &srs);
// assert!(valid, "t commitment should be valid"); let proof = argument.make_argument(
// } beta,
gamma,
& grand_product_challenges,
& wellformed_challenges,
y, z,
&specialized_srs, &srs);
let valid = PermutationArgument::verify(&s_commitments, &proof, z, &srs);
assert!(valid, "permutation argument must be valid");
}

@ -52,6 +52,7 @@ impl<E: Engine> WellformednessArgument<E> {
} }
pub fn make_argument(self, challenges: Vec<E::Fr>, srs: &SRS<E>) -> WellformednessProof<E> { pub fn make_argument(self, challenges: Vec<E::Fr>, srs: &SRS<E>) -> WellformednessProof<E> {
assert_eq!(challenges.len(), self.polynomials.len());
let mut polynomials = self.polynomials; let mut polynomials = self.polynomials;
let mut challenges = challenges; let mut challenges = challenges;
@ -165,7 +166,7 @@ fn test_argument_soundness() {
let srs_alpha = Fr::from_str("23728792").unwrap(); let srs_alpha = Fr::from_str("23728792").unwrap();
let srs = SRS::<Bls12>::dummy(830564, srs_x, srs_alpha); let srs = SRS::<Bls12>::dummy(830564, srs_x, srs_alpha);
let n: usize = 1 << 16; let n: usize = 1 << 8;
let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let coeffs = (0..n).map(|_| Fr::rand(rng)).collect::<Vec<_>>(); let coeffs = (0..n).map(|_| Fr::rand(rng)).collect::<Vec<_>>();