Skip to content

Commit

Permalink
feat: allow using custom R1CS to QAP conversions
Browse files Browse the repository at this point in the history
  • Loading branch information
gakonst committed Jul 20, 2021
1 parent 96ea457 commit 9518e51
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 15 deletions.
58 changes: 53 additions & 5 deletions src/generator.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{r1cs_to_qap::R1CStoQAP, ProvingKey, Vec, VerifyingKey};
use crate::{
r1cs_to_qap::{QAPCalculator, R1CStoQAP},
ProvingKey, Vec, VerifyingKey,
};
use ark_ec::{msm::FixedBaseMSM, PairingEngine, ProjectiveCurve};
use ark_ff::{Field, PrimeField, UniformRand, Zero};
use ark_poly::{EvaluationDomain, GeneralEvaluationDomain};
Expand All @@ -12,14 +15,30 @@ use ark_std::{cfg_into_iter, cfg_iter};
#[cfg(feature = "parallel")]
use rayon::prelude::*;

#[inline]
/// Generates a random common reference string for
/// a circuit.
#[inline]
pub fn generate_random_parameters<E, C, R>(circuit: C, rng: &mut R) -> R1CSResult<ProvingKey<E>>
where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
R: Rng,
{
generate_random_parameters_with_qap::<E, C, R, R1CStoQAP>(circuit, rng)
}

/// Generates a random common reference string for
/// a circuit using the provided R1CS to QAP calculator
#[inline]
pub fn generate_random_parameters_with_qap<E, C, R, QAP>(
circuit: C,
rng: &mut R,
) -> R1CSResult<ProvingKey<E>>
where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
R: Rng,
QAP: QAPCalculator,
{
let alpha = E::Fr::rand(rng);
let beta = E::Fr::rand(rng);
Expand All @@ -29,7 +48,7 @@ where
let g1_generator = E::G1Projective::rand(rng);
let g2_generator = E::G2Projective::rand(rng);

generate_parameters::<E, C, R>(
generate_parameters_with_qap::<E, C, R, QAP>(
circuit,
alpha,
beta,
Expand All @@ -41,7 +60,7 @@ where
)
}

/// Create parameters for a circuit, given some toxic waste and group generators
/// Create parameters for a circuit, given some toxic waste, and group generators
pub fn generate_parameters<E, C, R>(
circuit: C,
alpha: E::Fr,
Expand All @@ -56,6 +75,35 @@ where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
R: Rng,
{
generate_parameters_with_qap::<E, C, R, R1CStoQAP>(
circuit,
alpha,
beta,
gamma,
delta,
g1_generator,
g2_generator,
rng,
)
}

/// Create parameters for a circuit, given some toxic waste, R1CS to QAP calculator and group generators
pub fn generate_parameters_with_qap<E, C, R, QAP>(
circuit: C,
alpha: E::Fr,
beta: E::Fr,
gamma: E::Fr,
delta: E::Fr,
g1_generator: E::G1Projective,
g2_generator: E::G2Projective,
rng: &mut R,
) -> R1CSResult<ProvingKey<E>>
where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
R: Rng,
QAP: QAPCalculator,
{
type D<F> = GeneralEvaluationDomain<F>;

Expand Down Expand Up @@ -86,7 +134,7 @@ where
let reduction_time = start_timer!(|| "R1CS to QAP Instance Map with Evaluation");
let num_instance_variables = cs.num_instance_variables();
let (a, b, c, zt, qap_num_variables, m_raw) =
R1CStoQAP::instance_map_with_evaluation::<E::Fr, D<E::Fr>>(cs, &t)?;
QAP::instance_map_with_evaluation::<E::Fr, D<E::Fr>>(cs, &t)?;
end_timer!(reduction_time);

// Compute query densities
Expand Down
63 changes: 56 additions & 7 deletions src/prover.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{r1cs_to_qap::R1CStoQAP, Proof, ProvingKey, VerifyingKey};
use crate::{
r1cs_to_qap::{QAPCalculator, R1CStoQAP},
Proof, ProvingKey, VerifyingKey,
};
use ark_ec::{msm::VariableBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
use ark_ff::{Field, PrimeField, UniformRand, Zero};
use ark_poly::GeneralEvaluationDomain;
Expand All @@ -13,7 +16,6 @@ use rayon::prelude::*;

/// Create a Groth16 proof that is zero-knowledge.
/// This method samples randomness for zero knowledges via `rng`.
#[inline]
pub fn create_random_proof<E, C, R>(
circuit: C,
pk: &ProvingKey<E>,
Expand All @@ -23,25 +25,56 @@ where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
R: Rng,
{
create_random_proof_with_qap::<E, C, R, R1CStoQAP>(circuit, pk, rng)
}

/// Create a Groth16 proof that is zero-knowledge using the provided QAP calculator.
/// This method samples randomness for zero knowledges via `rng`.
#[inline]
pub fn create_random_proof_with_qap<E, C, R, QAP>(
circuit: C,
pk: &ProvingKey<E>,
rng: &mut R,
) -> R1CSResult<Proof<E>>
where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
R: Rng,
QAP: QAPCalculator,
{
let r = E::Fr::rand(rng);
let s = E::Fr::rand(rng);

create_proof::<E, C>(circuit, pk, r, s)
create_proof_with_qap::<E, C, QAP>(circuit, pk, r, s)
}

/// Create a Groth16 proof that is *not* zero-knowledge.
#[inline]
/// Create a Groth16 proof that is *not* zero-knowledge
pub fn create_proof_no_zk<E, C>(circuit: C, pk: &ProvingKey<E>) -> R1CSResult<Proof<E>>
where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
{
create_proof::<E, C>(circuit, pk, E::Fr::zero(), E::Fr::zero())
create_proof_with_qap::<E, C, R1CStoQAP>(circuit, pk, E::Fr::zero(), E::Fr::zero())
}

/// Create a Groth16 proof using randomness `r` and `s`.
/// Create a Groth16 proof that is *not* zero-knowledge with the provided QAP calculator
#[inline]
pub fn create_proof_with_qap_no_zk<E, C, QAP>(
circuit: C,
pk: &ProvingKey<E>,
) -> R1CSResult<Proof<E>>
where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
QAP: QAPCalculator,
{
create_proof_with_qap::<E, C, QAP>(circuit, pk, E::Fr::zero(), E::Fr::zero())
}

#[inline]
/// Create a Groth16 proof using randomness `r` and `s`.
pub fn create_proof<E, C>(
circuit: C,
pk: &ProvingKey<E>,
Expand All @@ -51,6 +84,22 @@ pub fn create_proof<E, C>(
where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
{
create_proof_with_qap::<E, C, R1CStoQAP>(circuit, pk, r, s)
}

/// Create a Groth16 proof using randomness `r` and `s` and the provided QAP calculator.
#[inline]
pub fn create_proof_with_qap<E, C, QAP>(
circuit: C,
pk: &ProvingKey<E>,
r: E::Fr,
s: E::Fr,
) -> R1CSResult<Proof<E>>
where
E: PairingEngine,
C: ConstraintSynthesizer<E::Fr>,
QAP: QAPCalculator,
{
type D<F> = GeneralEvaluationDomain<F>;

Expand All @@ -71,7 +120,7 @@ where
end_timer!(lc_time);

let witness_map_time = start_timer!(|| "R1CS to QAP witness map");
let h = R1CStoQAP::witness_map::<E::Fr, D<E::Fr>>(cs.clone())?;
let h = QAP::witness_map::<E::Fr, D<E::Fr>>(cs.clone())?;
end_timer!(witness_map_time);
let h_assignment = cfg_into_iter!(h).map(|s| s.into()).collect::<Vec<_>>();
let c_acc_time = start_timer!(|| "Compute C");
Expand Down
17 changes: 14 additions & 3 deletions src/r1cs_to_qap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,21 @@ where

pub(crate) struct R1CStoQAP;

impl R1CStoQAP {
pub trait QAPCalculator {
fn instance_map_with_evaluation<F: PrimeField, D: EvaluationDomain<F>>(
cs: ConstraintSystemRef<F>,
t: &F,
) -> Result<(Vec<F>, Vec<F>, Vec<F>, F, usize, usize), SynthesisError>;

fn witness_map<F: PrimeField, D: EvaluationDomain<F>>(
prover: ConstraintSystemRef<F>,
) -> Result<Vec<F>, SynthesisError>;
}

impl QAPCalculator for R1CStoQAP {
#[inline]
#[allow(clippy::type_complexity)]
pub(crate) fn instance_map_with_evaluation<F: PrimeField, D: EvaluationDomain<F>>(
fn instance_map_with_evaluation<F: PrimeField, D: EvaluationDomain<F>>(
cs: ConstraintSystemRef<F>,
t: &F,
) -> R1CSResult<(Vec<F>, Vec<F>, Vec<F>, F, usize, usize)> {
Expand Down Expand Up @@ -91,7 +102,7 @@ impl R1CStoQAP {
}

#[inline]
pub(crate) fn witness_map<F: PrimeField, D: EvaluationDomain<F>>(
fn witness_map<F: PrimeField, D: EvaluationDomain<F>>(
prover: ConstraintSystemRef<F>,
) -> R1CSResult<Vec<F>> {
let matrices = prover.to_matrices().unwrap();
Expand Down

0 comments on commit 9518e51

Please sign in to comment.