2020-07-10 12:07:00 +03:00
|
|
|
use leo_gadgets::{arithmetic::Add, Int8};
|
|
|
|
use snarkos_models::{
|
|
|
|
curves::{One, Zero},
|
|
|
|
gadgets::{
|
|
|
|
r1cs::{ConstraintSystem, Fr, TestConstraintSystem},
|
|
|
|
utilities::{alloc::AllocGadget, boolean::Boolean},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
use rand::{Rng, SeedableRng};
|
|
|
|
use rand_xorshift::XorShiftRng;
|
|
|
|
|
|
|
|
fn check_all_constant_bits(mut expected: i8, actual: Int8) {
|
|
|
|
for b in actual.bits.iter() {
|
|
|
|
match b {
|
|
|
|
&Boolean::Is(_) => panic!(),
|
|
|
|
&Boolean::Not(_) => panic!(),
|
|
|
|
&Boolean::Constant(b) => {
|
|
|
|
assert!(b == (expected & 1 == 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expected >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_all_allocated_bits(mut expected: i8, actual: Int8) {
|
|
|
|
for b in actual.bits.iter() {
|
|
|
|
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!(),
|
|
|
|
}
|
|
|
|
|
|
|
|
expected >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_int8_add_constants() {
|
|
|
|
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
|
|
|
|
|
|
|
for _ in 0..1000 {
|
|
|
|
let mut cs = TestConstraintSystem::<Fr>::new();
|
|
|
|
|
|
|
|
let a: i8 = rng.gen();
|
|
|
|
let b: i8 = rng.gen();
|
|
|
|
|
|
|
|
let a_bit = Int8::constant(a);
|
|
|
|
let b_bit = Int8::constant(b);
|
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
let expected = match a.checked_add(b) {
|
|
|
|
Some(valid) => valid,
|
|
|
|
None => continue,
|
|
|
|
};
|
2020-07-10 12:07:00 +03:00
|
|
|
|
|
|
|
let r = a_bit.add(cs.ns(|| "addition"), &b_bit).unwrap();
|
|
|
|
|
|
|
|
assert!(r.value == Some(expected));
|
|
|
|
|
|
|
|
check_all_constant_bits(expected, r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-10 14:04:55 +03:00
|
|
|
#[test]
|
|
|
|
fn test_int8_add() {
|
|
|
|
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
for _ in 0..1000 {
|
|
|
|
let mut cs = TestConstraintSystem::<Fr>::new();
|
2020-07-10 14:04:55 +03:00
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
let a: i8 = rng.gen();
|
|
|
|
let b: i8 = rng.gen();
|
2020-07-10 14:04:55 +03:00
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
let expected = match a.checked_add(b) {
|
|
|
|
Some(valid) => valid,
|
|
|
|
None => continue,
|
|
|
|
};
|
2020-07-10 14:04:55 +03:00
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
let a_bit = Int8::alloc(cs.ns(|| "a_bit"), || Ok(a)).unwrap();
|
|
|
|
let b_bit = Int8::alloc(cs.ns(|| "b_bit"), || Ok(b)).unwrap();
|
2020-07-10 14:04:55 +03:00
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
let r = a_bit.add(cs.ns(|| "addition"), &b_bit).unwrap();
|
2020-07-10 14:04:55 +03:00
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
assert!(cs.is_satisfied());
|
2020-07-10 14:04:55 +03:00
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
assert!(r.value == Some(expected));
|
2020-07-10 14:04:55 +03:00
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
check_all_allocated_bits(expected, r);
|
2020-07-10 14:04:55 +03:00
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
// Flip a bit_gadget and see if the addition constraint still works
|
|
|
|
if cs.get("addition/result bit_gadget 0/boolean").is_zero() {
|
|
|
|
cs.set("addition/result bit_gadget 0/boolean", Fr::one());
|
|
|
|
} else {
|
|
|
|
cs.set("addition/result bit_gadget 0/boolean", Fr::zero());
|
|
|
|
}
|
2020-07-10 14:04:55 +03:00
|
|
|
|
2020-07-11 04:05:37 +03:00
|
|
|
assert!(!cs.is_satisfied());
|
2020-07-10 14:04:55 +03:00
|
|
|
}
|
|
|
|
}
|