From 5659b0d9ea99ea2cd78477c8c468125010d0ca08 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 8 Apr 2020 10:57:29 -0700 Subject: [PATCH 1/5] Fix CI to test more code in `no_std` --- r1cs-std/src/bits/uint64.rs | 50 ++++++++++++------------- r1cs-std/src/test_constraint_counter.rs | 8 ++-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/r1cs-std/src/bits/uint64.rs b/r1cs-std/src/bits/uint64.rs index b834479..babc1f1 100644 --- a/r1cs-std/src/bits/uint64.rs +++ b/r1cs-std/src/bits/uint64.rs @@ -14,7 +14,7 @@ use core::borrow::Borrow; #[derive(Clone, Debug)] pub struct UInt64 { // Least significant bit_gadget first - bits: Vec, + bits: Vec, value: Option, } @@ -56,7 +56,7 @@ impl UInt64 { } v - }, + } None => vec![None; 64], }; @@ -95,19 +95,19 @@ impl UInt64 { if b { value.as_mut().map(|v| *v |= 1); } - }, + } &Boolean::Is(ref b) => match b.get_value() { Some(true) => { value.as_mut().map(|v| *v |= 1); - }, - Some(false) => {}, + } + Some(false) => {} None => value = None, }, &Boolean::Not(ref b) => match b.get_value() { Some(false) => { value.as_mut().map(|v| *v |= 1); - }, - Some(true) => {}, + } + Some(true) => {} None => value = None, }, } @@ -129,7 +129,7 @@ impl UInt64 { .collect(); UInt64 { - bits: new_bits, + bits: new_bits, value: self.value.map(|v| v.rotate_right(by as u32)), } } @@ -194,12 +194,12 @@ impl UInt64 { match op.value { Some(val) => { result_value.as_mut().map(|v| *v += u128::from(val)); - }, + } None => { // If any of our operands have unknown value, we won't // know the value of the result result_value = None; - }, + } } // Iterate over each bit_gadget of the operand and add the operand to @@ -212,18 +212,18 @@ impl UInt64 { // Add coeff * bit_gadget lc += (coeff, bit.get_variable()); - }, + } Boolean::Not(ref bit) => { all_constants = false; // Add coeff * (1 - bit_gadget) = coeff * ONE - coeff * bit_gadget lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable()); - }, + } Boolean::Constant(bit) => { if bit { lc += (coeff, CS::one()); } - }, + } } coeff.double_in_place(); @@ -270,7 +270,7 @@ impl UInt64 { result_bits.truncate(64); Ok(UInt64 { - bits: result_bits, + bits: result_bits, value: modular_value, }) } @@ -330,7 +330,7 @@ impl ToBytesGadget for UInt64 { let mut bytes = Vec::new(); for (i, chunk8) in self.to_bits_le().chunks(8).enumerate() { let byte = UInt8 { - bits: chunk8.to_vec(), + bits: chunk8.to_vec(), value: value_chunks[i], }; bytes.push(byte); @@ -397,7 +397,7 @@ mod test { match bit_gadget { &Boolean::Constant(bit_gadget) => { assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1)); - }, + } _ => unreachable!(), } } @@ -406,8 +406,8 @@ mod test { for x in v.iter().zip(expected_to_be_same.iter()) { 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!(), } } @@ -442,13 +442,13 @@ mod test { match b { &Boolean::Is(ref b) => { assert!(b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Not(ref b) => { assert!(!b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Constant(b) => { assert!(b == (expected & 1 == 1)); - }, + } } expected >>= 1; @@ -483,7 +483,7 @@ mod test { &Boolean::Not(_) => panic!(), &Boolean::Constant(b) => { assert!(b == (expected & 1 == 1)); - }, + } } expected >>= 1; @@ -521,10 +521,10 @@ mod test { match b { &Boolean::Is(ref b) => { assert!(b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Not(ref b) => { assert!(!b.get_value().unwrap() == (expected & 1 == 1)); - }, + } &Boolean::Constant(_) => unreachable!(), } @@ -560,7 +560,7 @@ mod test { match b { &Boolean::Constant(b) => { assert_eq!(b, tmp & 1 == 1); - }, + } _ => unreachable!(), } diff --git a/r1cs-std/src/test_constraint_counter.rs b/r1cs-std/src/test_constraint_counter.rs index 0adf53e..359f71d 100644 --- a/r1cs-std/src/test_constraint_counter.rs +++ b/r1cs-std/src/test_constraint_counter.rs @@ -4,16 +4,16 @@ use r1cs_core::{ConstraintSystem, Index, LinearCombination, SynthesisError, Vari /// Constraint counter for testing purposes. pub struct ConstraintCounter { - pub num_inputs: usize, - pub num_aux: usize, + pub num_inputs: usize, + pub num_aux: usize, pub num_constraints: usize, } impl ConstraintCounter { pub fn new() -> Self { Self { - num_aux: 0, - num_inputs: 0, + num_aux: 0, + num_inputs: 0, num_constraints: 0, } } From d4a2d31d0790bc6e0ca35ec42cdb527f61220959 Mon Sep 17 00:00:00 2001 From: Pascal Berrang Date: Tue, 7 Apr 2020 09:35:19 +0200 Subject: [PATCH 2/5] Fix Vec imports for no_std --- .../src/commitment/blake2s/constraints.rs | 2 +- .../src/commitment/pedersen/constraints.rs | 1 + crypto-primitives/src/crh/bowe_hopwood/constraints.rs | 11 +++++++---- crypto-primitives/src/crh/pedersen/constraints.rs | 9 ++++++--- crypto-primitives/src/nizk/gm17/constraints.rs | 5 ++++- crypto-primitives/src/nizk/groth16/constraints.rs | 5 ++++- crypto-primitives/src/prf/blake2s/constraints.rs | 2 +- crypto-primitives/src/prf/constraints.rs | 2 +- .../src/signature/schnorr/constraints.rs | 1 + 9 files changed, 26 insertions(+), 12 deletions(-) diff --git a/crypto-primitives/src/commitment/blake2s/constraints.rs b/crypto-primitives/src/commitment/blake2s/constraints.rs index fd4c04e..660a2fd 100644 --- a/crypto-primitives/src/commitment/blake2s/constraints.rs +++ b/crypto-primitives/src/commitment/blake2s/constraints.rs @@ -3,7 +3,7 @@ use r1cs_core::{ConstraintSystem, SynthesisError}; use crate::{ commitment::blake2s::Blake2sCommitment, prf::blake2s::constraints::{blake2s_gadget, Blake2sOutputGadget}, - CommitmentGadget, + CommitmentGadget, Vec, }; use algebra_core::{Field, PrimeField}; use r1cs_std::prelude::*; diff --git a/crypto-primitives/src/commitment/pedersen/constraints.rs b/crypto-primitives/src/commitment/pedersen/constraints.rs index 3b591e8..ffa54b9 100644 --- a/crypto-primitives/src/commitment/pedersen/constraints.rs +++ b/crypto-primitives/src/commitment/pedersen/constraints.rs @@ -1,6 +1,7 @@ use crate::{ commitment::pedersen::{PedersenCommitment, PedersenParameters, PedersenRandomness}, crh::pedersen::PedersenWindow, + Vec, }; use algebra_core::{ fields::{Field, PrimeField}, diff --git a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs b/crypto-primitives/src/crh/bowe_hopwood/constraints.rs index 5a077ec..b16f1a3 100644 --- a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs +++ b/crypto-primitives/src/crh/bowe_hopwood/constraints.rs @@ -1,9 +1,12 @@ 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 r1cs_core::{ConstraintSystem, SynthesisError}; diff --git a/crypto-primitives/src/crh/pedersen/constraints.rs b/crypto-primitives/src/crh/pedersen/constraints.rs index 4404e2d..6048adc 100644 --- a/crypto-primitives/src/crh/pedersen/constraints.rs +++ b/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 r1cs_core::{ConstraintSystem, SynthesisError}; diff --git a/crypto-primitives/src/nizk/gm17/constraints.rs b/crypto-primitives/src/nizk/gm17/constraints.rs index dc95a8a..1604be0 100644 --- a/crypto-primitives/src/nizk/gm17/constraints.rs +++ b/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 r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError}; use r1cs_std::prelude::*; diff --git a/crypto-primitives/src/nizk/groth16/constraints.rs b/crypto-primitives/src/nizk/groth16/constraints.rs index e238185..71907dd 100644 --- a/crypto-primitives/src/nizk/groth16/constraints.rs +++ b/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 r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError}; use r1cs_std::prelude::*; diff --git a/crypto-primitives/src/prf/blake2s/constraints.rs b/crypto-primitives/src/prf/blake2s/constraints.rs index 7695f4c..cd1d3b2 100644 --- a/crypto-primitives/src/prf/blake2s/constraints.rs +++ b/crypto-primitives/src/prf/blake2s/constraints.rs @@ -1,7 +1,7 @@ use algebra_core::PrimeField; use r1cs_core::{ConstraintSystem, SynthesisError}; -use crate::prf::PRFGadget; +use crate::{prf::PRFGadget, Vec}; use r1cs_std::prelude::*; use core::borrow::Borrow; diff --git a/crypto-primitives/src/prf/constraints.rs b/crypto-primitives/src/prf/constraints.rs index ef2befa..69de337 100644 --- a/crypto-primitives/src/prf/constraints.rs +++ b/crypto-primitives/src/prf/constraints.rs @@ -1,7 +1,7 @@ use algebra_core::Field; use core::fmt::Debug; -use crate::prf::PRF; +use crate::{prf::PRF, Vec}; use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_std::prelude::*; diff --git a/crypto-primitives/src/signature/schnorr/constraints.rs b/crypto-primitives/src/signature/schnorr/constraints.rs index 5790659..f9d8ad8 100644 --- a/crypto-primitives/src/signature/schnorr/constraints.rs +++ b/crypto-primitives/src/signature/schnorr/constraints.rs @@ -1,3 +1,4 @@ +use crate::Vec; use algebra_core::{groups::Group, Field}; use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_std::prelude::*; From c486e15f0e1b96408e4eb4ebbcf4e9649d70fab3 Mon Sep 17 00:00:00 2001 From: Pascal Berrang Date: Thu, 9 Apr 2020 10:08:31 +0200 Subject: [PATCH 3/5] Add test cases for COFACTOR and generalize SW tests --- .../groups/curves/short_weierstrass/mod.rs | 110 ++++++++++ r1cs-std/src/instantiated/bls12_377/curves.rs | 201 ++---------------- r1cs-std/src/instantiated/mnt4_298/curves.rs | 201 ++---------------- r1cs-std/src/instantiated/mnt4_753/curves.rs | 201 ++---------------- r1cs-std/src/instantiated/mnt6_298/curves.rs | 201 ++---------------- r1cs-std/src/instantiated/mnt6_753/curves.rs | 201 ++---------------- 6 files changed, 175 insertions(+), 940 deletions(-) diff --git a/r1cs-std/src/groups/curves/short_weierstrass/mod.rs b/r1cs-std/src/groups/curves/short_weierstrass/mod.rs index 116e2d4..59f998a 100644 --- a/r1cs-std/src/groups/curves/short_weierstrass/mod.rs +++ b/r1cs-std/src/groups/curves/short_weierstrass/mod.rs @@ -661,3 +661,113 @@ where Ok(x_bytes) } } + +#[cfg(test)] +#[allow(dead_code)] +pub(crate) fn test() +where + ConstraintF: Field, + P: SWModelParameters, + GG: GroupGadget, ConstraintF, Value = SWProjective

>, +{ + 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::, GG>(); + + let mut rng = test_rng(); + + let mut cs = TestConstraintSystem::::new(); + + let a = SWProjective::

::rand(&mut rng); + let b = SWProjective::

::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 = BitIterator::new(scalar.into_repr()).collect(); + // Get the scalar bits into little-endian form. + scalar.reverse(); + let input = Vec::::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::::new(); + + let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true)) + .unwrap() + .into(); + + let mut rng = test_rng(); + let a: SWProjective

= rng.gen(); + let b: SWProjective

= 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, + >::cost() + ); + assert_eq!(add_cost, GG::cost_of_add()); +} diff --git a/r1cs-std/src/instantiated/bls12_377/curves.rs b/r1cs-std/src/instantiated/bls12_377/curves.rs index 3ff2ef0..139ad33 100644 --- a/r1cs-std/src/instantiated/bls12_377/curves.rs +++ b/r1cs-std/src/instantiated/bls12_377/curves.rs @@ -7,192 +7,17 @@ pub type G2Gadget = bls12::G2Gadget; pub type G1PreparedGadget = bls12::G1PreparedGadget; pub type G2PreparedGadget = bls12::G2PreparedGadget; -#[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::::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, >::cost()); - assert_eq!(add_cost, G1Gadget::cost_of_add()); - } - - #[test] - fn bls12_g2_constraint_costs() { - use crate::boolean::AllocatedBit; - - let mut cs = TestConstraintSystem::::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, >::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::::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 = BitIterator::new(scalar.into_repr()).collect(); - // Get the scalar bits into little-endian form. - scalar.reverse(); - let input = Vec::::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::::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::< + _, + ::G1Parameters, + G1Gadget, + >(); + crate::groups::curves::short_weierstrass::test::< + _, + ::G2Parameters, + G2Gadget, + >(); } diff --git a/r1cs-std/src/instantiated/mnt4_298/curves.rs b/r1cs-std/src/instantiated/mnt4_298/curves.rs index e89cc4b..ae0e775 100644 --- a/r1cs-std/src/instantiated/mnt4_298/curves.rs +++ b/r1cs-std/src/instantiated/mnt4_298/curves.rs @@ -7,192 +7,17 @@ pub type G2Gadget = mnt4::G2Gadget; pub type G1PreparedGadget = mnt4::G1PreparedGadget; pub type G2PreparedGadget = mnt4::G2PreparedGadget; -#[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::::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, >::cost()); - assert_eq!(add_cost, G1Gadget::cost_of_add()); - } - - #[test] - fn mnt4_298_g2_constraint_costs() { - use crate::boolean::AllocatedBit; - - let mut cs = TestConstraintSystem::::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, >::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::::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 = BitIterator::new(scalar.into_repr()).collect(); - // Get the scalar bits into little-endian form. - scalar.reverse(); - let input = Vec::::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::::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::< + _, + ::G1Parameters, + G1Gadget, + >(); + crate::groups::curves::short_weierstrass::test::< + _, + ::G2Parameters, + G2Gadget, + >(); } diff --git a/r1cs-std/src/instantiated/mnt4_753/curves.rs b/r1cs-std/src/instantiated/mnt4_753/curves.rs index 347360d..0927e52 100644 --- a/r1cs-std/src/instantiated/mnt4_753/curves.rs +++ b/r1cs-std/src/instantiated/mnt4_753/curves.rs @@ -7,192 +7,17 @@ pub type G2Gadget = mnt4::G2Gadget; pub type G1PreparedGadget = mnt4::G1PreparedGadget; pub type G2PreparedGadget = mnt4::G2PreparedGadget; -#[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::::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, >::cost()); - assert_eq!(add_cost, G1Gadget::cost_of_add()); - } - - #[test] - fn mnt4_753_g2_constraint_costs() { - use crate::boolean::AllocatedBit; - - let mut cs = TestConstraintSystem::::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, >::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::::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 = BitIterator::new(scalar.into_repr()).collect(); - // Get the scalar bits into little-endian form. - scalar.reverse(); - let input = Vec::::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::::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::< + _, + ::G1Parameters, + G1Gadget, + >(); + crate::groups::curves::short_weierstrass::test::< + _, + ::G2Parameters, + G2Gadget, + >(); } diff --git a/r1cs-std/src/instantiated/mnt6_298/curves.rs b/r1cs-std/src/instantiated/mnt6_298/curves.rs index 841c754..c92acce 100644 --- a/r1cs-std/src/instantiated/mnt6_298/curves.rs +++ b/r1cs-std/src/instantiated/mnt6_298/curves.rs @@ -7,192 +7,17 @@ pub type G2Gadget = mnt6::G2Gadget; pub type G1PreparedGadget = mnt6::G1PreparedGadget; pub type G2PreparedGadget = mnt6::G2PreparedGadget; -#[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::::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, >::cost()); - assert_eq!(add_cost, G1Gadget::cost_of_add()); - } - - #[test] - fn mnt6_298_g2_constraint_costs() { - use crate::boolean::AllocatedBit; - - let mut cs = TestConstraintSystem::::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, >::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::::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 = BitIterator::new(scalar.into_repr()).collect(); - // Get the scalar bits into little-endian form. - scalar.reverse(); - let input = Vec::::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::::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::< + _, + ::G1Parameters, + G1Gadget, + >(); + crate::groups::curves::short_weierstrass::test::< + _, + ::G2Parameters, + G2Gadget, + >(); } diff --git a/r1cs-std/src/instantiated/mnt6_753/curves.rs b/r1cs-std/src/instantiated/mnt6_753/curves.rs index a085b88..f41c22a 100644 --- a/r1cs-std/src/instantiated/mnt6_753/curves.rs +++ b/r1cs-std/src/instantiated/mnt6_753/curves.rs @@ -7,192 +7,17 @@ pub type G2Gadget = mnt6::G2Gadget; pub type G1PreparedGadget = mnt6::G1PreparedGadget; pub type G2PreparedGadget = mnt6::G2PreparedGadget; -#[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::::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, >::cost()); - assert_eq!(add_cost, G1Gadget::cost_of_add()); - } - - #[test] - fn mnt6_753_g2_constraint_costs() { - use crate::boolean::AllocatedBit; - - let mut cs = TestConstraintSystem::::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, >::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::::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 = BitIterator::new(scalar.into_repr()).collect(); - // Get the scalar bits into little-endian form. - scalar.reverse(); - let input = Vec::::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::::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::< + _, + ::G1Parameters, + G1Gadget, + >(); + crate::groups::curves::short_weierstrass::test::< + _, + ::G2Parameters, + G2Gadget, + >(); } From 5cc094be6b29e11acb718edbfdc2c67dc287fabf Mon Sep 17 00:00:00 2001 From: Kobi Gurkan Date: Sun, 19 Apr 2020 02:03:33 +0300 Subject: [PATCH 4/5] Adds alloc_constant to AllocGadget (#189) * adds alloc constant to AllocGadget * fmt * fmt * more alloc constant impls * fmt * even more impls * fixes type * fixes alloc_constant in gm17 * uses alloc_constant from field gadget in group gadgets * fmt * handle most comments --- .../src/commitment/blake2s/constraints.rs | 26 ++++++++ .../src/commitment/pedersen/constraints.rs | 35 +++++++++-- .../src/crh/bowe_hopwood/constraints.rs | 19 ++++-- .../src/crh/pedersen/constraints.rs | 19 ++++-- .../src/merkle_tree/constraints.rs | 22 +++++++ .../src/nizk/gm17/constraints.rs | 63 +++++++++++++++++++ .../src/nizk/groth16/constraints.rs | 59 +++++++++++++++++ .../src/prf/blake2s/constraints.rs | 16 +++++ .../src/signature/schnorr/constraints.rs | 30 +++++++++ r1cs-std/src/alloc.rs | 22 +++++++ r1cs-std/src/bits/boolean.rs | 20 ++++++ r1cs-std/src/bits/uint64.rs | 10 +++ r1cs-std/src/bits/uint8.rs | 10 +++ r1cs-std/src/fields/fp/mod.rs | 12 ++++ r1cs-std/src/fields/fp12.rs | 11 ++++ r1cs-std/src/fields/fp2.rs | 11 ++++ r1cs-std/src/fields/fp3.rs | 11 ++++ r1cs-std/src/fields/fp4.rs | 11 ++++ r1cs-std/src/fields/fp6_2over3.rs | 11 ++++ r1cs-std/src/fields/fp6_3over2.rs | 11 ++++ .../groups/curves/short_weierstrass/mod.rs | 18 ++++++ .../src/groups/curves/twisted_edwards/mod.rs | 34 ++++++++++ 22 files changed, 468 insertions(+), 13 deletions(-) diff --git a/crypto-primitives/src/commitment/blake2s/constraints.rs b/crypto-primitives/src/commitment/blake2s/constraints.rs index 660a2fd..1fbeff5 100644 --- a/crypto-primitives/src/commitment/blake2s/constraints.rs +++ b/crypto-primitives/src/commitment/blake2s/constraints.rs @@ -48,6 +48,16 @@ impl CommitmentGadget } impl AllocGadget<(), ConstraintF> for Blake2sParametersGadget { + fn alloc_constant>( + cs: CS, + val: T, + ) -> Result + where + T: Borrow<()>, + { + Self::alloc(cs, || Ok(val)) + } + fn alloc>(_: CS, _: F) -> Result where F: FnOnce() -> Result, @@ -69,6 +79,22 @@ impl AllocGadget<(), ConstraintF> for Blake2sParametersGadge } impl AllocGadget<[u8; 32], ConstraintF> for Blake2sRandomnessGadget { + #[inline] + fn alloc_constant>( + mut cs: CS, + val: T, + ) -> Result + 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] fn alloc>( cs: CS, diff --git a/crypto-primitives/src/commitment/pedersen/constraints.rs b/crypto-primitives/src/commitment/pedersen/constraints.rs index ffa54b9..f408b9c 100644 --- a/crypto-primitives/src/commitment/pedersen/constraints.rs +++ b/crypto-primitives/src/commitment/pedersen/constraints.rs @@ -98,16 +98,14 @@ where W: PedersenWindow, ConstraintF: PrimeField, { - fn alloc>( + fn alloc_constant>( _cs: CS, - value_gen: F, + val: T, ) -> Result where - F: FnOnce() -> Result, T: Borrow>, { - let temp = value_gen()?; - let parameters = temp.borrow().clone(); + let parameters = val.borrow().clone(); Ok(PedersenCommitmentGadgetParameters { params: parameters, @@ -117,6 +115,18 @@ where }) } + fn alloc>( + cs: CS, + value_gen: F, + ) -> Result + where + F: FnOnce() -> Result, + T: Borrow>, + { + let temp = value_gen()?; + Self::alloc_constant(cs, temp) + } + fn alloc_input>( _cs: CS, value_gen: F, @@ -142,6 +152,21 @@ where G: Group, ConstraintF: PrimeField, { + fn alloc_constant>( + mut cs: CS, + val: T, + ) -> Result + where + T: Borrow>, + { + 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>( cs: CS, value_gen: F, diff --git a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs b/crypto-primitives/src/crh/bowe_hopwood/constraints.rs index b16f1a3..5afc543 100644 --- a/crypto-primitives/src/crh/bowe_hopwood/constraints.rs +++ b/crypto-primitives/src/crh/bowe_hopwood/constraints.rs @@ -89,15 +89,14 @@ impl, ConstraintF> for BoweHopwoodPedersenCRHGadgetParameters { - fn alloc>( + fn alloc_constant>( _cs: CS, - value_gen: F, + val: T, ) -> Result where - F: FnOnce() -> Result, T: Borrow>, { - let params = value_gen()?.borrow().clone(); + let params = val.borrow().clone(); Ok(BoweHopwoodPedersenCRHGadgetParameters { params, _group_g: PhantomData, @@ -106,6 +105,18 @@ impl>( + cs: CS, + value_gen: F, + ) -> Result + where + F: FnOnce() -> Result, + T: Borrow>, + { + let params = value_gen()?.borrow().clone(); + Self::alloc_constant(cs, params) + } + fn alloc_input>( _cs: CS, value_gen: F, diff --git a/crypto-primitives/src/crh/pedersen/constraints.rs b/crypto-primitives/src/crh/pedersen/constraints.rs index 6048adc..bb3f6a2 100644 --- a/crypto-primitives/src/crh/pedersen/constraints.rs +++ b/crypto-primitives/src/crh/pedersen/constraints.rs @@ -80,15 +80,14 @@ impl, ConstraintF> for PedersenCRHGadgetParameters { - fn alloc>( + fn alloc_constant>( _cs: CS, - value_gen: F, + val: T, ) -> Result where - F: FnOnce() -> Result, T: Borrow>, { - let params = value_gen()?.borrow().clone(); + let params = val.borrow().clone(); Ok(PedersenCRHGadgetParameters { params, _group_g: PhantomData, @@ -97,6 +96,18 @@ impl>( + cs: CS, + value_gen: F, + ) -> Result + where + F: FnOnce() -> Result, + T: Borrow>, + { + let params = value_gen()?.borrow().clone(); + Self::alloc_constant(cs, params) + } + fn alloc_input>( _cs: CS, value_gen: F, diff --git a/crypto-primitives/src/merkle_tree/constraints.rs b/crypto-primitives/src/merkle_tree/constraints.rs index 5136c40..58b242e 100644 --- a/crypto-primitives/src/merkle_tree/constraints.rs +++ b/crypto-primitives/src/merkle_tree/constraints.rs @@ -128,6 +128,28 @@ where HGadget: FixedLengthCRHGadget, ConstraintF: Field, { + fn alloc_constant>( + mut cs: CS, + val: T, + ) -> Result + where + T: Borrow>, + { + 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>( mut cs: CS, value_gen: F, diff --git a/crypto-primitives/src/nizk/gm17/constraints.rs b/crypto-primitives/src/nizk/gm17/constraints.rs index 1604be0..6e9b523 100644 --- a/crypto-primitives/src/nizk/gm17/constraints.rs +++ b/crypto-primitives/src/nizk/gm17/constraints.rs @@ -202,6 +202,54 @@ where ConstraintF: Field, P: PairingGadget, { + #[inline] + fn alloc_constant>( + mut cs: CS, + val: T, + ) -> Result + where + T: Borrow>, + { + 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::>() + .into_iter() + .collect::>()?; + Ok(Self { + h_g2, + g_alpha_g1, + h_beta_g2, + g_gamma_g1, + h_gamma_g2, + query, + }) + } + #[inline] fn alloc>( mut cs: CS, @@ -312,6 +360,21 @@ where ConstraintF: Field, P: PairingGadget, { + #[inline] + fn alloc_constant>( + mut cs: CS, + val: T, + ) -> Result + where + T: Borrow>, + { + 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] fn alloc>( mut cs: CS, diff --git a/crypto-primitives/src/nizk/groth16/constraints.rs b/crypto-primitives/src/nizk/groth16/constraints.rs index 71907dd..9b8144c 100644 --- a/crypto-primitives/src/nizk/groth16/constraints.rs +++ b/crypto-primitives/src/nizk/groth16/constraints.rs @@ -173,6 +173,50 @@ where ConstraintF: Field, P: PairingGadget, { + #[inline] + fn alloc_constant>( + mut cs: CS, + val: T, + ) -> Result + where + T: Borrow>, + { + 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::>() + .into_iter() + .collect::>()?; + Ok(Self { + alpha_g1, + beta_g2, + gamma_g2, + delta_g2, + gamma_abc_g1, + }) + } + #[inline] fn alloc>( mut cs: CS, @@ -276,6 +320,21 @@ where ConstraintF: Field, P: PairingGadget, { + #[inline] + fn alloc_constant>( + mut cs: CS, + val: T, + ) -> Result + where + T: Borrow>, + { + 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] fn alloc>( mut cs: CS, diff --git a/crypto-primitives/src/prf/blake2s/constraints.rs b/crypto-primitives/src/prf/blake2s/constraints.rs index cd1d3b2..68576eb 100644 --- a/crypto-primitives/src/prf/blake2s/constraints.rs +++ b/crypto-primitives/src/prf/blake2s/constraints.rs @@ -450,6 +450,22 @@ impl ToBytesGadget for Blake2sOutputGadget } impl AllocGadget<[u8; 32], ConstraintF> for Blake2sOutputGadget { + #[inline] + fn alloc_constant>( + mut cs: CS, + val: T, + ) -> Result + 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] fn alloc>( cs: CS, diff --git a/crypto-primitives/src/signature/schnorr/constraints.rs b/crypto-primitives/src/signature/schnorr/constraints.rs index f9d8ad8..f3395dc 100644 --- a/crypto-primitives/src/signature/schnorr/constraints.rs +++ b/crypto-primitives/src/signature/schnorr/constraints.rs @@ -96,6 +96,21 @@ where GG: GroupGadget, D: Digest, { + fn alloc_constant>( + cs: CS, + val: T, + ) -> Result + where + T: Borrow>, + { + let generator = GG::alloc_constant(cs, val.borrow().generator)?; + Ok(Self { + generator, + _engine: PhantomData, + _group: PhantomData, + }) + } + fn alloc>(cs: CS, f: F) -> Result where F: FnOnce() -> Result, @@ -133,6 +148,21 @@ where ConstraintF: Field, GG: GroupGadget, { + fn alloc_constant>( + cs: CS, + val: T, + ) -> Result + where + T: Borrow>, + { + let pub_key = GG::alloc_constant(cs, val.borrow())?; + Ok(Self { + pub_key, + _engine: PhantomData, + _group: PhantomData, + }) + } + fn alloc>(cs: CS, f: F) -> Result where F: FnOnce() -> Result, diff --git a/r1cs-std/src/alloc.rs b/r1cs-std/src/alloc.rs index 139820e..47a43f9 100644 --- a/r1cs-std/src/alloc.rs +++ b/r1cs-std/src/alloc.rs @@ -8,6 +8,13 @@ where Self: Sized, V: ?Sized, { + fn alloc_constant>( + cs: CS, + t: T, + ) -> Result + where + T: Borrow; + fn alloc>(cs: CS, f: F) -> Result where F: FnOnce() -> Result, @@ -47,6 +54,21 @@ where impl> AllocGadget<[I], ConstraintF> for Vec { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + 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>( mut cs: CS, f: F, diff --git a/r1cs-std/src/bits/boolean.rs b/r1cs-std/src/bits/boolean.rs index b696055..23a205f 100644 --- a/r1cs-std/src/bits/boolean.rs +++ b/r1cs-std/src/bits/boolean.rs @@ -235,6 +235,16 @@ impl PartialEq for AllocatedBit { impl Eq for AllocatedBit {} impl AllocGadget for AllocatedBit { + fn alloc_constant>( + _cs: CS, + _t: T, + ) -> Result + where + T: Borrow, + { + unimplemented!(); + } + fn alloc>( mut cs: CS, value_gen: F, @@ -715,6 +725,16 @@ impl From for Boolean { } impl AllocGadget for Boolean { + fn alloc_constant>( + _cs: CS, + t: T, + ) -> Result + where + T: Borrow, + { + Ok(Boolean::constant(*t.borrow())) + } + fn alloc>( cs: CS, value_gen: F, diff --git a/r1cs-std/src/bits/uint64.rs b/r1cs-std/src/bits/uint64.rs index babc1f1..67698d8 100644 --- a/r1cs-std/src/bits/uint64.rs +++ b/r1cs-std/src/bits/uint64.rs @@ -277,6 +277,16 @@ impl UInt64 { } impl AllocGadget for UInt64 { + fn alloc_constant>( + _cs: CS, + t: T, + ) -> Result + where + T: Borrow, + { + Ok(UInt64::constant(*t.borrow())) + } + fn alloc>( mut cs: CS, value_gen: F, diff --git a/r1cs-std/src/bits/uint8.rs b/r1cs-std/src/bits/uint8.rs index 6cb67e0..3783cca 100644 --- a/r1cs-std/src/bits/uint8.rs +++ b/r1cs-std/src/bits/uint8.rs @@ -214,6 +214,16 @@ impl ConditionalEqGadget for UInt8 { impl EqGadget for UInt8 {} impl AllocGadget for UInt8 { + fn alloc_constant>( + _cs: CS, + t: T, + ) -> Result + where + T: Borrow, + { + Ok(UInt8::constant(*t.borrow())) + } + fn alloc>( mut cs: CS, value_gen: F, diff --git a/r1cs-std/src/fields/fp/mod.rs b/r1cs-std/src/fields/fp/mod.rs index 2f8c937..6648864 100644 --- a/r1cs-std/src/fields/fp/mod.rs +++ b/r1cs-std/src/fields/fp/mod.rs @@ -584,6 +584,18 @@ impl Clone for FpGadget { } impl AllocGadget for FpGadget { + #[inline] + fn alloc_constant>(_cs: CS, t: T) -> Result + where + T: Borrow, + { + let value = t.borrow().clone(); + Ok(Self { + value: Some(value), + variable: LinearCombination::from((value, CS::one())).into(), + }) + } + #[inline] fn alloc>( mut cs: CS, diff --git a/r1cs-std/src/fields/fp12.rs b/r1cs-std/src/fields/fp12.rs index 7131676..4ead2b5 100644 --- a/r1cs-std/src/fields/fp12.rs +++ b/r1cs-std/src/fields/fp12.rs @@ -834,6 +834,17 @@ where P: Fp12Parameters, ::Fp2Params: Fp2Parameters, { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + where + T: Borrow>, + { + Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow()) + } + #[inline] fn alloc>( mut cs: CS, diff --git a/r1cs-std/src/fields/fp2.rs b/r1cs-std/src/fields/fp2.rs index 5dbc369..476ecc5 100644 --- a/r1cs-std/src/fields/fp2.rs +++ b/r1cs-std/src/fields/fp2.rs @@ -611,6 +611,17 @@ impl, ConstraintF: PrimeField> impl, ConstraintF: PrimeField> AllocGadget, ConstraintF> for Fp2Gadget { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + where + T: Borrow>, + { + Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow()) + } + #[inline] fn alloc>( mut cs: CS, diff --git a/r1cs-std/src/fields/fp3.rs b/r1cs-std/src/fields/fp3.rs index 39c6006..6ab72c7 100644 --- a/r1cs-std/src/fields/fp3.rs +++ b/r1cs-std/src/fields/fp3.rs @@ -867,6 +867,17 @@ impl, ConstraintF: PrimeField + SquareRootFie impl, ConstraintF: PrimeField + SquareRootField> AllocGadget, ConstraintF> for Fp3Gadget { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + where + T: Borrow>, + { + Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow()) + } + #[inline] fn alloc>( mut cs: CS, diff --git a/r1cs-std/src/fields/fp4.rs b/r1cs-std/src/fields/fp4.rs index 8c05cb7..91c0da6 100644 --- a/r1cs-std/src/fields/fp4.rs +++ b/r1cs-std/src/fields/fp4.rs @@ -673,6 +673,17 @@ where P: Fp4Parameters, P::Fp2Params: Fp2Parameters, { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + where + T: Borrow>, + { + Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow()) + } + #[inline] fn alloc>( mut cs: CS, diff --git a/r1cs-std/src/fields/fp6_2over3.rs b/r1cs-std/src/fields/fp6_2over3.rs index 29ec485..5c4a79a 100644 --- a/r1cs-std/src/fields/fp6_2over3.rs +++ b/r1cs-std/src/fields/fp6_2over3.rs @@ -664,6 +664,17 @@ where P: Fp6Parameters, P::Fp3Params: Fp3Parameters, { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + where + T: Borrow>, + { + Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow()) + } + #[inline] fn alloc>( mut cs: CS, diff --git a/r1cs-std/src/fields/fp6_3over2.rs b/r1cs-std/src/fields/fp6_3over2.rs index a7f3b49..f4b25e7 100644 --- a/r1cs-std/src/fields/fp6_3over2.rs +++ b/r1cs-std/src/fields/fp6_3over2.rs @@ -964,6 +964,17 @@ where P: Fp6Parameters, P::Fp2Params: Fp2Parameters, { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + where + T: Borrow>, + { + Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow()) + } + #[inline] fn alloc>( mut cs: CS, diff --git a/r1cs-std/src/groups/curves/short_weierstrass/mod.rs b/r1cs-std/src/groups/curves/short_weierstrass/mod.rs index 59f998a..4c2e725 100644 --- a/r1cs-std/src/groups/curves/short_weierstrass/mod.rs +++ b/r1cs-std/src/groups/curves/short_weierstrass/mod.rs @@ -437,6 +437,24 @@ where ConstraintF: PrimeField, F: FieldGadget, { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + where + T: Borrow>, + { + 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] fn alloc>( mut cs: CS, diff --git a/r1cs-std/src/groups/curves/twisted_edwards/mod.rs b/r1cs-std/src/groups/curves/twisted_edwards/mod.rs index ed071b8..e926ddf 100644 --- a/r1cs-std/src/groups/curves/twisted_edwards/mod.rs +++ b/r1cs-std/src/groups/curves/twisted_edwards/mod.rs @@ -492,6 +492,23 @@ mod affine_impl { F: FieldGadget, Self: GroupGadget, ConstraintF>, { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + where + T: Borrow>, + { + 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>( mut cs: CS, value_gen: FN, @@ -1089,6 +1106,23 @@ mod projective_impl { F: FieldGadget, Self: GroupGadget, ConstraintF>, { + #[inline] + fn alloc_constant>( + mut cs: CS, + t: T, + ) -> Result + where + T: Borrow>, + { + 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>( mut cs: CS, value_gen: FN, From bbb7d75ec8d338e40f7e69f809fa8c5cba31afe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Fran=C3=A7a?= <43445067+brunoffranca@users.noreply.github.com> Date: Wed, 22 Apr 2020 21:30:33 +0100 Subject: [PATCH 5/5] Implement `conditional_check_verify` for `NIZK`s (#195) * Implement `ToBitsGadget` for `UInt8` and `Vec` * Add `kary_or` function to `Boolean`. --- crypto-primitives/src/nizk/constraints.rs | 12 +++++++++ .../src/nizk/gm17/constraints.rs | 25 +++++++++++++++++-- crypto-primitives/src/nizk/gm17/mod.rs | 2 +- .../src/nizk/groth16/constraints.rs | 23 ++++++++++++++++- crypto-primitives/src/nizk/groth16/mod.rs | 2 +- r1cs-std/src/bits/boolean.rs | 16 ++++++++++++ r1cs-std/src/bits/mod.rs | 22 ++++++++++++++++ 7 files changed, 97 insertions(+), 5 deletions(-) diff --git a/crypto-primitives/src/nizk/constraints.rs b/crypto-primitives/src/nizk/constraints.rs index da75548..61c4cb6 100644 --- a/crypto-primitives/src/nizk/constraints.rs +++ b/crypto-primitives/src/nizk/constraints.rs @@ -20,4 +20,16 @@ pub trait NIZKVerifierGadget { CS: ConstraintSystem, I: Iterator, T: 'a + ToBitsGadget + ?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, + I: Iterator, + T: 'a + ToBitsGadget + ?Sized; } diff --git a/crypto-primitives/src/nizk/gm17/constraints.rs b/crypto-primitives/src/nizk/gm17/constraints.rs index 6e9b523..6f09608 100644 --- a/crypto-primitives/src/nizk/gm17/constraints.rs +++ b/crypto-primitives/src/nizk/gm17/constraints.rs @@ -109,10 +109,31 @@ where type ProofGadget = ProofGadget; fn check_verify<'a, CS, I, T>( + cs: CS, + vk: &Self::VerificationKeyGadget, + public_inputs: I, + proof: &Self::ProofGadget, + ) -> Result<(), SynthesisError> + where + CS: ConstraintSystem, + I: Iterator, + T: 'a + ToBitsGadget + ?Sized, + { + , ConstraintF>>::conditional_check_verify( + cs, + vk, + public_inputs, + proof, + &Boolean::constant(true), + ) + } + + fn conditional_check_verify<'a, CS, I, T>( mut cs: CS, vk: &Self::VerificationKeyGadget, mut public_inputs: I, proof: &Self::ProofGadget, + condition: &Boolean, ) -> Result<(), SynthesisError> where CS: ConstraintSystem, @@ -189,8 +210,8 @@ where let test2 = P::final_exponentiation(cs.ns(|| "Final Exp 2"), &test2_exp)?; 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(()) } } diff --git a/crypto-primitives/src/nizk/gm17/mod.rs b/crypto-primitives/src/nizk/gm17/mod.rs index 82c312c..290add9 100644 --- a/crypto-primitives/src/nizk/gm17/mod.rs +++ b/crypto-primitives/src/nizk/gm17/mod.rs @@ -35,10 +35,10 @@ impl, V: ToConstraintField; type VerificationParameters = VerifyingKey; type PreparedVerificationParameters = PreparedVerifyingKey; - type VerifierInput = V; type Proof = Proof; fn setup( diff --git a/crypto-primitives/src/nizk/groth16/constraints.rs b/crypto-primitives/src/nizk/groth16/constraints.rs index 9b8144c..49e07d7 100644 --- a/crypto-primitives/src/nizk/groth16/constraints.rs +++ b/crypto-primitives/src/nizk/groth16/constraints.rs @@ -110,10 +110,31 @@ where type ProofGadget = ProofGadget; fn check_verify<'a, CS, I, T>( + cs: CS, + vk: &Self::VerificationKeyGadget, + public_inputs: I, + proof: &Self::ProofGadget, + ) -> Result<(), SynthesisError> + where + CS: ConstraintSystem, + I: Iterator, + T: 'a + ToBitsGadget + ?Sized, + { + , ConstraintF>>::conditional_check_verify( + cs, + vk, + public_inputs, + proof, + &Boolean::constant(true), + ) + } + + fn conditional_check_verify<'a, CS, I, T>( mut cs: CS, vk: &Self::VerificationKeyGadget, mut public_inputs: I, proof: &Self::ProofGadget, + condition: &Boolean, ) -> Result<(), SynthesisError> where CS: ConstraintSystem, @@ -161,7 +182,7 @@ where 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(()) } } diff --git a/crypto-primitives/src/nizk/groth16/mod.rs b/crypto-primitives/src/nizk/groth16/mod.rs index 44faec9..c4d6f05 100644 --- a/crypto-primitives/src/nizk/groth16/mod.rs +++ b/crypto-primitives/src/nizk/groth16/mod.rs @@ -35,10 +35,10 @@ impl, V: ToConstraintField; type VerificationParameters = VerifyingKey; type PreparedVerificationParameters = PreparedVerifyingKey; - type VerifierInput = V; type Proof = Proof; fn setup( diff --git a/r1cs-std/src/bits/boolean.rs b/r1cs-std/src/bits/boolean.rs index 23a205f..70759d1 100644 --- a/r1cs-std/src/bits/boolean.rs +++ b/r1cs-std/src/bits/boolean.rs @@ -549,6 +549,22 @@ impl Boolean { Ok(cur) } + pub fn kary_or(mut cs: CS, bits: &[Self]) -> Result + where + ConstraintF: Field, + CS: ConstraintSystem, + { + 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. pub fn enforce_nand(mut cs: CS, bits: &[Self]) -> Result<(), SynthesisError> where diff --git a/r1cs-std/src/bits/mod.rs b/r1cs-std/src/bits/mod.rs index 3829d8b..6bb4747 100644 --- a/r1cs-std/src/bits/mod.rs +++ b/r1cs-std/src/bits/mod.rs @@ -58,6 +58,15 @@ impl ToBitsGadget for Vec { } } +impl ToBitsGadget for UInt8 { + fn to_bits>( + &self, + _cs: CS, + ) -> Result, SynthesisError> { + Ok(self.into_bits_le()) + } +} + impl ToBitsGadget for [UInt8] { fn to_bits>( &self, @@ -71,6 +80,19 @@ impl ToBitsGadget for [UInt8] { } } +impl ToBitsGadget for Vec { + fn to_bits>( + &self, + _cs: CS, + ) -> Result, 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 { /// Outputs a canonical byte-wise representation of `self`. ///