mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-11 00:11:29 +01:00
Prepare Zexe for recursion (#241)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
This commit is contained in:
@@ -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>(
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"))]
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
@@ -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
|
||||
|
||||
@@ -7,7 +7,7 @@ use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
|
||||
use r1cs_std::prelude::*;
|
||||
|
||||
use core::{borrow::Borrow, marker::PhantomData};
|
||||
use groth16::{Proof, VerifyingKey};
|
||||
use groth16::{PreparedVerifyingKey, Proof, VerifyingKey};
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Clone(bound = "P::G1Gadget: Clone, P::G2Gadget: Clone"))]
|
||||
@@ -106,6 +106,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>;
|
||||
|
||||
@@ -132,7 +133,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>
|
||||
@@ -142,6 +143,22 @@ where
|
||||
T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
|
||||
{
|
||||
let pvk = vk.prepare(&mut cs.ns(|| "Prepare vk"))?;
|
||||
<Self as NIZKVerifierGadget<Groth16<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();
|
||||
|
||||
let g_ic = {
|
||||
let mut cs = cs.ns(|| "Process input");
|
||||
@@ -187,6 +204,123 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<PairingE, ConstraintF, P> AllocGadget<PreparedVerifyingKey<PairingE>, ConstraintF>
|
||||
for PreparedVerifyingKeyGadget<PairingE, ConstraintF, P>
|
||||
where
|
||||
PairingE: PairingEngine,
|
||||
ConstraintF: Field,
|
||||
P: PairingGadget<PairingE, ConstraintF>,
|
||||
P::G2PreparedGadget: AllocGadget<PairingE::G2Prepared, ConstraintF>,
|
||||
{
|
||||
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 alpha_g1_beta_g2 =
|
||||
P::GTGadget::alloc_constant(cs.ns(|| "alpha_g1_beta_g2"), pvk.alpha_g1_beta_g2)?;
|
||||
|
||||
let gamma_g2_neg_pc =
|
||||
P::G2PreparedGadget::alloc_constant(cs.ns(|| "gamma_g2_neg_pc"), pvk.gamma_g2_neg_pc)?;
|
||||
|
||||
let delta_g2_neg_pc =
|
||||
P::G2PreparedGadget::alloc_constant(cs.ns(|| "delta_g2_neg_pc"), pvk.delta_g2_neg_pc)?;
|
||||
|
||||
let mut gamma_abc_g1 = Vec::<P::G1Gadget>::new();
|
||||
for (i, item) in pvk.gamma_abc_g1.iter().enumerate() {
|
||||
gamma_abc_g1.push(P::G1Gadget::alloc_constant(
|
||||
cs.ns(|| format!("query_{}", i)),
|
||||
item.borrow().into_projective(),
|
||||
)?);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
alpha_g1_beta_g2,
|
||||
gamma_g2_neg_pc,
|
||||
delta_g2_neg_pc,
|
||||
gamma_abc_g1,
|
||||
})
|
||||
}
|
||||
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
f: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<PreparedVerifyingKey<PairingE>>,
|
||||
{
|
||||
let pvk = f()?.borrow().clone();
|
||||
|
||||
let alpha_g1_beta_g2 =
|
||||
P::GTGadget::alloc(cs.ns(|| "alpha_g1_beta_g2"), || Ok(pvk.alpha_g1_beta_g2))?;
|
||||
|
||||
let gamma_g2_neg_pc =
|
||||
P::G2PreparedGadget::alloc(cs.ns(|| "gamma_g2_neg_pc"), || Ok(&pvk.gamma_g2_neg_pc))?;
|
||||
|
||||
let delta_g2_neg_pc =
|
||||
P::G2PreparedGadget::alloc(cs.ns(|| "delta_g2_neg_pc"), || Ok(&pvk.delta_g2_neg_pc))?;
|
||||
|
||||
let mut gamma_abc_g1 = Vec::<P::G1Gadget>::new();
|
||||
for (i, item) in pvk.gamma_abc_g1.iter().enumerate() {
|
||||
gamma_abc_g1.push(P::G1Gadget::alloc(
|
||||
cs.ns(|| format!("query_{}", i)),
|
||||
|| Ok(item.borrow().into_projective()),
|
||||
)?);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
alpha_g1_beta_g2,
|
||||
gamma_g2_neg_pc,
|
||||
delta_g2_neg_pc,
|
||||
gamma_abc_g1,
|
||||
})
|
||||
}
|
||||
|
||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
f: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<PreparedVerifyingKey<PairingE>>,
|
||||
{
|
||||
let pvk = f()?.borrow().clone();
|
||||
|
||||
let alpha_g1_beta_g2 =
|
||||
P::GTGadget::alloc_input(cs.ns(|| "alpha_g1_beta_g2"), || Ok(pvk.alpha_g1_beta_g2))?;
|
||||
|
||||
let gamma_g2_neg_pc =
|
||||
P::G2PreparedGadget::alloc_input(cs.ns(|| "gamma_g2_neg_pc"), || {
|
||||
Ok(&pvk.gamma_g2_neg_pc)
|
||||
})?;
|
||||
|
||||
let delta_g2_neg_pc =
|
||||
P::G2PreparedGadget::alloc_input(cs.ns(|| "delta_g2_neg_pc"), || {
|
||||
Ok(&pvk.delta_g2_neg_pc)
|
||||
})?;
|
||||
|
||||
let mut gamma_abc_g1 = Vec::<P::G1Gadget>::new();
|
||||
for (i, item) in pvk.gamma_abc_g1.iter().enumerate() {
|
||||
gamma_abc_g1.push(P::G1Gadget::alloc_input(
|
||||
cs.ns(|| format!("query_{}", i)),
|
||||
|| Ok(item.borrow().into_projective()),
|
||||
)?);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
alpha_g1_beta_g2,
|
||||
gamma_g2_neg_pc,
|
||||
delta_g2_neg_pc,
|
||||
gamma_abc_g1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<PairingE, ConstraintF, P> AllocGadget<VerifyingKey<PairingE>, ConstraintF>
|
||||
for VerifyingKeyGadget<PairingE, ConstraintF, P>
|
||||
where
|
||||
|
||||
Reference in New Issue
Block a user