Clean up prime field representation.

This commit is contained in:
Sean Bowe 2017-06-17 18:57:56 -06:00
parent d4903f19fe
commit 5cf6acd21a
7 changed files with 144 additions and 178 deletions

View File

@ -112,10 +112,10 @@ macro_rules! curve_impl {
self.infinity self.infinity
} }
fn mul<S: Convert<[u64], $engine>>(&self, e: &$engine, other: &S) -> $name { fn mul<S: Convert<<$scalarfield as PrimeField<$engine>>::Repr, $engine>>(&self, e: &$engine, other: &S) -> $name {
let mut res = $name::zero(e); let mut res = $name::zero(e);
for i in BitIterator::from((*other.convert(e)).borrow()) for i in BitIterator::new((*other.convert(e)).borrow())
{ {
res.double(e); res.double(e);
@ -314,10 +314,10 @@ macro_rules! curve_impl {
} }
} }
fn mul_assign<S: Convert<[u64], $engine>>(&mut self, engine: &$engine, other: &S) { fn mul_assign<S: Convert<<$scalarfield as PrimeField<$engine>>::Repr, $engine>>(&mut self, engine: &$engine, other: &S) {
let mut res = Self::zero(engine); let mut res = Self::zero(engine);
for i in BitIterator::from((*other.convert(engine)).borrow()) for i in BitIterator::new((*other.convert(engine)).borrow())
{ {
res.double(engine); res.double(engine);

View File

@ -183,6 +183,7 @@ macro_rules! fp_impl {
engine = $engine:ident, engine = $engine:ident,
params = $params_field:ident : $params_name:ident, params = $params_field:ident : $params_name:ident,
arith = $arith_mod:ident, arith = $arith_mod:ident,
repr = $repr:ident,
limbs = $limbs:expr, limbs = $limbs:expr,
$($params:tt)* $($params:tt)*
) => { ) => {
@ -218,15 +219,72 @@ macro_rules! fp_impl {
#[repr(C)] #[repr(C)]
pub struct $name([u64; $limbs]); pub struct $name([u64; $limbs]);
#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct $repr([u64; $limbs]);
impl PrimeFieldRepr for $repr {
fn from_u64(a: u64) -> Self {
let mut tmp: [u64; $limbs] = Default::default();
tmp[0] = a;
$repr(tmp)
}
fn sub_noborrow(&mut self, other: &Self) {
$arith_mod::sub_noborrow(&mut self.0, &other.0);
}
fn add_nocarry(&mut self, other: &Self) {
$arith_mod::add_nocarry(&mut self.0, &other.0);
}
fn num_bits(&self) -> usize {
$arith_mod::num_bits(&self.0)
}
fn is_zero(&self) -> bool {
self.0.iter().all(|&e| e==0)
}
fn is_odd(&self) -> bool {
$arith_mod::odd(&self.0)
}
fn div2(&mut self) {
$arith_mod::div2(&mut self.0);
}
}
impl AsRef<[u64]> for $repr {
fn as_ref(&self) -> &[u64] {
&self.0
}
}
impl Ord for $repr {
fn cmp(&self, other: &$repr) -> Ordering {
if $arith_mod::lt(&self.0, &other.0) {
Ordering::Less
} else if self.0 == other.0 {
Ordering::Equal
} else {
Ordering::Greater
}
}
}
impl PartialOrd for $repr {
fn partial_cmp(&self, other: &$repr) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl fmt::Debug for $name impl fmt::Debug for $name
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
ENGINE.with(|e| { ENGINE.with(|e| {
let mut repr = self.into_repr(&e);
repr.reverse();
try!(write!(f, "Fp(0x")); try!(write!(f, "Fp(0x"));
for i in &repr { for i in self.into_repr(&e).0.iter().rev() {
try!(write!(f, "{:016x}", *i)); try!(write!(f, "{:016x}", *i));
} }
write!(f, ")") write!(f, ")")
@ -260,21 +318,21 @@ macro_rules! fp_impl {
} }
} }
impl Convert<[u64], $engine> for $name impl Convert<$repr, $engine> for $name
{ {
type Target = [u64; $limbs]; type Target = $repr;
fn convert(&self, engine: &$engine) -> Cow<[u64; $limbs]> { fn convert(&self, engine: &$engine) -> Cow<$repr> {
Cow::Owned(self.into_repr(engine)) Cow::Owned(self.into_repr(engine))
} }
} }
impl PrimeField<$engine> for $name impl PrimeField<$engine> for $name
{ {
type Repr = [u64; $limbs]; type Repr = $repr;
fn from_repr(engine: &$engine, repr: Self::Repr) -> Result<Self, ()> { fn from_repr(engine: &$engine, repr: Self::Repr) -> Result<Self, ()> {
let mut tmp = $name(repr); let mut tmp = $name(repr.0);
if $arith_mod::lt(&tmp.0, &engine.$params_field.modulus) { if $arith_mod::lt(&tmp.0, &engine.$params_field.modulus) {
tmp.mul_assign(engine, &engine.$params_field.r2); tmp.mul_assign(engine, &engine.$params_field.r2);
Ok(tmp) Ok(tmp)
@ -283,55 +341,17 @@ macro_rules! fp_impl {
} }
} }
fn repr_lt(a: &Self::Repr, b: &Self::Repr) -> bool {
$arith_mod::lt(a, b)
}
fn repr_sub_noborrow(a: &mut Self::Repr, b: &Self::Repr) {
$arith_mod::sub_noborrow(a, b);
}
fn repr_add_nocarry(a: &mut Self::Repr, b: &Self::Repr) {
$arith_mod::add_nocarry(a, b);
}
fn repr_num_bits(a: &Self::Repr) -> usize {
$arith_mod::num_bits(a)
}
fn repr_is_zero(a: &Self::Repr) -> bool {
a.iter().all(|&e| e==0)
}
fn repr_is_odd(a: &Self::Repr) -> bool {
$arith_mod::odd(a)
}
fn repr_least_significant_limb(a: &Self::Repr) -> u64 {
a[0]
}
fn repr_div2(a: &mut Self::Repr) {
$arith_mod::div2(a);
}
fn repr_from_u64(a: u64) -> Self::Repr {
let mut tmp = Self::Repr::default();
tmp[0] = a;
tmp
}
fn into_repr(&self, engine: &$engine) -> Self::Repr { fn into_repr(&self, engine: &$engine) -> Self::Repr {
let mut tmp = *self; let mut tmp = *self;
tmp.mul_assign(engine, &engine.$params_field.one); tmp.mul_assign(engine, &engine.$params_field.one);
tmp.0 $repr(tmp.0)
} }
fn from_u64(engine: &$engine, n: u64) -> Self { fn from_u64(engine: &$engine, n: u64) -> Self {
let mut r = [0; $limbs]; let mut r = [0; $limbs];
r[0] = n; r[0] = n;
Self::from_repr(engine, r).unwrap() Self::from_repr(engine, $repr(r)).unwrap()
} }
fn from_str(engine: &$engine, s: &str) -> Result<Self, ()> { fn from_str(engine: &$engine, s: &str) -> Result<Self, ()> {
@ -351,12 +371,8 @@ macro_rules! fp_impl {
Ok(res) Ok(res)
} }
fn bits(&self, engine: &$engine) -> BitIterator<Self::Repr> {
self.into_repr(engine).into()
}
fn char(engine: &$engine) -> Self::Repr { fn char(engine: &$engine) -> Self::Repr {
engine.$params_field.modulus $repr(engine.$params_field.modulus)
} }
fn num_bits(engine: &$engine) -> usize { fn num_bits(engine: &$engine) -> usize {
@ -495,19 +511,20 @@ macro_rules! fp_impl {
} }
mod $arith_mod { mod $arith_mod {
use super::BitIterator;
// Arithmetic // Arithmetic
#[allow(dead_code)] #[allow(dead_code)]
pub fn num_bits(v: &[u64; $limbs]) -> usize pub fn num_bits(v: &[u64; $limbs]) -> usize
{ {
// TODO: optimize let mut ret = 64 * $limbs;
for (i, b) in BitIterator::from(&v[..]).enumerate() { for i in v.iter().rev() {
if b { let leading = i.leading_zeros() as usize;
return ($limbs*64) - i; ret -= leading;
if leading != 64 {
break;
} }
} }
0 ret
} }
#[inline] #[inline]

View File

@ -1,6 +1,7 @@
use rand; use rand;
use std::fmt; use std::fmt;
use std::cmp::Ordering;
use std::borrow::Borrow; use std::borrow::Borrow;
use super::{ use super::{
Engine, Engine,
@ -9,6 +10,7 @@ use super::{
CurveAffine, CurveAffine,
CurveRepresentation, CurveRepresentation,
PrimeField, PrimeField,
PrimeFieldRepr,
Field, Field,
SnarkField, SnarkField,
SqrtField, SqrtField,
@ -62,6 +64,7 @@ fp_impl!(
engine = Bls381, engine = Bls381,
params = fqparams: FqParams, params = fqparams: FqParams,
arith = fq_arith, arith = fq_arith,
repr = FqRepr,
limbs = 6, limbs = 6,
// q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 // q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
modulus = [ 0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a ], modulus = [ 0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a ],
@ -81,6 +84,7 @@ fp_impl!(
engine = Bls381, engine = Bls381,
params = frparams: FrParams, params = frparams: FrParams,
arith = fr_arith, arith = fr_arith,
repr = FrRepr,
limbs = 4, limbs = 4,
// r = 52435875175126190479447740508185965837690552500527637822603658699938581184513 // r = 52435875175126190479447740508185965837690552500527637822603658699938581184513
modulus = [ 0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48 ], modulus = [ 0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48 ],
@ -375,8 +379,8 @@ impl CurveRepresentation<Bls381> for G1Uncompressed {
} }
Ok(G1Affine { Ok(G1Affine {
x: try!(Fq::from_repr(e, x)), x: try!(Fq::from_repr(e, FqRepr(x))),
y: try!(Fq::from_repr(e, y)), y: try!(Fq::from_repr(e, FqRepr(y))),
infinity: false infinity: false
}) })
} }
@ -411,12 +415,12 @@ impl CurveRepresentation<Bls381> for G2Uncompressed {
if let (Some(y_c1), y_c0) = fq_arith::divrem(&y, &e.fqparams.modulus) { if let (Some(y_c1), y_c0) = fq_arith::divrem(&y, &e.fqparams.modulus) {
return Ok(G2Affine { return Ok(G2Affine {
x: Fq2 { x: Fq2 {
c0: try!(Fq::from_repr(e, x_c0)), c0: try!(Fq::from_repr(e, FqRepr(x_c0))),
c1: try!(Fq::from_repr(e, x_c1)) c1: try!(Fq::from_repr(e, FqRepr(x_c1)))
}, },
y: Fq2 { y: Fq2 {
c0: try!(Fq::from_repr(e, y_c0)), c0: try!(Fq::from_repr(e, FqRepr(y_c0))),
c1: try!(Fq::from_repr(e, y_c1)) c1: try!(Fq::from_repr(e, FqRepr(y_c1)))
}, },
infinity: false infinity: false
}); });
@ -440,14 +444,14 @@ impl G1Uncompressed {
{ {
let mut tmp = &mut tmp[0..]; let mut tmp = &mut tmp[0..];
for &digit in p.x.into_repr(e).iter().rev() { for &digit in p.x.into_repr(e).0.iter().rev() {
tmp.write_u64::<BigEndian>(digit).unwrap(); tmp.write_u64::<BigEndian>(digit).unwrap();
} }
} }
{ {
let mut tmp = &mut tmp[48..]; let mut tmp = &mut tmp[48..];
for &digit in p.y.into_repr(e).iter().rev() { for &digit in p.y.into_repr(e).0.iter().rev() {
tmp.write_u64::<BigEndian>(digit).unwrap(); tmp.write_u64::<BigEndian>(digit).unwrap();
} }
} }
@ -469,8 +473,8 @@ impl G2Uncompressed {
{ {
let mut tmp = &mut tmp[0..]; let mut tmp = &mut tmp[0..];
let mut x = [0; 12]; let mut x = [0; 12];
fq_arith::mac3(&mut x, &p.x.c1.into_repr(e), &e.fqparams.modulus); fq_arith::mac3(&mut x, &p.x.c1.into_repr(e).0, &e.fqparams.modulus);
fq_arith::add_carry(&mut x, &p.x.c0.into_repr(e)); fq_arith::add_carry(&mut x, &p.x.c0.into_repr(e).0);
for &digit in x.iter().rev() { for &digit in x.iter().rev() {
tmp.write_u64::<BigEndian>(digit).unwrap(); tmp.write_u64::<BigEndian>(digit).unwrap();
@ -480,8 +484,8 @@ impl G2Uncompressed {
{ {
let mut tmp = &mut tmp[96..]; let mut tmp = &mut tmp[96..];
let mut y = [0; 12]; let mut y = [0; 12];
fq_arith::mac3(&mut y, &p.y.c1.into_repr(e), &e.fqparams.modulus); fq_arith::mac3(&mut y, &p.y.c1.into_repr(e).0, &e.fqparams.modulus);
fq_arith::add_carry(&mut y, &p.y.c0.into_repr(e)); fq_arith::add_carry(&mut y, &p.y.c0.into_repr(e).0);
for &digit in y.iter().rev() { for &digit in y.iter().rev() {
tmp.write_u64::<BigEndian>(digit).unwrap(); tmp.write_u64::<BigEndian>(digit).unwrap();
@ -690,7 +694,7 @@ impl G2Prepared {
let mut r = q.to_jacobian(e); let mut r = q.to_jacobian(e);
let mut found_one = false; let mut found_one = false;
for i in BitIterator::from([BLS_X >> 1]) { for i in BitIterator::new(&[BLS_X >> 1]) {
if !found_one { if !found_one {
found_one = i; found_one = i;
continue; continue;
@ -1004,7 +1008,7 @@ impl Engine for Bls381 {
let mut f = Fq12::one(self); let mut f = Fq12::one(self);
let mut found_one = false; let mut found_one = false;
for i in BitIterator::from([BLS_X >> 1]) { for i in BitIterator::new(&[BLS_X >> 1]) {
if !found_one { if !found_one {
found_one = i; found_one = i;
continue; continue;

View File

@ -12,8 +12,8 @@ pub mod wnaf;
pub trait Engine: Sized + Clone + Send + Sync pub trait Engine: Sized + Clone + Send + Sync
{ {
type Fq: PrimeField<Self>; type Fq: PrimeField<Self> + Convert<<Self::Fq as PrimeField<Self>>::Repr, Self>;
type Fr: SnarkField<Self>; type Fr: SnarkField<Self> + Convert<<Self::Fr as PrimeField<Self>>::Repr, Self>;
type Fqe: SqrtField<Self>; type Fqe: SqrtField<Self>;
type Fqk: Field<Self>; type Fqk: Field<Self>;
type G1: Curve<Self> + Convert<<Self::G1 as Curve<Self>>::Affine, Self>; type G1: Curve<Self> + Convert<<Self::G1 as Curve<Self>>::Affine, Self>;
@ -85,7 +85,7 @@ pub trait Curve<E: Engine>: Sized +
fn add_assign(&mut self, &E, other: &Self); fn add_assign(&mut self, &E, other: &Self);
fn sub_assign(&mut self, &E, other: &Self); fn sub_assign(&mut self, &E, other: &Self);
fn add_assign_mixed(&mut self, &E, other: &Self::Affine); fn add_assign_mixed(&mut self, &E, other: &Self::Affine);
fn mul_assign<S: Convert<[u64], E>>(&mut self, &E, other: &S); fn mul_assign<S: Convert<<E::Fr as PrimeField<E>>::Repr, E>>(&mut self, &E, other: &S);
fn optimal_window(&E, scalar_bits: usize) -> Option<usize>; fn optimal_window(&E, scalar_bits: usize) -> Option<usize>;
fn optimal_window_batch(&self, &E, scalars: usize) -> wnaf::WindowTable<E, Self>; fn optimal_window_batch(&self, &E, scalars: usize) -> wnaf::WindowTable<E, Self>;
@ -99,7 +99,7 @@ pub trait Curve<E: Engine>: Sized +
table: &mut wnaf::WindowTable<E, Self>, table: &mut wnaf::WindowTable<E, Self>,
scratch: &mut wnaf::WNAFTable scratch: &mut wnaf::WNAFTable
) -> Self { ) -> Self {
let bits = E::Fr::repr_num_bits(&scalar); let bits = scalar.num_bits();
match Self::optimal_window(e, bits) { match Self::optimal_window(e, bits) {
Some(window) => { Some(window) => {
table.set_base(e, *self, window); table.set_base(e, *self, window);
@ -131,7 +131,7 @@ pub trait CurveAffine<E: Engine>: Copy +
fn to_jacobian(&self, &E) -> Self::Jacobian; fn to_jacobian(&self, &E) -> Self::Jacobian;
fn prepare(self, &E) -> <Self::Jacobian as Curve<E>>::Prepared; fn prepare(self, &E) -> <Self::Jacobian as Curve<E>>::Prepared;
fn is_zero(&self) -> bool; fn is_zero(&self) -> bool;
fn mul<S: Convert<[u64], E>>(&self, &E, other: &S) -> Self::Jacobian; fn mul<S: Convert<<E::Fr as PrimeField<E>>::Repr, E>>(&self, &E, other: &S) -> Self::Jacobian;
fn negate(&mut self, &E); fn negate(&mut self, &E);
/// Returns true iff the point is on the curve and in the correct /// Returns true iff the point is on the curve and in the correct
@ -187,11 +187,11 @@ pub trait Field<E: Engine>: Sized +
fn mul_assign(&mut self, &E, other: &Self); fn mul_assign(&mut self, &E, other: &Self);
fn inverse(&self, &E) -> Option<Self>; fn inverse(&self, &E) -> Option<Self>;
fn frobenius_map(&mut self, &E, power: usize); fn frobenius_map(&mut self, &E, power: usize);
fn pow<S: Convert<[u64], E>>(&self, engine: &E, exp: &S) -> Self fn pow<S: AsRef<[u64]>>(&self, engine: &E, exp: S) -> Self
{ {
let mut res = Self::one(engine); let mut res = Self::one(engine);
for i in BitIterator::from((*exp.convert(engine)).borrow()) { for i in BitIterator::new(exp) {
res.square(engine); res.square(engine);
if i { if i {
res.mul_assign(engine, self); res.mul_assign(engine, self);
@ -209,45 +209,25 @@ pub trait SqrtField<E: Engine>: Field<E>
fn sqrt(&self, engine: &E) -> Option<Self>; fn sqrt(&self, engine: &E) -> Option<Self>;
} }
pub trait PrimeField<E: Engine>: SqrtField<E> + Convert<[u64], E> pub trait PrimeFieldRepr: Clone + Eq + Ord + AsRef<[u64]> {
fn from_u64(a: u64) -> Self;
fn sub_noborrow(&mut self, other: &Self);
fn add_nocarry(&mut self, other: &Self);
fn num_bits(&self) -> usize;
fn is_zero(&self) -> bool;
fn is_odd(&self) -> bool;
fn div2(&mut self);
}
pub trait PrimeField<E: Engine>: SqrtField<E>
{ {
/// Little endian representation of a field element. type Repr: PrimeFieldRepr;
type Repr: Convert<[u64], E> + Eq + Clone;
fn from_u64(&E, u64) -> Self; fn from_u64(&E, u64) -> Self;
fn from_str(&E, s: &str) -> Result<Self, ()>; fn from_str(&E, s: &str) -> Result<Self, ()>;
fn from_repr(&E, Self::Repr) -> Result<Self, ()>; fn from_repr(&E, Self::Repr) -> Result<Self, ()>;
fn into_repr(&self, &E) -> Self::Repr; fn into_repr(&self, &E) -> Self::Repr;
/// Determines if a is less than b
fn repr_lt(a: &Self::Repr, b: &Self::Repr) -> bool;
/// Subtracts b from a. Undefined behavior if b > a.
fn repr_sub_noborrow(a: &mut Self::Repr, b: &Self::Repr);
/// Adds b to a. Undefined behavior if overflow occurs.
fn repr_add_nocarry(a: &mut Self::Repr, b: &Self::Repr);
/// Calculates the number of bits.
fn repr_num_bits(a: &Self::Repr) -> usize;
/// Determines if the representation is of a zero.
fn repr_is_zero(a: &Self::Repr) -> bool;
/// Determines if the representation is odd.
fn repr_is_odd(a: &Self::Repr) -> bool;
/// Divides by two via rightshift.
fn repr_div2(a: &mut Self::Repr);
/// Returns the limb of least significance
fn repr_least_significant_limb(a: &Self::Repr) -> u64;
/// Creates a repr given a u64.
fn repr_from_u64(a: u64) -> Self::Repr;
/// Returns an interator over all bits, most significant bit first.
fn bits(&self, &E) -> BitIterator<Self::Repr>;
/// Returns the field characteristic; the modulus. /// Returns the field characteristic; the modulus.
fn char(&E) -> Self::Repr; fn char(&E) -> Self::Repr;
@ -272,6 +252,17 @@ pub struct BitIterator<T> {
n: usize n: usize
} }
impl<T: AsRef<[u64]>> BitIterator<T> {
fn new(t: T) -> Self {
let bits = 64 * t.as_ref().len();
BitIterator {
t: t,
n: bits
}
}
}
impl<T: AsRef<[u64]>> Iterator for BitIterator<T> { impl<T: AsRef<[u64]>> Iterator for BitIterator<T> {
type Item = bool; type Item = bool;
@ -288,46 +279,6 @@ impl<T: AsRef<[u64]>> Iterator for BitIterator<T> {
} }
} }
impl<'a> From<&'a [u64]> for BitIterator<&'a [u64]>
{
fn from(v: &'a [u64]) -> Self {
assert!(v.len() < 100);
BitIterator {
t: v,
n: v.len() * 64
}
}
}
macro_rules! bit_iter_impl(
($n:expr) => {
impl From<[u64; $n]> for BitIterator<[u64; $n]> {
fn from(v: [u64; $n]) -> Self {
BitIterator {
t: v,
n: $n * 64
}
}
}
impl<E> Convert<[u64], E> for [u64; $n] {
type Target = [u64; $n];
fn convert(&self, _: &E) -> Cow<[u64; $n]> {
Cow::Borrowed(self)
}
}
};
);
bit_iter_impl!(1);
bit_iter_impl!(2);
bit_iter_impl!(3);
bit_iter_impl!(4);
bit_iter_impl!(5);
bit_iter_impl!(6);
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

View File

@ -1,6 +1,6 @@
//! This module provides an abstract implementation of the Bos-Coster multi-exponentiation algorithm. //! This module provides an abstract implementation of the Bos-Coster multi-exponentiation algorithm.
use super::{Engine, Curve, CurveAffine, Field, PrimeField}; use super::{Engine, Curve, CurveAffine, Field, PrimeField, PrimeFieldRepr};
use super::wnaf; use super::wnaf;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::BinaryHeap; use std::collections::BinaryHeap;
@ -109,8 +109,8 @@ fn justexp<E: Engine>(
{ {
use std::cmp::min; use std::cmp::min;
let abits = E::Fr::repr_num_bits(largest); let abits = largest.num_bits();
let bbits = E::Fr::repr_num_bits(smallest); let bbits = smallest.num_bits();
let limit = min(abits-bbits, 20); let limit = min(abits-bbits, 20);
if bbits < (1<<limit) { if bbits < (1<<limit) {
@ -180,13 +180,13 @@ pub fn perform_multiexp<E: Engine, Source: ElementSource<E>>(
// Rewrite // Rewrite
let second_greatest = second_greatest.unwrap(); let second_greatest = second_greatest.unwrap();
E::Fr::repr_sub_noborrow(&mut greatest.scalar, &second_greatest.scalar); greatest.scalar.sub_noborrow(&second_greatest.scalar);
let mut tmp = elements[second_greatest.index]; let mut tmp = elements[second_greatest.index];
elements[greatest.index].add_to_projective(e, &mut tmp); elements[greatest.index].add_to_projective(e, &mut tmp);
elements[second_greatest.index] = tmp; elements[second_greatest.index] = tmp;
} }
} }
if !E::Fr::repr_is_zero(&greatest.scalar) { if !greatest.scalar.is_zero() {
// Reinsert only nonzero scalars. // Reinsert only nonzero scalars.
heap.push(greatest); heap.push(greatest);
} }
@ -213,13 +213,7 @@ struct Exp<E: Engine> {
impl<E: Engine> Ord for Exp<E> { impl<E: Engine> Ord for Exp<E> {
fn cmp(&self, other: &Exp<E>) -> Ordering { fn cmp(&self, other: &Exp<E>) -> Ordering {
if E::Fr::repr_lt(&self.scalar, &other.scalar) { self.scalar.cmp(&other.scalar)
Ordering::Less
} else if self.scalar == other.scalar {
Ordering::Equal
} else {
Ordering::Greater
}
} }
} }

View File

@ -106,7 +106,7 @@ fn test_bilinearity<E: Engine>(e: &E) {
let mut test4 = e.pairing(&a, &b); let mut test4 = e.pairing(&a, &b);
assert!(test4 != test1); assert!(test4 != test1);
test4 = test4.pow(e, &s); test4 = test4.pow(e, &s.into_repr(e));
assert_eq!(test1, test4); assert_eq!(test1, test4);
} }

View File

@ -1,5 +1,5 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use super::{Engine, Curve, PrimeField}; use super::{Engine, Curve, PrimeField, PrimeFieldRepr};
/// Represents the scratch space for a wNAF form scalar. /// Represents the scratch space for a wNAF form scalar.
pub struct WNAFTable { pub struct WNAFTable {
@ -20,19 +20,19 @@ impl WNAFTable {
self.window = table.window; self.window = table.window;
self.wnaf.truncate(0); self.wnaf.truncate(0);
while !E::Fr::repr_is_zero(&c) { while !c.is_zero() {
let mut u; let mut u;
if E::Fr::repr_is_odd(&c) { if c.is_odd() {
u = (E::Fr::repr_least_significant_limb(&c) % (1 << (self.window+1))) as i64; u = (c.as_ref()[0] % (1 << (self.window+1))) as i64;
if u > (1 << self.window) { if u > (1 << self.window) {
u -= 1 << (self.window+1); u -= 1 << (self.window+1);
} }
if u > 0 { if u > 0 {
E::Fr::repr_sub_noborrow(&mut c, &E::Fr::repr_from_u64(u as u64)); c.sub_noborrow(&<<E::Fr as PrimeField<E>>::Repr as PrimeFieldRepr>::from_u64(u as u64));
} else { } else {
E::Fr::repr_add_nocarry(&mut c, &E::Fr::repr_from_u64((-u) as u64)); c.add_nocarry(&<<E::Fr as PrimeField<E>>::Repr as PrimeFieldRepr>::from_u64((-u) as u64));
} }
} else { } else {
u = 0; u = 0;
@ -40,7 +40,7 @@ impl WNAFTable {
self.wnaf.push(u); self.wnaf.push(u);
E::Fr::repr_div2(&mut c); c.div2();
} }
} }
} }