From ae9716a42853f3c48ed4125fd61be9f7cb2fda69 Mon Sep 17 00:00:00 2001 From: Alex Vlasov Date: Tue, 11 Jun 2019 15:43:27 +0300 Subject: [PATCH] TODO: reformulate permutation argument --- src/sonic/helped/helper.rs | 68 +-- src/sonic/tests/sonics.rs | 145 ++----- .../unhelped/{helper.rs => aggregate.rs} | 171 +++----- src/sonic/unhelped/grand_product_argument.rs | 32 +- src/sonic/unhelped/mod.rs | 7 +- src/sonic/unhelped/permutation_argument.rs | 282 +++++++------ src/sonic/unhelped/permutation_structure.rs | 394 +++++++++++++----- src/sonic/unhelped/verifier.rs | 360 ++++++++++------ src/sonic/unhelped/wellformed_argument.rs | 3 +- 9 files changed, 820 insertions(+), 642 deletions(-) rename src/sonic/unhelped/{helper.rs => aggregate.rs} (59%) diff --git a/src/sonic/helped/helper.rs b/src/sonic/helped/helper.rs index e6404c4..b9763f9 100644 --- a/src/sonic/helped/helper.rs +++ b/src/sonic/helped/helper.rs @@ -106,6 +106,8 @@ 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(); @@ -117,20 +119,6 @@ pub fn create_aggregate_on_srs_using_information, S: Sy w, &srs ) - - // let poly = kate_divison( - // s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()), - // w, - // ); - - // let negative_poly = poly[0..n].iter().rev(); - // let positive_poly = poly[n..].iter(); - // multiexp( - // srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext( - // srs.g_positive_x[0..positive_poly.len()].iter() - // ), - // negative_poly.chain_ext(positive_poly) - // ).into_affine() }; // Let's open up C to every y. @@ -143,22 +131,6 @@ pub fn create_aggregate_on_srs_using_information, S: Sy value.add_assign(&positive_powers_contrib); value.add_assign(&negative_powers_contrib); - // let mut tmp = yinv; - // for &coeff in poly_negative { - // let mut coeff = coeff; - // coeff.mul_assign(&tmp); - // value.add_assign(&coeff); - // tmp.mul_assign(&yinv); - // } - - // let mut tmp = *y; - // for &coeff in poly_positive { - // let mut coeff = coeff; - // coeff.mul_assign(&tmp); - // value.add_assign(&coeff); - // tmp.mul_assign(&y); - // } - value } @@ -180,20 +152,6 @@ pub fn create_aggregate_on_srs_using_information, S: Sy *y, &srs ) - - // let poly = kate_divison( - // s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()), - // *y, - // ); - - // let negative_poly = poly[0..n].iter().rev(); - // let positive_poly = poly[n..].iter(); - // multiexp( - // srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext( - // srs.g_positive_x[0..positive_poly.len()].iter() - // ), - // negative_poly.chain_ext(positive_poly) - // ).into_affine() }; c_openings.push((opening, value)); @@ -229,15 +187,6 @@ pub fn create_aggregate_on_srs_using_information, S: Sy mul_add_polynomials(& mut poly_negative[..], &s_poly_negative[..], r); mul_add_polynomials(& mut poly_positive[..], &s_poly_positive[..], r); - // for (mut coeff, target) in s_poly_negative.into_iter().zip(poly_negative.iter_mut()) { - // coeff.mul_assign(&r); - // target.add_assign(&coeff); - // } - - // for (mut coeff, target) in s_poly_positive.into_iter().zip(poly_positive.iter_mut()) { - // coeff.mul_assign(&r); - // target.add_assign(&coeff); - // } } println!("Re-evaluation of {} S polynomials taken {:?}", y_values.len(), start.elapsed()); @@ -254,19 +203,6 @@ pub fn create_aggregate_on_srs_using_information, S: Sy &srs ) - // let poly = kate_divison( - // poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(poly_positive.iter()), - // z, - // ); - - // let negative_poly = poly[0..n].iter().rev(); - // let positive_poly = poly[n..].iter(); - // multiexp( - // srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext( - // srs.g_positive_x[0..positive_poly.len()].iter() - // ), - // negative_poly.chain_ext(positive_poly) - // ).into_affine() }; Aggregate { diff --git a/src/sonic/tests/sonics.rs b/src/sonic/tests/sonics.rs index 91dc9b1..63a2b09 100644 --- a/src/sonic/tests/sonics.rs +++ b/src/sonic/tests/sonics.rs @@ -498,47 +498,13 @@ fn test_succinct_sonic_mimc() { use crate::sonic::sonic::AdaptorCircuit; use crate::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs}; use crate::sonic::helped::{get_circuit_parameters_for_succinct_sonic, MultiVerifier}; - use crate::sonic::helped::helper::{create_aggregate_on_srs}; use crate::sonic::sonic::Permutation3; use crate::sonic::unhelped::permutation_structure::*; use crate::sonic::unhelped::SuccinctMultiVerifier; + use crate::sonic::unhelped::{create_aggregate_on_srs}; use crate::sonic::cs::{Circuit, ConstraintSystem, LinearCombination, Coeff}; - struct MyCircuit; - - impl Circuit for MyCircuit { - fn synthesize>(&self, cs: &mut CS) -> Result<(), SynthesisError> { - let (a, b, c) = cs.multiply(|| { - Ok(( - E::Fr::from_str("10").unwrap(), - E::Fr::from_str("20").unwrap(), - E::Fr::from_str("200").unwrap(), - )) - })?; - - cs.enforce_zero(LinearCombination::zero() + (Coeff::Full(E::Fr::from_str("2").unwrap()), a) - b); - - let multiplier = cs.alloc_input(|| Ok(E::Fr::from_str("20").unwrap()))?; - - cs.enforce_zero(LinearCombination::from(b) - multiplier); - - let (a1, b1, _) = cs.multiply(|| { - Ok(( - E::Fr::from_str("5").unwrap(), - E::Fr::from_str("5").unwrap(), - E::Fr::from_str("25").unwrap(), - )) - })?; - - cs.enforce_zero(LinearCombination::zero() + (Coeff::Full(E::Fr::from_str("2").unwrap()), b1) - a); - cs.enforce_zero(LinearCombination::zero() + (Coeff::Full(E::Fr::from_str("4").unwrap()), a1) - b); - cs.enforce_zero(LinearCombination::zero() + (Coeff::Full(E::Fr::from_str("40").unwrap()), b1) - c); - - Ok(()) - } - } - // 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); @@ -560,84 +526,49 @@ fn test_succinct_sonic_mimc() { println!("creating aggregate for {} proofs", samples); let start = Instant::now(); let proofs: Vec<_> = (0..samples).map(|_| (proof.clone(), advice.clone())).collect(); - let aggregate = create_aggregate_on_srs::(&AdaptorCircuit(circuit.clone()), &proofs, &srs); + let aggregate = create_aggregate_on_srs::(&AdaptorCircuit(circuit.clone()), &proofs, &srs, &s1_srs); println!("done in {:?}", start.elapsed()); - { - let rng = thread_rng(); - let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying 1 proof without advice"); - let start = Instant::now(); - { - for _ in 0..1 { - verifier.add_proof(&proof, &[], |_, _| None); - } - assert_eq!(verifier.check_all(), true); // TODO - } - println!("done in {:?}", start.elapsed()); - } - { - let rng = thread_rng(); - let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying {} proofs without advice", samples); - let start = Instant::now(); - { - for _ in 0..samples { - verifier.add_proof(&proof, &[], |_, _| None); - } - assert_eq!(verifier.check_all(), true); // TODO - } - 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(); + // println!("verifying 1 proof without advice"); + // let start = Instant::now(); + // { + // for _ in 0..1 { + // verifier.add_proof(&proof, &[], |_, _| None); + // } + // assert_eq!(verifier.check_all(), true); // TODO + // } + // println!("done in {:?}", start.elapsed()); + // } - { - let rng = thread_rng(); - let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); - println!("verifying 100 proofs with advice non-succinct"); - let start = Instant::now(); - { - for (ref proof, ref advice) in &proofs { - verifier.add_proof_with_advice(proof, &[], advice); - } - verifier.add_aggregate(&proofs, &aggregate); - assert_eq!(verifier.check_all(), true); // TODO - } - println!("done in {:?}", start.elapsed()); - } + // { + // let rng = thread_rng(); + // let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); + // println!("verifying {} proofs without advice", samples); + // let start = Instant::now(); + // { + // for _ in 0..samples { + // verifier.add_proof(&proof, &[], |_, _| None); + // } + // assert_eq!(verifier.check_all(), true); // TODO + // } + // println!("done in {:?}", start.elapsed()); + // } { 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); - println!("Permutation argument done in {:?}", start.elapsed()); - - // 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!("S_1 naive = {}", s1_naive); - - // let mut s_1 = s1_naive; - // s_1.mul_assign(&z_inv_n_plus_1); - // s_1.mul_assign(&y_n); - - // println!("S_1 multiplied = {}", 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 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 mut verifier = SuccinctMultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap(); println!("verifying 100 proofs with succinct advice"); @@ -647,16 +578,10 @@ fn test_succinct_sonic_mimc() { verifier.add_proof_with_advice(proof, &[], advice); } verifier.add_aggregate( - &proofs, + &proofs, &aggregate, - &perm_arg_proof, - &perm_proof, - &s2_proof, - num_poly, &srs, - z_prime, - &perm_commitments, - s_prime_challenges + &s1_srs ); assert_eq!(verifier.check_all(), true); // TODO } diff --git a/src/sonic/unhelped/helper.rs b/src/sonic/unhelped/aggregate.rs similarity index 59% rename from src/sonic/unhelped/helper.rs rename to src/sonic/unhelped/aggregate.rs index 7fd5e4d..701059e 100644 --- a/src/sonic/unhelped/helper.rs +++ b/src/sonic/unhelped/aggregate.rs @@ -16,31 +16,46 @@ use crate::sonic::cs::{Circuit, Variable, Coeff}; use crate::sonic::srs::SRS; use crate::sonic::sonic::CountNandQ; use crate::sonic::sonic::M; +use super::s2_proof::{S2Eval, S2Proof}; +use super::permutation_structure::create_permutation_structure; +use super::permutation_argument::PermutationArgument; +use super::permutation_argument::SignatureOfCorrectComputation; +use super::permutation_argument::SpecializedSRS; #[derive(Clone)] pub struct SuccinctAggregate { - pub permutations: [] - pub a: Vec<[Option<(Coeff, usize)>; M]>, - pub b: Vec<[Option<(Coeff, usize)>; M]>, - pub c: Vec<[Option<(Coeff, usize)>; M]>, + pub signature: SignatureOfCorrectComputation, + pub s2_proof: S2Proof, + pub c: E::G1Affine, + // We have to open each of the S commitments to a random point `z` + pub s_opening: E::G1Affine, + // We have to open C to each constituent `y` + pub c_openings: Vec<(E::G1Affine, E::Fr)>, + // Then we have to finally open C + pub opening: E::G1Affine, + + pub z: E::Fr, + pub w: E::Fr, + } -pub fn create_aggregate, S: SynthesisDriver>( - circuit: &C, - inputs: &[(Proof, SxyAdvice)], - params: &Parameters, -) -> SuccinctAggregate -{ - let n = params.vk.n; - let q = params.vk.q; +// pub fn create_aggregate, S: SynthesisDriver>( +// circuit: &C, +// inputs: &[(Proof, SxyAdvice)], +// params: &Parameters, +// ) -> SuccinctAggregate +// { +// let n = params.vk.n; +// let q = params.vk.q; - create_aggregate_on_srs_using_information::(circuit, inputs, ¶ms.srs, n, q) -} +// create_aggregate_on_srs_using_information::(circuit, inputs, ¶ms.srs, n, q) +// } pub fn create_aggregate_on_srs, S: SynthesisDriver>( circuit: &C, inputs: &[(Proof, SxyAdvice)], srs: &SRS, + specialized_srs: &SpecializedSRS ) -> SuccinctAggregate { // TODO: precompute this? @@ -52,17 +67,19 @@ pub fn create_aggregate_on_srs, S: SynthesisDriver>( (tmp.n, tmp.q) }; - create_aggregate_on_srs_using_information::(circuit, inputs, srs, n, q) + create_aggregate_on_srs_using_information::(circuit, inputs, srs, specialized_srs, n, q) } pub fn create_aggregate_on_srs_using_information, S: SynthesisDriver>( circuit: &C, inputs: &[(Proof, SxyAdvice)], srs: &SRS, + specialized_srs: &SpecializedSRS, n: usize, q: usize, ) -> SuccinctAggregate { + // take few proofs that are to be evaluated at some y_i and make an aggregate from them let mut transcript = Transcript::new(&[]); let mut y_values: Vec = Vec::with_capacity(inputs.len()); for &(ref proof, ref sxyadvice) in inputs { @@ -77,22 +94,7 @@ pub fn create_aggregate_on_srs_using_information, S: Sy let z: E::Fr = transcript.get_challenge_scalar(); - let t = { - let mut tmp: PermutationSynthesizer = PermutationSynthesizer::new(backend); - - let one = tmp.alloc_input(|| Ok(E::Fr::one())).expect("should have no issues"); - - match (one, as ConstraintSystem>::ONE) { - (Variable::A(1), Variable::A(1)) => {}, - _ => panic!("one variable is incorrect") - } - - circuit.synthesize(&mut tmp).expect("should synthesize"); - - tmp - }; - - // Compute s(z, Y) + // Compute s(z, Y) for opening of the previous commitments at the same `z` let (s_poly_negative, s_poly_positive) = { let mut tmp = SyEval::new(z, n, q); S::synthesize(&mut tmp, circuit).unwrap(); // TODO @@ -113,8 +115,12 @@ 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(); @@ -126,22 +132,30 @@ pub fn create_aggregate_on_srs_using_information, S: Sy w, &srs ) - - // let poly = kate_divison( - // s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()), - // w, - // ); - - // let negative_poly = poly[0..n].iter().rev(); - // let positive_poly = poly[n..].iter(); - // multiexp( - // srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext( - // srs.g_positive_x[0..positive_poly.len()].iter() - // ), - // negative_poly.chain_ext(positive_poly) - // ).into_affine() }; + // now we need signature of correct computation. For this purpose + // verifier already knows specialized SRS, so we can just commit to + // s1 and s2 parts of such signature to get `w` and later open at this point! + + // Commit! + + // TODO: Precompute! + // this will internally synthesize a circuit and structure of permutations + + let s2_eval = S2Eval::new(n); + let s2_proof = s2_eval.evaluate(z, w, &srs); + let permutation_structure = create_permutation_structure(circuit); + let (non_permuted_coeffs, permutations) = permutation_structure.create_permutation_vectors(); + let signature = PermutationArgument::make_signature( + non_permuted_coeffs, + permutations, + w, + z, + &srs, + &specialized_srs + ); + // Let's open up C to every y. fn compute_value(y: &E::Fr, poly_positive: &[E::Fr], poly_negative: &[E::Fr]) -> E::Fr { let mut value = E::Fr::zero(); @@ -152,28 +166,14 @@ pub fn create_aggregate_on_srs_using_information, S: Sy value.add_assign(&positive_powers_contrib); value.add_assign(&negative_powers_contrib); - // let mut tmp = yinv; - // for &coeff in poly_negative { - // let mut coeff = coeff; - // coeff.mul_assign(&tmp); - // value.add_assign(&coeff); - // tmp.mul_assign(&yinv); - // } - - // let mut tmp = *y; - // for &coeff in poly_positive { - // let mut coeff = coeff; - // coeff.mul_assign(&tmp); - // value.add_assign(&coeff); - // tmp.mul_assign(&y); - // } - value } use std::time::Instant; let start = Instant::now(); + // we still need to re-open previous commitments at the same new z + let mut c_openings = vec![]; for y in &y_values { let value = compute_value::(y, &s_poly_positive, &s_poly_negative); @@ -189,20 +189,6 @@ pub fn create_aggregate_on_srs_using_information, S: Sy *y, &srs ) - - // let poly = kate_divison( - // s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()), - // *y, - // ); - - // let negative_poly = poly[0..n].iter().rev(); - // let positive_poly = poly[n..].iter(); - // multiexp( - // srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext( - // srs.g_positive_x[0..positive_poly.len()].iter() - // ), - // negative_poly.chain_ext(positive_poly) - // ).into_affine() }; c_openings.push((opening, value)); @@ -237,16 +223,6 @@ pub fn create_aggregate_on_srs_using_information, S: Sy mul_add_polynomials(& mut poly_negative[..], &s_poly_negative[..], r); mul_add_polynomials(& mut poly_positive[..], &s_poly_positive[..], r); - - // for (mut coeff, target) in s_poly_negative.into_iter().zip(poly_negative.iter_mut()) { - // coeff.mul_assign(&r); - // target.add_assign(&coeff); - // } - - // for (mut coeff, target) in s_poly_positive.into_iter().zip(poly_positive.iter_mut()) { - // coeff.mul_assign(&r); - // target.add_assign(&coeff); - // } } println!("Re-evaluation of {} S polynomials taken {:?}", y_values.len(), start.elapsed()); @@ -262,30 +238,17 @@ pub fn create_aggregate_on_srs_using_information, S: Sy z, &srs ) - - // let poly = kate_divison( - // poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(poly_positive.iter()), - // z, - // ); - - // let negative_poly = poly[0..n].iter().rev(); - // let positive_poly = poly[n..].iter(); - // multiexp( - // srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext( - // srs.g_positive_x[0..positive_poly.len()].iter() - // ), - // negative_poly.chain_ext(positive_poly) - // ).into_affine() }; - Aggregate { - // Commitment to s(z, Y) + SuccinctAggregate { + signature, + s2_proof, c, - // We have to open each of the S commitments to a random point `z` s_opening, - // We have to open C to each constituent `y` c_openings, - // Then we have to finally open C opening, + + z: z, + w: w, } } \ No newline at end of file diff --git a/src/sonic/unhelped/grand_product_argument.rs b/src/sonic/unhelped/grand_product_argument.rs index 8b6eed0..1df65e9 100644 --- a/src/sonic/unhelped/grand_product_argument.rs +++ b/src/sonic/unhelped/grand_product_argument.rs @@ -49,6 +49,7 @@ 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![]; @@ -68,7 +69,7 @@ impl GrandProductArgument { let mut all_polys = vec![]; let mut wellformed_challenges = vec![]; - for c in 0..(grand_products.len()*2) { + for _ in 0..(grand_products.len()*2) { let c = transcript.get_challenge_scalar(); wellformed_challenges.push(c); } @@ -196,21 +197,21 @@ impl GrandProductArgument { } } - // 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_grand_product(a: &[E::Fr], b: &[E::Fr], srs: &SRS) -> E::G1Affine { - assert_eq!(a.len(), b.len()); + // // 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_grand_product(a: &[E::Fr], b: &[E::Fr], srs: &SRS) -> E::G1Affine { + // assert_eq!(a.len(), b.len()); - let n = a.len(); + // let n = a.len(); + + // multiexp( + // srs.g_positive_x_alpha[0..(2*n+1)].iter(), + // a.iter() + // .chain_ext(Some(E::Fr::zero()).iter()) + // .chain_ext(b.iter()) + // ).into_affine() + // } - multiexp( - srs.g_positive_x_alpha[0..(2*n+1)].iter(), - a.iter() - .chain_ext(Some(E::Fr::zero()).iter()) - .chain_ext(b.iter()) - ).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::G1Affine, E::G1Affine) { assert_eq!(a.len(), b.len()); @@ -536,11 +537,10 @@ impl GrandProductArgument { y: E::Fr, z: E::Fr, srs: &SRS - ) -> bool { + ) -> bool { assert_eq!(randomness.len(), a_commitments.len()); assert_eq!(openings.len(), a_commitments.len()); assert_eq!(b_commitments.len(), a_commitments.len()); - let d = srs.d; // e(Dj,hαx)e(D−yz,hα) = e(Aj,h)e(Bj,hxn+1)e(g−aj ,hα) @@ -625,8 +625,6 @@ impl GrandProductArgument { 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 h_alpha_x_precomp = srs.h_positive_x_alpha[1].prepare(); diff --git a/src/sonic/unhelped/mod.rs b/src/sonic/unhelped/mod.rs index 9dd7a67..616d07d 100644 --- a/src/sonic/unhelped/mod.rs +++ b/src/sonic/unhelped/mod.rs @@ -9,10 +9,9 @@ mod grand_product_argument; mod permutation_argument; mod verifier; pub mod permutation_structure; -// mod helper; -// mod permutation; -// pub mod padding; +mod aggregate; pub use self::wellformed_argument::{WellformednessArgument, WellformednessProof}; pub use self::permutation_argument::{PermutationArgument, PermutationProof, PermutationArgumentProof}; -pub use self::verifier::SuccinctMultiVerifier; \ No newline at end of file +pub use self::verifier::SuccinctMultiVerifier; +pub use self::aggregate::*; \ No newline at end of file diff --git a/src/sonic/unhelped/permutation_argument.rs b/src/sonic/unhelped/permutation_argument.rs index f3fca7b..c04f2ba 100644 --- a/src/sonic/unhelped/permutation_argument.rs +++ b/src/sonic/unhelped/permutation_argument.rs @@ -15,10 +15,10 @@ use crate::sonic::transcript::{Transcript, TranscriptProtocol}; #[derive(Clone)] pub struct SpecializedSRS { - p_1: E::G1Affine, - p_2: Vec, - p_3: E::G1Affine, - p_4: Vec, + pub p_1: E::G1Affine, + pub p_2: Vec, + pub p_3: E::G1Affine, + pub p_4: Vec, n: usize } @@ -26,8 +26,8 @@ pub struct SpecializedSRS { pub struct PermutationArgument { non_permuted_coefficients: Vec>, non_permuted_at_y_coefficients: Vec>, - permuted_coefficients: Vec>, permuted_at_y_coefficients: Vec>, + inverse_permuted_at_y_coefficients: Vec>, permutations: Vec>, n: usize } @@ -97,9 +97,10 @@ impl PermutationArgument { PermutationArgument { non_permuted_coefficients: coefficients, - non_permuted_at_y_coefficients: vec![vec![]], - permuted_coefficients: vec![vec![]], - permuted_at_y_coefficients: vec![vec![]], + non_permuted_at_y_coefficients: vec![], + // permuted_coefficients: vec![], + permuted_at_y_coefficients: vec![], + inverse_permuted_at_y_coefficients: vec![], permutations: permutations, n: n } @@ -148,7 +149,9 @@ impl PermutationArgument { fe }).collect(); + let p4 = multiexp(srs.g_positive_x_alpha[0..n].iter(), values.iter()).into_affine(); + p_4.push(p4); } } @@ -164,71 +167,59 @@ impl PermutationArgument { // commit to s and s' at y. Mutates the state pub fn commit(&mut self, y: E::Fr, srs: &SRS) -> Vec<(E::G1Affine, E::G1Affine)> { + assert!(self.inverse_permuted_at_y_coefficients.len() == 0); let mut result = vec![]; let n = self.non_permuted_coefficients[0].len(); let mut non_permuted_at_y_coefficients = vec![]; - let mut permuted_coefficients = vec![]; + // let mut permuted_coefficients = vec![]; let mut permuted_at_y_coefficients = vec![]; + let mut inverse_permuted_at_y_coefficients = vec![]; // naive algorithms // for every permutation poly // -- go throught all variable_idx - // - take coeff from non-permuted coeffs[veriable_idx] + // - take coeff from non-permuted coeffs[permutation[variable_idx]] // - mul by Y^{permutation[variable_idx]} // - mul by X^{variable_idx + 1} - // let mut s_contrib = E::Fr::zero(); - // for permutation_index in 0..m { - // for (variable_index, constraint_power) in permutations[permutation_index].iter().enumerate() { - // let y_power = y.pow([*constraint_power as u64]); - // let x_power = z.pow([(variable_index+1) as u64]); - // let coeff = non_permuted_coeffs[permutation_index][variable_index]; - - // let mut result = coeff; - // result.mul_assign(&x_power); - // result.mul_assign(&y_power); - // s_contrib.add_assign(&result); - // } - // } - - - // this part distributes powers of Y^{constraint} and Y^{variable} for different arguments for (c, p) in self.non_permuted_coefficients.iter().zip(self.permutations.iter()) { - // this one will have terms coeff[0] * Y^1 let mut non_permuted_at_y = c.clone(); - - // permute to later have coeff[i] at spot K for distribution of powers and for argument - let permuted = permute(&non_permuted_at_y[..], &p[..]); - - // here will be distributed powers for coeff[i] * Y^K - let mut permuted_at_y = permuted.clone(); - - // distribute powers of Y to non-permuted coefficients as coeff[0]*Y^1, coeff[0]*Y^2, ... mut_distribute_consequitive_powers(&mut non_permuted_at_y[..], y, y); - // and commit to S' let s_prime = multiexp(srs.g_positive_x_alpha[0..n].iter(), non_permuted_at_y.iter()).into_affine(); - // this construction has already moved coeff[i] to the corresponding constraint k, so term is coeff[i]*Y^{K} for place K - mut_distribute_consequitive_powers(&mut permuted_at_y[..], y, y); + // if we pretend that non_permuted_at_y[sigma[i]] = coeffs[sigma[i]] * Y^sigma[i], + // then inverse_permuted_at_y[i] = coeffs[sigma[i]] * Y^sigma[i] + let inverse_permuted_at_y = permute_inverse(&non_permuted_at_y[..], &p[..]); - // now there is a coefficient coeff[i]*Y^{K} for place K at place K, so we need to move it back to i - let permuted_at_y = permute_inverse(&permuted_at_y[..], &p[..]); + // let mut t = vec![E::Fr::zero(); inverse_permuted_at_y.len()]; + // for i in 0..t.len() { + // let coeff = c[i]; + // let sigma_i = p[i]; + // let y_sigma_i = y.pow([sigma_i as u64]); + // t[i] = coeff; + // t[i].mul_assign(&y_sigma_i); + // } // and commit to S - let s = multiexp(srs.g_positive_x_alpha[0..n].iter(), permuted_at_y.iter()).into_affine(); + let s = multiexp(srs.g_positive_x_alpha[0..n].iter(), inverse_permuted_at_y.iter()).into_affine(); + + // let s = multiexp(srs.g_positive_x_alpha[0..n].iter(), t.iter()).into_affine(); result.push((s, s_prime)); non_permuted_at_y_coefficients.push(non_permuted_at_y); - permuted_coefficients.push(permuted); - permuted_at_y_coefficients.push(permuted_at_y); + // permuted_coefficients.push(permuted); + // permuted_at_y_coefficients.push(t); + // permuted_at_y_coefficients.push(permuted_at_y); + inverse_permuted_at_y_coefficients.push(inverse_permuted_at_y); } self.non_permuted_at_y_coefficients = non_permuted_at_y_coefficients; - self.permuted_coefficients = permuted_coefficients; + // self.permuted_coefficients = permuted_coefficients; self.permuted_at_y_coefficients = permuted_at_y_coefficients; + self.inverse_permuted_at_y_coefficients = inverse_permuted_at_y_coefficients; result } @@ -302,6 +293,7 @@ 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 @@ -313,6 +305,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() { if s_polynomial.is_some() { if let Some(poly) = s_polynomial.as_mut() { @@ -326,6 +319,8 @@ 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(); @@ -350,32 +345,76 @@ impl PermutationArgument { 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() + for (((non_permuted, inv_permuted), permutation), permuted) 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()) { - // \prod si+βσi+γ = \prod s'i + β*i + γ - let mut s_j_combination = non_permuted; + // in S combination at the place i there should be term coeff[sigma(i)] * Y^sigma(i), that we can take + // from non-permuted by inverse_permuting it + // let mut s_combination = permute_inverse(&non_permuted[..], &permutation); + let mut s_combination = inv_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(); + 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_j_combination[..], & p_4_values[..], beta); - mul_add_polynomials(&mut s_j_combination[..], & p_1_values[..], gamma); + fe + }).collect(); + mul_add_polynomials(&mut s_combination[..], & p_4_values[..], beta); + mul_add_polynomials(&mut s_combination[..], & p_1_values[..], gamma); } - let mut s_prime_j_combination = permuted; + let mut s_combination_may_be = 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); + 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); } - grand_products.push((s_j_combination, s_prime_j_combination)); + // combination of coeff[i]*Y^i + beta * i + gamma + let mut s_prime_combination = non_permuted.clone(); + { + + mul_add_polynomials(&mut s_prime_combination[..], & p_3_values[..], beta); + mul_add_polynomials(&mut s_prime_combination[..], & p_1_values[..], gamma); + } + + // Sanity check + let s_prime_product = s_prime_combination.iter().fold(E::Fr::one(), |mut sum, x| + { + sum.mul_assign(&x); + + sum + }); + + let s_product = s_combination.iter().fold(E::Fr::one(), |mut sum, x| + { + sum.mul_assign(&x); + + 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)); } let mut a_commitments = vec![]; @@ -400,7 +439,7 @@ impl PermutationArgument { let proof = wellformed_argument.make_argument(wellformed_challenges.clone(), &srs); let valid = WellformednessArgument::verify(n, &wellformed_challenges, &commitments, &proof, &srs); - assert!(valid, "wellformedness argument must be valid"); + // assert!(valid, "wellformedness argument must be valid"); } let mut grand_product_argument = GrandProductArgument::new(grand_products); @@ -416,7 +455,7 @@ impl PermutationArgument { let randomness = (0..j).map(|_| E::Fr::rand(rng)).collect::>(); let valid = GrandProductArgument::verify_ab_commitment(n, - &randomness, + & randomness, & a_commitments, & b_commitments, &grand_product_openings, @@ -605,42 +644,42 @@ impl PermutationArgument { let s_prime_commitments_opening = argument.open_commitments_to_s_prime(&challenges, y, z_prime, &srs); - let (proof, grand_product_signature) = { + let (proof, grand_product_signature, beta, gamma) = { // TODO: create better way to get few distinct challenges from the transcript - let (proof, grand_product_signature) = argument.make_argument_with_transcript( + let (proof, grand_product_signature, beta, gamma) = argument.make_argument_with_transcript( &mut transcript, y, z, &srs ); - (proof, grand_product_signature) + (proof, grand_product_signature, beta, gamma) }; // 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())); + for (j, (((a, b), s), s_prime)) in grand_product_signature.a_commitments.iter() + .zip(grand_product_signature.b_commitments.iter()) + .zip(s_commitments.iter()) + .zip(s_prime_commitments.iter()) + .enumerate() + { + // Sj(P4j)β(P1j)γ + let mut lhs = s.into_projective(); + lhs.add_assign(&specialized_srs.p_4[j].mul(beta.into_repr())); + lhs.add_assign(&specialized_srs.p_1.mul(gamma.into_repr())); - // assert!(lhs.into_affine() == *a); + assert!(lhs.into_affine() == *a); - // // Sj′(P3j)β(P1j)γ + // Sj′(P3j)β(P1j)γ - // let mut rhs = s_prime.into_projective(); - // rhs.add_assign(&specialized_srs.p_3.mul(beta.into_repr())); - // rhs.add_assign(&specialized_srs.p_1.mul(gamma.into_repr())); + let mut rhs = s_prime.into_projective(); + rhs.add_assign(&specialized_srs.p_3.mul(beta.into_repr())); + rhs.add_assign(&specialized_srs.p_1.mul(gamma.into_repr())); - // assert!(rhs.into_affine() == *b); - // } + assert!(rhs.into_affine() == *b); + } SignatureOfCorrectComputation { s_commitments, @@ -658,9 +697,11 @@ impl PermutationArgument { y: E::Fr, z: E::Fr, srs: &SRS - ) -> (PermutationArgumentProof, GrandProductSignature) { + ) -> (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 @@ -670,7 +711,8 @@ impl PermutationArgument { let mut s_polynomial: Option> = None; - for c in self.permuted_at_y_coefficients.iter() + // for c in self.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() { @@ -709,59 +751,54 @@ impl PermutationArgument { let mut grand_products = vec![]; // TODO: Check the validity! - - for ((non_permuted, permuted), permutation) in self.non_permuted_coefficients.into_iter() - .zip(self.permuted_coefficients.into_iter()) - .zip(self.permutations.into_iter()) - - // for ((non_permuted, permuted), permutation) in self.non_permuted_at_y_coefficients.into_iter() - // .zip(self.permuted_at_y_coefficients.into_iter()) - // .zip(self.permutations.into_iter()) + 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()) { - // \prod si+βσi+γ = \prod s'i + β*i + γ - - // s combination is coeff[sigma(i)]*Y^{sigma(i)} + beta*sigma(i) + gamma - let mut s_j_combination = non_permuted; - // let mut s_j_combination = permuted; + // in S combination at the place i there should be term coeff[sigma(i)] * Y^sigma(i), that we can take + // from non-permuted by inverse_permuting it + // let mut s_combination = permute_inverse(&non_permuted[..], &permutation); + let mut s_combination = inv_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(); + 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); + fe + }).collect(); + mul_add_polynomials(&mut s_combination[..], & p_4_values[..], beta); + mul_add_polynomials(&mut s_combination[..], & p_1_values[..], gamma); } - let mut s_prime_j_combination = permuted; - // let mut s_prime_j_combination = non_permuted; - // s' combination is coeff[i]*Y^{i} + beta*i + gamma - + // combination of coeff[i]*Y^i + beta * i + gamma + let mut s_prime_combination = non_permuted.clone(); { - mul_add_polynomials(&mut s_prime_j_combination[..], & p_3_values[..], beta); - mul_add_polynomials(&mut s_prime_j_combination[..], & p_1_values[..], gamma); + + mul_add_polynomials(&mut s_prime_combination[..], & p_3_values[..], beta); + mul_add_polynomials(&mut s_prime_combination[..], & p_1_values[..], gamma); } // Sanity check - let product = s_j_combination.iter().fold(E::Fr::one(), |mut sum, x| - { - sum.mul_assign(&x); - - sum - }); - let product_prime = s_prime_j_combination.iter().fold(E::Fr::one(), |mut sum, x| + let s_prime_product = s_prime_combination.iter().fold(E::Fr::one(), |mut sum, x| { sum.mul_assign(&x); sum }); - assert_eq!(product, product_prime); + let s_product = s_combination.iter().fold(E::Fr::one(), |mut sum, x| + { + sum.mul_assign(&x); - grand_products.push((s_j_combination, s_prime_j_combination)); + sum + }); + + assert_eq!(s_product, s_prime_product, "product of coefficients must be the same"); + + grand_products.push((s_combination, s_prime_combination)); } let grand_product_signature = GrandProductArgument::create_signature( @@ -778,7 +815,7 @@ impl PermutationArgument { s_zy: s_zy }; - (proof, grand_product_signature) + (proof, grand_product_signature, beta, gamma) } } @@ -791,7 +828,8 @@ 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::::dummy(830564, srs_x, srs_alpha); + let srs = SRS::::new(1024, 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 70bed44..5633132 100644 --- a/src/sonic/unhelped/permutation_structure.rs +++ b/src/sonic/unhelped/permutation_structure.rs @@ -74,82 +74,13 @@ impl PermutationStructure { S2Eval::calculate_commitment_element(self.n, srs) } - pub fn print_constraints(n:usize, q: usize, coeffs: &Vec>, permutations: &Vec>) { - let m = coeffs.len(); - - for constraint_idx in 1..=q { - println!("Constraint {}", constraint_idx); - let mut terms = vec![]; - for p_idx in 0..m { - if let Some(variable_idx) = permutations[p_idx].iter().position(|&s| s == constraint_idx) { - let coeff = coeffs[p_idx][variable_idx]; - terms.push((variable_idx, coeff)); - } - } - for (var_idx, coeff) in terms.into_iter() { - if var_idx < n + 1 { - print!("{} * A({})", coeff, n - var_idx); - } else if var_idx < 2*n + 1 { - print!("{} * B({})", coeff, var_idx - n); - } else { - print!("{} * C({})", coeff, var_idx - 2*n); - } - print!("\n"); - } - } - } - - pub fn print_terms_per_variable(n:usize, q: usize, coeffs: &Vec>, permutations: &Vec>) { - let m = coeffs.len(); - let k = coeffs[0].len(); - - for var_idx in 0..k { - println!("Terms for X^{}", var_idx + 1); - for p_idx in 0..m { - println!("In permutation poly {}", p_idx); - let constraint_index = permutations[p_idx][var_idx]; - if constraint_index == 0 { - continue; - } - let coeff = coeffs[p_idx][var_idx]; - if var_idx < n + 1 { - print!("{} * A({}) * Y^{}", coeff, n - var_idx, constraint_index); - } else if var_idx < 2*n + 1 { - print!("{} * B({}) * Y^{}", coeff, var_idx - n, constraint_index); - } else { - print!("{} * C({}) * Y^{}", coeff, var_idx - 2*n, constraint_index); - } - print!("\n"); - } - } - } - - pub fn print_terms_in_permutations(n:usize, q: usize, coeffs: &Vec>, permutations: &Vec>) { - let m = coeffs.len(); - - for p_idx in 0..m { - println!("Permutation polynomial {}", p_idx); - for (var_idx, constraint_idx) in permutations[p_idx].iter().enumerate() { - let coeff = coeffs[p_idx][var_idx]; - if var_idx < n + 1 { - print!("{} * A({})", coeff, n - var_idx); - } else if var_idx < 2*n + 1 { - print!("{} * B({})", coeff, var_idx - n); - } else { - print!("{} * C({})", coeff, var_idx - 2*n); - } - print!("\n"); - } - } - } - pub fn calculate_s2_proof(&self, x: E::Fr, y: E::Fr, srs: &SRS) -> S2Proof { let s2_eval = S2Eval::new(self.n); s2_eval.evaluate(x, y, &srs) } - fn create_permutation_vectors(&self) -> (Vec>, Vec>) { + pub fn create_inverse_permutation_vectors(&self) -> (Vec>, Vec>) { // we have to form non-permuted coefficients, as well as permutation structures; let n = self.n; let mut non_permuted_coeffs = vec![vec![E::Fr::zero(); 3*n+1]; M]; @@ -168,7 +99,6 @@ impl PermutationStructure { if let Some((coeff, place)) = info[i].as_ref() { // place it assert!(*place != 0); - let x_power = offset - gate_index + 1; let array_position = offset - gate_index; // special for A let place_coeff_into = &mut non_permuted_coeffs[i]; let place_permutation_into = &mut permutations[i]; @@ -201,7 +131,6 @@ impl PermutationStructure { if let Some((coeff, place)) = info[i].as_ref() { // place it assert!(*place != 0); - let x_power = offset + gate_index + 1; // 1 indexed let array_position = offset + gate_index; let place_coeff_into = &mut non_permuted_coeffs[i]; let place_permutation_into = &mut permutations[i]; @@ -235,7 +164,6 @@ impl PermutationStructure { if let Some((coeff, place)) = info[i].as_ref() { // place it assert!(*place != 0); - let x_power = offset + gate_index + 1; // 1 indexed let array_position = offset + gate_index; let place_coeff_into = &mut non_permuted_coeffs[i]; let place_permutation_into = &mut permutations[i]; @@ -262,6 +190,8 @@ impl PermutationStructure { } } + Self::print_constraints(n, self.q, &non_permuted_coeffs, &permutations); + // need to fill arrays with non-zero indexes just to have full permutation, even while it's just zero coefficient // TODO: fix @@ -283,15 +213,6 @@ impl PermutationStructure { assert!(m != 0); - // Self::print_constraints(n, self.q, &non_permuted_coeffs, &permutations); - // Self::print_terms_per_variable(n, self.q, &non_permuted_coeffs, &permutations); - // Self::print_terms_in_permutations(n, self.q, &non_permuted_coeffs, &permutations); - - // for i in 0..m { - // println!("Coeffs = {:?}", non_permuted_coeffs[i]); - // println!("Permutation = {:?}", permutations[i]); - // } - // find something faster, although it's still linear for i in 0..m { @@ -322,6 +243,198 @@ impl PermutationStructure { (non_permuted_coeffs, permutations) } + pub fn create_permutation_vectors(&self) -> (Vec>, Vec>) { + // we have to form non-permuted coefficients, as well as permutation structures; + let n = self.n; + let mut non_permuted_coeffs = vec![vec![E::Fr::zero(); 3*n+1]; M]; + let mut permutations = vec![vec![0usize; 3*n+1]; M]; + + let one = E::Fr::one(); + let mut minus_one = E::Fr::one(); + minus_one.negate(); + + let mut not_empty = [false; M]; + // go other the permutations + for (gate_index, info) in self.a.iter().enumerate() { + let offset = n-1; + for i in 0..M { + // coefficients of A are placed at the offset = 0 from the beginning of the vector + if let Some((coeff, place)) = info[i].as_ref() { + // place it + assert!(*place != 0); + let array_position = offset - gate_index; // special for A + let coeff_position = *place - 1; + let place_coeff_into = &mut non_permuted_coeffs[i]; + let place_permutation_into = &mut permutations[i]; + match coeff { + Coeff::Zero => { + }, + Coeff::One => { + not_empty[i] = true; + place_coeff_into[coeff_position] = one; + place_permutation_into[array_position] = *place; + }, + Coeff::NegativeOne => { + not_empty[i] = true; + place_coeff_into[coeff_position] = minus_one; + place_permutation_into[array_position] = *place; + }, + Coeff::Full(value) => { + not_empty[i] = true; + place_coeff_into[coeff_position] = *value; + place_permutation_into[array_position] = *place; + } + } + } + } + } + + for (gate_index, info) in self.b.iter().enumerate() { + let offset = n + 1; + for i in 0..M { + if let Some((coeff, place)) = info[i].as_ref() { + // place it + assert!(*place != 0); + let array_position = offset + gate_index; + let coeff_position = *place - 1; + let place_coeff_into = &mut non_permuted_coeffs[i]; + let place_permutation_into = &mut permutations[i]; + match coeff { + Coeff::Zero => { + }, + Coeff::One => { + not_empty[i] = true; + place_coeff_into[coeff_position] = one; + place_permutation_into[array_position] = *place; + }, + Coeff::NegativeOne => { + not_empty[i] = true; + place_coeff_into[coeff_position] = minus_one; + place_permutation_into[array_position] = *place; + }, + Coeff::Full(value) => { + not_empty[i] = true; + place_coeff_into[coeff_position] = *value; + place_permutation_into[array_position] = *place; + } + } + } + } + } + + for (gate_index, info) in self.c.iter().enumerate() { + let offset = 2*n + 1; + for i in 0..M { + // coefficients of A are placed at the offset = 0 from the beginning of the vector + if let Some((coeff, place)) = info[i].as_ref() { + // place it + assert!(*place != 0); + let array_position = offset + gate_index; + let coeff_position = *place - 1; + let place_coeff_into = &mut non_permuted_coeffs[i]; + let place_permutation_into = &mut permutations[i]; + match coeff { + Coeff::Zero => { + }, + Coeff::One => { + not_empty[i] = true; + place_coeff_into[coeff_position] = one; + place_permutation_into[array_position] = *place; + }, + Coeff::NegativeOne => { + not_empty[i] = true; + place_coeff_into[coeff_position] = minus_one; + place_permutation_into[array_position] = *place; + }, + Coeff::Full(value) => { + not_empty[i] = true; + place_coeff_into[coeff_position] = *value; + place_permutation_into[array_position] = *place; + } + } + } + } + } + + // Self::print_constraints(n, self.q, &non_permuted_coeffs, &permutations); + + // need to fill arrays with non-zero indexes just to have full permutation, even while it's just zero coefficient + + // TODO: fix + + let mut m = M; + // for i in (0..M).into_iter().rev() { + // // these are no constant terms + // assert!(non_permuted_coeffs[i][n].is_zero()); + // assert!(permutations[i][n] == 0); + // } + + for i in (0..M).into_iter().rev() { + if !not_empty[i] { + non_permuted_coeffs.pop(); + permutations.pop(); + m -= 1; + } + } + + assert!(m != 0); + + // find something faster, although it's still linear + + 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()) { + if *p == 0 { + continue; + // assert!(c.is_zero()); + } else { + fillers[*p - 1] = 0; + } + } + let mut fill_from = 0; + for p in permutations[i].iter_mut() { + if *p == 0 { + loop { + if fillers[fill_from] != 0 { + *p = fillers[fill_from]; + fill_from += 1; + break; + } else { + fill_from += 1; + } + } + } + } + } + + (non_permuted_coeffs, permutations) + } + + pub fn print_constraints(n:usize, q: usize, coeffs: &Vec>, permutations: &Vec>) { + let m = coeffs.len(); + + for constraint_idx in 1..=q { + println!("Constraint {} (term for Y^{})", constraint_idx, constraint_idx); + let mut terms = vec![]; + for p_idx in 0..m { + if let Some(variable_idx) = permutations[p_idx].iter().position(|&s| s == constraint_idx) { + let coeff = coeffs[p_idx][variable_idx]; + terms.push((variable_idx, coeff)); + } + } + for (var_idx, coeff) in terms.into_iter() { + if var_idx < n + 1 { + print!("{} * A({})", coeff, n - var_idx); + } else if var_idx < 2*n + 1 { + print!("{} * B({})", coeff, var_idx - n); + } else { + print!("{} * C({})", coeff, var_idx - 2*n); + } + print!("\n"); + } + } + } + pub fn create_permutation_special_reference(&self, srs: &SRS) -> SpecializedSRS { let (non_permuted_coeffs, permutations) = self.create_permutation_vectors(); @@ -335,9 +448,33 @@ impl PermutationStructure { specialized_srs } - pub fn make_signature(&self, y: E::Fr, z: E::Fr, srs: &SRS) { + pub fn make_signature(&self, y: E::Fr, z: E::Fr, srs: &SRS) -> SignatureOfCorrectComputation { let (non_permuted_coeffs, permutations) = self.create_permutation_vectors(); + let mut s_contrib = E::Fr::zero(); + for permutation_index in 0..permutations.len() { + for (variable_index, sigma_i) in permutations[permutation_index].iter().enumerate() { + let y_power = y.pow([*sigma_i as u64]); + let x_power = z.pow([(variable_index+1) as u64]); + let coeff = non_permuted_coeffs[permutation_index][*sigma_i - 1]; + + let mut result = coeff; + result.mul_assign(&x_power); + result.mul_assign(&y_power); + s_contrib.add_assign(&result); + } + } + + let z_n_plus_1_inv = z.pow([(self.n + 1) as u64]).inverse().unwrap(); + let y_n = y.pow([self.n as u64]); + + println!("Naive S contribution = {}", s_contrib); + + s_contrib.mul_assign(&z_n_plus_1_inv); + s_contrib.mul_assign(&y_n); + + println!("Naive S contribution scaled = {}", s_contrib); + let specialized_srs = PermutationArgument::make_specialized_srs( &non_permuted_coeffs, &permutations, @@ -352,6 +489,8 @@ impl PermutationStructure { &srs, &specialized_srs ); + + signature } pub fn create_permutation_arguments(&self, y: E::Fr, z: E::Fr, rng: &mut R, srs: &SRS) @@ -376,10 +515,10 @@ impl PermutationStructure { let mut s_contrib = E::Fr::zero(); for permutation_index in 0..m { - for (variable_index, constraint_power) in permutations[permutation_index].iter().enumerate() { - let y_power = y.pow([*constraint_power as u64]); + for (variable_index, sigma_i) in permutations[permutation_index].iter().enumerate() { + let y_power = y.pow([*sigma_i as u64]); let x_power = z.pow([(variable_index+1) as u64]); - let coeff = non_permuted_coeffs[permutation_index][variable_index]; + let coeff = non_permuted_coeffs[permutation_index][*sigma_i - 1]; let mut result = coeff; result.mul_assign(&x_power); @@ -388,6 +527,8 @@ impl PermutationStructure { } } + println!("Naive S contribution = {}", s_contrib); + let mut argument = PermutationArgument::new(non_permuted_coeffs, permutations); let challenges = (0..m).map(|_| E::Fr::rand(rng)).collect::>(); @@ -491,7 +632,8 @@ fn test_simple_succinct_sonic() { let srs_alpha = Fr::from_str("23728792").unwrap(); println!("making srs"); let start = Instant::now(); - let srs = SRS::::dummy(830564, srs_x, srs_alpha); + // let srs = SRS::::dummy(830564, srs_x, srs_alpha); + let srs = SRS::::new(100, srs_x, srs_alpha); println!("done in {:?}", start.elapsed()); { @@ -506,18 +648,52 @@ fn test_simple_succinct_sonic() { use crate::sonic::sonic::Permutation3; use crate::sonic::unhelped::permutation_structure::*; - let x: Fr = rng.gen(); - let y: Fr = rng.gen(); + // let z: Fr = rng.gen(); + // let y: Fr = rng.gen(); - let x = Fr::one(); - let mut y = Fr::one(); - y.double(); + let z: Fr = Fr::from_str("2").unwrap(); + let y: Fr = Fr::one(); let perm_structure = create_permutation_structure::(&MyCircuit); - perm_structure.create_permutation_arguments(x, y, rng, &srs); - perm_structure.make_signature(x, y, &srs); + let (non_permuted_coeffs, permutations) = perm_structure.create_permutation_vectors(); + println!("Non-permuted = {:?}", non_permuted_coeffs[0]); + println!("Permutation = {:?}", permutations[0]); + println!("N = {}, Q = {}", perm_structure.n, perm_structure.q); + let n = perm_structure.n; + let szy = { + let mut tmp = SxEval::::new(y, n); + Permutation3::synthesize(&mut tmp, &MyCircuit).unwrap(); // TODO + tmp.finalize(z) + }; + + let naive_s1 = { + let mut res = Fr::zero(); + for j in 0..permutations.len() { + 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 y_power = y.pow([sigma_i as u64]); + let x_power = z.pow([(i+1) as u64]); + // let mut result = coeff_sigma_i; + let mut result = coeff_i; + result.mul_assign(&y_power); + result.mul_assign(&x_power); + + res.add_assign(&result); + } + } + + res + }; + + println!("Naive s1 = {}", naive_s1); + + // perm_structure.create_permutation_arguments(y, z, rng, &srs); + let signature = perm_structure.make_signature(y, z, &srs); let s2 = S2Eval::new(perm_structure.n); - let s2 = s2.evaluate(x, y, &srs); + let s2 = s2.evaluate(z, y, &srs); let mut s2_value = s2.c_value; s2_value.add_assign(&s2.d_value); @@ -525,7 +701,7 @@ fn test_simple_succinct_sonic() { let y_inv = y.inverse().unwrap(); let mut p1 = y; p1.add_assign(&y_inv); - p1.mul_assign(&x); + p1.mul_assign(&z); expected_s2_value.add_assign(&p1); let mut t0 = y; @@ -536,13 +712,33 @@ fn test_simple_succinct_sonic() { let mut p2 = t0; p2.add_assign(&t1); - p2.mul_assign(&x); - p2.mul_assign(&x); + p2.mul_assign(&z); + p2.mul_assign(&z); expected_s2_value.add_assign(&p2); + let z_n = z.pow([n as u64]); + let z_n_plus_1_inv = z.pow([(n + 1) as u64]).inverse().unwrap(); + let y_n = y.pow([n as u64]); + assert!(expected_s2_value == s2_value); - println!("N = {}, Q = {}", perm_structure.n, perm_structure.q); + s2_value.mul_assign(&z_n); + + let mut s1 = signature.perm_argument_proof.s_zy; + println!("S1 = {}", s1); + s1.mul_assign(&z_n_plus_1_inv); + s1.mul_assign(&y_n); + + s1.sub_assign(&s2_value); + + let mut naive_s1 = naive_s1; + naive_s1.mul_assign(&z_n_plus_1_inv); + naive_s1.mul_assign(&y_n); + naive_s1.sub_assign(&s2_value); + + println!("S1(?) = {}", naive_s1); + + assert_eq!(s1, szy); } } \ No newline at end of file diff --git a/src/sonic/unhelped/verifier.rs b/src/sonic/unhelped/verifier.rs index 9531812..4d57d81 100644 --- a/src/sonic/unhelped/verifier.rs +++ b/src/sonic/unhelped/verifier.rs @@ -19,9 +19,14 @@ use crate::sonic::srs::SRS; use crate::sonic::sonic::Preprocess; use super::s2_proof::{S2Proof, S2Eval}; +use super::aggregate::SuccinctAggregate; use super::permutation_structure::create_permutation_structure; -use super::permutation_argument::SpecializedSRS; -use super::permutation_argument::{PermutationArgumentProof, PermutationProof, PermutationArgument}; +use super::permutation_argument::{ + PermutationArgumentProof, + PermutationProof, + PermutationArgument, + SpecializedSRS +}; pub struct SuccinctMultiVerifier, S: SynthesisDriver, R: Rng> { circuit: C, @@ -51,7 +56,6 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier let s2_special_reference = permutation_structure.calculate_s2_commitment_value(&srs); let s1_special_reference = permutation_structure.create_permutation_special_reference(&srs); - Ok(SuccinctMultiVerifier { circuit, s1_special_reference, @@ -65,91 +69,12 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier }) } - // pub fn add_non_succinct_aggregate( - // &mut self, - // proofs: &[(Proof, SxyAdvice)], - // aggregate: &Aggregate, - // ) - // { - // let mut transcript = Transcript::new(&[]); - // let mut y_values: Vec = Vec::with_capacity(proofs.len()); - // for &(ref proof, ref sxyadvice) in proofs { - // { - // let mut transcript = Transcript::new(&[]); - // transcript.commit_point(&proof.r); - // y_values.push(transcript.get_challenge_scalar()); - // } - - // transcript.commit_point(&sxyadvice.s); - // } - - // let z: E::Fr = transcript.get_challenge_scalar(); - - // let z = E::Fr::one(); - - // transcript.commit_point(&aggregate.c); - - // let w: E::Fr = transcript.get_challenge_scalar(); - - // let szw = { - // let mut tmp = SxEval::new(w, self.n); - // S::synthesize(&mut tmp, &self.circuit).unwrap(); // TODO - - // tmp.finalize(z) - // }; - - // println!("Nonsuccinct S(z,w) = {}", szw); - - // // { - // // let random: E::Fr = self.randomness_source.gen(); - - // // self.batch.add_opening(aggregate.opening, random, w); - // // self.batch.add_commitment(aggregate.c, random); - // // self.batch.add_opening_value(szw, random); - // // } - - // for ((opening, value), &y) in aggregate.c_openings.iter().zip(y_values.iter()) { - // let random: E::Fr = self.randomness_source.gen(); - - // self.batch.add_opening(*opening, random, y); - // self.batch.add_commitment(aggregate.c, random); - // self.batch.add_opening_value(*value, random); - // } - - // let random: E::Fr = self.randomness_source.gen(); - - // let mut expected_value = E::Fr::zero(); - // for ((_, advice), c_opening) in proofs.iter().zip(aggregate.c_openings.iter()) { - // let mut r: E::Fr = transcript.get_challenge_scalar(); - - // // expected value of the later opening - // { - // let mut tmp = c_opening.1; - // tmp.mul_assign(&r); - // expected_value.add_assign(&tmp); - // } - - // r.mul_assign(&random); - - // self.batch.add_commitment(advice.s, r); - // } - - // self.batch.add_opening_value(expected_value, random); - // self.batch.add_opening(aggregate.s_opening, random, z); - // } - pub fn add_aggregate( &mut self, proofs: &[(Proof, SxyAdvice)], - aggregate: &Aggregate, - permutation_argument_proof: &PermutationArgumentProof, - permutation_proof: &PermutationProof, - s2_proof: &S2Proof, - num_permutation_polynomials: usize, + aggregate: &SuccinctAggregate, srs: &SRS, - z_prime: E::Fr, // TODO, temporary before incorporation to the transcript - permutation_argument_commitments: & Vec<(E::G1Affine, E::G1Affine)>, - s_prime_challenges: Vec + specialized_srs: &SpecializedSRS ) { let mut transcript = Transcript::new(&[]); @@ -170,6 +95,8 @@ 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 @@ -184,6 +111,7 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier // simultaneously add components to the batch verifier // this is s2 contribution itself + let s2_proof = &aggregate.s2_proof; let mut s2_part = s2_proof.c_value; s2_part.add_assign(&s2_proof.d_value); s2_part.mul_assign(&x_n); @@ -222,50 +150,244 @@ impl, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier // now work with s1 part - let mut s1_part = permutation_argument_proof.s_zy; + let mut s1_part = aggregate.signature.perm_argument_proof.s_zy; s1_part.mul_assign(&x_n_plus_1_inv); s1_part.mul_assign(&y_n); - // TODO: this one should be from transcipt - // let s_prime_challenges = (0..num_permutation_polynomials).map(|_| E::Fr::rand(&mut self.randomness_source)).collect::>(); + let mut szw = s1_part; + szw.sub_assign(&s2_part); - // s and s' commitments of permutation argument - let mut s_commitments = vec![]; - let mut s_prime_commitments = vec![]; - for (s, s_prime) in permutation_argument_commitments.iter() { - s_commitments.push(*s); - s_prime_commitments.push(*s_prime); + // verify commitments for s' and s + + { + let mut transcript = Transcript::new(&[]); + + // let s_commitments = &aggregate.signature.s_commitments; + // let s_prime_commitments = &aggregate.signature.s_prime_commitments; + + let mut challenges = vec![]; + for (s, s_prime) in aggregate.signature.s_commitments.iter() + .zip(aggregate.signature.s_prime_commitments.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); + } + + let z_prime: E::Fr = transcript.get_challenge_scalar(); + + // we expect M permutation proofs, add them all into verification + // using batching with random challenges and extra randomness for pairing equation + { + // e(E,hαx)e(E−z′,hα) = e(􏰇Mj=1Sj′rj,h)e(g−v,hα) + let perm_proof = &aggregate.signature.perm_proof; + + let s_r = multiexp( + aggregate.signature.s_prime_commitments.iter(), + challenges.iter() + ).into_affine(); + + let p2_r = multiexp( + self.s1_special_reference.p_2.iter(), + challenges.iter() + ).into_affine(); + + + let value = perm_proof.v_zy; + + let random: E::Fr = self.randomness_source.gen(); + + self.batch.add_opening(perm_proof.e_opening, random, z_prime); + self.batch.add_opening_value(random, value); + self.batch.add_commitment(s_r, random); + + + // e(F,hαx)e(F−yz′,hα) = e(􏰇Mj=1P2jrj,h)e(g−v,hα) + + let mut y_z_prime = z_prime; + y_z_prime.mul_assign(&w); + + let random: E::Fr = self.randomness_source.gen(); + + self.batch.add_opening(perm_proof.f_opening, random, y_z_prime); + self.batch.add_opening_value(random, value); + self.batch.add_commitment(p2_r, random); + + } + + // now we can actually take an opening of S commitments and + + { + // e(I,hαx)e(I−z,hα) = e(􏰇Mj=1 Sj,h)e(g−s,hα) + + let value = aggregate.signature.perm_argument_proof.s_zy; + let mut s_commitment = E::G1::zero(); + + for s in aggregate.signature.s_commitments.iter() { + s_commitment.add_assign_mixed(s); + } + + let random: E::Fr = self.randomness_source.gen(); + + self.batch.add_opening(aggregate.signature.perm_argument_proof.s_opening, random, z); + self.batch.add_opening_value(random, value); + self.batch.add_commitment(s_commitment.into_affine(), random); + + } + + // TODO: Add grand product argument! + + // for each of the grand product arguments create a corresponding commitment + // 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![]; + + use crate::pairing::CurveAffine; + use crate::pairing::ff::PrimeField; + + for (j, (s, s_prime)) in aggregate.signature.s_commitments.iter() + .zip(aggregate.signature.s_prime_commitments.iter()) + .enumerate() + + { + // Sj(P4j)β(P1j)γ + + let mut a = s.into_projective(); + a.add_assign(&self.s1_special_reference.p_4[j].mul(beta.into_repr())); + a.add_assign(&self.s1_special_reference.p_1.mul(gamma.into_repr())); + let a = a.into_affine(); + + // Sj′(P3j)β(P1j)γ + + let mut b = s_prime.into_projective(); + b.add_assign(&self.s1_special_reference.p_3.mul(beta.into_repr())); + b.add_assign(&self.s1_special_reference.p_1.mul(gamma.into_repr())); + let b = b.into_affine(); + + // let a_original = aggregate.signature.grand_product_signature.a_commitments[j]; + // let b_original = aggregate.signature.grand_product_signature.b_commitments[j]; + + // assert!(a == a_original); + // assert!(b == b_original); + + a_commitments.push(a); + b_commitments.push(b); + } + + // Now perform an actual check + { + let randomness: Vec = (0..aggregate.signature.s_commitments.len()).map(|_| self.randomness_source.gen()).collect(); + // e(Dj,hαx)e(D−yz,hα) = e(Aj,h)e(Bj,hxn+1)e(g−aj ,hα) + + 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_x_n_plus_one_precomp = srs.h_positive_x[self.n]; + h_x_n_plus_one_precomp.negate(); + let h_x_n_plus_one_precomp = h_x_n_plus_one_precomp.prepare(); + + let mut h_prep = srs.h_positive_x[0]; + h_prep.negate(); + let h_prep = h_prep.prepare(); + + let a = multiexp( + a_commitments.iter(), + randomness.iter(), + ).into_affine(); + + let a = a.prepare(); + + let b = multiexp( + b_commitments.iter(), + randomness.iter(), + ).into_affine(); + + let b = b.prepare(); + + let mut yz_neg = w; + yz_neg.mul_assign(&z); + yz_neg.negate(); + + let mut ops = vec![]; + let mut value = E::Fr::zero(); + + for (el, r) in aggregate.signature.grand_product_signature.grand_product_openings.iter().zip(randomness.iter()) { + let (v, o) = el; + ops.push(o.clone()); + let mut val = *v; + val.mul_assign(&r); + value.add_assign(&val); + } + + let value = g.mul(value.into_repr()).into_affine().prepare(); + + let openings = multiexp( + ops.iter(), + randomness.iter(), + ).into_affine(); + + let openings_zy = openings.mul(yz_neg.into_repr()).into_affine().prepare(); + let openings = openings.prepare(); + + // e(Dj,hαx)e(D−yz,hα) = e(Aj,h)e(Bj,hxn+1)e(g−aj ,hα) + + let valid = E::final_exponentiation(&E::miller_loop(&[ + (&openings, &h_alpha_x_precomp), + (&openings_zy, &h_alpha_precomp), + (&a, &h_prep), + (&b, &h_x_n_plus_one_precomp), + (&value, &h_alpha_precomp) + ])).unwrap() == E::Fqk::one(); + + // TODO + // assert!(valid, "grand product arguments must be valid for individual commitments"); + + } + + + // TODO: sanity check for now, + // later eliminate a and b commitments + // for (j, (((a, b), s), s_prime)) in grand_product_signature.a_commitments.iter() + // .zip(grand_product_signature.b_commitments.iter()) + // .zip(s_commitments.iter()) + // .zip(s_prime_commitments.iter()) + // .enumerate() + // { + // // Sj(P4j)β(P1j)γ + // let mut lhs = s.into_projective(); + // lhs.add_assign(&specialized_srs.p_4[j].mul(beta.into_repr())); + // lhs.add_assign(&specialized_srs.p_1.mul(gamma.into_repr())); + + // assert!(lhs.into_affine() == *a); + + // // Sj′(P3j)β(P1j)γ + + // let mut rhs = s_prime.into_projective(); + // rhs.add_assign(&specialized_srs.p_3.mul(beta.into_repr())); + // rhs.add_assign(&specialized_srs.p_1.mul(gamma.into_repr())); + + // assert!(rhs.into_affine() == *b); + // } } - let randomness = (0..2).map(|_| E::Fr::rand(&mut self.randomness_source)).collect::>(); - - let valid = PermutationArgument::verify_s_prime_commitment(self.n, - &randomness, - &s_prime_challenges, - &s_prime_commitments, - permutation_proof, - w, - z_prime, - &self.s1_special_reference, - &srs); - - assert!(valid); - - // TODO: move all these to the transcripts - let beta : E::Fr = self.randomness_source.gen(); - let gamma : E::Fr = self.randomness_source.gen(); - - let valid = PermutationArgument::verify(&s_commitments, &permutation_argument_proof, z, &srs); - - assert!(valid); - - let mut s = s1_part; - s.sub_assign(&s2_part); - - s + 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 df8ca61..8f47c97 100644 --- a/src/sonic/unhelped/wellformed_argument.rs +++ b/src/sonic/unhelped/wellformed_argument.rs @@ -34,8 +34,9 @@ impl WellformednessArgument { srs: &SRS ) -> WellformednessSignature { let j = all_polys.len(); - let mut transcript = Transcript::new(&[]); + println!("Making wellformedness argument for {} polys", j); let wellformed_argument = WellformednessArgument::new(all_polys); + // TODO: remove commitments let commitments = wellformed_argument.commit(&srs); // let mut wellformed_challenges = vec![]; // for c in commitments.iter() {