Merge branch 'master' into inline-asm

This commit is contained in:
jon-chuang
2020-04-08 20:40:30 +08:00
committed by GitHub
44 changed files with 654 additions and 848 deletions

View File

@@ -13,7 +13,7 @@ problem_files=()
# collect ill-formatted files # collect ill-formatted files
for file in $(git diff --name-only --cached); do for file in $(git diff --name-only --cached); do
if [ ${file: -3} == ".rs" ]; then if [ ${file: -3} == ".rs" ]; then
rustfmt +nightly --check $file &>/dev/null rustfmt +stable --check $file &>/dev/null
if [ $? != 0 ]; then if [ $? != 0 ]; then
problem_files+=($file) problem_files+=($file)
fi fi
@@ -27,7 +27,7 @@ else
# reformat the files that need it and re-stage them. # reformat the files that need it and re-stage them.
printf "[pre_commit] the following files were rustfmt'd before commit: \n" printf "[pre_commit] the following files were rustfmt'd before commit: \n"
for file in ${problem_files[@]}; do for file in ${problem_files[@]}; do
rustfmt $file rustfmt +stable $file
git add $file git add $file
printf "\033[0;32m $file\033[0m \n" printf "\033[0;32m $file\033[0m \n"
done done

View File

@@ -248,7 +248,7 @@ impl core::fmt::Display for MerkleTreeError {
let msg = match self { let msg = match self {
MerkleTreeError::IncorrectLeafIndex(index) => { MerkleTreeError::IncorrectLeafIndex(index) => {
format!("incorrect leaf index: {}", index) format!("incorrect leaf index: {}", index)
}, }
MerkleTreeError::IncorrectPathLength(len) => format!("incorrect path length: {}", len), MerkleTreeError::IncorrectPathLength(len) => format!("incorrect path length: {}", len),
}; };
write!(f, "{}", msg) write!(f, "{}", msg)

View File

@@ -664,14 +664,14 @@ mod test {
match b { match b {
Boolean::Is(b) => { Boolean::Is(b) => {
assert!(s.next().unwrap() == b.get_value().unwrap()); assert!(s.next().unwrap() == b.get_value().unwrap());
}, }
Boolean::Not(b) => { Boolean::Not(b) => {
assert!(s.next().unwrap() != b.get_value().unwrap()); assert!(s.next().unwrap() != b.get_value().unwrap());
}, }
Boolean::Constant(b) => { Boolean::Constant(b) => {
assert!(input_len == 0); assert!(input_len == 0);
assert!(s.next().unwrap() == b); assert!(s.next().unwrap() == b);
}, }
} }
} }
} }

View File

@@ -400,11 +400,11 @@ impl Boolean {
} else { } else {
LinearCombination::<ConstraintF>::zero() LinearCombination::<ConstraintF>::zero()
} }
}, }
Boolean::Is(ref v) => (coeff, v.get_variable()).into(), Boolean::Is(ref v) => (coeff, v.get_variable()).into(),
Boolean::Not(ref v) => { Boolean::Not(ref v) => {
LinearCombination::<ConstraintF>::zero() + (coeff, one) - (coeff, v.get_variable()) LinearCombination::<ConstraintF>::zero() + (coeff, one) - (coeff, v.get_variable())
}, }
} }
} }
@@ -458,12 +458,12 @@ impl Boolean {
(is @ &Boolean::Is(_), not @ &Boolean::Not(_)) (is @ &Boolean::Is(_), not @ &Boolean::Not(_))
| (not @ &Boolean::Not(_), is @ &Boolean::Is(_)) => { | (not @ &Boolean::Not(_), is @ &Boolean::Is(_)) => {
Ok(Boolean::xor(cs, is, &not.not())?.not()) Ok(Boolean::xor(cs, is, &not.not())?.not())
}, }
// a XOR b = (NOT a) XOR (NOT b) // a XOR b = (NOT a) XOR (NOT b)
(&Boolean::Is(ref a), &Boolean::Is(ref b)) (&Boolean::Is(ref a), &Boolean::Is(ref b))
| (&Boolean::Not(ref a), &Boolean::Not(ref b)) => { | (&Boolean::Not(ref a), &Boolean::Not(ref b)) => {
Ok(Boolean::Is(AllocatedBit::xor(cs, a, b)?)) Ok(Boolean::Is(AllocatedBit::xor(cs, a, b)?))
}, }
} }
} }
@@ -477,16 +477,16 @@ impl Boolean {
(&Boolean::Constant(false), x) | (x, &Boolean::Constant(false)) => Ok(*x), (&Boolean::Constant(false), x) | (x, &Boolean::Constant(false)) => Ok(*x),
(&Boolean::Constant(true), _) | (_, &Boolean::Constant(true)) => { (&Boolean::Constant(true), _) | (_, &Boolean::Constant(true)) => {
Ok(Boolean::Constant(true)) Ok(Boolean::Constant(true))
}, }
// a OR b = NOT ((NOT a) AND b) // a OR b = NOT ((NOT a) AND b)
(a @ &Boolean::Is(_), b @ &Boolean::Not(_)) (a @ &Boolean::Is(_), b @ &Boolean::Not(_))
| (b @ &Boolean::Not(_), a @ &Boolean::Is(_)) | (b @ &Boolean::Not(_), a @ &Boolean::Is(_))
| (b @ &Boolean::Not(_), a @ &Boolean::Not(_)) => { | (b @ &Boolean::Not(_), a @ &Boolean::Not(_)) => {
Ok(Boolean::and(cs, &a.not(), &b.not())?.not()) Ok(Boolean::and(cs, &a.not(), &b.not())?.not())
}, }
(&Boolean::Is(ref a), &Boolean::Is(ref b)) => { (&Boolean::Is(ref a), &Boolean::Is(ref b)) => {
AllocatedBit::or(cs, a, b).map(Boolean::from) AllocatedBit::or(cs, a, b).map(Boolean::from)
}, }
} }
} }
@@ -504,22 +504,22 @@ impl Boolean {
// false AND x is always false // false AND x is always false
(&Boolean::Constant(false), _) | (_, &Boolean::Constant(false)) => { (&Boolean::Constant(false), _) | (_, &Boolean::Constant(false)) => {
Ok(Boolean::Constant(false)) Ok(Boolean::Constant(false))
}, }
// true AND x is always x // true AND x is always x
(&Boolean::Constant(true), x) | (x, &Boolean::Constant(true)) => Ok(*x), (&Boolean::Constant(true), x) | (x, &Boolean::Constant(true)) => Ok(*x),
// a AND (NOT b) // a AND (NOT b)
(&Boolean::Is(ref is), &Boolean::Not(ref not)) (&Boolean::Is(ref is), &Boolean::Not(ref not))
| (&Boolean::Not(ref not), &Boolean::Is(ref is)) => { | (&Boolean::Not(ref not), &Boolean::Is(ref is)) => {
Ok(Boolean::Is(AllocatedBit::and_not(cs, is, not)?)) Ok(Boolean::Is(AllocatedBit::and_not(cs, is, not)?))
}, }
// (NOT a) AND (NOT b) = a NOR b // (NOT a) AND (NOT b) = a NOR b
(&Boolean::Not(ref a), &Boolean::Not(ref b)) => { (&Boolean::Not(ref a), &Boolean::Not(ref b)) => {
Ok(Boolean::Is(AllocatedBit::nor(cs, a, b)?)) Ok(Boolean::Is(AllocatedBit::nor(cs, a, b)?))
}, }
// a AND b // a AND b
(&Boolean::Is(ref a), &Boolean::Is(ref b)) => { (&Boolean::Is(ref a), &Boolean::Is(ref b)) => {
Ok(Boolean::Is(AllocatedBit::and(cs, a, b)?)) Ok(Boolean::Is(AllocatedBit::and(cs, a, b)?))
}, }
} }
} }
@@ -559,7 +559,7 @@ impl Boolean {
); );
Ok(()) Ok(())
}, }
Boolean::Not(ref res) => { Boolean::Not(ref res) => {
cs.enforce( cs.enforce(
|| "enforce nand", || "enforce nand",
@@ -569,7 +569,7 @@ impl Boolean {
); );
Ok(()) Ok(())
}, }
} }
} }
@@ -760,25 +760,25 @@ impl<ConstraintF: Field> ConditionalEqGadget<ConstraintF> for Boolean {
// 1 - a // 1 - a
(Constant(true), Is(a)) | (Is(a), Constant(true)) => { (Constant(true), Is(a)) | (Is(a), Constant(true)) => {
LinearCombination::zero() + one - a.get_variable() LinearCombination::zero() + one - a.get_variable()
}, }
// a - 0 = a // a - 0 = a
(Constant(false), Is(a)) | (Is(a), Constant(false)) => { (Constant(false), Is(a)) | (Is(a), Constant(false)) => {
LinearCombination::zero() + a.get_variable() LinearCombination::zero() + a.get_variable()
}, }
// 1 - !a = 1 - (1 - a) = a // 1 - !a = 1 - (1 - a) = a
(Constant(true), Not(a)) | (Not(a), Constant(true)) => { (Constant(true), Not(a)) | (Not(a), Constant(true)) => {
LinearCombination::zero() + a.get_variable() LinearCombination::zero() + a.get_variable()
}, }
// !a - 0 = !a = 1 - a // !a - 0 = !a = 1 - a
(Constant(false), Not(a)) | (Not(a), Constant(false)) => { (Constant(false), Not(a)) | (Not(a), Constant(false)) => {
LinearCombination::zero() + one - a.get_variable() LinearCombination::zero() + one - a.get_variable()
}, }
// b - a, // b - a,
(Is(a), Is(b)) => LinearCombination::zero() + b.get_variable() - a.get_variable(), (Is(a), Is(b)) => LinearCombination::zero() + b.get_variable() - a.get_variable(),
// !b - a = (1 - b) - a // !b - a = (1 - b) - a
(Is(a), Not(b)) | (Not(b), Is(a)) => { (Is(a), Not(b)) | (Not(b), Is(a)) => {
LinearCombination::zero() + one - b.get_variable() - a.get_variable() LinearCombination::zero() + one - b.get_variable() - a.get_variable()
}, }
// !b - !a = (1 - b) - (1 - a) = a - b, // !b - !a = (1 - b) - (1 - a) = a - b,
(Not(a), Not(b)) => LinearCombination::zero() + a.get_variable() - b.get_variable(), (Not(a), Not(b)) => LinearCombination::zero() + a.get_variable() - b.get_variable(),
}; };
@@ -831,7 +831,7 @@ impl<ConstraintF: PrimeField> CondSelectGadget<ConstraintF> for Boolean {
Boolean::Constant(false) => Ok(false_value.clone()), Boolean::Constant(false) => Ok(false_value.clone()),
cond @ Boolean::Not(_) => { cond @ Boolean::Not(_) => {
Self::conditionally_select(cs, &cond.not(), false_value, true_value) Self::conditionally_select(cs, &cond.not(), false_value, true_value)
}, }
cond @ Boolean::Is(_) => match (true_value, false_value) { cond @ Boolean::Is(_) => match (true_value, false_value) {
(x, &Boolean::Constant(false)) => Boolean::and(cs.ns(|| "and"), cond, x).into(), (x, &Boolean::Constant(false)) => Boolean::and(cs.ns(|| "and"), cond, x).into(),
(&Boolean::Constant(false), x) => Boolean::and(cs.ns(|| "and"), &cond.not(), x), (&Boolean::Constant(false), x) => Boolean::and(cs.ns(|| "and"), &cond.not(), x),
@@ -847,7 +847,7 @@ impl<ConstraintF: PrimeField> CondSelectGadget<ConstraintF> for Boolean {
cond_select_helper(cs, cond, (a.get_value(), a_lc), (b.get_value(), b_lc))? cond_select_helper(cs, cond, (a.get_value(), a_lc), (b.get_value(), b_lc))?
.into(), .into(),
) )
}, }
}, },
} }
} }
@@ -1138,42 +1138,42 @@ mod test {
let mut b = Boolean::from(AllocatedBit::alloc(&mut cs, || Ok(true)).unwrap()); let mut b = Boolean::from(AllocatedBit::alloc(&mut cs, || Ok(true)).unwrap());
match b { match b {
Boolean::Is(_) => {}, Boolean::Is(_) => {}
_ => panic!("unexpected value"), _ => panic!("unexpected value"),
} }
b = b.not(); b = b.not();
match b { match b {
Boolean::Not(_) => {}, Boolean::Not(_) => {}
_ => panic!("unexpected value"), _ => panic!("unexpected value"),
} }
b = b.not(); b = b.not();
match b { match b {
Boolean::Is(_) => {}, Boolean::Is(_) => {}
_ => panic!("unexpected value"), _ => panic!("unexpected value"),
} }
b = Boolean::constant(true); b = Boolean::constant(true);
match b { match b {
Boolean::Constant(true) => {}, Boolean::Constant(true) => {}
_ => panic!("unexpected value"), _ => panic!("unexpected value"),
} }
b = b.not(); b = b.not();
match b { match b {
Boolean::Constant(false) => {}, Boolean::Constant(false) => {}
_ => panic!("unexpected value"), _ => panic!("unexpected value"),
} }
b = b.not(); b = b.not();
match b { match b {
Boolean::Constant(true) => {}, Boolean::Constant(true) => {}
_ => panic!("unexpected value"), _ => panic!("unexpected value"),
} }
} }
@@ -1215,16 +1215,16 @@ mod test {
OperandType::False => Boolean::constant(false), OperandType::False => Boolean::constant(false),
OperandType::AllocatedTrue => { OperandType::AllocatedTrue => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap())
}, }
OperandType::AllocatedFalse => { OperandType::AllocatedFalse => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap())
}, }
OperandType::NegatedAllocatedTrue => { OperandType::NegatedAllocatedTrue => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()).not() Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()).not()
}, }
OperandType::NegatedAllocatedFalse => { OperandType::NegatedAllocatedFalse => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()).not() Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()).not()
}, }
} }
}; };
@@ -1237,22 +1237,22 @@ mod test {
assert!(cs.is_satisfied()); assert!(cs.is_satisfied());
match (first_operand, second_operand, c) { match (first_operand, second_operand, c) {
(OperandType::True, OperandType::True, Boolean::Constant(false)) => {}, (OperandType::True, OperandType::True, Boolean::Constant(false)) => {}
(OperandType::True, OperandType::False, Boolean::Constant(true)) => {}, (OperandType::True, OperandType::False, Boolean::Constant(true)) => {}
(OperandType::True, OperandType::AllocatedTrue, Boolean::Not(_)) => {}, (OperandType::True, OperandType::AllocatedTrue, Boolean::Not(_)) => {}
(OperandType::True, OperandType::AllocatedFalse, Boolean::Not(_)) => {}, (OperandType::True, OperandType::AllocatedFalse, Boolean::Not(_)) => {}
(OperandType::True, OperandType::NegatedAllocatedTrue, Boolean::Is(_)) => {}, (OperandType::True, OperandType::NegatedAllocatedTrue, Boolean::Is(_)) => {}
(OperandType::True, OperandType::NegatedAllocatedFalse, Boolean::Is(_)) => {}, (OperandType::True, OperandType::NegatedAllocatedFalse, Boolean::Is(_)) => {}
(OperandType::False, OperandType::True, Boolean::Constant(true)) => {}, (OperandType::False, OperandType::True, Boolean::Constant(true)) => {}
(OperandType::False, OperandType::False, Boolean::Constant(false)) => {}, (OperandType::False, OperandType::False, Boolean::Constant(false)) => {}
(OperandType::False, OperandType::AllocatedTrue, Boolean::Is(_)) => {}, (OperandType::False, OperandType::AllocatedTrue, Boolean::Is(_)) => {}
(OperandType::False, OperandType::AllocatedFalse, Boolean::Is(_)) => {}, (OperandType::False, OperandType::AllocatedFalse, Boolean::Is(_)) => {}
(OperandType::False, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {}, (OperandType::False, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {}
(OperandType::False, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {}, (OperandType::False, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {}
(OperandType::AllocatedTrue, OperandType::True, Boolean::Not(_)) => {}, (OperandType::AllocatedTrue, OperandType::True, Boolean::Not(_)) => {}
(OperandType::AllocatedTrue, OperandType::False, Boolean::Is(_)) => {}, (OperandType::AllocatedTrue, OperandType::False, Boolean::Is(_)) => {}
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
@@ -1260,7 +1260,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::zero()); assert!(cs.get("xor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
@@ -1268,7 +1268,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::one()); assert!(cs.get("xor result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
@@ -1276,7 +1276,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::zero()); assert!(cs.get("xor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
@@ -1284,10 +1284,10 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::one()); assert!(cs.get("xor result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
(OperandType::AllocatedFalse, OperandType::True, Boolean::Not(_)) => {}, (OperandType::AllocatedFalse, OperandType::True, Boolean::Not(_)) => {}
(OperandType::AllocatedFalse, OperandType::False, Boolean::Is(_)) => {}, (OperandType::AllocatedFalse, OperandType::False, Boolean::Is(_)) => {}
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
@@ -1295,7 +1295,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::one()); assert!(cs.get("xor result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
@@ -1303,7 +1303,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::zero()); assert!(cs.get("xor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
@@ -1311,7 +1311,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::one()); assert!(cs.get("xor result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
@@ -1319,10 +1319,10 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::zero()); assert!(cs.get("xor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
(OperandType::NegatedAllocatedTrue, OperandType::True, Boolean::Is(_)) => {}, (OperandType::NegatedAllocatedTrue, OperandType::True, Boolean::Is(_)) => {}
(OperandType::NegatedAllocatedTrue, OperandType::False, Boolean::Not(_)) => {}, (OperandType::NegatedAllocatedTrue, OperandType::False, Boolean::Not(_)) => {}
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
@@ -1330,7 +1330,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::zero()); assert!(cs.get("xor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
@@ -1338,7 +1338,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::one()); assert!(cs.get("xor result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
@@ -1346,7 +1346,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::zero()); assert!(cs.get("xor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
@@ -1354,10 +1354,10 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::one()); assert!(cs.get("xor result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
(OperandType::NegatedAllocatedFalse, OperandType::True, Boolean::Is(_)) => {}, (OperandType::NegatedAllocatedFalse, OperandType::True, Boolean::Is(_)) => {}
(OperandType::NegatedAllocatedFalse, OperandType::False, Boolean::Not(_)) => {}, (OperandType::NegatedAllocatedFalse, OperandType::False, Boolean::Not(_)) => {}
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
@@ -1365,7 +1365,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::one()); assert!(cs.get("xor result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
@@ -1373,7 +1373,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::zero()); assert!(cs.get("xor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
@@ -1381,7 +1381,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::one()); assert!(cs.get("xor result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
@@ -1389,7 +1389,7 @@ mod test {
) => { ) => {
assert!(cs.get("xor result") == Fr::zero()); assert!(cs.get("xor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
_ => panic!("this should never be encountered"), _ => panic!("this should never be encountered"),
} }
@@ -1426,18 +1426,18 @@ mod test {
OperandType::False => Boolean::constant(false), OperandType::False => Boolean::constant(false),
OperandType::AllocatedTrue => { OperandType::AllocatedTrue => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap())
}, }
OperandType::AllocatedFalse => { OperandType::AllocatedFalse => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap())
}, }
OperandType::NegatedAllocatedTrue => { OperandType::NegatedAllocatedTrue => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap())
.not() .not()
}, }
OperandType::NegatedAllocatedFalse => { OperandType::NegatedAllocatedFalse => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap())
.not() .not()
}, }
} }
}; };
@@ -1498,16 +1498,16 @@ mod test {
OperandType::False => Boolean::constant(false), OperandType::False => Boolean::constant(false),
OperandType::AllocatedTrue => { OperandType::AllocatedTrue => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap())
}, }
OperandType::AllocatedFalse => { OperandType::AllocatedFalse => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap())
}, }
OperandType::NegatedAllocatedTrue => { OperandType::NegatedAllocatedTrue => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()).not() Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()).not()
}, }
OperandType::NegatedAllocatedFalse => { OperandType::NegatedAllocatedFalse => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()).not() Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()).not()
}, }
} }
}; };
@@ -1520,159 +1520,159 @@ mod test {
assert!(cs.is_satisfied()); assert!(cs.is_satisfied());
match (first_operand, second_operand, c) { match (first_operand, second_operand, c) {
(OperandType::True, OperandType::True, Boolean::Constant(true)) => {}, (OperandType::True, OperandType::True, Boolean::Constant(true)) => {}
(OperandType::True, OperandType::False, Boolean::Constant(true)) => {}, (OperandType::True, OperandType::False, Boolean::Constant(true)) => {}
(OperandType::True, OperandType::AllocatedTrue, Boolean::Constant(true)) => {}, (OperandType::True, OperandType::AllocatedTrue, Boolean::Constant(true)) => {}
(OperandType::True, OperandType::AllocatedFalse, Boolean::Constant(true)) => {}, (OperandType::True, OperandType::AllocatedFalse, Boolean::Constant(true)) => {}
( (
OperandType::True, OperandType::True,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
Boolean::Constant(true), Boolean::Constant(true),
) => {}, ) => {}
( (
OperandType::True, OperandType::True,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
Boolean::Constant(true), Boolean::Constant(true),
) => {}, ) => {}
(OperandType::False, OperandType::True, Boolean::Constant(true)) => {}, (OperandType::False, OperandType::True, Boolean::Constant(true)) => {}
(OperandType::False, OperandType::False, Boolean::Constant(false)) => {}, (OperandType::False, OperandType::False, Boolean::Constant(false)) => {}
(OperandType::False, OperandType::AllocatedTrue, Boolean::Is(_)) => {}, (OperandType::False, OperandType::AllocatedTrue, Boolean::Is(_)) => {}
(OperandType::False, OperandType::AllocatedFalse, Boolean::Is(_)) => {}, (OperandType::False, OperandType::AllocatedFalse, Boolean::Is(_)) => {}
(OperandType::False, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {}, (OperandType::False, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {}
(OperandType::False, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {}, (OperandType::False, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {}
(OperandType::AllocatedTrue, OperandType::True, Boolean::Constant(true)) => {}, (OperandType::AllocatedTrue, OperandType::True, Boolean::Constant(true)) => {}
(OperandType::AllocatedTrue, OperandType::False, Boolean::Is(_)) => {}, (OperandType::AllocatedTrue, OperandType::False, Boolean::Is(_)) => {}
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
Boolean::Is(ref v), Boolean::Is(ref v),
) => { ) => {
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
Boolean::Is(ref v), Boolean::Is(ref v),
) => { ) => {
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
(OperandType::AllocatedFalse, OperandType::True, Boolean::Constant(true)) => {}, (OperandType::AllocatedFalse, OperandType::True, Boolean::Constant(true)) => {}
(OperandType::AllocatedFalse, OperandType::False, Boolean::Is(_)) => {}, (OperandType::AllocatedFalse, OperandType::False, Boolean::Is(_)) => {}
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
Boolean::Is(ref v), Boolean::Is(ref v),
) => { ) => {
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
Boolean::Is(ref v), Boolean::Is(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::True, OperandType::True,
Boolean::Constant(true), Boolean::Constant(true),
) => {}, ) => {}
(OperandType::NegatedAllocatedTrue, OperandType::False, Boolean::Not(_)) => {}, (OperandType::NegatedAllocatedTrue, OperandType::False, Boolean::Not(_)) => {}
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::True, OperandType::True,
Boolean::Constant(true), Boolean::Constant(true),
) => {}, ) => {}
(OperandType::NegatedAllocatedFalse, OperandType::False, Boolean::Not(_)) => {}, (OperandType::NegatedAllocatedFalse, OperandType::False, Boolean::Not(_)) => {}
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
Boolean::Not(ref v), Boolean::Not(ref v),
) => { ) => {
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
_ => panic!( _ => panic!(
"this should never be encountered, in case: (a = {:?}, b = {:?}, c = {:?})", "this should never be encountered, in case: (a = {:?}, b = {:?}, c = {:?})",
@@ -1710,16 +1710,16 @@ mod test {
OperandType::False => Boolean::constant(false), OperandType::False => Boolean::constant(false),
OperandType::AllocatedTrue => { OperandType::AllocatedTrue => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap())
}, }
OperandType::AllocatedFalse => { OperandType::AllocatedFalse => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()) Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap())
}, }
OperandType::NegatedAllocatedTrue => { OperandType::NegatedAllocatedTrue => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()).not() Boolean::from(AllocatedBit::alloc(cs, || Ok(true)).unwrap()).not()
}, }
OperandType::NegatedAllocatedFalse => { OperandType::NegatedAllocatedFalse => {
Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()).not() Boolean::from(AllocatedBit::alloc(cs, || Ok(false)).unwrap()).not()
}, }
} }
}; };
@@ -1732,33 +1732,31 @@ mod test {
assert!(cs.is_satisfied()); assert!(cs.is_satisfied());
match (first_operand, second_operand, c) { match (first_operand, second_operand, c) {
(OperandType::True, OperandType::True, Boolean::Constant(true)) => {}, (OperandType::True, OperandType::True, Boolean::Constant(true)) => {}
(OperandType::True, OperandType::False, Boolean::Constant(false)) => {}, (OperandType::True, OperandType::False, Boolean::Constant(false)) => {}
(OperandType::True, OperandType::AllocatedTrue, Boolean::Is(_)) => {}, (OperandType::True, OperandType::AllocatedTrue, Boolean::Is(_)) => {}
(OperandType::True, OperandType::AllocatedFalse, Boolean::Is(_)) => {}, (OperandType::True, OperandType::AllocatedFalse, Boolean::Is(_)) => {}
(OperandType::True, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {}, (OperandType::True, OperandType::NegatedAllocatedTrue, Boolean::Not(_)) => {}
(OperandType::True, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {}, (OperandType::True, OperandType::NegatedAllocatedFalse, Boolean::Not(_)) => {}
(OperandType::False, OperandType::True, Boolean::Constant(false)) => {}, (OperandType::False, OperandType::True, Boolean::Constant(false)) => {}
(OperandType::False, OperandType::False, Boolean::Constant(false)) => {}, (OperandType::False, OperandType::False, Boolean::Constant(false)) => {}
(OperandType::False, OperandType::AllocatedTrue, Boolean::Constant(false)) => { (OperandType::False, OperandType::AllocatedTrue, Boolean::Constant(false)) => {}
},
(OperandType::False, OperandType::AllocatedFalse, Boolean::Constant(false)) => { (OperandType::False, OperandType::AllocatedFalse, Boolean::Constant(false)) => {
}, }
( (
OperandType::False, OperandType::False,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
Boolean::Constant(false), Boolean::Constant(false),
) => {}, ) => {}
( (
OperandType::False, OperandType::False,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
Boolean::Constant(false), Boolean::Constant(false),
) => {}, ) => {}
(OperandType::AllocatedTrue, OperandType::True, Boolean::Is(_)) => {}, (OperandType::AllocatedTrue, OperandType::True, Boolean::Is(_)) => {}
(OperandType::AllocatedTrue, OperandType::False, Boolean::Constant(false)) => { (OperandType::AllocatedTrue, OperandType::False, Boolean::Constant(false)) => {}
},
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
@@ -1766,7 +1764,7 @@ mod test {
) => { ) => {
assert!(cs.get("and result") == Fr::one()); assert!(cs.get("and result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
@@ -1774,7 +1772,7 @@ mod test {
) => { ) => {
assert!(cs.get("and result") == Fr::zero()); assert!(cs.get("and result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
@@ -1782,7 +1780,7 @@ mod test {
) => { ) => {
assert!(cs.get("and not result") == Fr::zero()); assert!(cs.get("and not result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
@@ -1790,11 +1788,11 @@ mod test {
) => { ) => {
assert!(cs.get("and not result") == Fr::one()); assert!(cs.get("and not result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
(OperandType::AllocatedFalse, OperandType::True, Boolean::Is(_)) => {}, (OperandType::AllocatedFalse, OperandType::True, Boolean::Is(_)) => {}
(OperandType::AllocatedFalse, OperandType::False, Boolean::Constant(false)) => { (OperandType::AllocatedFalse, OperandType::False, Boolean::Constant(false)) => {
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
@@ -1802,7 +1800,7 @@ mod test {
) => { ) => {
assert!(cs.get("and result") == Fr::zero()); assert!(cs.get("and result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
@@ -1810,7 +1808,7 @@ mod test {
) => { ) => {
assert!(cs.get("and result") == Fr::zero()); assert!(cs.get("and result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
@@ -1818,7 +1816,7 @@ mod test {
) => { ) => {
assert!(cs.get("and not result") == Fr::zero()); assert!(cs.get("and not result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
@@ -1826,14 +1824,14 @@ mod test {
) => { ) => {
assert!(cs.get("and not result") == Fr::zero()); assert!(cs.get("and not result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
(OperandType::NegatedAllocatedTrue, OperandType::True, Boolean::Not(_)) => {}, (OperandType::NegatedAllocatedTrue, OperandType::True, Boolean::Not(_)) => {}
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::False, OperandType::False,
Boolean::Constant(false), Boolean::Constant(false),
) => {}, ) => {}
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
@@ -1841,7 +1839,7 @@ mod test {
) => { ) => {
assert!(cs.get("and not result") == Fr::zero()); assert!(cs.get("and not result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
@@ -1849,7 +1847,7 @@ mod test {
) => { ) => {
assert!(cs.get("and not result") == Fr::zero()); assert!(cs.get("and not result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
@@ -1857,7 +1855,7 @@ mod test {
) => { ) => {
assert!(cs.get("nor result") == Fr::zero()); assert!(cs.get("nor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
@@ -1865,14 +1863,14 @@ mod test {
) => { ) => {
assert!(cs.get("nor result") == Fr::zero()); assert!(cs.get("nor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
(OperandType::NegatedAllocatedFalse, OperandType::True, Boolean::Not(_)) => {}, (OperandType::NegatedAllocatedFalse, OperandType::True, Boolean::Not(_)) => {}
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::False, OperandType::False,
Boolean::Constant(false), Boolean::Constant(false),
) => {}, ) => {}
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::AllocatedTrue, OperandType::AllocatedTrue,
@@ -1880,7 +1878,7 @@ mod test {
) => { ) => {
assert!(cs.get("and not result") == Fr::one()); assert!(cs.get("and not result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::AllocatedFalse, OperandType::AllocatedFalse,
@@ -1888,7 +1886,7 @@ mod test {
) => { ) => {
assert!(cs.get("and not result") == Fr::zero()); assert!(cs.get("and not result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::NegatedAllocatedTrue, OperandType::NegatedAllocatedTrue,
@@ -1896,7 +1894,7 @@ mod test {
) => { ) => {
assert!(cs.get("nor result") == Fr::zero()); assert!(cs.get("nor result") == Fr::zero());
assert_eq!(v.value, Some(false)); assert_eq!(v.value, Some(false));
}, }
( (
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
OperandType::NegatedAllocatedFalse, OperandType::NegatedAllocatedFalse,
@@ -1904,14 +1902,14 @@ mod test {
) => { ) => {
assert!(cs.get("nor result") == Fr::one()); assert!(cs.get("nor result") == Fr::one());
assert_eq!(v.value, Some(true)); assert_eq!(v.value, Some(true));
}, }
_ => { _ => {
panic!( panic!(
"unexpected behavior at {:?} AND {:?}", "unexpected behavior at {:?} AND {:?}",
first_operand, second_operand first_operand, second_operand
); );
}, }
} }
} }
} }
@@ -2072,7 +2070,7 @@ mod test {
match r { match r {
Boolean::Is(ref r) => { Boolean::Is(ref r) => {
assert_eq!(r.value.unwrap(), expected); assert_eq!(r.value.unwrap(), expected);
}, }
_ => unreachable!(), _ => unreachable!(),
} }
} }

View File

@@ -55,7 +55,7 @@ impl UInt32 {
} }
v v
}, }
None => vec![None; 32], None => vec![None; 32],
}; };
@@ -94,19 +94,19 @@ impl UInt32 {
if b { if b {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
} }
}, }
&Boolean::Is(ref b) => match b.get_value() { &Boolean::Is(ref b) => match b.get_value() {
Some(true) => { Some(true) => {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
}, }
Some(false) => {}, Some(false) => {}
None => value = None, None => value = None,
}, },
&Boolean::Not(ref b) => match b.get_value() { &Boolean::Not(ref b) => match b.get_value() {
Some(false) => { Some(false) => {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
}, }
Some(true) => {}, Some(true) => {}
None => value = None, None => value = None,
}, },
} }
@@ -193,12 +193,12 @@ impl UInt32 {
match op.value { match op.value {
Some(val) => { Some(val) => {
result_value.as_mut().map(|v| *v += u64::from(val)); result_value.as_mut().map(|v| *v += u64::from(val));
}, }
None => { None => {
// If any of our operands have unknown value, we won't // If any of our operands have unknown value, we won't
// know the value of the result // know the value of the result
result_value = None; result_value = None;
}, }
} }
// Iterate over each bit_gadget of the operand and add the operand to // Iterate over each bit_gadget of the operand and add the operand to
@@ -211,18 +211,18 @@ impl UInt32 {
// Add coeff * bit_gadget // Add coeff * bit_gadget
lc += (coeff, bit.get_variable()); lc += (coeff, bit.get_variable());
}, }
Boolean::Not(ref bit) => { Boolean::Not(ref bit) => {
all_constants = false; all_constants = false;
// Add coeff * (1 - bit_gadget) = coeff * ONE - coeff * bit_gadget // Add coeff * (1 - bit_gadget) = coeff * ONE - coeff * bit_gadget
lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable()); lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable());
}, }
Boolean::Constant(bit) => { Boolean::Constant(bit) => {
if bit { if bit {
lc += (coeff, CS::one()); lc += (coeff, CS::one());
} }
}, }
} }
coeff.double_in_place(); coeff.double_in_place();
@@ -362,7 +362,7 @@ mod test {
match bit_gadget { match bit_gadget {
&Boolean::Constant(bit_gadget) => { &Boolean::Constant(bit_gadget) => {
assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1)); assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1));
}, }
_ => unreachable!(), _ => unreachable!(),
} }
} }
@@ -371,8 +371,8 @@ mod test {
for x in v.iter().zip(expected_to_be_same.iter()) { for x in v.iter().zip(expected_to_be_same.iter()) {
match x { match x {
(&Boolean::Constant(true), &Boolean::Constant(true)) => {}, (&Boolean::Constant(true), &Boolean::Constant(true)) => {}
(&Boolean::Constant(false), &Boolean::Constant(false)) => {}, (&Boolean::Constant(false), &Boolean::Constant(false)) => {}
_ => unreachable!(), _ => unreachable!(),
} }
} }
@@ -407,13 +407,13 @@ mod test {
match b { match b {
&Boolean::Is(ref b) => { &Boolean::Is(ref b) => {
assert!(b.get_value().unwrap() == (expected & 1 == 1)); assert!(b.get_value().unwrap() == (expected & 1 == 1));
}, }
&Boolean::Not(ref b) => { &Boolean::Not(ref b) => {
assert!(!b.get_value().unwrap() == (expected & 1 == 1)); assert!(!b.get_value().unwrap() == (expected & 1 == 1));
}, }
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert!(b == (expected & 1 == 1)); assert!(b == (expected & 1 == 1));
}, }
} }
expected >>= 1; expected >>= 1;
@@ -448,7 +448,7 @@ mod test {
&Boolean::Not(_) => panic!(), &Boolean::Not(_) => panic!(),
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert!(b == (expected & 1 == 1)); assert!(b == (expected & 1 == 1));
}, }
} }
expected >>= 1; expected >>= 1;
@@ -486,10 +486,10 @@ mod test {
match b { match b {
&Boolean::Is(ref b) => { &Boolean::Is(ref b) => {
assert!(b.get_value().unwrap() == (expected & 1 == 1)); assert!(b.get_value().unwrap() == (expected & 1 == 1));
}, }
&Boolean::Not(ref b) => { &Boolean::Not(ref b) => {
assert!(!b.get_value().unwrap() == (expected & 1 == 1)); assert!(!b.get_value().unwrap() == (expected & 1 == 1));
}, }
&Boolean::Constant(_) => unreachable!(), &Boolean::Constant(_) => unreachable!(),
} }
@@ -525,7 +525,7 @@ mod test {
match b { match b {
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert_eq!(b, tmp & 1 == 1); assert_eq!(b, tmp & 1 == 1);
}, }
_ => unreachable!(), _ => unreachable!(),
} }

View File

@@ -56,7 +56,7 @@ impl UInt64 {
} }
v v
} },
None => vec![None; 64], None => vec![None; 64],
}; };
@@ -95,19 +95,19 @@ impl UInt64 {
if b { if b {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
} }
} },
&Boolean::Is(ref b) => match b.get_value() { &Boolean::Is(ref b) => match b.get_value() {
Some(true) => { Some(true) => {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
} },
Some(false) => {} Some(false) => {},
None => value = None, None => value = None,
}, },
&Boolean::Not(ref b) => match b.get_value() { &Boolean::Not(ref b) => match b.get_value() {
Some(false) => { Some(false) => {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
} },
Some(true) => {} Some(true) => {},
None => value = None, None => value = None,
}, },
} }
@@ -194,12 +194,12 @@ impl UInt64 {
match op.value { match op.value {
Some(val) => { Some(val) => {
result_value.as_mut().map(|v| *v += u128::from(val)); result_value.as_mut().map(|v| *v += u128::from(val));
} },
None => { None => {
// If any of our operands have unknown value, we won't // If any of our operands have unknown value, we won't
// know the value of the result // know the value of the result
result_value = None; result_value = None;
} },
} }
// Iterate over each bit_gadget of the operand and add the operand to // Iterate over each bit_gadget of the operand and add the operand to
@@ -212,18 +212,18 @@ impl UInt64 {
// Add coeff * bit_gadget // Add coeff * bit_gadget
lc += (coeff, bit.get_variable()); lc += (coeff, bit.get_variable());
} },
Boolean::Not(ref bit) => { Boolean::Not(ref bit) => {
all_constants = false; all_constants = false;
// Add coeff * (1 - bit_gadget) = coeff * ONE - coeff * bit_gadget // Add coeff * (1 - bit_gadget) = coeff * ONE - coeff * bit_gadget
lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable()); lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable());
} },
Boolean::Constant(bit) => { Boolean::Constant(bit) => {
if bit { if bit {
lc += (coeff, CS::one()); lc += (coeff, CS::one());
} }
} },
} }
coeff.double_in_place(); coeff.double_in_place();
@@ -397,7 +397,7 @@ mod test {
match bit_gadget { match bit_gadget {
&Boolean::Constant(bit_gadget) => { &Boolean::Constant(bit_gadget) => {
assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1)); assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1));
} },
_ => unreachable!(), _ => unreachable!(),
} }
} }
@@ -406,8 +406,8 @@ mod test {
for x in v.iter().zip(expected_to_be_same.iter()) { for x in v.iter().zip(expected_to_be_same.iter()) {
match x { match x {
(&Boolean::Constant(true), &Boolean::Constant(true)) => {} (&Boolean::Constant(true), &Boolean::Constant(true)) => {},
(&Boolean::Constant(false), &Boolean::Constant(false)) => {} (&Boolean::Constant(false), &Boolean::Constant(false)) => {},
_ => unreachable!(), _ => unreachable!(),
} }
} }
@@ -442,13 +442,13 @@ mod test {
match b { match b {
&Boolean::Is(ref b) => { &Boolean::Is(ref b) => {
assert!(b.get_value().unwrap() == (expected & 1 == 1)); assert!(b.get_value().unwrap() == (expected & 1 == 1));
} },
&Boolean::Not(ref b) => { &Boolean::Not(ref b) => {
assert!(!b.get_value().unwrap() == (expected & 1 == 1)); assert!(!b.get_value().unwrap() == (expected & 1 == 1));
} },
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert!(b == (expected & 1 == 1)); assert!(b == (expected & 1 == 1));
} },
} }
expected >>= 1; expected >>= 1;
@@ -483,7 +483,7 @@ mod test {
&Boolean::Not(_) => panic!(), &Boolean::Not(_) => panic!(),
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert!(b == (expected & 1 == 1)); assert!(b == (expected & 1 == 1));
} },
} }
expected >>= 1; expected >>= 1;
@@ -521,10 +521,10 @@ mod test {
match b { match b {
&Boolean::Is(ref b) => { &Boolean::Is(ref b) => {
assert!(b.get_value().unwrap() == (expected & 1 == 1)); assert!(b.get_value().unwrap() == (expected & 1 == 1));
} },
&Boolean::Not(ref b) => { &Boolean::Not(ref b) => {
assert!(!b.get_value().unwrap() == (expected & 1 == 1)); assert!(!b.get_value().unwrap() == (expected & 1 == 1));
} },
&Boolean::Constant(_) => unreachable!(), &Boolean::Constant(_) => unreachable!(),
} }
@@ -560,7 +560,7 @@ mod test {
match b { match b {
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert_eq!(b, tmp & 1 == 1); assert_eq!(b, tmp & 1 == 1);
} },
_ => unreachable!(), _ => unreachable!(),
} }

View File

@@ -134,19 +134,19 @@ impl UInt8 {
if b { if b {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
} }
}, }
Boolean::Is(ref b) => match b.get_value() { Boolean::Is(ref b) => match b.get_value() {
Some(true) => { Some(true) => {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
}, }
Some(false) => {}, Some(false) => {}
None => value = None, None => value = None,
}, },
Boolean::Not(ref b) => match b.get_value() { Boolean::Not(ref b) => match b.get_value() {
Some(false) => { Some(false) => {
value.as_mut().map(|v| *v |= 1); value.as_mut().map(|v| *v |= 1);
}, }
Some(true) => {}, Some(true) => {}
None => value = None, None => value = None,
}, },
} }
@@ -233,7 +233,7 @@ impl<ConstraintF: Field> AllocGadget<u8, ConstraintF> for UInt8 {
} }
v v
}, }
_ => vec![None; 8], _ => vec![None; 8],
}; };
@@ -272,7 +272,7 @@ impl<ConstraintF: Field> AllocGadget<u8, ConstraintF> for UInt8 {
} }
v v
}, }
_ => vec![None; 8], _ => vec![None; 8],
}; };
@@ -342,7 +342,7 @@ mod test {
match bit_gadget { match bit_gadget {
&Boolean::Constant(bit_gadget) => { &Boolean::Constant(bit_gadget) => {
assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1)); assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1));
}, }
_ => unreachable!(), _ => unreachable!(),
} }
} }
@@ -351,8 +351,8 @@ mod test {
for x in v.iter().zip(expected_to_be_same.iter()) { for x in v.iter().zip(expected_to_be_same.iter()) {
match x { match x {
(&Boolean::Constant(true), &Boolean::Constant(true)) => {}, (&Boolean::Constant(true), &Boolean::Constant(true)) => {}
(&Boolean::Constant(false), &Boolean::Constant(false)) => {}, (&Boolean::Constant(false), &Boolean::Constant(false)) => {}
_ => unreachable!(), _ => unreachable!(),
} }
} }
@@ -387,13 +387,13 @@ mod test {
match b { match b {
&Boolean::Is(ref b) => { &Boolean::Is(ref b) => {
assert!(b.get_value().unwrap() == (expected & 1 == 1)); assert!(b.get_value().unwrap() == (expected & 1 == 1));
}, }
&Boolean::Not(ref b) => { &Boolean::Not(ref b) => {
assert!(!b.get_value().unwrap() == (expected & 1 == 1)); assert!(!b.get_value().unwrap() == (expected & 1 == 1));
}, }
&Boolean::Constant(b) => { &Boolean::Constant(b) => {
assert!(b == (expected & 1 == 1)); assert!(b == (expected & 1 == 1));
}, }
} }
expected >>= 1; expected >>= 1;

View File

@@ -111,14 +111,14 @@ impl<F: PrimeField> FpGadget<F> {
Ordering::Less => { Ordering::Less => {
left = a; left = a;
right = b; right = b;
}, }
Ordering::Greater => { Ordering::Greater => {
left = b; left = b;
right = a; right = a;
}, }
Ordering::Equal => { Ordering::Equal => {
return Err(SynthesisError::Unsatisfiable); return Err(SynthesisError::Unsatisfiable);
}, }
}; };
let right_for_check = if should_also_check_equality { let right_for_check = if should_also_check_equality {
right.add_constant(cs.ns(|| "plus one"), &F::one())? right.add_constant(cs.ns(|| "plus one"), &F::one())?
@@ -252,7 +252,7 @@ mod test {
true, true,
) )
.unwrap(); .unwrap();
}, }
Ordering::Greater => { Ordering::Greater => {
a_var a_var
.enforce_cmp( .enforce_cmp(
@@ -270,8 +270,8 @@ mod test {
true, true,
) )
.unwrap(); .unwrap();
}, }
_ => {}, _ => {}
} }
if i == 0 { if i == 0 {
@@ -300,7 +300,7 @@ mod test {
true, true,
) )
.unwrap(); .unwrap();
}, }
Ordering::Greater => { Ordering::Greater => {
a_var a_var
.enforce_cmp( .enforce_cmp(
@@ -318,8 +318,8 @@ mod test {
true, true,
) )
.unwrap(); .unwrap();
}, }
_ => {}, _ => {}
} }
assert!(!cs.is_satisfied()); assert!(!cs.is_satisfied());

View File

@@ -364,7 +364,7 @@ impl<F: PrimeField> ToBitsGadget<F> for FpGadget<F> {
assert_eq!(tmp.len(), num_bits as usize); assert_eq!(tmp.len(), num_bits as usize);
tmp tmp
}, }
None => vec![None; num_bits as usize], None => vec![None; num_bits as usize],
}; };
@@ -422,7 +422,7 @@ impl<F: PrimeField> ToBytesGadget<F> for FpGadget<F> {
let default = F::default(); let default = F::default();
let default_len = to_bytes![&default].unwrap().len(); let default_len = to_bytes![&default].unwrap().len();
vec![None; default_len] vec![None; default_len]
}, }
}; };
let bytes = UInt8::alloc_vec(cs.ns(|| "Alloc bytes"), &byte_values)?; let bytes = UInt8::alloc_vec(cs.ns(|| "Alloc bytes"), &byte_values)?;
@@ -438,7 +438,7 @@ impl<F: PrimeField> ToBytesGadget<F> for FpGadget<F> {
Boolean::Is(bit) => { Boolean::Is(bit) => {
lc += (coeff, bit.get_variable()); lc += (coeff, bit.get_variable());
coeff.double_in_place(); coeff.double_in_place();
}, }
Boolean::Constant(_) | Boolean::Not(_) => unreachable!(), Boolean::Constant(_) | Boolean::Not(_) => unreachable!(),
} }
} }

View File

@@ -6,11 +6,11 @@ use algebra::{
fp6_3over2::{Fp6, Fp6Parameters}, fp6_3over2::{Fp6, Fp6Parameters},
Fp2Parameters, Fp2Parameters,
}, },
BitIterator, Field, One, PrimeField, BitIterator, PrimeField,
}; };
use core::{borrow::Borrow, marker::PhantomData}; use core::{borrow::Borrow, marker::PhantomData};
use crate::{prelude::*, Assignment, Vec}; use crate::{prelude::*, Vec};
type Fp2Gadget<P, ConstraintF> = super::fp2::Fp2Gadget< type Fp2Gadget<P, ConstraintF> = super::fp2::Fp2Gadget<
<<P as Fp12Parameters>::Fp6Params as Fp6Parameters>::Fp2Params, <<P as Fp12Parameters>::Fp6Params as Fp6Parameters>::Fp2Params,
@@ -546,47 +546,6 @@ where
Ok(self) Ok(self)
} }
fn inverse<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Self, SynthesisError> {
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || {
self.get_value().and_then(|val| val.inverse()).get()
})?;
// Karatsuba multiplication for Fp2 with the inverse:
// v0 = A.c0 * B.c0
// v1 = A.c1 * B.c1
//
// 1 = v0 + non_residue * v1
// => v0 = 1 - non_residue * v1
//
// 0 = result.c1 = (A.c0 + A.c1) * (B.c0 + B.c1) - v0 - v1
// => v0 + v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// => 1 + (1 - non_residue) * v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// Enforced with 2 constraints:
// A.c1 * B.c1 = v1
// => 1 + (1 - non_residue) * v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// Reference:
// "Multiplication and Squaring on Pairing-Friendly Fields"
// Devegili, OhEigeartaigh, Scott, Dahab
// Constraint 1
let v1 = self.c1.mul(cs.ns(|| "inv_constraint_1"), &inverse.c1)?;
// Constraint 2
let a0_plus_a1 = self.c0.add(cs.ns(|| "a0 + a1"), &self.c1)?;
let b0_plus_b1 = inverse.c0.add(cs.ns(|| "b0 + b1"), &inverse.c1)?;
let one = Fp6::<P::Fp6Params>::one();
let rhs = Self::mul_fp6_by_nonresidue(cs.ns(|| "nr * v1"), &v1)?
.sub(cs.ns(|| "sub v1"), &v1)?
.negate(cs.ns(|| "negate it"))?
.add_constant(cs.ns(|| "add one"), &one)?;
a0_plus_a1.mul_equals(cs.ns(|| "inv_constraint_2"), &b0_plus_b1, &rhs)?;
Ok(inverse)
}
fn mul_equals<CS: ConstraintSystem<ConstraintF>>( fn mul_equals<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
mut cs: CS, mut cs: CS,
@@ -639,16 +598,12 @@ where
} }
fn cost_of_mul() -> usize { fn cost_of_mul() -> usize {
unimplemented!() 3 * Fp6Gadget::<P, ConstraintF>::cost_of_mul()
} }
fn cost_of_mul_equals() -> usize { fn cost_of_mul_equals() -> usize {
Self::cost_of_mul() Self::cost_of_mul()
} }
fn cost_of_inv() -> usize {
Self::cost_of_mul() + <Self as EqGadget<ConstraintF>>::cost()
}
} }
impl<P, ConstraintF: PrimeField> PartialEq for Fp12Gadget<P, ConstraintF> impl<P, ConstraintF: PrimeField> PartialEq for Fp12Gadget<P, ConstraintF>
@@ -892,7 +847,7 @@ where
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1)) (Ok(fe.c0), Ok(fe.c1))
}, }
Err(_) => ( Err(_) => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -917,7 +872,7 @@ where
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1)) (Ok(fe.c0), Ok(fe.c1))
}, }
Err(_) => ( Err(_) => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),

View File

@@ -1,11 +1,11 @@
use algebra::{ use algebra::{
fields::{Fp2, Fp2Parameters}, fields::{Fp2, Fp2Parameters},
Field, PrimeField, PrimeField,
}; };
use core::{borrow::Borrow, marker::PhantomData}; use core::{borrow::Borrow, marker::PhantomData};
use r1cs_core::{ConstraintSystem, ConstraintVar, SynthesisError}; use r1cs_core::{ConstraintSystem, ConstraintVar, SynthesisError};
use crate::{fields::fp::FpGadget, prelude::*, Assignment, Vec}; use crate::{fields::fp::FpGadget, prelude::*, Vec};
#[derive(Derivative)] #[derive(Derivative)]
#[derivative(Debug(bound = "P: Fp2Parameters, ConstraintF: PrimeField"))] #[derivative(Debug(bound = "P: Fp2Parameters, ConstraintF: PrimeField"))]
@@ -289,47 +289,6 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> FieldGadget<Fp
Ok(self) Ok(self)
} }
#[inline]
fn inverse<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Self, SynthesisError> {
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || {
self.get_value().and_then(|val| val.inverse()).get()
})?;
// Karatsuba multiplication for Fp2 with the inverse:
// v0 = A.c0 * B.c0
// v1 = A.c1 * B.c1
//
// 1 = v0 + non_residue * v1
// => v0 = 1 - non_residue * v1
//
// 0 = result.c1 = (A.c0 + A.c1) * (B.c0 + B.c1) - v0 - v1
// => v0 + v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// => 1 + (1 - non_residue) * v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// Enforced with 2 constraints:
// A.c1 * B.c1 = v1
// => 1 + (1 - non_residue) * v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// Reference:
// "Multiplication and Squaring on Pairing-Friendly Fields"
// Devegili, OhEigeartaigh, Scott, Dahab
// Constraint 1
let mut v1 = self.c1.mul(cs.ns(|| "inv_constraint_1"), &inverse.c1)?;
// Constraint 2
let a0_plus_a1 = self.c0.add(cs.ns(|| "a0 + a1"), &self.c1)?;
let b0_plus_b1 = inverse.c0.add(cs.ns(|| "b0 + b1"), &inverse.c1)?;
let one = P::Fp::one();
let rhs = v1
.mul_by_constant_in_place(cs.ns(|| "(1 - nonresidue) * v1"), &(one - &P::NONRESIDUE))?
.add_constant_in_place(cs.ns(|| "add one"), &one)?;
a0_plus_a1.mul_equals(cs.ns(|| "inv_constraint_2"), &b0_plus_b1, rhs)?;
Ok(inverse)
}
fn mul_equals<CS: ConstraintSystem<ConstraintF>>( fn mul_equals<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
mut cs: CS, mut cs: CS,
@@ -450,16 +409,12 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> FieldGadget<Fp
} }
fn cost_of_mul() -> usize { fn cost_of_mul() -> usize {
3 3 * FpGadget::<ConstraintF>::cost_of_mul()
} }
fn cost_of_mul_equals() -> usize { fn cost_of_mul_equals() -> usize {
Self::cost_of_mul() Self::cost_of_mul()
} }
fn cost_of_inv() -> usize {
2
}
} }
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> PartialEq impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> PartialEq
@@ -669,7 +624,7 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> AllocGadget<Fp
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1)) (Ok(fe.c0), Ok(fe.c1))
}, }
Err(_) => ( Err(_) => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -694,7 +649,7 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> AllocGadget<Fp
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1)) (Ok(fe.c0), Ok(fe.c1))
}, }
Err(_) => ( Err(_) => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),

View File

@@ -1,14 +1,11 @@
use algebra::{ use algebra::{
fields::{ fields::fp3::{Fp3, Fp3Parameters},
fp3::{Fp3, Fp3Parameters},
Field,
},
PrimeField, SquareRootField, PrimeField, SquareRootField,
}; };
use core::{borrow::Borrow, marker::PhantomData}; use core::{borrow::Borrow, marker::PhantomData};
use r1cs_core::{ConstraintSystem, ConstraintVar, SynthesisError}; use r1cs_core::{ConstraintSystem, ConstraintVar, SynthesisError};
use crate::{fields::fp::FpGadget, prelude::*, Assignment, Vec}; use crate::{fields::fp::FpGadget, prelude::*, Vec};
#[derive(Derivative)] #[derive(Derivative)]
#[derivative(Debug( #[derivative(Debug(
@@ -40,6 +37,7 @@ impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootFie
_params: PhantomData, _params: PhantomData,
} }
} }
/// Multiply a FpGadget by quadratic nonresidue P::NONRESIDUE. /// Multiply a FpGadget by quadratic nonresidue P::NONRESIDUE.
#[inline] #[inline]
pub fn mul_fp_gadget_by_nonresidue<CS: ConstraintSystem<ConstraintF>>( pub fn mul_fp_gadget_by_nonresidue<CS: ConstraintSystem<ConstraintF>>(
@@ -332,122 +330,115 @@ impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootFie
Ok(Self::new(c0, c1, c2)) Ok(Self::new(c0, c1, c2))
} }
/// Use the Toom-Cook-3x method to compute multiplication. #[inline]
fn mul_equals<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
other: &Self,
result: &Self,
) -> Result<(), SynthesisError> {
// Karatsuba multiplication for Fp3:
// v0 = A.c0 * B.c0
// v1 = A.c1 * B.c1
// v2 = A.c2 * B.c2
// result.c0 = v0 + β((a1 + a2)(b1 + b2) v1 v2)
// result.c1 = (a0 + a1)(b0 + b1) v0 v1 + βv2
// result.c2 = (a0 + a2)(b0 + b2) v0 + v1 v2,
// We enforce this with six constraints:
//
// v0 = A.c0 * B.c0
// v1 = A.c1 * B.c1
// v2 = A.c2 * B.c2
//
// result.c0 - v0 + \beta*(v1 + v2) = β(a1 + a2)(b1 + b2))
// result.c1 + v0 + v1 - βv2 = (a0 + a1)(b0 + b1)
// result.c2 + v0 - v1 + v2 = (a0 + a2)(b0 + b2)
// Reference:
// "Multiplication and Squaring on Pairing-Friendly Fields"
// Devegili, OhEigeartaigh, Scott, Dahab
//
// This implementation adapted from
// https://github.com/ZencashOfficial/ginger-lib/blob/development/r1cs/gadgets/std/src/fields/fp3.rs
let v0 = self.c0.mul(cs.ns(|| "v0 = a0 * b0"), &other.c0)?;
let v1 = self.c1.mul(cs.ns(|| "v1 = a1 * b1"), &other.c1)?;
let v2 = self.c2.mul(cs.ns(|| "v2 = a2 * b2"), &other.c2)?;
// Check c0
let nr_a1_plus_a2 = self
.c1
.add(cs.ns(|| "a1 + a2"), &self.c2)?
.mul_by_constant(cs.ns(|| "nr*(a1 + a2)"), &P::NONRESIDUE)?;
let b1_plus_b2 = other.c1.add(cs.ns(|| "b1 + b2"), &other.c2)?;
let nr_v1 = v1.mul_by_constant(cs.ns(|| "nr * v1"), &P::NONRESIDUE)?;
let nr_v2 = v2.mul_by_constant(cs.ns(|| "nr * v2"), &P::NONRESIDUE)?;
let to_check = result
.c0
.sub(cs.ns(|| "c0 - v0"), &v0)?
.add(cs.ns(|| "c0 - v0 + nr * v1"), &nr_v1)?
.add(cs.ns(|| "c0 - v0 + nr * v1 + nr * v2"), &nr_v2)?;
nr_a1_plus_a2.mul_equals(cs.ns(|| "check c0"), &b1_plus_b2, &to_check)?;
// Check c1
let a0_plus_a1 = self.c0.add(cs.ns(|| "a0 + a1"), &self.c1)?;
let b0_plus_b1 = other.c0.add(cs.ns(|| "b0 + b1"), &other.c1)?;
let to_check = result
.c1
.sub(cs.ns(|| "c1 - nr * v2"), &nr_v2)?
.add(cs.ns(|| "c1 - nr * v2 + v0"), &v0)?
.add(cs.ns(|| "c1 - nr * v2 + v0 + v1"), &v1)?;
a0_plus_a1.mul_equals(cs.ns(|| "check c1"), &b0_plus_b1, &to_check)?;
// Check c2
let a0_plus_a2 = self.c0.add(cs.ns(|| "a0 + a2"), &self.c2)?;
let b0_plus_b2 = other.c0.add(cs.ns(|| "b0 + b2"), &other.c2)?;
let to_check = result
.c2
.add(cs.ns(|| "c2 + v0"), &v0)?
.sub(cs.ns(|| "c2 + v0 - v1"), &v1)?
.add(cs.ns(|| "c2 + v0 - v1 + v2"), &v2)?;
a0_plus_a2.mul_equals(cs.ns(|| "check c2"), &b0_plus_b2, &to_check)?;
Ok(())
}
/// Use the Chung-Hasan asymmetric squaring formula.
///
/// (Devegili OhEig Scott Dahab --- Multiplication and Squaring on
/// Abstract Pairing-Friendly
/// Fields.pdf; Section 4 (CH-SQR2))
#[inline] #[inline]
fn square<CS: ConstraintSystem<ConstraintF>>( fn square<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
mut cs: CS, mut cs: CS,
) -> Result<Self, SynthesisError> { ) -> Result<Self, SynthesisError> {
// Uses Toom-Cook-3x multiplication from let a = self.c0.clone();
// let b = self.c1.clone();
// Reference: let c = self.c2.clone();
// "Multiplication and Squaring on Pairing-Friendly Fields"
// Devegili, OhEigeartaigh, Scott, Dahab
// v0 = a(0)^2 = a0^2 let s0 = a.square(cs.ns(|| "s0"))?;
let v0 = self.c0.square(&mut cs.ns(|| "Calc v0"))?; let ab = a.mul(cs.ns(|| "ab"), &b)?;
let s1 = ab.double(cs.ns(|| "s1"))?;
let s2 = a
.sub(cs.ns(|| "a-b"), &b)?
.add(cs.ns(|| "plus c"), &c)?
.square(cs.ns(|| "s2"))?;
let s3 = b.mul(cs.ns(|| "bc"), &c)?.double(cs.ns(|| "s3"))?;
let s4 = c.square(cs.ns(|| "s4"))?;
// v1 = a(1)^2 = (a0 + a1 + a2)^2 let c0 = Self::mul_fp_gadget_by_nonresidue(cs.ns(|| "c0 part 1"), &s3)?
let v1 = { .add(cs.ns(|| "c0"), &s0)?;
let a0_plus_a1_plus_a2 = self
.c0
.add(cs.ns(|| "a0 + a1"), &self.c1)?
.add(cs.ns(|| "a0 + a1 + a2"), &self.c2)?;
a0_plus_a1_plus_a2.square(&mut cs.ns(|| "(a0 + a1 + a2)^2"))?
};
// v2 = a(1)^2 = (a0 a1 + a2)^2 let c1 = Self::mul_fp_gadget_by_nonresidue(cs.ns(|| "c1 part 1"), &s4)?
let v2 = { .add(cs.ns(|| "c1"), &s1)?;
let a0_minus_a1_plus_a2 = self
.c0
.sub(cs.ns(|| "a0 - a1"), &self.c1)?
.add(cs.ns(|| "a0 - a2 + a2"), &self.c2)?;
a0_minus_a1_plus_a2.square(&mut cs.ns(|| "(a0 - a1 + a2)^2"))?
};
// v3 = a(2)^2 = (a0 + 2a1 + 4a2)^2 let c2 = s1
let v3 = { .add(cs.ns(|| "c2 part1"), &s2)?
let a1_double = self.c1.double(cs.ns(|| "2a1"))?; .add(cs.ns(|| "c2 part2"), &s3)?
let a2_quad = self.c2.double(cs.ns(|| "2a2"))?.double(cs.ns(|| "4a2"))?; .sub(cs.ns(|| "c2 part3"), &s0)?
let a0_plus_2_a1_plus_4_a2 = self .sub(cs.ns(|| "c2 part4"), &s4)?;
.c0
.add(cs.ns(|| "a0 + 2a1"), &a1_double)?
.add(cs.ns(|| "a0 + 2a1 + 4a2"), &a2_quad)?;
a0_plus_2_a1_plus_4_a2.square(&mut cs.ns(|| "(a0 + 2a1 + 4a2)^2"))?
};
// v4 = a(∞)^2 = a2^2
let v4 = self.c2.square(&mut cs.ns(|| "a2^2"))?;
let two = P::Fp::one().double();
let six = two.double() + &two;
let mut two_and_six = [two, six];
algebra::fields::batch_inversion(&mut two_and_six);
let (two_inverse, six_inverse) = (two_and_six[0], two_and_six[1]);
let half_v0 = v0.mul_by_constant(cs.ns(|| "half_v0"), &two_inverse)?;
let half_v1 = v1.mul_by_constant(cs.ns(|| "half_v1"), &two_inverse)?;
let one_sixth_v2 = v2.mul_by_constant(cs.ns(|| "one_sixth_v2"), &six_inverse)?;
let one_sixth_v3 = v3.mul_by_constant(cs.ns(|| "one_sixth_v3"), &six_inverse)?;
let two_v4 = v4.double(cs.ns(|| "double_v4"))?;
// c0 = v0 + β((1/2)v0 (1/2)v1 (1/6)v2 + (1/6)v3 2v4)
let c0 = {
let mut c0_cs = cs.ns(|| "c0");
// No constraints, only get a linear combination back.
let inner = half_v0
.sub(c0_cs.ns(|| "sub1"), &half_v1)?
.sub(c0_cs.ns(|| "sub2"), &one_sixth_v2)?
.add(c0_cs.ns(|| "add3"), &one_sixth_v3)?
.sub(c0_cs.ns(|| "sub4"), &two_v4)?;
let non_residue_times_inner =
inner.mul_by_constant(c0_cs.ns(|| "mul_by_res"), &P::NONRESIDUE)?;
v0.add(c0_cs.ns(|| "add5"), &non_residue_times_inner)?
};
// (1/2)v0 + v1 (1/3)v2 (1/6)v3 + 2v4 + βv4
let c1 = {
let mut c1_cs = cs.ns(|| "c1");
let one_third_v2 = one_sixth_v2.double(c1_cs.ns(|| "v2_by_3"))?;
let non_residue_v4 = v4.mul_by_constant(c1_cs.ns(|| "mul_by_res"), &P::NONRESIDUE)?;
half_v0
.negate(c1_cs.ns(|| "neg1"))?
.add(c1_cs.ns(|| "add1"), &v1)?
.sub(c1_cs.ns(|| "sub2"), &one_third_v2)?
.sub(c1_cs.ns(|| "sub3"), &one_sixth_v3)?
.add(c1_cs.ns(|| "add4"), &two_v4)?
.add(c1_cs.ns(|| "add5"), &non_residue_v4)?
};
// -v0 + (1/2)v1 + (1/2)v2 v4
let c2 = {
let mut c2_cs = cs.ns(|| "c2");
let half_v2 = v2.mul_by_constant(c2_cs.ns(|| "half_v2"), &two_inverse)?;
half_v1
.add(c2_cs.ns(|| "add1"), &half_v2)?
.sub(c2_cs.ns(|| "sub1"), &v4)?
.sub(c2_cs.ns(|| "sub2"), &v0)?
};
Ok(Self::new(c0, c1, c2)) Ok(Self::new(c0, c1, c2))
} }
// 18 constraints, we can probably do better but not sure it's worth it.
#[inline]
fn inverse<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Self, SynthesisError> {
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || {
self.get_value().and_then(|val| val.inverse()).get()
})?;
let one = Self::one(cs.ns(|| "one"))?;
inverse.mul_equals(cs.ns(|| "check inverse"), &self, &one)?;
Ok(inverse)
}
#[inline] #[inline]
fn add_constant<CS: ConstraintSystem<ConstraintF>>( fn add_constant<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
@@ -634,8 +625,8 @@ impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootFie
5 * FpGadget::<ConstraintF>::cost_of_mul() 5 * FpGadget::<ConstraintF>::cost_of_mul()
} }
fn cost_of_inv() -> usize { fn cost_of_mul_equals() -> usize {
Self::cost_of_mul() + <Self as EqGadget<ConstraintF>>::cost() 6 * FpGadget::<ConstraintF>::cost_of_mul()
} }
} }
@@ -889,7 +880,7 @@ impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootFie
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1), Ok(fe.c2)) (Ok(fe.c0), Ok(fe.c1), Ok(fe.c2))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -916,7 +907,7 @@ impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootFie
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1), Ok(fe.c2)) (Ok(fe.c0), Ok(fe.c1), Ok(fe.c2))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),

View File

@@ -1,11 +1,11 @@
use algebra::{ use algebra::{
fields::{Fp2, Fp2Parameters, Fp4, Fp4Parameters}, fields::{Fp2, Fp2Parameters, Fp4, Fp4Parameters},
BigInteger, Field, One, PrimeField, BigInteger, PrimeField,
}; };
use core::{borrow::Borrow, marker::PhantomData}; use core::{borrow::Borrow, marker::PhantomData};
use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSystem, SynthesisError};
use crate::{prelude::*, Assignment, Vec}; use crate::{prelude::*, Vec};
type Fp2Gadget<P, ConstraintF> = type Fp2Gadget<P, ConstraintF> =
super::fp2::Fp2Gadget<<P as Fp4Parameters>::Fp2Params, ConstraintF>; super::fp2::Fp2Gadget<<P as Fp4Parameters>::Fp2Params, ConstraintF>;
@@ -308,48 +308,6 @@ where
Ok(Self::new(c0, c1)) Ok(Self::new(c0, c1))
} }
#[inline]
fn inverse<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Self, SynthesisError> {
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || {
self.get_value().and_then(|val| val.inverse()).get()
})?;
// Karatsuba multiplication for Fp4 with the inverse:
// v0 = A.c0 * B.c0
// v1 = A.c1 * B.c1
//
// 1 = v0 + non_residue * v1
// => v0 = 1 - non_residue * v1
//
// 0 = result.c1 = (A.c0 + A.c1) * (B.c0 + B.c1) - v0 - v1
// => v0 + v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// => 1 + (1 - non_residue) * v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// Enforced with 2 constraints:
// A.c1 * B.c1 = v1
// => 1 + (1 - non_residue) * v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// Reference:
// "Multiplication and Squaring on Pairing-Friendly Fields"
// Devegili, OhEigeartaigh, Scott, Dahab
// Constraint 1
let v1 = self.c1.mul(cs.ns(|| "inv_constraint_1"), &inverse.c1)?;
// Constraint 2
let a0_plus_a1 = self.c0.add(cs.ns(|| "a0 + a1"), &self.c1)?;
let b0_plus_b1 = inverse.c0.add(cs.ns(|| "b0 + b1"), &inverse.c1)?;
let one = Fp2::<<P as Fp4Parameters>::Fp2Params>::one();
let rhs = Self::mul_fp2_gadget_by_nonresidue(cs.ns(|| "nr * v1"), &v1)?
.sub(cs.ns(|| "sub v1"), &v1)?
.negate(cs.ns(|| "negate it"))?
.add_constant(cs.ns(|| "add one"), &one)?;
a0_plus_a1.mul_equals(cs.ns(|| "inv_constraint_2"), &b0_plus_b1, &rhs)?;
Ok(inverse)
}
fn mul_equals<CS: ConstraintSystem<ConstraintF>>( fn mul_equals<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
mut cs: CS, mut cs: CS,
@@ -475,17 +433,12 @@ where
} }
fn cost_of_mul() -> usize { fn cost_of_mul() -> usize {
3 * <Fp2Gadget<P, ConstraintF> as FieldGadget<Fp2<P::Fp2Params>, ConstraintF>>::cost_of_mul( 3 * Fp2Gadget::<P, ConstraintF>::cost_of_mul()
)
} }
fn cost_of_mul_equals() -> usize { fn cost_of_mul_equals() -> usize {
Self::cost_of_mul() Self::cost_of_mul()
} }
fn cost_of_inv() -> usize {
unimplemented!()
}
} }
impl<P, ConstraintF: PrimeField> PartialEq for Fp4Gadget<P, ConstraintF> impl<P, ConstraintF: PrimeField> PartialEq for Fp4Gadget<P, ConstraintF>
@@ -733,7 +686,7 @@ where
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1)) (Ok(fe.c0), Ok(fe.c1))
}, }
Err(_) => ( Err(_) => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -758,7 +711,7 @@ where
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1)) (Ok(fe.c0), Ok(fe.c1))
}, }
Err(_) => ( Err(_) => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),

View File

@@ -3,12 +3,12 @@ use algebra::{
fp6_2over3::{Fp6, Fp6Parameters}, fp6_2over3::{Fp6, Fp6Parameters},
Fp3, Fp3Parameters, Fp3, Fp3Parameters,
}, },
BigInteger, Field, One, PrimeField, SquareRootField, BigInteger, PrimeField, SquareRootField,
}; };
use core::{borrow::Borrow, marker::PhantomData}; use core::{borrow::Borrow, marker::PhantomData};
use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSystem, SynthesisError};
use crate::{prelude::*, Assignment, Vec}; use crate::{prelude::*, Vec};
type Fp3Gadget<P, ConstraintF> = type Fp3Gadget<P, ConstraintF> =
super::fp3::Fp3Gadget<<P as Fp6Parameters>::Fp3Params, ConstraintF>; super::fp3::Fp3Gadget<<P as Fp6Parameters>::Fp3Params, ConstraintF>;
@@ -291,48 +291,6 @@ where
Ok(Self::new(c0, c1)) Ok(Self::new(c0, c1))
} }
#[inline]
fn inverse<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Self, SynthesisError> {
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || {
self.get_value().and_then(|val| val.inverse()).get()
})?;
// Karatsuba multiplication for Fp6 with the inverse:
// v0 = A.c0 * B.c0
// v1 = A.c1 * B.c1
//
// 1 = v0 + non_residue * v1
// => v0 = 1 - non_residue * v1
//
// 0 = result.c1 = (A.c0 + A.c1) * (B.c0 + B.c1) - v0 - v1
// => v0 + v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// => 1 + (1 - non_residue) * v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// Enforced with 2 constraints:
// A.c1 * B.c1 = v1
// => 1 + (1 - non_residue) * v1 = (A.c0 + A.c1) * (B.c0 + B.c1)
// Reference:
// "Multiplication and Squaring on Pairing-Friendly Fields"
// Devegili, OhEigeartaigh, Scott, Dahab
// Constraint 1
let v1 = self.c1.mul(cs.ns(|| "inv_constraint_1"), &inverse.c1)?;
// Constraint 2
let a0_plus_a1 = self.c0.add(cs.ns(|| "a0 + a1"), &self.c1)?;
let b0_plus_b1 = inverse.c0.add(cs.ns(|| "b0 + b1"), &inverse.c1)?;
let one = Fp3::<<P as Fp6Parameters>::Fp3Params>::one();
let rhs = Self::mul_fp3_gadget_by_nonresidue(cs.ns(|| "nr * v1"), &v1)?
.sub(cs.ns(|| "sub v1"), &v1)?
.negate(cs.ns(|| "negate it"))?
.add_constant(cs.ns(|| "add one"), &one)?;
a0_plus_a1.mul_equals(cs.ns(|| "inv_constraint_2"), &b0_plus_b1, &rhs)?;
Ok(inverse)
}
fn mul_equals<CS: ConstraintSystem<ConstraintF>>( fn mul_equals<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
mut cs: CS, mut cs: CS,
@@ -458,17 +416,12 @@ where
} }
fn cost_of_mul() -> usize { fn cost_of_mul() -> usize {
3 * <Fp3Gadget<P, ConstraintF> as FieldGadget<Fp3<P::Fp3Params>, ConstraintF>>::cost_of_mul( 2 * Fp3Gadget::<P, ConstraintF>::cost_of_mul()
)
} }
fn cost_of_mul_equals() -> usize { fn cost_of_mul_equals() -> usize {
Self::cost_of_mul() Self::cost_of_mul()
} }
fn cost_of_inv() -> usize {
unimplemented!()
}
} }
impl<P, ConstraintF: PrimeField + SquareRootField> PartialEq for Fp6Gadget<P, ConstraintF> impl<P, ConstraintF: PrimeField + SquareRootField> PartialEq for Fp6Gadget<P, ConstraintF>
@@ -724,7 +677,7 @@ where
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1)) (Ok(fe.c0), Ok(fe.c1))
}, }
Err(_) => ( Err(_) => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -749,7 +702,7 @@ where
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1)) (Ok(fe.c0), Ok(fe.c1))
}, }
Err(_) => ( Err(_) => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),

View File

@@ -8,7 +8,7 @@ use algebra::{
use core::{borrow::Borrow, marker::PhantomData}; use core::{borrow::Borrow, marker::PhantomData};
use r1cs_core::{ConstraintSystem, ConstraintVar, SynthesisError}; use r1cs_core::{ConstraintSystem, ConstraintVar, SynthesisError};
use crate::{prelude::*, Assignment, Vec}; use crate::{prelude::*, Vec};
type Fp2Gadget<P, ConstraintF> = type Fp2Gadget<P, ConstraintF> =
super::fp2::Fp2Gadget<<P as Fp6Parameters>::Fp2Params, ConstraintF>; super::fp2::Fp2Gadget<<P as Fp6Parameters>::Fp2Params, ConstraintF>;
@@ -398,120 +398,113 @@ where
Ok(Self::new(c0, c1, c2)) Ok(Self::new(c0, c1, c2))
} }
/// Use the Toom-Cook-3x method to compute multiplication. /// Use the Chung-Hasan asymmetric squaring formula.
///
/// (Devegili OhEig Scott Dahab --- Multiplication and Squaring on
/// Abstract Pairing-Friendly
/// Fields.pdf; Section 4 (CH-SQR2))
#[inline] #[inline]
fn square<CS: ConstraintSystem<ConstraintF>>( fn square<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
mut cs: CS, mut cs: CS,
) -> Result<Self, SynthesisError> { ) -> Result<Self, SynthesisError> {
// Uses Toom-Cook-3x multiplication from let a = self.c0.clone();
// let b = self.c1.clone();
// Reference: let c = self.c2.clone();
// "Multiplication and Squaring on Pairing-Friendly Fields"
// Devegili, OhEigeartaigh, Scott, Dahab
// v0 = a(0)^2 = a0^2 let s0 = a.square(cs.ns(|| "s0"))?;
let v0 = self.c0.square(&mut cs.ns(|| "Calc v0"))?; let ab = a.mul(cs.ns(|| "ab"), &b)?;
let s1 = ab.double(cs.ns(|| "s1"))?;
let s2 = a
.sub(cs.ns(|| "a-b"), &b)?
.add(cs.ns(|| "plus c"), &c)?
.square(cs.ns(|| "s2"))?;
let s3 = b.mul(cs.ns(|| "bc"), &c)?.double(cs.ns(|| "s3"))?;
let s4 = c.square(cs.ns(|| "s4"))?;
// v1 = a(1)^2 = (a0 + a1 + a2)^2 let c0 = Self::mul_fp2_gadget_by_nonresidue(cs.ns(|| "c0 part 1"), &s3)?
let v1 = { .add(cs.ns(|| "c0"), &s0)?;
let a0_plus_a1_plus_a2 = self
.c0
.add(cs.ns(|| "a0 + a1"), &self.c1)?
.add(cs.ns(|| "a0 + a1 + a2"), &self.c2)?;
a0_plus_a1_plus_a2.square(&mut cs.ns(|| "(a0 + a1 + a2)^2"))?
};
// v2 = a(1)^2 = (a0 a1 + a2)^2 let c1 = Self::mul_fp2_gadget_by_nonresidue(cs.ns(|| "c1 part 1"), &s4)?
let v2 = { .add(cs.ns(|| "c1"), &s1)?;
let a0_minus_a1_plus_a2 = self
.c0
.sub(cs.ns(|| "a0 - a1"), &self.c1)?
.add(cs.ns(|| "a0 - a2 + a2"), &self.c2)?;
a0_minus_a1_plus_a2.square(&mut cs.ns(|| "(a0 - a1 + a2)^2"))?
};
// v3 = a(2)^2 = (a0 + 2a1 + 4a2)^2 let c2 = s1
let v3 = { .add(cs.ns(|| "c2 part1"), &s2)?
let a1_double = self.c1.double(cs.ns(|| "2a1"))?; .add(cs.ns(|| "c2 part2"), &s3)?
let a2_quad = self.c2.double(cs.ns(|| "2a2"))?.double(cs.ns(|| "4a2"))?; .sub(cs.ns(|| "c2 part3"), &s0)?
let a0_plus_2_a1_plus_4_a2 = self .sub(cs.ns(|| "c2 part4"), &s4)?;
.c0
.add(cs.ns(|| "a0 + 2a1"), &a1_double)?
.add(cs.ns(|| "a0 + 2a1 + 4a2"), &a2_quad)?;
a0_plus_2_a1_plus_4_a2.square(&mut cs.ns(|| "(a0 + 2a1 + 4a2)^2"))?
};
// v4 = a(∞)^2 = a2^2
let v4 = self.c2.square(&mut cs.ns(|| "a2^2"))?;
let two = <P::Fp2Params as Fp2Parameters>::Fp::one().double();
let six = two.double() + &two;
let mut two_and_six = [two, six];
algebra::fields::batch_inversion(&mut two_and_six);
let (two_inverse, six_inverse) = (two_and_six[0], two_and_six[1]);
let half_v0 = v0.mul_by_fp_constant(cs.ns(|| "half_v0"), &two_inverse)?;
let half_v1 = v1.mul_by_fp_constant(cs.ns(|| "half_v1"), &two_inverse)?;
let one_sixth_v2 = v2.mul_by_fp_constant(cs.ns(|| "one_sixth_v2"), &six_inverse)?;
let one_sixth_v3 = v3.mul_by_fp_constant(cs.ns(|| "one_sixth_v3"), &six_inverse)?;
let two_v4 = v4.double(cs.ns(|| "double_v4"))?;
// c0 = v0 + β((1/2)v0 (1/2)v1 (1/6)v2 + (1/6)v3 2v4)
let c0 = {
let mut c0_cs = cs.ns(|| "c0");
// No constraints, only get a linear combination back.
let inner = half_v0
.sub(c0_cs.ns(|| "sub1"), &half_v1)?
.sub(c0_cs.ns(|| "sub2"), &one_sixth_v2)?
.add(c0_cs.ns(|| "add3"), &one_sixth_v3)?
.sub(c0_cs.ns(|| "sub4"), &two_v4)?;
let non_residue_times_inner =
inner.mul_by_constant(c0_cs.ns(|| "mul_by_res"), &P::NONRESIDUE)?;
v0.add(c0_cs.ns(|| "add5"), &non_residue_times_inner)?
};
// (1/2)v0 + v1 (1/3)v2 (1/6)v3 + 2v4 + βv4
let c1 = {
let mut c1_cs = cs.ns(|| "c1");
let one_third_v2 = one_sixth_v2.double(c1_cs.ns(|| "v2_by_3"))?;
let non_residue_v4 = v4.mul_by_constant(c1_cs.ns(|| "mul_by_res"), &P::NONRESIDUE)?;
half_v0
.negate(c1_cs.ns(|| "neg1"))?
.add(c1_cs.ns(|| "add1"), &v1)?
.sub(c1_cs.ns(|| "sub2"), &one_third_v2)?
.sub(c1_cs.ns(|| "sub3"), &one_sixth_v3)?
.add(c1_cs.ns(|| "add4"), &two_v4)?
.add(c1_cs.ns(|| "add5"), &non_residue_v4)?
};
// -v0 + (1/2)v1 + (1/2)v2 v4
let c2 = {
let mut c2_cs = cs.ns(|| "c2");
let half_v2 = v2.mul_by_fp_constant(c2_cs.ns(|| "half_v2"), &two_inverse)?;
half_v1
.add(c2_cs.ns(|| "add1"), &half_v2)?
.sub(c2_cs.ns(|| "sub1"), &v4)?
.sub(c2_cs.ns(|| "sub2"), &v0)?
};
Ok(Self::new(c0, c1, c2)) Ok(Self::new(c0, c1, c2))
} }
// 18 constraints, we can probably do better but not sure it's worth it.
#[inline] #[inline]
fn inverse<CS: ConstraintSystem<ConstraintF>>( fn mul_equals<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
mut cs: CS, mut cs: CS,
) -> Result<Self, SynthesisError> { other: &Self,
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || { result: &Self,
self.get_value().and_then(|val| val.inverse()).get() ) -> Result<(), SynthesisError> {
})?; // Karatsuba multiplication for Fp3:
let one = Self::one(cs.ns(|| "one"))?; // v0 = A.c0 * B.c0
inverse.mul_equals(cs.ns(|| "check inverse"), &self, &one)?; // v1 = A.c1 * B.c1
Ok(inverse) // v2 = A.c2 * B.c2
// result.c0 = v0 + β((a1 + a2)(b1 + b2) v1 v2)
// result.c1 = (a0 + a1)(b0 + b1) v0 v1 + βv2
// result.c2 = (a0 + a2)(b0 + b2) v0 + v1 v2,
// We enforce this with six constraints:
//
// v0 = A.c0 * B.c0
// v1 = A.c1 * B.c1
// v2 = A.c2 * B.c2
//
// result.c0 - v0 + \beta*(v1 + v2) = β(a1 + a2)(b1 + b2))
// result.c1 + v0 + v1 - βv2 = (a0 + a1)(b0 + b1)
// result.c2 + v0 - v1 + v2 = (a0 + a2)(b0 + b2)
// Reference:
// "Multiplication and Squaring on Pairing-Friendly Fields"
// Devegili, OhEigeartaigh, Scott, Dahab
//
// This implementation adapted from
// https://github.com/ZencashOfficial/ginger-lib/blob/development/r1cs/gadgets/std/src/fields/fp3.rs
let v0 = self.c0.mul(cs.ns(|| "v0 = a0 * b0"), &other.c0)?;
let v1 = self.c1.mul(cs.ns(|| "v1 = a1 * b1"), &other.c1)?;
let v2 = self.c2.mul(cs.ns(|| "v2 = a2 * b2"), &other.c2)?;
// Check c0
let nr_a1_plus_a2 = self
.c1
.add(cs.ns(|| "a1 + a2"), &self.c2)?
.mul_by_constant(cs.ns(|| "nr*(a1 + a2)"), &P::NONRESIDUE)?;
let b1_plus_b2 = other.c1.add(cs.ns(|| "b1 + b2"), &other.c2)?;
let nr_v1 = v1.mul_by_constant(cs.ns(|| "nr * v1"), &P::NONRESIDUE)?;
let nr_v2 = v2.mul_by_constant(cs.ns(|| "nr * v2"), &P::NONRESIDUE)?;
let to_check = result
.c0
.sub(cs.ns(|| "c0 - v0"), &v0)?
.add(cs.ns(|| "c0 - v0 + nr * v1"), &nr_v1)?
.add(cs.ns(|| "c0 - v0 + nr * v1 + nr * v2"), &nr_v2)?;
nr_a1_plus_a2.mul_equals(cs.ns(|| "check c0"), &b1_plus_b2, &to_check)?;
// Check c1
let a0_plus_a1 = self.c0.add(cs.ns(|| "a0 + a1"), &self.c1)?;
let b0_plus_b1 = other.c0.add(cs.ns(|| "b0 + b1"), &other.c1)?;
let to_check = result
.c1
.sub(cs.ns(|| "c1 - nr * v2"), &nr_v2)?
.add(cs.ns(|| "c1 - nr * v2 + v0"), &v0)?
.add(cs.ns(|| "c1 - nr * v2 + v0 + v1"), &v1)?;
a0_plus_a1.mul_equals(cs.ns(|| "check c1"), &b0_plus_b1, &to_check)?;
// Check c2
let a0_plus_a2 = self.c0.add(cs.ns(|| "a0 + a2"), &self.c2)?;
let b0_plus_b2 = other.c0.add(cs.ns(|| "b0 + b2"), &other.c2)?;
let to_check = result
.c2
.add(cs.ns(|| "c2 + v0"), &v0)?
.sub(cs.ns(|| "c2 + v0 - v1"), &v1)?
.add(cs.ns(|| "c2 + v0 - v1 + v2"), &v2)?;
a0_plus_a2.mul_equals(cs.ns(|| "check c2"), &b0_plus_b2, &to_check)?;
Ok(())
} }
#[inline] #[inline]
@@ -704,8 +697,8 @@ where
5 * Fp2Gadget::<P, ConstraintF>::cost_of_mul() 5 * Fp2Gadget::<P, ConstraintF>::cost_of_mul()
} }
fn cost_of_inv() -> usize { fn cost_of_mul_equals() -> usize {
Self::cost_of_mul() + <Self as EqGadget<ConstraintF>>::cost() 6 * Fp2Gadget::<P, ConstraintF>::cost_of_mul()
} }
} }
@@ -984,7 +977,7 @@ where
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1), Ok(fe.c2)) (Ok(fe.c0), Ok(fe.c1), Ok(fe.c2))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -1011,7 +1004,7 @@ where
Ok(fe) => { Ok(fe) => {
let fe = *fe.borrow(); let fe = *fe.borrow();
(Ok(fe.c0), Ok(fe.c1), Ok(fe.c2)) (Ok(fe.c0), Ok(fe.c1), Ok(fe.c2))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),

View File

@@ -2,7 +2,7 @@ use algebra::{fields::BitIterator, Field};
use core::fmt::Debug; use core::fmt::Debug;
use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSystem, SynthesisError};
use crate::prelude::*; use crate::{prelude::*, Assignment};
pub mod fp; pub mod fp;
pub mod fp12; pub mod fp12;
@@ -188,7 +188,17 @@ pub trait FieldGadget<F: Field, ConstraintF: Field>:
Ok(self) Ok(self)
} }
fn inverse<CS: ConstraintSystem<ConstraintF>>(&self, _: CS) -> Result<Self, SynthesisError>; fn inverse<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
) -> Result<Self, SynthesisError> {
let one = Self::one(&mut cs.ns(|| "one"))?;
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || {
self.get_value().and_then(|val| val.inverse()).get()
})?;
self.mul_equals(cs.ns(|| "check inv"), &inverse, &one)?;
Ok(inverse)
}
fn frobenius_map<CS: ConstraintSystem<ConstraintF>>( fn frobenius_map<CS: ConstraintSystem<ConstraintF>>(
&self, &self,
@@ -255,7 +265,9 @@ pub trait FieldGadget<F: Field, ConstraintF: Field>:
Self::cost_of_mul() + <Self as EqGadget<ConstraintF>>::cost() Self::cost_of_mul() + <Self as EqGadget<ConstraintF>>::cost()
} }
fn cost_of_inv() -> usize; fn cost_of_inv() -> usize {
Self::cost_of_mul_equals()
}
} }
#[cfg(test)] #[cfg(test)]

View File

@@ -53,7 +53,7 @@ impl<P: SWModelParameters, ConstraintF: Field, F: FieldGadget<P::BaseField, Cons
Ok(ge) => { Ok(ge) => {
let ge = ge.into_affine(); let ge = ge.into_affine();
(Ok(ge.x), Ok(ge.y), Ok(ge.infinity)) (Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -107,7 +107,7 @@ where
) { ) {
(Some(x), Some(y), Some(infinity)) => { (Some(x), Some(y), Some(infinity)) => {
Some(SWAffine::new(x, y, infinity).into_projective()) Some(SWAffine::new(x, y, infinity).into_projective())
}, }
(None, None, None) => None, (None, None, None) => None,
_ => unreachable!(), _ => unreachable!(),
} }
@@ -450,7 +450,7 @@ where
Ok(ge) => { Ok(ge) => {
let ge = ge.borrow().into_affine(); let ge = ge.borrow().into_affine();
(Ok(ge.x), Ok(ge.y), Ok(ge.infinity)) (Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -574,7 +574,7 @@ where
Ok(ge) => { Ok(ge) => {
let ge = ge.borrow().into_affine(); let ge = ge.borrow().into_affine();
(Ok(ge.x), Ok(ge.y), Ok(ge.infinity)) (Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),

View File

@@ -90,7 +90,7 @@ mod montgomery_affine_impl {
t0.mul_assign(&invy); t0.mul_assign(&invy);
Ok(t0) Ok(t0)
}, }
None => Err(SynthesisError::DivisionByZero), None => Err(SynthesisError::DivisionByZero),
} }
})?; })?;
@@ -108,7 +108,7 @@ mod montgomery_affine_impl {
t0.mul_assign(&t1); t0.mul_assign(&t1);
Ok(t0) Ok(t0)
}, }
None => Err(SynthesisError::DivisionByZero), None => Err(SynthesisError::DivisionByZero),
} }
})?; })?;
@@ -140,7 +140,7 @@ mod montgomery_affine_impl {
Some(d) => { Some(d) => {
n.mul_assign(&d); n.mul_assign(&d);
Ok(n) Ok(n)
}, }
None => Err(SynthesisError::DivisionByZero), None => Err(SynthesisError::DivisionByZero),
} }
})?; })?;
@@ -504,7 +504,7 @@ mod affine_impl {
Ok(ge) => { Ok(ge) => {
let ge = *ge.borrow(); let ge = *ge.borrow();
(Ok(ge.x), Ok(ge.y)) (Ok(ge.x), Ok(ge.y))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -621,7 +621,7 @@ mod affine_impl {
Ok(ge) => { Ok(ge) => {
let ge = *ge.borrow(); let ge = *ge.borrow();
(Ok(ge.x), Ok(ge.y)) (Ok(ge.x), Ok(ge.y))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -960,14 +960,14 @@ mod projective_impl {
match edwards_result { match edwards_result {
None => { None => {
edwards_result = Some(segment_result); edwards_result = Some(segment_result);
}, }
Some(ref mut edwards_result) => { Some(ref mut edwards_result) => {
*edwards_result = GroupGadget::<TEAffine<P>, ConstraintF>::add( *edwards_result = GroupGadget::<TEAffine<P>, ConstraintF>::add(
&segment_result, &segment_result,
cs.ns(|| "edwards addition"), cs.ns(|| "edwards addition"),
edwards_result, edwards_result,
)?; )?;
}, }
} }
Ok(()) Ok(())
@@ -1050,13 +1050,13 @@ mod projective_impl {
match result { match result {
None => { None => {
result = Some(tmp); result = Some(tmp);
}, }
Some(ref mut result) => { Some(ref mut result) => {
*result = tmp.add( *result = tmp.add(
cs.ns(|| format!("addition of window {}, {}", segment_i, i)), cs.ns(|| format!("addition of window {}, {}", segment_i, i)),
result, result,
)?; )?;
}, }
} }
} }
@@ -1101,7 +1101,7 @@ mod projective_impl {
Ok(ge) => { Ok(ge) => {
let ge = ge.borrow().into_affine(); let ge = ge.borrow().into_affine();
(Ok(ge.x), Ok(ge.y)) (Ok(ge.x), Ok(ge.y))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
@@ -1223,7 +1223,7 @@ mod projective_impl {
Ok(ge) => { Ok(ge) => {
let ge = ge.borrow().into_affine(); let ge = ge.borrow().into_affine();
(Ok(ge.x), Ok(ge.y)) (Ok(ge.x), Ok(ge.y))
}, }
_ => ( _ => (
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),
Err(SynthesisError::AssignmentMissing), Err(SynthesisError::AssignmentMissing),

View File

@@ -33,8 +33,8 @@ use ralloc::{collections::BTreeMap, string::String, vec::Vec};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::{collections::BTreeMap, string::String, vec::Vec}; use std::{collections::BTreeMap, string::String, vec::Vec};
pub mod test_constraint_system;
pub mod test_constraint_counter; pub mod test_constraint_counter;
pub mod test_constraint_system;
pub mod bits; pub mod bits;
pub use self::bits::*; pub use self::bits::*;

View File

@@ -36,7 +36,7 @@ impl<P: Bls12Parameters> PairingGadget<P> {
c1.c1 = c1.c1.mul(cs.ns(|| "mul c1.c1"), &p.x)?; c1.c1 = c1.c1.mul(cs.ns(|| "mul c1.c1"), &p.x)?;
*f = f.mul_by_014(cs.ns(|| "sparse mul f"), &c0, &c1, &c2)?; *f = f.mul_by_014(cs.ns(|| "sparse mul f"), &c0, &c1, &c2)?;
Ok(()) Ok(())
}, }
TwistType::D => { TwistType::D => {
let c0 = Fp2G::<P>::new(p.y.clone(), zero); let c0 = Fp2G::<P>::new(p.y.clone(), zero);
let mut c1 = coeffs.0.clone(); let mut c1 = coeffs.0.clone();
@@ -46,7 +46,7 @@ impl<P: Bls12Parameters> PairingGadget<P> {
c1.c1 = c1.c1.mul(cs.ns(|| "mul c1.c1"), &p.x)?; c1.c1 = c1.c1.mul(cs.ns(|| "mul c1.c1"), &p.x)?;
*f = f.mul_by_034(cs.ns(|| "sparse mul f"), &c0, &c1, &c2)?; *f = f.mul_by_034(cs.ns(|| "sparse mul f"), &c0, &c1, &c2)?;
Ok(()) Ok(())
}, }
} }
} }

View File

@@ -1,13 +1,9 @@
reorder_imports = true reorder_imports = true
wrap_comments = true wrap_comments = true
normalize_comments = true normalize_comments = true
format_strings = true
struct_field_align_threshold = 40
use_try_shorthand = true use_try_shorthand = true
match_block_trailing_comma = true match_block_trailing_comma = true
use_field_init_shorthand = true use_field_init_shorthand = true
edition = "2018" edition = "2018"
condense_wildcard_suffixes = true condense_wildcard_suffixes = true
merge_imports = true merge_imports = true
imports_layout = "Mixed"
unstable_features = true