pairing: Remove BLS12-381 implementation
It is replaced by the bls12_381 crate.
This commit is contained in:
parent
b9a8e1e415
commit
f735e8b83b
|
@ -24,6 +24,7 @@ byteorder = "1"
|
|||
subtle = "2.2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
bls12_381 = { version = "0.1", path = "../bls12_381" }
|
||||
hex-literal = "0.2"
|
||||
rand = "0.7"
|
||||
rand_xorshift = "0.2"
|
||||
|
|
|
@ -375,7 +375,7 @@ fn parallel_fft<S: PrimeField, T: Group<S>>(
|
|||
#[cfg(feature = "pairing")]
|
||||
#[test]
|
||||
fn polynomial_arith() {
|
||||
use pairing::bls12_381::Fr;
|
||||
use bls12_381::Scalar as Fr;
|
||||
use rand_core::RngCore;
|
||||
|
||||
fn test_mul<S: PrimeField, R: RngCore>(rng: &mut R) {
|
||||
|
@ -422,7 +422,7 @@ fn polynomial_arith() {
|
|||
#[cfg(feature = "pairing")]
|
||||
#[test]
|
||||
fn fft_composition() {
|
||||
use pairing::bls12_381::Fr;
|
||||
use bls12_381::Scalar as Fr;
|
||||
use rand_core::RngCore;
|
||||
|
||||
fn test_comp<S: PrimeField, R: RngCore>(rng: &mut R) {
|
||||
|
@ -460,7 +460,7 @@ fn fft_composition() {
|
|||
#[cfg(feature = "pairing")]
|
||||
#[test]
|
||||
fn parallel_fft_consistency() {
|
||||
use pairing::bls12_381::Fr;
|
||||
use bls12_381::Scalar as Fr;
|
||||
use rand_core::RngCore;
|
||||
use std::cmp::min;
|
||||
|
||||
|
|
|
@ -408,8 +408,8 @@ pub fn blake2s<Scalar: PrimeField, CS: ConstraintSystem<Scalar>>(
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use blake2s_simd::Params as Blake2sParams;
|
||||
use bls12_381::Scalar;
|
||||
use hex_literal::hex;
|
||||
use pairing::bls12_381::Fr;
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
|
@ -420,7 +420,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_blank_hash() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let input_bits = vec![];
|
||||
let out = blake2s(&mut cs, &input_bits, b"12345678").unwrap();
|
||||
assert!(cs.is_satisfied());
|
||||
|
@ -443,7 +443,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_blake2s_constraints() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let input_bits: Vec<_> = (0..512)
|
||||
.map(|i| {
|
||||
AllocatedBit::alloc(cs.namespace(|| format!("input bit {}", i)), Some(true))
|
||||
|
@ -461,7 +461,7 @@ mod test {
|
|||
// Test that 512 fixed leading bits (constants)
|
||||
// doesn't result in more constraints.
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
|
||||
0xbc, 0xe5,
|
||||
|
@ -481,7 +481,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_blake2s_constant_constraints() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
|
||||
0xbc, 0xe5,
|
||||
|
@ -512,7 +512,7 @@ mod test {
|
|||
|
||||
let hash_result = h.finalize();
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let mut input_bits = vec![];
|
||||
|
||||
|
@ -559,7 +559,7 @@ mod test {
|
|||
let data: Vec<u8> = hex!("be9f9c485e670acce8b1516a378176161b20583637b6f1c536fbc1158a0a3296831df2920e57a442d5738f4be4dd6be89dd7913fc8b4d1c0a815646a4d674b77f7caf313bd880bf759fcac27037c48c2b2a20acd2fd5248e3be426c84a341c0a3c63eaf36e0d537d10b8db5c6e4c801832c41eb1a3ed602177acded8b4b803bd34339d99a18b71df399641cc8dfae2ad193fcd74b5913e704551777160d14c78f2e8d5c32716a8599c1080cb89a40ccd6ba596694a8b4a065d9f2d0667ef423ed2e418093caff884540858b4f4b62acd47edcea880523e1b1cda8eb225c128c2e9e83f14f6e7448c5733a195cac7d79a53dde5083172462c45b2f799e42af1c9").to_vec();
|
||||
assert_eq!(data.len(), 256);
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let mut input_bits = vec![];
|
||||
|
||||
|
@ -596,7 +596,7 @@ mod test {
|
|||
let data: Vec<u8> = hex!("5dcfe8bab4c758d2eb1ddb7ef337583e0df3e2c358e1755b7cd303a658de9a1227eed1d1114179a5c3c38d692ff2cf2d4e5c92a9516de750106774bbf9f7d063f707f4c9b6a02c0a77e4feb99e036c3ccaee7d1a31cb144093aa074bc9da608f8ff30b39c3c60e4a243cc0bbd406d1262a7d6607b31c60275c6bcc8b0ac49a06a4b629a98693c5f7640f3bca45e4977cfabc5b17f52838af3433b1fd407dbbdc131e8e4bd58bcee85bbab4b57b656c6a2ec6cf852525bc8423675e2bf29159139cd5df99db94719f3f7167230e0d5bd76f6d7891b656732cef9c3c0d48a5fa3d7a879988157b39015a85451b25af0301ca5e759ac35fea79dca38c673ec6db9f3885d9103e2dcb3304bd3d59b0b1d01babc97ef8a74d91b6ab6bf50f29eb5adf7250a28fd85db37bff0133193635da69caeefc72979cf3bef1d2896d847eea7e8a81e0927893dbd010feb6fb845d0399007d9a148a0596d86cd8f4192631f975c560f4de8da5f712c161342063af3c11029d93d6df7ff46db48343499de9ec4786cac059c4025ef418c9fe40132428ff8b91259d71d1709ff066add84ae944b45a817f60b4c1bf719e39ae23e9b413469db2310793e9137cf38741e5dd2a3c138a566dbde1950c00071b20ac457b46ba9b0a7ebdddcc212bd228d2a4c4146a970e54158477247c27871af1564b176576e9fd43bf63740bf77434bc4ea3b1a4b430e1a11714bf43160145578a575c3f78ddeaa48de97f73460f26f8df2b5d63e31800100d16bc27160fea5ced5a977ef541cfe8dadc7b3991ed1c0d4f16a3076bbfed96ba3e155113e794987af8abb133f06feefabc2ac32eb4d4d4ba1541ca08b9e518d2e74b7f946b0cbd2663d58c689359b9a565821acc619011233d1011963fa302cde34fc9c5ba2e03eeb2512f547391e940d56218e22ae325f2dfa38d4bae35744ee707aa5dc9c17674025d15390a08f5c452343546ef6da0f7").to_vec();
|
||||
assert_eq!(data.len(), 700);
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let mut input_bits = vec![];
|
||||
|
||||
|
@ -651,7 +651,7 @@ mod test {
|
|||
|
||||
let hash_result = h.finalize();
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let mut input_bits = vec![];
|
||||
|
||||
|
|
|
@ -749,19 +749,19 @@ mod test {
|
|||
use super::{field_into_allocated_bits_le, u64_into_boolean_vec_le, AllocatedBit, Boolean};
|
||||
use crate::gadgets::test::*;
|
||||
use crate::ConstraintSystem;
|
||||
use bls12_381::Scalar;
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::bls12_381::Fr;
|
||||
|
||||
#[test]
|
||||
fn test_allocated_bit() {
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
AllocatedBit::alloc(&mut cs, Some(true)).unwrap();
|
||||
assert!(cs.get("boolean") == Fr::one());
|
||||
assert!(cs.get("boolean") == Scalar::one());
|
||||
assert!(cs.is_satisfied());
|
||||
cs.set("boolean", Fr::zero());
|
||||
cs.set("boolean", Scalar::zero());
|
||||
assert!(cs.is_satisfied());
|
||||
cs.set("boolean", Fr::from_str("2").unwrap());
|
||||
cs.set("boolean", Scalar::from_str("2").unwrap());
|
||||
assert!(!cs.is_satisfied());
|
||||
assert!(cs.which_is_unsatisfied() == Some("boolean constraint"));
|
||||
}
|
||||
|
@ -770,7 +770,7 @@ mod test {
|
|||
fn test_xor() {
|
||||
for a_val in [false, true].iter() {
|
||||
for b_val in [false, true].iter() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let a = AllocatedBit::alloc(cs.namespace(|| "a"), Some(*a_val)).unwrap();
|
||||
let b = AllocatedBit::alloc(cs.namespace(|| "b"), Some(*b_val)).unwrap();
|
||||
let c = AllocatedBit::xor(&mut cs, &a, &b).unwrap();
|
||||
|
@ -806,7 +806,7 @@ mod test {
|
|||
fn test_and() {
|
||||
for a_val in [false, true].iter() {
|
||||
for b_val in [false, true].iter() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let a = AllocatedBit::alloc(cs.namespace(|| "a"), Some(*a_val)).unwrap();
|
||||
let b = AllocatedBit::alloc(cs.namespace(|| "b"), Some(*b_val)).unwrap();
|
||||
let c = AllocatedBit::and(&mut cs, &a, &b).unwrap();
|
||||
|
@ -842,7 +842,7 @@ mod test {
|
|||
fn test_and_not() {
|
||||
for a_val in [false, true].iter() {
|
||||
for b_val in [false, true].iter() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let a = AllocatedBit::alloc(cs.namespace(|| "a"), Some(*a_val)).unwrap();
|
||||
let b = AllocatedBit::alloc(cs.namespace(|| "b"), Some(*b_val)).unwrap();
|
||||
let c = AllocatedBit::and_not(&mut cs, &a, &b).unwrap();
|
||||
|
@ -878,7 +878,7 @@ mod test {
|
|||
fn test_nor() {
|
||||
for a_val in [false, true].iter() {
|
||||
for b_val in [false, true].iter() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let a = AllocatedBit::alloc(cs.namespace(|| "a"), Some(*a_val)).unwrap();
|
||||
let b = AllocatedBit::alloc(cs.namespace(|| "b"), Some(*b_val)).unwrap();
|
||||
let c = AllocatedBit::nor(&mut cs, &a, &b).unwrap();
|
||||
|
@ -917,7 +917,7 @@ mod test {
|
|||
for a_neg in [false, true].iter().cloned() {
|
||||
for b_neg in [false, true].iter().cloned() {
|
||||
{
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let mut a = Boolean::from(
|
||||
AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_bool)).unwrap(),
|
||||
|
@ -938,7 +938,7 @@ mod test {
|
|||
assert_eq!(cs.is_satisfied(), (a_bool ^ a_neg) == (b_bool ^ b_neg));
|
||||
}
|
||||
{
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let mut a = Boolean::Constant(a_bool);
|
||||
let mut b = Boolean::from(
|
||||
|
@ -957,7 +957,7 @@ mod test {
|
|||
assert_eq!(cs.is_satisfied(), (a_bool ^ a_neg) == (b_bool ^ b_neg));
|
||||
}
|
||||
{
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let mut a = Boolean::from(
|
||||
AllocatedBit::alloc(cs.namespace(|| "a"), Some(a_bool)).unwrap(),
|
||||
|
@ -976,7 +976,7 @@ mod test {
|
|||
assert_eq!(cs.is_satisfied(), (a_bool ^ a_neg) == (b_bool ^ b_neg));
|
||||
}
|
||||
{
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let mut a = Boolean::Constant(a_bool);
|
||||
let mut b = Boolean::Constant(b_bool);
|
||||
|
@ -1005,7 +1005,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_boolean_negation() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let mut b = Boolean::from(AllocatedBit::alloc(&mut cs, Some(true)).unwrap());
|
||||
|
||||
|
@ -1097,7 +1097,7 @@ mod test {
|
|||
|
||||
for first_operand in variants.iter().cloned() {
|
||||
for second_operand in variants.iter().cloned() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let a;
|
||||
let b;
|
||||
|
@ -1306,7 +1306,7 @@ mod test {
|
|||
|
||||
for first_operand in variants.iter().cloned() {
|
||||
for second_operand in variants.iter().cloned() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let a;
|
||||
let b;
|
||||
|
@ -1527,7 +1527,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_u64_into_boolean_vec_le() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let bits = u64_into_boolean_vec_le(&mut cs, Some(17234652694787248421)).unwrap();
|
||||
|
||||
|
@ -1548,9 +1548,9 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_field_into_allocated_bits_le() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let r = Fr::from_str(
|
||||
let r = Scalar::from_str(
|
||||
"9147677615426976802526883532204139322118074541891858454835346926874644257775",
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -1643,16 +1643,16 @@ mod test {
|
|||
} else {
|
||||
assert_eq!(cs.get("ch"), {
|
||||
if expected {
|
||||
Fr::one()
|
||||
Scalar::one()
|
||||
} else {
|
||||
Fr::zero()
|
||||
Scalar::zero()
|
||||
}
|
||||
});
|
||||
cs.set("ch", {
|
||||
if expected {
|
||||
Fr::zero()
|
||||
Scalar::zero()
|
||||
} else {
|
||||
Fr::one()
|
||||
Scalar::one()
|
||||
}
|
||||
});
|
||||
assert_eq!(cs.which_is_unsatisfied().unwrap(), "ch computation");
|
||||
|
@ -1735,16 +1735,16 @@ mod test {
|
|||
} else {
|
||||
assert_eq!(cs.get("maj"), {
|
||||
if expected {
|
||||
Fr::one()
|
||||
Scalar::one()
|
||||
} else {
|
||||
Fr::zero()
|
||||
Scalar::zero()
|
||||
}
|
||||
});
|
||||
cs.set("maj", {
|
||||
if expected {
|
||||
Fr::zero()
|
||||
Scalar::zero()
|
||||
} else {
|
||||
Fr::one()
|
||||
Scalar::one()
|
||||
}
|
||||
});
|
||||
assert_eq!(cs.which_is_unsatisfied().unwrap(), "maj computation");
|
||||
|
@ -1757,7 +1757,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_alloc_conditionally() {
|
||||
{
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let b = AllocatedBit::alloc(&mut cs, Some(false)).unwrap();
|
||||
|
||||
let value = None;
|
||||
|
@ -1773,7 +1773,7 @@ mod test {
|
|||
|
||||
{
|
||||
// since value is true, b must be false, so it should succeed
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let value = Some(true);
|
||||
let b = AllocatedBit::alloc(&mut cs, Some(false)).unwrap();
|
||||
|
@ -1790,7 +1790,7 @@ mod test {
|
|||
|
||||
{
|
||||
// since value is true, b must be false, so it should fail
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let value = Some(true);
|
||||
let b = AllocatedBit::alloc(&mut cs, Some(true)).unwrap();
|
||||
|
@ -1805,7 +1805,7 @@ mod test {
|
|||
|
||||
let value = Some(false);
|
||||
//check with false bit
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let b1 = AllocatedBit::alloc(&mut cs, Some(false)).unwrap();
|
||||
AllocatedBit::alloc_conditionally(cs.namespace(|| "alloc_conditionally"), value, &b1)
|
||||
.unwrap();
|
||||
|
@ -1813,7 +1813,7 @@ mod test {
|
|||
assert!(cs.is_satisfied());
|
||||
|
||||
//check with true bit
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let b2 = AllocatedBit::alloc(&mut cs, Some(true)).unwrap();
|
||||
AllocatedBit::alloc_conditionally(cs.namespace(|| "alloc_conditionally"), value, &b2)
|
||||
.unwrap();
|
||||
|
|
|
@ -191,8 +191,8 @@ mod test {
|
|||
use crate::gadgets::boolean::{AllocatedBit, Boolean};
|
||||
use crate::gadgets::test::*;
|
||||
|
||||
use bls12_381::Scalar;
|
||||
use ff::Field;
|
||||
use pairing::bls12_381::Fr;
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{AddAssign, Neg};
|
||||
|
@ -218,8 +218,8 @@ mod test {
|
|||
|
||||
let bits = vec![a, b, c];
|
||||
|
||||
let points: Vec<(Fr, Fr)> = (0..8)
|
||||
.map(|_| (Fr::random(&mut rng), Fr::random(&mut rng)))
|
||||
let points: Vec<(Scalar, Scalar)> = (0..8)
|
||||
.map(|_| (Scalar::random(&mut rng), Scalar::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let res = lookup3_xy(&mut cs, &bits, &points).unwrap();
|
||||
|
@ -263,8 +263,8 @@ mod test {
|
|||
|
||||
let bits = vec![a, b, c];
|
||||
|
||||
let points: Vec<(Fr, Fr)> = (0..4)
|
||||
.map(|_| (Fr::random(&mut rng), Fr::random(&mut rng)))
|
||||
let points: Vec<(Scalar, Scalar)> = (0..4)
|
||||
.map(|_| (Scalar::random(&mut rng), Scalar::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let res = lookup3_xy_with_conditional_negation(&mut cs, &bits, &points).unwrap();
|
||||
|
@ -297,15 +297,15 @@ mod test {
|
|||
|
||||
let window_size = 4;
|
||||
|
||||
let mut assignment = vec![Fr::zero(); 1 << window_size];
|
||||
let mut assignment = vec![Scalar::zero(); 1 << window_size];
|
||||
let constants: Vec<_> = (0..(1 << window_size))
|
||||
.map(|_| Fr::random(&mut rng))
|
||||
.map(|_| Scalar::random(&mut rng))
|
||||
.collect();
|
||||
|
||||
synth(window_size, &constants, &mut assignment);
|
||||
|
||||
for b in 0..(1 << window_size) {
|
||||
let mut acc = Fr::zero();
|
||||
let mut acc = Scalar::zero();
|
||||
|
||||
for j in 0..(1 << window_size) {
|
||||
if j & b == j {
|
||||
|
|
|
@ -74,7 +74,7 @@ pub fn compute_multipacking<Scalar: PrimeField>(bits: &[bool]) -> Vec<Scalar> {
|
|||
#[test]
|
||||
fn test_multipacking() {
|
||||
use crate::ConstraintSystem;
|
||||
use pairing::bls12_381::Fr;
|
||||
use bls12_381::Scalar;
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
|
@ -87,7 +87,7 @@ fn test_multipacking() {
|
|||
]);
|
||||
|
||||
for num_bits in 0..1500 {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let bits: Vec<bool> = (0..num_bits).map(|_| rng.next_u32() % 2 != 0).collect();
|
||||
|
||||
|
|
|
@ -410,8 +410,8 @@ impl<Scalar: PrimeField> Num<Scalar> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::ConstraintSystem;
|
||||
use bls12_381::Scalar;
|
||||
use ff::{BitIterator, Field, PrimeField};
|
||||
use pairing::bls12_381::Fr;
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{Neg, SubAssign};
|
||||
|
@ -423,22 +423,22 @@ mod test {
|
|||
fn test_allocated_num() {
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
AllocatedNum::alloc(&mut cs, || Ok(Fr::one())).unwrap();
|
||||
AllocatedNum::alloc(&mut cs, || Ok(Scalar::one())).unwrap();
|
||||
|
||||
assert!(cs.get("num") == Fr::one());
|
||||
assert!(cs.get("num") == Scalar::one());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_num_squaring() {
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
let n = AllocatedNum::alloc(&mut cs, || Ok(Fr::from_str("3").unwrap())).unwrap();
|
||||
let n = AllocatedNum::alloc(&mut cs, || Ok(Scalar::from_str("3").unwrap())).unwrap();
|
||||
let n2 = n.square(&mut cs).unwrap();
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert!(cs.get("squared num") == Fr::from_str("9").unwrap());
|
||||
assert!(n2.value.unwrap() == Fr::from_str("9").unwrap());
|
||||
cs.set("squared num", Fr::from_str("10").unwrap());
|
||||
assert!(cs.get("squared num") == Scalar::from_str("9").unwrap());
|
||||
assert!(n2.value.unwrap() == Scalar::from_str("9").unwrap());
|
||||
cs.set("squared num", Scalar::from_str("10").unwrap());
|
||||
assert!(!cs.is_satisfied());
|
||||
}
|
||||
|
||||
|
@ -446,16 +446,16 @@ mod test {
|
|||
fn test_num_multiplication() {
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
let n =
|
||||
AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Fr::from_str("12").unwrap())).unwrap();
|
||||
let n2 =
|
||||
AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Fr::from_str("10").unwrap())).unwrap();
|
||||
let n = AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Scalar::from_str("12").unwrap()))
|
||||
.unwrap();
|
||||
let n2 = AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Scalar::from_str("10").unwrap()))
|
||||
.unwrap();
|
||||
let n3 = n.mul(&mut cs, &n2).unwrap();
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert!(cs.get("product num") == Fr::from_str("120").unwrap());
|
||||
assert!(n3.value.unwrap() == Fr::from_str("120").unwrap());
|
||||
cs.set("product num", Fr::from_str("121").unwrap());
|
||||
assert!(cs.get("product num") == Scalar::from_str("120").unwrap());
|
||||
assert!(n3.value.unwrap() == Scalar::from_str("120").unwrap());
|
||||
cs.set("product num", Scalar::from_str("121").unwrap());
|
||||
assert!(!cs.is_satisfied());
|
||||
}
|
||||
|
||||
|
@ -468,8 +468,10 @@ mod test {
|
|||
{
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
let a = AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Fr::random(&mut rng))).unwrap();
|
||||
let b = AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Fr::random(&mut rng))).unwrap();
|
||||
let a =
|
||||
AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Scalar::random(&mut rng))).unwrap();
|
||||
let b =
|
||||
AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Scalar::random(&mut rng))).unwrap();
|
||||
let condition = Boolean::constant(false);
|
||||
let (c, d) = AllocatedNum::conditionally_reverse(&mut cs, &a, &b, &condition).unwrap();
|
||||
|
||||
|
@ -482,8 +484,10 @@ mod test {
|
|||
{
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
let a = AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Fr::random(&mut rng))).unwrap();
|
||||
let b = AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Fr::random(&mut rng))).unwrap();
|
||||
let a =
|
||||
AllocatedNum::alloc(cs.namespace(|| "a"), || Ok(Scalar::random(&mut rng))).unwrap();
|
||||
let b =
|
||||
AllocatedNum::alloc(cs.namespace(|| "b"), || Ok(Scalar::random(&mut rng))).unwrap();
|
||||
let condition = Boolean::constant(true);
|
||||
let (c, d) = AllocatedNum::conditionally_reverse(&mut cs, &a, &b, &condition).unwrap();
|
||||
|
||||
|
@ -499,24 +503,24 @@ mod test {
|
|||
{
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
let n = AllocatedNum::alloc(&mut cs, || Ok(Fr::from_str("3").unwrap())).unwrap();
|
||||
let n = AllocatedNum::alloc(&mut cs, || Ok(Scalar::from_str("3").unwrap())).unwrap();
|
||||
n.assert_nonzero(&mut cs).unwrap();
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
cs.set("ephemeral inverse", Fr::from_str("3").unwrap());
|
||||
cs.set("ephemeral inverse", Scalar::from_str("3").unwrap());
|
||||
assert!(cs.which_is_unsatisfied() == Some("nonzero assertion constraint"));
|
||||
}
|
||||
{
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
let n = AllocatedNum::alloc(&mut cs, || Ok(Fr::zero())).unwrap();
|
||||
let n = AllocatedNum::alloc(&mut cs, || Ok(Scalar::zero())).unwrap();
|
||||
assert!(n.assert_nonzero(&mut cs).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_into_bits_strict() {
|
||||
let negone = Fr::one().neg();
|
||||
let negone = Scalar::one().neg();
|
||||
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
|
@ -526,7 +530,7 @@ mod test {
|
|||
assert!(cs.is_satisfied());
|
||||
|
||||
// make the bit representation the characteristic
|
||||
cs.set("bit 254/boolean", Fr::one());
|
||||
cs.set("bit 254/boolean", Scalar::one());
|
||||
|
||||
// this makes the conditional boolean constraint fail
|
||||
assert_eq!(
|
||||
|
@ -543,7 +547,7 @@ mod test {
|
|||
]);
|
||||
|
||||
for i in 0..200 {
|
||||
let r = Fr::random(&mut rng);
|
||||
let r = Scalar::random(&mut rng);
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
|
||||
let n = AllocatedNum::alloc(&mut cs, || Ok(r)).unwrap();
|
||||
|
@ -567,15 +571,15 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
cs.set("num", Fr::random(&mut rng));
|
||||
cs.set("num", Scalar::random(&mut rng));
|
||||
assert!(!cs.is_satisfied());
|
||||
cs.set("num", r);
|
||||
assert!(cs.is_satisfied());
|
||||
|
||||
for i in 0..Fr::NUM_BITS {
|
||||
for i in 0..Scalar::NUM_BITS {
|
||||
let name = format!("bit {}/boolean", i);
|
||||
let cur = cs.get(&name);
|
||||
let mut tmp = Fr::one();
|
||||
let mut tmp = Scalar::one();
|
||||
tmp.sub_assign(&cur);
|
||||
cs.set(&name, tmp);
|
||||
assert!(!cs.is_satisfied());
|
||||
|
|
|
@ -273,8 +273,8 @@ mod test {
|
|||
use super::*;
|
||||
use crate::gadgets::boolean::AllocatedBit;
|
||||
use crate::gadgets::test::TestConstraintSystem;
|
||||
use bls12_381::Scalar;
|
||||
use hex_literal::hex;
|
||||
use pairing::bls12_381::Fr;
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
|
@ -282,7 +282,7 @@ mod test {
|
|||
fn test_blank_hash() {
|
||||
let iv = get_sha256_iv();
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let mut input_bits: Vec<_> = (0..512).map(|_| Boolean::Constant(false)).collect();
|
||||
input_bits[0] = Boolean::Constant(true);
|
||||
let out = sha256_compression_function(&mut cs, &input_bits, &iv).unwrap();
|
||||
|
@ -312,7 +312,7 @@ mod test {
|
|||
|
||||
let iv = get_sha256_iv();
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let input_bits: Vec<_> = (0..512)
|
||||
.map(|i| {
|
||||
Boolean::from(
|
||||
|
@ -346,7 +346,7 @@ mod test {
|
|||
h.update(&data);
|
||||
let hash_result = h.finalize();
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
let mut input_bits = vec![];
|
||||
|
||||
for (byte_i, input_byte) in data.into_iter().enumerate() {
|
||||
|
|
|
@ -418,46 +418,46 @@ impl<Scalar: PrimeField> ConstraintSystem<Scalar> for TestConstraintSystem<Scala
|
|||
|
||||
#[test]
|
||||
fn test_cs() {
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::bls12_381::Fr;
|
||||
use bls12_381::Scalar;
|
||||
use ff::PrimeField;
|
||||
|
||||
let mut cs = TestConstraintSystem::new();
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(cs.num_constraints(), 0);
|
||||
let a = cs
|
||||
.namespace(|| "a")
|
||||
.alloc(|| "var", || Ok(Fr::from_str("10").unwrap()))
|
||||
.alloc(|| "var", || Ok(Scalar::from_str("10").unwrap()))
|
||||
.unwrap();
|
||||
let b = cs
|
||||
.namespace(|| "b")
|
||||
.alloc(|| "var", || Ok(Fr::from_str("4").unwrap()))
|
||||
.alloc(|| "var", || Ok(Scalar::from_str("4").unwrap()))
|
||||
.unwrap();
|
||||
let c = cs
|
||||
.alloc(|| "product", || Ok(Fr::from_str("40").unwrap()))
|
||||
.alloc(|| "product", || Ok(Scalar::from_str("40").unwrap()))
|
||||
.unwrap();
|
||||
|
||||
cs.enforce(|| "mult", |lc| lc + a, |lc| lc + b, |lc| lc + c);
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(cs.num_constraints(), 1);
|
||||
|
||||
cs.set("a/var", Fr::from_str("4").unwrap());
|
||||
cs.set("a/var", Scalar::from_str("4").unwrap());
|
||||
|
||||
let one = TestConstraintSystem::<Fr>::one();
|
||||
let one = TestConstraintSystem::<Scalar>::one();
|
||||
cs.enforce(|| "eq", |lc| lc + a, |lc| lc + one, |lc| lc + b);
|
||||
|
||||
assert!(!cs.is_satisfied());
|
||||
assert!(cs.which_is_unsatisfied() == Some("mult"));
|
||||
|
||||
assert!(cs.get("product") == Fr::from_str("40").unwrap());
|
||||
assert!(cs.get("product") == Scalar::from_str("40").unwrap());
|
||||
|
||||
cs.set("product", Fr::from_str("16").unwrap());
|
||||
cs.set("product", Scalar::from_str("16").unwrap());
|
||||
assert!(cs.is_satisfied());
|
||||
|
||||
{
|
||||
let mut cs = cs.namespace(|| "test1");
|
||||
let mut cs = cs.namespace(|| "test2");
|
||||
cs.alloc(|| "hehe", || Ok(Fr::one())).unwrap();
|
||||
cs.alloc(|| "hehe", || Ok(Scalar::one())).unwrap();
|
||||
}
|
||||
|
||||
assert!(cs.get("test1/test2/hehe") == Fr::one());
|
||||
assert!(cs.get("test1/test2/hehe") == Scalar::one());
|
||||
}
|
||||
|
|
|
@ -401,8 +401,8 @@ mod test {
|
|||
use crate::gadgets::multieq::MultiEq;
|
||||
use crate::gadgets::test::*;
|
||||
use crate::ConstraintSystem;
|
||||
use bls12_381::Scalar;
|
||||
use ff::Field;
|
||||
use pairing::bls12_381::Fr;
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
|
@ -484,7 +484,7 @@ mod test {
|
|||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let a = rng.next_u32();
|
||||
let b = rng.next_u32();
|
||||
|
@ -529,7 +529,7 @@ mod test {
|
|||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let a = rng.next_u32();
|
||||
let b = rng.next_u32();
|
||||
|
@ -572,7 +572,7 @@ mod test {
|
|||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let a = rng.next_u32();
|
||||
let b = rng.next_u32();
|
||||
|
@ -685,7 +685,7 @@ mod test {
|
|||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let a = rng.next_u32();
|
||||
let b = rng.next_u32();
|
||||
|
@ -729,7 +729,7 @@ mod test {
|
|||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut cs = TestConstraintSystem::<Scalar>::new();
|
||||
|
||||
let a = rng.next_u32();
|
||||
let b = rng.next_u32();
|
||||
|
|
|
@ -479,8 +479,8 @@ mod test_with_bls12_381 {
|
|||
use super::*;
|
||||
use crate::{Circuit, ConstraintSystem, SynthesisError};
|
||||
|
||||
use bls12_381::{Bls12, Scalar};
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use rand::thread_rng;
|
||||
use std::ops::MulAssign;
|
||||
|
||||
|
@ -537,8 +537,8 @@ mod test_with_bls12_381 {
|
|||
let pvk = prepare_verifying_key::<Bls12>(¶ms.vk);
|
||||
|
||||
for _ in 0..100 {
|
||||
let a = Fr::random(rng);
|
||||
let b = Fr::random(rng);
|
||||
let a = Scalar::random(rng);
|
||||
let b = Scalar::random(rng);
|
||||
let mut c = a;
|
||||
c.mul_assign(&b);
|
||||
|
||||
|
|
|
@ -311,17 +311,19 @@ fn test_with_bls12() {
|
|||
acc
|
||||
}
|
||||
|
||||
use bls12_381::{Bls12, Scalar};
|
||||
use group::{Curve, Group};
|
||||
use pairing::{
|
||||
bls12_381::{Bls12, Fr},
|
||||
Engine,
|
||||
};
|
||||
use pairing::Engine;
|
||||
use rand;
|
||||
|
||||
const SAMPLES: usize = 1 << 14;
|
||||
|
||||
let rng = &mut rand::thread_rng();
|
||||
let v = Arc::new((0..SAMPLES).map(|_| Fr::random(rng)).collect::<Vec<_>>());
|
||||
let v = Arc::new(
|
||||
(0..SAMPLES)
|
||||
.map(|_| Scalar::random(rng))
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
let g = Arc::new(
|
||||
(0..SAMPLES)
|
||||
.map(|_| <Bls12 as Engine>::G1::random(rng).to_affine())
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::time::{Duration, Instant};
|
|||
use ff::{Field, PrimeField};
|
||||
|
||||
// We're going to use the BLS12-381 pairing-friendly elliptic curve.
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use bls12_381::{Bls12, Scalar};
|
||||
|
||||
// We'll use these interfaces to construct our circuit.
|
||||
use bellman::{Circuit, ConstraintSystem, SynthesisError};
|
||||
|
@ -151,7 +151,7 @@ fn test_mimc() {
|
|||
|
||||
// Generate the MiMC round constants
|
||||
let constants = (0..MIMC_ROUNDS)
|
||||
.map(|_| Fr::random(rng))
|
||||
.map(|_| Scalar::random(rng))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
println!("Creating parameters...");
|
||||
|
@ -183,8 +183,8 @@ fn test_mimc() {
|
|||
|
||||
for _ in 0..SAMPLES {
|
||||
// Generate a random preimage and compute the image
|
||||
let xl = Fr::random(rng);
|
||||
let xr = Fr::random(rng);
|
||||
let xl = Scalar::random(rng);
|
||||
let xr = Scalar::random(rng);
|
||||
let image = mimc(xl, xr, &constants);
|
||||
|
||||
proof_vec.truncate(0);
|
||||
|
|
|
@ -32,9 +32,5 @@ unstable-features = ["expose-arith"]
|
|||
expose-arith = []
|
||||
default = []
|
||||
|
||||
[[bench]]
|
||||
name = "pairing_benches"
|
||||
harness = false
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
pub(crate) mod g1 {
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use ff::Field;
|
||||
use group::Group;
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
fn bench_g1_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
|
||||
0xbc, 0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(G1, Fr)> = (0..SAMPLES)
|
||||
.map(|_| (G1::random(&mut rng), Fr::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("G1::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp *= v[count].1;
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_g1_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
|
||||
0xbc, 0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(G1, G1)> = (0..SAMPLES)
|
||||
.map(|_| (G1::random(&mut rng), G1::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("G1::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_g1_add_assign_mixed(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
|
||||
0xbc, 0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(G1, G1Affine)> = (0..SAMPLES)
|
||||
.map(|_| (G1::random(&mut rng), G1::random(&mut rng).into()))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("G1::add_assign_mixed", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_g1_add_assign,
|
||||
bench_g1_add_assign_mixed,
|
||||
bench_g1_mul_assign,
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) mod g2 {
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use ff::Field;
|
||||
use group::Group;
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
fn bench_g2_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
|
||||
0xbc, 0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(G2, Fr)> = (0..SAMPLES)
|
||||
.map(|_| (G2::random(&mut rng), Fr::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("G2::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp *= v[count].1;
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_g2_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
|
||||
0xbc, 0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(G2, G2)> = (0..SAMPLES)
|
||||
.map(|_| (G2::random(&mut rng), G2::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("G2::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_g2_add_assign_mixed(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
|
||||
0xbc, 0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(G2, G2Affine)> = (0..SAMPLES)
|
||||
.map(|_| (G2::random(&mut rng), G2::random(&mut rng).into()))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("G2::add_assign_mixed", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_g2_add_assign,
|
||||
bench_g2_add_assign_mixed,
|
||||
bench_g2_mul_assign,
|
||||
);
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
fn bench_fq_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fq, Fq)> = (0..SAMPLES)
|
||||
.map(|_| (Fq::random(&mut rng), Fq::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq_sub_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fq, Fq)> = (0..SAMPLES)
|
||||
.map(|_| (Fq::random(&mut rng), Fq::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq::sub_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fq, Fq)> = (0..SAMPLES)
|
||||
.map(|_| (Fq::random(&mut rng), Fq::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq_square(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq> = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq::square", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq_invert(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq> = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq::invert", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].invert()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq_neg(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq> = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq::neg", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].neg();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq_sqrt(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq> = (0..SAMPLES)
|
||||
.map(|_| Fq::random(&mut rng).square())
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq::sqrt", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].sqrt()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq_to_repr(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq> = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq::to_repr", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].to_repr()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq_from_repr(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<FqRepr> = (0..SAMPLES)
|
||||
.map(|_| Fq::random(&mut rng).to_repr())
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq::from_repr", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
Fq::from_repr(v[count])
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_fq_add_assign,
|
||||
bench_fq_sub_assign,
|
||||
bench_fq_mul_assign,
|
||||
bench_fq_square,
|
||||
bench_fq_invert,
|
||||
bench_fq_neg,
|
||||
bench_fq_sqrt,
|
||||
bench_fq_to_repr,
|
||||
bench_fq_from_repr,
|
||||
);
|
|
@ -1,125 +0,0 @@
|
|||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
||||
|
||||
use ff::Field;
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
fn bench_fq12_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fq12, Fq12)> = (0..SAMPLES)
|
||||
.map(|_| (Fq12::random(&mut rng), Fq12::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq12::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq12_sub_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fq12, Fq12)> = (0..SAMPLES)
|
||||
.map(|_| (Fq12::random(&mut rng), Fq12::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq12::sub_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq12_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fq12, Fq12)> = (0..SAMPLES)
|
||||
.map(|_| (Fq12::random(&mut rng), Fq12::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq12::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq12_squaring(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq12> = (0..SAMPLES).map(|_| Fq12::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq12::square", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq12_invert(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq12> = (0..SAMPLES).map(|_| Fq12::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq12::invert", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].invert();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_fq12_add_assign,
|
||||
bench_fq12_sub_assign,
|
||||
bench_fq12_mul_assign,
|
||||
bench_fq12_squaring,
|
||||
bench_fq12_invert,
|
||||
);
|
|
@ -1,146 +0,0 @@
|
|||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
||||
|
||||
use ff::Field;
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
fn bench_fq2_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fq2, Fq2)> = (0..SAMPLES)
|
||||
.map(|_| (Fq2::random(&mut rng), Fq2::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq2::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq2_sub_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fq2, Fq2)> = (0..SAMPLES)
|
||||
.map(|_| (Fq2::random(&mut rng), Fq2::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq2::sub_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq2_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fq2, Fq2)> = (0..SAMPLES)
|
||||
.map(|_| (Fq2::random(&mut rng), Fq2::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq2::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq2_squaring(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq2> = (0..SAMPLES).map(|_| Fq2::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq2::square", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq2_invert(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq2> = (0..SAMPLES).map(|_| Fq2::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq2::invert", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].invert();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fq2_sqrt(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq2> = (0..SAMPLES).map(|_| Fq2::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fq2::sqrt", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].sqrt();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_fq2_add_assign,
|
||||
bench_fq2_sub_assign,
|
||||
bench_fq2_mul_assign,
|
||||
bench_fq2_squaring,
|
||||
bench_fq2_invert,
|
||||
bench_fq2_sqrt,
|
||||
);
|
|
@ -1,209 +0,0 @@
|
|||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
fn bench_fr_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fr, Fr)> = (0..SAMPLES)
|
||||
.map(|_| (Fr::random(&mut rng), Fr::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fr::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fr_sub_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fr, Fr)> = (0..SAMPLES)
|
||||
.map(|_| (Fr::random(&mut rng), Fr::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fr::sub_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fr_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(Fr, Fr)> = (0..SAMPLES)
|
||||
.map(|_| (Fr::random(&mut rng), Fr::random(&mut rng)))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fr::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fr_square(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fr> = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fr::square", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fr_invert(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fr> = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fr::invert", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].invert()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fr_neg(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fr> = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fr::neg", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].neg();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fr_sqrt(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fr> = (0..SAMPLES)
|
||||
.map(|_| Fr::random(&mut rng).square())
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fr::sqrt", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].sqrt()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fr_to_repr(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fr> = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fr::to_repr", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].to_repr()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_fr_from_repr(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<FrRepr> = (0..SAMPLES)
|
||||
.map(|_| Fr::random(&mut rng).to_repr())
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Fr::from_repr", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
Fr::from_repr(v[count])
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_fr_add_assign,
|
||||
bench_fr_sub_assign,
|
||||
bench_fr_mul_assign,
|
||||
bench_fr_square,
|
||||
bench_fr_invert,
|
||||
bench_fr_neg,
|
||||
bench_fr_sqrt,
|
||||
bench_fr_to_repr,
|
||||
bench_fr_from_repr,
|
||||
);
|
|
@ -1,118 +0,0 @@
|
|||
pub(crate) mod ec;
|
||||
pub(crate) mod fq;
|
||||
pub(crate) mod fq12;
|
||||
pub(crate) mod fq2;
|
||||
pub(crate) mod fr;
|
||||
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
use group::Group;
|
||||
use pairing::bls12_381::*;
|
||||
use pairing::{Engine, MillerLoopResult, MultiMillerLoop};
|
||||
|
||||
fn bench_pairing_g2_preparation(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<G2> = (0..SAMPLES).map(|_| G2::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("G2 preparation", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = G2Prepared::from(G2Affine::from(v[count]));
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_pairing_miller_loop(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(G1Affine, G2Prepared)> = (0..SAMPLES)
|
||||
.map(|_| {
|
||||
(
|
||||
G1Affine::from(G1::random(&mut rng)),
|
||||
G2Affine::from(G2::random(&mut rng)).into(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Miller loop", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = Bls12::multi_miller_loop(&[(&v[count].0, &v[count].1)]);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_pairing_final_exponentiation(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<Fq12> = (0..SAMPLES)
|
||||
.map(|_| {
|
||||
(
|
||||
G1Affine::from(G1::random(&mut rng)),
|
||||
G2Affine::from(G2::random(&mut rng)).into(),
|
||||
)
|
||||
})
|
||||
.map(|(ref p, ref q)| Bls12::multi_miller_loop(&[(p, q)]))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Final exponentiation", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].final_exponentiation();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_pairing_full(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let v: Vec<(G1Affine, G2Affine)> = (0..SAMPLES)
|
||||
.map(|_| (G1::random(&mut rng).into(), G2::random(&mut rng).into()))
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
c.bench_function("Full pairing", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = Bls12::pairing(&v[count].0, &v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_pairing_g2_preparation,
|
||||
bench_pairing_miller_loop,
|
||||
bench_pairing_final_exponentiation,
|
||||
bench_pairing_full,
|
||||
);
|
|
@ -1,12 +0,0 @@
|
|||
use criterion::criterion_main;
|
||||
mod bls12_381;
|
||||
|
||||
criterion_main!(
|
||||
bls12_381::benches,
|
||||
bls12_381::ec::g1::benches,
|
||||
bls12_381::ec::g2::benches,
|
||||
bls12_381::fq::benches,
|
||||
bls12_381::fq12::benches,
|
||||
bls12_381::fq2::benches,
|
||||
bls12_381::fr::benches,
|
||||
);
|
|
@ -1,71 +0,0 @@
|
|||
# BLS12-381
|
||||
|
||||
This is an implementation of the BLS12-381 pairing-friendly elliptic curve construction.
|
||||
|
||||
## BLS12 Parameterization
|
||||
|
||||
BLS12 curves are parameterized by a value *x* such that the base field modulus *q* and subgroup *r* can be computed by:
|
||||
|
||||
* q = (x - 1)<sup>2</sup> ((x<sup>4</sup> - x<sup>2</sup> + 1) / 3) + x
|
||||
* r = (x<sup>4</sup> - x<sup>2</sup> + 1)
|
||||
|
||||
Given primes *q* and *r* parameterized as above, we can easily construct an elliptic curve over the prime field F<sub>*q*</sub> which contains a subgroup of order *r* such that *r* | (*q*<sup>12</sup> - 1), giving it an embedding degree of 12. Instantiating its sextic twist over an extension field F<sub>q<sup>2</sup></sub> gives rise to an efficient bilinear pairing function between elements of the order *r* subgroups of either curves, into an order *r* multiplicative subgroup of F<sub>q<sup>12</sup></sub>.
|
||||
|
||||
In zk-SNARK schemes, we require F<sub>r</sub> with large 2<sup>n</sup> roots of unity for performing efficient fast-fourier transforms. As such, guaranteeing that large 2<sup>n</sup> | (r - 1), or equivalently that *x* has a large 2<sup>n</sup> factor, gives rise to BLS12 curves suitable for zk-SNARKs.
|
||||
|
||||
Due to recent research, it is estimated by many that *q* should be approximately 384 bits to target 128-bit security. Conveniently, *r* is approximately 256 bits when *q* is approximately 384 bits, making BLS12 curves ideal for 128-bit security. It also makes them ideal for many zk-SNARK applications, as the scalar field can be used for keying material such as embedded curve constructions.
|
||||
|
||||
Many curves match our descriptions, but we require some extra properties for efficiency purposes:
|
||||
|
||||
* *q* should be smaller than 2<sup>383</sup>, and *r* should be smaller than 2<sup>255</sup>, so that the most significant bit is unset when using 64-bit or 32-bit limbs. This allows for cheap reductions.
|
||||
* F<sub>q<sup>12</sup></sub> is typically constructed using towers of extension fields. As a byproduct of [research](https://eprint.iacr.org/2011/465.pdf) for BLS curves of embedding degree 24, we can identify subfamilies of BLS12 curves (for our purposes, where x mod 72 = {16, 64}) that produce efficient extension field towers and twisting isomorphisms.
|
||||
* We desire *x* of small Hamming weight, to increase the performance of the pairing function.
|
||||
|
||||
## BLS12-381 Instantiation
|
||||
|
||||
The BLS12-381 construction is instantiated by `x = -0xd201000000010000`, which produces the largest `q` and smallest Hamming weight of `x` that meets the above requirements. This produces:
|
||||
|
||||
* q = `0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab` (381 bits)
|
||||
* r = `0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001` (255 bits)
|
||||
|
||||
Our extension field tower is constructed as follows:
|
||||
|
||||
1. F<sub>q<sup>2</sup></sub> is constructed as F<sub>q</sub>(u) / (u<sup>2</sup> - β) where β = -1.
|
||||
2. F<sub>q<sup>6</sup></sub> is constructed as F<sub>q<sup>2</sup></sub>(v) / (v<sup>3</sup> - ξ) where ξ = u + 1
|
||||
3. F<sub>q<sup>12</sup></sub> is constructed as F<sub>q<sup>6</sup></sub>(w) / (w<sup>2</sup> - γ) where γ = v
|
||||
|
||||
Now, we instantiate the elliptic curve E(F<sub>q</sub>) : y<sup>2</sup> = x<sup>3</sup> + 4, and the elliptic curve E'(F<sub>q<sup>2</sup></sub>) : y<sup>2</sup> = x<sup>3</sup> + 4(u + 1).
|
||||
|
||||
The group G<sub>1</sub> is the *r* order subgroup of E, which has cofactor (x - 1)<sup>2</sup> / 3. The group G<sub>2</sub> is the *r* order subgroup of E', which has cofactor (x<sup>8</sup> - 4x<sup>7</sup> + 5x<sup>6</sup> - 4x<sup>4</sup> + 6x<sup>3</sup> - 4x<sup>2</sup> - 4x + 13) / 9.
|
||||
|
||||
### Generators
|
||||
|
||||
The generators of G<sub>1</sub> and G<sub>2</sub> are computed by finding the lexicographically smallest valid `x`-coordinate, and its lexicographically smallest `y`-coordinate and scaling it by the cofactor such that the result is not the point at infinity.
|
||||
|
||||
#### G1
|
||||
|
||||
```
|
||||
x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
|
||||
y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
|
||||
```
|
||||
|
||||
#### G2
|
||||
|
||||
```
|
||||
x = 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758*u + 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160
|
||||
y = 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582*u + 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905
|
||||
```
|
||||
|
||||
### Serialization
|
||||
|
||||
* Fq elements are encoded in big-endian form. They occupy 48 bytes in this form.
|
||||
* Fq2 elements are encoded in big-endian form, meaning that the Fq element c0 + c1 * u is represented by the Fq element c1 followed by the Fq element c0. This means Fq2 elements occupy 96 bytes in this form.
|
||||
* The group G1 uses Fq elements for coordinates. The group G2 uses Fq2 elements for coordinates.
|
||||
* G1 and G2 elements can be encoded in uncompressed form (the x-coordinate followed by the y-coordinate) or in compressed form (just the x-coordinate). G1 elements occupy 96 bytes in uncompressed form, and 48 bytes in compressed form. G2 elements occupy 192 bytes in uncompressed form, and 96 bytes in compressed form.
|
||||
|
||||
The most-significant three bits of a G1 or G2 encoding should be masked away before the coordinate(s) are interpreted. These bits are used to unambiguously represent the underlying element:
|
||||
|
||||
* The most significant bit, when set, indicates that the point is in compressed form. Otherwise, the point is in uncompressed form.
|
||||
* The second-most significant bit indicates that the point is at infinity. If this bit is set, the remaining bits of the group element's encoding should be set to zero.
|
||||
* The third-most significant bit is set if (and only if) this point is in compressed form _and_ it is not the point at infinity _and_ its y-coordinate is the lexicographically largest of the two associated with the encoded x-coordinate.
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,286 +0,0 @@
|
|||
use super::fq::FROBENIUS_COEFF_FQ12_C1;
|
||||
use super::fq2::Fq2;
|
||||
use super::fq6::Fq6;
|
||||
use ff::Field;
|
||||
use rand_core::RngCore;
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use subtle::{Choice, ConditionallySelectable, CtOption};
|
||||
|
||||
/// An element of Fq12, represented by c0 + c1 * w.
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Fq12 {
|
||||
pub c0: Fq6,
|
||||
pub c1: Fq6,
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for Fq12 {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
write!(f, "Fq12({} + {} * w)", self.c0, self.c1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Fq12 {
|
||||
pub fn conjugate(&mut self) {
|
||||
self.c1 = self.c1.neg();
|
||||
}
|
||||
|
||||
pub fn mul_by_014(&mut self, c0: &Fq2, c1: &Fq2, c4: &Fq2) {
|
||||
let mut aa = self.c0;
|
||||
aa.mul_by_01(c0, c1);
|
||||
let mut bb = self.c1;
|
||||
bb.mul_by_1(c4);
|
||||
let mut o = *c1;
|
||||
o.add_assign(c4);
|
||||
self.c1.add_assign(&self.c0);
|
||||
self.c1.mul_by_01(c0, &o);
|
||||
self.c1.sub_assign(&aa);
|
||||
self.c1.sub_assign(&bb);
|
||||
self.c0 = bb;
|
||||
self.c0.mul_by_nonresidue();
|
||||
self.c0.add_assign(&aa);
|
||||
}
|
||||
|
||||
pub fn frobenius_map(&mut self, power: usize) {
|
||||
self.c0.frobenius_map(power);
|
||||
self.c1.frobenius_map(power);
|
||||
|
||||
self.c1.c0.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
|
||||
self.c1.c1.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
|
||||
self.c1.c2.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
|
||||
}
|
||||
}
|
||||
|
||||
impl ConditionallySelectable for Fq12 {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
Fq12 {
|
||||
c0: Fq6::conditional_select(&a.c0, &b.c0, choice),
|
||||
c1: Fq6::conditional_select(&a.c1, &b.c1, choice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
Fq12 {
|
||||
c0: self.c0.neg(),
|
||||
c1: self.c1.neg(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Add<&'r Fq12> for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: &Self) -> Self {
|
||||
Fq12 {
|
||||
c0: self.c0 + other.c0,
|
||||
c1: self.c1 + other.c1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
self.add(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> AddAssign<&'r Fq12> for Fq12 {
|
||||
fn add_assign(&mut self, other: &'r Self) {
|
||||
self.c0.add_assign(&other.c0);
|
||||
self.c1.add_assign(&other.c1);
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Fq12 {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.add_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Sub<&'r Fq12> for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: &Self) -> Self {
|
||||
Fq12 {
|
||||
c0: self.c0 - other.c0,
|
||||
c1: self.c1 - other.c1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self.sub(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> SubAssign<&'r Fq12> for Fq12 {
|
||||
fn sub_assign(&mut self, other: &'r Self) {
|
||||
self.c0.sub_assign(&other.c0);
|
||||
self.c1.sub_assign(&other.c1);
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Fq12 {
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.sub_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Mul<&'r Fq12> for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.mul_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self.mul(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> MulAssign<&'r Fq12> for Fq12 {
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
let mut aa = self.c0;
|
||||
aa.mul_assign(&other.c0);
|
||||
let mut bb = self.c1;
|
||||
bb.mul_assign(&other.c1);
|
||||
let mut o = other.c0;
|
||||
o.add_assign(&other.c1);
|
||||
self.c1.add_assign(&self.c0);
|
||||
self.c1.mul_assign(&o);
|
||||
self.c1.sub_assign(&aa);
|
||||
self.c1.sub_assign(&bb);
|
||||
self.c0 = bb;
|
||||
self.c0.mul_by_nonresidue();
|
||||
self.c0.add_assign(&aa);
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for Fq12 {
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
self.mul_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for Fq12 {
|
||||
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
|
||||
Fq12 {
|
||||
c0: Fq6::random(rng),
|
||||
c1: Fq6::random(rng),
|
||||
}
|
||||
}
|
||||
|
||||
fn zero() -> Self {
|
||||
Fq12 {
|
||||
c0: Fq6::zero(),
|
||||
c1: Fq6::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn one() -> Self {
|
||||
Fq12 {
|
||||
c0: Fq6::one(),
|
||||
c1: Fq6::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
self.c0.is_zero() && self.c1.is_zero()
|
||||
}
|
||||
|
||||
fn double(&self) -> Self {
|
||||
Fq12 {
|
||||
c0: self.c0.double(),
|
||||
c1: self.c1.double(),
|
||||
}
|
||||
}
|
||||
|
||||
fn square(&self) -> Self {
|
||||
let mut ab = self.c0;
|
||||
ab.mul_assign(&self.c1);
|
||||
let mut c0c1 = self.c0;
|
||||
c0c1.add_assign(&self.c1);
|
||||
let mut c0 = self.c1;
|
||||
c0.mul_by_nonresidue();
|
||||
c0.add_assign(&self.c0);
|
||||
c0.mul_assign(&c0c1);
|
||||
c0.sub_assign(&ab);
|
||||
let mut c1 = ab;
|
||||
c1.add_assign(&ab);
|
||||
ab.mul_by_nonresidue();
|
||||
c0.sub_assign(&ab);
|
||||
Fq12 { c0, c1 }
|
||||
}
|
||||
|
||||
fn invert(&self) -> CtOption<Self> {
|
||||
let mut c0s = self.c0.square();
|
||||
let mut c1s = self.c1.square();
|
||||
c1s.mul_by_nonresidue();
|
||||
c0s.sub_assign(&c1s);
|
||||
|
||||
c0s.invert().map(|t| Fq12 {
|
||||
c0: t.mul(&self.c0),
|
||||
c1: t.mul(&self.c1).neg(),
|
||||
})
|
||||
}
|
||||
|
||||
fn sqrt(&self) -> CtOption<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use rand_core::SeedableRng;
|
||||
#[cfg(test)]
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
#[test]
|
||||
fn test_fq12_mul_by_014() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let c0 = Fq2::random(&mut rng);
|
||||
let c1 = Fq2::random(&mut rng);
|
||||
let c5 = Fq2::random(&mut rng);
|
||||
let mut a = Fq12::random(&mut rng);
|
||||
let mut b = a;
|
||||
|
||||
a.mul_by_014(&c0, &c1, &c5);
|
||||
b.mul_assign(&Fq12 {
|
||||
c0: Fq6 {
|
||||
c0,
|
||||
c1,
|
||||
c2: Fq2::zero(),
|
||||
},
|
||||
c1: Fq6 {
|
||||
c0: Fq2::zero(),
|
||||
c1: c5,
|
||||
c2: Fq2::zero(),
|
||||
},
|
||||
});
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fq12_field_tests() {
|
||||
crate::tests::field::random_field_tests::<Fq12>();
|
||||
}
|
|
@ -1,925 +0,0 @@
|
|||
use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE};
|
||||
use ff::Field;
|
||||
use rand_core::RngCore;
|
||||
use std::cmp::Ordering;
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use subtle::{Choice, ConditionallySelectable, CtOption};
|
||||
|
||||
/// An element of Fq2, represented by c0 + c1 * u.
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Fq2 {
|
||||
pub c0: Fq,
|
||||
pub c1: Fq,
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for Fq2 {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
write!(f, "Fq2({} + {} * u)", self.c0, self.c1)
|
||||
}
|
||||
}
|
||||
|
||||
/// `Fq2` elements are ordered lexicographically.
|
||||
impl Ord for Fq2 {
|
||||
#[inline(always)]
|
||||
fn cmp(&self, other: &Fq2) -> Ordering {
|
||||
match self.c1.cmp(&other.c1) {
|
||||
Ordering::Greater => Ordering::Greater,
|
||||
Ordering::Less => Ordering::Less,
|
||||
Ordering::Equal => self.c0.cmp(&other.c0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Fq2 {
|
||||
#[inline(always)]
|
||||
fn partial_cmp(&self, other: &Fq2) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Fq2 {
|
||||
/// Multiply this element by the cubic and quadratic nonresidue 1 + u.
|
||||
pub fn mul_by_nonresidue(&mut self) {
|
||||
let t0 = self.c0;
|
||||
self.c0.sub_assign(&self.c1);
|
||||
self.c1.add_assign(&t0);
|
||||
}
|
||||
|
||||
/// Norm of Fq2 as extension field in i over Fq
|
||||
pub fn norm(&self) -> Fq {
|
||||
let t0 = self.c0.square();
|
||||
let mut t1 = self.c1.square();
|
||||
t1.add_assign(&t0);
|
||||
|
||||
t1
|
||||
}
|
||||
|
||||
pub fn frobenius_map(&mut self, power: usize) {
|
||||
self.c1.mul_assign(&FROBENIUS_COEFF_FQ2_C1[power % 2]);
|
||||
}
|
||||
}
|
||||
|
||||
impl ConditionallySelectable for Fq2 {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
Fq2 {
|
||||
c0: Fq::conditional_select(&a.c0, &b.c0, choice),
|
||||
c1: Fq::conditional_select(&a.c1, &b.c1, choice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
Fq2 {
|
||||
c0: self.c0.neg(),
|
||||
c1: self.c1.neg(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Add<&'r Fq2> for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: &Self) -> Self {
|
||||
Fq2 {
|
||||
c0: self.c0 + other.c0,
|
||||
c1: self.c1 + other.c1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
self.add(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> AddAssign<&'r Fq2> for Fq2 {
|
||||
fn add_assign(&mut self, other: &'r Self) {
|
||||
self.c0.add_assign(&other.c0);
|
||||
self.c1.add_assign(&other.c1);
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Fq2 {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.add_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Sub<&'r Fq2> for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: &Self) -> Self {
|
||||
Fq2 {
|
||||
c0: self.c0 - other.c0,
|
||||
c1: self.c1 - other.c1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self.sub(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> SubAssign<&'r Fq2> for Fq2 {
|
||||
fn sub_assign(&mut self, other: &'r Self) {
|
||||
self.c0.sub_assign(&other.c0);
|
||||
self.c1.sub_assign(&other.c1);
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Fq2 {
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.sub_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Mul<&'r Fq2> for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.mul_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self.mul(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> MulAssign<&'r Fq2> for Fq2 {
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
let mut aa = self.c0;
|
||||
aa.mul_assign(&other.c0);
|
||||
let mut bb = self.c1;
|
||||
bb.mul_assign(&other.c1);
|
||||
let mut o = other.c0;
|
||||
o.add_assign(&other.c1);
|
||||
self.c1.add_assign(&self.c0);
|
||||
self.c1.mul_assign(&o);
|
||||
self.c1.sub_assign(&aa);
|
||||
self.c1.sub_assign(&bb);
|
||||
self.c0 = aa;
|
||||
self.c0.sub_assign(&bb);
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for Fq2 {
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
self.mul_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for Fq2 {
|
||||
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
|
||||
Fq2 {
|
||||
c0: Fq::random(rng),
|
||||
c1: Fq::random(rng),
|
||||
}
|
||||
}
|
||||
|
||||
fn zero() -> Self {
|
||||
Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn one() -> Self {
|
||||
Fq2 {
|
||||
c0: Fq::one(),
|
||||
c1: Fq::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
self.c0.is_zero() && self.c1.is_zero()
|
||||
}
|
||||
|
||||
fn square(&self) -> Self {
|
||||
let mut ab = self.c0;
|
||||
ab.mul_assign(&self.c1);
|
||||
let mut c0c1 = self.c0;
|
||||
c0c1.add_assign(&self.c1);
|
||||
let mut c0 = self.c1.neg();
|
||||
c0.add_assign(&self.c0);
|
||||
c0.mul_assign(&c0c1);
|
||||
c0.sub_assign(&ab);
|
||||
let mut c1 = ab;
|
||||
c1.add_assign(&ab);
|
||||
c0.add_assign(&ab);
|
||||
Fq2 { c0, c1 }
|
||||
}
|
||||
|
||||
fn double(&self) -> Self {
|
||||
Fq2 {
|
||||
c0: self.c0.double(),
|
||||
c1: self.c1.double(),
|
||||
}
|
||||
}
|
||||
|
||||
fn invert(&self) -> CtOption<Self> {
|
||||
let t1 = self.c1.square();
|
||||
let mut t0 = self.c0.square();
|
||||
t0.add_assign(&t1);
|
||||
t0.invert().map(|t| Fq2 {
|
||||
c0: self.c0.mul(&t),
|
||||
c1: self.c1.mul(&t).neg(),
|
||||
})
|
||||
}
|
||||
|
||||
/// WARNING: THIS IS NOT ACTUALLY CONSTANT TIME YET!
|
||||
/// THIS WILL BE REPLACED BY THE bls12_381 CRATE, WHICH IS CONSTANT TIME!
|
||||
fn sqrt(&self) -> CtOption<Self> {
|
||||
// Algorithm 9, https://eprint.iacr.org/2012/685.pdf
|
||||
|
||||
if self.is_zero() {
|
||||
CtOption::new(Self::zero(), Choice::from(1))
|
||||
} else {
|
||||
// a1 = self^((q - 3) / 4)
|
||||
let mut a1 = self.pow_vartime([
|
||||
0xee7fbfffffffeaaau64,
|
||||
0x7aaffffac54ffff,
|
||||
0xd9cc34a83dac3d89,
|
||||
0xd91dd2e13ce144af,
|
||||
0x92c6e9ed90d2eb35,
|
||||
0x680447a8e5ff9a6,
|
||||
]);
|
||||
let mut alpha = a1.square();
|
||||
alpha.mul_assign(self);
|
||||
let mut a0 = alpha;
|
||||
a0.frobenius_map(1);
|
||||
a0.mul_assign(&alpha);
|
||||
|
||||
let neg1 = Fq2 {
|
||||
c0: NEGATIVE_ONE,
|
||||
c1: Fq::zero(),
|
||||
};
|
||||
|
||||
if a0 == neg1 {
|
||||
CtOption::new(Self::zero(), Choice::from(0))
|
||||
} else {
|
||||
a1.mul_assign(self);
|
||||
|
||||
if alpha == neg1 {
|
||||
a1.mul_assign(&Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::one(),
|
||||
});
|
||||
} else {
|
||||
alpha.add_assign(&Fq2::one());
|
||||
// alpha = alpha^((q - 1) / 2)
|
||||
alpha = alpha.pow_vartime([
|
||||
0xdcff7fffffffd555u64,
|
||||
0xf55ffff58a9ffff,
|
||||
0xb39869507b587b12,
|
||||
0xb23ba5c279c2895f,
|
||||
0x258dd3db21a5d66b,
|
||||
0xd0088f51cbff34d,
|
||||
]);
|
||||
a1.mul_assign(&alpha);
|
||||
}
|
||||
|
||||
CtOption::new(a1, Choice::from(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use super::fq::FqRepr;
|
||||
#[cfg(test)]
|
||||
use ff::PrimeField;
|
||||
|
||||
#[test]
|
||||
fn test_fq2_ordering() {
|
||||
let mut a = Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::zero(),
|
||||
};
|
||||
|
||||
let mut b = a;
|
||||
|
||||
assert!(a.cmp(&b) == Ordering::Equal);
|
||||
b.c0.add_assign(&Fq::one());
|
||||
assert!(a.cmp(&b) == Ordering::Less);
|
||||
a.c0.add_assign(&Fq::one());
|
||||
assert!(a.cmp(&b) == Ordering::Equal);
|
||||
b.c1.add_assign(&Fq::one());
|
||||
assert!(a.cmp(&b) == Ordering::Less);
|
||||
a.c0.add_assign(&Fq::one());
|
||||
assert!(a.cmp(&b) == Ordering::Less);
|
||||
a.c1.add_assign(&Fq::one());
|
||||
assert!(a.cmp(&b) == Ordering::Greater);
|
||||
b.c0.add_assign(&Fq::one());
|
||||
assert!(a.cmp(&b) == Ordering::Equal);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_basics() {
|
||||
assert_eq!(
|
||||
Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::zero(),
|
||||
},
|
||||
Fq2::zero()
|
||||
);
|
||||
assert_eq!(
|
||||
Fq2 {
|
||||
c0: Fq::one(),
|
||||
c1: Fq::zero(),
|
||||
},
|
||||
Fq2::one()
|
||||
);
|
||||
assert!(Fq2::zero().is_zero());
|
||||
assert!(!Fq2::one().is_zero());
|
||||
assert!(!Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::one(),
|
||||
}
|
||||
.is_zero());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_squaring() {
|
||||
let a = Fq2 {
|
||||
c0: Fq::one(),
|
||||
c1: Fq::one(),
|
||||
}; // u + 1
|
||||
assert_eq!(
|
||||
a.square(),
|
||||
Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::from(2),
|
||||
}
|
||||
); // 2u
|
||||
|
||||
let a = Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::one(),
|
||||
}; // u
|
||||
assert_eq!(a.square(), {
|
||||
Fq2 {
|
||||
c0: Fq::one().neg(),
|
||||
c1: Fq::zero(),
|
||||
}
|
||||
}); // -1
|
||||
|
||||
let a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x07, 0x08, 0x0c, 0x5f, 0xa1, 0xd8, 0xe0, 0x42, 0x41, 0xb7, 0x6d, 0xcc, 0x1c, 0x3f,
|
||||
0xbe, 0x5e, 0xf7, 0xf2, 0x95, 0xa9, 0x4e, 0x58, 0xae, 0x7c, 0x90, 0xe3, 0x4a, 0xab,
|
||||
0x6f, 0xb6, 0xa6, 0xbd, 0x4e, 0xef, 0x5c, 0x94, 0x65, 0x36, 0xf6, 0x02, 0x9c, 0x2c,
|
||||
0x63, 0x09, 0xbb, 0xf8, 0xb5, 0x98,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x10, 0xd1, 0x61, 0x5e, 0x75, 0x25, 0x0a, 0x21, 0xfc, 0x58, 0xa7, 0xb7, 0xbe, 0x81,
|
||||
0x54, 0x07, 0xbf, 0xb9, 0x90, 0x20, 0x60, 0x41, 0x37, 0xa0, 0xda, 0xc5, 0xa4, 0xc9,
|
||||
0x11, 0xa4, 0x35, 0x3e, 0x6a, 0xd3, 0x29, 0x11, 0x77, 0xc8, 0xc7, 0xe5, 0x38, 0xf4,
|
||||
0x73, 0xb3, 0xc8, 0x70, 0xa4, 0xab,
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
assert_eq!(
|
||||
a.square(),
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x07, 0xea, 0xc8, 0x13, 0x69, 0xc4, 0x33, 0x61, 0x4c, 0xf1, 0x7b, 0x58, 0x93, 0xc3,
|
||||
0xd3, 0x27, 0xcb, 0x67, 0x41, 0x57, 0x61, 0x8d, 0xa1, 0x76, 0x0d, 0xc4, 0x6a, 0xb8,
|
||||
0xfa, 0xd6, 0x7a, 0xe0, 0xb9, 0xf2, 0xa6, 0x6e, 0xae, 0x10, 0x73, 0xba, 0xf2, 0x62,
|
||||
0xc2, 0x8c, 0x53, 0x8b, 0xcf, 0x68,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x15, 0x42, 0xa6, 0x1c, 0x8a, 0x8d, 0xb9, 0x94, 0x73, 0x9c, 0x98, 0x30, 0x42, 0x77,
|
||||
0x9a, 0x65, 0x38, 0xd0, 0xd7, 0x27, 0x5a, 0x96, 0x89, 0xe1, 0xe7, 0x51, 0x38, 0xbc,
|
||||
0xe4, 0xce, 0xc7, 0xaa, 0xa2, 0x3e, 0xb7, 0xe1, 0x2d, 0xd5, 0x4d, 0x98, 0xc1, 0x57,
|
||||
0x9c, 0xf5, 0x8e, 0x98, 0x0c, 0xf8,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_mul() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
let mut a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x05, 0x1d, 0x3f, 0x92, 0x53, 0xe2, 0x51, 0x6f, 0x1c, 0x20, 0x2d, 0x8e, 0xd9, 0x7a,
|
||||
0xfb, 0x45, 0x9e, 0xe5, 0x3e, 0x7e, 0x84, 0xd7, 0x53, 0x2e, 0x41, 0xe4, 0x61, 0x15,
|
||||
0x4a, 0x73, 0x54, 0xa3, 0xa2, 0xe3, 0x3c, 0x33, 0x34, 0x49, 0xa1, 0xd6, 0x85, 0xc9,
|
||||
0xf9, 0x89, 0xe1, 0x46, 0x1f, 0x03,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x18, 0x0c, 0x3e, 0xe4, 0x66, 0x56, 0xb0, 0x08, 0x7a, 0x5e, 0x1e, 0xcb, 0x67, 0x6d,
|
||||
0x65, 0xf9, 0x09, 0x53, 0x3e, 0x4a, 0x9a, 0x51, 0x58, 0xbe, 0x4c, 0xc4, 0x80, 0x81,
|
||||
0xc0, 0x9b, 0x89, 0x03, 0x14, 0x3c, 0x21, 0x5d, 0x81, 0x76, 0xb3, 0x19, 0xa7, 0x34,
|
||||
0x8a, 0x8b, 0x51, 0x1a, 0xed, 0xcf,
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
a.mul_assign(&Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x02, 0xc9, 0x3a, 0x72, 0xeb, 0x8a, 0xf8, 0x3e, 0x06, 0xc9, 0x11, 0x02, 0x92, 0xbf,
|
||||
0xa4, 0x09, 0xcd, 0x46, 0x0f, 0x9f, 0x0c, 0x23, 0xe4, 0x30, 0x27, 0xec, 0xe1, 0x75,
|
||||
0xbe, 0x07, 0xa5, 0x31, 0xfc, 0x87, 0xe6, 0x2e, 0x17, 0x9c, 0x28, 0x5d, 0xe2, 0x1f,
|
||||
0x91, 0x69, 0x80, 0x5f, 0x53, 0x7e,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x19, 0xe1, 0x73, 0x34, 0xd4, 0xe9, 0x35, 0x58, 0x63, 0x4c, 0xd3, 0xc6, 0xc5, 0x65,
|
||||
0x09, 0x6d, 0x57, 0xa0, 0x6d, 0x31, 0x35, 0xa7, 0x52, 0xae, 0x88, 0x71, 0xc5, 0x08,
|
||||
0x65, 0x8d, 0x1e, 0x5f, 0x1d, 0x2a, 0x72, 0x91, 0x6d, 0xba, 0x4c, 0x8a, 0x4b, 0x1c,
|
||||
0x3f, 0x93, 0x6d, 0x89, 0x92, 0xd4,
|
||||
]))
|
||||
.unwrap(),
|
||||
});
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x17, 0x51, 0xaf, 0xbe, 0x16, 0x6e, 0x53, 0x99, 0x53, 0x10, 0xa2, 0x02, 0xd9, 0x2f,
|
||||
0x99, 0x63, 0x55, 0x11, 0xfe, 0x4d, 0x84, 0xee, 0x5f, 0x78, 0xf6, 0x1a, 0x96, 0xda,
|
||||
0xcf, 0x5a, 0x39, 0xbc, 0xde, 0x29, 0xc3, 0x1a, 0x19, 0xa6, 0x93, 0x7e, 0x95, 0xb5,
|
||||
0x12, 0x7e, 0x63, 0x60, 0xc7, 0xe4,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x01, 0xef, 0x1a, 0x36, 0xc2, 0x01, 0x58, 0x9d, 0x33, 0xa9, 0xac, 0x82, 0xce, 0x4c,
|
||||
0x50, 0x83, 0xc9, 0x75, 0x10, 0x65, 0x79, 0xc2, 0x75, 0xee, 0x5b, 0xa6, 0xe5, 0x43,
|
||||
0x0e, 0x88, 0x3d, 0x40, 0x06, 0xc6, 0x3c, 0xd4, 0xda, 0x2c, 0x2a, 0xa7, 0x84, 0xaf,
|
||||
0x0e, 0x1b, 0xd6, 0x30, 0x11, 0x7a,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_invert() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
assert!(bool::from(Fq2::zero().invert().is_none()));
|
||||
|
||||
let a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x05, 0x1d, 0x3f, 0x92, 0x53, 0xe2, 0x51, 0x6f, 0x1c, 0x20, 0x2d, 0x8e, 0xd9, 0x7a,
|
||||
0xfb, 0x45, 0x9e, 0xe5, 0x3e, 0x7e, 0x84, 0xd7, 0x53, 0x2e, 0x41, 0xe4, 0x61, 0x15,
|
||||
0x4a, 0x73, 0x54, 0xa3, 0xa2, 0xe3, 0x3c, 0x33, 0x34, 0x49, 0xa1, 0xd6, 0x85, 0xc9,
|
||||
0xf9, 0x89, 0xe1, 0x46, 0x1f, 0x03,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x18, 0x0c, 0x3e, 0xe4, 0x66, 0x56, 0xb0, 0x08, 0x7a, 0x5e, 0x1e, 0xcb, 0x67, 0x6d,
|
||||
0x65, 0xf9, 0x09, 0x53, 0x3e, 0x4a, 0x9a, 0x51, 0x58, 0xbe, 0x4c, 0xc4, 0x80, 0x81,
|
||||
0xc0, 0x9b, 0x89, 0x03, 0x14, 0x3c, 0x21, 0x5d, 0x81, 0x76, 0xb3, 0x19, 0xa7, 0x34,
|
||||
0x8a, 0x8b, 0x51, 0x1a, 0xed, 0xcf,
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
let a = a.invert().unwrap();
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x13, 0x51, 0xef, 0x01, 0x94, 0x1b, 0x70, 0xc4, 0xa6, 0xc3, 0xd8, 0xf9, 0x58, 0x6f,
|
||||
0x26, 0x36, 0xdf, 0xba, 0x70, 0x32, 0x93, 0x94, 0x1c, 0x30, 0x64, 0xbe, 0xf6, 0x17,
|
||||
0xd2, 0x91, 0x5a, 0x8f, 0xe5, 0xec, 0xda, 0x5f, 0xda, 0xfd, 0xdb, 0xb2, 0x07, 0x03,
|
||||
0x00, 0xf9, 0xbc, 0xb9, 0xe5, 0x94,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x10, 0x3b, 0xdf, 0x24, 0x1a, 0xfb, 0x00, 0x19, 0xdf, 0x4e, 0x54, 0xf0, 0xd3, 0xef,
|
||||
0x15, 0xa6, 0xcb, 0xf6, 0x51, 0xa0, 0xf3, 0x67, 0xaf, 0xb2, 0x94, 0x71, 0x43, 0xf8,
|
||||
0x9f, 0xae, 0xde, 0xe9, 0x15, 0xd7, 0xb6, 0xb9, 0x5d, 0xef, 0xbf, 0xf0, 0x8c, 0x39,
|
||||
0xfd, 0x76, 0xa8, 0x31, 0x2c, 0xb4,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_addition() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
let mut a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
|
||||
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
|
||||
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
|
||||
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
|
||||
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
|
||||
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
|
||||
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
a.add_assign(&Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x13, 0xce, 0x43, 0x3f, 0xa2, 0x60, 0x27, 0xf5, 0x98, 0x6a, 0x4a, 0x62, 0xfa, 0x82,
|
||||
0xa4, 0x9d, 0x3b, 0x88, 0x89, 0x9a, 0x42, 0xa6, 0x31, 0x8f, 0x4b, 0xf0, 0xb9, 0x9a,
|
||||
0x9f, 0x0d, 0xca, 0x12, 0xb9, 0x3a, 0xdf, 0xc9, 0x11, 0x9e, 0x33, 0xe8, 0x61, 0x9a,
|
||||
0x02, 0xd7, 0x8d, 0xc7, 0x0e, 0xf2,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x11, 0xd6, 0xe2, 0x0e, 0x98, 0x6c, 0x20, 0x85, 0x4c, 0x8c, 0x18, 0x00, 0xeb, 0x10,
|
||||
0x45, 0x66, 0x22, 0x36, 0xf5, 0x52, 0x46, 0xd0, 0xd4, 0x4d, 0x40, 0x2a, 0xef, 0x1f,
|
||||
0xb7, 0x97, 0xe3, 0x2f, 0xa1, 0x37, 0x9b, 0x6f, 0xac, 0xf6, 0xe5, 0x96, 0x66, 0x32,
|
||||
0x3b, 0xf8, 0x0b, 0x58, 0xb9, 0xb9,
|
||||
]))
|
||||
.unwrap(),
|
||||
});
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x14, 0xc7, 0x15, 0xd5, 0x55, 0x3f, 0x01, 0xd2, 0x65, 0x30, 0x94, 0x27, 0xb3, 0xd5,
|
||||
0xd0, 0x90, 0xf4, 0xef, 0x57, 0xd6, 0x04, 0xb6, 0xbc, 0xa2, 0xd7, 0x0b, 0x0c, 0x7b,
|
||||
0x48, 0x1d, 0x23, 0xff, 0xcb, 0x20, 0x7e, 0x6b, 0x33, 0x41, 0xea, 0xba, 0x8e, 0x9a,
|
||||
0x7a, 0xda, 0xf6, 0xeb, 0x0e, 0xb9,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x13, 0x03, 0xf3, 0x46, 0x51, 0x12, 0xc8, 0xbc, 0x9a, 0xd2, 0x65, 0xeb, 0x46, 0xe0,
|
||||
0x19, 0x84, 0xd6, 0x2f, 0xa5, 0x13, 0x34, 0xf5, 0x60, 0xfa, 0xfe, 0x4b, 0x23, 0x31,
|
||||
0x7e, 0x07, 0x96, 0xd5, 0x35, 0xa2, 0x80, 0x9d, 0x15, 0x46, 0x8d, 0x83, 0xfd, 0xb0,
|
||||
0x32, 0xe7, 0xd9, 0x07, 0x9a, 0x94,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_subtraction() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
let mut a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
|
||||
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
|
||||
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
|
||||
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
|
||||
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
|
||||
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
|
||||
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
a.sub_assign(&Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x13, 0xce, 0x43, 0x3f, 0xa2, 0x60, 0x27, 0xf5, 0x98, 0x6a, 0x4a, 0x62, 0xfa, 0x82,
|
||||
0xa4, 0x9d, 0x3b, 0x88, 0x89, 0x9a, 0x42, 0xa6, 0x31, 0x8f, 0x4b, 0xf0, 0xb9, 0x9a,
|
||||
0x9f, 0x0d, 0xca, 0x12, 0xb9, 0x3a, 0xdf, 0xc9, 0x11, 0x9e, 0x33, 0xe8, 0x61, 0x9a,
|
||||
0x02, 0xd7, 0x8d, 0xc7, 0x0e, 0xf2,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x11, 0xd6, 0xe2, 0x0e, 0x98, 0x6c, 0x20, 0x85, 0x4c, 0x8c, 0x18, 0x00, 0xeb, 0x10,
|
||||
0x45, 0x66, 0x22, 0x36, 0xf5, 0x52, 0x46, 0xd0, 0xd4, 0x4d, 0x40, 0x2a, 0xef, 0x1f,
|
||||
0xb7, 0x97, 0xe3, 0x2f, 0xa1, 0x37, 0x9b, 0x6f, 0xac, 0xf6, 0xe5, 0x96, 0x66, 0x32,
|
||||
0x3b, 0xf8, 0x0b, 0x58, 0xb9, 0xb9,
|
||||
]))
|
||||
.unwrap(),
|
||||
});
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x07, 0x2b, 0xa1, 0x40, 0x49, 0xfe, 0x98, 0x81, 0x7f, 0x77, 0xa7, 0x18, 0x02, 0x1c,
|
||||
0x34, 0x2d, 0xe2, 0x55, 0x90, 0x26, 0x72, 0xef, 0x6c, 0x43, 0xa6, 0x5a, 0x6b, 0xe7,
|
||||
0x00, 0xb2, 0x85, 0xfe, 0x77, 0x56, 0xbe, 0xd7, 0xc1, 0x59, 0x82, 0xe9, 0x85, 0x65,
|
||||
0x75, 0x2b, 0xdb, 0x5c, 0x9b, 0x80,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x09, 0x57, 0x41, 0x13, 0x59, 0xba, 0x6e, 0x4c, 0x4c, 0xd5, 0xdd, 0x9f, 0xb4, 0x0b,
|
||||
0x3b, 0x8f, 0xf6, 0x39, 0x05, 0xf3, 0x9a, 0xd8, 0xcb, 0x1f, 0xe5, 0x26, 0x17, 0x93,
|
||||
0x05, 0x88, 0xc6, 0x9a, 0x11, 0xdf, 0x49, 0xbc, 0x6c, 0xac, 0xc2, 0x56, 0xeb, 0x4a,
|
||||
0xba, 0xf7, 0xc2, 0x55, 0xd1, 0xcd,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_negation() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
let a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
|
||||
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
|
||||
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
|
||||
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
|
||||
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
|
||||
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
|
||||
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
.neg();
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x19, 0x08, 0x3f, 0x54, 0x86, 0xa1, 0x0c, 0xbd, 0x7e, 0x55, 0x5d, 0xf1, 0x89, 0xf8,
|
||||
0x80, 0xe3, 0xab, 0x10, 0x7d, 0x49, 0x31, 0x74, 0x87, 0xab, 0xdc, 0x16, 0x7f, 0xc0,
|
||||
0x4d, 0xa1, 0x9c, 0x37, 0x0c, 0xc6, 0x61, 0x5c, 0x8f, 0xb0, 0x49, 0x2d, 0x8c, 0xfe,
|
||||
0x87, 0xfc, 0x96, 0xdb, 0xaa, 0xe4,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x18, 0xd4, 0x00, 0xb2, 0x80, 0xd9, 0x3e, 0x62, 0xfc, 0xd5, 0x59, 0xcb, 0xe7, 0x7b,
|
||||
0xd8, 0xb8, 0xb0, 0x7e, 0x9b, 0xc4, 0x05, 0x60, 0x86, 0x11, 0xa9, 0x10, 0x9e, 0x8f,
|
||||
0x30, 0x41, 0x42, 0x7e, 0x8a, 0x41, 0x1a, 0xd1, 0x49, 0x04, 0x58, 0x12, 0x22, 0x81,
|
||||
0x09, 0x10, 0x32, 0x50, 0xc9, 0xd0,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_doubling() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
let a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
|
||||
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
|
||||
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
|
||||
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
|
||||
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
|
||||
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
|
||||
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
assert_eq!(
|
||||
a.double(),
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x01, 0xf1, 0xa5, 0x2b, 0x65, 0xbd, 0xb3, 0xb9, 0x99, 0x8c, 0x93, 0x89, 0x72, 0xa6,
|
||||
0x57, 0xe7, 0x72, 0xcd, 0x9c, 0x77, 0x84, 0x21, 0x16, 0x27, 0x16, 0x34, 0xa5, 0xc1,
|
||||
0x52, 0x1e, 0xb3, 0xda, 0x23, 0xcb, 0x3d, 0x44, 0x43, 0x47, 0x6d, 0xa4, 0x5a, 0x00,
|
||||
0xf0, 0x06, 0xd2, 0x47, 0xff, 0x8e,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x02, 0x5a, 0x22, 0x6f, 0x71, 0x4d, 0x50, 0x6e, 0x9c, 0x8c, 0x9b, 0xd4, 0xb7, 0x9f,
|
||||
0xa8, 0x3d, 0x67, 0xf1, 0x5f, 0x81, 0xdc, 0x49, 0x19, 0x5b, 0x7c, 0x40, 0x68, 0x23,
|
||||
0x8c, 0xdf, 0x67, 0x4b, 0x28, 0xd5, 0xca, 0x5a, 0xd0, 0x9f, 0x4f, 0xdb, 0x2e, 0xfb,
|
||||
0xed, 0xdf, 0x9b, 0x5d, 0xc1, 0xb6,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_frobenius_map() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
let mut a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
|
||||
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
|
||||
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
|
||||
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
|
||||
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
|
||||
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
|
||||
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
a.frobenius_map(0);
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
|
||||
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
|
||||
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
|
||||
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
|
||||
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
|
||||
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
|
||||
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
a.frobenius_map(1);
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
|
||||
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
|
||||
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
|
||||
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x18, 0xd4, 0x00, 0xb2, 0x80, 0xd9, 0x3e, 0x62, 0xfc, 0xd5, 0x59, 0xcb, 0xe7, 0x7b,
|
||||
0xd8, 0xb8, 0xb0, 0x7e, 0x9b, 0xc4, 0x05, 0x60, 0x86, 0x11, 0xa9, 0x10, 0x9e, 0x8f,
|
||||
0x30, 0x41, 0x42, 0x7e, 0x8a, 0x41, 0x1a, 0xd1, 0x49, 0x04, 0x58, 0x12, 0x22, 0x81,
|
||||
0x09, 0x10, 0x32, 0x50, 0xc9, 0xd0,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
a.frobenius_map(1);
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
|
||||
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
|
||||
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
|
||||
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
|
||||
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
|
||||
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
|
||||
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
a.frobenius_map(2);
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
|
||||
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
|
||||
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
|
||||
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
|
||||
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
|
||||
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
|
||||
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_sqrt() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
assert_eq!(
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x07, 0xca, 0x7d, 0xa1, 0xf1, 0x36, 0x06, 0xac, 0x1e, 0x58, 0xb2, 0x15, 0x9d, 0xfe,
|
||||
0x10, 0xe2, 0xdb, 0x4a, 0x11, 0x6b, 0x5b, 0xf7, 0x4a, 0xa1, 0xa5, 0x7e, 0x6f, 0xc1,
|
||||
0xba, 0xb5, 0x1f, 0xd9, 0x03, 0x4c, 0x2d, 0x04, 0xfa, 0xff, 0xda, 0xb6, 0x47, 0x6b,
|
||||
0x4c, 0x30, 0x97, 0x20, 0xe2, 0x27,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x0e, 0xc9, 0x23, 0x36, 0x65, 0x0e, 0x49, 0xd5, 0x08, 0xee, 0x53, 0x94, 0xd7, 0x7a,
|
||||
0xfb, 0x3d, 0x21, 0x26, 0x11, 0xbc, 0xa4, 0xe9, 0x91, 0x21, 0x4c, 0xec, 0x2d, 0xca,
|
||||
0x57, 0x7a, 0x3e, 0xb6, 0x37, 0x1a, 0x75, 0xed, 0x14, 0xf4, 0x16, 0x29, 0xfa, 0x8d,
|
||||
0xe8, 0x8b, 0x75, 0x16, 0xd2, 0xc3,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
.sqrt()
|
||||
.unwrap(),
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x10, 0xf6, 0x96, 0x3b, 0xba, 0xd2, 0xeb, 0xc5, 0x88, 0x1b, 0x3e, 0x01, 0xb6, 0x11,
|
||||
0xc0, 0x70, 0x8d, 0x7f, 0x1f, 0x72, 0x3d, 0x02, 0xc1, 0xd3, 0x6d, 0x2d, 0xdb, 0xe5,
|
||||
0x52, 0x20, 0x3e, 0x82, 0x6e, 0xf7, 0xde, 0x92, 0xe8, 0xc6, 0x8b, 0x63, 0x40, 0xb2,
|
||||
0x99, 0xb2, 0x70, 0x42, 0x58, 0xc5,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x08, 0xd7, 0xcf, 0xff, 0x94, 0x21, 0x63, 0x30, 0xa4, 0xc9, 0x3b, 0x08, 0x10, 0x5d,
|
||||
0x71, 0xa9, 0x6b, 0x85, 0x2a, 0xea, 0xf2, 0xaf, 0xcb, 0x1b, 0x28, 0xa2, 0x0f, 0xae,
|
||||
0xd2, 0x11, 0xef, 0xe7, 0x76, 0x70, 0x59, 0x46, 0x65, 0x67, 0x64, 0x47, 0xc0, 0x99,
|
||||
0x53, 0x4f, 0xc2, 0x09, 0xe7, 0x52,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b,
|
||||
0xac, 0xd7, 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0,
|
||||
0xf6, 0xb0, 0xf6, 0x24, 0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xf7,
|
||||
0x84, 0x29, 0xd1, 0x51, 0x7a, 0x6b,
|
||||
]))
|
||||
.unwrap(),
|
||||
c1: Fq::zero(),
|
||||
}
|
||||
.sqrt()
|
||||
.unwrap(),
|
||||
Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::from_repr(FqRepr([
|
||||
0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b,
|
||||
0xac, 0xd7, 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0,
|
||||
0xf6, 0xb0, 0xf6, 0x24, 0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe,
|
||||
0xff, 0xff, 0xfd, 0x43, 0x57, 0xa3,
|
||||
]))
|
||||
.unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use rand_core::SeedableRng;
|
||||
#[cfg(test)]
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
#[test]
|
||||
fn test_fq2_mul_nonresidue() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let nqr = Fq2 {
|
||||
c0: Fq::one(),
|
||||
c1: Fq::one(),
|
||||
};
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut a = Fq2::random(&mut rng);
|
||||
let mut b = a;
|
||||
a.mul_by_nonresidue();
|
||||
b.mul_assign(&nqr);
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fq2_field_tests() {
|
||||
crate::tests::field::random_field_tests::<Fq2>();
|
||||
crate::tests::field::random_sqrt_tests::<Fq2>();
|
||||
}
|
|
@ -1,478 +0,0 @@
|
|||
use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2};
|
||||
use super::fq2::Fq2;
|
||||
use ff::Field;
|
||||
use rand_core::RngCore;
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use subtle::{Choice, ConditionallySelectable, CtOption};
|
||||
|
||||
/// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2).
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Fq6 {
|
||||
pub c0: Fq2,
|
||||
pub c1: Fq2,
|
||||
pub c2: Fq2,
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for Fq6 {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
write!(f, "Fq6({} + {} * v, {} * v^2)", self.c0, self.c1, self.c2)
|
||||
}
|
||||
}
|
||||
|
||||
impl Fq6 {
|
||||
/// Multiply by quadratic nonresidue v.
|
||||
pub fn mul_by_nonresidue(&mut self) {
|
||||
use std::mem::swap;
|
||||
swap(&mut self.c0, &mut self.c1);
|
||||
swap(&mut self.c0, &mut self.c2);
|
||||
|
||||
self.c0.mul_by_nonresidue();
|
||||
}
|
||||
|
||||
pub fn mul_by_1(&mut self, c1: &Fq2) {
|
||||
let mut b_b = self.c1;
|
||||
b_b.mul_assign(c1);
|
||||
|
||||
let mut t1 = *c1;
|
||||
{
|
||||
let mut tmp = self.c1;
|
||||
tmp.add_assign(&self.c2);
|
||||
|
||||
t1.mul_assign(&tmp);
|
||||
t1.sub_assign(&b_b);
|
||||
t1.mul_by_nonresidue();
|
||||
}
|
||||
|
||||
let mut t2 = *c1;
|
||||
{
|
||||
let mut tmp = self.c0;
|
||||
tmp.add_assign(&self.c1);
|
||||
|
||||
t2.mul_assign(&tmp);
|
||||
t2.sub_assign(&b_b);
|
||||
}
|
||||
|
||||
self.c0 = t1;
|
||||
self.c1 = t2;
|
||||
self.c2 = b_b;
|
||||
}
|
||||
|
||||
pub fn mul_by_01(&mut self, c0: &Fq2, c1: &Fq2) {
|
||||
let mut a_a = self.c0;
|
||||
let mut b_b = self.c1;
|
||||
a_a.mul_assign(c0);
|
||||
b_b.mul_assign(c1);
|
||||
|
||||
let mut t1 = *c1;
|
||||
{
|
||||
let mut tmp = self.c1;
|
||||
tmp.add_assign(&self.c2);
|
||||
|
||||
t1.mul_assign(&tmp);
|
||||
t1.sub_assign(&b_b);
|
||||
t1.mul_by_nonresidue();
|
||||
t1.add_assign(&a_a);
|
||||
}
|
||||
|
||||
let mut t3 = *c0;
|
||||
{
|
||||
let mut tmp = self.c0;
|
||||
tmp.add_assign(&self.c2);
|
||||
|
||||
t3.mul_assign(&tmp);
|
||||
t3.sub_assign(&a_a);
|
||||
t3.add_assign(&b_b);
|
||||
}
|
||||
|
||||
let mut t2 = *c0;
|
||||
t2.add_assign(c1);
|
||||
{
|
||||
let mut tmp = self.c0;
|
||||
tmp.add_assign(&self.c1);
|
||||
|
||||
t2.mul_assign(&tmp);
|
||||
t2.sub_assign(&a_a);
|
||||
t2.sub_assign(&b_b);
|
||||
}
|
||||
|
||||
self.c0 = t1;
|
||||
self.c1 = t2;
|
||||
self.c2 = t3;
|
||||
}
|
||||
|
||||
pub fn frobenius_map(&mut self, power: usize) {
|
||||
self.c0.frobenius_map(power);
|
||||
self.c1.frobenius_map(power);
|
||||
self.c2.frobenius_map(power);
|
||||
|
||||
self.c1.mul_assign(&FROBENIUS_COEFF_FQ6_C1[power % 6]);
|
||||
self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]);
|
||||
}
|
||||
}
|
||||
|
||||
impl ConditionallySelectable for Fq6 {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::conditional_select(&a.c0, &b.c0, choice),
|
||||
c1: Fq2::conditional_select(&a.c1, &b.c1, choice),
|
||||
c2: Fq2::conditional_select(&a.c2, &b.c2, choice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
Fq6 {
|
||||
c0: self.c0.neg(),
|
||||
c1: self.c1.neg(),
|
||||
c2: self.c2.neg(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Add<&'r Fq6> for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: &Self) -> Self {
|
||||
Fq6 {
|
||||
c0: self.c0 + other.c0,
|
||||
c1: self.c1 + other.c1,
|
||||
c2: self.c2 + other.c2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
self.add(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> AddAssign<&'r Fq6> for Fq6 {
|
||||
fn add_assign(&mut self, other: &'r Self) {
|
||||
self.c0.add_assign(&other.c0);
|
||||
self.c1.add_assign(&other.c1);
|
||||
self.c2.add_assign(&other.c2);
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Fq6 {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.add_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Sub<&'r Fq6> for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: &Self) -> Self {
|
||||
Fq6 {
|
||||
c0: self.c0 - other.c0,
|
||||
c1: self.c1 - other.c1,
|
||||
c2: self.c2 - other.c2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self.sub(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> SubAssign<&'r Fq6> for Fq6 {
|
||||
fn sub_assign(&mut self, other: &'r Self) {
|
||||
self.c0.sub_assign(&other.c0);
|
||||
self.c1.sub_assign(&other.c1);
|
||||
self.c2.sub_assign(&other.c2);
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Fq6 {
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.sub_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Mul<&'r Fq6> for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.mul_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self.mul(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> MulAssign<&'r Fq6> for Fq6 {
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
let mut a_a = self.c0;
|
||||
let mut b_b = self.c1;
|
||||
let mut c_c = self.c2;
|
||||
a_a.mul_assign(&other.c0);
|
||||
b_b.mul_assign(&other.c1);
|
||||
c_c.mul_assign(&other.c2);
|
||||
|
||||
let mut t1 = other.c1;
|
||||
t1.add_assign(&other.c2);
|
||||
{
|
||||
let mut tmp = self.c1;
|
||||
tmp.add_assign(&self.c2);
|
||||
|
||||
t1.mul_assign(&tmp);
|
||||
t1.sub_assign(&b_b);
|
||||
t1.sub_assign(&c_c);
|
||||
t1.mul_by_nonresidue();
|
||||
t1.add_assign(&a_a);
|
||||
}
|
||||
|
||||
let mut t3 = other.c0;
|
||||
t3.add_assign(&other.c2);
|
||||
{
|
||||
let mut tmp = self.c0;
|
||||
tmp.add_assign(&self.c2);
|
||||
|
||||
t3.mul_assign(&tmp);
|
||||
t3.sub_assign(&a_a);
|
||||
t3.add_assign(&b_b);
|
||||
t3.sub_assign(&c_c);
|
||||
}
|
||||
|
||||
let mut t2 = other.c0;
|
||||
t2.add_assign(&other.c1);
|
||||
{
|
||||
let mut tmp = self.c0;
|
||||
tmp.add_assign(&self.c1);
|
||||
|
||||
t2.mul_assign(&tmp);
|
||||
t2.sub_assign(&a_a);
|
||||
t2.sub_assign(&b_b);
|
||||
c_c.mul_by_nonresidue();
|
||||
t2.add_assign(&c_c);
|
||||
}
|
||||
|
||||
self.c0 = t1;
|
||||
self.c1 = t2;
|
||||
self.c2 = t3;
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for Fq6 {
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
self.mul_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for Fq6 {
|
||||
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::random(rng),
|
||||
c1: Fq2::random(rng),
|
||||
c2: Fq2::random(rng),
|
||||
}
|
||||
}
|
||||
|
||||
fn zero() -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::zero(),
|
||||
c1: Fq2::zero(),
|
||||
c2: Fq2::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn one() -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::one(),
|
||||
c1: Fq2::zero(),
|
||||
c2: Fq2::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
self.c0.is_zero() && self.c1.is_zero() && self.c2.is_zero()
|
||||
}
|
||||
|
||||
fn double(&self) -> Self {
|
||||
Fq6 {
|
||||
c0: self.c0.double(),
|
||||
c1: self.c1.double(),
|
||||
c2: self.c2.double(),
|
||||
}
|
||||
}
|
||||
|
||||
fn square(&self) -> Self {
|
||||
let s0 = self.c0.square();
|
||||
let mut ab = self.c0;
|
||||
ab.mul_assign(&self.c1);
|
||||
let s1 = ab.double();
|
||||
let mut s2 = self.c0;
|
||||
s2.sub_assign(&self.c1);
|
||||
s2.add_assign(&self.c2);
|
||||
s2 = s2.square();
|
||||
let mut bc = self.c1;
|
||||
bc.mul_assign(&self.c2);
|
||||
let s3 = bc.double();
|
||||
let s4 = self.c2.square();
|
||||
|
||||
let mut c0 = s3;
|
||||
c0.mul_by_nonresidue();
|
||||
c0.add_assign(&s0);
|
||||
|
||||
let mut c1 = s4;
|
||||
c1.mul_by_nonresidue();
|
||||
c1.add_assign(&s1);
|
||||
|
||||
let mut c2 = s1;
|
||||
c2.add_assign(&s2);
|
||||
c2.add_assign(&s3);
|
||||
c2.sub_assign(&s0);
|
||||
c2.sub_assign(&s4);
|
||||
|
||||
Fq6 { c0, c1, c2 }
|
||||
}
|
||||
|
||||
fn invert(&self) -> CtOption<Self> {
|
||||
let mut c0 = self.c2;
|
||||
c0.mul_by_nonresidue();
|
||||
c0.mul_assign(&self.c1);
|
||||
c0 = c0.neg();
|
||||
{
|
||||
let c0s = self.c0.square();
|
||||
c0.add_assign(&c0s);
|
||||
}
|
||||
let mut c1 = self.c2.square();
|
||||
c1.mul_by_nonresidue();
|
||||
{
|
||||
let mut c01 = self.c0;
|
||||
c01.mul_assign(&self.c1);
|
||||
c1.sub_assign(&c01);
|
||||
}
|
||||
let mut c2 = self.c1.square();
|
||||
{
|
||||
let mut c02 = self.c0;
|
||||
c02.mul_assign(&self.c2);
|
||||
c2.sub_assign(&c02);
|
||||
}
|
||||
|
||||
let mut tmp1 = self.c2;
|
||||
tmp1.mul_assign(&c1);
|
||||
let mut tmp2 = self.c1;
|
||||
tmp2.mul_assign(&c2);
|
||||
tmp1.add_assign(&tmp2);
|
||||
tmp1.mul_by_nonresidue();
|
||||
tmp2 = self.c0;
|
||||
tmp2.mul_assign(&c0);
|
||||
tmp1.add_assign(&tmp2);
|
||||
|
||||
tmp1.invert().map(|t| {
|
||||
let mut tmp = Fq6 {
|
||||
c0: t,
|
||||
c1: t,
|
||||
c2: t,
|
||||
};
|
||||
tmp.c0.mul_assign(&c0);
|
||||
tmp.c1.mul_assign(&c1);
|
||||
tmp.c2.mul_assign(&c2);
|
||||
|
||||
tmp
|
||||
})
|
||||
}
|
||||
|
||||
fn sqrt(&self) -> CtOption<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use rand_core::SeedableRng;
|
||||
#[cfg(test)]
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
#[test]
|
||||
fn test_fq6_mul_nonresidue() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let nqr = Fq6 {
|
||||
c0: Fq2::zero(),
|
||||
c1: Fq2::one(),
|
||||
c2: Fq2::zero(),
|
||||
};
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut a = Fq6::random(&mut rng);
|
||||
let mut b = a;
|
||||
a.mul_by_nonresidue();
|
||||
b.mul_assign(&nqr);
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq6_mul_by_1() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let c1 = Fq2::random(&mut rng);
|
||||
let mut a = Fq6::random(&mut rng);
|
||||
let mut b = a;
|
||||
|
||||
a.mul_by_1(&c1);
|
||||
b.mul_assign(&Fq6 {
|
||||
c0: Fq2::zero(),
|
||||
c1,
|
||||
c2: Fq2::zero(),
|
||||
});
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq6_mul_by_01() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let c0 = Fq2::random(&mut rng);
|
||||
let c1 = Fq2::random(&mut rng);
|
||||
let mut a = Fq6::random(&mut rng);
|
||||
let mut b = a;
|
||||
|
||||
a.mul_by_01(&c0, &c1);
|
||||
b.mul_assign(&Fq6 {
|
||||
c0,
|
||||
c1,
|
||||
c2: Fq2::zero(),
|
||||
});
|
||||
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fq6_field_tests() {
|
||||
crate::tests::field::random_field_tests::<Fq6>();
|
||||
}
|
|
@ -1,601 +0,0 @@
|
|||
use ff::{Field, PrimeField};
|
||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
||||
|
||||
#[derive(PrimeField)]
|
||||
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
|
||||
#[PrimeFieldGenerator = "7"]
|
||||
#[PrimeFieldReprEndianness = "little"]
|
||||
pub struct Fr([u64; 4]);
|
||||
|
||||
#[cfg(test)]
|
||||
use rand_core::SeedableRng;
|
||||
#[cfg(test)]
|
||||
use rand_xorshift::XorShiftRng;
|
||||
#[cfg(test)]
|
||||
use std::ops::Neg;
|
||||
|
||||
#[test]
|
||||
fn test_fr_is_valid() {
|
||||
let mut a = MODULUS_LIMBS;
|
||||
assert!(!a.is_valid());
|
||||
a.sub_noborrow(&Fr([1, 0, 0, 0]));
|
||||
assert!(a.is_valid());
|
||||
assert!(Fr::from(0).is_valid());
|
||||
assert!(Fr([
|
||||
0xffffffff00000000,
|
||||
0x53bda402fffe5bfe,
|
||||
0x3339d80809a1d805,
|
||||
0x73eda753299d7d48
|
||||
])
|
||||
.is_valid());
|
||||
assert!(!Fr([
|
||||
0xffffffffffffffff,
|
||||
0xffffffffffffffff,
|
||||
0xffffffffffffffff,
|
||||
0xffffffffffffffff
|
||||
])
|
||||
.is_valid());
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let a = Fr::random(&mut rng);
|
||||
assert!(a.is_valid());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_add_assign() {
|
||||
{
|
||||
// Random number
|
||||
let mut tmp = Fr([
|
||||
0x437ce7616d580765,
|
||||
0xd42d1ccb29d1235b,
|
||||
0xed8f753821bd1423,
|
||||
0x4eede1c9c89528ca,
|
||||
]);
|
||||
assert!(tmp.is_valid());
|
||||
// Test that adding zero has no effect.
|
||||
tmp.add_assign(&Fr([0, 0, 0, 0]));
|
||||
assert_eq!(
|
||||
tmp,
|
||||
Fr([
|
||||
0x437ce7616d580765,
|
||||
0xd42d1ccb29d1235b,
|
||||
0xed8f753821bd1423,
|
||||
0x4eede1c9c89528ca
|
||||
])
|
||||
);
|
||||
// Add one and test for the result.
|
||||
tmp.add_assign(&Fr([1, 0, 0, 0]));
|
||||
assert_eq!(
|
||||
tmp,
|
||||
Fr([
|
||||
0x437ce7616d580766,
|
||||
0xd42d1ccb29d1235b,
|
||||
0xed8f753821bd1423,
|
||||
0x4eede1c9c89528ca
|
||||
])
|
||||
);
|
||||
// Add another random number that exercises the reduction.
|
||||
tmp.add_assign(&Fr([
|
||||
0x946f435944f7dc79,
|
||||
0xb55e7ee6533a9b9b,
|
||||
0x1e43b84c2f6194ca,
|
||||
0x58717ab525463496,
|
||||
]));
|
||||
assert_eq!(
|
||||
tmp,
|
||||
Fr([
|
||||
0xd7ec2abbb24fe3de,
|
||||
0x35cdf7ae7d0d62f7,
|
||||
0xd899557c477cd0e9,
|
||||
0x3371b52bc43de018
|
||||
])
|
||||
);
|
||||
// Add one to (r - 1) and test for the result.
|
||||
tmp = Fr([
|
||||
0xffffffff00000000,
|
||||
0x53bda402fffe5bfe,
|
||||
0x3339d80809a1d805,
|
||||
0x73eda753299d7d48,
|
||||
]);
|
||||
tmp.add_assign(&Fr([1, 0, 0, 0]));
|
||||
assert!(tmp.is_zero());
|
||||
// Add a random number to another one such that the result is r - 1
|
||||
tmp = Fr([
|
||||
0xade5adacdccb6190,
|
||||
0xaa21ee0f27db3ccd,
|
||||
0x2550f4704ae39086,
|
||||
0x591d1902e7c5ba27,
|
||||
]);
|
||||
tmp.add_assign(&Fr([
|
||||
0x521a525223349e70,
|
||||
0xa99bb5f3d8231f31,
|
||||
0xde8e397bebe477e,
|
||||
0x1ad08e5041d7c321,
|
||||
]));
|
||||
assert_eq!(
|
||||
tmp,
|
||||
Fr([
|
||||
0xffffffff00000000,
|
||||
0x53bda402fffe5bfe,
|
||||
0x3339d80809a1d805,
|
||||
0x73eda753299d7d48
|
||||
])
|
||||
);
|
||||
// Add one to the result and test for it.
|
||||
tmp.add_assign(&Fr([1, 0, 0, 0]));
|
||||
assert!(tmp.is_zero());
|
||||
}
|
||||
|
||||
// Test associativity
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Generate a, b, c and ensure (a + b) + c == a + (b + c).
|
||||
let a = Fr::random(&mut rng);
|
||||
let b = Fr::random(&mut rng);
|
||||
let c = Fr::random(&mut rng);
|
||||
|
||||
let mut tmp1 = a;
|
||||
tmp1.add_assign(&b);
|
||||
tmp1.add_assign(&c);
|
||||
|
||||
let mut tmp2 = b;
|
||||
tmp2.add_assign(&c);
|
||||
tmp2.add_assign(&a);
|
||||
|
||||
assert!(tmp1.is_valid());
|
||||
assert!(tmp2.is_valid());
|
||||
assert_eq!(tmp1, tmp2);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_sub_assign() {
|
||||
{
|
||||
// Test arbitrary subtraction that tests reduction.
|
||||
let mut tmp = Fr([
|
||||
0x6a68c64b6f735a2b,
|
||||
0xd5f4d143fe0a1972,
|
||||
0x37c17f3829267c62,
|
||||
0xa2f37391f30915c,
|
||||
]);
|
||||
tmp.sub_assign(&Fr([
|
||||
0xade5adacdccb6190,
|
||||
0xaa21ee0f27db3ccd,
|
||||
0x2550f4704ae39086,
|
||||
0x591d1902e7c5ba27,
|
||||
]));
|
||||
assert_eq!(
|
||||
tmp,
|
||||
Fr([
|
||||
0xbc83189d92a7f89c,
|
||||
0x7f908737d62d38a3,
|
||||
0x45aa62cfe7e4c3e1,
|
||||
0x24ffc5896108547d
|
||||
])
|
||||
);
|
||||
|
||||
// Test the opposite subtraction which doesn't test reduction.
|
||||
tmp = Fr([
|
||||
0xade5adacdccb6190,
|
||||
0xaa21ee0f27db3ccd,
|
||||
0x2550f4704ae39086,
|
||||
0x591d1902e7c5ba27,
|
||||
]);
|
||||
tmp.sub_assign(&Fr([
|
||||
0x6a68c64b6f735a2b,
|
||||
0xd5f4d143fe0a1972,
|
||||
0x37c17f3829267c62,
|
||||
0xa2f37391f30915c,
|
||||
]));
|
||||
assert_eq!(
|
||||
tmp,
|
||||
Fr([
|
||||
0x437ce7616d580765,
|
||||
0xd42d1ccb29d1235b,
|
||||
0xed8f753821bd1423,
|
||||
0x4eede1c9c89528ca
|
||||
])
|
||||
);
|
||||
|
||||
// Test for sensible results with zero
|
||||
tmp = Fr::from(0);
|
||||
tmp.sub_assign(&Fr::from(0));
|
||||
assert!(tmp.is_zero());
|
||||
|
||||
tmp = Fr([
|
||||
0x437ce7616d580765,
|
||||
0xd42d1ccb29d1235b,
|
||||
0xed8f753821bd1423,
|
||||
0x4eede1c9c89528ca,
|
||||
]);
|
||||
tmp.sub_assign(&Fr::from(0));
|
||||
assert_eq!(
|
||||
tmp,
|
||||
Fr([
|
||||
0x437ce7616d580765,
|
||||
0xd42d1ccb29d1235b,
|
||||
0xed8f753821bd1423,
|
||||
0x4eede1c9c89528ca
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Ensure that (a - b) + (b - a) = 0.
|
||||
let a = Fr::random(&mut rng);
|
||||
let b = Fr::random(&mut rng);
|
||||
|
||||
let mut tmp1 = a;
|
||||
tmp1.sub_assign(&b);
|
||||
|
||||
let mut tmp2 = b;
|
||||
tmp2.sub_assign(&a);
|
||||
|
||||
tmp1.add_assign(&tmp2);
|
||||
assert!(tmp1.is_zero());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_mul_assign() {
|
||||
let mut tmp = Fr([
|
||||
0x6b7e9b8faeefc81a,
|
||||
0xe30a8463f348ba42,
|
||||
0xeff3cb67a8279c9c,
|
||||
0x3d303651bd7c774d,
|
||||
]);
|
||||
tmp.mul_assign(&Fr([
|
||||
0x13ae28e3bc35ebeb,
|
||||
0xa10f4488075cae2c,
|
||||
0x8160e95a853c3b5d,
|
||||
0x5ae3f03b561a841d,
|
||||
]));
|
||||
assert!(
|
||||
tmp == Fr([
|
||||
0x23717213ce710f71,
|
||||
0xdbee1fe53a16e1af,
|
||||
0xf565d3e1c2a48000,
|
||||
0x4426507ee75df9d7
|
||||
])
|
||||
);
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000000 {
|
||||
// Ensure that (a * b) * c = a * (b * c)
|
||||
let a = Fr::random(&mut rng);
|
||||
let b = Fr::random(&mut rng);
|
||||
let c = Fr::random(&mut rng);
|
||||
|
||||
let mut tmp1 = a;
|
||||
tmp1.mul_assign(&b);
|
||||
tmp1.mul_assign(&c);
|
||||
|
||||
let mut tmp2 = b;
|
||||
tmp2.mul_assign(&c);
|
||||
tmp2.mul_assign(&a);
|
||||
|
||||
assert_eq!(tmp1, tmp2);
|
||||
}
|
||||
|
||||
for _ in 0..1000000 {
|
||||
// Ensure that r * (a + b + c) = r*a + r*b + r*c
|
||||
|
||||
let r = Fr::random(&mut rng);
|
||||
let mut a = Fr::random(&mut rng);
|
||||
let mut b = Fr::random(&mut rng);
|
||||
let mut c = Fr::random(&mut rng);
|
||||
|
||||
let mut tmp1 = a;
|
||||
tmp1.add_assign(&b);
|
||||
tmp1.add_assign(&c);
|
||||
tmp1.mul_assign(&r);
|
||||
|
||||
a.mul_assign(&r);
|
||||
b.mul_assign(&r);
|
||||
c.mul_assign(&r);
|
||||
|
||||
a.add_assign(&b);
|
||||
a.add_assign(&c);
|
||||
|
||||
assert_eq!(tmp1, a);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_squaring() {
|
||||
let a = Fr([
|
||||
0xffffffffffffffff,
|
||||
0xffffffffffffffff,
|
||||
0xffffffffffffffff,
|
||||
0x73eda753299d7d47,
|
||||
]);
|
||||
assert!(a.is_valid());
|
||||
assert_eq!(
|
||||
a.square(),
|
||||
Fr::from_repr(FrRepr([
|
||||
0xb8, 0x77, 0xe0, 0xbd, 0xe7, 0x98, 0xd6, 0xc0, 0xc2, 0x6e, 0xe7, 0x79, 0x05, 0x31,
|
||||
0x9a, 0xb7, 0x5f, 0x4e, 0xaf, 0xa9, 0xd0, 0xa8, 0x1d, 0xac, 0x97, 0x3e, 0xf2, 0x9b,
|
||||
0xc4, 0x29, 0xf6, 0x13,
|
||||
]))
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000000 {
|
||||
// Ensure that (a * a) = a^2
|
||||
let a = Fr::random(&mut rng);
|
||||
assert_eq!(a.square(), a * a);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_invert() {
|
||||
assert!(bool::from(Fr::zero().invert().is_none()));
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
let one = Fr::one();
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Ensure that a * a^-1 = 1
|
||||
let mut a = Fr::random(&mut rng);
|
||||
let ainv = a.invert().unwrap();
|
||||
a.mul_assign(&ainv);
|
||||
assert_eq!(a, one);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_double() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Ensure doubling a is equivalent to adding a to itself.
|
||||
let a = Fr::random(&mut rng);
|
||||
assert_eq!(a.double(), a + a);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_neg() {
|
||||
{
|
||||
let a = Fr::zero().neg();
|
||||
|
||||
assert!(a.is_zero());
|
||||
}
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Ensure (a - (-a)) = 0.
|
||||
let mut a = Fr::random(&mut rng);
|
||||
let b = a.neg();
|
||||
a.add_assign(&b);
|
||||
|
||||
assert!(a.is_zero());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_pow() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for i in 0u64..1000 {
|
||||
// Exponentiate by various small numbers and ensure it consists with repeated
|
||||
// multiplication.
|
||||
let a = Fr::random(&mut rng);
|
||||
let target = a.pow_vartime(&[i]);
|
||||
let mut c = Fr::one();
|
||||
for _ in 0..i {
|
||||
c.mul_assign(&a);
|
||||
}
|
||||
assert_eq!(c, target);
|
||||
}
|
||||
|
||||
use byteorder::ByteOrder;
|
||||
let mut char_limbs = [0; 4];
|
||||
byteorder::LittleEndian::read_u64_into(Fr::char().as_ref(), &mut char_limbs);
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Exponentiating by the modulus should have no effect in a prime field.
|
||||
let a = Fr::random(&mut rng);
|
||||
|
||||
assert_eq!(a, a.pow_vartime(char_limbs));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_sqrt() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
assert_eq!(Fr::zero().sqrt().unwrap(), Fr::zero());
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Ensure sqrt(a^2) = a or -a
|
||||
let a = Fr::random(&mut rng);
|
||||
let nega = a.neg();
|
||||
let b = a.square();
|
||||
|
||||
let b = b.sqrt().unwrap();
|
||||
|
||||
assert!(a == b || nega == b);
|
||||
}
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Ensure sqrt(a)^2 = a for random a
|
||||
let a = Fr::random(&mut rng);
|
||||
|
||||
let tmp = a.sqrt();
|
||||
if tmp.is_some().into() {
|
||||
assert_eq!(a, tmp.unwrap().square());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_from_to_repr() {
|
||||
// r + 1 should not be in the field
|
||||
assert!(Fr::from_repr(FrRepr([
|
||||
0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0x02, 0xa4, 0xbd,
|
||||
0x53, 0x05, 0xd8, 0xa1, 0x09, 0x08, 0xd8, 0x39, 0x33, 0x48, 0x7d, 0x9d, 0x29, 0x53, 0xa7,
|
||||
0xed, 0x73,
|
||||
]))
|
||||
.is_none());
|
||||
|
||||
// r should not be in the field
|
||||
assert!(Fr::from_repr(Fr::char()).is_none());
|
||||
|
||||
// Multiply some arbitrary representations to see if the result is as expected.
|
||||
let a = FrRepr([
|
||||
0x6a, 0x0c, 0x3c, 0xad, 0xa3, 0xe3, 0xeb, 0x25, 0x7c, 0x81, 0x2e, 0x09, 0x9d, 0xe3, 0x90,
|
||||
0x69, 0x8e, 0x65, 0xf5, 0x42, 0x0d, 0x90, 0x1f, 0x94, 0xe0, 0x71, 0x8a, 0xb3, 0x03, 0xa1,
|
||||
0xf8, 0x44,
|
||||
]);
|
||||
let mut a_fr = Fr::from_repr(a).unwrap();
|
||||
let b = FrRepr([
|
||||
0x75, 0x24, 0x5e, 0x88, 0x54, 0x94, 0x4e, 0x26, 0x70, 0x83, 0x30, 0xb0, 0x6b, 0x74, 0xf7,
|
||||
0x46, 0xf9, 0x11, 0x74, 0x34, 0xf5, 0x3e, 0x68, 0x04, 0x92, 0x44, 0x8d, 0x20, 0x7f, 0x8d,
|
||||
0x83, 0x58,
|
||||
]);
|
||||
let b_fr = Fr::from_repr(b).unwrap();
|
||||
let c = FrRepr([
|
||||
0x0d, 0x74, 0xfc, 0x3c, 0xb9, 0x9a, 0xa0, 0x48, 0x71, 0xa6, 0xc7, 0xbf, 0x0f, 0x60, 0xa6,
|
||||
0x03, 0x67, 0xd7, 0x01, 0x75, 0x01, 0x67, 0x85, 0x83, 0x12, 0x55, 0x74, 0x77, 0xda, 0xd6,
|
||||
0x61, 0x71,
|
||||
]);
|
||||
a_fr.mul_assign(&b_fr);
|
||||
assert_eq!(a_fr.to_repr(), c);
|
||||
|
||||
// Zero should be in the field.
|
||||
assert!(Fr::from_repr(FrRepr([0; 32])).unwrap().is_zero());
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Try to turn Fr elements into representations and back again, and compare.
|
||||
let a = Fr::random(&mut rng);
|
||||
let a_repr = a.to_repr();
|
||||
let b_repr = FrRepr::from(a);
|
||||
assert_eq!(a_repr, b_repr);
|
||||
let a_again = Fr::from_repr(a_repr).unwrap();
|
||||
|
||||
assert_eq!(a, a_again);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_display() {
|
||||
assert_eq!(
|
||||
format!(
|
||||
"{}",
|
||||
Fr::from_repr(FrRepr([
|
||||
0xc7, 0xec, 0xb5, 0xa3, 0x46, 0xe7, 0xca, 0xc3, 0xee, 0x5a, 0x5b, 0x3f, 0xeb, 0xc8,
|
||||
0x5e, 0x18, 0x99, 0xdd, 0xb9, 0xe4, 0xff, 0x99, 0x44, 0x68, 0xaa, 0x8f, 0xb6, 0xaf,
|
||||
0xa7, 0xbb, 0xc9, 0x07,
|
||||
]))
|
||||
.unwrap()
|
||||
),
|
||||
"Fr(0x07c9bba7afb68faa684499ffe4b9dd99185ec8eb3f5b5aeec3cae746a3b5ecc7)".to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
format!(
|
||||
"{}",
|
||||
Fr::from_repr(FrRepr([
|
||||
0x06, 0x81, 0x19, 0xff, 0x98, 0x12, 0xc7, 0x44, 0x6a, 0x9b, 0xf7, 0x7d, 0x81, 0x10,
|
||||
0xad, 0xb0, 0x2b, 0x13, 0x74, 0x2b, 0x0a, 0xa8, 0x34, 0xd0, 0x19, 0x07, 0xf5, 0x36,
|
||||
0x13, 0x9a, 0xcf, 0x41,
|
||||
]))
|
||||
.unwrap()
|
||||
),
|
||||
"Fr(0x41cf9a1336f50719d034a80a2b74132bb0ad10817df79b6a44c71298ff198106)".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_is_odd() {
|
||||
assert!(!Fr::from(0).is_odd());
|
||||
assert!(Fr::from(0).is_even());
|
||||
assert!(Fr::from(1).is_odd());
|
||||
assert!(!Fr::from(1).is_even());
|
||||
assert!(!Fr::from(324834872).is_odd());
|
||||
assert!(Fr::from(324834872).is_even());
|
||||
assert!(Fr::from(324834873).is_odd());
|
||||
assert!(!Fr::from(324834873).is_even());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_num_bits() {
|
||||
assert_eq!(Fr::NUM_BITS, 255);
|
||||
assert_eq!(Fr::CAPACITY, 254);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_root_of_unity() {
|
||||
assert_eq!(Fr::S, 32);
|
||||
assert_eq!(Fr::multiplicative_generator(), Fr::from(7));
|
||||
assert_eq!(
|
||||
Fr::multiplicative_generator().pow_vartime([
|
||||
0xfffe5bfeffffffffu64,
|
||||
0x9a1d80553bda402,
|
||||
0x299d7d483339d808,
|
||||
0x73eda753
|
||||
]),
|
||||
Fr::root_of_unity()
|
||||
);
|
||||
assert_eq!(Fr::root_of_unity().pow_vartime([1u64 << Fr::S]), Fr::one());
|
||||
assert!(bool::from(Fr::multiplicative_generator().sqrt().is_none()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fr_field_tests() {
|
||||
crate::tests::field::random_field_tests::<Fr>();
|
||||
crate::tests::field::random_sqrt_tests::<Fr>();
|
||||
crate::tests::field::from_str_tests::<Fr>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fr_repr_tests() {
|
||||
crate::tests::repr::random_repr_tests::<Fr>();
|
||||
}
|
|
@ -1,524 +0,0 @@
|
|||
//! An implementation of the BLS12-381 pairing-friendly elliptic curve
|
||||
//! construction.
|
||||
|
||||
mod ec;
|
||||
mod fq;
|
||||
mod fq12;
|
||||
mod fq2;
|
||||
mod fq6;
|
||||
mod fr;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use self::ec::{
|
||||
G1Affine, G1Compressed, G1Uncompressed, G2Affine, G2Compressed, G2Prepared, G2Uncompressed, G1,
|
||||
G2,
|
||||
};
|
||||
pub use self::fq::{Fq, FqRepr};
|
||||
pub use self::fq12::Fq12;
|
||||
pub use self::fq2::Fq2;
|
||||
pub use self::fq6::Fq6;
|
||||
pub use self::fr::{Fr, FrRepr};
|
||||
|
||||
use super::{Engine, MillerLoopResult, MultiMillerLoop};
|
||||
|
||||
use ff::{BitIterator, Field, PrimeField};
|
||||
use group::{prime::PrimeCurveAffine, Group};
|
||||
use rand_core::RngCore;
|
||||
use std::fmt;
|
||||
use std::iter::Sum;
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use subtle::{Choice, ConditionallySelectable};
|
||||
|
||||
// The BLS parameter x for BLS12-381 is -0xd201000000010000
|
||||
const BLS_X: u64 = 0xd201000000010000;
|
||||
const BLS_X_IS_NEGATIVE: bool = true;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Gt(Fq12);
|
||||
|
||||
impl fmt::Display for Gt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConditionallySelectable for Gt {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
Gt(Fq12::conditional_select(&a.0, &b.0, choice))
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Gt {
|
||||
type Output = Gt;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
let mut ret = self.0;
|
||||
ret.conjugate();
|
||||
Gt(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sum for Gt {
|
||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::identity(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Sum<&'r Gt> for Gt {
|
||||
fn sum<I: Iterator<Item = &'r Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::identity(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Gt {
|
||||
type Output = Gt;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Gt(self.0 * rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<&Gt> for Gt {
|
||||
type Output = Gt;
|
||||
|
||||
fn add(self, rhs: &Gt) -> Self::Output {
|
||||
Gt(self.0 * rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Gt {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.0 *= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<&Gt> for Gt {
|
||||
fn add_assign(&mut self, rhs: &Gt) {
|
||||
self.0 *= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Gt {
|
||||
type Output = Gt;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
self + (-rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<&Gt> for Gt {
|
||||
type Output = Gt;
|
||||
|
||||
fn sub(self, rhs: &Gt) -> Self::Output {
|
||||
self + (-*rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Gt {
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
*self = *self - rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign<&Gt> for Gt {
|
||||
fn sub_assign(&mut self, rhs: &Gt) {
|
||||
*self = *self - rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<&Fr> for Gt {
|
||||
type Output = Gt;
|
||||
|
||||
fn mul(self, other: &Fr) -> Self::Output {
|
||||
let mut acc = Self::identity();
|
||||
|
||||
// This is a simple double-and-add implementation of group element
|
||||
// multiplication, moving from most significant to least
|
||||
// significant bit of the scalar.
|
||||
//
|
||||
// We skip the leading bit because it's always unset for Fr
|
||||
// elements.
|
||||
for bit in other
|
||||
.to_repr()
|
||||
.as_ref()
|
||||
.iter()
|
||||
.rev()
|
||||
.flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
|
||||
.skip(1)
|
||||
{
|
||||
acc = acc.double();
|
||||
acc = Gt::conditional_select(&acc, &(acc + self), bit);
|
||||
}
|
||||
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Fr> for Gt {
|
||||
type Output = Gt;
|
||||
|
||||
fn mul(self, other: Fr) -> Self::Output {
|
||||
self * &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> MulAssign<&'r Fr> for Gt {
|
||||
fn mul_assign(&mut self, other: &'r Fr) {
|
||||
*self = *self * other
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<Fr> for Gt {
|
||||
fn mul_assign(&mut self, other: Fr) {
|
||||
self.mul_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl Group for Gt {
|
||||
type Scalar = Fr;
|
||||
|
||||
fn random<R: RngCore + ?Sized>(_rng: &mut R) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn identity() -> Self {
|
||||
Gt(Fq12::one())
|
||||
}
|
||||
|
||||
fn generator() -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn is_identity(&self) -> Choice {
|
||||
Choice::from(if self.0 == Fq12::one() { 1 } else { 0 })
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn double(&self) -> Self {
|
||||
Gt(self.0.square())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Bls12;
|
||||
|
||||
impl Engine for Bls12 {
|
||||
type Fr = Fr;
|
||||
type G1 = G1;
|
||||
type G1Affine = G1Affine;
|
||||
type G2 = G2;
|
||||
type G2Affine = G2Affine;
|
||||
type Gt = Gt;
|
||||
|
||||
fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
|
||||
Self::multi_miller_loop(&[(p, &(*q).into())]).final_exponentiation()
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiMillerLoop for Bls12 {
|
||||
type G2Prepared = G2Prepared;
|
||||
type Result = Fq12;
|
||||
|
||||
fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result {
|
||||
let mut pairs = vec![];
|
||||
for &(p, q) in terms {
|
||||
if !bool::from(p.is_identity()) && !q.is_identity() {
|
||||
pairs.push((p, q.coeffs.iter()));
|
||||
}
|
||||
}
|
||||
|
||||
// Twisting isomorphism from E to E'
|
||||
fn ell(f: &mut Fq12, coeffs: &(Fq2, Fq2, Fq2), p: &G1Affine) {
|
||||
let mut c0 = coeffs.0;
|
||||
let mut c1 = coeffs.1;
|
||||
|
||||
c0.c0.mul_assign(&p.y);
|
||||
c0.c1.mul_assign(&p.y);
|
||||
|
||||
c1.c0.mul_assign(&p.x);
|
||||
c1.c1.mul_assign(&p.x);
|
||||
|
||||
// Sparse multiplication in Fq12
|
||||
f.mul_by_014(&coeffs.2, &c1, &c0);
|
||||
}
|
||||
|
||||
let mut f = Fq12::one();
|
||||
|
||||
let mut found_one = false;
|
||||
for i in BitIterator::<u64, _>::new(&[BLS_X >> 1]) {
|
||||
if !found_one {
|
||||
found_one = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
for &mut (p, ref mut coeffs) in &mut pairs {
|
||||
ell(&mut f, coeffs.next().unwrap(), p);
|
||||
}
|
||||
|
||||
if i {
|
||||
for &mut (p, ref mut coeffs) in &mut pairs {
|
||||
ell(&mut f, coeffs.next().unwrap(), p);
|
||||
}
|
||||
}
|
||||
|
||||
f = f.square();
|
||||
}
|
||||
|
||||
for &mut (p, ref mut coeffs) in &mut pairs {
|
||||
ell(&mut f, coeffs.next().unwrap(), p);
|
||||
}
|
||||
|
||||
if BLS_X_IS_NEGATIVE {
|
||||
f.conjugate();
|
||||
}
|
||||
|
||||
f
|
||||
}
|
||||
}
|
||||
|
||||
impl MillerLoopResult for Fq12 {
|
||||
type Gt = Gt;
|
||||
|
||||
fn final_exponentiation(&self) -> Gt {
|
||||
let mut f1 = *self;
|
||||
f1.conjugate();
|
||||
|
||||
self.invert()
|
||||
.map(|mut f2| {
|
||||
let mut r = f1;
|
||||
r.mul_assign(&f2);
|
||||
f2 = r;
|
||||
r.frobenius_map(2);
|
||||
r.mul_assign(&f2);
|
||||
|
||||
fn exp_by_x(f: &mut Fq12, x: u64) {
|
||||
*f = f.pow_vartime(&[x]);
|
||||
if BLS_X_IS_NEGATIVE {
|
||||
f.conjugate();
|
||||
}
|
||||
}
|
||||
|
||||
let mut x = BLS_X;
|
||||
let y0 = r.square();
|
||||
let mut y1 = y0;
|
||||
exp_by_x(&mut y1, x);
|
||||
x >>= 1;
|
||||
let mut y2 = y1;
|
||||
exp_by_x(&mut y2, x);
|
||||
x <<= 1;
|
||||
let mut y3 = r;
|
||||
y3.conjugate();
|
||||
y1.mul_assign(&y3);
|
||||
y1.conjugate();
|
||||
y1.mul_assign(&y2);
|
||||
y2 = y1;
|
||||
exp_by_x(&mut y2, x);
|
||||
y3 = y2;
|
||||
exp_by_x(&mut y3, x);
|
||||
y1.conjugate();
|
||||
y3.mul_assign(&y1);
|
||||
y1.conjugate();
|
||||
y1.frobenius_map(3);
|
||||
y2.frobenius_map(2);
|
||||
y1.mul_assign(&y2);
|
||||
y2 = y3;
|
||||
exp_by_x(&mut y2, x);
|
||||
y2.mul_assign(&y0);
|
||||
y2.mul_assign(&r);
|
||||
y1.mul_assign(&y2);
|
||||
y2 = y3;
|
||||
y2.frobenius_map(1);
|
||||
y1.mul_assign(&y2);
|
||||
|
||||
Gt(y1)
|
||||
})
|
||||
// self must be nonzero.
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl G2Prepared {
|
||||
pub fn is_identity(&self) -> bool {
|
||||
self.infinity
|
||||
}
|
||||
|
||||
pub fn from_affine(q: G2Affine) -> Self {
|
||||
if q.is_identity().into() {
|
||||
return G2Prepared {
|
||||
coeffs: vec![],
|
||||
infinity: true,
|
||||
};
|
||||
}
|
||||
|
||||
fn doubling_step(r: &mut G2) -> (Fq2, Fq2, Fq2) {
|
||||
// Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf
|
||||
let mut tmp0 = r.x.square();
|
||||
|
||||
let mut tmp1 = r.y.square();
|
||||
|
||||
let mut tmp2 = tmp1.square();
|
||||
|
||||
let mut tmp3 = tmp1;
|
||||
tmp3.add_assign(&r.x);
|
||||
tmp3 = tmp3.square();
|
||||
tmp3.sub_assign(&tmp0);
|
||||
tmp3.sub_assign(&tmp2);
|
||||
tmp3 = tmp3.double();
|
||||
|
||||
let mut tmp4 = tmp0.double();
|
||||
tmp4.add_assign(&tmp0);
|
||||
|
||||
let mut tmp6 = r.x;
|
||||
tmp6.add_assign(&tmp4);
|
||||
|
||||
let tmp5 = tmp4.square();
|
||||
|
||||
let zsquared = r.z.square();
|
||||
|
||||
r.x = tmp5;
|
||||
r.x.sub_assign(&tmp3);
|
||||
r.x.sub_assign(&tmp3);
|
||||
|
||||
r.z.add_assign(&r.y);
|
||||
r.z = r.z.square();
|
||||
r.z.sub_assign(&tmp1);
|
||||
r.z.sub_assign(&zsquared);
|
||||
|
||||
r.y = tmp3;
|
||||
r.y.sub_assign(&r.x);
|
||||
r.y.mul_assign(&tmp4);
|
||||
|
||||
tmp2 = tmp2.double().double().double();
|
||||
|
||||
r.y.sub_assign(&tmp2);
|
||||
|
||||
tmp3 = tmp4;
|
||||
tmp3.mul_assign(&zsquared);
|
||||
tmp3 = tmp3.double().neg();
|
||||
|
||||
tmp6 = tmp6.square();
|
||||
tmp6.sub_assign(&tmp0);
|
||||
tmp6.sub_assign(&tmp5);
|
||||
|
||||
tmp1 = tmp1.double().double();
|
||||
|
||||
tmp6.sub_assign(&tmp1);
|
||||
|
||||
tmp0 = r.z;
|
||||
tmp0.mul_assign(&zsquared);
|
||||
tmp0 = tmp0.double();
|
||||
|
||||
(tmp0, tmp3, tmp6)
|
||||
}
|
||||
|
||||
fn addition_step(r: &mut G2, q: &G2Affine) -> (Fq2, Fq2, Fq2) {
|
||||
// Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf
|
||||
let zsquared = r.z.square();
|
||||
|
||||
let ysquared = q.y.square();
|
||||
|
||||
let mut t0 = zsquared;
|
||||
t0.mul_assign(&q.x);
|
||||
|
||||
let mut t1 = q.y;
|
||||
t1.add_assign(&r.z);
|
||||
t1 = t1.square();
|
||||
t1.sub_assign(&ysquared);
|
||||
t1.sub_assign(&zsquared);
|
||||
t1.mul_assign(&zsquared);
|
||||
|
||||
let mut t2 = t0;
|
||||
t2.sub_assign(&r.x);
|
||||
|
||||
let t3 = t2.square();
|
||||
|
||||
let t4 = t3.double().double();
|
||||
|
||||
let mut t5 = t4;
|
||||
t5.mul_assign(&t2);
|
||||
|
||||
let mut t6 = t1;
|
||||
t6.sub_assign(&r.y);
|
||||
t6.sub_assign(&r.y);
|
||||
|
||||
let mut t9 = t6;
|
||||
t9.mul_assign(&q.x);
|
||||
|
||||
let mut t7 = t4;
|
||||
t7.mul_assign(&r.x);
|
||||
|
||||
r.x = t6.square();
|
||||
r.x.sub_assign(&t5);
|
||||
r.x.sub_assign(&t7);
|
||||
r.x.sub_assign(&t7);
|
||||
|
||||
r.z.add_assign(&t2);
|
||||
r.z = r.z.square();
|
||||
r.z.sub_assign(&zsquared);
|
||||
r.z.sub_assign(&t3);
|
||||
|
||||
let mut t10 = q.y;
|
||||
t10.add_assign(&r.z);
|
||||
|
||||
let mut t8 = t7;
|
||||
t8.sub_assign(&r.x);
|
||||
t8.mul_assign(&t6);
|
||||
|
||||
t0 = r.y;
|
||||
t0.mul_assign(&t5);
|
||||
t0 = t0.double();
|
||||
|
||||
r.y = t8;
|
||||
r.y.sub_assign(&t0);
|
||||
|
||||
t10 = t10.square();
|
||||
t10.sub_assign(&ysquared);
|
||||
|
||||
let ztsquared = r.z.square();
|
||||
|
||||
t10.sub_assign(&ztsquared);
|
||||
|
||||
t9 = t9.double();
|
||||
t9.sub_assign(&t10);
|
||||
|
||||
t10 = r.z.double();
|
||||
|
||||
t6 = t6.neg();
|
||||
|
||||
t1 = t6.double();
|
||||
|
||||
(t10, t1, t9)
|
||||
}
|
||||
|
||||
let mut coeffs = vec![];
|
||||
let mut r: G2 = q.into();
|
||||
|
||||
let mut found_one = false;
|
||||
for i in BitIterator::<u64, _>::new([BLS_X >> 1]) {
|
||||
if !found_one {
|
||||
found_one = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
coeffs.push(doubling_step(&mut r));
|
||||
|
||||
if i {
|
||||
coeffs.push(addition_step(&mut r, &q));
|
||||
}
|
||||
}
|
||||
|
||||
coeffs.push(doubling_step(&mut r));
|
||||
|
||||
G2Prepared {
|
||||
coeffs,
|
||||
infinity: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bls12_engine_tests() {
|
||||
crate::tests::engine::engine_tests::<Bls12>();
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,645 +0,0 @@
|
|||
use ff::PrimeField;
|
||||
use group::{GroupEncoding, UncompressedEncoding};
|
||||
|
||||
use super::*;
|
||||
use crate::*;
|
||||
|
||||
#[test]
|
||||
fn test_pairing_result_against_relic() {
|
||||
/*
|
||||
Sent to me from Diego Aranha (author of RELIC library):
|
||||
|
||||
1250EBD871FC0A92 A7B2D83168D0D727 272D441BEFA15C50 3DD8E90CE98DB3E7 B6D194F60839C508 A84305AACA1789B6
|
||||
089A1C5B46E5110B 86750EC6A5323488 68A84045483C92B7 AF5AF689452EAFAB F1A8943E50439F1D 59882A98EAA0170F
|
||||
1368BB445C7C2D20 9703F239689CE34C 0378A68E72A6B3B2 16DA0E22A5031B54 DDFF57309396B38C 881C4C849EC23E87
|
||||
193502B86EDB8857 C273FA075A505129 37E0794E1E65A761 7C90D8BD66065B1F FFE51D7A579973B1 315021EC3C19934F
|
||||
01B2F522473D1713 91125BA84DC4007C FBF2F8DA752F7C74 185203FCCA589AC7 19C34DFFBBAAD843 1DAD1C1FB597AAA5
|
||||
018107154F25A764 BD3C79937A45B845 46DA634B8F6BE14A 8061E55CCEBA478B 23F7DACAA35C8CA7 8BEAE9624045B4B6
|
||||
19F26337D205FB46 9CD6BD15C3D5A04D C88784FBB3D0B2DB DEA54D43B2B73F2C BB12D58386A8703E 0F948226E47EE89D
|
||||
06FBA23EB7C5AF0D 9F80940CA771B6FF D5857BAAF222EB95 A7D2809D61BFE02E 1BFD1B68FF02F0B8 102AE1C2D5D5AB1A
|
||||
11B8B424CD48BF38 FCEF68083B0B0EC5 C81A93B330EE1A67 7D0D15FF7B984E89 78EF48881E32FAC9 1B93B47333E2BA57
|
||||
03350F55A7AEFCD3 C31B4FCB6CE5771C C6A0E9786AB59733 20C806AD36082910 7BA810C5A09FFDD9 BE2291A0C25A99A2
|
||||
04C581234D086A99 02249B64728FFD21 A189E87935A95405 1C7CDBA7B3872629 A4FAFC05066245CB 9108F0242D0FE3EF
|
||||
0F41E58663BF08CF 068672CBD01A7EC7 3BACA4D72CA93544 DEFF686BFD6DF543 D48EAA24AFE47E1E FDE449383B676631
|
||||
*/
|
||||
|
||||
assert_eq!(Bls12::pairing(&G1Affine::generator(), &G2Affine::generator()), Gt(Fq12 {
|
||||
c0: Fq6 {
|
||||
c0: Fq2 {
|
||||
c0: Fq::from_str("2819105605953691245277803056322684086884703000473961065716485506033588504203831029066448642358042597501014294104502").unwrap(),
|
||||
c1: Fq::from_str("1323968232986996742571315206151405965104242542339680722164220900812303524334628370163366153839984196298685227734799").unwrap()
|
||||
},
|
||||
c1: Fq2 {
|
||||
c0: Fq::from_str("2987335049721312504428602988447616328830341722376962214011674875969052835043875658579425548512925634040144704192135").unwrap(),
|
||||
c1: Fq::from_str("3879723582452552452538684314479081967502111497413076598816163759028842927668327542875108457755966417881797966271311").unwrap()
|
||||
},
|
||||
c2: Fq2 {
|
||||
c0: Fq::from_str("261508182517997003171385743374653339186059518494239543139839025878870012614975302676296704930880982238308326681253").unwrap(),
|
||||
c1: Fq::from_str("231488992246460459663813598342448669854473942105054381511346786719005883340876032043606739070883099647773793170614").unwrap()
|
||||
}
|
||||
},
|
||||
c1: Fq6 {
|
||||
c0: Fq2 {
|
||||
c0: Fq::from_str("3993582095516422658773669068931361134188738159766715576187490305611759126554796569868053818105850661142222948198557").unwrap(),
|
||||
c1: Fq::from_str("1074773511698422344502264006159859710502164045911412750831641680783012525555872467108249271286757399121183508900634").unwrap()
|
||||
},
|
||||
c1: Fq2 {
|
||||
c0: Fq::from_str("2727588299083545686739024317998512740561167011046940249988557419323068809019137624943703910267790601287073339193943").unwrap(),
|
||||
c1: Fq::from_str("493643299814437640914745677854369670041080344349607504656543355799077485536288866009245028091988146107059514546594").unwrap()
|
||||
},
|
||||
c2: Fq2 {
|
||||
c0: Fq::from_str("734401332196641441839439105942623141234148957972407782257355060229193854324927417865401895596108124443575283868655").unwrap(),
|
||||
c1: Fq::from_str("2348330098288556420918672502923664952620152483128593484301759394583320358354186482723629999370241674973832318248497").unwrap()
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
fn uncompressed_test_vectors<G: PrimeCurve>(expected: &[u8])
|
||||
where
|
||||
G::Affine: UncompressedEncoding,
|
||||
{
|
||||
let mut e = G::identity();
|
||||
let encoded_len = <G::Affine as UncompressedEncoding>::Uncompressed::default()
|
||||
.as_ref()
|
||||
.len();
|
||||
|
||||
let mut v = vec![];
|
||||
{
|
||||
let mut expected = expected;
|
||||
for _ in 0..1000 {
|
||||
let e_affine = e.to_affine();
|
||||
let encoded = e_affine.to_uncompressed();
|
||||
v.extend_from_slice(encoded.as_ref());
|
||||
|
||||
let mut decoded = <G::Affine as UncompressedEncoding>::Uncompressed::default();
|
||||
decoded.as_mut().copy_from_slice(&expected[0..encoded_len]);
|
||||
expected = &expected[encoded_len..];
|
||||
let decoded = G::Affine::from_uncompressed(&decoded).unwrap();
|
||||
assert_eq!(e_affine, decoded);
|
||||
|
||||
e.add_assign(&G::generator());
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(&v[..], expected);
|
||||
}
|
||||
|
||||
fn compressed_test_vectors<G: PrimeCurve>(expected: &[u8]) {
|
||||
let mut e = G::identity();
|
||||
let encoded_len = <G::Affine as GroupEncoding>::Repr::default().as_ref().len();
|
||||
|
||||
let mut v = vec![];
|
||||
{
|
||||
let mut expected = expected;
|
||||
for _ in 0..1000 {
|
||||
let e_affine = e.to_affine();
|
||||
let encoded = e_affine.to_bytes();
|
||||
v.extend_from_slice(encoded.as_ref());
|
||||
|
||||
let mut decoded = <G::Affine as GroupEncoding>::Repr::default();
|
||||
decoded.as_mut().copy_from_slice(&expected[0..encoded_len]);
|
||||
expected = &expected[encoded_len..];
|
||||
let decoded = G::Affine::from_bytes(&decoded).unwrap();
|
||||
assert_eq!(e_affine, decoded);
|
||||
|
||||
e.add_assign(&G::generator());
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(&v[..], expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g1_uncompressed_valid_vectors() {
|
||||
uncompressed_test_vectors::<G1>(include_bytes!("g1_uncompressed_valid_test_vectors.dat"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g1_compressed_valid_vectors() {
|
||||
compressed_test_vectors::<G1>(include_bytes!("g1_compressed_valid_test_vectors.dat"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g2_uncompressed_valid_vectors() {
|
||||
uncompressed_test_vectors::<G2>(include_bytes!("g2_uncompressed_valid_test_vectors.dat"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g2_compressed_valid_vectors() {
|
||||
compressed_test_vectors::<G2>(include_bytes!("g2_compressed_valid_test_vectors.dat"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g1_uncompressed_invalid_vectors() {
|
||||
{
|
||||
let z = G1Affine::identity().to_uncompressed();
|
||||
|
||||
{
|
||||
let mut z = z;
|
||||
z.as_mut()[0] |= 0b1000_0000;
|
||||
if G1Affine::from_uncompressed(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because we expected an uncompressed point");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut z = z;
|
||||
z.as_mut()[0] |= 0b0010_0000;
|
||||
if G1Affine::from_uncompressed(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..G1Uncompressed::size() {
|
||||
let mut z = z;
|
||||
z.as_mut()[i] |= 0b0000_0001;
|
||||
if G1Affine::from_uncompressed(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let o = G1Affine::generator().to_uncompressed();
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
if G1Affine::from_uncompressed(&o).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because we expected an uncompressed point");
|
||||
}
|
||||
}
|
||||
|
||||
let m = Fq::char();
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[..48].copy_from_slice(m.as_ref());
|
||||
|
||||
if G1Affine::from_uncompressed(&o).is_none().into() {
|
||||
// x coordinate
|
||||
} else {
|
||||
panic!("should have rejected the point")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[48..].copy_from_slice(m.as_ref());
|
||||
|
||||
if G1Affine::from_uncompressed(&o).is_none().into() {
|
||||
// y coordinate
|
||||
} else {
|
||||
panic!("should have rejected the point")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let m = Fq::zero().to_repr();
|
||||
|
||||
let mut o = o;
|
||||
o.as_mut()[..48].copy_from_slice(m.as_ref());
|
||||
|
||||
if G1Affine::from_uncompressed(&o).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because it isn't on the curve")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
let mut x = Fq::one();
|
||||
|
||||
loop {
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq::from(4)); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
let y = x3b.sqrt();
|
||||
if y.is_some().into() {
|
||||
let y = y.unwrap();
|
||||
|
||||
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
|
||||
o.as_mut()[..48].copy_from_slice(x.to_repr().as_ref());
|
||||
o.as_mut()[48..].copy_from_slice(y.to_repr().as_ref());
|
||||
|
||||
if G1Affine::from_uncompressed(&o).is_none().into() {
|
||||
break;
|
||||
} else {
|
||||
panic!(
|
||||
"should have rejected the point because it isn't in the correct subgroup"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
x.add_assign(&Fq::one());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g2_uncompressed_invalid_vectors() {
|
||||
{
|
||||
let z = G2Affine::identity().to_uncompressed();
|
||||
|
||||
{
|
||||
let mut z = z;
|
||||
z.as_mut()[0] |= 0b1000_0000;
|
||||
if G2Affine::from_uncompressed(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because we expected an uncompressed point");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut z = z;
|
||||
z.as_mut()[0] |= 0b0010_0000;
|
||||
if G2Affine::from_uncompressed(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..G2Uncompressed::size() {
|
||||
let mut z = z;
|
||||
z.as_mut()[i] |= 0b0000_0001;
|
||||
if G2Affine::from_uncompressed(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let o = G2Affine::generator().to_uncompressed();
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
if G2Affine::from_uncompressed(&o).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because we expected an uncompressed point");
|
||||
}
|
||||
}
|
||||
|
||||
let m = Fq::char();
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[..48].copy_from_slice(m.as_ref());
|
||||
|
||||
if G2Affine::from_uncompressed(&o).is_none().into() {
|
||||
// x coordinate (c1)
|
||||
} else {
|
||||
panic!("should have rejected the point")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[48..96].copy_from_slice(m.as_ref());
|
||||
|
||||
if G2Affine::from_uncompressed(&o).is_none().into() {
|
||||
// x coordinate (c0)
|
||||
} else {
|
||||
panic!("should have rejected the point")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[96..144].copy_from_slice(m.as_ref());
|
||||
|
||||
if G2Affine::from_uncompressed(&o).is_none().into() {
|
||||
// y coordinate (c1)
|
||||
} else {
|
||||
panic!("should have rejected the point")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[144..].copy_from_slice(m.as_ref());
|
||||
|
||||
if G2Affine::from_uncompressed(&o).is_none().into() {
|
||||
// y coordinate (c0)
|
||||
} else {
|
||||
panic!("should have rejected the point")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let m = Fq::zero().to_repr();
|
||||
|
||||
let mut o = o;
|
||||
o.as_mut()[..48].copy_from_slice(m.as_ref());
|
||||
o.as_mut()[48..96].copy_from_slice(m.as_ref());
|
||||
|
||||
if G2Affine::from_uncompressed(&o).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because it isn't on the curve")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
let mut x = Fq2::one();
|
||||
|
||||
loop {
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq2 {
|
||||
c0: Fq::from(4),
|
||||
c1: Fq::from(4),
|
||||
}); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
let y = x3b.sqrt();
|
||||
if y.is_some().into() {
|
||||
let y = y.unwrap();
|
||||
|
||||
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
|
||||
o.as_mut()[..48].copy_from_slice(x.c1.to_repr().as_ref());
|
||||
o.as_mut()[48..96].copy_from_slice(x.c0.to_repr().as_ref());
|
||||
o.as_mut()[96..144].copy_from_slice(y.c1.to_repr().as_ref());
|
||||
o.as_mut()[144..].copy_from_slice(y.c0.to_repr().as_ref());
|
||||
|
||||
if G2Affine::from_uncompressed(&o).is_none().into() {
|
||||
break;
|
||||
} else {
|
||||
panic!(
|
||||
"should have rejected the point because it isn't in the correct subgroup"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
x.add_assign(&Fq2::one());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g1_compressed_invalid_vectors() {
|
||||
{
|
||||
let z = G1Affine::identity().to_bytes();
|
||||
|
||||
{
|
||||
let mut z = z;
|
||||
z.as_mut()[0] &= 0b0111_1111;
|
||||
if G1Affine::from_bytes(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because we expected a compressed point");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut z = z;
|
||||
z.as_mut()[0] |= 0b0010_0000;
|
||||
if G1Affine::from_bytes(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..G1Compressed::size() {
|
||||
let mut z = z;
|
||||
z.as_mut()[i] |= 0b0000_0001;
|
||||
if G1Affine::from_bytes(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let o = G1Affine::generator().to_bytes();
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[0] &= 0b0111_1111;
|
||||
if G1Affine::from_bytes(&o).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because we expected a compressed point");
|
||||
}
|
||||
}
|
||||
|
||||
let m = Fq::char();
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[..48].copy_from_slice(m.as_ref());
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
|
||||
if G1Affine::from_bytes(&o).is_none().into() {
|
||||
// x coordinate
|
||||
} else {
|
||||
panic!("should have rejected the point")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
let mut x = Fq::one();
|
||||
|
||||
loop {
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq::from(4)); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if x3b.sqrt().is_some().into() {
|
||||
x.add_assign(&Fq::one());
|
||||
} else {
|
||||
o.as_mut().copy_from_slice(x.to_repr().as_ref());
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
|
||||
if G1Affine::from_bytes(&o).is_none().into() {
|
||||
break;
|
||||
} else {
|
||||
panic!("should have rejected the point because it isn't on the curve")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
let mut x = Fq::one();
|
||||
|
||||
loop {
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq::from(4)); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if x3b.sqrt().is_some().into() {
|
||||
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
|
||||
o.as_mut().copy_from_slice(x.to_repr().as_ref());
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
|
||||
if G1Affine::from_bytes(&o).is_none().into() {
|
||||
break;
|
||||
} else {
|
||||
panic!(
|
||||
"should have rejected the point because it isn't in the correct subgroup"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
x.add_assign(&Fq::one());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g2_compressed_invalid_vectors() {
|
||||
{
|
||||
let z = G2Affine::identity().to_bytes();
|
||||
|
||||
{
|
||||
let mut z = z;
|
||||
z.as_mut()[0] &= 0b0111_1111;
|
||||
if G2Affine::from_bytes(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because we expected a compressed point");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut z = z;
|
||||
z.as_mut()[0] |= 0b0010_0000;
|
||||
if G2Affine::from_bytes(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..G2Compressed::size() {
|
||||
let mut z = z;
|
||||
z.as_mut()[i] |= 0b0000_0001;
|
||||
if G2Affine::from_bytes(&z).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let o = G2Affine::generator().to_bytes();
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[0] &= 0b0111_1111;
|
||||
if G2Affine::from_bytes(&o).is_none().into() {
|
||||
// :)
|
||||
} else {
|
||||
panic!("should have rejected the point because we expected a compressed point");
|
||||
}
|
||||
}
|
||||
|
||||
let m = Fq::char();
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[..48].copy_from_slice(m.as_ref());
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
|
||||
if G2Affine::from_bytes(&o).is_none().into() {
|
||||
// x coordinate (c1)
|
||||
} else {
|
||||
panic!("should have rejected the point")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
o.as_mut()[48..96].copy_from_slice(m.as_ref());
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
|
||||
if G2Affine::from_bytes(&o).is_none().into() {
|
||||
// x coordinate (c0)
|
||||
} else {
|
||||
panic!("should have rejected the point")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
let mut x = Fq2 {
|
||||
c0: Fq::one(),
|
||||
c1: Fq::one(),
|
||||
};
|
||||
|
||||
loop {
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq2 {
|
||||
c0: Fq::from(4),
|
||||
c1: Fq::from(4),
|
||||
}); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if x3b.sqrt().is_some().into() {
|
||||
x.add_assign(&Fq2::one());
|
||||
} else {
|
||||
o.as_mut()[..48].copy_from_slice(x.c1.to_repr().as_ref());
|
||||
o.as_mut()[48..].copy_from_slice(x.c0.to_repr().as_ref());
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
|
||||
if G2Affine::from_bytes(&o).is_none().into() {
|
||||
break;
|
||||
} else {
|
||||
panic!("should have rejected the point because it isn't on the curve")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut o = o;
|
||||
let mut x = Fq2 {
|
||||
c0: Fq::one(),
|
||||
c1: Fq::one(),
|
||||
};
|
||||
|
||||
loop {
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq2 {
|
||||
c0: Fq::from(4),
|
||||
c1: Fq::from(4),
|
||||
}); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if x3b.sqrt().is_some().into() {
|
||||
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
|
||||
o.as_mut()[..48].copy_from_slice(x.c1.to_repr().as_ref());
|
||||
o.as_mut()[48..].copy_from_slice(x.c0.to_repr().as_ref());
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
|
||||
if G2Affine::from_bytes(&o).is_none().into() {
|
||||
break;
|
||||
} else {
|
||||
panic!(
|
||||
"should have rejected the point because it isn't in the correct subgroup"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
x.add_assign(&Fq2::one());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,8 +18,6 @@
|
|||
#[cfg(test)]
|
||||
pub mod tests;
|
||||
|
||||
pub mod bls12_381;
|
||||
|
||||
use core::ops::Mul;
|
||||
use ff::PrimeField;
|
||||
use group::{
|
||||
|
|
Loading…
Reference in New Issue