macro_rules! curve_impl {
(
$name:expr,
$projective:ident,
$affine:ident,
$prepared:ident,
$basefield:ident,
$scalarfield:ident,
$uncompressed:ident,
$compressed:ident,
$pairing:ident
) => {
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct $affine {
pub(crate) x: $basefield,
pub(crate) y: $basefield,
}
impl ::std::fmt::Display for $affine
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
if self.x.is_zero() && self.y.is_zero() {
write!(f, "{}(Infinity)", $name)
} else {
write!(f, "{}(x={}, y={})", $name, self.x, self.y)
}
}
}
#[derive(Copy, Clone, Debug, Eq)]
pub struct $projective {
pub(crate) x: $basefield,
pub(crate) y: $basefield,
pub(crate) z: $basefield
}
impl ::std::fmt::Display for $projective
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "{}", self.into_affine())
}
}
impl PartialEq for $projective {
fn eq(&self, other: &$projective) -> bool {
if self.is_zero() {
return other.is_zero();
}
if other.is_zero() {
return false;
}
let mut z1 = self.z;
z1.square();
let mut z2 = other.z;
z2.square();
let mut tmp1 = self.x;
tmp1.mul_assign(&z2);
let mut tmp2 = other.x;
tmp2.mul_assign(&z1);
if tmp1 != tmp2 {
return false;
}
z1.mul_assign(&self.z);
z2.mul_assign(&other.z);
z2.mul_assign(&self.y);
z1.mul_assign(&other.y);
if z1 != z2 {
return false;
}
true
}
}
impl $affine {
fn mul_bits<S: AsRef<[u64]>>(&self, bits: BitIterator<S>) -> $projective {
let mut res = $projective::zero();
for i in bits {
res.double();
if i { res.add_assign_mixed(self) }
}
res
}
fn get_point_from_x(x: $basefield, greatest: bool) -> Option<$affine> {
let mut x3b = x;
x3b.square();
x3b.mul_assign(&x);
x3b.add_assign(&$affine::get_coeff_b());
x3b.sqrt().map(|y| {
let mut negy = y;
negy.negate();
$affine {
x: x,
y: if (y < negy) ^ greatest {
y
} else {
negy
},
}
})
}
fn is_on_curve(&self) -> bool {
if self.is_zero() {
true
} else {
let mut y2 = self.y;
y2.square();
let mut x3b = self.x;
x3b.square();
x3b.mul_assign(&self.x);
x3b.add_assign(&Self::get_coeff_b());
y2 == x3b
}
}
}
impl CurveAffine for $affine {
type Engine = Bn256;
type Scalar = $scalarfield;
type Base = $basefield;
type Prepared = $prepared;
type Projective = $projective;
type Uncompressed = $uncompressed;
type Compressed = $compressed;
type Pair = $pairing;
type PairingResult = Fq12;
fn zero() -> Self {
$affine {
x: $basefield::zero(),
y: $basefield::zero(),
}
}
fn one() -> Self {
Self::get_generator()
}
fn is_zero(&self) -> bool {
self.x.is_zero() && self.y.is_zero()
}
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, by: S) -> $projective {
let bits = BitIterator::new(by.into());
self.mul_bits(bits)
}
fn negate(&mut self) {
if !self.is_zero() {
self.y.negate();
}
}
fn prepare(&self) -> Self::Prepared {
$prepared::from_affine(*self)
}
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
self.perform_pairing(other)
}
fn into_projective(&self) -> $projective {
(*self).into()
}
#[inline(always)]
fn as_xy(&self) -> (&Self::Base, &Self::Base) {
(&self.x, &self.y)
}
#[inline(always)]
fn into_xy_unchecked(&self) -> (Self::Base, Self::Base) {
(self.x, self.y)
}
#[inline(always)]
fn from_xy_unchecked(x: Self::Base, y: Self::Base) -> Self {
Self {
x: x,
y: y,
}
}
fn from_xy_checked(x: Self::Base, y: Self::Base) -> Result<Self, GroupDecodingError> {
let affine = Self {
x: x,
y: y,
};
if !affine.is_on_curve() {
Err(GroupDecodingError::NotOnCurve)
} else {
Ok(affine)
}
}
}
impl CurveProjective for $projective {
type Engine = Bn256;
type Scalar = $scalarfield;
type Base = $basefield;
type Affine = $affine;
fn zero() -> Self {
$projective {
x: $basefield::zero(),
y: $basefield::one(),
z: $basefield::zero()
}
}
fn one() -> Self {
$affine::one().into()
}
fn is_zero(&self) -> bool {
self.z.is_zero()
}
fn is_normalized(&self) -> bool {
self.is_zero() || self.z == $basefield::one()
}
fn batch_normalization(v: &mut [Self])
{
let mut prod = Vec::with_capacity(v.len());
let mut tmp = $basefield::one();
for g in v.iter_mut()
.filter(|g| !g.is_normalized())
{
tmp.mul_assign(&g.z);
prod.push(tmp);
}
tmp = tmp.inverse().unwrap();
for (g, s) in v.iter_mut()
.rev()
.filter(|g| !g.is_normalized())
.zip(prod.into_iter().rev().skip(1).chain(Some($basefield::one())))
{
let mut newtmp = tmp;
newtmp.mul_assign(&g.z);
g.z = tmp;
g.z.mul_assign(&s);
tmp = newtmp;
}
for g in v.iter_mut()
.filter(|g| !g.is_normalized())
{
let mut z = g.z;
z.square();
g.x.mul_assign(&z);
z.mul_assign(&g.z);
g.y.mul_assign(&z);
g.z = $basefield::one();
}
}
fn double(&mut self) {
if self.is_zero() {
return;
}
let mut a = self.x;
a.square();
let mut b = self.y;
b.square();
let mut c = b;
c.square();
let mut d = self.x;
d.add_assign(&b);
d.square();
d.sub_assign(&a);
d.sub_assign(&c);
d.double();
let mut e = a;
e.double();
e.add_assign(&a);
let mut f = e;
f.square();
self.z.mul_assign(&self.y);
self.z.double();
self.x = f;
self.x.sub_assign(&d);
self.x.sub_assign(&d);
self.y = d;
self.y.sub_assign(&self.x);
self.y.mul_assign(&e);
c.double();
c.double();
c.double();
self.y.sub_assign(&c);
}
fn add_assign(&mut self, other: &Self) {
if self.is_zero() {
*self = *other;
return;
}
if other.is_zero() {
return;
}
let mut z1z1 = self.z;
z1z1.square();
let mut z2z2 = other.z;
z2z2.square();
let mut u1 = self.x;
u1.mul_assign(&z2z2);
let mut u2 = other.x;
u2.mul_assign(&z1z1);
let mut s1 = self.y;
s1.mul_assign(&other.z);
s1.mul_assign(&z2z2);
let mut s2 = other.y;
s2.mul_assign(&self.z);
s2.mul_assign(&z1z1);
if u1 == u2 && s1 == s2 {
self.double();
} else {
if u1 == u2 {
(*self) = Self::zero();
return;
}
let mut h = u2;
h.sub_assign(&u1);
let mut i = h;
i.double();
i.square();
let mut j = h;
j.mul_assign(&i);
let mut r = s2;
r.sub_assign(&s1);
r.double();
let mut v = u1;
v.mul_assign(&i);
self.x = r;
self.x.square();
self.x.sub_assign(&j);
self.x.sub_assign(&v);
self.x.sub_assign(&v);
self.y = v;
self.y.sub_assign(&self.x);
self.y.mul_assign(&r);
s1.mul_assign(&j);
s1.double();
self.y.sub_assign(&s1);
self.z.add_assign(&other.z);
self.z.square();
self.z.sub_assign(&z1z1);
self.z.sub_assign(&z2z2);
self.z.mul_assign(&h);
}
}
fn add_assign_mixed(&mut self, other: &Self::Affine) {
if other.is_zero() {
return;
}
if self.is_zero() {
self.x = other.x;
self.y = other.y;
self.z = $basefield::one();
return;
}
let mut z1z1 = self.z;
z1z1.square();
let mut u2 = other.x;
u2.mul_assign(&z1z1);
let mut s2 = other.y;
s2.mul_assign(&self.z);
s2.mul_assign(&z1z1);
if self.x == u2 && self.y == s2 {
self.double();
} else {
let mut h = u2;
h.sub_assign(&self.x);
let mut hh = h;
hh.square();
let mut i = hh;
i.double();
i.double();
let mut j = h;
j.mul_assign(&i);
let mut r = s2;
r.sub_assign(&self.y);
r.double();
let mut v = self.x;
v.mul_assign(&i);
self.x = r;
self.x.square();
self.x.sub_assign(&j);
self.x.sub_assign(&v);
self.x.sub_assign(&v);
j.mul_assign(&self.y);
j.double();
self.y = v;
self.y.sub_assign(&self.x);
self.y.mul_assign(&r);
self.y.sub_assign(&j);
self.z.add_assign(&h);
self.z.square();
self.z.sub_assign(&z1z1);
self.z.sub_assign(&hh);
}
}
fn negate(&mut self) {
if !self.is_zero() {
self.y.negate()
}
}
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
let mut res = Self::zero();
let mut found_one = false;
for i in BitIterator::new(other.into())
{
if found_one {
res.double();
} else {
found_one = i;
}
if i {
res.add_assign(self);
}
}
*self = res;
}
fn into_affine(&self) -> $affine {
(*self).into()
}
fn recommended_wnaf_for_scalar(scalar: <Self::Scalar as PrimeField>::Repr) -> usize {
Self::empirical_recommended_wnaf_for_scalar(scalar)
}
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
Self::empirical_recommended_wnaf_for_num_scalars(num_scalars)
}
}
impl From<$affine> for $projective {
fn from(p: $affine) -> $projective {
if p.is_zero() {
$projective::zero()
} else {
$projective {
x: p.x,
y: p.y,
z: $basefield::one()
}
}
}
}
impl From<$projective> for $affine {
fn from(p: $projective) -> $affine {
if p.is_zero() {
$affine::zero()
} else if p.z == $basefield::one() {
$affine {
x: p.x,
y: p.y,
}
} else {
let zinv = p.z.inverse().unwrap();
let mut zinv_powered = zinv;
zinv_powered.square();
let mut x = p.x;
x.mul_assign(&zinv_powered);
let mut y = p.y;
zinv_powered.mul_assign(&zinv);
y.mul_assign(&zinv_powered);
$affine {
x: x,
y: y,
}
}
}
}
}
}
pub mod g1 {
use super::super::{Bn256, Fq, Fq12, FqRepr, Fr, FrRepr};
use super::g2::G2Affine;
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use rand::{Rand, Rng};
use std::fmt;
use crate::{RawEncodable, CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError};
curve_impl!(
"G1",
G1,
G1Affine,
G1Prepared,
Fq,
Fr,
G1Uncompressed,
G1Compressed,
G2Affine
);
impl RawEncodable for G1Affine {
fn into_raw_uncompressed_le(&self) -> Self::Uncompressed {
let mut res = Self::Uncompressed::empty();
{
let mut writer = &mut res.0[..];
self.x.into_raw_repr().write_le(&mut writer).unwrap();
self.y.into_raw_repr().write_le(&mut writer).unwrap();
}
res
}
fn from_raw_uncompressed_le_unchecked(
encoded: &Self::Uncompressed,
_infinity: bool
) -> Result<Self, GroupDecodingError> {
let copy = encoded.0;
if copy.iter().all(|b| *b == 0) {
return Ok(Self::zero());
}
let mut x = FqRepr([0; 4]);
let mut y = FqRepr([0; 4]);
{
let mut reader = ©[..];
x.read_le(&mut reader).unwrap();
y.read_le(&mut reader).unwrap();
}
Ok(G1Affine {
x: Fq::from_raw_repr(x).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("x coordinate", e)
})?,
y: Fq::from_raw_repr(y).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("y coordinate", e)
})?,
})
}
fn from_raw_uncompressed_le(encoded: &Self::Uncompressed, _infinity: bool) -> Result<Self, GroupDecodingError> {
let affine = Self::from_raw_uncompressed_le_unchecked(&encoded, _infinity)?;
if !affine.is_on_curve() {
Err(GroupDecodingError::NotOnCurve)
} else {
Ok(affine)
}
}
}
#[derive(Copy, Clone)]
pub struct G1Uncompressed([u8; 64]);
impl Rand for G1 {
fn rand<R: Rng>(rng: &mut R) -> Self {
loop {
let x = rng.gen();
let greatest = rng.gen();
if let Some(p) = G1Affine::get_point_from_x(x, greatest) {
if !p.is_zero() {
if p.is_on_curve() {
return p.into_projective();
}
}
}
}
}
}
impl Rand for G1Affine {
fn rand<R: Rng>(rng: &mut R) -> Self {
loop {
let x = rng.gen();
let greatest = rng.gen();
if let Some(p) = G1Affine::get_point_from_x(x, greatest) {
if !p.is_zero() {
if p.is_on_curve() {
return p;
}
}
}
}
}
}
impl AsRef<[u8]> for G1Uncompressed {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u8]> for G1Uncompressed {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl fmt::Debug for G1Uncompressed {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.0[..].fmt(formatter)
}
}
impl EncodedPoint for G1Uncompressed {
type Affine = G1Affine;
fn empty() -> Self {
G1Uncompressed([0; 64])
}
fn size() -> usize {
64
}
fn into_affine(&self) -> Result<G1Affine, GroupDecodingError> {
let affine = self.into_affine_unchecked()?;
if !affine.is_on_curve() {
Err(GroupDecodingError::NotOnCurve)
} else {
Ok(affine)
}
}
fn into_affine_unchecked(&self) -> Result<G1Affine, GroupDecodingError> {
let mut copy = self.0;
if copy[0] & (1 << 6) != 0 {
copy[0] &= 0x3f;
if copy.iter().all(|b| *b == 0) {
Ok(G1Affine::zero())
} else {
Err(GroupDecodingError::UnexpectedInformation)
}
} else {
if copy[0] & (1 << 7) != 0 {
return Err(GroupDecodingError::UnexpectedInformation);
}
copy[0] &= 0x3f;
let mut x = FqRepr([0; 4]);
let mut y = FqRepr([0; 4]);
{
let mut reader = ©[..];
x.read_be(&mut reader).unwrap();
y.read_be(&mut reader).unwrap();
}
Ok(G1Affine {
x: Fq::from_repr(x).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("x coordinate", e)
})?,
y: Fq::from_repr(y).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("y coordinate", e)
})?,
})
}
}
fn from_affine(affine: G1Affine) -> Self {
let mut res = Self::empty();
if affine.is_zero() {
res.0[0] |= 1 << 6;
} else {
let mut writer = &mut res.0[..];
affine.x.into_repr().write_be(&mut writer).unwrap();
affine.y.into_repr().write_be(&mut writer).unwrap();
}
res
}
}
#[derive(Copy, Clone)]
pub struct G1Compressed([u8; 32]);
impl AsRef<[u8]> for G1Compressed {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u8]> for G1Compressed {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl fmt::Debug for G1Compressed {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.0[..].fmt(formatter)
}
}
impl EncodedPoint for G1Compressed {
type Affine = G1Affine;
fn empty() -> Self {
G1Compressed([0; 32])
}
fn size() -> usize {
32
}
fn into_affine(&self) -> Result<G1Affine, GroupDecodingError> {
let affine = self.into_affine_unchecked()?;
Ok(affine)
}
fn into_affine_unchecked(&self) -> Result<G1Affine, GroupDecodingError> {
let mut copy = self.0;
if copy[0] & (1 << 6) != 0 {
copy[0] &= 0x3f;
if copy.iter().all(|b| *b == 0) {
Ok(G1Affine::zero())
} else {
Err(GroupDecodingError::UnexpectedInformation)
}
} else {
let greatest = copy[0] & (1 << 7) != 0;
copy[0] &= 0x3f;
let mut x = FqRepr([0; 4]);
{
let mut reader = ©[..];
x.read_be(&mut reader).unwrap();
}
let x = Fq::from_repr(x)
.map_err(|e| GroupDecodingError::CoordinateDecodingError("x coordinate", e))?;
G1Affine::get_point_from_x(x, greatest).ok_or(GroupDecodingError::NotOnCurve)
}
}
fn from_affine(affine: G1Affine) -> Self {
let mut res = Self::empty();
if affine.is_zero() {
res.0[0] |= 1 << 6;
} else {
{
let mut writer = &mut res.0[..];
affine.x.into_repr().write_be(&mut writer).unwrap();
}
let mut negy = affine.y;
negy.negate();
if affine.y > negy {
res.0[0] |= 1 << 7;
}
}
res
}
}
impl G1Affine {
fn get_generator() -> Self {
G1Affine {
x: super::super::fq::G1_GENERATOR_X,
y: super::super::fq::G1_GENERATOR_Y,
}
}
fn get_coeff_b() -> Fq {
super::super::fq::B_COEFF
}
fn perform_pairing(&self, other: &G2Affine) -> Fq12 {
super::super::Bn256::pairing(*self, *other)
}
}
impl G1 {
fn empirical_recommended_wnaf_for_scalar(scalar: FrRepr) -> usize {
let num_bits = scalar.num_bits() as usize;
if num_bits >= 130 {
4
} else if num_bits >= 34 {
3
} else {
2
}
}
fn empirical_recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
const RECOMMENDATIONS: [usize; 12] =
[1, 3, 7, 20, 43, 120, 273, 563, 1630, 3128, 7933, 62569];
let mut ret = 4;
for r in &RECOMMENDATIONS {
if num_scalars > *r {
ret += 1;
} else {
break;
}
}
ret
}
}
#[derive(Clone, Debug)]
pub struct G1Prepared(pub(crate) G1Affine);
impl G1Prepared {
pub fn is_zero(&self) -> bool {
self.0.is_zero()
}
pub fn from_affine(p: G1Affine) -> Self {
G1Prepared(p)
}
}
#[test]
fn g1_generator() {
use SqrtField;
let mut x = Fq::zero();
let mut i = 0;
loop {
let mut rhs = x;
rhs.square();
rhs.mul_assign(&x);
rhs.add_assign(&G1Affine::get_coeff_b());
if let Some(y) = rhs.sqrt() {
let yrepr = y.into_repr();
let mut negy = y;
negy.negate();
let negyrepr = negy.into_repr();
let p = G1Affine {
x: x,
y: if yrepr < negyrepr { y } else { negy },
};
let g1 = p.into_projective();
if !g1.is_zero() {
assert_eq!(i, 1);
let g1 = G1Affine::from(g1);
assert_eq!(g1, G1Affine::one());
break;
}
}
i += 1;
x.add_assign(&Fq::one());
}
}
#[test]
fn test_base_point_addition_and_doubling() {
let mut a = G1::one();
print!("{}\n\n", a);
a.add_assign(&G1::one());
print!("{}\n\n", a);
}
#[test]
fn g1_curve_tests() {
crate::tests::curve::curve_tests::<G1>();
crate::tests::curve::random_transformation_tests::<G1>();
}
}
pub mod g2 {
use super::super::{Bn256, Fq, Fq12, Fq2, FqRepr, Fr, FrRepr};
use super::g1::G1Affine;
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use rand::{Rand, Rng};
use std::fmt;
use crate::{CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError};
curve_impl!(
"G2",
G2,
G2Affine,
G2Prepared,
Fq2,
Fr,
G2Uncompressed,
G2Compressed,
G1Affine
);
impl Rand for G2 {
fn rand<R: Rng>(rng: &mut R) -> Self {
loop {
let x = rng.gen();
let greatest = rng.gen();
if let Some(p) = G2Affine::get_point_from_x(x, greatest) {
if !p.is_zero() {
if p.is_on_curve() {
return p.scale_by_cofactor();
}
}
}
}
}
}
impl Rand for G2Affine {
fn rand<R: Rng>(rng: &mut R) -> Self {
let r = G2::rand(rng);
return r.into_affine();
}
}
#[derive(Copy, Clone)]
pub struct G2Uncompressed([u8; 128]);
impl AsRef<[u8]> for G2Uncompressed {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u8]> for G2Uncompressed {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl fmt::Debug for G2Uncompressed {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.0[..].fmt(formatter)
}
}
impl EncodedPoint for G2Uncompressed {
type Affine = G2Affine;
fn empty() -> Self {
G2Uncompressed([0; 128])
}
fn size() -> usize {
128
}
fn into_affine(&self) -> Result<G2Affine, GroupDecodingError> {
let affine = self.into_affine_unchecked()?;
if !affine.is_on_curve() {
Err(GroupDecodingError::NotOnCurve)
} else {
Ok(affine)
}
}
fn into_affine_unchecked(&self) -> Result<G2Affine, GroupDecodingError> {
let mut copy = self.0;
if copy[0] & (1 << 7) != 0 {
return Err(GroupDecodingError::UnexpectedCompressionMode);
}
if copy[0] & (1 << 6) != 0 {
copy[0] &= 0x3f;
if copy.iter().all(|b| *b == 0) {
Ok(G2Affine::zero())
} else {
Err(GroupDecodingError::UnexpectedInformation)
}
} else {
copy[0] &= 0x3f;
let mut x_c0 = FqRepr([0; 4]);
let mut x_c1 = FqRepr([0; 4]);
let mut y_c0 = FqRepr([0; 4]);
let mut y_c1 = FqRepr([0; 4]);
{
let mut reader = ©[..];
x_c1.read_be(&mut reader).unwrap();
x_c0.read_be(&mut reader).unwrap();
y_c1.read_be(&mut reader).unwrap();
y_c0.read_be(&mut reader).unwrap();
}
Ok(G2Affine {
x: Fq2 {
c0: Fq::from_repr(x_c0).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("x coordinate (c0)", e)
})?,
c1: Fq::from_repr(x_c1).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("x coordinate (c1)", e)
})?,
},
y: Fq2 {
c0: Fq::from_repr(y_c0).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("y coordinate (c0)", e)
})?,
c1: Fq::from_repr(y_c1).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("y coordinate (c1)", e)
})?,
},
})
}
}
fn from_affine(affine: G2Affine) -> Self {
let mut res = Self::empty();
if affine.is_zero() {
res.0[0] |= 1 << 6;
} else {
let mut writer = &mut res.0[..];
affine.x.c1.into_repr().write_be(&mut writer).unwrap();
affine.x.c0.into_repr().write_be(&mut writer).unwrap();
affine.y.c1.into_repr().write_be(&mut writer).unwrap();
affine.y.c0.into_repr().write_be(&mut writer).unwrap();
}
res
}
}
#[derive(Copy, Clone)]
pub struct G2Compressed([u8; 64]);
impl AsRef<[u8]> for G2Compressed {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u8]> for G2Compressed {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl fmt::Debug for G2Compressed {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.0[..].fmt(formatter)
}
}
impl EncodedPoint for G2Compressed {
type Affine = G2Affine;
fn empty() -> Self {
G2Compressed([0; 64])
}
fn size() -> usize {
64
}
fn into_affine(&self) -> Result<G2Affine, GroupDecodingError> {
let affine = self.into_affine_unchecked()?;
Ok(affine)
}
fn into_affine_unchecked(&self) -> Result<G2Affine, GroupDecodingError> {
let mut copy = self.0;
if copy[0] & (1 << 6) != 0 {
copy[0] &= 0x3f;
if copy.iter().all(|b| *b == 0) {
Ok(G2Affine::zero())
} else {
Err(GroupDecodingError::UnexpectedInformation)
}
} else {
let greatest = copy[0] & (1 << 7) != 0;
copy[0] &= 0x3f;
let mut x_c1 = FqRepr([0; 4]);
let mut x_c0 = FqRepr([0; 4]);
{
let mut reader = ©[..];
x_c1.read_be(&mut reader).unwrap();
x_c0.read_be(&mut reader).unwrap();
}
let x = Fq2 {
c0: Fq::from_repr(x_c0).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("x coordinate (c0)", e)
})?,
c1: Fq::from_repr(x_c1).map_err(|e| {
GroupDecodingError::CoordinateDecodingError("x coordinate (c1)", e)
})?,
};
G2Affine::get_point_from_x(x, greatest).ok_or(GroupDecodingError::NotOnCurve)
}
}
fn from_affine(affine: G2Affine) -> Self {
let mut res = Self::empty();
if affine.is_zero() {
res.0[0] |= 1 << 6;
} else {
{
let mut writer = &mut res.0[..];
affine.x.c1.into_repr().write_be(&mut writer).unwrap();
affine.x.c0.into_repr().write_be(&mut writer).unwrap();
}
let mut negy = affine.y;
negy.negate();
if affine.y > negy {
res.0[0] |= 1 << 7;
}
}
res
}
}
impl G2Affine {
fn scale_by_cofactor(&self) -> G2 {
let cofactor = BitIterator::new([
0x345f2299c0f9fa8d,
0x06ceecda572a2489,
0xb85045b68181585e,
0x30644e72e131a029,
]);
self.mul_bits(cofactor)
}
fn get_generator() -> Self {
G2Affine {
x: Fq2 {
c0: super::super::fq::G2_GENERATOR_X_C0,
c1: super::super::fq::G2_GENERATOR_X_C1,
},
y: Fq2 {
c0: super::super::fq::G2_GENERATOR_Y_C0,
c1: super::super::fq::G2_GENERATOR_Y_C1,
},
}
}
fn get_coeff_b() -> Fq2 {
super::super::fq::B_COEFF_FQ2
}
fn perform_pairing(&self, other: &G1Affine) -> Fq12 {
super::super::Bn256::pairing(*other, *self)
}
}
impl G2 {
fn empirical_recommended_wnaf_for_scalar(scalar: FrRepr) -> usize {
let num_bits = scalar.num_bits() as usize;
if num_bits >= 103 {
4
} else if num_bits >= 37 {
3
} else {
2
}
}
fn empirical_recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
const RECOMMENDATIONS: [usize; 11] =
[1, 3, 8, 20, 47, 126, 260, 826, 1501, 4555, 84071];
let mut ret = 4;
for r in &RECOMMENDATIONS {
if num_scalars > *r {
ret += 1;
} else {
break;
}
}
ret
}
}
#[derive(Clone, Debug)]
pub struct G2Prepared {
pub(crate) coeffs: Vec<(Fq2, Fq2, Fq2)>,
pub(crate) infinity: bool,
}
#[test]
fn g2_generator() {
use SqrtField;
let mut x = Fq2::zero();
let mut i = 0;
loop {
let mut rhs = x;
rhs.square();
rhs.mul_assign(&x);
rhs.add_assign(&G2Affine::get_coeff_b());
if let Some(y) = rhs.sqrt() {
let mut negy = y;
negy.negate();
let p = G2Affine {
x: x,
y: if y < negy { y } else { negy },
};
let g2 = p.into_projective();
if !g2.is_zero() {
assert_eq!(i, 0);
let g2 = G2Affine::from(g2);
assert_eq!(g2, G2Affine::one());
break;
}
}
i += 1;
x.add_assign(&Fq2::one());
}
}
#[test]
fn test_generate_g2_in_subgroup() {
use SqrtField;
let mut x = Fq2::zero();
loop {
let mut rhs = x;
rhs.square();
rhs.mul_assign(&x);
rhs.add_assign(&G2Affine::get_coeff_b());
if let Some(y) = rhs.sqrt() {
let mut negy = y;
negy.negate();
let p = G2Affine {
x: x,
y: if y < negy { y } else { negy },
};
let g2 = p.into_projective();
let mut minus_one = Fr::one();
minus_one.negate();
let mut expected_zero = p.mul(minus_one);
expected_zero.add_assign(&g2);
if !expected_zero.is_zero() {
let p = expected_zero.into_affine();
let scaled_by_cofactor = p.scale_by_cofactor();
if scaled_by_cofactor.is_zero() {
let g2 = G2Affine::from(expected_zero);
println!("Invalid subgroup point = {}", g2);
return;
}
}
}
x.add_assign(&Fq2::one());
}
}
#[cfg(test)]
use rand::{SeedableRng, XorShiftRng};
#[test]
fn g2_generator_on_curve() {
use SqrtField;
let gen = G2Affine::get_generator();
let x = gen.x;
let mut rhs = x;
rhs.square();
rhs.mul_assign(&x);
rhs.add_assign(&G2Affine::get_coeff_b());
if let Some(y) = rhs.sqrt() {
let mut negy = y;
negy.negate();
let p = G2Affine {
x: x,
y: if y < negy { y } else { negy },
};
assert_eq!(p.y, gen.y);
assert_eq!(p, G2Affine::one());
return;
}
panic!();
}
#[test]
fn g2_curve_tests() {
crate::tests::curve::curve_tests::<G2>();
crate::tests::curve::random_transformation_tests::<G2>();
}
#[test]
fn test_b_coeff() {
let b2 = G2Affine::get_coeff_b();
print!("{}\n\n", b2);
}
#[test]
fn test_base_point_addition_and_doubling() {
let mut two = G2::one();
two.add_assign(&G2::one());
let one = G2::one();
let mut three21 = two;
three21.add_assign(&one);
let mut three12 = one;
three12.add_assign(&two);
assert_eq!(three12, three21);
}
#[test]
fn test_addition_and_doubling() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..1000 {
let a = G2::rand(&mut rng);
assert!(a.into_affine().is_on_curve());
let b = G2::rand(&mut rng);
let c = G2::rand(&mut rng);
let a_affine = a.into_affine();
let b_affine = b.into_affine();
let c_affine = c.into_affine();
{
let mut aplusa = a;
aplusa.add_assign(&a);
let mut aplusamixed = a;
aplusamixed.add_assign_mixed(&a.into_affine());
let mut adouble = a;
adouble.double();
assert_eq!(aplusa, adouble);
assert_eq!(aplusamixed, adouble);
}
let mut ab = a;
ab.add_assign(&b);
let mut ba = b;
ba.add_assign(&a);
assert_eq!(ab, ba, "Addition should not depend on order");
let mut tmp = vec![G2::zero(); 6];
tmp[0] = a;
tmp[0].add_assign(&b);
tmp[0].add_assign(&c);
tmp[1] = b;
tmp[1].add_assign(&c);
tmp[1].add_assign(&a);
tmp[2] = a;
tmp[2].add_assign(&c);
tmp[2].add_assign(&b);
tmp[3] = a_affine.into_projective();
tmp[3].add_assign_mixed(&b_affine);
tmp[3].add_assign_mixed(&c_affine);
tmp[4] = b_affine.into_projective();
tmp[4].add_assign_mixed(&c_affine);
tmp[4].add_assign_mixed(&a_affine);
tmp[5] = a_affine.into_projective();
tmp[5].add_assign_mixed(&c_affine);
tmp[5].add_assign_mixed(&b_affine);
for i in 0..6 {
for j in 0..6 {
assert_eq!(tmp[i], tmp[j]);
assert_eq!(tmp[i].into_affine(), tmp[j].into_affine());
}
assert!(tmp[i] != a);
assert!(tmp[i] != b);
assert!(tmp[i] != c);
assert!(a != tmp[i]);
assert!(b != tmp[i]);
assert!(c != tmp[i]);
}
}
}
#[test]
fn random_negation_tests() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..1000 {
let mut r = G2::one();
let k = Fr::rand(&mut rng);
r.mul_assign(k);
let s = Fr::rand(&mut rng);
let mut sneg = s;
sneg.negate();
let mut t1 = r;
t1.mul_assign(s);
let mut t2 = r;
t2.mul_assign(sneg);
let mut t3 = t1;
t3.add_assign(&t2);
assert!(t3.is_zero());
let mut t4 = t1;
t4.add_assign_mixed(&t2.into_affine());
assert!(t4.is_zero());
t1.negate();
assert_eq!(t1, t2);
}
}
#[test]
fn mul_by_order_tests() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..1000 {
let mut r = G2::one();
let k = Fr::rand(&mut rng);
r.mul_assign(k);
let order = Fr::char();
let mut q = G2::one();
q.mul_assign(order);
assert!(q.is_zero());
r.mul_assign(order);
assert!(r.is_zero());
let mut t = G2::rand(&mut rng);
t.mul_assign(order);
assert!(t.is_zero());
}
}
}
pub use self::g1::*;
pub use self::g2::*;