Browse Source

Merge branch 'master' into inline-asm

master
jon-chuang 4 years ago
committed by GitHub
parent
commit
b1f4c50fd8
33 changed files with 795 additions and 999 deletions
  1. +27
    -1
      crypto-primitives/src/commitment/blake2s/constraints.rs
  2. +31
    -5
      crypto-primitives/src/commitment/pedersen/constraints.rs
  3. +22
    -8
      crypto-primitives/src/crh/bowe_hopwood/constraints.rs
  4. +21
    -7
      crypto-primitives/src/crh/pedersen/constraints.rs
  5. +22
    -0
      crypto-primitives/src/merkle_tree/constraints.rs
  6. +12
    -0
      crypto-primitives/src/nizk/constraints.rs
  7. +90
    -3
      crypto-primitives/src/nizk/gm17/constraints.rs
  8. +1
    -1
      crypto-primitives/src/nizk/gm17/mod.rs
  9. +85
    -2
      crypto-primitives/src/nizk/groth16/constraints.rs
  10. +1
    -1
      crypto-primitives/src/nizk/groth16/mod.rs
  11. +17
    -1
      crypto-primitives/src/prf/blake2s/constraints.rs
  12. +1
    -1
      crypto-primitives/src/prf/constraints.rs
  13. +31
    -0
      crypto-primitives/src/signature/schnorr/constraints.rs
  14. +22
    -0
      r1cs-std/src/alloc.rs
  15. +36
    -0
      r1cs-std/src/bits/boolean.rs
  16. +22
    -0
      r1cs-std/src/bits/mod.rs
  17. +35
    -25
      r1cs-std/src/bits/uint64.rs
  18. +10
    -0
      r1cs-std/src/bits/uint8.rs
  19. +12
    -0
      r1cs-std/src/fields/fp/mod.rs
  20. +11
    -0
      r1cs-std/src/fields/fp12.rs
  21. +11
    -0
      r1cs-std/src/fields/fp2.rs
  22. +11
    -0
      r1cs-std/src/fields/fp3.rs
  23. +11
    -0
      r1cs-std/src/fields/fp4.rs
  24. +11
    -0
      r1cs-std/src/fields/fp6_2over3.rs
  25. +11
    -0
      r1cs-std/src/fields/fp6_3over2.rs
  26. +128
    -0
      r1cs-std/src/groups/curves/short_weierstrass/mod.rs
  27. +34
    -0
      r1cs-std/src/groups/curves/twisted_edwards/mod.rs
  28. +13
    -188
      r1cs-std/src/instantiated/bls12_377/curves.rs
  29. +13
    -188
      r1cs-std/src/instantiated/mnt4_298/curves.rs
  30. +13
    -188
      r1cs-std/src/instantiated/mnt4_753/curves.rs
  31. +13
    -188
      r1cs-std/src/instantiated/mnt6_298/curves.rs
  32. +13
    -188
      r1cs-std/src/instantiated/mnt6_753/curves.rs
  33. +4
    -4
      r1cs-std/src/test_constraint_counter.rs

+ 27
- 1
crypto-primitives/src/commitment/blake2s/constraints.rs

@ -3,7 +3,7 @@ use r1cs_core::{ConstraintSystem, SynthesisError};
use crate::{ use crate::{
commitment::blake2s::Blake2sCommitment, commitment::blake2s::Blake2sCommitment,
prf::blake2s::constraints::{blake2s_gadget, Blake2sOutputGadget}, prf::blake2s::constraints::{blake2s_gadget, Blake2sOutputGadget},
CommitmentGadget,
CommitmentGadget, Vec,
}; };
use algebra_core::{Field, PrimeField}; use algebra_core::{Field, PrimeField};
use r1cs_std::prelude::*; use r1cs_std::prelude::*;
@ -48,6 +48,16 @@ impl CommitmentGadget
} }
impl<ConstraintF: Field> AllocGadget<(), ConstraintF> for Blake2sParametersGadget { impl<ConstraintF: Field> AllocGadget<(), ConstraintF> for Blake2sParametersGadget {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<()>,
{
Self::alloc(cs, || Ok(val))
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(_: CS, _: F) -> Result<Self, SynthesisError> fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(_: CS, _: F) -> Result<Self, SynthesisError>
where where
F: FnOnce() -> Result<T, SynthesisError>, F: FnOnce() -> Result<T, SynthesisError>,
@ -69,6 +79,22 @@ impl AllocGadget<(), ConstraintF> for Blake2sParametersGadge
} }
impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sRandomnessGadget { impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sRandomnessGadget {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<[u8; 32]>,
{
let mut bytes = vec![];
for (i, b) in val.borrow().iter().enumerate() {
bytes.push(UInt8::alloc_constant(cs.ns(|| format!("value {}", i)), b)?)
}
Ok(Blake2sRandomnessGadget(bytes))
}
#[inline] #[inline]
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
cs: CS, cs: CS,

+ 31
- 5
crypto-primitives/src/commitment/pedersen/constraints.rs

@ -1,6 +1,7 @@
use crate::{ use crate::{
commitment::pedersen::{PedersenCommitment, PedersenParameters, PedersenRandomness}, commitment::pedersen::{PedersenCommitment, PedersenParameters, PedersenRandomness},
crh::pedersen::PedersenWindow, crh::pedersen::PedersenWindow,
Vec,
}; };
use algebra_core::{ use algebra_core::{
fields::{Field, PrimeField}, fields::{Field, PrimeField},
@ -97,16 +98,14 @@ where
W: PedersenWindow, W: PedersenWindow,
ConstraintF: PrimeField, ConstraintF: PrimeField,
{ {
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS, _cs: CS,
value_gen: F,
val: T,
) -> Result<Self, SynthesisError> ) -> Result<Self, SynthesisError>
where where
F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<PedersenParameters<G>>, T: Borrow<PedersenParameters<G>>,
{ {
let temp = value_gen()?;
let parameters = temp.borrow().clone();
let parameters = val.borrow().clone();
Ok(PedersenCommitmentGadgetParameters { Ok(PedersenCommitmentGadgetParameters {
params: parameters, params: parameters,
@ -116,6 +115,18 @@ where
}) })
} }
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
cs: CS,
value_gen: F,
) -> Result<Self, SynthesisError>
where
F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<PedersenParameters<G>>,
{
let temp = value_gen()?;
Self::alloc_constant(cs, temp)
}
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS, _cs: CS,
value_gen: F, value_gen: F,
@ -141,6 +152,21 @@ where
G: Group, G: Group,
ConstraintF: PrimeField, ConstraintF: PrimeField,
{ {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<PedersenRandomness<G>>,
{
let mut result_bytes = vec![];
for (i, byte) in to_bytes![val.borrow().0].unwrap().into_iter().enumerate() {
let cur = UInt8::alloc_constant(cs.ns(|| format!("byte {}", i)), byte)?;
result_bytes.push(cur);
}
Ok(PedersenRandomnessGadget(result_bytes))
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
cs: CS, cs: CS,
value_gen: F, value_gen: F,

+ 22
- 8
crypto-primitives/src/crh/bowe_hopwood/constraints.rs

@ -1,9 +1,12 @@
use core::{borrow::Borrow, hash::Hash, marker::PhantomData}; use core::{borrow::Borrow, hash::Hash, marker::PhantomData};
use crate::crh::{
bowe_hopwood::{BoweHopwoodPedersenCRH, BoweHopwoodPedersenParameters, CHUNK_SIZE},
pedersen::PedersenWindow,
FixedLengthCRHGadget,
use crate::{
crh::{
bowe_hopwood::{BoweHopwoodPedersenCRH, BoweHopwoodPedersenParameters, CHUNK_SIZE},
pedersen::PedersenWindow,
FixedLengthCRHGadget,
},
Vec,
}; };
use algebra_core::{groups::Group, Field}; use algebra_core::{groups::Group, Field};
use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSystem, SynthesisError};
@ -86,15 +89,14 @@ impl
AllocGadget<BoweHopwoodPedersenParameters<G>, ConstraintF> AllocGadget<BoweHopwoodPedersenParameters<G>, ConstraintF>
for BoweHopwoodPedersenCRHGadgetParameters<G, W, ConstraintF, GG> for BoweHopwoodPedersenCRHGadgetParameters<G, W, ConstraintF, GG>
{ {
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS, _cs: CS,
value_gen: F,
val: T,
) -> Result<Self, SynthesisError> ) -> Result<Self, SynthesisError>
where where
F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<BoweHopwoodPedersenParameters<G>>, T: Borrow<BoweHopwoodPedersenParameters<G>>,
{ {
let params = value_gen()?.borrow().clone();
let params = val.borrow().clone();
Ok(BoweHopwoodPedersenCRHGadgetParameters { Ok(BoweHopwoodPedersenCRHGadgetParameters {
params, params,
_group_g: PhantomData, _group_g: PhantomData,
@ -103,6 +105,18 @@ impl
}) })
} }
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
cs: CS,
value_gen: F,
) -> Result<Self, SynthesisError>
where
F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<BoweHopwoodPedersenParameters<G>>,
{
let params = value_gen()?.borrow().clone();
Self::alloc_constant(cs, params)
}
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS, _cs: CS,
value_gen: F, value_gen: F,

+ 21
- 7
crypto-primitives/src/crh/pedersen/constraints.rs

@ -1,6 +1,9 @@
use crate::crh::{
pedersen::{PedersenCRH, PedersenParameters, PedersenWindow},
FixedLengthCRHGadget,
use crate::{
crh::{
pedersen::{PedersenCRH, PedersenParameters, PedersenWindow},
FixedLengthCRHGadget,
},
Vec,
}; };
use algebra_core::{Field, Group}; use algebra_core::{Field, Group};
use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSystem, SynthesisError};
@ -77,15 +80,14 @@ impl
AllocGadget<PedersenParameters<G>, ConstraintF> AllocGadget<PedersenParameters<G>, ConstraintF>
for PedersenCRHGadgetParameters<G, W, ConstraintF, GG> for PedersenCRHGadgetParameters<G, W, ConstraintF, GG>
{ {
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS, _cs: CS,
value_gen: F,
val: T,
) -> Result<Self, SynthesisError> ) -> Result<Self, SynthesisError>
where where
F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<PedersenParameters<G>>, T: Borrow<PedersenParameters<G>>,
{ {
let params = value_gen()?.borrow().clone();
let params = val.borrow().clone();
Ok(PedersenCRHGadgetParameters { Ok(PedersenCRHGadgetParameters {
params, params,
_group_g: PhantomData, _group_g: PhantomData,
@ -94,6 +96,18 @@ impl
}) })
} }
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
cs: CS,
value_gen: F,
) -> Result<Self, SynthesisError>
where
F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<PedersenParameters<G>>,
{
let params = value_gen()?.borrow().clone();
Self::alloc_constant(cs, params)
}
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS, _cs: CS,
value_gen: F, value_gen: F,

+ 22
- 0
crypto-primitives/src/merkle_tree/constraints.rs

@ -128,6 +128,28 @@ where
HGadget: FixedLengthCRHGadget<P::H, ConstraintF>, HGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
ConstraintF: Field, ConstraintF: Field,
{ {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<MerkleTreePath<P>>,
{
let mut path = Vec::new();
for (i, &(ref l, ref r)) in val.borrow().path.iter().enumerate() {
let l_hash = HGadget::OutputGadget::alloc_constant(
&mut cs.ns(|| format!("l_child_{}", i)),
l.clone(),
)?;
let r_hash = HGadget::OutputGadget::alloc_constant(
&mut cs.ns(|| format!("r_child_{}", i)),
r.clone(),
)?;
path.push((l_hash, r_hash));
}
Ok(MerkleTreePathGadget { path })
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
value_gen: F, value_gen: F,

+ 12
- 0
crypto-primitives/src/nizk/constraints.rs

@ -20,4 +20,16 @@ pub trait NIZKVerifierGadget {
CS: ConstraintSystem<ConstraintF>, CS: ConstraintSystem<ConstraintF>,
I: Iterator<Item = &'a T>, I: Iterator<Item = &'a T>,
T: 'a + ToBitsGadget<ConstraintF> + ?Sized; T: 'a + ToBitsGadget<ConstraintF> + ?Sized;
fn conditional_check_verify<'a, CS, I, T>(
cs: CS,
verification_key: &Self::VerificationKeyGadget,
input: I,
proof: &Self::ProofGadget,
condition: &Boolean,
) -> Result<(), SynthesisError>
where
CS: ConstraintSystem<ConstraintF>,
I: Iterator<Item = &'a T>,
T: 'a + ToBitsGadget<ConstraintF> + ?Sized;
} }

+ 90
- 3
crypto-primitives/src/nizk/gm17/constraints.rs

@ -1,4 +1,7 @@
use crate::nizk::{gm17::Gm17, NIZKVerifierGadget};
use crate::{
nizk::{gm17::Gm17, NIZKVerifierGadget},
Vec,
};
use algebra_core::{AffineCurve, Field, PairingEngine, ToConstraintField}; use algebra_core::{AffineCurve, Field, PairingEngine, ToConstraintField};
use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
use r1cs_std::prelude::*; use r1cs_std::prelude::*;
@ -106,10 +109,31 @@ where
type ProofGadget = ProofGadget<PairingE, ConstraintF, P>; type ProofGadget = ProofGadget<PairingE, ConstraintF, P>;
fn check_verify<'a, CS, I, T>( fn check_verify<'a, CS, I, T>(
cs: CS,
vk: &Self::VerificationKeyGadget,
public_inputs: I,
proof: &Self::ProofGadget,
) -> Result<(), SynthesisError>
where
CS: ConstraintSystem<ConstraintF>,
I: Iterator<Item = &'a T>,
T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
{
<Self as NIZKVerifierGadget<Gm17<PairingE, C, V>, ConstraintF>>::conditional_check_verify(
cs,
vk,
public_inputs,
proof,
&Boolean::constant(true),
)
}
fn conditional_check_verify<'a, CS, I, T>(
mut cs: CS, mut cs: CS,
vk: &Self::VerificationKeyGadget, vk: &Self::VerificationKeyGadget,
mut public_inputs: I, mut public_inputs: I,
proof: &Self::ProofGadget, proof: &Self::ProofGadget,
condition: &Boolean,
) -> Result<(), SynthesisError> ) -> Result<(), SynthesisError>
where where
CS: ConstraintSystem<ConstraintF>, CS: ConstraintSystem<ConstraintF>,
@ -186,8 +210,8 @@ where
let test2 = P::final_exponentiation(cs.ns(|| "Final Exp 2"), &test2_exp)?; let test2 = P::final_exponentiation(cs.ns(|| "Final Exp 2"), &test2_exp)?;
let one = P::GTGadget::one(cs.ns(|| "GT One"))?; let one = P::GTGadget::one(cs.ns(|| "GT One"))?;
test1.enforce_equal(cs.ns(|| "Test 1"), &one)?;
test2.enforce_equal(cs.ns(|| "Test 2"), &one)?;
test1.conditional_enforce_equal(cs.ns(|| "Test 1"), &one, condition)?;
test2.conditional_enforce_equal(cs.ns(|| "Test 2"), &one, condition)?;
Ok(()) Ok(())
} }
} }
@ -199,6 +223,54 @@ where
ConstraintF: Field, ConstraintF: Field,
P: PairingGadget<PairingE, ConstraintF>, P: PairingGadget<PairingE, ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<VerifyingKey<PairingE>>,
{
let VerifyingKey {
h_g2,
g_alpha_g1,
h_beta_g2,
g_gamma_g1,
h_gamma_g2,
query,
} = val.borrow().clone();
let h_g2 = P::G2Gadget::alloc_constant(cs.ns(|| "h_g2"), h_g2.into_projective())?;
let g_alpha_g1 =
P::G1Gadget::alloc_constant(cs.ns(|| "g_alpha"), g_alpha_g1.into_projective())?;
let h_beta_g2 =
P::G2Gadget::alloc_constant(cs.ns(|| "h_beta"), h_beta_g2.into_projective())?;
let g_gamma_g1 =
P::G1Gadget::alloc_constant(cs.ns(|| "g_gamma_g1"), g_gamma_g1.into_projective())?;
let h_gamma_g2 =
P::G2Gadget::alloc_constant(cs.ns(|| "h_gamma_g2"), h_gamma_g2.into_projective())?;
let query = query
.into_iter()
.enumerate()
.map(|(i, query_i)| {
P::G1Gadget::alloc_constant(
cs.ns(|| format!("query_{}", i)),
query_i.into_projective(),
)
})
.collect::<Vec<_>>()
.into_iter()
.collect::<Result<_, _>>()?;
Ok(Self {
h_g2,
g_alpha_g1,
h_beta_g2,
g_gamma_g1,
h_gamma_g2,
query,
})
}
#[inline] #[inline]
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
@ -309,6 +381,21 @@ where
ConstraintF: Field, ConstraintF: Field,
P: PairingGadget<PairingE, ConstraintF>, P: PairingGadget<PairingE, ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<Proof<PairingE>>,
{
let Proof { a, b, c } = val.borrow().clone();
let a = P::G1Gadget::alloc_constant(cs.ns(|| "a"), a.into_projective())?;
let b = P::G2Gadget::alloc_constant(cs.ns(|| "b"), b.into_projective())?;
let c = P::G1Gadget::alloc_constant(cs.ns(|| "c"), c.into_projective())?;
Ok(Self { a, b, c })
}
#[inline] #[inline]
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,

+ 1
- 1
crypto-primitives/src/nizk/gm17/mod.rs

@ -35,10 +35,10 @@ impl, V: ToConstraintField
{ {
type Circuit = C; type Circuit = C;
type AssignedCircuit = C; type AssignedCircuit = C;
type VerifierInput = V;
type ProvingParameters = Parameters<E>; type ProvingParameters = Parameters<E>;
type VerificationParameters = VerifyingKey<E>; type VerificationParameters = VerifyingKey<E>;
type PreparedVerificationParameters = PreparedVerifyingKey<E>; type PreparedVerificationParameters = PreparedVerifyingKey<E>;
type VerifierInput = V;
type Proof = Proof<E>; type Proof = Proof<E>;
fn setup<R: Rng>( fn setup<R: Rng>(

+ 85
- 2
crypto-primitives/src/nizk/groth16/constraints.rs

@ -1,4 +1,7 @@
use crate::nizk::{groth16::Groth16, NIZKVerifierGadget};
use crate::{
nizk::{groth16::Groth16, NIZKVerifierGadget},
Vec,
};
use algebra_core::{AffineCurve, Field, PairingEngine, ToConstraintField}; use algebra_core::{AffineCurve, Field, PairingEngine, ToConstraintField};
use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
use r1cs_std::prelude::*; use r1cs_std::prelude::*;
@ -107,10 +110,31 @@ where
type ProofGadget = ProofGadget<PairingE, ConstraintF, P>; type ProofGadget = ProofGadget<PairingE, ConstraintF, P>;
fn check_verify<'a, CS, I, T>( fn check_verify<'a, CS, I, T>(
cs: CS,
vk: &Self::VerificationKeyGadget,
public_inputs: I,
proof: &Self::ProofGadget,
) -> Result<(), SynthesisError>
where
CS: ConstraintSystem<ConstraintF>,
I: Iterator<Item = &'a T>,
T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
{
<Self as NIZKVerifierGadget<Groth16<PairingE, C, V>, ConstraintF>>::conditional_check_verify(
cs,
vk,
public_inputs,
proof,
&Boolean::constant(true),
)
}
fn conditional_check_verify<'a, CS, I, T>(
mut cs: CS, mut cs: CS,
vk: &Self::VerificationKeyGadget, vk: &Self::VerificationKeyGadget,
mut public_inputs: I, mut public_inputs: I,
proof: &Self::ProofGadget, proof: &Self::ProofGadget,
condition: &Boolean,
) -> Result<(), SynthesisError> ) -> Result<(), SynthesisError>
where where
CS: ConstraintSystem<ConstraintF>, CS: ConstraintSystem<ConstraintF>,
@ -158,7 +182,7 @@ where
let test = P::final_exponentiation(cs.ns(|| "Final Exp"), &test_exp).unwrap(); let test = P::final_exponentiation(cs.ns(|| "Final Exp"), &test_exp).unwrap();
test.enforce_equal(cs.ns(|| "Test 1"), &pvk.alpha_g1_beta_g2)?;
test.conditional_enforce_equal(cs.ns(|| "Test 1"), &pvk.alpha_g1_beta_g2, condition)?;
Ok(()) Ok(())
} }
} }
@ -170,6 +194,50 @@ where
ConstraintF: Field, ConstraintF: Field,
P: PairingGadget<PairingE, ConstraintF>, P: PairingGadget<PairingE, ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<VerifyingKey<PairingE>>,
{
let VerifyingKey {
alpha_g1,
beta_g2,
gamma_g2,
delta_g2,
gamma_abc_g1,
} = val.borrow().clone();
let alpha_g1 =
P::G1Gadget::alloc_constant(cs.ns(|| "alpha_g1"), alpha_g1.into_projective())?;
let beta_g2 = P::G2Gadget::alloc_constant(cs.ns(|| "beta_g2"), beta_g2.into_projective())?;
let gamma_g2 =
P::G2Gadget::alloc_constant(cs.ns(|| "gamma_g2"), gamma_g2.into_projective())?;
let delta_g2 =
P::G2Gadget::alloc_constant(cs.ns(|| "delta_g2"), delta_g2.into_projective())?;
let gamma_abc_g1 = gamma_abc_g1
.into_iter()
.enumerate()
.map(|(i, gamma_abc_i)| {
P::G1Gadget::alloc_constant(
cs.ns(|| format!("gamma_abc_{}", i)),
gamma_abc_i.into_projective(),
)
})
.collect::<Vec<_>>()
.into_iter()
.collect::<Result<_, _>>()?;
Ok(Self {
alpha_g1,
beta_g2,
gamma_g2,
delta_g2,
gamma_abc_g1,
})
}
#[inline] #[inline]
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
@ -273,6 +341,21 @@ where
ConstraintF: Field, ConstraintF: Field,
P: PairingGadget<PairingE, ConstraintF>, P: PairingGadget<PairingE, ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<Proof<PairingE>>,
{
let Proof { a, b, c } = val.borrow().clone();
let a = P::G1Gadget::alloc_constant(cs.ns(|| "a"), a.into_projective())?;
let b = P::G2Gadget::alloc_constant(cs.ns(|| "b"), b.into_projective())?;
let c = P::G1Gadget::alloc_constant(cs.ns(|| "c"), c.into_projective())?;
Ok(Self { a, b, c })
}
#[inline] #[inline]
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,

+ 1
- 1
crypto-primitives/src/nizk/groth16/mod.rs

@ -35,10 +35,10 @@ impl, V: ToConstraintField
{ {
type Circuit = C; type Circuit = C;
type AssignedCircuit = C; type AssignedCircuit = C;
type VerifierInput = V;
type ProvingParameters = Parameters<E>; type ProvingParameters = Parameters<E>;
type VerificationParameters = VerifyingKey<E>; type VerificationParameters = VerifyingKey<E>;
type PreparedVerificationParameters = PreparedVerifyingKey<E>; type PreparedVerificationParameters = PreparedVerifyingKey<E>;
type VerifierInput = V;
type Proof = Proof<E>; type Proof = Proof<E>;
fn setup<R: Rng>( fn setup<R: Rng>(

+ 17
- 1
crypto-primitives/src/prf/blake2s/constraints.rs

@ -1,7 +1,7 @@
use algebra_core::PrimeField; use algebra_core::PrimeField;
use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSystem, SynthesisError};
use crate::prf::PRFGadget;
use crate::{prf::PRFGadget, Vec};
use r1cs_std::prelude::*; use r1cs_std::prelude::*;
use core::borrow::Borrow; use core::borrow::Borrow;
@ -450,6 +450,22 @@ impl ToBytesGadget for Blake2sOutputGadget
} }
impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sOutputGadget { impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sOutputGadget {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<[u8; 32]>,
{
let mut bytes = vec![];
for (i, b) in val.borrow().iter().enumerate() {
bytes.push(UInt8::alloc_constant(cs.ns(|| format!("value {}", i)), b)?)
}
Ok(Blake2sOutputGadget(bytes))
}
#[inline] #[inline]
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
cs: CS, cs: CS,

+ 1
- 1
crypto-primitives/src/prf/constraints.rs

@ -1,7 +1,7 @@
use algebra_core::Field; use algebra_core::Field;
use core::fmt::Debug; use core::fmt::Debug;
use crate::prf::PRF;
use crate::{prf::PRF, Vec};
use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSystem, SynthesisError};
use r1cs_std::prelude::*; use r1cs_std::prelude::*;

+ 31
- 0
crypto-primitives/src/signature/schnorr/constraints.rs

@ -1,3 +1,4 @@
use crate::Vec;
use algebra_core::{groups::Group, Field}; use algebra_core::{groups::Group, Field};
use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSystem, SynthesisError};
use r1cs_std::prelude::*; use r1cs_std::prelude::*;
@ -95,6 +96,21 @@ where
GG: GroupGadget<G, ConstraintF>, GG: GroupGadget<G, ConstraintF>,
D: Digest, D: Digest,
{ {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<SchnorrSigParameters<G, D>>,
{
let generator = GG::alloc_constant(cs, val.borrow().generator)?;
Ok(Self {
generator,
_engine: PhantomData,
_group: PhantomData,
})
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError> fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
where where
F: FnOnce() -> Result<T, SynthesisError>, F: FnOnce() -> Result<T, SynthesisError>,
@ -132,6 +148,21 @@ where
ConstraintF: Field, ConstraintF: Field,
GG: GroupGadget<G, ConstraintF>, GG: GroupGadget<G, ConstraintF>,
{ {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
cs: CS,
val: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<SchnorrPublicKey<G>>,
{
let pub_key = GG::alloc_constant(cs, val.borrow())?;
Ok(Self {
pub_key,
_engine: PhantomData,
_group: PhantomData,
})
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError> fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
where where
F: FnOnce() -> Result<T, SynthesisError>, F: FnOnce() -> Result<T, SynthesisError>,

+ 22
- 0
r1cs-std/src/alloc.rs

@ -8,6 +8,13 @@ where
Self: Sized, Self: Sized,
V: ?Sized, V: ?Sized,
{ {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<V>;
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError> fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
where where
F: FnOnce() -> Result<T, SynthesisError>, F: FnOnce() -> Result<T, SynthesisError>,
@ -47,6 +54,21 @@ where
impl<I, ConstraintF: Field, A: AllocGadget<I, ConstraintF>> AllocGadget<[I], ConstraintF> impl<I, ConstraintF: Field, A: AllocGadget<I, ConstraintF>> AllocGadget<[I], ConstraintF>
for Vec<A> for Vec<A>
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<[I]>,
{
let mut vec = Vec::new();
for (i, value) in t.borrow().iter().enumerate() {
vec.push(A::alloc_constant(cs.ns(|| format!("value_{}", i)), value)?);
}
Ok(vec)
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
f: F, f: F,

+ 36
- 0
r1cs-std/src/bits/boolean.rs

@ -235,6 +235,16 @@ impl PartialEq for AllocatedBit {
impl Eq for AllocatedBit {} impl Eq for AllocatedBit {}
impl<ConstraintF: Field> AllocGadget<bool, ConstraintF> for AllocatedBit { impl<ConstraintF: Field> AllocGadget<bool, ConstraintF> for AllocatedBit {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS,
_t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<bool>,
{
unimplemented!();
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
value_gen: F, value_gen: F,
@ -539,6 +549,22 @@ impl Boolean {
Ok(cur) Ok(cur)
} }
pub fn kary_or<ConstraintF, CS>(mut cs: CS, bits: &[Self]) -> Result<Self, SynthesisError>
where
ConstraintF: Field,
CS: ConstraintSystem<ConstraintF>,
{
assert!(!bits.is_empty());
let mut bits = bits.iter();
let mut cur: Self = *bits.next().unwrap();
for (i, next) in bits.enumerate() {
cur = Boolean::or(cs.ns(|| format!("OR {}", i)), &cur, next)?;
}
Ok(cur)
}
/// Asserts that at least one operand is false. /// Asserts that at least one operand is false.
pub fn enforce_nand<ConstraintF, CS>(mut cs: CS, bits: &[Self]) -> Result<(), SynthesisError> pub fn enforce_nand<ConstraintF, CS>(mut cs: CS, bits: &[Self]) -> Result<(), SynthesisError>
where where
@ -715,6 +741,16 @@ impl From for Boolean {
} }
impl<ConstraintF: Field> AllocGadget<bool, ConstraintF> for Boolean { impl<ConstraintF: Field> AllocGadget<bool, ConstraintF> for Boolean {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<bool>,
{
Ok(Boolean::constant(*t.borrow()))
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
cs: CS, cs: CS,
value_gen: F, value_gen: F,

+ 22
- 0
r1cs-std/src/bits/mod.rs

@ -58,6 +58,15 @@ impl ToBitsGadget for Vec {
} }
} }
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for UInt8 {
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
_cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
Ok(self.into_bits_le())
}
}
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [UInt8] { impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [UInt8] {
fn to_bits<CS: ConstraintSystem<ConstraintF>>( fn to_bits<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
@ -71,6 +80,19 @@ impl ToBitsGadget for [UInt8] {
} }
} }
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for Vec<UInt8> {
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
&self,
_cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
let mut result = Vec::with_capacity(&self.len() * 8);
for byte in self {
result.extend_from_slice(&byte.into_bits_le());
}
Ok(result)
}
}
pub trait ToBytesGadget<ConstraintF: Field> { pub trait ToBytesGadget<ConstraintF: Field> {
/// Outputs a canonical byte-wise representation of `self`. /// Outputs a canonical byte-wise representation of `self`.
/// ///

+ 35
- 25
r1cs-std/src/bits/uint64.rs

@ -14,7 +14,7 @@ use core::borrow::Borrow;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct UInt64 { pub struct UInt64 {
// Least significant bit_gadget first // Least significant bit_gadget first
bits: Vec<Boolean>,
bits: Vec<Boolean>,
value: Option<u64>, value: Option<u64>,
} }
@ -56,7 +56,7 @@ impl UInt64 {
} }
v v
},
}
None => vec![None; 64], None => vec![None; 64],
}; };
@ -95,19 +95,19 @@ impl UInt64 {
if b { if b {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
} }
},
}
&Boolean::Is(ref b) => match b.get_value() { &Boolean::Is(ref b) => match b.get_value() {
Some(true) => { Some(true) => {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
},
Some(false) => {},
}
Some(false) => {}
None => value = None, None => value = None,
}, },
&Boolean::Not(ref b) => match b.get_value() { &Boolean::Not(ref b) => match b.get_value() {
Some(false) => { Some(false) => {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
},
Some(true) => {},
}
Some(true) => {}
None => value = None, None => value = None,
}, },
} }
@ -129,7 +129,7 @@ impl UInt64 {
.collect(); .collect();
UInt64 { UInt64 {
bits: new_bits,
bits: new_bits,
value: self.value.map(|v| v.rotate_right(by as u32)), value: self.value.map(|v| v.rotate_right(by as u32)),
} }
} }
@ -194,12 +194,12 @@ impl UInt64 {
match op.value { match op.value {
Some(val) => { Some(val) => {
result_value.as_mut().map(|v| *v += u128::from(val)); result_value.as_mut().map(|v| *v += u128::from(val));
},
}
None => { None => {
// If any of our operands have unknown value, we won't // If any of our operands have unknown value, we won't
// know the value of the result // know the value of the result
result_value = None; result_value = None;
},
}
} }
// Iterate over each bit_gadget of the operand and add the operand to // Iterate over each bit_gadget of the operand and add the operand to
@ -212,18 +212,18 @@ impl UInt64 {
// Add coeff * bit_gadget // Add coeff * bit_gadget
lc += (coeff, bit.get_variable()); lc += (coeff, bit.get_variable());
},
}
Boolean::Not(ref bit) => { Boolean::Not(ref bit) => {
all_constants = false; all_constants = false;
// Add coeff * (1 - bit_gadget) = coeff * ONE - coeff * bit_gadget // Add coeff * (1 - bit_gadget) = coeff * ONE - coeff * bit_gadget
lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable()); lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable());
},
}
Boolean::Constant(bit) => { Boolean::Constant(bit) => {
if bit { if bit {
lc += (coeff, CS::one()); lc += (coeff, CS::one());
} }
},
}
} }
coeff.double_in_place(); coeff.double_in_place();
@ -270,13 +270,23 @@ impl UInt64 {
result_bits.truncate(64); result_bits.truncate(64);
Ok(UInt64 { Ok(UInt64 {
bits: result_bits,
bits: result_bits,
value: modular_value, value: modular_value,
}) })
} }
} }
impl<ConstraintF: Field> AllocGadget<u64, ConstraintF> for UInt64 { impl<ConstraintF: Field> AllocGadget<u64, ConstraintF> for UInt64 {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<u64>,
{
Ok(UInt64::constant(*t.borrow()))
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
value_gen: F, value_gen: F,
@ -330,7 +340,7 @@ impl ToBytesGadget for UInt64 {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for (i, chunk8) in self.to_bits_le().chunks(8).enumerate() { for (i, chunk8) in self.to_bits_le().chunks(8).enumerate() {
let byte = UInt8 { let byte = UInt8 {
bits: chunk8.to_vec(),
bits: chunk8.to_vec(),
value: value_chunks[i], value: value_chunks[i],
}; };
bytes.push(byte); bytes.push(byte);
@ -397,7 +407,7 @@ mod test {
match bit_gadget { match bit_gadget {
&Boolean::Constant(bit_gadget) => { &Boolean::Constant(bit_gadget) => {
assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1)); assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1));
},
}
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -406,8 +416,8 @@ mod test {
for x in v.iter().zip(expected_to_be_same.iter()) { for x in v.iter().zip(expected_to_be_same.iter()) {
match x { match x {
(&Boolean::Constant(true), &Boolean::Constant(true)) => {},
(&Boolean::Constant(false), &Boolean::Constant(false)) => {},
(&Boolean::Constant(true), &Boolean::Constant(true)) => {}
(&Boolean::Constant(false), &Boolean::Constant(false)) => {}
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -442,13 +452,13 @@ mod test {
match b { match b {
&Boolean::Is(ref b) => { &Boolean::Is(ref b) => {
assert!(b.get_value().unwrap() == (expected & 1 == 1)); assert!(b.get_value().unwrap() == (expected & 1 == 1));
},
}
&Boolean::Not(ref b) => { &Boolean::Not(ref b) => {
assert!(!b.get_value().unwrap() == (expected & 1 == 1)); assert!(!b.get_value().unwrap() == (expected & 1 == 1));
},
}
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert!(b == (expected & 1 == 1)); assert!(b == (expected & 1 == 1));
},
}
} }
expected >>= 1; expected >>= 1;
@ -483,7 +493,7 @@ mod test {
&Boolean::Not(_) => panic!(), &Boolean::Not(_) => panic!(),
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert!(b == (expected & 1 == 1)); assert!(b == (expected & 1 == 1));
},
}
} }
expected >>= 1; expected >>= 1;
@ -521,10 +531,10 @@ mod test {
match b { match b {
&Boolean::Is(ref b) => { &Boolean::Is(ref b) => {
assert!(b.get_value().unwrap() == (expected & 1 == 1)); assert!(b.get_value().unwrap() == (expected & 1 == 1));
},
}
&Boolean::Not(ref b) => { &Boolean::Not(ref b) => {
assert!(!b.get_value().unwrap() == (expected & 1 == 1)); assert!(!b.get_value().unwrap() == (expected & 1 == 1));
},
}
&Boolean::Constant(_) => unreachable!(), &Boolean::Constant(_) => unreachable!(),
} }
@ -560,7 +570,7 @@ mod test {
match b { match b {
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert_eq!(b, tmp & 1 == 1); assert_eq!(b, tmp & 1 == 1);
},
}
_ => unreachable!(), _ => unreachable!(),
} }

+ 10
- 0
r1cs-std/src/bits/uint8.rs

@ -214,6 +214,16 @@ impl ConditionalEqGadget for UInt8 {
impl<ConstraintF: Field> EqGadget<ConstraintF> for UInt8 {} impl<ConstraintF: Field> EqGadget<ConstraintF> for UInt8 {}
impl<ConstraintF: Field> AllocGadget<u8, ConstraintF> for UInt8 { impl<ConstraintF: Field> AllocGadget<u8, ConstraintF> for UInt8 {
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
_cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<u8>,
{
Ok(UInt8::constant(*t.borrow()))
}
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
value_gen: F, value_gen: F,

+ 12
- 0
r1cs-std/src/fields/fp/mod.rs

@ -584,6 +584,18 @@ impl Clone for FpGadget {
} }
impl<F: PrimeField> AllocGadget<F, F> for FpGadget<F> { impl<F: PrimeField> AllocGadget<F, F> for FpGadget<F> {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<F>>(_cs: CS, t: T) -> Result<Self, SynthesisError>
where
T: Borrow<F>,
{
let value = t.borrow().clone();
Ok(Self {
value: Some(value),
variable: LinearCombination::from((value, CS::one())).into(),
})
}
#[inline] #[inline]
fn alloc<FN, T, CS: ConstraintSystem<F>>( fn alloc<FN, T, CS: ConstraintSystem<F>>(
mut cs: CS, mut cs: CS,

+ 11
- 0
r1cs-std/src/fields/fp12.rs

@ -834,6 +834,17 @@ where
P: Fp12Parameters, P: Fp12Parameters,
<P::Fp6Params as Fp6Parameters>::Fp2Params: Fp2Parameters<Fp = ConstraintF>, <P::Fp6Params as Fp6Parameters>::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<Fp12<P>>,
{
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
}
#[inline] #[inline]
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,

+ 11
- 0
r1cs-std/src/fields/fp2.rs

@ -611,6 +611,17 @@ impl, ConstraintF: PrimeField>
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> AllocGadget<Fp2<P>, ConstraintF> impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> AllocGadget<Fp2<P>, ConstraintF>
for Fp2Gadget<P, ConstraintF> for Fp2Gadget<P, ConstraintF>
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<Fp2<P>>,
{
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
}
#[inline] #[inline]
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,

+ 11
- 0
r1cs-std/src/fields/fp3.rs

@ -867,6 +867,17 @@ impl, ConstraintF: PrimeField + SquareRootFie
impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootField> impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootField>
AllocGadget<Fp3<P>, ConstraintF> for Fp3Gadget<P, ConstraintF> AllocGadget<Fp3<P>, ConstraintF> for Fp3Gadget<P, ConstraintF>
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<Fp3<P>>,
{
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
}
#[inline] #[inline]
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,

+ 11
- 0
r1cs-std/src/fields/fp4.rs

@ -673,6 +673,17 @@ where
P: Fp4Parameters, P: Fp4Parameters,
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>, P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<Fp4<P>>,
{
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
}
#[inline] #[inline]
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,

+ 11
- 0
r1cs-std/src/fields/fp6_2over3.rs

@ -664,6 +664,17 @@ where
P: Fp6Parameters, P: Fp6Parameters,
P::Fp3Params: Fp3Parameters<Fp = ConstraintF>, P::Fp3Params: Fp3Parameters<Fp = ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<Fp6<P>>,
{
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
}
#[inline] #[inline]
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,

+ 11
- 0
r1cs-std/src/fields/fp6_3over2.rs

@ -964,6 +964,17 @@ where
P: Fp6Parameters, P: Fp6Parameters,
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>, P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<Fp6<P>>,
{
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
}
#[inline] #[inline]
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,

+ 128
- 0
r1cs-std/src/groups/curves/short_weierstrass/mod.rs

@ -437,6 +437,24 @@ where
ConstraintF: PrimeField, ConstraintF: PrimeField,
F: FieldGadget<P::BaseField, ConstraintF>, F: FieldGadget<P::BaseField, ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<SWProjective<P>>,
{
let p = t.borrow().into_affine();
Ok(Self {
x: F::alloc_constant(cs.ns(|| "x"), &p.x)?,
y: F::alloc_constant(cs.ns(|| "y"), &p.y)?,
infinity: Boolean::constant(p.infinity),
_params: PhantomData,
_engine: PhantomData,
})
}
#[inline] #[inline]
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
@ -661,3 +679,113 @@ where
Ok(x_bytes) Ok(x_bytes)
} }
} }
#[cfg(test)]
#[allow(dead_code)]
pub(crate) fn test<ConstraintF, P, GG>()
where
ConstraintF: Field,
P: SWModelParameters,
GG: GroupGadget<SWProjective<P>, ConstraintF, Value = SWProjective<P>>,
{
use crate::{boolean::AllocatedBit, prelude::*, test_constraint_system::TestConstraintSystem};
use algebra::{test_rng, Group, UniformRand};
use rand::Rng;
// Incomplete addition doesn't allow us to call the group_test.
// group_test::<ConstraintF, SWProjective<P>, GG>();
let mut rng = test_rng();
let mut cs = TestConstraintSystem::<ConstraintF>::new();
let a = SWProjective::<P>::rand(&mut rng);
let b = SWProjective::<P>::rand(&mut rng);
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = GG::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = GG::alloc_checked(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.get_value().unwrap().x, a_affine.x);
assert_eq!(gadget_a.get_value().unwrap().y, a_affine.y);
assert_eq!(gadget_b.get_value().unwrap().x, b_affine.x);
assert_eq!(gadget_b.get_value().unwrap().y, b_affine.y);
// Check addition
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
let ab_val = gadget_ab
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
// Check doubling
let aa = Group::double(&a);
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
let aa_val = gadget_a
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(
aa_val, aa_affine,
"Gadget and native values are unequal after double."
);
// Check mul_bits
let scalar = P::ScalarField::rand(&mut rng);
let native_result = aa.into_affine().mul(scalar) + &b;
let native_result = native_result.into_affine();
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
// Get the scalar bits into little-endian form.
scalar.reverse();
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
let result = gadget_a
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
.unwrap();
let result_val = result.get_value().unwrap().into_affine();
assert_eq!(
result_val, native_result,
"gadget & native values are diff. after scalar mul"
);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
// Constraint cost etc.
let mut cs = TestConstraintSystem::<ConstraintF>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: SWProjective<P> = rng.gen();
let b: SWProjective<P> = rng.gen();
let gadget_a = GG::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = GG::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ =
GG::conditionally_select(&mut cs.ns(|| "cond_select"), &bit, &gadget_a, &gadget_b).unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(
cond_select_cost,
<GG as CondSelectGadget<ConstraintF>>::cost()
);
assert_eq!(add_cost, GG::cost_of_add());
}

+ 34
- 0
r1cs-std/src/groups/curves/twisted_edwards/mod.rs

@ -492,6 +492,23 @@ mod affine_impl {
F: FieldGadget<P::BaseField, ConstraintF>, F: FieldGadget<P::BaseField, ConstraintF>,
Self: GroupGadget<TEAffine<P>, ConstraintF>, Self: GroupGadget<TEAffine<P>, ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<TEAffine<P>>,
{
let p = t.borrow();
Ok(Self {
x: F::alloc_constant(cs.ns(|| "x"), &p.x)?,
y: F::alloc_constant(cs.ns(|| "y"), &p.y)?,
_params: PhantomData,
_engine: PhantomData,
})
}
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
value_gen: FN, value_gen: FN,
@ -1089,6 +1106,23 @@ mod projective_impl {
F: FieldGadget<P::BaseField, ConstraintF>, F: FieldGadget<P::BaseField, ConstraintF>,
Self: GroupGadget<TEProjective<P>, ConstraintF>, Self: GroupGadget<TEProjective<P>, ConstraintF>,
{ {
#[inline]
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS,
t: T,
) -> Result<Self, SynthesisError>
where
T: Borrow<TEProjective<P>>,
{
let p = t.borrow().into_affine();
Ok(Self {
x: F::alloc_constant(cs.ns(|| "x"), &p.x)?,
y: F::alloc_constant(cs.ns(|| "y"), &p.y)?,
_params: PhantomData,
_engine: PhantomData,
})
}
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>( fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
mut cs: CS, mut cs: CS,
value_gen: FN, value_gen: FN,

+ 13
- 188
r1cs-std/src/instantiated/bls12_377/curves.rs

@ -7,192 +7,17 @@ pub type G2Gadget = bls12::G2Gadget;
pub type G1PreparedGadget = bls12::G1PreparedGadget<Parameters>; pub type G1PreparedGadget = bls12::G1PreparedGadget<Parameters>;
pub type G2PreparedGadget = bls12::G2PreparedGadget<Parameters>; pub type G2PreparedGadget = bls12::G2PreparedGadget<Parameters>;
#[cfg(test)]
mod test {
use rand::Rng;
use super::{G1Gadget, G2Gadget};
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
use algebra::{bls12_377::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
use r1cs_core::ConstraintSystem;
#[test]
fn bls12_g1_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G1Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G1Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G1Gadget::cost_of_add());
}
#[test]
fn bls12_g2_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G2Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G2Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G2Gadget::cost_of_add());
}
#[test]
fn bls12_g1_gadget_test() {
use algebra::UniformRand;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut cs = TestConstraintSystem::<Fq>::new();
let a = G1Projective::rand(&mut rng);
let b = G1Projective::rand(&mut rng);
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
// Check addition
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
let ab_val = gadget_ab
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
// Check doubling
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
let aa_val = gadget_a
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(
aa_val, aa_affine,
"Gadget and native values are unequal after double."
);
// Check mul_bits
let scalar = Fr::rand(&mut rng);
let native_result = aa.into_affine().mul(scalar) + &b;
let native_result = native_result.into_affine();
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
// Get the scalar bits into little-endian form.
scalar.reverse();
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
let result = gadget_a
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
.unwrap();
let result_val = result.get_value().unwrap().into_affine();
assert_eq!(
result_val, native_result,
"gadget & native values are diff. after scalar mul"
);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn bls12_g2_gadget_test() {
let mut cs = TestConstraintSystem::<Fq>::new();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn test() {
use algebra::curves::models::bls12::Bls12Parameters;
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as Bls12Parameters>::G1Parameters,
G1Gadget,
>();
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as Bls12Parameters>::G2Parameters,
G2Gadget,
>();
} }

+ 13
- 188
r1cs-std/src/instantiated/mnt4_298/curves.rs

@ -7,192 +7,17 @@ pub type G2Gadget = mnt4::G2Gadget;
pub type G1PreparedGadget = mnt4::G1PreparedGadget<Parameters>; pub type G1PreparedGadget = mnt4::G1PreparedGadget<Parameters>;
pub type G2PreparedGadget = mnt4::G2PreparedGadget<Parameters>; pub type G2PreparedGadget = mnt4::G2PreparedGadget<Parameters>;
#[cfg(test)]
mod test {
use rand::Rng;
use super::{G1Gadget, G2Gadget};
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
use algebra::{mnt4_298::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
use r1cs_core::ConstraintSystem;
#[test]
fn mnt4_298_g1_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G1Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G1Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G1Gadget::cost_of_add());
}
#[test]
fn mnt4_298_g2_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G2Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G2Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G2Gadget::cost_of_add());
}
#[test]
fn mnt4_298_g1_gadget_test() {
use algebra::UniformRand;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut cs = TestConstraintSystem::<Fq>::new();
let a = G1Projective::rand(&mut rng);
let b = G1Projective::rand(&mut rng);
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
// Check addition
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
let ab_val = gadget_ab
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
// Check doubling
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
let aa_val = gadget_a
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(
aa_val, aa_affine,
"Gadget and native values are unequal after double."
);
// Check mul_bits
let scalar = Fr::rand(&mut rng);
let native_result = aa.into_affine().mul(scalar) + &b;
let native_result = native_result.into_affine();
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
// Get the scalar bits into little-endian form.
scalar.reverse();
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
let result = gadget_a
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
.unwrap();
let result_val = result.get_value().unwrap().into_affine();
assert_eq!(
result_val, native_result,
"gadget & native values are diff. after scalar mul"
);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn mnt4_298_g2_gadget_test() {
let mut cs = TestConstraintSystem::<Fq>::new();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn test() {
use algebra::curves::models::mnt4::MNT4Parameters;
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as MNT4Parameters>::G1Parameters,
G1Gadget,
>();
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as MNT4Parameters>::G2Parameters,
G2Gadget,
>();
} }

+ 13
- 188
r1cs-std/src/instantiated/mnt4_753/curves.rs

@ -7,192 +7,17 @@ pub type G2Gadget = mnt4::G2Gadget;
pub type G1PreparedGadget = mnt4::G1PreparedGadget<Parameters>; pub type G1PreparedGadget = mnt4::G1PreparedGadget<Parameters>;
pub type G2PreparedGadget = mnt4::G2PreparedGadget<Parameters>; pub type G2PreparedGadget = mnt4::G2PreparedGadget<Parameters>;
#[cfg(test)]
mod test {
use rand::Rng;
use super::{G1Gadget, G2Gadget};
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
use algebra::{mnt4_753::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
use r1cs_core::ConstraintSystem;
#[test]
fn mnt4_753_g1_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G1Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G1Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G1Gadget::cost_of_add());
}
#[test]
fn mnt4_753_g2_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G2Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G2Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G2Gadget::cost_of_add());
}
#[test]
fn mnt4_753_g1_gadget_test() {
use algebra::UniformRand;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut cs = TestConstraintSystem::<Fq>::new();
let a = G1Projective::rand(&mut rng);
let b = G1Projective::rand(&mut rng);
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
// Check addition
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
let ab_val = gadget_ab
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
// Check doubling
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
let aa_val = gadget_a
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(
aa_val, aa_affine,
"Gadget and native values are unequal after double."
);
// Check mul_bits
let scalar = Fr::rand(&mut rng);
let native_result = aa.into_affine().mul(scalar) + &b;
let native_result = native_result.into_affine();
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
// Get the scalar bits into little-endian form.
scalar.reverse();
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
let result = gadget_a
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
.unwrap();
let result_val = result.get_value().unwrap().into_affine();
assert_eq!(
result_val, native_result,
"gadget & native values are diff. after scalar mul"
);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn mnt4_753_g2_gadget_test() {
let mut cs = TestConstraintSystem::<Fq>::new();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn test() {
use algebra::curves::models::mnt4::MNT4Parameters;
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as MNT4Parameters>::G1Parameters,
G1Gadget,
>();
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as MNT4Parameters>::G2Parameters,
G2Gadget,
>();
} }

+ 13
- 188
r1cs-std/src/instantiated/mnt6_298/curves.rs

@ -7,192 +7,17 @@ pub type G2Gadget = mnt6::G2Gadget;
pub type G1PreparedGadget = mnt6::G1PreparedGadget<Parameters>; pub type G1PreparedGadget = mnt6::G1PreparedGadget<Parameters>;
pub type G2PreparedGadget = mnt6::G2PreparedGadget<Parameters>; pub type G2PreparedGadget = mnt6::G2PreparedGadget<Parameters>;
#[cfg(test)]
mod test {
use rand::Rng;
use super::{G1Gadget, G2Gadget};
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
use algebra::{mnt6_298::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
use r1cs_core::ConstraintSystem;
#[test]
fn mnt6_298_g1_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G1Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G1Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G1Gadget::cost_of_add());
}
#[test]
fn mnt6_298_g2_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G2Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G2Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G2Gadget::cost_of_add());
}
#[test]
fn mnt6_298_g1_gadget_test() {
use algebra::UniformRand;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut cs = TestConstraintSystem::<Fq>::new();
let a = G1Projective::rand(&mut rng);
let b = G1Projective::rand(&mut rng);
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
// Check addition
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
let ab_val = gadget_ab
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
// Check doubling
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
let aa_val = gadget_a
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(
aa_val, aa_affine,
"Gadget and native values are unequal after double."
);
// Check mul_bits
let scalar = Fr::rand(&mut rng);
let native_result = aa.into_affine().mul(scalar) + &b;
let native_result = native_result.into_affine();
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
// Get the scalar bits into little-endian form.
scalar.reverse();
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
let result = gadget_a
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
.unwrap();
let result_val = result.get_value().unwrap().into_affine();
assert_eq!(
result_val, native_result,
"gadget & native values are diff. after scalar mul"
);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn mnt6_298_g2_gadget_test() {
let mut cs = TestConstraintSystem::<Fq>::new();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn test() {
use algebra::curves::models::mnt6::MNT6Parameters;
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as MNT6Parameters>::G1Parameters,
G1Gadget,
>();
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as MNT6Parameters>::G2Parameters,
G2Gadget,
>();
} }

+ 13
- 188
r1cs-std/src/instantiated/mnt6_753/curves.rs

@ -7,192 +7,17 @@ pub type G2Gadget = mnt6::G2Gadget;
pub type G1PreparedGadget = mnt6::G1PreparedGadget<Parameters>; pub type G1PreparedGadget = mnt6::G1PreparedGadget<Parameters>;
pub type G2PreparedGadget = mnt6::G2PreparedGadget<Parameters>; pub type G2PreparedGadget = mnt6::G2PreparedGadget<Parameters>;
#[cfg(test)]
mod test {
use rand::Rng;
use super::{G1Gadget, G2Gadget};
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
use algebra::{mnt6_753::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
use r1cs_core::ConstraintSystem;
#[test]
fn mnt6_753_g1_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G1Projective = rng.gen();
let b: G1Projective = rng.gen();
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G1Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G1Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G1Gadget::cost_of_add());
}
#[test]
fn mnt6_753_g2_constraint_costs() {
use crate::boolean::AllocatedBit;
let mut cs = TestConstraintSystem::<Fq>::new();
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
.unwrap()
.into();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
let alloc_cost = cs.num_constraints();
let _ = G2Gadget::conditionally_select(
&mut cs.ns(|| "cond_select"),
&bit,
&gadget_a,
&gadget_b,
)
.unwrap();
let cond_select_cost = cs.num_constraints() - alloc_cost;
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
assert!(cs.is_satisfied());
assert_eq!(cond_select_cost, <G2Gadget as CondSelectGadget<Fq>>::cost());
assert_eq!(add_cost, G2Gadget::cost_of_add());
}
#[test]
fn mnt6_753_g1_gadget_test() {
use algebra::UniformRand;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
let mut cs = TestConstraintSystem::<Fq>::new();
let a = G1Projective::rand(&mut rng);
let b = G1Projective::rand(&mut rng);
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
// Check addition
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
let ab_val = gadget_ab
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
// Check doubling
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
let aa_val = gadget_a
.get_value()
.expect("Doubling should be successful")
.into_affine();
assert_eq!(
aa_val, aa_affine,
"Gadget and native values are unequal after double."
);
// Check mul_bits
let scalar = Fr::rand(&mut rng);
let native_result = aa.into_affine().mul(scalar) + &b;
let native_result = native_result.into_affine();
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
// Get the scalar bits into little-endian form.
scalar.reverse();
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
let result = gadget_a
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
.unwrap();
let result_val = result.get_value().unwrap().into_affine();
assert_eq!(
result_val, native_result,
"gadget & native values are diff. after scalar mul"
);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn mnt6_753_g2_gadget_test() {
let mut cs = TestConstraintSystem::<Fq>::new();
let mut rng = test_rng();
let a: G2Projective = rng.gen();
let b: G2Projective = rng.gen();
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
let ab = a + &b;
let ab_affine = ab.into_affine();
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
gadget_ba
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
.unwrap();
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
let aa = a.double();
let aa_affine = aa.into_affine();
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
if !cs.is_satisfied() {
println!("{:?}", cs.which_is_unsatisfied().unwrap());
}
assert!(cs.is_satisfied());
}
#[test]
fn test() {
use algebra::curves::models::mnt6::MNT6Parameters;
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as MNT6Parameters>::G1Parameters,
G1Gadget,
>();
crate::groups::curves::short_weierstrass::test::<
_,
<Parameters as MNT6Parameters>::G2Parameters,
G2Gadget,
>();
} }

+ 4
- 4
r1cs-std/src/test_constraint_counter.rs

@ -4,16 +4,16 @@ use r1cs_core::{ConstraintSystem, Index, LinearCombination, SynthesisError, Vari
/// Constraint counter for testing purposes. /// Constraint counter for testing purposes.
pub struct ConstraintCounter { pub struct ConstraintCounter {
pub num_inputs: usize,
pub num_aux: usize,
pub num_inputs: usize,
pub num_aux: usize,
pub num_constraints: usize, pub num_constraints: usize,
} }
impl ConstraintCounter { impl ConstraintCounter {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
num_aux: 0,
num_inputs: 0,
num_aux: 0,
num_inputs: 0,
num_constraints: 0, num_constraints: 0,
} }
} }

Loading…
Cancel
Save