permutation argument works as itself, but not for verifier
This commit is contained in:
parent
95b91fc0b0
commit
b8d4b0cea4
@ -104,6 +104,7 @@ impl<E: Engine> Batch<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// add `(r*P) to the h^(alpha*x) terms, add -(r*point)*P to h^(alpha) terms
|
||||||
pub fn add_opening(&mut self, p: E::G1Affine, mut r: E::Fr, point: E::Fr) {
|
pub fn add_opening(&mut self, p: E::G1Affine, mut r: E::Fr, point: E::Fr) {
|
||||||
self.alpha_x.push((p, r));
|
self.alpha_x.push((p, r));
|
||||||
r.mul_assign(&point);
|
r.mul_assign(&point);
|
||||||
@ -111,14 +112,17 @@ impl<E: Engine> Batch<E> {
|
|||||||
self.alpha.push((p, r));
|
self.alpha.push((p, r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// add (r*P) to -h^(x) terms
|
||||||
pub fn add_commitment(&mut self, p: E::G1Affine, r: E::Fr) {
|
pub fn add_commitment(&mut self, p: E::G1Affine, r: E::Fr) {
|
||||||
self.neg_h.push((p, r));
|
self.neg_h.push((p, r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// add (r*P) to -h^(d-n) terms
|
||||||
pub fn add_commitment_max_n(&mut self, p: E::G1Affine, r: E::Fr) {
|
pub fn add_commitment_max_n(&mut self, p: E::G1Affine, r: E::Fr) {
|
||||||
self.neg_x_n_minus_d.push((p, r));
|
self.neg_x_n_minus_d.push((p, r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// add (r*point) to g terms for later pairing with h^(alpha)
|
||||||
pub fn add_opening_value(&mut self, mut r: E::Fr, point: E::Fr) {
|
pub fn add_opening_value(&mut self, mut r: E::Fr, point: E::Fr) {
|
||||||
r.mul_assign(&point);
|
r.mul_assign(&point);
|
||||||
self.value.add_assign(&r);
|
self.value.add_assign(&r);
|
||||||
|
@ -26,6 +26,9 @@ pub struct Aggregate<E: Engine> {
|
|||||||
pub c_openings: Vec<(E::G1Affine, E::Fr)>,
|
pub c_openings: Vec<(E::G1Affine, E::Fr)>,
|
||||||
// Then we have to finally open C
|
// Then we have to finally open C
|
||||||
pub opening: E::G1Affine,
|
pub opening: E::G1Affine,
|
||||||
|
|
||||||
|
pub z: E::Fr,
|
||||||
|
pub w: E::Fr,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_aggregate<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
|
pub fn create_aggregate<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
|
||||||
@ -80,6 +83,8 @@ pub fn create_aggregate_on_srs_using_information<E: Engine, C: Circuit<E>, S: Sy
|
|||||||
|
|
||||||
let z: E::Fr = transcript.get_challenge_scalar();
|
let z: E::Fr = transcript.get_challenge_scalar();
|
||||||
|
|
||||||
|
// let z = E::Fr::one();
|
||||||
|
|
||||||
// Compute s(z, Y)
|
// Compute s(z, Y)
|
||||||
let (s_poly_negative, s_poly_positive) = {
|
let (s_poly_negative, s_poly_positive) = {
|
||||||
let mut tmp = SyEval::new(z, n, q);
|
let mut tmp = SyEval::new(z, n, q);
|
||||||
@ -101,8 +106,12 @@ pub fn create_aggregate_on_srs_using_information<E: Engine, C: Circuit<E>, S: Sy
|
|||||||
// Open C at w
|
// Open C at w
|
||||||
let w: E::Fr = transcript.get_challenge_scalar();
|
let w: E::Fr = transcript.get_challenge_scalar();
|
||||||
|
|
||||||
|
let w = E::Fr::one();
|
||||||
|
|
||||||
let value = compute_value::<E>(&w, &s_poly_positive, &s_poly_negative);
|
let value = compute_value::<E>(&w, &s_poly_positive, &s_poly_negative);
|
||||||
|
|
||||||
|
println!("In helper s(z, w) = {}", value);
|
||||||
|
|
||||||
let opening = {
|
let opening = {
|
||||||
let mut value = value;
|
let mut value = value;
|
||||||
value.negate();
|
value.negate();
|
||||||
@ -275,5 +284,9 @@ pub fn create_aggregate_on_srs_using_information<E: Engine, C: Circuit<E>, S: Sy
|
|||||||
c_openings,
|
c_openings,
|
||||||
// Then we have to finally open C
|
// Then we have to finally open C
|
||||||
opening,
|
opening,
|
||||||
|
|
||||||
|
z: z,
|
||||||
|
|
||||||
|
w: w
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,6 +32,7 @@ pub fn create_advice_on_information_and_srs<E: Engine, C: Circuit<E>, S: Synthes
|
|||||||
transcript.commit_point(&proof.t);
|
transcript.commit_point(&proof.t);
|
||||||
z = transcript.get_challenge_scalar();
|
z = transcript.get_challenge_scalar();
|
||||||
}
|
}
|
||||||
|
|
||||||
let z_inv = z.inverse().ok_or(SynthesisError::DivisionByZero)?;
|
let z_inv = z.inverse().ok_or(SynthesisError::DivisionByZero)?;
|
||||||
|
|
||||||
let (s_poly_negative, s_poly_positive) = {
|
let (s_poly_negative, s_poly_positive) = {
|
||||||
|
@ -66,10 +66,14 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng> MultiVerifier<E, C, S
|
|||||||
|
|
||||||
let z: E::Fr = transcript.get_challenge_scalar();
|
let z: E::Fr = transcript.get_challenge_scalar();
|
||||||
|
|
||||||
|
// let z = E::Fr::one();
|
||||||
|
|
||||||
transcript.commit_point(&aggregate.c);
|
transcript.commit_point(&aggregate.c);
|
||||||
|
|
||||||
let w: E::Fr = transcript.get_challenge_scalar();
|
let w: E::Fr = transcript.get_challenge_scalar();
|
||||||
|
|
||||||
|
let w = E::Fr::one();
|
||||||
|
|
||||||
let szw = {
|
let szw = {
|
||||||
let mut tmp = SxEval::new(w, self.n);
|
let mut tmp = SxEval::new(w, self.n);
|
||||||
S::synthesize(&mut tmp, &self.circuit).unwrap(); // TODO
|
S::synthesize(&mut tmp, &self.circuit).unwrap(); // TODO
|
||||||
|
@ -351,6 +351,112 @@ fn test_sonic_mimc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sonic_mimc_in_permutation_driver() {
|
||||||
|
use crate::pairing::ff::{Field, PrimeField};
|
||||||
|
use crate::pairing::{Engine, CurveAffine, CurveProjective};
|
||||||
|
use crate::pairing::bls12_381::{Bls12, Fr};
|
||||||
|
use std::time::{Instant};
|
||||||
|
use crate::sonic::srs::SRS;
|
||||||
|
|
||||||
|
let srs_x = Fr::from_str("23923").unwrap();
|
||||||
|
let srs_alpha = Fr::from_str("23728792").unwrap();
|
||||||
|
println!("making srs");
|
||||||
|
let start = Instant::now();
|
||||||
|
let srs = SRS::<Bls12>::dummy(830564, srs_x, srs_alpha);
|
||||||
|
println!("done in {:?}", start.elapsed());
|
||||||
|
|
||||||
|
{
|
||||||
|
// This may not be cryptographically safe, use
|
||||||
|
// `OsRng` (for example) in production software.
|
||||||
|
let rng = &mut thread_rng();
|
||||||
|
|
||||||
|
// Generate the MiMC round constants
|
||||||
|
let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::<Vec<_>>();
|
||||||
|
let samples: usize = 100;
|
||||||
|
|
||||||
|
let xl = rng.gen();
|
||||||
|
let xr = rng.gen();
|
||||||
|
let image = mimc::<Bls12>(xl, xr, &constants);
|
||||||
|
|
||||||
|
// Create an instance of our circuit (with the
|
||||||
|
// witness)
|
||||||
|
let circuit = MiMCDemoNoInputs {
|
||||||
|
xl: Some(xl),
|
||||||
|
xr: Some(xr),
|
||||||
|
image: Some(image),
|
||||||
|
constants: &constants
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::sonic::sonic::Basic;
|
||||||
|
use crate::sonic::sonic::AdaptorCircuit;
|
||||||
|
use crate::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs};
|
||||||
|
use crate::sonic::helped::{MultiVerifier, get_circuit_parameters};
|
||||||
|
use crate::sonic::helped::helper::{create_aggregate_on_srs};
|
||||||
|
use crate::sonic::sonic::Permutation3;
|
||||||
|
|
||||||
|
println!("creating proof");
|
||||||
|
let start = Instant::now();
|
||||||
|
let proof = create_proof_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &srs).unwrap();
|
||||||
|
println!("done in {:?}", start.elapsed());
|
||||||
|
|
||||||
|
println!("creating advice");
|
||||||
|
let start = Instant::now();
|
||||||
|
let advice = create_advice_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &proof, &srs).unwrap();
|
||||||
|
println!("done in {:?}", start.elapsed());
|
||||||
|
|
||||||
|
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::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &proofs, &srs);
|
||||||
|
println!("done in {:?}", start.elapsed());
|
||||||
|
|
||||||
|
{
|
||||||
|
let rng = thread_rng();
|
||||||
|
let mut verifier = MultiVerifier::<Bls12, _, Permutation3, _>::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::<Bls12, _, Permutation3, _>::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 rng = thread_rng();
|
||||||
|
let mut verifier = MultiVerifier::<Bls12, _, Permutation3, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||||
|
println!("verifying 100 proofs with advice");
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_succinct_sonic_mimc() {
|
fn test_succinct_sonic_mimc() {
|
||||||
use crate::pairing::ff::{Field, PrimeField};
|
use crate::pairing::ff::{Field, PrimeField};
|
||||||
@ -390,79 +496,136 @@ fn test_succinct_sonic_mimc() {
|
|||||||
use crate::sonic::sonic::Basic;
|
use crate::sonic::sonic::Basic;
|
||||||
use crate::sonic::sonic::AdaptorCircuit;
|
use crate::sonic::sonic::AdaptorCircuit;
|
||||||
use crate::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs};
|
use crate::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs};
|
||||||
use crate::sonic::helped::{MultiVerifier, get_circuit_parameters_for_succinct_sonic};
|
use crate::sonic::helped::{get_circuit_parameters_for_succinct_sonic, MultiVerifier};
|
||||||
use crate::sonic::helped::helper::{create_aggregate_on_srs};
|
use crate::sonic::helped::helper::{create_aggregate_on_srs};
|
||||||
use crate::sonic::sonic::Permutation3;
|
use crate::sonic::sonic::Permutation3;
|
||||||
use crate::sonic::unhelped::permutation_structure::*;
|
use crate::sonic::unhelped::permutation_structure::*;
|
||||||
|
use crate::sonic::unhelped::SuccinctMultiVerifier;
|
||||||
|
|
||||||
|
use crate::sonic::cs::{Circuit, ConstraintSystem, LinearCombination, Coeff};
|
||||||
|
|
||||||
|
struct MyCircuit;
|
||||||
|
|
||||||
|
impl<E: Engine> Circuit<E> for MyCircuit {
|
||||||
|
fn synthesize<CS: ConstraintSystem<E>>(&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()))?;
|
||||||
|
|
||||||
|
let dummy = cs.alloc_input(|| Ok(E::Fr::from_str("200").unwrap()))?;
|
||||||
|
|
||||||
|
cs.enforce_zero(LinearCombination::from(b) - multiplier);
|
||||||
|
cs.enforce_zero(LinearCombination::from(c) - dummy);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let perm_structure = create_permutation_structure::<Bls12, _>(&AdaptorCircuit(circuit.clone()));
|
let perm_structure = create_permutation_structure::<Bls12, _>(&AdaptorCircuit(circuit.clone()));
|
||||||
perm_structure.create_permutation_arguments(Fr::one(), Fr::one(), rng, &srs);
|
// let perm_structure = create_permutation_structure::<Bls12, _>(&MyCircuit);
|
||||||
|
let s1_srs = perm_structure.create_permutation_special_reference(&srs);
|
||||||
|
let s2_srs = perm_structure.calculate_s2_commitment_value(&srs);
|
||||||
println!("N = {}, Q = {}", perm_structure.n, perm_structure.q);
|
|
||||||
return;
|
|
||||||
|
|
||||||
// let info = get_circuit_parameters_for_succinct_sonic::<Bls12, _>(circuit.clone()).expect("Must get circuit info");
|
// let info = get_circuit_parameters_for_succinct_sonic::<Bls12, _>(circuit.clone()).expect("Must get circuit info");
|
||||||
// println!("{:?}", info);
|
// println!("{:?}", info);
|
||||||
|
|
||||||
// println!("creating proof");
|
println!("creating proof");
|
||||||
// let start = Instant::now();
|
let start = Instant::now();
|
||||||
// let proof = create_proof_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &srs).unwrap();
|
let proof = create_proof_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &srs).unwrap();
|
||||||
// println!("done in {:?}", start.elapsed());
|
println!("done in {:?}", start.elapsed());
|
||||||
|
|
||||||
// println!("creating advice");
|
println!("creating advice");
|
||||||
// let start = Instant::now();
|
let start = Instant::now();
|
||||||
// let advice = create_advice_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &proof, &srs).unwrap();
|
let advice = create_advice_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &proof, &srs).unwrap();
|
||||||
// println!("done in {:?}", start.elapsed());
|
println!("done in {:?}", start.elapsed());
|
||||||
|
|
||||||
// println!("creating aggregate for {} proofs", samples);
|
println!("creating aggregate for {} proofs", samples);
|
||||||
// let start = Instant::now();
|
let start = Instant::now();
|
||||||
// let proofs: Vec<_> = (0..samples).map(|_| (proof.clone(), advice.clone())).collect();
|
let proofs: Vec<_> = (0..samples).map(|_| (proof.clone(), advice.clone())).collect();
|
||||||
// let aggregate = create_aggregate_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &proofs, &srs);
|
let aggregate = create_aggregate_on_srs::<Bls12, _, Permutation3>(&AdaptorCircuit(circuit.clone()), &proofs, &srs);
|
||||||
// println!("done in {:?}", start.elapsed());
|
println!("done in {:?}", start.elapsed());
|
||||||
|
|
||||||
// {
|
{
|
||||||
// let rng = thread_rng();
|
let rng = thread_rng();
|
||||||
// let mut verifier = MultiVerifier::<Bls12, _, Permutation3, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
let mut verifier = MultiVerifier::<Bls12, _, Permutation3, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||||
// println!("verifying 1 proof without advice");
|
println!("verifying 1 proof without advice");
|
||||||
// let start = Instant::now();
|
let start = Instant::now();
|
||||||
// {
|
{
|
||||||
// for _ in 0..1 {
|
for _ in 0..1 {
|
||||||
// verifier.add_proof(&proof, &[], |_, _| None);
|
verifier.add_proof(&proof, &[], |_, _| None);
|
||||||
// }
|
}
|
||||||
// assert_eq!(verifier.check_all(), true); // TODO
|
assert_eq!(verifier.check_all(), true); // TODO
|
||||||
// }
|
}
|
||||||
// println!("done in {:?}", start.elapsed());
|
println!("done in {:?}", start.elapsed());
|
||||||
// }
|
}
|
||||||
|
|
||||||
// {
|
{
|
||||||
// let rng = thread_rng();
|
let rng = thread_rng();
|
||||||
// let mut verifier = MultiVerifier::<Bls12, _, Permutation3, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
let mut verifier = MultiVerifier::<Bls12, _, Permutation3, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||||
// println!("verifying {} proofs without advice", samples);
|
println!("verifying {} proofs without advice", samples);
|
||||||
// let start = Instant::now();
|
let start = Instant::now();
|
||||||
// {
|
{
|
||||||
// for _ in 0..samples {
|
for _ in 0..samples {
|
||||||
// verifier.add_proof(&proof, &[], |_, _| None);
|
verifier.add_proof(&proof, &[], |_, _| None);
|
||||||
// }
|
}
|
||||||
// assert_eq!(verifier.check_all(), true); // TODO
|
assert_eq!(verifier.check_all(), true); // TODO
|
||||||
// }
|
}
|
||||||
// println!("done in {:?}", start.elapsed());
|
println!("done in {:?}", start.elapsed());
|
||||||
// }
|
}
|
||||||
|
|
||||||
// {
|
{
|
||||||
// let rng = thread_rng();
|
let rng = thread_rng();
|
||||||
// let mut verifier = MultiVerifier::<Bls12, _, Permutation3, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
let mut verifier = MultiVerifier::<Bls12, _, Permutation3, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||||
// println!("verifying 100 proofs with advice");
|
println!("verifying 100 proofs with advice non-succinct");
|
||||||
// let start = Instant::now();
|
let start = Instant::now();
|
||||||
// {
|
{
|
||||||
// for (ref proof, ref advice) in &proofs {
|
for (ref proof, ref advice) in &proofs {
|
||||||
// verifier.add_proof_with_advice(proof, &[], advice);
|
verifier.add_proof_with_advice(proof, &[], advice);
|
||||||
// }
|
}
|
||||||
// verifier.add_aggregate(&proofs, &aggregate);
|
verifier.add_aggregate(&proofs, &aggregate);
|
||||||
// assert_eq!(verifier.check_all(), true); // TODO
|
assert_eq!(verifier.check_all(), true); // TODO
|
||||||
// }
|
}
|
||||||
// println!("done in {:?}", start.elapsed());
|
println!("done in {:?}", start.elapsed());
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
use rand::{XorShiftRng, SeedableRng, Rand, Rng};
|
||||||
|
let mut rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
|
let (perm_commitments, s_prime_challenges, perm_proof, perm_arg_proof, z_prime, num_poly) = perm_structure.create_permutation_arguments(aggregate.w, aggregate.z, &mut rng, &srs);
|
||||||
|
let s2_proof = perm_structure.calculate_s2_proof(aggregate.z, aggregate.w, &srs);
|
||||||
|
|
||||||
|
let mut verifier = SuccinctMultiVerifier::<Bls12, _, Permutation3, _>::new(AdaptorCircuit(circuit.clone()), &srs, rng).unwrap();
|
||||||
|
println!("verifying 100 proofs with advice");
|
||||||
|
let start = Instant::now();
|
||||||
|
{
|
||||||
|
for (ref proof, ref advice) in &proofs {
|
||||||
|
verifier.add_proof_with_advice(proof, &[], advice);
|
||||||
|
}
|
||||||
|
verifier.add_aggregate(
|
||||||
|
&proofs,
|
||||||
|
&aggregate,
|
||||||
|
&perm_arg_proof,
|
||||||
|
&perm_proof,
|
||||||
|
&s2_proof,
|
||||||
|
num_poly,
|
||||||
|
&srs,
|
||||||
|
z_prime,
|
||||||
|
&perm_commitments,
|
||||||
|
s_prime_challenges
|
||||||
|
);
|
||||||
|
assert_eq!(verifier.check_all(), true); // TODO
|
||||||
|
}
|
||||||
|
println!("done in {:?}", start.elapsed());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,5 +14,5 @@ pub mod permutation_structure;
|
|||||||
// pub mod padding;
|
// pub mod padding;
|
||||||
|
|
||||||
pub use self::wellformed_argument::{WellformednessArgument, WellformednessProof};
|
pub use self::wellformed_argument::{WellformednessArgument, WellformednessProof};
|
||||||
pub use self::permutation_argument::{PermutationArgument, PermutationProof, Proof};
|
pub use self::permutation_argument::{PermutationArgument, PermutationProof, PermutationArgumentProof};
|
||||||
pub use self::verifier::SuccinctMultiVerifier;
|
pub use self::verifier::SuccinctMultiVerifier;
|
@ -31,27 +31,27 @@ pub struct PermutationArgument<E: Engine> {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PermutationProof<E: Engine> {
|
pub struct PermutationProof<E: Engine> {
|
||||||
v_zy: E::Fr,
|
pub v_zy: E::Fr,
|
||||||
e_opening: E::G1Affine,
|
pub e_opening: E::G1Affine,
|
||||||
f_opening: E::G1Affine,
|
pub f_opening: E::G1Affine,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Proof<E: Engine> {
|
pub struct PermutationArgumentProof<E: Engine> {
|
||||||
j: usize,
|
pub j: usize,
|
||||||
s_opening: E::G1Affine,
|
pub s_opening: E::G1Affine,
|
||||||
s_zy: E::Fr
|
pub s_zy: E::Fr
|
||||||
}
|
}
|
||||||
|
|
||||||
fn permute<F: Field>(coeffs: &[F], permutation: & [usize]) -> Vec<F>{
|
fn permute<F: Field>(coeffs: &[F], permutation: & [usize]) -> Vec<F>{
|
||||||
assert_eq!(coeffs.len(), permutation.len());
|
assert_eq!(coeffs.len(), permutation.len());
|
||||||
let mut result: Vec<F> = vec![F::zero(); coeffs.len()];
|
let mut result: Vec<F> = vec![F::zero(); coeffs.len()];
|
||||||
for (i, j) in permutation.iter().enumerate() {
|
for (i, j) in permutation.iter().enumerate() {
|
||||||
if *j < 1 {
|
// if *j < 1 {
|
||||||
// if permutation information is missing coefficient itself must be zero!
|
// // if permutation information is missing coefficient itself must be zero!
|
||||||
assert!(coeffs[i].is_zero());
|
// assert!(coeffs[i].is_zero());
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
result[*j - 1] = coeffs[i];
|
result[*j - 1] = coeffs[i];
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
@ -234,9 +234,9 @@ impl<E: Engine> PermutationArgument<E> {
|
|||||||
wellformed_challenges: & Vec<E::Fr>,
|
wellformed_challenges: & Vec<E::Fr>,
|
||||||
y: E::Fr,
|
y: E::Fr,
|
||||||
z: E::Fr,
|
z: E::Fr,
|
||||||
specialized_srs: &SpecializedSRS<E>,
|
_specialized_srs: &SpecializedSRS<E>,
|
||||||
srs: &SRS<E>
|
srs: &SRS<E>
|
||||||
) -> Proof<E> {
|
) -> PermutationArgumentProof<E> {
|
||||||
// Sj(P4j)β(P1j)γ is equal to the product of the coefficients of Sj′(P3j)β(P1j)γ
|
// 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
|
// also open s = \sum self.permuted_coefficients(X, y) at z
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ impl<E: Engine> PermutationArgument<E> {
|
|||||||
|
|
||||||
let valid = GrandProductArgument::verify_ab_commitment(n,
|
let valid = GrandProductArgument::verify_ab_commitment(n,
|
||||||
&randomness,
|
&randomness,
|
||||||
&a_commitments,
|
& a_commitments,
|
||||||
& b_commitments,
|
& b_commitments,
|
||||||
&grand_product_openings,
|
&grand_product_openings,
|
||||||
y,
|
y,
|
||||||
@ -375,7 +375,7 @@ impl<E: Engine> PermutationArgument<E> {
|
|||||||
assert!(valid, "grand product argument must be valid");
|
assert!(valid, "grand product argument must be valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
Proof {
|
PermutationArgumentProof {
|
||||||
j: j,
|
j: j,
|
||||||
s_opening: s_zy_opening,
|
s_opening: s_zy_opening,
|
||||||
s_zy: s_zy
|
s_zy: s_zy
|
||||||
@ -542,7 +542,7 @@ impl<E: Engine> PermutationArgument<E> {
|
|||||||
|
|
||||||
pub fn verify(
|
pub fn verify(
|
||||||
s_commitments: &Vec<E::G1Affine>,
|
s_commitments: &Vec<E::G1Affine>,
|
||||||
proof: &Proof<E>,
|
proof: &PermutationArgumentProof<E>,
|
||||||
z: E::Fr,
|
z: E::Fr,
|
||||||
srs: &SRS<E>
|
srs: &SRS<E>
|
||||||
) -> bool {
|
) -> bool {
|
||||||
@ -651,7 +651,8 @@ fn test_permutation_argument() {
|
|||||||
gamma,
|
gamma,
|
||||||
& grand_product_challenges,
|
& grand_product_challenges,
|
||||||
& wellformed_challenges,
|
& wellformed_challenges,
|
||||||
y, z,
|
y,
|
||||||
|
z,
|
||||||
&specialized_srs, &srs);
|
&specialized_srs, &srs);
|
||||||
|
|
||||||
let valid = PermutationArgument::verify(&s_commitments, &proof, z, &srs);
|
let valid = PermutationArgument::verify(&s_commitments, &proof, z, &srs);
|
||||||
|
@ -80,9 +80,7 @@ impl<E: Engine> PermutationStructure<E> {
|
|||||||
s2_eval.evaluate(x, y, &srs)
|
s2_eval.evaluate(x, y, &srs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_permutation_arguments<R: Rng>(&self, y: E::Fr, z: E::Fr, rng: &mut R, srs: &SRS<E>)
|
fn create_permutation_vectors(&self) -> (Vec<Vec<E::Fr>>, Vec<Vec<usize>>) {
|
||||||
// -> PermutationProof<E>
|
|
||||||
{
|
|
||||||
// we have to form non-permuted coefficients, as well as permutation structures;
|
// we have to form non-permuted coefficients, as well as permutation structures;
|
||||||
let n = self.n;
|
let n = self.n;
|
||||||
let mut non_permuted_coeffs = vec![vec![E::Fr::zero(); 3*n+1]; M];
|
let mut non_permuted_coeffs = vec![vec![E::Fr::zero(); 3*n+1]; M];
|
||||||
@ -91,7 +89,7 @@ impl<E: Engine> PermutationStructure<E> {
|
|||||||
let one = E::Fr::one();
|
let one = E::Fr::one();
|
||||||
let mut minus_one = E::Fr::one();
|
let mut minus_one = E::Fr::one();
|
||||||
minus_one.negate();
|
minus_one.negate();
|
||||||
// println!("A");
|
|
||||||
let mut not_empty = [false; M];
|
let mut not_empty = [false; M];
|
||||||
// go other the permutations
|
// go other the permutations
|
||||||
for (gate_index, info) in self.a.iter().enumerate() {
|
for (gate_index, info) in self.a.iter().enumerate() {
|
||||||
@ -107,41 +105,27 @@ impl<E: Engine> PermutationStructure<E> {
|
|||||||
let place_permutation_into = &mut permutations[i];
|
let place_permutation_into = &mut permutations[i];
|
||||||
match coeff {
|
match coeff {
|
||||||
Coeff::Zero => {
|
Coeff::Zero => {
|
||||||
// println!("Variable A({}) coefficient 0 at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Coeff 0 will be for Y^{} for X^{} for permutation {} ", place, x_power, i);
|
|
||||||
},
|
},
|
||||||
Coeff::One => {
|
Coeff::One => {
|
||||||
not_empty[i] = true;
|
not_empty[i] = true;
|
||||||
place_coeff_into[array_position] = one;
|
place_coeff_into[array_position] = one;
|
||||||
place_permutation_into[array_position] = *place;
|
place_permutation_into[array_position] = *place;
|
||||||
// println!("Variable A({}) coefficient 1 at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Term 1*X^{}*Y^{} in poly {}", x_power, place,i);
|
|
||||||
// println!("Coeff 1 will be at for Y^{} for X^{} for permutation {} ", place, x_power, i);
|
|
||||||
},
|
},
|
||||||
Coeff::NegativeOne => {
|
Coeff::NegativeOne => {
|
||||||
not_empty[i] = true;
|
not_empty[i] = true;
|
||||||
place_coeff_into[array_position] = minus_one;
|
place_coeff_into[array_position] = minus_one;
|
||||||
place_permutation_into[array_position] = *place;
|
place_permutation_into[array_position] = *place;
|
||||||
// println!("Variable A({}) coefficient -1 at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Term -1*X^{}*Y^{} in poly {}", x_power, place,i);
|
|
||||||
// println!("Coeff -1 will be at for Y^{} for X^{} for permutation {} ", place, x_power, i);
|
|
||||||
},
|
},
|
||||||
Coeff::Full(value) => {
|
Coeff::Full(value) => {
|
||||||
not_empty[i] = true;
|
not_empty[i] = true;
|
||||||
place_coeff_into[array_position] = *value;
|
place_coeff_into[array_position] = *value;
|
||||||
place_permutation_into[array_position] = *place;
|
place_permutation_into[array_position] = *place;
|
||||||
// println!("Variable A({}) coefficient * at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Term k*X^{}*Y^{} in poly {}", x_power, place,i);
|
|
||||||
// println!("Coeff {} will be at for Y^{} for X^{} for permutation {} ", value, place, x_power, i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// println!("Empty coeff for X^{} in permutation {}", gate_index, i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// println!("B");
|
|
||||||
for (gate_index, info) in self.b.iter().enumerate() {
|
for (gate_index, info) in self.b.iter().enumerate() {
|
||||||
let offset = n + 1;
|
let offset = n + 1;
|
||||||
for i in 0..M {
|
for i in 0..M {
|
||||||
@ -154,41 +138,27 @@ impl<E: Engine> PermutationStructure<E> {
|
|||||||
let place_permutation_into = &mut permutations[i];
|
let place_permutation_into = &mut permutations[i];
|
||||||
match coeff {
|
match coeff {
|
||||||
Coeff::Zero => {
|
Coeff::Zero => {
|
||||||
// println!("Coeff 0 will be for Y^{} for X^{} for permutation {} ", place, x_power, i);
|
|
||||||
// println!("Variable B({}) coefficient 0 at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
},
|
},
|
||||||
Coeff::One => {
|
Coeff::One => {
|
||||||
not_empty[i] = true;
|
not_empty[i] = true;
|
||||||
place_coeff_into[array_position] = one;
|
place_coeff_into[array_position] = one;
|
||||||
place_permutation_into[array_position] = *place;
|
place_permutation_into[array_position] = *place;
|
||||||
// println!("Coeff 1 will be at for Y^{} for X^{} for permutation {} ", place, x_power, i);
|
|
||||||
// println!("Variable B({}) coefficient 1 at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Term 1*X^{}*Y^{} in poly {}", x_power, place,i);
|
|
||||||
},
|
},
|
||||||
Coeff::NegativeOne => {
|
Coeff::NegativeOne => {
|
||||||
not_empty[i] = true;
|
not_empty[i] = true;
|
||||||
place_coeff_into[array_position] = minus_one;
|
place_coeff_into[array_position] = minus_one;
|
||||||
place_permutation_into[array_position] = *place;
|
place_permutation_into[array_position] = *place;
|
||||||
// println!("Coeff -1 will be at for Y^{} for X^{} for permutation {} ", place, x_power, i);
|
|
||||||
// println!("Variable B({}) coefficient -1 at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Term -1*X^{}*Y^{} in poly {}", x_power, place,i);
|
|
||||||
},
|
},
|
||||||
Coeff::Full(value) => {
|
Coeff::Full(value) => {
|
||||||
not_empty[i] = true;
|
not_empty[i] = true;
|
||||||
place_coeff_into[array_position] = *value;
|
place_coeff_into[array_position] = *value;
|
||||||
place_permutation_into[array_position] = *place;
|
place_permutation_into[array_position] = *place;
|
||||||
// println!("Coeff {} will be at for Y^{} for X^{} for permutation {} ", value, place, x_power, i);
|
|
||||||
// println!("Variable B({}) coefficient * at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Term k*X^{}*Y^{} in poly {}", x_power, place,i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// println!("Empty coeff for X^{} in permutation {}", gate_index, i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// println!("C");
|
|
||||||
for (gate_index, info) in self.c.iter().enumerate() {
|
for (gate_index, info) in self.c.iter().enumerate() {
|
||||||
let offset = 2*n + 1;
|
let offset = 2*n + 1;
|
||||||
for i in 0..M {
|
for i in 0..M {
|
||||||
@ -202,55 +172,29 @@ impl<E: Engine> PermutationStructure<E> {
|
|||||||
let place_permutation_into = &mut permutations[i];
|
let place_permutation_into = &mut permutations[i];
|
||||||
match coeff {
|
match coeff {
|
||||||
Coeff::Zero => {
|
Coeff::Zero => {
|
||||||
// println!("Coeff 0 will be for Y^{} for X^{} for permutation {} ", place, x_power, i);
|
|
||||||
// println!("Variable C({}) coefficient 0 at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
},
|
},
|
||||||
Coeff::One => {
|
Coeff::One => {
|
||||||
not_empty[i] = true;
|
not_empty[i] = true;
|
||||||
place_coeff_into[array_position] = one;
|
place_coeff_into[array_position] = one;
|
||||||
place_permutation_into[array_position] = *place;
|
place_permutation_into[array_position] = *place;
|
||||||
// println!("Coeff 1 will be at for Y^{} for X^{} for permutation {} ", place, x_power, i);
|
|
||||||
// println!("Variable C({}) coefficient 1 at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Term 1*X^{}*Y^{} in poly {}", x_power, place,i);
|
|
||||||
},
|
},
|
||||||
Coeff::NegativeOne => {
|
Coeff::NegativeOne => {
|
||||||
not_empty[i] = true;
|
not_empty[i] = true;
|
||||||
place_coeff_into[array_position] = minus_one;
|
place_coeff_into[array_position] = minus_one;
|
||||||
place_permutation_into[array_position] = *place;
|
place_permutation_into[array_position] = *place;
|
||||||
// println!("Coeff -1 will be at for Y^{} for X^{} for permutation {} ", place, x_power, i);
|
|
||||||
// println!("Variable C({}) coefficient -1 at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Term -1*X^{}*Y^{} in poly {}", x_power, place,i);
|
|
||||||
},
|
},
|
||||||
Coeff::Full(value) => {
|
Coeff::Full(value) => {
|
||||||
not_empty[i] = true;
|
not_empty[i] = true;
|
||||||
place_coeff_into[array_position] = *value;
|
place_coeff_into[array_position] = *value;
|
||||||
place_permutation_into[array_position] = *place;
|
place_permutation_into[array_position] = *place;
|
||||||
// println!("Coeff {} will be at for Y^{} for X^{} for permutation {} ", value, place, x_power, i);
|
|
||||||
// println!("Variable C({}) coefficient * at constraint {} in poly {}", gate_index+1, place, i);
|
|
||||||
// println!("Term k*X^{}*Y^{} in poly {}", x_power, place,i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// println!("Empty coeff for X^{} in permutation {}", gate_index, i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to fill arrays with non-zero indexes just to have full permutation, even while it's just zero coefficient
|
// need to fill arrays with non-zero indexes just to have full permutation, even while it's just zero coefficient
|
||||||
|
|
||||||
// permutations[0][2] = 5;
|
|
||||||
// permutations[0][5] = 6;
|
|
||||||
// permutations[0][6] = 7;
|
|
||||||
|
|
||||||
// permutations[1][0] = 1;
|
|
||||||
// permutations[1][1] = 3;
|
|
||||||
// permutations[1][2] = 5;
|
|
||||||
// permutations[1][5] = 6;
|
|
||||||
// permutations[1][6] = 7;
|
|
||||||
|
|
||||||
|
|
||||||
println!("Not empty = {:?}", not_empty);
|
|
||||||
|
|
||||||
// TODO: fix
|
// TODO: fix
|
||||||
|
|
||||||
let mut m = M;
|
let mut m = M;
|
||||||
@ -292,14 +236,34 @@ impl<E: Engine> PermutationStructure<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(non_permuted_coeffs, permutations)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_permutation_special_reference(&self, srs: &SRS<E>) -> SpecializedSRS<E>
|
||||||
|
{
|
||||||
|
let (non_permuted_coeffs, permutations) = self.create_permutation_vectors();
|
||||||
|
|
||||||
|
let specialized_srs = PermutationArgument::make_specialized_srs(
|
||||||
|
&non_permuted_coeffs,
|
||||||
|
&permutations,
|
||||||
|
&srs
|
||||||
|
);
|
||||||
|
|
||||||
|
specialized_srs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_permutation_arguments<R: Rng>(&self, y: E::Fr, z: E::Fr, rng: &mut R, srs: &SRS<E>)
|
||||||
|
-> (Vec<(E::G1Affine, E::G1Affine)>, Vec<E::Fr>, PermutationProof<E>, PermutationArgumentProof<E>, E::Fr, usize)
|
||||||
|
{
|
||||||
|
// we have to form non-permuted coefficients, as well as permutation structures;
|
||||||
|
let n = self.n;
|
||||||
|
|
||||||
|
let (non_permuted_coeffs, permutations) = self.create_permutation_vectors();
|
||||||
|
|
||||||
|
let m = non_permuted_coeffs.len();
|
||||||
|
|
||||||
println!("Will need {} permutation polynomials", m);
|
println!("Will need {} permutation polynomials", m);
|
||||||
|
|
||||||
// println!("Nonpermuted 0 (coeffs for X^1, X^2, ...) = {:?}", non_permuted_coeffs[0]);
|
|
||||||
// println!("Permutation 0 (power of Y for X^1, X^2, ...) = {:?}", permutations[0]);
|
|
||||||
|
|
||||||
// println!("Nonpermuted 1 (coeffs for X^1, X^2, ...)= {:?}", non_permuted_coeffs[1]);
|
|
||||||
// println!("Permutation 1 (power of Y for X^1, X^2, ...) = {:?}", permutations[1]);
|
|
||||||
|
|
||||||
let specialized_srs = PermutationArgument::make_specialized_srs(
|
let specialized_srs = PermutationArgument::make_specialized_srs(
|
||||||
&non_permuted_coeffs,
|
&non_permuted_coeffs,
|
||||||
&permutations,
|
&permutations,
|
||||||
@ -312,12 +276,13 @@ impl<E: Engine> PermutationStructure<E> {
|
|||||||
let commitments = argument.commit(y, &srs);
|
let commitments = argument.commit(y, &srs);
|
||||||
let mut s_commitments = vec![];
|
let mut s_commitments = vec![];
|
||||||
let mut s_prime_commitments = vec![];
|
let mut s_prime_commitments = vec![];
|
||||||
for (s, s_prime) in commitments.into_iter() {
|
for (s, s_prime) in commitments.clone().into_iter() {
|
||||||
s_commitments.push(s);
|
s_commitments.push(s);
|
||||||
// println!("S' = {}", s_prime);
|
// println!("S' = {}", s_prime);
|
||||||
s_prime_commitments.push(s_prime);
|
s_prime_commitments.push(s_prime);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let z_prime : E::Fr = rng.gen();
|
let z_prime : E::Fr = rng.gen();
|
||||||
|
|
||||||
let opening = argument.open_commitments_to_s_prime(&challenges, y, z_prime, &srs);
|
let opening = argument.open_commitments_to_s_prime(&challenges, y, z_prime, &srs);
|
||||||
@ -354,6 +319,8 @@ impl<E: Engine> PermutationStructure<E> {
|
|||||||
let valid = PermutationArgument::verify(&s_commitments, &proof, z, &srs);
|
let valid = PermutationArgument::verify(&s_commitments, &proof, z, &srs);
|
||||||
|
|
||||||
assert!(valid, "permutation argument must be valid");
|
assert!(valid, "permutation argument must be valid");
|
||||||
|
|
||||||
|
(commitments, challenges, opening, proof, z_prime, m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,10 +14,10 @@ pub struct S2Eval<E: Engine> {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct S2Proof<E: Engine> {
|
pub struct S2Proof<E: Engine> {
|
||||||
o: E::G1Affine,
|
o: E::G1Affine,
|
||||||
c_value: E::Fr,
|
pub c_value: E::Fr,
|
||||||
d_value: E::Fr,
|
pub d_value: E::Fr,
|
||||||
c_opening: E::G1Affine,
|
pub c_opening: E::G1Affine,
|
||||||
d_opening: E::G1Affine
|
pub d_opening: E::G1Affine
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> S2Eval<E> {
|
impl<E: Engine> S2Eval<E> {
|
||||||
@ -48,7 +48,7 @@ impl<E: Engine> S2Eval<E> {
|
|||||||
let (c, c_opening) = {
|
let (c, c_opening) = {
|
||||||
let mut point = y;
|
let mut point = y;
|
||||||
point.mul_assign(&x);
|
point.mul_assign(&x);
|
||||||
let val = evaluate_at_consequitive_powers(&poly[1..], E::Fr::one(), point);
|
let val = evaluate_at_consequitive_powers(&poly[1..], point, point);
|
||||||
poly[0] = val;
|
poly[0] = val;
|
||||||
poly[0].negate();
|
poly[0].negate();
|
||||||
let opening = polynomial_commitment_opening(0, self.n, poly.iter(), point, &srs);
|
let opening = polynomial_commitment_opening(0, self.n, poly.iter(), point, &srs);
|
||||||
@ -59,7 +59,7 @@ impl<E: Engine> S2Eval<E> {
|
|||||||
let (d, d_opening) = {
|
let (d, d_opening) = {
|
||||||
let mut point = y.inverse().unwrap();
|
let mut point = y.inverse().unwrap();
|
||||||
point.mul_assign(&x);
|
point.mul_assign(&x);
|
||||||
let val = evaluate_at_consequitive_powers(&poly[1..], E::Fr::one(), point);
|
let val = evaluate_at_consequitive_powers(&poly[1..], point, point);
|
||||||
poly[0] = val;
|
poly[0] = val;
|
||||||
poly[0].negate();
|
poly[0].negate();
|
||||||
let opening = polynomial_commitment_opening(0, self.n, poly.iter(), point, &srs);
|
let opening = polynomial_commitment_opening(0, self.n, poly.iter(), point, &srs);
|
||||||
@ -87,17 +87,19 @@ impl<E: Engine> S2Eval<E> {
|
|||||||
h_prep.negate();
|
h_prep.negate();
|
||||||
let h_prep = h_prep.prepare();
|
let h_prep = h_prep.prepare();
|
||||||
|
|
||||||
let mut c_minus_xy = proof.c_value;
|
let mut minus_xy = x;
|
||||||
let mut xy = x;
|
minus_xy.mul_assign(&y);
|
||||||
xy.mul_assign(&y);
|
minus_xy.negate();
|
||||||
|
|
||||||
c_minus_xy.sub_assign(&xy);
|
let mut h_alpha_term = proof.c_opening.mul(minus_xy.into_repr());
|
||||||
|
let g_in_c = E::G1Affine::one().mul(proof.c_value);
|
||||||
|
h_alpha_term.add_assign(&g_in_c);
|
||||||
|
|
||||||
let c_in_c_minus_xy = proof.c_opening.mul(c_minus_xy.into_repr()).into_affine();
|
let h_alpha_term = h_alpha_term.into_affine();
|
||||||
|
|
||||||
let valid = E::final_exponentiation(&E::miller_loop(&[
|
let valid = E::final_exponentiation(&E::miller_loop(&[
|
||||||
(&proof.c_opening.prepare(), &alpha_x_precomp),
|
(&proof.c_opening.prepare(), &alpha_x_precomp),
|
||||||
(&c_in_c_minus_xy.prepare(), &alpha_precomp),
|
(&h_alpha_term.prepare(), &alpha_precomp),
|
||||||
(&proof.o.prepare(), &h_prep),
|
(&proof.o.prepare(), &h_prep),
|
||||||
])).unwrap() == E::Fqk::one();
|
])).unwrap() == E::Fqk::one();
|
||||||
|
|
||||||
@ -107,17 +109,19 @@ impl<E: Engine> S2Eval<E> {
|
|||||||
|
|
||||||
// e(D,hαx)e(D−y−1z,hα) = e(O,h)e(g−d,hα)
|
// e(D,hαx)e(D−y−1z,hα) = e(O,h)e(g−d,hα)
|
||||||
|
|
||||||
let mut d_minus_x_y_inv = proof.d_value;
|
let mut minus_x_y_inv = x;
|
||||||
let mut x_y_inv = x;
|
minus_x_y_inv.mul_assign(&y.inverse().unwrap());
|
||||||
x_y_inv.mul_assign(&y.inverse().unwrap());
|
minus_x_y_inv.negate();
|
||||||
|
|
||||||
d_minus_x_y_inv.sub_assign(&x_y_inv);
|
let mut h_alpha_term = proof.d_opening.mul(minus_x_y_inv.into_repr());
|
||||||
|
let g_in_d = E::G1Affine::one().mul(proof.d_value);
|
||||||
|
h_alpha_term.add_assign(&g_in_d);
|
||||||
|
|
||||||
let d_in_d_minus_x_y_inv = proof.d_opening.mul(d_minus_x_y_inv.into_repr()).into_affine();
|
let h_alpha_term = h_alpha_term.into_affine();
|
||||||
|
|
||||||
let valid = E::final_exponentiation(&E::miller_loop(&[
|
let valid = E::final_exponentiation(&E::miller_loop(&[
|
||||||
(&proof.d_opening.prepare(), &alpha_x_precomp),
|
(&proof.d_opening.prepare(), &alpha_x_precomp),
|
||||||
(&d_in_d_minus_x_y_inv.prepare(), &alpha_precomp),
|
(&h_alpha_term.prepare(), &alpha_precomp),
|
||||||
(&proof.o.prepare(), &h_prep),
|
(&proof.o.prepare(), &h_prep),
|
||||||
])).unwrap() == E::Fqk::one();
|
])).unwrap() == E::Fqk::one();
|
||||||
|
|
||||||
@ -127,4 +131,37 @@ impl<E: Engine> S2Eval<E> {
|
|||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_s2_proof() {
|
||||||
|
use crate::pairing::ff::{Field, PrimeField};
|
||||||
|
use crate::pairing::{Engine, CurveAffine, CurveProjective};
|
||||||
|
use crate::pairing::bls12_381::{Bls12, Fr};
|
||||||
|
use std::time::{Instant};
|
||||||
|
use crate::sonic::srs::SRS;
|
||||||
|
use crate::sonic::cs::{Circuit, ConstraintSystem, LinearCombination};
|
||||||
|
|
||||||
|
let srs_x = Fr::from_str("23923").unwrap();
|
||||||
|
let srs_alpha = Fr::from_str("23728792").unwrap();
|
||||||
|
println!("making srs");
|
||||||
|
let start = Instant::now();
|
||||||
|
let srs = SRS::<Bls12>::dummy(830564, srs_x, srs_alpha);
|
||||||
|
println!("done in {:?}", start.elapsed());
|
||||||
|
|
||||||
|
{
|
||||||
|
use rand::{XorShiftRng, SeedableRng, Rand, Rng};
|
||||||
|
let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
|
let x: Fr = rng.gen();
|
||||||
|
let y: Fr = rng.gen();
|
||||||
|
|
||||||
|
let proof = S2Eval::new(1024);
|
||||||
|
let proof = proof.evaluate(x, y, &srs);
|
||||||
|
|
||||||
|
let valid = S2Eval::verify(x, y, &proof, &srs);
|
||||||
|
|
||||||
|
assert!(valid);
|
||||||
|
}
|
||||||
}
|
}
|
@ -18,8 +18,15 @@ use crate::sonic::cs::{Circuit, Variable, Coeff};
|
|||||||
use crate::sonic::srs::SRS;
|
use crate::sonic::srs::SRS;
|
||||||
use crate::sonic::sonic::Preprocess;
|
use crate::sonic::sonic::Preprocess;
|
||||||
|
|
||||||
|
use super::s2_proof::{S2Proof, S2Eval};
|
||||||
|
use super::permutation_structure::create_permutation_structure;
|
||||||
|
use super::permutation_argument::SpecializedSRS;
|
||||||
|
use super::permutation_argument::{PermutationArgumentProof, PermutationProof, PermutationArgument};
|
||||||
|
|
||||||
pub struct SuccinctMultiVerifier<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng> {
|
pub struct SuccinctMultiVerifier<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng> {
|
||||||
circuit: C,
|
circuit: C,
|
||||||
|
s1_special_reference: SpecializedSRS<E>,
|
||||||
|
s2_special_reference: E::G1Affine,
|
||||||
pub(crate) batch: Batch<E>,
|
pub(crate) batch: Batch<E>,
|
||||||
k_map: Vec<usize>,
|
k_map: Vec<usize>,
|
||||||
n: usize,
|
n: usize,
|
||||||
@ -31,26 +38,118 @@ pub struct SuccinctMultiVerifier<E: Engine, C: Circuit<E>, S: SynthesisDriver, R
|
|||||||
impl<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier<E, C, S, R> {
|
impl<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier<E, C, S, R> {
|
||||||
// This constructor consumes randomness source cause it's later used internally
|
// This constructor consumes randomness source cause it's later used internally
|
||||||
pub fn new(circuit: C, srs: &SRS<E>, rng: R) -> Result<Self, SynthesisError> {
|
pub fn new(circuit: C, srs: &SRS<E>, rng: R) -> Result<Self, SynthesisError> {
|
||||||
let mut preprocess = Preprocess::new();
|
let (n, q, k_map) = {
|
||||||
|
let mut preprocess = Preprocess::new();
|
||||||
|
S::synthesize(&mut preprocess, &circuit)?;
|
||||||
|
|
||||||
|
(preprocess.n, preprocess.q, preprocess.k_map)
|
||||||
|
};
|
||||||
|
|
||||||
|
// also calculate special reference for s1
|
||||||
|
|
||||||
|
let permutation_structure = create_permutation_structure(&circuit);
|
||||||
|
let s2_special_reference = permutation_structure.calculate_s2_commitment_value(&srs);
|
||||||
|
let s1_special_reference = permutation_structure.create_permutation_special_reference(&srs);
|
||||||
|
|
||||||
S::synthesize(&mut preprocess, &circuit)?;
|
|
||||||
|
|
||||||
Ok(SuccinctMultiVerifier {
|
Ok(SuccinctMultiVerifier {
|
||||||
circuit,
|
circuit,
|
||||||
batch: Batch::new(srs, preprocess.n),
|
s1_special_reference,
|
||||||
k_map: preprocess.k_map,
|
s2_special_reference,
|
||||||
n: preprocess.n,
|
batch: Batch::new(srs, n),
|
||||||
q: preprocess.q,
|
k_map: k_map,
|
||||||
|
n: n,
|
||||||
|
q: q,
|
||||||
randomness_source: rng,
|
randomness_source: rng,
|
||||||
_marker: PhantomData
|
_marker: PhantomData
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub fn add_non_succinct_aggregate(
|
||||||
|
// &mut self,
|
||||||
|
// proofs: &[(Proof<E>, SxyAdvice<E>)],
|
||||||
|
// aggregate: &Aggregate<E>,
|
||||||
|
// )
|
||||||
|
// {
|
||||||
|
// let mut transcript = Transcript::new(&[]);
|
||||||
|
// let mut y_values: Vec<E::Fr> = 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(
|
pub fn add_aggregate(
|
||||||
&mut self,
|
&mut self,
|
||||||
proofs: &[(Proof<E>, SxyAdvice<E>)],
|
proofs: &[(Proof<E>, SxyAdvice<E>)],
|
||||||
aggregate: &Aggregate<E>,
|
aggregate: &Aggregate<E>,
|
||||||
szw: E::Fr
|
permutation_argument_proof: &PermutationArgumentProof<E>,
|
||||||
|
permutation_proof: &PermutationProof<E>,
|
||||||
|
s2_proof: &S2Proof<E>,
|
||||||
|
num_permutation_polynomials: usize,
|
||||||
|
srs: &SRS<E>,
|
||||||
|
z_prime: E::Fr, // TODO, temporary before incorporation to the transcript
|
||||||
|
permutation_argument_commitments: & Vec<(E::G1Affine, E::G1Affine)>,
|
||||||
|
s_prime_challenges: Vec<E::Fr>
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let mut transcript = Transcript::new(&[]);
|
let mut transcript = Transcript::new(&[]);
|
||||||
@ -67,16 +166,119 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver, R: Rng> SuccinctMultiVerifier
|
|||||||
|
|
||||||
let z: E::Fr = transcript.get_challenge_scalar();
|
let z: E::Fr = transcript.get_challenge_scalar();
|
||||||
|
|
||||||
|
// let z = E::Fr::one();
|
||||||
|
|
||||||
|
println!("Verifier z = {}", z);
|
||||||
|
|
||||||
transcript.commit_point(&aggregate.c);
|
transcript.commit_point(&aggregate.c);
|
||||||
|
|
||||||
let w: E::Fr = transcript.get_challenge_scalar();
|
let w: E::Fr = transcript.get_challenge_scalar();
|
||||||
|
|
||||||
// let szw = {
|
let w = E::Fr::one();
|
||||||
// let mut tmp = SxEval::new(w, self.n);
|
|
||||||
// S::synthesize(&mut tmp, &self.circuit).unwrap(); // TODO
|
|
||||||
|
|
||||||
// tmp.finalize(z)
|
println!("Verifier w = {}", w);
|
||||||
// };
|
|
||||||
|
println!("N = {}", self.n);
|
||||||
|
|
||||||
|
let szw = {
|
||||||
|
// prover will supply s1 and s2, need to calculate
|
||||||
|
// s(z, w) = X^-(N+1) * Y^N * s1 - X^N * s2
|
||||||
|
|
||||||
|
let x_n = z.pow(&[self.n as u64]);
|
||||||
|
let mut x_n_plus_1 = x_n;
|
||||||
|
x_n_plus_1.mul_assign(&z);
|
||||||
|
let x_n_plus_1_inv = x_n_plus_1.inverse().unwrap();
|
||||||
|
|
||||||
|
let y_n = w.pow(&[self.n as u64]);
|
||||||
|
|
||||||
|
// simultaneously add components to the batch verifier
|
||||||
|
|
||||||
|
// this is s2 contribution itself
|
||||||
|
let mut s2_part = s2_proof.c_value;
|
||||||
|
s2_part.add_assign(&s2_proof.d_value);
|
||||||
|
println!("S2 = {}", s2_part);
|
||||||
|
s2_part.mul_assign(&x_n);
|
||||||
|
|
||||||
|
// add terms for S2 for verification
|
||||||
|
|
||||||
|
// {
|
||||||
|
// let random: E::Fr = self.randomness_source.gen();
|
||||||
|
|
||||||
|
// // e(C,hαx)e(C−yz,hα) = e(O,h)e(g−c,hα) that is
|
||||||
|
// // e(C,hαx)e(C^−yz,hα)*e(O,-h)e(g^c,hα) = 1
|
||||||
|
|
||||||
|
// let mut xy = z;
|
||||||
|
// xy.mul_assign(&w);
|
||||||
|
|
||||||
|
// self.batch.add_opening(s2_proof.c_opening, random, xy);
|
||||||
|
// self.batch.add_opening_value(random, s2_proof.c_value);
|
||||||
|
// self.batch.add_commitment(self.s2_special_reference, random);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// {
|
||||||
|
// let random: E::Fr = self.randomness_source.gen();
|
||||||
|
|
||||||
|
// // e(D,hαx)e(D−y−1z,hα) = e(O,h)e(g−d,hα) that is
|
||||||
|
// // e(D,hαx)e(D^−y-1z,hα)*e(O,-h)e(g^d,hα) = 1
|
||||||
|
|
||||||
|
// let mut y_inv_by_x = z;
|
||||||
|
// y_inv_by_x.mul_assign(&w.inverse().unwrap());
|
||||||
|
|
||||||
|
// self.batch.add_opening(s2_proof.d_opening, random, y_inv_by_x);
|
||||||
|
// self.batch.add_opening_value(random, s2_proof.d_value);
|
||||||
|
// self.batch.add_commitment(self.s2_special_reference, random);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// now work with s1 part
|
||||||
|
|
||||||
|
let mut s1_part = permutation_argument_proof.s_zy;
|
||||||
|
println!("S1 = {}", s1_part);
|
||||||
|
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::<Vec<_>>();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let randomness = (0..2).map(|_| E::Fr::rand(&mut self.randomness_source)).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("Succinct s(z, w) = {}", szw);
|
||||||
|
|
||||||
{
|
{
|
||||||
let random: E::Fr = self.randomness_source.gen();
|
let random: E::Fr = self.randomness_source.gen();
|
||||||
|
Loading…
Reference in New Issue
Block a user