mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-09 07:21:29 +01:00
Merge nonnative (#79)
Co-authored-by: Nicholas Ward <npward@berkeley.edu> Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu> Co-authored-by: Weikeng Chen <w.k@berkeley.edu> Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com> Co-authored-by: Daira Hopwood <daira@jacaranda.org> Co-authored-by: William Lin <31808623+Will-Lin4@users.noreply.github.com> Co-authored-by: Dev Ojha <dojha12@gmail.com> Co-authored-by: Alex Ozdemir <aozdemir@hmc.edu>
This commit is contained in:
713
tests/arithmetic_tests.rs
Normal file
713
tests/arithmetic_tests.rs
Normal file
@@ -0,0 +1,713 @@
|
||||
use ark_bls12_381::Bls12_381;
|
||||
use ark_ec::PairingEngine;
|
||||
use ark_ff::{BigInteger, PrimeField};
|
||||
use ark_mnt4_298::MNT4_298;
|
||||
use ark_mnt4_753::MNT4_753;
|
||||
use ark_mnt6_298::MNT6_298;
|
||||
use ark_mnt6_753::MNT6_753;
|
||||
|
||||
use ark_r1cs_std::fields::nonnative::{AllocatedNonNativeFieldVar, NonNativeFieldVar};
|
||||
use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::FieldVar, R1CSVar};
|
||||
use ark_relations::r1cs::{ConstraintSystem, ConstraintSystemRef};
|
||||
use ark_std::rand::RngCore;
|
||||
|
||||
#[cfg(not(ci))]
|
||||
const NUM_REPETITIONS: usize = 100;
|
||||
#[cfg(ci)]
|
||||
const NUM_REPETITIONS: usize = 1;
|
||||
|
||||
#[cfg(not(ci))]
|
||||
const TEST_COUNT: usize = 100;
|
||||
#[cfg(ci)]
|
||||
const TEST_COUNT: usize = 1;
|
||||
|
||||
fn allocation_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let a_native = TargetField::rand(rng);
|
||||
let a = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "alloc a"),
|
||||
|| Ok(a_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a_actual = a.value().unwrap();
|
||||
let a_expected = a_native;
|
||||
assert!(
|
||||
a_actual.eq(&a_expected),
|
||||
"allocated value does not equal the expected value"
|
||||
);
|
||||
|
||||
let (_a, a_bits) =
|
||||
AllocatedNonNativeFieldVar::<TargetField, BaseField>::new_witness_with_le_bits(
|
||||
ark_relations::ns!(cs, "alloc a2"),
|
||||
|| Ok(a_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a_bits_actual: Vec<bool> = a_bits.into_iter().map(|b| b.value().unwrap()).collect();
|
||||
let mut a_bits_expected = a_native.into_repr().to_bits_le();
|
||||
a_bits_expected.truncate(TargetField::size_in_bits());
|
||||
assert_eq!(
|
||||
a_bits_actual, a_bits_expected,
|
||||
"allocated bits does not equal the expected bits"
|
||||
);
|
||||
}
|
||||
|
||||
fn addition_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let a_native = TargetField::rand(rng);
|
||||
let a = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "alloc a"),
|
||||
|| Ok(a_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let b_native = TargetField::rand(rng);
|
||||
let b = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "alloc b"),
|
||||
|| Ok(b_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a_plus_b = a + &b;
|
||||
|
||||
let a_plus_b_actual = a_plus_b.value().unwrap();
|
||||
let a_plus_b_expected = a_native + &b_native;
|
||||
assert!(a_plus_b_actual.eq(&a_plus_b_expected), "a + b failed");
|
||||
}
|
||||
|
||||
fn multiplication_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let a_native = TargetField::rand(rng);
|
||||
let a = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "alloc a"),
|
||||
|| Ok(a_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let b_native = TargetField::rand(rng);
|
||||
let b = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "alloc b"),
|
||||
|| Ok(b_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a_times_b = a * &b;
|
||||
|
||||
let a_times_b_actual = a_times_b.value().unwrap();
|
||||
let a_times_b_expected = a_native * &b_native;
|
||||
|
||||
assert!(
|
||||
a_times_b_actual.eq(&a_times_b_expected),
|
||||
"a_times_b = {:?}, a_times_b_actual = {:?}, a_times_b_expected = {:?}",
|
||||
a_times_b,
|
||||
a_times_b_actual.into_repr().as_ref(),
|
||||
a_times_b_expected.into_repr().as_ref()
|
||||
);
|
||||
}
|
||||
|
||||
fn equality_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let a_native = TargetField::rand(rng);
|
||||
let a = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "alloc a"),
|
||||
|| Ok(a_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let b_native = TargetField::rand(rng);
|
||||
let b = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "alloc b"),
|
||||
|| Ok(b_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a_times_b = a * &b;
|
||||
|
||||
let a_times_b_expected = a_native * &b_native;
|
||||
let a_times_b_expected_gadget = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "alloc a * b"),
|
||||
|| Ok(a_times_b_expected),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
a_times_b.enforce_equal(&a_times_b_expected_gadget).unwrap();
|
||||
}
|
||||
|
||||
fn edge_cases_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let zero_native = TargetField::zero();
|
||||
let zero = NonNativeFieldVar::<TargetField, BaseField>::zero();
|
||||
let one = NonNativeFieldVar::<TargetField, BaseField>::one();
|
||||
|
||||
let a_native = TargetField::rand(rng);
|
||||
let minus_a_native = TargetField::zero() - &a_native;
|
||||
let a = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "alloc a"),
|
||||
|| Ok(a_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a_plus_zero = &a + &zero;
|
||||
let a_minus_zero = &a - &zero;
|
||||
let zero_minus_a = &zero - &a;
|
||||
let a_times_zero = &a * &zero;
|
||||
|
||||
let zero_plus_a = &zero + &a;
|
||||
let zero_times_a = &zero * &a;
|
||||
|
||||
let a_times_one = &a * &one;
|
||||
let one_times_a = &one * &a;
|
||||
|
||||
let a_plus_zero_native = a_plus_zero.value().unwrap();
|
||||
let a_minus_zero_native = a_minus_zero.value().unwrap();
|
||||
let zero_minus_a_native = zero_minus_a.value().unwrap();
|
||||
let a_times_zero_native = a_times_zero.value().unwrap();
|
||||
let zero_plus_a_native = zero_plus_a.value().unwrap();
|
||||
let zero_times_a_native = zero_times_a.value().unwrap();
|
||||
let a_times_one_native = a_times_one.value().unwrap();
|
||||
let one_times_a_native = one_times_a.value().unwrap();
|
||||
|
||||
assert!(
|
||||
a_plus_zero_native.eq(&a_native),
|
||||
"a_plus_zero = {:?}, a = {:?}",
|
||||
a_plus_zero_native.into_repr().as_ref(),
|
||||
a_native.into_repr().as_ref()
|
||||
);
|
||||
assert!(
|
||||
a_minus_zero_native.eq(&a_native),
|
||||
"a_minus_zero = {:?}, a = {:?}",
|
||||
a_minus_zero_native.into_repr().as_ref(),
|
||||
a_native.into_repr().as_ref()
|
||||
);
|
||||
assert!(
|
||||
zero_minus_a_native.eq(&minus_a_native),
|
||||
"zero_minus_a = {:?}, minus_a = {:?}",
|
||||
zero_minus_a_native.into_repr().as_ref(),
|
||||
minus_a_native.into_repr().as_ref()
|
||||
);
|
||||
assert!(
|
||||
a_times_zero_native.eq(&zero_native),
|
||||
"a_times_zero = {:?}, zero = {:?}",
|
||||
a_times_zero_native.into_repr().as_ref(),
|
||||
zero_native.into_repr().as_ref()
|
||||
);
|
||||
assert!(
|
||||
zero_plus_a_native.eq(&a_native),
|
||||
"zero_plus_a = {:?}, a = {:?}",
|
||||
zero_plus_a_native.into_repr().as_ref(),
|
||||
a_native.into_repr().as_ref()
|
||||
);
|
||||
assert!(
|
||||
zero_times_a_native.eq(&zero_native),
|
||||
"zero_times_a = {:?}, zero = {:?}",
|
||||
zero_times_a_native.into_repr().as_ref(),
|
||||
zero_native.into_repr().as_ref()
|
||||
);
|
||||
assert!(
|
||||
a_times_one_native.eq(&a_native),
|
||||
"a_times_one = {:?}, a = {:?}",
|
||||
a_times_one_native.into_repr().as_ref(),
|
||||
a_native.into_repr().as_ref()
|
||||
);
|
||||
assert!(
|
||||
one_times_a_native.eq(&a_native),
|
||||
"one_times_a = {:?}, a = {:?}",
|
||||
one_times_a_native.into_repr().as_ref(),
|
||||
a_native.into_repr().as_ref()
|
||||
);
|
||||
}
|
||||
|
||||
fn distribution_law_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let a_native = TargetField::rand(rng);
|
||||
let b_native = TargetField::rand(rng);
|
||||
let c_native = TargetField::rand(rng);
|
||||
|
||||
let a_plus_b_native = a_native.clone() + &b_native;
|
||||
let a_times_c_native = a_native.clone() * &c_native;
|
||||
let b_times_c_native = b_native.clone() * &c_native;
|
||||
let a_plus_b_times_c_native = a_plus_b_native.clone() * &c_native;
|
||||
let a_times_c_plus_b_times_c_native = a_times_c_native + &b_times_c_native;
|
||||
|
||||
assert!(
|
||||
a_plus_b_times_c_native.eq(&a_times_c_plus_b_times_c_native),
|
||||
"(a + b) * c doesn't equal (a * c) + (b * c)"
|
||||
);
|
||||
|
||||
let a = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "a"),
|
||||
|| Ok(a_native),
|
||||
)
|
||||
.unwrap();
|
||||
let b = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "b"),
|
||||
|| Ok(b_native),
|
||||
)
|
||||
.unwrap();
|
||||
let c = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "c"),
|
||||
|| Ok(c_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a_plus_b = &a + &b;
|
||||
let a_times_c = &a * &c;
|
||||
let b_times_c = &b * &c;
|
||||
let a_plus_b_times_c = &a_plus_b * &c;
|
||||
let a_times_c_plus_b_times_c = &a_times_c + &b_times_c;
|
||||
|
||||
assert!(
|
||||
a_plus_b.value().unwrap().eq(&a_plus_b_native),
|
||||
"a + b doesn't match"
|
||||
);
|
||||
assert!(
|
||||
a_times_c.value().unwrap().eq(&a_times_c_native),
|
||||
"a * c doesn't match"
|
||||
);
|
||||
assert!(
|
||||
b_times_c.value().unwrap().eq(&b_times_c_native),
|
||||
"b * c doesn't match"
|
||||
);
|
||||
assert!(
|
||||
a_plus_b_times_c
|
||||
.value()
|
||||
.unwrap()
|
||||
.eq(&a_plus_b_times_c_native),
|
||||
"(a + b) * c doesn't match"
|
||||
);
|
||||
assert!(
|
||||
a_times_c_plus_b_times_c
|
||||
.value()
|
||||
.unwrap()
|
||||
.eq(&a_times_c_plus_b_times_c_native),
|
||||
"(a * c) + (b * c) doesn't match"
|
||||
);
|
||||
assert!(
|
||||
a_plus_b_times_c_native.eq(&a_times_c_plus_b_times_c_native),
|
||||
"(a + b) * c != (a * c) + (b * c)"
|
||||
);
|
||||
}
|
||||
|
||||
fn randomized_arithmetic_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let mut operations: Vec<u32> = Vec::new();
|
||||
for _ in 0..TEST_COUNT {
|
||||
operations.push(rng.next_u32() % 3);
|
||||
}
|
||||
|
||||
let mut num_native = TargetField::rand(rng);
|
||||
let mut num = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "initial num"),
|
||||
|| Ok(num_native),
|
||||
)
|
||||
.unwrap();
|
||||
for op in operations.iter() {
|
||||
let next_native = TargetField::rand(rng);
|
||||
let next = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "next num for repetition"),
|
||||
|| Ok(next_native),
|
||||
)
|
||||
.unwrap();
|
||||
match op {
|
||||
0 => {
|
||||
num_native += &next_native;
|
||||
num += &next;
|
||||
}
|
||||
1 => {
|
||||
num_native *= &next_native;
|
||||
num *= &next;
|
||||
}
|
||||
2 => {
|
||||
num_native -= &next_native;
|
||||
num -= &next;
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
assert!(
|
||||
num.value().unwrap().eq(&num_native),
|
||||
"randomized arithmetic failed:"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn addition_stress_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let mut num_native = TargetField::rand(rng);
|
||||
let mut num =
|
||||
NonNativeFieldVar::new_witness(ark_relations::ns!(cs, "initial num"), || Ok(num_native))
|
||||
.unwrap();
|
||||
for _ in 0..TEST_COUNT {
|
||||
let next_native = TargetField::rand(rng);
|
||||
let next = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "next num for repetition"),
|
||||
|| Ok(next_native),
|
||||
)
|
||||
.unwrap();
|
||||
num_native += &next_native;
|
||||
num += &next;
|
||||
|
||||
assert!(num.value().unwrap().eq(&num_native));
|
||||
}
|
||||
}
|
||||
|
||||
fn multiplication_stress_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let mut num_native = TargetField::rand(rng);
|
||||
let mut num = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "initial num"),
|
||||
|| Ok(num_native),
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..TEST_COUNT {
|
||||
let next_native = TargetField::rand(rng);
|
||||
let next = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "next num for repetition"),
|
||||
|| Ok(next_native),
|
||||
)
|
||||
.unwrap();
|
||||
num_native *= &next_native;
|
||||
num *= &next;
|
||||
|
||||
assert!(num.value().unwrap().eq(&num_native));
|
||||
}
|
||||
}
|
||||
|
||||
fn mul_and_add_stress_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let mut num_native = TargetField::rand(rng);
|
||||
let mut num = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "initial num"),
|
||||
|| Ok(num_native),
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..TEST_COUNT {
|
||||
let next_add_native = TargetField::rand(rng);
|
||||
let next_add = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "next to add num for repetition"),
|
||||
|| Ok(next_add_native),
|
||||
)
|
||||
.unwrap();
|
||||
let next_mul_native = TargetField::rand(rng);
|
||||
let next_mul = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "next to mul num for repetition"),
|
||||
|| Ok(next_mul_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
num_native = num_native * &next_mul_native + &next_add_native;
|
||||
num = num * &next_mul + &next_add;
|
||||
|
||||
assert!(num.value().unwrap().eq(&num_native));
|
||||
}
|
||||
}
|
||||
|
||||
fn square_mul_add_stress_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let mut num_native = TargetField::rand(rng);
|
||||
let mut num = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "initial num"),
|
||||
|| Ok(num_native),
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..TEST_COUNT {
|
||||
let next_add_native = TargetField::rand(rng);
|
||||
let next_add = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "next to add num for repetition"),
|
||||
|| Ok(next_add_native),
|
||||
)
|
||||
.unwrap();
|
||||
let next_mul_native = TargetField::rand(rng);
|
||||
let next_mul = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "next to mul num for repetition"),
|
||||
|| Ok(next_mul_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
num_native = num_native * &num_native * &next_mul_native + &next_add_native;
|
||||
num = &num * &num * &next_mul + &next_add;
|
||||
|
||||
assert!(num.value().unwrap().eq(&num_native));
|
||||
}
|
||||
}
|
||||
|
||||
fn double_stress_test_1<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let mut num_native = TargetField::rand(rng);
|
||||
let mut num = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "initial num"),
|
||||
|| Ok(num_native),
|
||||
)
|
||||
.unwrap();
|
||||
// Add to at least BaseField::size_in_bits() to ensure that we teat the overflowing
|
||||
for _ in 0..TEST_COUNT + BaseField::size_in_bits() {
|
||||
// double
|
||||
num_native = num_native + &num_native;
|
||||
num = &num + #
|
||||
|
||||
assert!(num.value().unwrap().eq(&num_native), "result incorrect");
|
||||
}
|
||||
}
|
||||
|
||||
fn double_stress_test_2<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let mut num_native = TargetField::rand(rng);
|
||||
let mut num = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "initial num"),
|
||||
|| Ok(num_native),
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..TEST_COUNT {
|
||||
// double
|
||||
num_native = num_native + &num_native;
|
||||
num = &num + #
|
||||
|
||||
assert!(num.value().unwrap().eq(&num_native));
|
||||
|
||||
// square
|
||||
let num_square_native = num_native * &num_native;
|
||||
let num_square = &num * #
|
||||
assert!(num_square.value().unwrap().eq(&num_square_native));
|
||||
}
|
||||
}
|
||||
|
||||
fn double_stress_test_3<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
let mut num_native = TargetField::rand(rng);
|
||||
let mut num = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "initial num"),
|
||||
|| Ok(num_native),
|
||||
)
|
||||
.unwrap();
|
||||
for _ in 0..TEST_COUNT {
|
||||
// double
|
||||
num_native = num_native + &num_native;
|
||||
num = &num + #
|
||||
|
||||
assert!(num.value().unwrap().eq(&num_native));
|
||||
|
||||
// square
|
||||
let num_square_native = num_native * &num_native;
|
||||
let num_square = &num * #
|
||||
let num_square_native_gadget = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "repetition: alloc_native num"),
|
||||
|| Ok(num_square_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
num_square.enforce_equal(&num_square_native_gadget).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn inverse_stress_test<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
|
||||
cs: ConstraintSystemRef<BaseField>,
|
||||
rng: &mut R,
|
||||
) {
|
||||
for _ in 0..TEST_COUNT {
|
||||
let num_native = TargetField::rand(rng);
|
||||
let num = NonNativeFieldVar::<TargetField, BaseField>::new_witness(
|
||||
ark_relations::ns!(cs, "num"),
|
||||
|| Ok(num_native),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if num_native == TargetField::zero() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let num_native_inverse = num_native.inverse().unwrap();
|
||||
let num_inverse = num.inverse().unwrap();
|
||||
|
||||
assert!(num_inverse.value().unwrap().eq(&num_native_inverse));
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! nonnative_test_individual {
|
||||
($test_method:ident, $test_name:ident, $test_target_field:ty, $test_base_field:ty) => {
|
||||
paste::item! {
|
||||
#[test]
|
||||
fn [<$test_method _ $test_name:lower>]() {
|
||||
let rng = &mut ark_std::test_rng();
|
||||
|
||||
for _ in 0..NUM_REPETITIONS {
|
||||
let cs = ConstraintSystem::<$test_base_field>::new_ref();
|
||||
$test_method::<$test_target_field, $test_base_field, _>(cs.clone(), rng);
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! nonnative_test {
|
||||
($test_name:ident, $test_target_field:ty, $test_base_field:ty) => {
|
||||
nonnative_test_individual!(
|
||||
allocation_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
addition_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
multiplication_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
equality_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
edge_cases_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
distribution_law_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
addition_stress_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
double_stress_test_1,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
double_stress_test_2,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
double_stress_test_3,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
randomized_arithmetic_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
multiplication_stress_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
mul_and_add_stress_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
square_mul_add_stress_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
nonnative_test_individual!(
|
||||
inverse_stress_test,
|
||||
$test_name,
|
||||
$test_target_field,
|
||||
$test_base_field
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
nonnative_test!(
|
||||
MNT46Small,
|
||||
<MNT4_298 as PairingEngine>::Fr,
|
||||
<MNT6_298 as PairingEngine>::Fr
|
||||
);
|
||||
nonnative_test!(
|
||||
MNT64Small,
|
||||
<MNT6_298 as PairingEngine>::Fr,
|
||||
<MNT4_298 as PairingEngine>::Fr
|
||||
);
|
||||
nonnative_test!(
|
||||
MNT46Big,
|
||||
<MNT4_753 as PairingEngine>::Fr,
|
||||
<MNT6_753 as PairingEngine>::Fr
|
||||
);
|
||||
nonnative_test!(
|
||||
MNT64Big,
|
||||
<MNT6_753 as PairingEngine>::Fr,
|
||||
<MNT4_753 as PairingEngine>::Fr
|
||||
);
|
||||
nonnative_test!(
|
||||
BLS12MNT4Small,
|
||||
<Bls12_381 as PairingEngine>::Fr,
|
||||
<MNT4_298 as PairingEngine>::Fr
|
||||
);
|
||||
nonnative_test!(
|
||||
BLS12,
|
||||
<Bls12_381 as PairingEngine>::Fq,
|
||||
<Bls12_381 as PairingEngine>::Fr
|
||||
);
|
||||
#[cfg(not(ci))]
|
||||
nonnative_test!(
|
||||
MNT6BigMNT4Small,
|
||||
<MNT6_753 as PairingEngine>::Fr,
|
||||
<MNT4_298 as PairingEngine>::Fr
|
||||
);
|
||||
nonnative_test!(
|
||||
PallasFrMNT6Fr,
|
||||
ark_pallas::Fr,
|
||||
<MNT6_753 as PairingEngine>::Fr
|
||||
);
|
||||
nonnative_test!(
|
||||
MNT6FrPallasFr,
|
||||
<MNT6_753 as PairingEngine>::Fr,
|
||||
ark_pallas::Fr
|
||||
);
|
||||
nonnative_test!(PallasFqFr, ark_pallas::Fq, ark_pallas::Fr);
|
||||
nonnative_test!(PallasFrFq, ark_pallas::Fr, ark_pallas::Fq);
|
||||
24
tests/from_test.rs
Normal file
24
tests/from_test.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use ark_r1cs_std::alloc::AllocVar;
|
||||
use ark_r1cs_std::fields::nonnative::{NonNativeFieldMulResultVar, NonNativeFieldVar};
|
||||
use ark_r1cs_std::R1CSVar;
|
||||
use ark_relations::r1cs::ConstraintSystem;
|
||||
use ark_std::UniformRand;
|
||||
|
||||
#[test]
|
||||
fn from_test() {
|
||||
type F = ark_bls12_377::Fr;
|
||||
type CF = ark_bls12_377::Fq;
|
||||
|
||||
let mut rng = ark_std::test_rng();
|
||||
let cs = ConstraintSystem::<CF>::new_ref();
|
||||
let f = F::rand(&mut rng);
|
||||
|
||||
let f_var = NonNativeFieldVar::<F, CF>::new_input(cs.clone(), || Ok(f)).unwrap();
|
||||
let f_var_converted = NonNativeFieldMulResultVar::<F, CF>::from(&f_var);
|
||||
let f_var_converted_reduced = f_var_converted.reduce().unwrap();
|
||||
|
||||
let f_var_value = f_var.value().unwrap();
|
||||
let f_var_converted_reduced_value = f_var_converted_reduced.value().unwrap();
|
||||
|
||||
assert_eq!(f_var_value, f_var_converted_reduced_value);
|
||||
}
|
||||
50
tests/to_bytes_test.rs
Normal file
50
tests/to_bytes_test.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use ark_ec::PairingEngine;
|
||||
use ark_ff::{to_bytes, Zero};
|
||||
use ark_mnt4_298::MNT4_298;
|
||||
use ark_mnt6_298::MNT6_298;
|
||||
use ark_r1cs_std::alloc::AllocVar;
|
||||
use ark_r1cs_std::fields::nonnative::NonNativeFieldVar;
|
||||
use ark_r1cs_std::{R1CSVar, ToBitsGadget, ToBytesGadget};
|
||||
use ark_relations::r1cs::ConstraintSystem;
|
||||
|
||||
#[test]
|
||||
fn to_bytes_test() {
|
||||
let cs = ConstraintSystem::<<MNT6_298 as PairingEngine>::Fr>::new_ref();
|
||||
|
||||
let target_test_elem = <MNT4_298 as PairingEngine>::Fr::from(123456u128);
|
||||
let target_test_gadget = NonNativeFieldVar::<
|
||||
<MNT4_298 as PairingEngine>::Fr,
|
||||
<MNT6_298 as PairingEngine>::Fr,
|
||||
>::new_witness(cs, || Ok(target_test_elem))
|
||||
.unwrap();
|
||||
|
||||
let target_to_bytes: Vec<u8> = target_test_gadget
|
||||
.to_bytes()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|v| v.value().unwrap())
|
||||
.collect();
|
||||
|
||||
// 123456 = 65536 + 226 * 256 + 64
|
||||
assert_eq!(target_to_bytes[0], 64);
|
||||
assert_eq!(target_to_bytes[1], 226);
|
||||
assert_eq!(target_to_bytes[2], 1);
|
||||
|
||||
for byte in target_to_bytes.iter().skip(3) {
|
||||
assert_eq!(*byte, 0);
|
||||
}
|
||||
|
||||
assert_eq!(to_bytes!(target_test_elem).unwrap(), target_to_bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_bits_test() {
|
||||
type F = ark_bls12_377::Fr;
|
||||
type CF = ark_bls12_377::Fq;
|
||||
|
||||
let cs = ConstraintSystem::<CF>::new_ref();
|
||||
let f = F::zero();
|
||||
|
||||
let f_var = NonNativeFieldVar::<F, CF>::new_input(cs.clone(), || Ok(f)).unwrap();
|
||||
f_var.to_bits_le().unwrap();
|
||||
}
|
||||
28
tests/to_constraint_field_test.rs
Normal file
28
tests/to_constraint_field_test.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
use ark_r1cs_std::alloc::AllocVar;
|
||||
use ark_r1cs_std::fields::nonnative::NonNativeFieldVar;
|
||||
use ark_r1cs_std::{R1CSVar, ToConstraintFieldGadget};
|
||||
use ark_relations::r1cs::ConstraintSystem;
|
||||
|
||||
#[test]
|
||||
fn to_constraint_field_test() {
|
||||
type F = ark_bls12_377::Fr;
|
||||
type CF = ark_bls12_377::Fq;
|
||||
|
||||
let cs = ConstraintSystem::<CF>::new_ref();
|
||||
|
||||
let a = NonNativeFieldVar::Constant(F::from(12u8));
|
||||
let b = NonNativeFieldVar::new_input(cs.clone(), || Ok(F::from(6u8))).unwrap();
|
||||
|
||||
let b2 = &b + &b;
|
||||
|
||||
let a_to_constraint_field = a.to_constraint_field().unwrap();
|
||||
let b2_to_constraint_field = b2.to_constraint_field().unwrap();
|
||||
|
||||
assert_eq!(a_to_constraint_field.len(), b2_to_constraint_field.len());
|
||||
for (left, right) in a_to_constraint_field
|
||||
.iter()
|
||||
.zip(b2_to_constraint_field.iter())
|
||||
{
|
||||
assert_eq!(left.value(), right.value());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user