diff --git a/curve-constraint-tests/src/lib.rs b/curve-constraint-tests/src/lib.rs index abd3b6e..ba7e6bc 100644 --- a/curve-constraint-tests/src/lib.rs +++ b/curve-constraint-tests/src/lib.rs @@ -1,4 +1,3 @@ -#![no_std] #![macro_use] extern crate ark_relations; @@ -20,176 +19,187 @@ pub mod fields { AF: TwoBitLookupGadget, for<'a> &'a AF: FieldOpsBounds<'a, F, AF>, { - let cs = ConstraintSystem::::new_ref(); - - let mut rng = test_rng(); - let a_native = F::rand(&mut rng); - let b_native = F::rand(&mut rng); - let a = AF::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native))?; - let b = AF::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native))?; - let b_const = AF::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; - - let zero = AF::zero(); - let zero_native = zero.value()?; - zero.enforce_equal(&zero)?; - - let one = AF::one(); - let one_native = one.value()?; - one.enforce_equal(&one)?; - - one.enforce_not_equal(&zero)?; - - let one_dup = &zero + &one; - one_dup.enforce_equal(&one)?; - - let two = &one + &one; - two.enforce_equal(&two)?; - two.enforce_equal(&one.double()?)?; - two.enforce_not_equal(&one)?; - two.enforce_not_equal(&zero)?; - - // a + 0 = a - let a_plus_zero = &a + &zero; - assert_eq!(a_plus_zero.value()?, a_native); - a_plus_zero.enforce_equal(&a)?; - a_plus_zero.enforce_not_equal(&a.double()?)?; - - // a - 0 = a - let a_minus_zero = &a - &zero; - assert_eq!(a_minus_zero.value()?, a_native); - a_minus_zero.enforce_equal(&a)?; - - // a - a = 0 - let a_minus_a = &a - &a; - assert_eq!(a_minus_a.value()?, zero_native); - a_minus_a.enforce_equal(&zero)?; - - // a + b = b + a - let a_b = &a + &b; - let b_a = &b + &a; - assert_eq!(a_b.value()?, a_native + &b_native); - a_b.enforce_equal(&b_a)?; - - // (a + b) + a = a + (b + a) - let ab_a = &a_b + &a; - let a_ba = &a + &b_a; - assert_eq!(ab_a.value()?, a_native + &b_native + &a_native); - ab_a.enforce_equal(&a_ba)?; - - let b_times_a_plus_b = &a_b * &b; - let b_times_b_plus_a = &b_a * &b; - assert_eq!( - b_times_a_plus_b.value()?, - b_native * &(b_native + &a_native) - ); - assert_eq!( - b_times_a_plus_b.value()?, - (b_native + &a_native) * &b_native - ); - assert_eq!( - b_times_a_plus_b.value()?, - (a_native + &b_native) * &b_native - ); - b_times_b_plus_a.enforce_equal(&b_times_a_plus_b)?; - - // a * 1 = a - assert_eq!((&a * &one).value()?, a_native * &one_native); - - // a * b = b * a - let ab = &a * &b; - let ba = &b * &a; - assert_eq!(ab.value()?, ba.value()?); - assert_eq!(ab.value()?, a_native * &b_native); - - let ab_const = &a * &b_const; - let b_const_a = &b_const * &a; - assert_eq!(ab_const.value()?, b_const_a.value()?); - assert_eq!(ab_const.value()?, ab.value()?); - assert_eq!(ab_const.value()?, a_native * &b_native); - - // (a * b) * a = a * (b * a) - let ab_a = &ab * &a; - let a_ba = &a * &ba; - assert_eq!(ab_a.value()?, a_ba.value()?); - assert_eq!(ab_a.value()?, a_native * &b_native * &a_native); - - let aa = &a * &a; - let a_squared = a.square()?; - a_squared.enforce_equal(&aa)?; - assert_eq!(aa.value()?, a_squared.value()?); - assert_eq!(aa.value()?, a_native.square()); - - let aa = &a * a.value()?; - a_squared.enforce_equal(&aa)?; - assert_eq!(aa.value()?, a_squared.value()?); - assert_eq!(aa.value()?, a_native.square()); - - let a_b2 = &a + b_native; - a_b.enforce_equal(&a_b2)?; - assert_eq!(a_b.value()?, a_b2.value()?); - - let a_inv = a.inverse()?; - a_inv.mul_equals(&a, &one)?; - assert_eq!(a_inv.value()?, a.value()?.inverse().unwrap()); - assert_eq!(a_inv.value()?, a_native.inverse().unwrap()); - - let a_b_inv = a.mul_by_inverse(&b)?; - a_b_inv.mul_equals(&b, &a)?; - assert_eq!(a_b_inv.value()?, a_native * b_native.inverse().unwrap()); - - // a * a * a = a^3 - let bits = BitIteratorLE::without_trailing_zeros([3u64]) - .map(Boolean::constant) - .collect::>(); - assert_eq!(a_native.pow([0x3]), a.pow_le(&bits)?.value()?); - - // a * a * a = a^3 - assert_eq!(a_native.pow([0x3]), a.pow_by_constant(&[0x3])?.value()?); - assert!(cs.is_satisfied().unwrap()); - - // a * a * a = a^3 - let mut constants = [F::zero(); 4]; - for c in &mut constants { - *c = UniformRand::rand(&mut test_rng()); - } - let bits = [ - Boolean::::constant(false), - Boolean::constant(true), + let modes = [ + AllocationMode::Input, + AllocationMode::Witness, + AllocationMode::Constant, ]; - let lookup_result = AF::two_bit_lookup(&bits, constants.as_ref())?; - assert_eq!(lookup_result.value()?, constants[2]); - assert!(cs.is_satisfied().unwrap()); - - let f = F::from(1u128 << 64); - let f_bits = ark_ff::BitIteratorLE::new(&[0u64, 1u64]).collect::>(); - let fv = AF::new_witness(ark_relations::ns!(cs, "alloc u128"), || Ok(f))?; - assert_eq!(fv.to_bits_le()?.value().unwrap()[..128], f_bits[..128]); - assert!(cs.is_satisfied().unwrap()); - - let r_native: F = UniformRand::rand(&mut test_rng()); - - let r = AF::new_witness(ark_relations::ns!(cs, "r_native"), || Ok(r_native)).unwrap(); - let _ = r.to_non_unique_bits_le()?; - assert!(cs.is_satisfied().unwrap()); - let _ = r.to_bits_le()?; - assert!(cs.is_satisfied().unwrap()); - - let bytes = r.to_non_unique_bytes()?; - assert_eq!(ark_ff::to_bytes!(r_native).unwrap(), bytes.value().unwrap()); - assert!(cs.is_satisfied().unwrap()); - let bytes = r.to_bytes()?; - assert_eq!(ark_ff::to_bytes!(r_native).unwrap(), bytes.value().unwrap()); - assert!(cs.is_satisfied().unwrap()); - - let ab_false = &a + (AF::from(Boolean::Constant(false)) * b_native); - assert_eq!(ab_false.value()?, a_native); - let ab_true = &a + (AF::from(Boolean::Constant(true)) * b_native); - assert_eq!(ab_true.value()?, a_native + &b_native); - - if !cs.is_satisfied().unwrap() { - panic!("{:?}", cs.which_is_unsatisfied().unwrap()); + for &mode in &modes { + let cs = ConstraintSystem::::new_ref(); + + let mut rng = test_rng(); + let a_native = F::rand(&mut rng); + let b_native = F::rand(&mut rng); + let a = AF::new_variable(ark_relations::ns!(cs, "generate_a"), || Ok(a_native), mode)?; + let b = AF::new_variable(ark_relations::ns!(cs, "generate_b"), || Ok(b_native), mode)?; + let b_const = AF::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?; + + let zero = AF::zero(); + let zero_native = zero.value()?; + zero.enforce_equal(&zero)?; + + let one = AF::one(); + let one_native = one.value()?; + one.enforce_equal(&one)?; + + one.enforce_not_equal(&zero)?; + + let one_dup = &zero + &one; + one_dup.enforce_equal(&one)?; + + let two = &one + &one; + two.enforce_equal(&two)?; + two.enforce_equal(&one.double()?)?; + two.enforce_not_equal(&one)?; + two.enforce_not_equal(&zero)?; + + // a + 0 = a + let a_plus_zero = &a + &zero; + assert_eq!(a_plus_zero.value()?, a_native); + a_plus_zero.enforce_equal(&a)?; + a_plus_zero.enforce_not_equal(&a.double()?)?; + + // a - 0 = a + let a_minus_zero = &a - &zero; + assert_eq!(a_minus_zero.value()?, a_native); + a_minus_zero.enforce_equal(&a)?; + + // a - a = 0 + let a_minus_a = &a - &a; + assert_eq!(a_minus_a.value()?, zero_native); + a_minus_a.enforce_equal(&zero)?; + + // a + b = b + a + let a_b = &a + &b; + let b_a = &b + &a; + assert_eq!(a_b.value()?, a_native + &b_native); + a_b.enforce_equal(&b_a)?; + + // (a + b) + a = a + (b + a) + let ab_a = &a_b + &a; + let a_ba = &a + &b_a; + assert_eq!(ab_a.value()?, a_native + &b_native + &a_native); + ab_a.enforce_equal(&a_ba)?; + + let b_times_a_plus_b = &a_b * &b; + let b_times_b_plus_a = &b_a * &b; + assert_eq!( + b_times_a_plus_b.value()?, + b_native * &(b_native + &a_native) + ); + assert_eq!( + b_times_a_plus_b.value()?, + (b_native + &a_native) * &b_native + ); + assert_eq!( + b_times_a_plus_b.value()?, + (a_native + &b_native) * &b_native + ); + b_times_b_plus_a.enforce_equal(&b_times_a_plus_b)?; + + // a * 1 = a + assert_eq!((&a * &one).value()?, a_native * &one_native); + + // a * b = b * a + let ab = &a * &b; + let ba = &b * &a; + assert_eq!(ab.value()?, ba.value()?); + assert_eq!(ab.value()?, a_native * &b_native); + + let ab_const = &a * &b_const; + let b_const_a = &b_const * &a; + assert_eq!(ab_const.value()?, b_const_a.value()?); + assert_eq!(ab_const.value()?, ab.value()?); + assert_eq!(ab_const.value()?, a_native * &b_native); + + // (a * b) * a = a * (b * a) + let ab_a = &ab * &a; + let a_ba = &a * &ba; + assert_eq!(ab_a.value()?, a_ba.value()?); + assert_eq!(ab_a.value()?, a_native * &b_native * &a_native); + + let aa = &a * &a; + let a_squared = a.square()?; + a_squared.enforce_equal(&aa)?; + assert_eq!(aa.value()?, a_squared.value()?); + assert_eq!(aa.value()?, a_native.square()); + + let aa = &a * a_native; + a_squared.enforce_equal(&aa)?; + assert_eq!(aa.value()?, a_squared.value()?); + assert_eq!(aa.value()?, a_native.square()); + + let a_b2 = &a + b_native; + a_b.enforce_equal(&a_b2)?; + assert_eq!(a_b.value()?, a_b2.value()?); + + let a_inv = a.inverse()?; + a_inv.mul_equals(&a, &one)?; + assert_eq!(a_inv.value()?, a.value()?.inverse().unwrap()); + assert_eq!(a_inv.value()?, a_native.inverse().unwrap()); + + let a_b_inv = a.mul_by_inverse(&b)?; + a_b_inv.mul_equals(&b, &a)?; + assert_eq!(a_b_inv.value()?, a_native * b_native.inverse().unwrap()); + + // a * a * a = a^3 + let bits = BitIteratorLE::without_trailing_zeros([3u64]) + .map(Boolean::constant) + .collect::>(); + assert_eq!(a_native.pow([0x3]), a.pow_le(&bits)?.value()?); + + // a * a * a = a^3 + assert_eq!(a_native.pow([0x3]), a.pow_by_constant(&[0x3])?.value()?); + assert!(cs.is_satisfied().unwrap()); + + let mut constants = [F::zero(); 4]; + for c in &mut constants { + *c = UniformRand::rand(&mut test_rng()); + } + let bits = [ + Boolean::::constant(false), + Boolean::constant(true), + ]; + let lookup_result = AF::two_bit_lookup(&bits, constants.as_ref())?; + assert_eq!(lookup_result.value()?, constants[2]); + assert!(cs.is_satisfied().unwrap()); + + let f = F::from(1u128 << 64); + let f_bits = ark_ff::BitIteratorLE::new(&[0u64, 1u64]).collect::>(); + let fv = AF::new_variable(ark_relations::ns!(cs, "alloc u128"), || Ok(f), mode)?; + assert_eq!(fv.to_bits_le()?.value().unwrap()[..128], f_bits[..128]); + assert!(cs.is_satisfied().unwrap()); + + let r_native: F = UniformRand::rand(&mut test_rng()); + + let r = AF::new_variable(ark_relations::ns!(cs, "r_native"), || Ok(r_native), mode) + .unwrap(); + let _ = r.to_non_unique_bits_le()?; + assert!(cs.is_satisfied().unwrap()); + let _ = r.to_bits_le()?; + assert!(cs.is_satisfied().unwrap()); + + let bytes = r.to_non_unique_bytes()?; + assert_eq!(ark_ff::to_bytes!(r_native).unwrap(), bytes.value().unwrap()); + assert!(cs.is_satisfied().unwrap()); + let bytes = r.to_bytes()?; + assert_eq!(ark_ff::to_bytes!(r_native).unwrap(), bytes.value().unwrap()); + assert!(cs.is_satisfied().unwrap()); + + let ab_false = &a + (AF::from(Boolean::Constant(false)) * b_native); + let ab_true = &a + (AF::from(Boolean::Constant(true)) * b_native); + assert_eq!(ab_false.value()?, a_native); + assert_eq!(ab_true.value()?, a_native + &b_native); + + if !cs.is_satisfied().unwrap() { + panic!( + "Unsatisfied in mode {:?}.\n{:?}", + mode, + cs.which_is_unsatisfied().unwrap() + ); + } + assert!(cs.is_satisfied().unwrap()); } - assert!(cs.is_satisfied().unwrap()); Ok(()) } @@ -200,18 +210,25 @@ pub mod fields { AF: FieldVar, for<'a> &'a AF: FieldOpsBounds<'a, F, AF>, { - let cs = ConstraintSystem::::new_ref(); - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - for i in 0..=maxpower { - let mut a = F::rand(&mut rng); - let mut a_gadget = AF::new_witness(ark_relations::ns!(cs, "a"), || Ok(a))?; - a_gadget.frobenius_map_in_place(i)?; - a.frobenius_map(i); - - assert_eq!(a_gadget.value()?, a); + let modes = [ + AllocationMode::Input, + AllocationMode::Witness, + AllocationMode::Constant, + ]; + for &mode in &modes { + let cs = ConstraintSystem::::new_ref(); + let mut rng = XorShiftRng::seed_from_u64(1231275789u64); + for i in 0..=maxpower { + let mut a = F::rand(&mut rng); + let mut a_gadget = AF::new_variable(ark_relations::ns!(cs, "a"), || Ok(a), mode)?; + a_gadget.frobenius_map_in_place(i)?; + a.frobenius_map(i); + + assert_eq!(a_gadget.value()?, a); + } + + assert!(cs.is_satisfied().unwrap()); } - - assert!(cs.is_satisfied().unwrap()); Ok(()) } } @@ -234,68 +251,81 @@ pub mod curves { GG: CurveVar, for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, { - let cs = ConstraintSystem::::new_ref(); - - let mut rng = test_rng(); - let a_native = C::rand(&mut rng); - let b_native = C::rand(&mut rng); - let a = GG::new_witness(ark_relations::ns!(cs, "generate_a"), || Ok(a_native)).unwrap(); - let b = GG::new_witness(ark_relations::ns!(cs, "generate_b"), || Ok(b_native)).unwrap(); - - let zero = GG::zero(); - assert_eq!(zero.value()?, zero.value()?); - - // a == a - assert_eq!(a.value()?, a.value()?); - // a + 0 = a - assert_eq!((&a + &zero).value()?, a.value()?); - // a - 0 = a - assert_eq!((&a - &zero).value()?, a.value()?); - // a - a = 0 - assert_eq!((&a - &a).value()?, zero.value()?); - // a + b = b + a - let a_b = &a + &b; - let b_a = &b + &a; - assert_eq!(a_b.value()?, b_a.value()?); - a_b.enforce_equal(&b_a)?; - assert!(cs.is_satisfied().unwrap()); - - // (a + b) + a = a + (b + a) - let ab_a = &a_b + &a; - let a_ba = &a + &b_a; - assert_eq!(ab_a.value()?, a_ba.value()?); - ab_a.enforce_equal(&a_ba)?; - assert!(cs.is_satisfied().unwrap()); - - // a.double() = a + a - let a_a = &a + &a; - let mut a2 = a.clone(); - a2.double_in_place()?; - a2.enforce_equal(&a_a)?; - assert_eq!(a2.value()?, a_native.double()); - assert_eq!(a_a.value()?, a_native.double()); - assert_eq!(a2.value()?, a_a.value()?); - assert!(cs.is_satisfied().unwrap()); - - // b.double() = b + b - let mut b2 = b.clone(); - b2.double_in_place()?; - let b_b = &b + &b; - b2.enforce_equal(&b_b)?; - assert!(cs.is_satisfied().unwrap()); - assert_eq!(b2.value()?, b_b.value()?); - - let _ = a.to_bytes()?; - assert!(cs.is_satisfied().unwrap()); - let _ = a.to_non_unique_bytes()?; - assert!(cs.is_satisfied().unwrap()); - - let _ = b.to_bytes()?; - let _ = b.to_non_unique_bytes()?; - if !cs.is_satisfied().unwrap() { - panic!("{:?}", cs.which_is_unsatisfied().unwrap()); + let modes = [ + AllocationMode::Input, + AllocationMode::Witness, + AllocationMode::Constant, + ]; + for &mode in &modes { + let cs = ConstraintSystem::::new_ref(); + + let mut rng = test_rng(); + let a_native = C::rand(&mut rng); + let b_native = C::rand(&mut rng); + let a = GG::new_variable(ark_relations::ns!(cs, "generate_a"), || Ok(a_native), mode) + .unwrap(); + let b = GG::new_variable(ark_relations::ns!(cs, "generate_b"), || Ok(b_native), mode) + .unwrap(); + + let zero = GG::zero(); + assert_eq!(zero.value()?, zero.value()?); + + // a == a + assert_eq!(a.value()?, a.value()?); + // a + 0 = a + assert_eq!((&a + &zero).value()?, a.value()?); + // a - 0 = a + assert_eq!((&a - &zero).value()?, a.value()?); + // a - a = 0 + assert_eq!((&a - &a).value()?, zero.value()?); + // a + b = b + a + let a_b = &a + &b; + let b_a = &b + &a; + assert_eq!(a_b.value()?, b_a.value()?); + a_b.enforce_equal(&b_a)?; + assert!(cs.is_satisfied().unwrap()); + + // (a + b) + a = a + (b + a) + let ab_a = &a_b + &a; + let a_ba = &a + &b_a; + assert_eq!(ab_a.value()?, a_ba.value()?); + ab_a.enforce_equal(&a_ba)?; + assert!(cs.is_satisfied().unwrap()); + + // a.double() = a + a + let a_a = &a + &a; + let mut a2 = a.clone(); + a2.double_in_place()?; + a2.enforce_equal(&a_a)?; + assert_eq!(a2.value()?, a_native.double()); + assert_eq!(a_a.value()?, a_native.double()); + assert_eq!(a2.value()?, a_a.value()?); + assert!(cs.is_satisfied().unwrap()); + + // b.double() = b + b + let mut b2 = b.clone(); + b2.double_in_place()?; + let b_b = &b + &b; + b2.enforce_equal(&b_b)?; + assert!(cs.is_satisfied().unwrap()); + assert_eq!(b2.value()?, b_b.value()?); + + let _ = a.to_bytes()?; + assert!(cs.is_satisfied().unwrap()); + let _ = a.to_non_unique_bytes()?; + assert!(cs.is_satisfied().unwrap()); + + let _ = b.to_bytes()?; + let _ = b.to_non_unique_bytes()?; + if !cs.is_satisfied().unwrap() { + panic!( + "Unsatisfied in mode {:?}.\n{:?}", + mode, + cs.which_is_unsatisfied().unwrap() + ); + } + assert!(cs.is_satisfied().unwrap()); } - assert!(cs.is_satisfied().unwrap()); Ok(()) } @@ -305,75 +335,100 @@ pub mod curves { GG: CurveVar, ::BasePrimeField>, for<'a> &'a GG: GroupOpsBounds<'a, SWProjective

, GG>, { - use ark_ec::group::Group; - use ark_ff::BitIteratorLE; - use ark_r1cs_std::prelude::*; - use ark_std::UniformRand; - - group_test::, _, GG>()?; - - let mut rng = test_rng(); - - let cs = ConstraintSystem::<::BasePrimeField>::new_ref(); - - 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 ns = ark_relations::ns!(cs, "allocating variables"); - let mut gadget_a = GG::new_witness(cs.clone(), || Ok(a))?; - let gadget_b = GG::new_witness(cs.clone(), || Ok(b))?; - drop(ns); - assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x); - assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y); - assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x); - assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y); - assert_eq!(cs.which_is_unsatisfied().unwrap(), None); - - // Check addition - let ab = a + &b; - let ab_affine = ab.into_affine(); - let gadget_ab = &gadget_a + &gadget_b; - let gadget_ba = &gadget_b + &gadget_a; - gadget_ba.enforce_equal(&gadget_ab)?; - - let ab_val = gadget_ab.value()?.into_affine(); - assert_eq!(ab_val, ab_affine, "Result of addition is unequal"); - assert!(cs.is_satisfied().unwrap()); - - // Check doubling - let aa = Group::double(&a); - let aa_affine = aa.into_affine(); - gadget_a.double_in_place()?; - let aa_val = gadget_a.value()?.into_affine(); - assert_eq!( - aa_val, aa_affine, - "Gadget and native values are unequal after double." - ); - assert!(cs.is_satisfied().unwrap()); - - // Check mul_bits - let scalar = P::ScalarField::rand(&mut rng); - let native_result = aa.into_affine().mul(scalar); - let native_result = native_result.into_affine(); - - let scalar: Vec = BitIteratorLE::new(scalar.into_repr()).collect(); - let input: Vec> = - Vec::new_witness(ark_relations::ns!(cs, "bits"), || Ok(scalar)).unwrap(); - let result = gadget_a.scalar_mul_le(input.iter())?; - let result_val = result.value()?.into_affine(); - assert_eq!( - result_val, native_result, - "gadget & native values are diff. after scalar mul" - ); - assert!(cs.is_satisfied().unwrap()); - - if !cs.is_satisfied().unwrap() { - panic!("{:?}", cs.which_is_unsatisfied().unwrap()); + let modes = [ + AllocationMode::Input, + AllocationMode::Witness, + AllocationMode::Constant, + ]; + for &mode in &modes { + use ark_ec::group::Group; + use ark_ff::{BitIteratorLE, Zero}; + use ark_r1cs_std::prelude::*; + use ark_std::UniformRand; + + group_test::, _, GG>()?; + + let mut rng = test_rng(); + + let cs = ConstraintSystem::<::BasePrimeField>::new_ref(); + + 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 ns = ark_relations::ns!(cs, "allocating variables"); + let mut gadget_a = GG::new_variable(cs.clone(), || Ok(a), mode)?; + let gadget_b = GG::new_variable(cs.clone(), || Ok(b), mode)?; + let zero = GG::zero(); + drop(ns); + assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x); + assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y); + assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x); + assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y); + assert_eq!(cs.which_is_unsatisfied().unwrap(), None); + + // Check addition + let ab = a + &b; + let ab_affine = ab.into_affine(); + let gadget_ab = &gadget_a + &gadget_b; + let gadget_ba = &gadget_b + &gadget_a; + gadget_ba.enforce_equal(&gadget_ab)?; + + let ab_val = gadget_ab.value()?.into_affine(); + assert_eq!(ab_val, ab_affine, "Result of addition is unequal"); + assert!(cs.is_satisfied().unwrap()); + + let gadget_a_zero = &gadget_a + &zero; + gadget_a_zero.enforce_equal(&gadget_a)?; + + // Check doubling + let aa = Group::double(&a); + let aa_affine = aa.into_affine(); + gadget_a.double_in_place()?; + let aa_val = gadget_a.value()?.into_affine(); + assert_eq!( + aa_val, aa_affine, + "Gadget and native values are unequal after double." + ); + assert!(cs.is_satisfied().unwrap()); + + // Check mul_bits + let scalar = P::ScalarField::rand(&mut rng); + let native_result = aa.into_affine().mul(scalar); + let native_result = native_result.into_affine(); + + let scalar: Vec = BitIteratorLE::new(scalar.into_repr()).collect(); + let input: Vec> = + Vec::new_witness(ark_relations::ns!(cs, "bits"), || Ok(scalar)).unwrap(); + let result = gadget_a.scalar_mul_le(input.iter())?; + let result_val = result.value()?.into_affine(); + assert_eq!( + result_val, native_result, + "gadget & native values are diff. after scalar mul" + ); + assert!(cs.is_satisfied().unwrap()); + + let result = zero.scalar_mul_le(input.iter())?; + let result_val = result.value()?.into_affine(); + result.enforce_equal(&zero)?; + assert_eq!( + result_val, + SWProjective::zero(), + "gadget & native values are diff. after scalar mul of zero" + ); + assert!(cs.is_satisfied().unwrap()); + + if !cs.is_satisfied().unwrap() { + panic!( + "Unsatisfied in mode {:?}.\n{:?}", + mode, + cs.which_is_unsatisfied().unwrap() + ); + } + + assert!(cs.is_satisfied().unwrap()); } - - assert!(cs.is_satisfied().unwrap()); Ok(()) } @@ -383,75 +438,86 @@ pub mod curves { GG: CurveVar, ::BasePrimeField>, for<'a> &'a GG: GroupOpsBounds<'a, TEProjective

, GG>, { - use ark_ec::group::Group; - use ark_ff::BitIteratorLE; - use ark_std::UniformRand; - - group_test::, _, GG>()?; - - let mut rng = test_rng(); - - let cs = ConstraintSystem::<::BasePrimeField>::new_ref(); - - let a = TEProjective::

::rand(&mut rng); - let b = TEProjective::

::rand(&mut rng); - let a_affine = a.into_affine(); - let b_affine = b.into_affine(); - - let ns = ark_relations::ns!(cs, "allocating variables"); - let mut gadget_a = GG::new_witness(cs.clone(), || Ok(a))?; - let gadget_b = GG::new_witness(cs.clone(), || Ok(b))?; - drop(ns); - - assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x); - assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y); - assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x); - assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y); - assert_eq!(cs.which_is_unsatisfied()?, None); - - // Check addition - let ab = a + &b; - let ab_affine = ab.into_affine(); - let gadget_ab = &gadget_a + &gadget_b; - let gadget_ba = &gadget_b + &gadget_a; - gadget_ba.enforce_equal(&gadget_ab)?; - - let ab_val = gadget_ab.value()?.into_affine(); - assert_eq!(ab_val, ab_affine, "Result of addition is unequal"); - assert!(cs.is_satisfied().unwrap()); - - // Check doubling - let aa = Group::double(&a); - let aa_affine = aa.into_affine(); - gadget_a.double_in_place()?; - let aa_val = gadget_a.value()?.into_affine(); - assert_eq!( - aa_val, aa_affine, - "Gadget and native values are unequal after double." - ); - assert!(cs.is_satisfied().unwrap()); - - // Check mul_bits - let scalar = P::ScalarField::rand(&mut rng); - let native_result = AffineCurve::mul(&aa.into_affine(), scalar); - let native_result = native_result.into_affine(); - - let scalar: Vec = BitIteratorLE::new(scalar.into_repr()).collect(); - let input: Vec> = - Vec::new_witness(ark_relations::ns!(cs, "bits"), || Ok(scalar)).unwrap(); - let result = gadget_a.scalar_mul_le(input.iter())?; - let result_val = result.value()?.into_affine(); - assert_eq!( - result_val, native_result, - "gadget & native values are diff. after scalar mul" - ); - assert!(cs.is_satisfied().unwrap()); - - if !cs.is_satisfied().unwrap() { - panic!("{:?}", cs.which_is_unsatisfied().unwrap()); + let modes = [ + AllocationMode::Input, + AllocationMode::Witness, + AllocationMode::Constant, + ]; + for &mode in &modes { + use ark_ec::group::Group; + use ark_ff::BitIteratorLE; + use ark_std::UniformRand; + + group_test::, _, GG>()?; + + let mut rng = test_rng(); + + let cs = ConstraintSystem::<::BasePrimeField>::new_ref(); + + let a = TEProjective::

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

::rand(&mut rng); + let a_affine = a.into_affine(); + let b_affine = b.into_affine(); + + let ns = ark_relations::ns!(cs, "allocating variables"); + let mut gadget_a = GG::new_variable(cs.clone(), || Ok(a), mode)?; + let gadget_b = GG::new_variable(cs.clone(), || Ok(b), mode)?; + drop(ns); + + assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x); + assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y); + assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x); + assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y); + assert_eq!(cs.which_is_unsatisfied()?, None); + + // Check addition + let ab = a + &b; + let ab_affine = ab.into_affine(); + let gadget_ab = &gadget_a + &gadget_b; + let gadget_ba = &gadget_b + &gadget_a; + gadget_ba.enforce_equal(&gadget_ab)?; + + let ab_val = gadget_ab.value()?.into_affine(); + assert_eq!(ab_val, ab_affine, "Result of addition is unequal"); + assert!(cs.is_satisfied().unwrap()); + + // Check doubling + let aa = Group::double(&a); + let aa_affine = aa.into_affine(); + gadget_a.double_in_place()?; + let aa_val = gadget_a.value()?.into_affine(); + assert_eq!( + aa_val, aa_affine, + "Gadget and native values are unequal after double." + ); + assert!(cs.is_satisfied().unwrap()); + + // Check mul_bits + let scalar = P::ScalarField::rand(&mut rng); + let native_result = AffineCurve::mul(&aa.into_affine(), scalar); + let native_result = native_result.into_affine(); + + let scalar: Vec = BitIteratorLE::new(scalar.into_repr()).collect(); + let input: Vec> = + Vec::new_witness(ark_relations::ns!(cs, "bits"), || Ok(scalar)).unwrap(); + let result = gadget_a.scalar_mul_le(input.iter())?; + let result_val = result.value()?.into_affine(); + assert_eq!( + result_val, native_result, + "gadget & native values are diff. after scalar mul" + ); + assert!(cs.is_satisfied().unwrap()); + + if !cs.is_satisfied().unwrap() { + panic!( + "Unsatisfied in mode {:?}.\n{:?}", + mode, + cs.which_is_unsatisfied().unwrap() + ); + } + + assert!(cs.is_satisfied().unwrap()); } - - assert!(cs.is_satisfied().unwrap()); Ok(()) } } @@ -470,85 +536,88 @@ pub mod pairing { for<'a> &'a P::G2Var: GroupOpsBounds<'a, E::G2Projective, P::G2Var>, for<'a> &'a P::GTVar: FieldOpsBounds<'a, E::Fqk, P::GTVar>, { - let cs = ConstraintSystem::::new_ref(); - - let mut rng = test_rng(); - let a = E::G1Projective::rand(&mut rng); - let b = E::G2Projective::rand(&mut rng); - let s = E::Fr::rand(&mut rng); - - let mut sa = a; - sa *= s; - let mut sb = b; - sb *= s; - - let a_g = P::G1Var::new_witness(cs.clone(), || Ok(a.into_affine()))?; - let b_g = P::G2Var::new_witness(cs.clone(), || Ok(b.into_affine()))?; - let sa_g = P::G1Var::new_witness(cs.clone(), || Ok(sa.into_affine()))?; - let sb_g = P::G2Var::new_witness(cs.clone(), || Ok(sb.into_affine()))?; - - let mut _preparation_num_constraints = cs.num_constraints(); - let a_prep_g = P::prepare_g1(&a_g)?; - let b_prep_g = P::prepare_g2(&b_g)?; - _preparation_num_constraints = cs.num_constraints() - _preparation_num_constraints; - - let sa_prep_g = P::prepare_g1(&sa_g)?; - let sb_prep_g = P::prepare_g2(&sb_g)?; - - let (ans1_g, ans1_n) = { - let _ml_constraints = cs.num_constraints(); - let ml_g = P::miller_loop(&[sa_prep_g], &[b_prep_g.clone()])?; - let _fe_constraints = cs.num_constraints(); - let ans_g = P::final_exponentiation(&ml_g)?; - let ans_n = E::pairing(sa, b); - (ans_g, ans_n) - }; - - let (ans2_g, ans2_n) = { - let ans_g = P::pairing(a_prep_g.clone(), sb_prep_g)?; - let ans_n = E::pairing(a, sb); - (ans_g, ans_n) - }; - - let (ans3_g, ans3_n) = { - let s_iter = BitIteratorLE::without_trailing_zeros(s.into_repr()) - .map(Boolean::constant) - .collect::>(); - - let mut ans_g = P::pairing(a_prep_g, b_prep_g)?; - let mut ans_n = E::pairing(a, b); - ans_n = ans_n.pow(s.into_repr()); - ans_g = ans_g.pow_le(&s_iter)?; - - (ans_g, ans_n) - }; - - ans1_g.enforce_equal(&ans2_g)?; - ans2_g.enforce_equal(&ans3_g)?; - - assert_eq!(ans1_g.value()?, ans1_n, "Failed native test 1"); - assert_eq!(ans2_g.value()?, ans2_n, "Failed native test 2"); - assert_eq!(ans3_g.value()?, ans3_n, "Failed native test 3"); - - assert_eq!(ans1_n, ans2_n, "Failed ans1_native == ans2_native"); - assert_eq!(ans2_n, ans3_n, "Failed ans2_native == ans3_native"); - assert_eq!(ans1_g.value()?, ans3_g.value()?, "Failed ans1 == ans3"); - assert_eq!(ans1_g.value()?, ans2_g.value()?, "Failed ans1 == ans2"); - assert_eq!(ans2_g.value()?, ans3_g.value()?, "Failed ans2 == ans3"); - - if !cs.is_satisfied().unwrap() { - panic!("Unsatisfied: {:?}", cs.which_is_unsatisfied()); + let modes = [ + AllocationMode::Input, + AllocationMode::Witness, + AllocationMode::Constant, + ]; + for &mode in &modes { + let cs = ConstraintSystem::::new_ref(); + + let mut rng = test_rng(); + let a = E::G1Projective::rand(&mut rng); + let b = E::G2Projective::rand(&mut rng); + let s = E::Fr::rand(&mut rng); + + let mut sa = a; + sa *= s; + let mut sb = b; + sb *= s; + + let a_g = P::G1Var::new_variable(cs.clone(), || Ok(a.into_affine()), mode)?; + let b_g = P::G2Var::new_variable(cs.clone(), || Ok(b.into_affine()), mode)?; + let sa_g = P::G1Var::new_variable(cs.clone(), || Ok(sa.into_affine()), mode)?; + let sb_g = P::G2Var::new_variable(cs.clone(), || Ok(sb.into_affine()), mode)?; + + let mut _preparation_num_constraints = cs.num_constraints(); + let a_prep_g = P::prepare_g1(&a_g)?; + let b_prep_g = P::prepare_g2(&b_g)?; + _preparation_num_constraints = cs.num_constraints() - _preparation_num_constraints; + + let sa_prep_g = P::prepare_g1(&sa_g)?; + let sb_prep_g = P::prepare_g2(&sb_g)?; + + let (ans1_g, ans1_n) = { + let _ml_constraints = cs.num_constraints(); + let ml_g = P::miller_loop(&[sa_prep_g], &[b_prep_g.clone()])?; + let _fe_constraints = cs.num_constraints(); + let ans_g = P::final_exponentiation(&ml_g)?; + let ans_n = E::pairing(sa, b); + (ans_g, ans_n) + }; + + let (ans2_g, ans2_n) = { + let ans_g = P::pairing(a_prep_g.clone(), sb_prep_g)?; + let ans_n = E::pairing(a, sb); + (ans_g, ans_n) + }; + + let (ans3_g, ans3_n) = { + let s_iter = BitIteratorLE::without_trailing_zeros(s.into_repr()) + .map(Boolean::constant) + .collect::>(); + + let mut ans_g = P::pairing(a_prep_g, b_prep_g)?; + let mut ans_n = E::pairing(a, b); + ans_n = ans_n.pow(s.into_repr()); + ans_g = ans_g.pow_le(&s_iter)?; + + (ans_g, ans_n) + }; + + ans1_g.enforce_equal(&ans2_g)?; + ans2_g.enforce_equal(&ans3_g)?; + + assert_eq!(ans1_g.value()?, ans1_n, "Failed native test 1"); + assert_eq!(ans2_g.value()?, ans2_n, "Failed native test 2"); + assert_eq!(ans3_g.value()?, ans3_n, "Failed native test 3"); + + assert_eq!(ans1_n, ans2_n, "Failed ans1_native == ans2_native"); + assert_eq!(ans2_n, ans3_n, "Failed ans2_native == ans3_native"); + assert_eq!(ans1_g.value()?, ans3_g.value()?, "Failed ans1 == ans3"); + assert_eq!(ans1_g.value()?, ans2_g.value()?, "Failed ans1 == ans2"); + assert_eq!(ans2_g.value()?, ans3_g.value()?, "Failed ans2 == ans3"); + + if !cs.is_satisfied().unwrap() { + panic!( + "Unsatisfied in mode {:?}.\n{:?}", + mode, + cs.which_is_unsatisfied().unwrap() + ); + } + + assert!(cs.is_satisfied().unwrap(), "cs is not satisfied"); } - - assert!(cs.is_satisfied().unwrap(), "cs is not satisfied"); Ok(()) } } - -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -}