Switch to tracing-based constraint debugging

This commit is contained in:
Pratyush Mishra
2020-09-09 13:26:26 -07:00
parent e22ab36f7e
commit 5e00793999
37 changed files with 622 additions and 283 deletions

View File

@@ -38,6 +38,7 @@ r1cs-std = { path = "../r1cs-std", optional = true, default-features = false }
rand = { version = "0.7", default-features = false }
rayon = { version = "1.0", optional = true }
derivative = { version = "2.0", features = ["use_core"] }
tracing = { version = "0.1", default-features = false, features = [ "attributes" ] }
[features]
default = ["std", "r1cs"]

View File

@@ -24,6 +24,7 @@ impl<F: PrimeField> CommitmentGadget<blake2s::Commitment, F> for CommGadget {
type ParametersVar = ParametersVar;
type RandomnessVar = RandomnessVar<F>;
#[tracing::instrument(target = "r1cs", skip(input, r))]
fn commit(
_: &Self::ParametersVar,
input: &[UInt8<F>],
@@ -43,6 +44,7 @@ impl<F: PrimeField> CommitmentGadget<blake2s::Commitment, F> for CommGadget {
}
impl<ConstraintF: Field> AllocVar<(), ConstraintF> for ParametersVar {
#[tracing::instrument(target = "r1cs", skip(_cs, _f))]
fn new_variable<T: Borrow<()>>(
_cs: impl Into<Namespace<ConstraintF>>,
_f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -53,6 +55,7 @@ impl<ConstraintF: Field> AllocVar<(), ConstraintF> for ParametersVar {
}
impl<ConstraintF: PrimeField> AllocVar<[u8; 32], ConstraintF> for RandomnessVar<ConstraintF> {
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_variable<T: Borrow<[u8; 32]>>(
cs: impl Into<Namespace<ConstraintF>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -111,7 +114,7 @@ mod test {
let parameters_var =
<TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::ParametersVar::new_witness(
cs.ns("gadget_parameters"),
r1cs_core::ns!(cs, "gadget_parameters"),
|| Ok(&parameters),
)
.unwrap();

View File

@@ -53,6 +53,7 @@ where
type ParametersVar = ParametersVar<C, GG>;
type RandomnessVar = RandomnessVar<ConstraintF<C>>;
#[tracing::instrument(target = "r1cs", skip(parameters, r))]
fn commit(
parameters: &Self::ParametersVar,
input: &[UInt8<ConstraintF<C>>],
@@ -183,13 +184,13 @@ mod test {
let randomness_var =
<TestCOMMGadget as CommitmentGadget<TestCOMM, Fq>>::RandomnessVar::new_witness(
cs.ns("gadget_randomness"),
r1cs_core::ns!(cs, "gadget_randomness"),
|| Ok(&randomness),
)
.unwrap();
let parameters_var =
<TestCOMMGadget as CommitmentGadget<TestCOMM, Fq>>::ParametersVar::new_witness(
cs.ns("gadget_parameters"),
r1cs_core::ns!(cs, "gadget_parameters"),
|| Ok(&parameters),
)
.unwrap();

View File

@@ -51,6 +51,7 @@ where
type OutputVar = AffineVar<P, F>;
type ParametersVar = ParametersVar<P, W>;
#[tracing::instrument(target = "r1cs", skip(parameters, input))]
fn evaluate(
parameters: &Self::ParametersVar,
input: &[UInt8<ConstraintF<P>>],
@@ -91,6 +92,7 @@ where
P: TEModelParameters,
W: Window,
{
#[tracing::instrument(target = "r1cs", skip(_cs, f))]
fn new_variable<T: Borrow<Parameters<P>>>(
_cs: impl Into<Namespace<ConstraintF<P>>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -158,7 +160,7 @@ mod test {
let parameters_var =
<TestCRHGadget as FixedLengthCRHGadget<TestCRH, Fr>>::ParametersVar::new_witness(
cs.ns("parameters_var"),
r1cs_core::ns!(cs, "parameters_var"),
|| Ok(&parameters),
)
.unwrap();

View File

@@ -87,6 +87,7 @@ where
type OutputVar = IG::OutputVar;
type ParametersVar = ped_constraints::CRHParametersVar<C, GG>;
#[tracing::instrument(target = "r1cs", skip(parameters, input))]
fn evaluate(
parameters: &Self::ParametersVar,
input: &[UInt8<ConstraintF<C>>],

View File

@@ -45,6 +45,7 @@ where
type OutputVar = GG;
type ParametersVar = CRHParametersVar<C, GG>;
#[tracing::instrument(target = "r1cs", skip(parameters, input))]
fn evaluate(
parameters: &Self::ParametersVar,
input: &[UInt8<ConstraintF<C>>],
@@ -78,6 +79,7 @@ where
GG: CurveVar<C, ConstraintF<C>>,
for<'a> &'a GG: GroupOpsBounds<'a, C, GG>,
{
#[tracing::instrument(target = "r1cs", skip(_cs, f))]
fn new_variable<T: Borrow<Parameters<C>>>(
_cs: impl Into<Namespace<ConstraintF<C>>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -138,7 +140,8 @@ mod test {
let primitive_result = TestCRH::evaluate(&parameters, &input).unwrap();
let parameters_var =
CRHParametersVar::new_constant(cs.ns("CRH Parameters"), &parameters).unwrap();
CRHParametersVar::new_constant(r1cs_core::ns!(cs, "CRH Parameters"), &parameters)
.unwrap();
let result_var = TestCRHGadget::evaluate(&parameters_var, &input_var).unwrap();

View File

@@ -25,6 +25,7 @@ where
CRHGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
<CRHGadget::OutputVar as R1CSVar<ConstraintF>>::Value: PartialEq,
{
#[tracing::instrument(target = "r1cs", skip(self, parameters, root, leaf))]
pub fn check_membership(
&self,
parameters: &CRHGadget::ParametersVar,
@@ -39,7 +40,7 @@ where
let cs = leaf_hash.cs().or(root.cs()).unwrap();
// Check if leaf is one of the bottom-most siblings.
let leaf_is_left = Boolean::new_witness(cs.ns("leaf_is_left"), || {
let leaf_is_left = Boolean::new_witness(r1cs_core::ns!(cs, "leaf_is_left"), || {
Ok(leaf_hash.value()?.eq(&self.path[0].0.value()?))
})?;
@@ -48,24 +49,20 @@ where
// Check levels between leaf level and root.
let mut previous_hash = leaf_hash;
let mut i = 0;
for &(ref left_hash, ref right_hash) in &self.path {
// Check if the previous_hash matches the correct current hash.
let previous_is_left = Boolean::new_witness(cs.ns("previous_is_left"), || {
Ok(previous_hash.value()?.eq(&left_hash.value()?))
})?;
let previous_is_left =
Boolean::new_witness(r1cs_core::ns!(cs, "previous_is_left"), || {
Ok(previous_hash.value()?.eq(&left_hash.value()?))
})?;
let ns = cs.ns(format!(
"enforcing that inner hash is correct at i-th level{}",
i
));
let ns = r1cs_core::ns!(cs, "enforcing that inner hash is correct");
let equality_cmp = previous_is_left.select(left_hash, right_hash)?;
result = result.and(&previous_hash.is_eq(&equality_cmp)?)?;
drop(ns);
previous_hash =
hash_inner_node::<P::H, CRHGadget, ConstraintF>(parameters, left_hash, right_hash)?;
i += 1;
}
result.and(&root.is_eq(&previous_hash)?)
@@ -106,8 +103,16 @@ where
f().and_then(|val| {
let mut path = Vec::new();
for &(ref l, ref r) in val.borrow().path.iter() {
let l_hash = HGadget::OutputVar::new_variable(cs.ns("l_child"), || Ok(l), mode)?;
let r_hash = HGadget::OutputVar::new_variable(cs.ns("r_child"), || Ok(r), mode)?;
let l_hash = HGadget::OutputVar::new_variable(
r1cs_core::ns!(cs, "l_child"),
|| Ok(l),
mode,
)?;
let r_hash = HGadget::OutputVar::new_variable(
r1cs_core::ns!(cs, "r_child"),
|| Ok(r),
mode,
)?;
path.push((l_hash, r_hash));
}
Ok(PathVar { path })
@@ -157,15 +162,14 @@ mod test {
let crh_parameters = H::setup(&mut rng).unwrap();
let tree = JubJubMerkleTree::new(crh_parameters.clone(), leaves).unwrap();
let root = tree.root();
let mut satisfied = true;
let cs = ConstraintSystem::<Fq>::new_ref();
for (i, leaf) in leaves.iter().enumerate() {
let cs = ConstraintSystem::<Fq>::new_ref();
let proof = tree.generate_proof(i, &leaf).unwrap();
assert!(proof.verify(&crh_parameters, &root, &leaf).unwrap());
// Allocate Merkle Tree Root
let root = <HG as FixedLengthCRHGadget<H, _>>::OutputVar::new_witness(
cs.ns("new_digest"),
r1cs_core::ns!(cs, "new_digest"),
|| {
if use_bad_root {
Ok(<H as FixedLengthCRH>::Output::default())
@@ -181,7 +185,7 @@ mod test {
// Allocate Parameters for CRH
let crh_parameters = <HG as FixedLengthCRHGadget<H, Fq>>::ParametersVar::new_constant(
cs.ns("new_parameter"),
r1cs_core::ns!(cs, "new_parameter"),
&crh_parameters,
)
.unwrap();
@@ -200,7 +204,9 @@ mod test {
println!("constraints from leaf: {}", constraints_from_leaf);
// Allocate Merkle Tree Path
let cw = PathVar::<_, HG, _>::new_witness(cs.ns("new_witness"), || Ok(&proof)).unwrap();
let cw =
PathVar::<_, HG, _>::new_witness(r1cs_core::ns!(cs, "new_witness"), || Ok(&proof))
.unwrap();
for (i, (l, r)) in cw.path.iter().enumerate() {
assert_eq!(l.value().unwrap(), proof.path[i].0);
assert_eq!(r.value().unwrap(), proof.path[i].1);
@@ -216,13 +222,6 @@ mod test {
.unwrap()
.enforce_equal(&Boolean::TRUE)
.unwrap();
if !cs.is_satisfied().unwrap() {
satisfied = false;
println!(
"Unsatisfied constraint: {}",
cs.which_is_unsatisfied().unwrap()
);
}
let setup_constraints = constraints_from_leaf
+ constraints_from_digest
+ constraints_from_parameters
@@ -233,7 +232,7 @@ mod test {
);
}
assert!(satisfied);
assert!(cs.is_satisfied().unwrap());
}
#[test]

View File

@@ -15,6 +15,7 @@ pub trait NIZKVerifierGadget<N: NIZK, ConstraintF: Field> {
/// subgroup checks.
///
/// The default implementation doesn't omit these checks.
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_proof_unchecked<T: Borrow<N::Proof>>(
cs: impl Into<Namespace<ConstraintF>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -27,6 +28,7 @@ pub trait NIZKVerifierGadget<N: NIZK, ConstraintF: Field> {
/// without performing subgroup checks.
///
/// The default implementation doesn't omit these checks.
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_verification_key_unchecked<T: Borrow<N::VerificationParameters>>(
cs: impl Into<Namespace<ConstraintF>>,
f: impl FnOnce() -> Result<T, SynthesisError>,

View File

@@ -32,6 +32,7 @@ pub struct VerifyingKeyVar<E: PairingEngine, P: PairingVar<E>> {
}
impl<E: PairingEngine, P: PairingVar<E>> VerifyingKeyVar<E, P> {
#[tracing::instrument(target = "r1cs", skip(self))]
pub fn prepare(&self) -> Result<PreparedVerifyingKeyVar<E, P>, SynthesisError> {
let g_alpha_pc = P::prepare_g1(&self.g_alpha_g1)?;
let h_beta_pc = P::prepare_g2(&self.h_beta_g2)?;
@@ -89,6 +90,7 @@ where
/// Allocates `N::Proof` in `cs` without performing
/// subgroup checks.
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_proof_unchecked<T: Borrow<Proof<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -99,17 +101,17 @@ where
f().and_then(|proof| {
let proof = proof.borrow();
let a = CurveVar::new_variable_omit_prime_order_check(
cs.ns("Proof.a"),
r1cs_core::ns!(cs, "Proof.a"),
|| Ok(proof.a.into_projective()),
mode,
)?;
let b = CurveVar::new_variable_omit_prime_order_check(
cs.ns("Proof.b"),
r1cs_core::ns!(cs, "Proof.b"),
|| Ok(proof.b.into_projective()),
mode,
)?;
let c = CurveVar::new_variable_omit_prime_order_check(
cs.ns("Proof.c"),
r1cs_core::ns!(cs, "Proof.c"),
|| Ok(proof.c.into_projective()),
mode,
)?;
@@ -119,6 +121,7 @@ where
/// Allocates `N::Proof` in `cs` without performing
/// subgroup checks.
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_verification_key_unchecked<T: Borrow<VerifyingKey<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -129,27 +132,27 @@ where
f().and_then(|vk| {
let vk = vk.borrow();
let g_alpha_g1 = P::G1Var::new_variable_omit_prime_order_check(
cs.ns("g_alpha"),
r1cs_core::ns!(cs, "g_alpha"),
|| Ok(vk.g_alpha_g1.into_projective()),
mode,
)?;
let h_g2 = P::G2Var::new_variable_omit_prime_order_check(
cs.ns("h"),
r1cs_core::ns!(cs, "h"),
|| Ok(vk.h_g2.into_projective()),
mode,
)?;
let h_beta_g2 = P::G2Var::new_variable_omit_prime_order_check(
cs.ns("h_beta"),
r1cs_core::ns!(cs, "h_beta"),
|| Ok(vk.h_beta_g2.into_projective()),
mode,
)?;
let g_gamma_g1 = P::G1Var::new_variable_omit_prime_order_check(
cs.ns("g_gamma"),
r1cs_core::ns!(cs, "g_gamma"),
|| Ok(vk.g_gamma_g1.into_projective()),
mode,
)?;
let h_gamma_g2 = P::G2Var::new_variable_omit_prime_order_check(
cs.ns("h_gamma"),
r1cs_core::ns!(cs, "h_gamma"),
|| Ok(vk.h_gamma_g2.into_projective()),
mode,
)?;
@@ -159,7 +162,7 @@ where
.iter()
.map(|g| {
P::G1Var::new_variable_omit_prime_order_check(
cs.ns("g"),
r1cs_core::ns!(cs, "g"),
|| Ok(g.into_projective()),
mode,
)
@@ -176,6 +179,7 @@ where
})
}
#[tracing::instrument(target = "r1cs", skip(vk, input, proof))]
fn verify<'a, T: 'a + ToBitsGadget<E::Fq> + ?Sized>(
vk: &Self::VerificationKeyVar,
input: impl IntoIterator<Item = &'a T>,
@@ -185,6 +189,7 @@ where
<Self as NIZKVerifierGadget<Gm17<E, C, V>, E::Fq>>::verify_prepared(&pvk, input, proof)
}
#[tracing::instrument(target = "r1cs", skip(pvk, input, proof))]
fn verify_prepared<'a, T: 'a + ToBitsGadget<E::Fq> + ?Sized>(
pvk: &Self::PreparedVerificationKeyVar,
input: impl IntoIterator<Item = &'a T>,
@@ -263,6 +268,7 @@ where
P::G1PreparedVar: AllocVar<E::G1Prepared, E::Fq>,
P::G2PreparedVar: AllocVar<E::G2Prepared, E::Fq>,
{
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_variable<T: Borrow<PreparedVerifyingKey<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -273,21 +279,34 @@ where
f().and_then(|pvk| {
let pvk = pvk.borrow();
let g_alpha = P::G1Var::new_variable(cs.ns("g_alpha"), || Ok(pvk.g_alpha), mode)?;
let h_beta = P::G2Var::new_variable(cs.ns("h_beta"), || Ok(pvk.h_beta), mode)?;
let g_alpha =
P::G1Var::new_variable(r1cs_core::ns!(cs, "g_alpha"), || Ok(pvk.g_alpha), mode)?;
let h_beta =
P::G2Var::new_variable(r1cs_core::ns!(cs, "h_beta"), || Ok(pvk.h_beta), mode)?;
let g_alpha_pc = P::G1PreparedVar::new_variable(
cs.ns("g_alpha_pc"),
r1cs_core::ns!(cs, "g_alpha_pc"),
|| Ok(pvk.g_alpha.into()),
mode,
)?;
let h_beta_pc =
P::G2PreparedVar::new_variable(cs.ns("h_beta_pc"), || Ok(pvk.h_beta.into()), mode)?;
let g_gamma_pc =
P::G1PreparedVar::new_variable(cs.ns("g_gamma_pc"), || Ok(&pvk.g_gamma_pc), mode)?;
let h_gamma_pc =
P::G2PreparedVar::new_variable(cs.ns("h_gamma_pc"), || Ok(&pvk.h_gamma_pc), mode)?;
let h_pc = P::G2PreparedVar::new_variable(cs.ns("h_pc"), || Ok(&pvk.h_pc), mode)?;
let query = Vec::new_variable(cs.ns("query"), || Ok(pvk.query.clone()), mode)?;
let h_beta_pc = P::G2PreparedVar::new_variable(
r1cs_core::ns!(cs, "h_beta_pc"),
|| Ok(pvk.h_beta.into()),
mode,
)?;
let g_gamma_pc = P::G1PreparedVar::new_variable(
r1cs_core::ns!(cs, "g_gamma_pc"),
|| Ok(&pvk.g_gamma_pc),
mode,
)?;
let h_gamma_pc = P::G2PreparedVar::new_variable(
r1cs_core::ns!(cs, "h_gamma_pc"),
|| Ok(&pvk.h_gamma_pc),
mode,
)?;
let h_pc =
P::G2PreparedVar::new_variable(r1cs_core::ns!(cs, "h_pc"), || Ok(&pvk.h_pc), mode)?;
let query =
Vec::new_variable(r1cs_core::ns!(cs, "query"), || Ok(pvk.query.clone()), mode)?;
Ok(Self {
g_alpha,
@@ -309,6 +328,7 @@ where
P: PairingVar<E>,
{
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_variable<T: Borrow<VerifyingKey<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -319,12 +339,17 @@ where
f().and_then(|vk| {
let vk = vk.borrow();
let g_alpha_g1 = P::G1Var::new_variable(cs.ns("g_alpha"), || Ok(vk.g_alpha_g1), mode)?;
let h_g2 = P::G2Var::new_variable(cs.ns("h"), || Ok(vk.h_g2), mode)?;
let h_beta_g2 = P::G2Var::new_variable(cs.ns("h_beta"), || Ok(vk.h_beta_g2), mode)?;
let g_gamma_g1 = P::G1Var::new_variable(cs.ns("g_gamma"), || Ok(&vk.g_gamma_g1), mode)?;
let h_gamma_g2 = P::G2Var::new_variable(cs.ns("h_gamma"), || Ok(&vk.h_gamma_g2), mode)?;
let query = Vec::new_variable(cs.ns("query"), || Ok(vk.query.clone()), mode)?;
let g_alpha_g1 =
P::G1Var::new_variable(r1cs_core::ns!(cs, "g_alpha"), || Ok(vk.g_alpha_g1), mode)?;
let h_g2 = P::G2Var::new_variable(r1cs_core::ns!(cs, "h"), || Ok(vk.h_g2), mode)?;
let h_beta_g2 =
P::G2Var::new_variable(r1cs_core::ns!(cs, "h_beta"), || Ok(vk.h_beta_g2), mode)?;
let g_gamma_g1 =
P::G1Var::new_variable(r1cs_core::ns!(cs, "g_gamma"), || Ok(&vk.g_gamma_g1), mode)?;
let h_gamma_g2 =
P::G2Var::new_variable(r1cs_core::ns!(cs, "h_gamma"), || Ok(&vk.h_gamma_g2), mode)?;
let query =
Vec::new_variable(r1cs_core::ns!(cs, "query"), || Ok(vk.query.clone()), mode)?;
Ok(Self {
h_g2,
g_alpha_g1,
@@ -344,6 +369,7 @@ where
P: PairingVar<E>,
{
#[inline]
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_variable<T: Borrow<Proof<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -354,9 +380,9 @@ where
f().and_then(|proof| {
let Proof { a, b, c } = proof.borrow().clone();
let a = P::G1Var::new_variable(cs.ns("a"), || Ok(a), mode)?;
let b = P::G2Var::new_variable(cs.ns("b"), || Ok(b), mode)?;
let c = P::G1Var::new_variable(cs.ns("c"), || Ok(c), mode)?;
let a = P::G1Var::new_variable(cs.clone(), || Ok(a), mode)?;
let b = P::G2Var::new_variable(cs.clone(), || Ok(b), mode)?;
let c = P::G1Var::new_variable(r1cs_core::ns!(cs, "c"), || Ok(c), mode)?;
Ok(Self { a, b, c })
})
}
@@ -428,8 +454,7 @@ mod test {
let result_var = cs.new_witness_variable(|| {
result_val.ok_or(SynthesisError::AssignmentMissing)
})?;
cs.enforce_named_constraint(
format!("Enforce constraint {}", i),
cs.enforce_constraint(
lc!() + input_1_var,
lc!() + input_2_var,
lc!() + result_var,
@@ -480,10 +505,10 @@ mod test {
let mut input_gadgets = Vec::new();
{
for (i, input) in inputs.into_iter().enumerate() {
for input in inputs.into_iter() {
let input_bits: Vec<_> = BitIteratorLE::new(input.into_repr()).collect();
let input_bits =
Vec::<Boolean<Fq>>::new_input(cs.ns(format!("Input {}", i)), || {
Vec::<Boolean<Fq>>::new_input(r1cs_core::ns!(cs, "Input"), || {
Ok(input_bits)
})
.unwrap();
@@ -491,9 +516,11 @@ mod test {
}
}
let vk_gadget = TestVkVar::new_input(cs.ns("Vk"), || Ok(&params.vk)).unwrap();
let vk_gadget =
TestVkVar::new_input(r1cs_core::ns!(cs, "Vk"), || Ok(&params.vk)).unwrap();
let proof_gadget =
TestProofVar::new_witness(cs.ns("Proof"), || Ok(proof.clone())).unwrap();
TestProofVar::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone()))
.unwrap();
println!("Time to verify!\n\n\n\n");
<TestVerifierGadget as NIZKVerifierGadget<TestProofSystem, Fq>>::verify(
&vk_gadget,
@@ -573,8 +600,7 @@ mod test_recursive {
let result_var = cs.new_witness_variable(|| {
result_val.ok_or(SynthesisError::AssignmentMissing)
})?;
cs.enforce_named_constraint(
format!("Enforce constraint {}", i),
cs.enforce_constraint(
lc!() + input_1_var,
lc!() + input_2_var,
lc!() + result_var,
@@ -624,7 +650,8 @@ mod test_recursive {
.collect::<Vec<_>>();
// Allocate this byte array as input packed into field elements.
let input_bytes = UInt8::new_input_vec(cs.ns("Input"), &input_bytes[..])?;
let input_bytes =
UInt8::new_input_vec(r1cs_core::ns!(cs, "Input"), &input_bytes[..])?;
// 40 byte
let element_size = <MNT4FqParameters as FftParameters>::BigInt::NUM_LIMBS * 8;
input_gadgets = input_bytes
@@ -638,9 +665,10 @@ mod test_recursive {
.collect::<Vec<_>>();
}
let vk_gadget = TestVkVar1::new_witness(cs.ns("Vk"), || Ok(&params.vk))?;
let vk_gadget = TestVkVar1::new_witness(r1cs_core::ns!(cs, "Vk"), || Ok(&params.vk))?;
let proof_gadget =
TestProofVar1::new_witness(cs.ns("Proof"), || Ok(proof.clone())).unwrap();
TestProofVar1::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone()))
.unwrap();
<TestVerifierGadget1 as NIZKVerifierGadget<TestProofSystem1, MNT6Fq>>::verify(
&vk_gadget,
&input_gadgets,
@@ -714,9 +742,9 @@ mod test_recursive {
{
let bigint_size = <MNT4FqParameters as FftParameters>::BigInt::NUM_LIMBS * 64;
let mut input_bits = Vec::new();
for (i, input) in inputs.into_iter().enumerate() {
for input in inputs.into_iter() {
let input_gadget =
FpVar::new_input(cs.ns(format!("Input {}", i)), || Ok(input)).unwrap();
FpVar::new_input(r1cs_core::ns!(cs, "Input"), || Ok(input)).unwrap();
let mut fp_bits = input_gadget.to_bits_le().unwrap();
// Use 320 bits per element.
@@ -741,9 +769,11 @@ mod test_recursive {
// assert!(!verify_proof(&pvk, &proof, &[a]).unwrap());
}
let vk_gadget = TestVkVar2::new_input(cs.ns("Vk"), || Ok(&params.vk)).unwrap();
let vk_gadget =
TestVkVar2::new_input(r1cs_core::ns!(cs, "Vk"), || Ok(&params.vk)).unwrap();
let proof_gadget =
TestProofVar2::new_witness(cs.ns("Proof"), || Ok(proof.clone())).unwrap();
TestProofVar2::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone()))
.unwrap();
println!("Time to verify!\n\n\n\n");
<TestVerifierGadget2 as NIZKVerifierGadget<TestProofSystem2, MNT4Fq>>::verify(
&vk_gadget,

View File

@@ -83,6 +83,7 @@ where
/// Allocates `N::Proof` in `cs` without performing
/// subgroup checks.
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_proof_unchecked<T: Borrow<Proof<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -93,17 +94,17 @@ where
f().and_then(|proof| {
let proof = proof.borrow();
let a = CurveVar::new_variable_omit_prime_order_check(
cs.ns("Proof.a"),
r1cs_core::ns!(cs, "Proof.a"),
|| Ok(proof.a.into_projective()),
mode,
)?;
let b = CurveVar::new_variable_omit_prime_order_check(
cs.ns("Proof.b"),
r1cs_core::ns!(cs, "Proof.b"),
|| Ok(proof.b.into_projective()),
mode,
)?;
let c = CurveVar::new_variable_omit_prime_order_check(
cs.ns("Proof.c"),
r1cs_core::ns!(cs, "Proof.c"),
|| Ok(proof.c.into_projective()),
mode,
)?;
@@ -113,6 +114,7 @@ where
/// Allocates `N::Proof` in `cs` without performing
/// subgroup checks.
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_verification_key_unchecked<T: Borrow<VerifyingKey<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -123,22 +125,22 @@ where
f().and_then(|vk| {
let vk = vk.borrow();
let alpha_g1 = P::G1Var::new_variable_omit_prime_order_check(
cs.ns("alpha_g1"),
r1cs_core::ns!(cs, "alpha_g1"),
|| Ok(vk.alpha_g1.into_projective()),
mode,
)?;
let beta_g2 = P::G2Var::new_variable_omit_prime_order_check(
cs.ns("beta_g2"),
r1cs_core::ns!(cs, "beta_g2"),
|| Ok(vk.beta_g2.into_projective()),
mode,
)?;
let gamma_g2 = P::G2Var::new_variable_omit_prime_order_check(
cs.ns("gamma_g2"),
r1cs_core::ns!(cs, "gamma_g2"),
|| Ok(vk.gamma_g2.into_projective()),
mode,
)?;
let delta_g2 = P::G2Var::new_variable_omit_prime_order_check(
cs.ns("delta_g2"),
r1cs_core::ns!(cs, "delta_g2"),
|| Ok(vk.delta_g2.into_projective()),
mode,
)?;
@@ -148,7 +150,7 @@ where
.iter()
.map(|g| {
P::G1Var::new_variable_omit_prime_order_check(
cs.ns("g"),
r1cs_core::ns!(cs, "g"),
|| Ok(g.into_projective()),
mode,
)
@@ -164,6 +166,7 @@ where
})
}
#[tracing::instrument(target = "r1cs", skip(vk, input, proof))]
fn verify<'a, T: 'a + ToBitsGadget<E::Fq> + ?Sized>(
vk: &Self::VerificationKeyVar,
input: impl IntoIterator<Item = &'a T>,
@@ -173,6 +176,7 @@ where
<Self as NIZKVerifierGadget<Groth16<E, C, V>, E::Fq>>::verify_prepared(&pvk, input, proof)
}
#[tracing::instrument(target = "r1cs", skip(pvk, public_inputs, proof))]
fn verify_prepared<'a, T: 'a + ToBitsGadget<E::Fq> + ?Sized>(
pvk: &Self::PreparedVerificationKeyVar,
public_inputs: impl IntoIterator<Item = &'a T>,
@@ -222,6 +226,7 @@ where
E: PairingEngine,
P: PairingVar<E>,
{
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_variable<T: Borrow<PreparedVerifyingKey<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -233,25 +238,28 @@ where
f().and_then(|pvk| {
let pvk = pvk.borrow();
let alpha_g1_beta_g2 = P::GTVar::new_variable(
cs.ns("alpha_g1_beta_g2"),
r1cs_core::ns!(cs, "alpha_g1_beta_g2"),
|| Ok(pvk.alpha_g1_beta_g2),
mode,
)?;
let gamma_g2_neg_pc = P::G2PreparedVar::new_variable(
cs.ns("gamma_g2_neg_pc"),
r1cs_core::ns!(cs, "gamma_g2_neg_pc"),
|| Ok(pvk.gamma_g2_neg_pc.clone()),
mode,
)?;
let delta_g2_neg_pc = P::G2PreparedVar::new_variable(
cs.ns("delta_g2_neg_pc"),
r1cs_core::ns!(cs, "delta_g2_neg_pc"),
|| Ok(pvk.delta_g2_neg_pc.clone()),
mode,
)?;
let gamma_abc_g1 =
Vec::new_variable(cs.ns("gamma_abc_g1"), || Ok(pvk.gamma_abc_g1.clone()), mode)?;
let gamma_abc_g1 = Vec::new_variable(
r1cs_core::ns!(cs, "gamma_abc_g1"),
|| Ok(pvk.gamma_abc_g1.clone()),
mode,
)?;
Ok(Self {
alpha_g1_beta_g2,
@@ -269,6 +277,7 @@ where
P: PairingVar<E>,
{
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_variable<T: Borrow<VerifyingKey<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -285,10 +294,14 @@ where
delta_g2,
gamma_abc_g1,
} = vk.borrow().clone();
let alpha_g1 = P::G1Var::new_variable(cs.ns("alpha_g1"), || Ok(alpha_g1), mode)?;
let beta_g2 = P::G2Var::new_variable(cs.ns("beta_g2"), || Ok(beta_g2), mode)?;
let gamma_g2 = P::G2Var::new_variable(cs.ns("gamma_g2"), || Ok(gamma_g2), mode)?;
let delta_g2 = P::G2Var::new_variable(cs.ns("delta_g2"), || Ok(delta_g2), mode)?;
let alpha_g1 =
P::G1Var::new_variable(r1cs_core::ns!(cs, "alpha_g1"), || Ok(alpha_g1), mode)?;
let beta_g2 =
P::G2Var::new_variable(r1cs_core::ns!(cs, "beta_g2"), || Ok(beta_g2), mode)?;
let gamma_g2 =
P::G2Var::new_variable(r1cs_core::ns!(cs, "gamma_g2"), || Ok(gamma_g2), mode)?;
let delta_g2 =
P::G2Var::new_variable(r1cs_core::ns!(cs, "delta_g2"), || Ok(delta_g2), mode)?;
let gamma_abc_g1 = Vec::new_variable(cs.clone(), || Ok(gamma_abc_g1), mode)?;
Ok(Self {
@@ -307,6 +320,7 @@ where
E: PairingEngine,
P: PairingVar<E>,
{
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_variable<T: Borrow<Proof<E>>>(
cs: impl Into<Namespace<E::Fq>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -317,9 +331,9 @@ where
f().and_then(|proof| {
let Proof { a, b, c } = proof.borrow().clone();
let a = P::G1Var::new_variable(cs.ns("a"), || Ok(a), mode)?;
let b = P::G2Var::new_variable(cs.ns("b"), || Ok(b), mode)?;
let c = P::G1Var::new_variable(cs.ns("c"), || Ok(c), mode)?;
let a = P::G1Var::new_variable(r1cs_core::ns!(cs, "a"), || Ok(a), mode)?;
let b = P::G2Var::new_variable(r1cs_core::ns!(cs, "b"), || Ok(b), mode)?;
let c = P::G1Var::new_variable(r1cs_core::ns!(cs, "c"), || Ok(c), mode)?;
Ok(Self { a, b, c })
})
}
@@ -331,6 +345,7 @@ where
P: PairingVar<E>,
{
#[inline]
#[tracing::instrument(target = "r1cs", skip(self))]
fn to_bytes(&self) -> Result<Vec<UInt8<E::Fq>>, SynthesisError> {
let mut bytes = Vec::new();
bytes.extend_from_slice(&self.alpha_g1.to_bytes()?);
@@ -389,8 +404,7 @@ mod test {
let result_var = cs.new_witness_variable(|| {
result_val.ok_or(SynthesisError::AssignmentMissing)
})?;
cs.enforce_named_constraint(
format!("Enforce constraint {}", i),
cs.enforce_constraint(
lc!() + input_1_var,
lc!() + input_2_var,
lc!() + result_var,
@@ -441,11 +455,11 @@ mod test {
let mut input_gadgets = Vec::new();
{
for (i, input) in inputs.into_iter().enumerate() {
for input in inputs.into_iter() {
let input_bits = BitIteratorLE::new(input.into_repr()).collect::<Vec<_>>();
let input_bits =
Vec::<Boolean<Fq>>::new_input(cs.ns(format!("Input {}", i)), || {
Vec::<Boolean<Fq>>::new_input(r1cs_core::ns!(cs, "Input"), || {
Ok(input_bits)
})
.unwrap();
@@ -453,9 +467,11 @@ mod test {
}
}
let vk_gadget = TestVkVar::new_input(cs.ns("Vk"), || Ok(&params.vk)).unwrap();
let vk_gadget =
TestVkVar::new_input(r1cs_core::ns!(cs, "Vk"), || Ok(&params.vk)).unwrap();
let proof_gadget =
TestProofVar::new_witness(cs.ns("Proof"), || Ok(proof.clone())).unwrap();
TestProofVar::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone()))
.unwrap();
println!("Time to verify!\n\n\n\n");
<TestVerifierGadget as NIZKVerifierGadget<TestProofSystem, Fq>>::verify(
&vk_gadget,
@@ -534,8 +550,7 @@ mod test_recursive {
let result_var = cs.new_witness_variable(|| {
result_val.ok_or(SynthesisError::AssignmentMissing)
})?;
cs.enforce_named_constraint(
format!("Enforce constraint {}", i),
cs.enforce_constraint(
lc!() + input_1_var,
lc!() + input_2_var,
lc!() + result_var,
@@ -585,7 +600,8 @@ mod test_recursive {
.collect::<Vec<_>>();
// Allocate this byte array as input packed into field elements.
let input_bytes = UInt8::new_input_vec(cs.ns("Input"), &input_bytes[..])?;
let input_bytes =
UInt8::new_input_vec(r1cs_core::ns!(cs, "Input"), &input_bytes[..])?;
// 40 byte
let element_size = <MNT4FqParameters as FftParameters>::BigInt::NUM_LIMBS * 8;
input_gadgets = input_bytes
@@ -599,9 +615,10 @@ mod test_recursive {
.collect::<Vec<_>>();
}
let vk_gadget = TestVkVar1::new_witness(cs.ns("Vk"), || Ok(&params.vk))?;
let vk_gadget = TestVkVar1::new_witness(r1cs_core::ns!(cs, "Vk"), || Ok(&params.vk))?;
let proof_gadget =
TestProofVar1::new_witness(cs.ns("Proof"), || Ok(proof.clone())).unwrap();
TestProofVar1::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone()))
.unwrap();
<TestVerifierGadget1 as NIZKVerifierGadget<TestProofSystem1, MNT6Fq>>::verify(
&vk_gadget,
&input_gadgets,
@@ -675,9 +692,9 @@ mod test_recursive {
{
let bigint_size = <MNT4FqParameters as FftParameters>::BigInt::NUM_LIMBS * 64;
let mut input_bits = Vec::new();
for (i, input) in inputs.into_iter().enumerate() {
for input in inputs.into_iter() {
let input_gadget =
FpVar::new_input(cs.ns(format!("Input {}", i)), || Ok(input)).unwrap();
FpVar::new_input(r1cs_core::ns!(cs, "Input"), || Ok(input)).unwrap();
let mut fp_bits = input_gadget.to_bits_le().unwrap();
// Use 320 bits per element.
@@ -702,9 +719,11 @@ mod test_recursive {
// assert!(!verify_proof(&pvk, &proof, &[a]).unwrap());
}
let vk_gadget = TestVkVar2::new_input(cs.ns("Vk"), || Ok(&params.vk)).unwrap();
let vk_gadget =
TestVkVar2::new_input(r1cs_core::ns!(cs, "Vk"), || Ok(&params.vk)).unwrap();
let proof_gadget =
TestProofVar2::new_witness(cs.ns("Proof"), || Ok(proof.clone())).unwrap();
TestProofVar2::new_witness(r1cs_core::ns!(cs, "Proof"), || Ok(proof.clone()))
.unwrap();
println!("Time to verify!\n\n\n\n");
<TestVerifierGadget2 as NIZKVerifierGadget<TestProofSystem2, MNT4Fq>>::verify(
&vk_gadget,

View File

@@ -91,12 +91,7 @@ mod test {
let sum = cs.new_input_variable(|| Ok(self.sum.unwrap()))?;
let witness = cs.new_witness_variable(|| Ok(self.w.unwrap()))?;
cs.enforce_named_constraint(
"enforce sum",
lc!() + sum,
lc!() + Variable::One,
lc!() + input + witness,
)?;
cs.enforce_constraint(lc!() + sum, lc!() + Variable::One, lc!() + input + witness)?;
Ok(())
}
}

View File

@@ -294,12 +294,14 @@ pub struct Blake2sGadget;
pub struct OutputVar<ConstraintF: PrimeField>(pub Vec<UInt8<ConstraintF>>);
impl<ConstraintF: PrimeField> EqGadget<ConstraintF> for OutputVar<ConstraintF> {
#[tracing::instrument(target = "r1cs")]
fn is_eq(&self, other: &Self) -> Result<Boolean<ConstraintF>, SynthesisError> {
self.0.is_eq(&other.0)
}
/// If `should_enforce == true`, enforce that `self` and `other` are equal; else,
/// enforce a vacuously true statement.
#[tracing::instrument(target = "r1cs")]
fn conditional_enforce_equal(
&self,
other: &Self,
@@ -310,6 +312,7 @@ impl<ConstraintF: PrimeField> EqGadget<ConstraintF> for OutputVar<ConstraintF> {
/// If `should_enforce == true`, enforce that `self` and `other` are not equal; else,
/// enforce a vacuously true statement.
#[tracing::instrument(target = "r1cs")]
fn conditional_enforce_not_equal(
&self,
other: &Self,
@@ -329,6 +332,7 @@ impl<ConstraintF: PrimeField> ToBytesGadget<ConstraintF> for OutputVar<Constrain
}
impl<ConstraintF: PrimeField> AllocVar<[u8; 32], ConstraintF> for OutputVar<ConstraintF> {
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_variable<T: Borrow<[u8; 32]>>(
cs: impl Into<Namespace<ConstraintF>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -362,10 +366,14 @@ impl<F: PrimeField> R1CSVar<F> for OutputVar<F> {
impl<F: PrimeField> PRFGadget<Blake2s, F> for Blake2sGadget {
type OutputVar = OutputVar<F>;
fn new_seed(cs: ConstraintSystemRef<F>, seed: &[u8; 32]) -> Vec<UInt8<F>> {
UInt8::new_witness_vec(cs.ns("New Blake2s seed"), seed).unwrap()
#[tracing::instrument(target = "r1cs", skip(cs))]
fn new_seed(cs: impl Into<Namespace<F>>, seed: &[u8; 32]) -> Vec<UInt8<F>> {
let ns = cs.into();
let cs = ns.cs();
UInt8::new_witness_vec(r1cs_core::ns!(cs, "New Blake2s seed"), seed).unwrap()
}
#[tracing::instrument(target = "r1cs", skip(seed, input))]
fn evaluate(seed: &[UInt8<F>], input: &[UInt8<F>]) -> Result<Self::OutputVar, SynthesisError> {
assert_eq!(seed.len(), 32);
let input: Vec<_> = seed
@@ -398,7 +406,7 @@ mod test {
fn test_blake2s_constraints() {
let cs = ConstraintSystem::<Fr>::new_ref();
let input_bits: Vec<_> = (0..512)
.map(|i| Boolean::new_witness(cs.ns(format!("input bit {}", i)), || Ok(true)).unwrap())
.map(|_| Boolean::new_witness(r1cs_core::ns!(cs, "input bit"), || Ok(true)).unwrap())
.collect();
evaluate_blake2s(&input_bits).unwrap();
assert!(cs.is_satisfied().unwrap());
@@ -420,10 +428,11 @@ mod test {
rng.fill(&mut input);
let seed_var = Blake2sGadget::new_seed(cs.clone(), &seed);
let input_var = UInt8::new_witness_vec(cs.ns("declare_input"), &input).unwrap();
let input_var =
UInt8::new_witness_vec(r1cs_core::ns!(cs, "declare_input"), &input).unwrap();
let out = B2SPRF::evaluate(&seed, &input).unwrap();
let actual_out_var = <Blake2sGadget as PRFGadget<_, Fr>>::OutputVar::new_witness(
cs.ns("declare_output"),
r1cs_core::ns!(cs, "declare_output"),
|| Ok(out),
)
.unwrap();
@@ -449,8 +458,8 @@ mod test {
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let input_bits: Vec<_> = (0..512)
.map(|_| Boolean::constant(rng.gen()))
.chain((0..512).map(|i| {
Boolean::new_witness(cs.ns(format!("input bit {}", i)), || Ok(true)).unwrap()
.chain((0..512).map(|_| {
Boolean::new_witness(r1cs_core::ns!(cs, "input bit"), || Ok(true)).unwrap()
}))
.collect();
evaluate_blake2s(&input_bits).unwrap();
@@ -488,9 +497,9 @@ mod test {
let mut input_bits = vec![];
for (byte_i, input_byte) in data.into_iter().enumerate() {
for input_byte in data.into_iter() {
for bit_i in 0..8 {
let cs = cs.ns(format!("input bit {} {}", byte_i, bit_i));
let cs = r1cs_core::ns!(cs, "input bit");
input_bits.push(
Boolean::new_witness(cs, || Ok((input_byte >> bit_i) & 1u8 == 1u8))

View File

@@ -2,7 +2,7 @@ use algebra_core::Field;
use core::fmt::Debug;
use crate::{prf::PRF, Vec};
use r1cs_core::{ConstraintSystemRef, SynthesisError};
use r1cs_core::{Namespace, SynthesisError};
use r1cs_std::prelude::*;
@@ -14,7 +14,7 @@ pub trait PRFGadget<P: PRF, F: Field> {
+ Clone
+ Debug;
fn new_seed(cs: ConstraintSystemRef<F>, seed: &P::Seed) -> Vec<UInt8<F>>;
fn new_seed(cs: impl Into<Namespace<F>>, seed: &P::Seed) -> Vec<UInt8<F>>;
fn evaluate(seed: &[UInt8<F>], input: &[UInt8<F>]) -> Result<Self::OutputVar, SynthesisError>;
}

View File

@@ -56,6 +56,7 @@ where
type ParametersVar = ParametersVar<C, GC>;
type PublicKeyVar = PublicKeyVar<C, GC>;
#[tracing::instrument(target = "r1cs", skip(parameters, public_key, randomness))]
fn randomize(
parameters: &Self::ParametersVar,
public_key: &Self::PublicKeyVar,