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

Prepare Zexe for recursion #241

Merged
merged 16 commits into from
Jul 20, 2020
13 changes: 13 additions & 0 deletions algebra-core/src/curves/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,16 @@ pub fn prepare_g2<E: PairingEngine>(g: impl Into<E::G2Affine>) -> E::G2Prepared
let g: E::G2Affine = g.into();
E::G2Prepared::from(g)
}

/// A cycle of pairing-friendly elliptic curves.
pub trait CycleEngine: Sized + 'static + Copy + Debug + Sync + Send
where
<Self::E2 as PairingEngine>::G1Projective: MulAssign<<Self::E1 as PairingEngine>::Fq>,
<Self::E2 as PairingEngine>::G2Projective: MulAssign<<Self::E1 as PairingEngine>::Fq>,
{
type E1: PairingEngine;
type E2: PairingEngine<
Fr = <Self::E1 as PairingEngine>::Fq,
Fq = <Self::E1 as PairingEngine>::Fr,
>;
}
23 changes: 23 additions & 0 deletions algebra-core/src/to_field_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,26 @@ impl<ConstraintF: PrimeField> ToConstraintField<ConstraintF> for [u8; 32] {
self.as_ref().to_field_elements()
}
}

impl<ConstraintF: PrimeField> ToConstraintField<ConstraintF> for Vec<u8> {
#[inline]
fn to_field_elements(&self) -> Result<Vec<ConstraintF>, Error> {
let max_size = <ConstraintF as PrimeField>::Params::CAPACITY / 8;
let max_size = max_size as usize;
let bigint_size = <ConstraintF as PrimeField>::BigInt::NUM_LIMBS * 8;
let fes = self
.chunks(max_size)
.map(|chunk| {
let mut chunk = chunk.to_vec();
let len = chunk.len();
for _ in len..bigint_size {
chunk.push(0u8);
}
ConstraintF::read(chunk.as_slice())
})
.collect::<Result<Vec<_>, _>>()
.map_err(crate::SerializationError::from)
.map_err(|e| Box::new(e))?;
Ok(fes)
}
}
14 changes: 13 additions & 1 deletion crypto-primitives/src/nizk/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use r1cs_std::prelude::*;
use crate::nizk::NIZK;

pub trait NIZKVerifierGadget<N: NIZK, ConstraintF: Field> {
type PreparedVerificationKeyGadget;
type VerificationKeyGadget: AllocGadget<N::VerificationParameters, ConstraintF>
+ ToBytesGadget<ConstraintF>;

type ProofGadget: AllocGadget<N::Proof, ConstraintF>;

fn check_verify<'a, CS, I, T>(
Expand All @@ -32,4 +32,16 @@ pub trait NIZKVerifierGadget<N: NIZK, ConstraintF: Field> {
CS: ConstraintSystem<ConstraintF>,
I: Iterator<Item = &'a T>,
T: 'a + ToBitsGadget<ConstraintF> + ?Sized;

fn conditional_check_verify_prepared<'a, CS, I, T>(
cs: CS,
prepared_verification_key: &Self::PreparedVerificationKeyGadget,
input: I,
proof: &Self::ProofGadget,
condition: &Boolean,
) -> Result<(), SynthesisError>
where
CS: ConstraintSystem<ConstraintF>,
I: Iterator<Item = &'a T>,
T: 'a + ToBitsGadget<ConstraintF> + ?Sized;
}
164 changes: 161 additions & 3 deletions crypto-primitives/src/nizk/gm17/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
use r1cs_std::prelude::*;

use core::{borrow::Borrow, marker::PhantomData};
use gm17::{Proof, VerifyingKey};
use gm17::{PreparedVerifyingKey, Proof, VerifyingKey};

#[derive(Derivative)]
#[derivative(Clone(bound = "P::G1Gadget: Clone, P::G2Gadget: Clone"))]
Expand Down Expand Up @@ -105,6 +105,7 @@ where
V: ToConstraintField<PairingE::Fr>,
P: PairingGadget<PairingE, ConstraintF>,
{
type PreparedVerificationKeyGadget = PreparedVerifyingKeyGadget<PairingE, ConstraintF, P>;
type VerificationKeyGadget = VerifyingKeyGadget<PairingE, ConstraintF, P>;
type ProofGadget = ProofGadget<PairingE, ConstraintF, P>;

Expand All @@ -131,7 +132,7 @@ where
fn conditional_check_verify<'a, CS, I, T>(
mut cs: CS,
vk: &Self::VerificationKeyGadget,
mut public_inputs: I,
public_inputs: I,
proof: &Self::ProofGadget,
condition: &Boolean,
) -> Result<(), SynthesisError>
Expand All @@ -141,9 +142,24 @@ where
T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
{
let pvk = vk.prepare(&mut cs.ns(|| "Prepare vk"))?;
<Self as NIZKVerifierGadget<Gm17<PairingE, C, V>, ConstraintF>>::conditional_check_verify_prepared(cs, &pvk, public_inputs, proof, condition)
}

fn conditional_check_verify_prepared<'a, CS, I, T>(
mut cs: CS,
pvk: &Self::PreparedVerificationKeyGadget,
mut public_inputs: I,
proof: &Self::ProofGadget,
condition: &Boolean,
) -> Result<(), SynthesisError>
where
CS: ConstraintSystem<ConstraintF>,
I: Iterator<Item = &'a T>,
T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
{
let pvk = pvk.clone();
// e(A*G^{alpha}, B*H^{beta}) = e(G^{alpha}, H^{beta}) * e(G^{psi}, H^{gamma}) *
// e(C, H) where psi = \sum_{i=0}^l input_i pvk.query[i]

let g_psi = {
let mut cs = cs.ns(|| "Process input");
let mut g_psi = pvk.query[0].clone();
Expand Down Expand Up @@ -216,6 +232,148 @@ where
}
}

impl<PairingE, ConstraintF, P> AllocGadget<PreparedVerifyingKey<PairingE>, ConstraintF>
for PreparedVerifyingKeyGadget<PairingE, ConstraintF, P>
where
PairingE: PairingEngine,
ConstraintF: Field,
P: PairingGadget<PairingE, ConstraintF>,
P::G1PreparedGadget: AllocGadget<PairingE::G1Prepared, ConstraintF>,
P::G2PreparedGadget: AllocGadget<PairingE::G2Prepared, ConstraintF>,
{
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<PreparedVerifyingKey<PairingE>>,
{
let pvk = val.borrow().clone();

let g_alpha =
P::G1Gadget::alloc_constant(cs.ns(|| "g_alpha"), pvk.g_alpha.into_projective())?;
let h_beta = P::G2Gadget::alloc_constant(cs.ns(|| "h_beta"), pvk.h_beta.into_projective())?;
let g_alpha_pc =
P::G1PreparedGadget::alloc_constant(cs.ns(|| "g_alpha_pc"), pvk.g_alpha.into())?;
let h_beta_pc =
P::G2PreparedGadget::alloc_constant(cs.ns(|| "h_beta_pc"), pvk.h_beta.into())?;
let g_gamma_pc =
P::G1PreparedGadget::alloc_constant(cs.ns(|| "g_gamma_pc"), pvk.g_gamma_pc)?;
let h_gamma_pc =
P::G2PreparedGadget::alloc_constant(cs.ns(|| "h_gamma_pc"), pvk.h_gamma_pc)?;
let h_pc = P::G2PreparedGadget::alloc_constant(cs.ns(|| "h_pc"), pvk.h_pc)?;

let mut query = Vec::<P::G1Gadget>::new();
for (i, item) in pvk.query.iter().enumerate() {
query.push(P::G1Gadget::alloc_constant(
&mut cs.ns(|| format!("query_{}", i)),
item.borrow().into_projective(),
)?);
}

Ok(Self {
g_alpha,
h_beta,
g_alpha_pc,
h_beta_pc,
g_gamma_pc,
h_gamma_pc,
h_pc,
query,
})
}

#[inline]
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
value_gen: FN,
) -> Result<Self, SynthesisError>
where
FN: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<PreparedVerifyingKey<PairingE>>,
{
let pvk = value_gen()?.borrow().clone();

let g_alpha =
P::G1Gadget::alloc(cs.ns(|| "g_alpha"), || Ok(pvk.g_alpha.into_projective()))?;
let h_beta = P::G2Gadget::alloc(cs.ns(|| "h_beta"), || Ok(pvk.h_beta.into_projective()))?;
let g_alpha_pc =
P::G1PreparedGadget::alloc(cs.ns(|| "g_alpha_pc"), || Ok(pvk.g_alpha.into()))?;
let h_beta_pc =
P::G2PreparedGadget::alloc(cs.ns(|| "h_beta_pc"), || Ok(pvk.h_beta.into()))?;
let g_gamma_pc =
P::G1PreparedGadget::alloc(cs.ns(|| "g_gamma_pc"), || Ok(&pvk.g_gamma_pc))?;
let h_gamma_pc =
P::G2PreparedGadget::alloc(cs.ns(|| "h_gamma_pc"), || Ok(&pvk.h_gamma_pc))?;
let h_pc = P::G2PreparedGadget::alloc(cs.ns(|| "h_pc"), || Ok(&pvk.h_pc))?;

let mut query = Vec::<P::G1Gadget>::new();
for (i, item) in pvk.query.iter().enumerate() {
query.push(P::G1Gadget::alloc(
cs.ns(|| format!("query_{}", i)),
|| Ok(item.borrow().into_projective()),
)?);
}

Ok(Self {
g_alpha,
h_beta,
g_alpha_pc,
h_beta_pc,
g_gamma_pc,
h_gamma_pc,
h_pc,
query,
})
}

#[inline]
fn alloc_input<FN, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
value_gen: FN,
) -> Result<Self, SynthesisError>
where
FN: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<PreparedVerifyingKey<PairingE>>,
{
let pvk = value_gen()?.borrow().clone();

let g_alpha =
P::G1Gadget::alloc_input(cs.ns(|| "g_alpha"), || Ok(pvk.g_alpha.into_projective()))?;
let h_beta =
P::G2Gadget::alloc_input(cs.ns(|| "h_beta"), || Ok(pvk.h_beta.into_projective()))?;
let g_alpha_pc =
P::G1PreparedGadget::alloc_input(cs.ns(|| "g_alpha_pc"), || Ok(pvk.g_alpha.into()))?;
let h_beta_pc =
P::G2PreparedGadget::alloc_input(cs.ns(|| "h_beta_pc"), || Ok(pvk.h_beta.into()))?;
let g_gamma_pc =
P::G1PreparedGadget::alloc_input(cs.ns(|| "g_gamma_pc"), || Ok(&pvk.g_gamma_pc))?;
let h_gamma_pc =
P::G2PreparedGadget::alloc_input(cs.ns(|| "h_gamma_pc"), || Ok(&pvk.h_gamma_pc))?;
let h_pc = P::G2PreparedGadget::alloc_input(cs.ns(|| "h_pc"), || Ok(&pvk.h_pc))?;

let mut query = Vec::<P::G1Gadget>::new();
for (i, item) in pvk.query.iter().enumerate() {
query.push(P::G1Gadget::alloc_input(
&mut cs.ns(|| format!("query_{}", i)),
|| Ok(item.borrow().into_projective()),
)?);
}

Ok(Self {
g_alpha,
h_beta,
g_alpha_pc,
h_beta_pc,
g_gamma_pc,
h_gamma_pc,
h_pc,
query,
})
}
}

impl<PairingE, ConstraintF, P> AllocGadget<VerifyingKey<PairingE>, ConstraintF>
for VerifyingKeyGadget<PairingE, ConstraintF, P>
where
Expand Down
Loading