Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented proof rerandomization #16

Merged
merged 7 commits into from
Dec 16, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions src/prover.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{r1cs_to_qap::R1CStoQAP, Proof, ProvingKey};
use crate::{r1cs_to_qap::R1CStoQAP, Proof, ProvingKey, VerifyingKey};
use ark_ec::{msm::VariableBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{PrimeField, UniformRand, Zero};
use ark_ff::{Field, PrimeField, UniformRand, Zero};
use ark_poly::GeneralEvaluationDomain;
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem, Result as R1CSResult};
use ark_std::{cfg_into_iter, cfg_iter, vec::Vec};
Expand Down Expand Up @@ -144,6 +144,32 @@ where
})
}

/// Given a Groth16 proof, returns a proof of the same statement. The proof that is returned is
/// computationally unlinkable to the given proof, assuming the RNG is cryptographically secure
pub fn rerandomize_proof<E, R>(rng: &mut R, vk: &VerifyingKey<E>, proof: &Proof<E>) -> Proof<E>
where
E: PairingEngine,
R: Rng,
{
// These are our rerandomization factors
let (r, s) = (E::Fr::rand(rng), E::Fr::rand(rng));
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved

// A' = rA
// B' = (1/r)B + s(δG₂)
// C' = C + rsA

let new_a = proof.a.mul(r);
// We can unwrap() this because r = 0 with negligible probability
let new_b = proof.b.mul(r.inverse().unwrap()) + &vk.delta_g2.mul(s);
let new_c = proof.c + proof.a.mul(r * &s).into_affine();

Proof {
a: new_a.into_affine(),
b: new_b.into_affine(),
c: new_c,
}
}

fn calculate_coeff<G: AffineCurve>(
initial: G::Projective,
query: &[G],
Expand Down
161 changes: 98 additions & 63 deletions src/test.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
use crate::{
create_random_proof, generate_random_parameters, prepare_verifying_key, rerandomize_proof,
verify_proof,
};
use ark_ec::PairingEngine;
use ark_ff::UniformRand;
use ark_std::test_rng;

use core::ops::MulAssign;

use ark_ff::{Field, Zero};
use ark_relations::{
lc,
Expand Down Expand Up @@ -35,71 +45,22 @@ impl<ConstraintF: Field> ConstraintSynthesizer<ConstraintF> for MySillyCircuit<C
}
}

mod bls12_377 {
use super::*;
use crate::{
create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof,
};
use ark_std::{test_rng, UniformRand};
fn test_prove_and_verify<E>(n_iters: usize)
where
E: PairingEngine,
{
let rng = &mut test_rng();

use ark_bls12_377::{Bls12_377, Fr};
use core::ops::MulAssign;
let params =
generate_random_parameters::<E, _, _>(MySillyCircuit { a: None, b: None }, rng).unwrap();

#[test]
fn prove_and_verify() {
let rng = &mut test_rng();

let params =
generate_random_parameters::<Bls12_377, _, _>(MySillyCircuit { a: None, b: None }, rng)
.unwrap();

let pvk = prepare_verifying_key::<Bls12_377>(&params.vk);

for _ in 0..100 {
let a = Fr::rand(rng);
let b = Fr::rand(rng);
let mut c = a;
c.mul_assign(&b);

let proof = create_random_proof(
MySillyCircuit {
a: Some(a),
b: Some(b),
},
&params,
rng,
)
.unwrap();

assert!(verify_proof(&pvk, &proof, &[c]).unwrap());
assert!(!verify_proof(&pvk, &proof, &[a]).unwrap());
}
}
}

mod cp6_782 {
use super::*;
use crate::{
create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof,
};
let pvk = prepare_verifying_key::<E>(&params.vk);

use ark_std::{test_rng, UniformRand};

use ark_cp6_782::{Fr, CP6_782};

#[test]
fn prove_and_verify() {
let rng = &mut test_rng();

let params =
generate_random_parameters::<CP6_782, _, _>(MySillyCircuit { a: None, b: None }, rng)
.unwrap();

let pvk = prepare_verifying_key::<CP6_782>(&params.vk);

let a = Fr::rand(rng);
let b = Fr::rand(rng);
let c = a * &b;
for _ in 0..n_iters {
let a = E::Fr::rand(rng);
let b = E::Fr::rand(rng);
let mut c = a;
c.mul_assign(&b);

let proof = create_random_proof(
MySillyCircuit {
Expand All @@ -112,6 +73,80 @@ mod cp6_782 {
.unwrap();

assert!(verify_proof(&pvk, &proof, &[c]).unwrap());
assert!(!verify_proof(&pvk, &proof, &[Fr::zero()]).unwrap());
assert!(!verify_proof(&pvk, &proof, &[a]).unwrap());
}
}

fn test_rerandomize<E>()
where
E: PairingEngine,
{
// First create an arbitrary Groth16 in the normal way

let rng = &mut test_rng();

let params =
generate_random_parameters::<E, _, _>(MySillyCircuit { a: None, b: None }, rng).unwrap();

let pvk = prepare_verifying_key::<E>(&params.vk);

let a = E::Fr::rand(rng);
let b = E::Fr::rand(rng);
let c = a * &b;

// Create the initial proof
let proof1 = create_random_proof(
MySillyCircuit {
a: Some(a),
b: Some(b),
},
&params,
rng,
)
.unwrap();

// Rerandomize the proof, then rerandomize that
let proof2 = rerandomize_proof(rng, &params.vk, &proof1);
let proof3 = rerandomize_proof(rng, &params.vk, &proof2);

// Check that the proofs are equivalent

assert!(verify_proof(&pvk, &proof1, &[c]).unwrap());
assert!(verify_proof(&pvk, &proof2, &[c]).unwrap());
assert!(verify_proof(&pvk, &proof3, &[c]).unwrap());

assert!(!verify_proof(&pvk, &proof1, &[E::Fr::zero()]).unwrap());
assert!(!verify_proof(&pvk, &proof2, &[E::Fr::zero()]).unwrap());
assert!(!verify_proof(&pvk, &proof3, &[E::Fr::zero()]).unwrap());
Pratyush marked this conversation as resolved.
Show resolved Hide resolved
}

mod bls12_377 {
use super::{test_prove_and_verify, test_rerandomize};
use ark_bls12_377::Bls12_377;

#[test]
fn prove_and_verify() {
test_prove_and_verify::<Bls12_377>(100);
}

#[test]
fn rerandomize() {
test_rerandomize::<Bls12_377>();
}
}

mod cp6_782 {
use super::{test_prove_and_verify, test_rerandomize};

use ark_cp6_782::CP6_782;

#[test]
fn prove_and_verify() {
test_prove_and_verify::<CP6_782>(1);
}

#[test]
fn rerandomize() {
test_rerandomize::<CP6_782>();
}
}