Merge pull request #244 from str4d/pairing-gt-fix
pairing: Bound Engine::Gt on Group instead of Field
This commit is contained in:
commit
7134ab8215
|
@ -367,7 +367,7 @@ macro_rules! curve_impl {
|
|||
|
||||
impl PairingCurveAffine for $affine {
|
||||
type Pair = $pairing;
|
||||
type PairingResult = Fq12;
|
||||
type PairingResult = Gt;
|
||||
|
||||
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
|
||||
self.perform_pairing(other)
|
||||
|
@ -1205,7 +1205,7 @@ impl fmt::Display for GroupDecodingError {
|
|||
}
|
||||
|
||||
pub mod g1 {
|
||||
use super::super::{Fq, Fq12, FqRepr, Fr};
|
||||
use super::super::{Fq, FqRepr, Fr, Gt};
|
||||
use super::{g2::G2Affine, GroupDecodingError};
|
||||
use crate::{Engine, PairingCurveAffine};
|
||||
use ff::{BitIterator, Field, PrimeField};
|
||||
|
@ -1446,7 +1446,7 @@ pub mod g1 {
|
|||
super::super::fq::B_COEFF
|
||||
}
|
||||
|
||||
fn perform_pairing(&self, other: &G2Affine) -> Fq12 {
|
||||
fn perform_pairing(&self, other: &G2Affine) -> Gt {
|
||||
super::super::Bls12::pairing(self, other)
|
||||
}
|
||||
}
|
||||
|
@ -1788,7 +1788,7 @@ pub mod g1 {
|
|||
}
|
||||
|
||||
pub mod g2 {
|
||||
use super::super::{Fq, Fq12, Fq2, FqRepr, Fr};
|
||||
use super::super::{Fq, Fq2, FqRepr, Fr, Gt};
|
||||
use super::{g1::G1Affine, GroupDecodingError};
|
||||
use crate::{Engine, PairingCurveAffine};
|
||||
use ff::{BitIterator, Field, PrimeField};
|
||||
|
@ -2078,7 +2078,7 @@ pub mod g2 {
|
|||
self.mul_bits_u64(cofactor)
|
||||
}
|
||||
|
||||
fn perform_pairing(&self, other: &G1Affine) -> Fq12 {
|
||||
fn perform_pairing(&self, other: &G1Affine) -> Gt {
|
||||
super::super::Bls12::pairing(other, self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,14 +23,184 @@ pub use self::fr::{Fr, FrRepr};
|
|||
|
||||
use super::{Engine, MillerLoopResult, MultiMillerLoop};
|
||||
|
||||
use ff::{BitIterator, Field};
|
||||
use group::cofactor::CofactorCurveAffine;
|
||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
use ff::{BitIterator, Field, PrimeField};
|
||||
use group::{cofactor::CofactorCurveAffine, 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;
|
||||
|
||||
|
@ -40,7 +210,7 @@ impl Engine for Bls12 {
|
|||
type G1Affine = G1Affine;
|
||||
type G2 = G2;
|
||||
type G2Affine = G2Affine;
|
||||
type Gt = Fq12;
|
||||
type Gt = Gt;
|
||||
|
||||
fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
|
||||
Self::multi_miller_loop(&[(p, &(*q).into())]).final_exponentiation()
|
||||
|
@ -109,9 +279,9 @@ impl MultiMillerLoop for Bls12 {
|
|||
}
|
||||
|
||||
impl MillerLoopResult for Fq12 {
|
||||
type Gt = Fq12;
|
||||
type Gt = Gt;
|
||||
|
||||
fn final_exponentiation(&self) -> Fq12 {
|
||||
fn final_exponentiation(&self) -> Gt {
|
||||
let mut f1 = *self;
|
||||
f1.conjugate();
|
||||
|
||||
|
@ -162,7 +332,7 @@ impl MillerLoopResult for Fq12 {
|
|||
y2.frobenius_map(1);
|
||||
y1.mul_assign(&y2);
|
||||
|
||||
y1
|
||||
Gt(y1)
|
||||
})
|
||||
// self must be nonzero.
|
||||
.unwrap()
|
||||
|
|
|
@ -26,7 +26,7 @@ fn test_pairing_result_against_relic() {
|
|||
0F41E58663BF08CF 068672CBD01A7EC7 3BACA4D72CA93544 DEFF686BFD6DF543 D48EAA24AFE47E1E FDE449383B676631
|
||||
*/
|
||||
|
||||
assert_eq!(Bls12::pairing(&G1Affine::generator(), &G2Affine::generator()), Fq12 {
|
||||
assert_eq!(Bls12::pairing(&G1Affine::generator(), &G2Affine::generator()), Gt(Fq12 {
|
||||
c0: Fq6 {
|
||||
c0: Fq2 {
|
||||
c0: Fq::from_str("2819105605953691245277803056322684086884703000473961065716485506033588504203831029066448642358042597501014294104502").unwrap(),
|
||||
|
@ -55,7 +55,7 @@ fn test_pairing_result_against_relic() {
|
|||
c1: Fq::from_str("2348330098288556420918672502923664952620152483128593484301759394583320358354186482723629999370241674973832318248497").unwrap()
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
fn uncompressed_test_vectors<G: CofactorCurve>(expected: &[u8])
|
||||
|
|
|
@ -21,10 +21,10 @@ pub mod tests;
|
|||
pub mod bls12_381;
|
||||
|
||||
use core::ops::Mul;
|
||||
use ff::{Field, PrimeField};
|
||||
use ff::PrimeField;
|
||||
use group::{
|
||||
cofactor::{CofactorCurve, CofactorCurveAffine},
|
||||
GroupOps, GroupOpsOwned, ScalarMul, ScalarMulOwned, UncompressedEncoding,
|
||||
Group, GroupOps, GroupOpsOwned, ScalarMul, ScalarMulOwned, UncompressedEncoding,
|
||||
};
|
||||
|
||||
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
||||
|
@ -71,7 +71,7 @@ pub trait Engine: Sized + 'static + Clone {
|
|||
+ for<'a> Mul<&'a Self::Fr, Output = Self::G2>;
|
||||
|
||||
/// The extension field that hosts the target group of the pairing.
|
||||
type Gt: Field;
|
||||
type Gt: Group<Scalar = Self::Fr> + ScalarMul<Self::Fr> + ScalarMulOwned<Self::Fr>;
|
||||
|
||||
/// Invoke the pairing function `G1 x G2 -> Gt` without the use of precomputation and
|
||||
/// other optimizations.
|
||||
|
@ -82,7 +82,7 @@ pub trait Engine: Sized + 'static + Clone {
|
|||
/// to perform pairings.
|
||||
pub trait PairingCurveAffine: CofactorCurveAffine + UncompressedEncoding {
|
||||
type Pair: PairingCurveAffine<Pair = Self>;
|
||||
type PairingResult: Field;
|
||||
type PairingResult: Group;
|
||||
|
||||
/// Perform a pairing
|
||||
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
|
||||
|
@ -108,7 +108,7 @@ pub trait MultiMillerLoop: Engine {
|
|||
/// [`MillerLoopResult::final_exponentiation`] is called, which is also expensive.
|
||||
pub trait MillerLoopResult {
|
||||
/// The extension field that hosts the target group of the pairing.
|
||||
type Gt: Field;
|
||||
type Gt: Group;
|
||||
|
||||
/// This performs a "final exponentiation" routine to convert the result of a Miller
|
||||
/// loop into an element of [`MillerLoopResult::Gt`], so that it can be compared with
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use ff::{Endianness, Field, PrimeField};
|
||||
use ff::Field;
|
||||
use group::{cofactor::CofactorCurveAffine, Curve, Group};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::MulAssign;
|
||||
use std::ops::Mul;
|
||||
|
||||
use crate::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
|
||||
|
||||
|
@ -30,12 +30,12 @@ pub fn engine_tests<E: MultiMillerLoop>() {
|
|||
let d = E::G2::random(&mut rng).to_affine().into();
|
||||
|
||||
assert_eq!(
|
||||
E::Gt::one(),
|
||||
E::Gt::identity(),
|
||||
E::multi_miller_loop(&[(&z1, &b)]).final_exponentiation()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
E::Gt::one(),
|
||||
E::Gt::identity(),
|
||||
E::multi_miller_loop(&[(&a, &z2)]).final_exponentiation()
|
||||
);
|
||||
|
||||
|
@ -85,8 +85,7 @@ fn random_miller_loop_tests<E: MultiMillerLoop>() {
|
|||
let ab = E::pairing(&a, &b);
|
||||
let cd = E::pairing(&c, &d);
|
||||
|
||||
let mut abcd = ab;
|
||||
abcd.mul_assign(&cd);
|
||||
let abcd = ab + &cd;
|
||||
|
||||
let a = a;
|
||||
let b = b.into();
|
||||
|
@ -121,14 +120,9 @@ fn random_bilinearity_tests<E: Engine>() {
|
|||
let acbd = E::pairing(&ac, &bd);
|
||||
let adbc = E::pairing(&ad, &bc);
|
||||
|
||||
let mut cd = (c * &d).to_repr();
|
||||
<E::Fr as PrimeField>::ReprEndianness::toggle_little_endian(&mut cd);
|
||||
|
||||
use byteorder::ByteOrder;
|
||||
let mut cd_limbs = [0; 4];
|
||||
byteorder::LittleEndian::read_u64_into(cd.as_ref(), &mut cd_limbs);
|
||||
|
||||
let abcd = E::pairing(&a, &b).pow_vartime(cd_limbs);
|
||||
let ab = E::pairing(&a, &b);
|
||||
let cd = c * &d;
|
||||
let abcd = Mul::<E::Fr>::mul(ab, cd);
|
||||
|
||||
assert_eq!(acbd, adbc);
|
||||
assert_eq!(acbd, abcd);
|
||||
|
|
|
@ -17,7 +17,7 @@ bs58 = { version = "0.3", features = ["check"] }
|
|||
ff = { version = "0.6", path = "../ff" }
|
||||
hex = "0.3"
|
||||
pairing = { version = "0.16", path = "../pairing" }
|
||||
protobuf = "2"
|
||||
protobuf = "=2.14.0" # 2.15 has MSRV of 1.44.1
|
||||
subtle = "2"
|
||||
zcash_primitives = { version = "0.2", path = "../zcash_primitives" }
|
||||
|
||||
|
|
Loading…
Reference in New Issue