done? now fix transcripts for multiple challenges

This commit is contained in:
Alex Vlasov 2019-06-11 21:31:32 +03:00
parent ae9716a428
commit fafa64749e
13 changed files with 302 additions and 148 deletions

@ -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"]

@ -57,7 +57,7 @@ pub trait Backend<E: Engine> {
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<E>, y: &Self::LinearConstraintIndex) { }
fn insert_coefficient(&mut self, _var: Variable, _coeff: Coeff<E>, _y: &Self::LinearConstraintIndex) { }
/// Compute a `LinearConstraintIndex` from `q`.
fn get_for_q(&self, q: usize) -> Self::LinearConstraintIndex;

@ -106,8 +106,6 @@ pub fn create_aggregate_on_srs_using_information<E: Engine, C: Circuit<E>, S: Sy
let value = compute_value::<E>(&w, &s_poly_positive, &s_poly_negative);
println!("Helper s(z, w) = {}", value);
let opening = {
let mut value = value;
value.negate();

@ -18,7 +18,7 @@ pub struct Preprocess<E: Engine> {
impl<'a, E: Engine> Backend<E> for &'a mut Preprocess<E> {
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<E> for &'a mut Wires<E> {
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<S: SynthesisDriver> {
impl<'a, E: Engine, S: SynthesisDriver> Backend<E> for &'a mut CountNandQ<S> {
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<E> for &'a mut CountN<S> {
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;

@ -505,10 +505,9 @@ fn test_succinct_sonic_mimc() {
use crate::sonic::cs::{Circuit, ConstraintSystem, LinearCombination, Coeff};
// let perm_structure = create_permutation_structure::<Bls12, _>(&AdaptorCircuit(circuit.clone()));
let perm_structure = create_permutation_structure::<Bls12, _>(&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::<Bls12, _>(circuit.clone()).expect("Must get circuit info");
println!("{:?}", info);
@ -529,8 +528,6 @@ fn test_succinct_sonic_mimc() {
let aggregate = create_aggregate_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &proofs, &srs, &s1_srs);
println!("done in {:?}", start.elapsed());
let _ = crate::sonic::helped::helper::create_aggregate_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &proofs, &srs);
// {
// let rng = thread_rng();
// let mut verifier = MultiVerifier::<Bls12, _, Permutation3, _>::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::<Bls12, _, Permutation3, _>::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
}

@ -115,12 +115,8 @@ pub fn create_aggregate_on_srs_using_information<E: Engine, C: Circuit<E>, S: Sy
// Open C at w
let w: E::Fr = transcript.get_challenge_scalar();
println!("Aggregate: Z = {}, W = {}", z, w);
let value = compute_value::<E>(&w, &s_poly_positive, &s_poly_negative);
println!("Aggregate: S(z,w) = {}", value);
let opening = {
let mut value = value;
value.negate();

@ -49,7 +49,6 @@ impl<E: Engine> GrandProductArgument<E> {
z: E::Fr,
srs: &SRS<E>,
) -> GrandProductSignature<E> {
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<E: Engine> GrandProductArgument<E> {
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<E: Engine> GrandProductArgument<E> {
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<E: Engine> GrandProductArgument<E> {
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<E: Engine> GrandProductArgument<E> {
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<E: Engine> GrandProductArgument<E> {
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<E: Engine> GrandProductArgument<E> {
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<E: Engine> GrandProductArgument<E> {
}
}
pub fn verify_ab_commitment(n: usize,
pub fn verify_ab_commitment(
n: usize,
randomness: & Vec<E::Fr>,
a_commitments: &Vec<E::G1Affine>,
b_commitments: &Vec<E::G1Affine>,
@ -550,7 +582,8 @@ impl<E: Engine> GrandProductArgument<E> {
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::<Bls12>::dummy(830564, srs_x, srs_alpha);
// let srs = SRS::<Bls12>::dummy(830564, srs_x, srs_alpha);
let srs = SRS::<Bls12>::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::<Vec<_>>();
let coeffs = (1..=n).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
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::<Vec<_>>();
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");

@ -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;

@ -55,19 +55,19 @@ pub struct SignatureOfCorrectComputation<E: Engine> {
pub grand_product_signature: GrandProductSignature<E>
}
fn permute<F: Field>(coeffs: &[F], permutation: & [usize]) -> Vec<F>{
assert_eq!(coeffs.len(), permutation.len());
let mut result: Vec<F> = 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<F: Field>(coeffs: &[F], permutation: & [usize]) -> Vec<F>{
// assert_eq!(coeffs.len(), permutation.len());
// let mut result: Vec<F> = 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<F: Field>(permuted_coeffs: &[F], permutation: & [usize]) -> Vec<F>{
assert_eq!(permuted_coeffs.len(), permutation.len());
@ -174,7 +174,7 @@ impl<E: Engine> PermutationArgument<E> {
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<E: Engine> PermutationArgument<E> {
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<E: Engine> PermutationArgument<E> {
_specialized_srs: &SpecializedSRS<E>,
srs: &SRS<E>
) -> PermutationArgumentProof<E> {
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<E: Engine> PermutationArgument<E> {
let mut s_polynomial: Option<Vec<E::Fr>> = 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<E: Engine> PermutationArgument<E> {
// 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<E: Engine> PermutationArgument<E> {
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<E: Engine> PermutationArgument<E> {
// let mut s_combination = permute_inverse(&non_permuted[..], &permutation);
let mut s_combination = inv_permuted;
{
let p_4_values: Vec<E::Fr> = permutation.clone().into_iter().map(|el| {
let p_4_values: Vec<E::Fr> = permutation.into_iter().map(|el| {
let mut repr = <<E as ScalarEngine>::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<E: Engine> PermutationArgument<E> {
mul_add_polynomials(&mut s_combination[..], & p_1_values[..], gamma);
}
let mut s_combination_may_be = permuted;
{
let p_4_values: Vec<E::Fr> = permutation.clone().into_iter().map(|el| {
let mut repr = <<E as ScalarEngine>::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<E: Engine> PermutationArgument<E> {
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<E: Engine> PermutationArgument<E> {
}
pub fn verify_s_prime_commitment(
n: usize,
_n: usize,
randomness: & Vec<E::Fr>,
challenges: & Vec<E::Fr>,
commitments: &Vec<E::G1Affine>,
@ -699,9 +672,7 @@ impl<E: Engine> PermutationArgument<E> {
srs: &SRS<E>
) -> (PermutationArgumentProof<E>, GrandProductSignature<E>, 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<E: Engine> PermutationArgument<E> {
});
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::<Bls12>::dummy(830564, srs_x, srs_alpha);
let srs = SRS::<Bls12>::new(1024, srs_x, srs_alpha);
let srs = SRS::<Bls12>::new(128, srs_x, srs_alpha);
let n: usize = 1 << 4;
let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);

@ -383,7 +383,7 @@ impl<E: Engine> PermutationStructure<E> {
for i in 0..m {
let mut fillers: Vec<usize> = (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]);

@ -73,8 +73,7 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier
&mut self,
proofs: &[(Proof<E>, SxyAdvice<E>)],
aggregate: &SuccinctAggregate<E>,
srs: &SRS<E>,
specialized_srs: &SpecializedSRS<E>
srs: &SRS<E>
)
{
let mut transcript = Transcript::new(&[]);
@ -95,8 +94,6 @@ impl<E: Engine, C: Circuit<E>, 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<E: Engine, C: Circuit<E>, 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<E: Engine, C: Circuit<E>, 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<E::Fr> = (0..aggregate.signature.s_commitments.len()).map(|_| self.randomness_source.gen()).collect();
@ -294,7 +296,7 @@ impl<E: Engine, C: Circuit<E>, 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<E: Engine, C: Circuit<E>, 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)z1
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(Tz,hα) = e(T,h)e(gt(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();

@ -34,7 +34,6 @@ impl<E: Engine> WellformednessArgument<E> {
srs: &SRS<E>
) -> WellformednessSignature<E> {
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<E: Engine> WellformednessArgument<E> {
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<E: Engine> WellformednessArgument<E> {
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::<Bls12>::dummy(830564, srs_x, srs_alpha);
// let srs = SRS::<Bls12>::dummy(830564, srs_x, srs_alpha);
let srs = SRS::<Bls12>::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::<Vec<_>>();
let coeffs = (1..=n).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
let argument = WellformednessArgument::new(vec![coeffs]);
let challenges = (0..1).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
@ -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::<Vec<_>>();
let coeffs = (1..=n).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
let argument = WellformednessArgument::new(vec![coeffs]);
let commitments = argument.commit(&srs);
let coeffs = (0..n).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
let coeffs = (1..=n).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
let argument = WellformednessArgument::new(vec![coeffs]);
let challenges = (0..1).map(|_| Fr::rand(rng)).collect::<Vec<_>>();

@ -116,7 +116,7 @@ pub fn polynomial_commitment_opening<
I: IntoIterator<Item = &'a E::Fr>
>(
largest_negative_power: usize,
largest_positive_power: usize,
_largest_positive_power: usize,
polynomial_coefficients: I,
point: E::Fr,
srs: &'a SRS<E>,
@ -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(&current_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(&current_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<Item = &'a E::Fr>>(a: I, mut b: E::Fr) -> Vec<E::Fr>
pub fn parallel_kate_divison<'a, E: Engine, I: IntoIterator<Item = &'a E::Fr>>(a: I, b: E::Fr) -> Vec<E::Fr>
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);
}