Merge pull request #17 from zcash/ff-0.11

ff 0.11, group 0.11
This commit is contained in:
ebfull 2021-09-02 11:45:18 -06:00 committed by GitHub
commit 4f85fa5c7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 30 additions and 72 deletions

View File

@ -7,13 +7,17 @@ and this project adheres to Rust's notion of
## [Unreleased]
## [0.2.0] - 2021-09-02
### Changed
- Migrated to `ff 0.11`, `group 0.11`.
## [0.1.2] - 2021-08-06
## Added
### Added
- Implementation of `group::WnafGroup` for Pallas and Vesta, enabling them to be
used with `group::Wnaf` for targeted performance improvements.
## [0.1.1] - 2021-06-04
## Added
### Added
- Implementations of `group::cofactor::{CofactorCurve, CofactorCurveAffine}` for
Pallas and Vesta, enabling them to be used in cofactor-aware protocols that
also want to leverage the affine point representation.

View File

@ -1,7 +1,7 @@
[package]
name = "pasta_curves"
description = "Implementation of the Pallas and Vesta (Pasta) curve cycle"
version = "0.1.2"
version = "0.2.0"
authors = [
"Sean Bowe <sean@electriccoin.co>",
"Ying Tong Lai <yingtong@electriccoin.co>",
@ -41,8 +41,8 @@ harness = false
[dependencies]
subtle = "2.3"
ff = "0.10"
group = "0.10"
ff = "0.11"
group = "0.11"
rand = "0.8"
blake2b_simd = "0.5"
lazy_static = "1.4.0"

View File

@ -6,7 +6,7 @@ use static_assertions::const_assert;
use std::assert;
use std::convert::TryInto;
use std::marker::PhantomData;
use subtle::{Choice, ConstantTimeEq, CtOption};
use subtle::{Choice, CtOption};
use super::Group;
@ -16,9 +16,7 @@ const_assert!(size_of::<usize>() >= 4);
/// This trait is a common interface for dealing with elements of a finite
/// field.
pub trait FieldExt:
ff::PrimeField + From<bool> + Ord + ConstantTimeEq + Group<Scalar = Self>
{
pub trait FieldExt: ff::PrimeField + From<bool> + Ord + Group<Scalar = Self> {
/// Modulus of the field written as a string for display purposes
const MODULUS: &'static str;
@ -69,9 +67,6 @@ pub trait FieldExt:
Self::random(rand::rngs::OsRng)
}
/// Returns whether or not this element is zero.
fn ct_is_zero(&self) -> Choice;
/// Obtains a field element congruent to the integer `v`.
fn from_u64(v: u64) -> Self;
@ -133,31 +128,6 @@ pub trait FieldExt:
fn pow_by_t_minus1_over2(&self) -> Self {
ff::Field::pow_vartime(&self, &Self::T_MINUS1_OVER2)
}
/// Performs a batch inversion using Montgomery's trick, returns the product
/// of every inverse. Zero inputs are ignored.
fn batch_invert(v: &mut [Self]) -> Self {
let mut tmp = Vec::with_capacity(v.len());
let mut acc = Self::one();
for p in v.iter() {
tmp.push(acc);
acc = Self::conditional_select(&(acc * p), &acc, p.ct_is_zero());
}
acc = acc.invert().unwrap();
let allinv = acc;
for (p, tmp) in v.iter_mut().rev().zip(tmp.into_iter().rev()) {
let skip = p.ct_is_zero();
let tmp = tmp * acc;
acc = Self::conditional_select(&(acc * *p), &acc, skip);
*p = Self::conditional_select(&tmp, p, skip);
}
allinv
}
}
/// Parameters for a perfect hash function used in square root computation.
@ -296,10 +266,10 @@ impl<F: FieldExt> SqrtTables<F> {
let res = self.sqrt_common(&uv, &v);
let sqdiv = res.square() * div;
let is_square = (sqdiv - num).ct_is_zero();
let is_nonsquare = (sqdiv - F::ROOT_OF_UNITY * num).ct_is_zero();
let is_square = (sqdiv - num).is_zero();
let is_nonsquare = (sqdiv - F::ROOT_OF_UNITY * num).is_zero();
assert!(bool::from(
num.ct_is_zero() | div.ct_is_zero() | (is_square ^ is_nonsquare)
num.is_zero() | div.is_zero() | (is_square ^ is_nonsquare)
));
(is_square, res)
@ -313,9 +283,9 @@ impl<F: FieldExt> SqrtTables<F> {
let res = self.sqrt_common(&uv, &v);
let sq = res.square();
let is_square = (sq - u).ct_is_zero();
let is_nonsquare = (sq - F::ROOT_OF_UNITY * u).ct_is_zero();
assert!(bool::from(u.ct_is_zero() | (is_square ^ is_nonsquare)));
let is_square = (sq - u).is_zero();
let is_nonsquare = (sq - F::ROOT_OF_UNITY * u).is_zero();
assert!(bool::from(u.is_zero() | (is_square ^ is_nonsquare)));
(is_square, res)
}

View File

@ -92,7 +92,7 @@ macro_rules! new_curve_impl {
}
fn is_identity(&self) -> Choice {
self.z.ct_is_zero()
self.z.is_zero()
}
}
@ -150,7 +150,7 @@ macro_rules! new_curve_impl {
let z6 = z4 * z2;
(self.y.square() - (self.x.square() + $name::curve_constant_a() * z4) * self.x)
.ct_eq(&(z6 * $name::curve_constant_b()))
| self.z.ct_is_zero()
| self.z.is_zero()
}
}
@ -208,7 +208,7 @@ macro_rules! new_curve_impl {
infinity: Choice::from(0u8),
};
$name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.ct_is_zero())
$name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.is_zero())
}
}
@ -647,7 +647,7 @@ macro_rules! new_curve_impl {
tmp[31] &= 0b0111_1111;
$base::from_bytes(&tmp).and_then(|x| {
CtOption::new(Self::identity(), x.ct_is_zero() & (!ysign)).or_else(|| {
CtOption::new(Self::identity(), x.is_zero() & (!ysign)).or_else(|| {
let x3 = x.square() * x;
(x3 + $name::curve_constant_b()).sqrt().and_then(|y| {
let sign = Choice::from(y.to_bytes()[0] & 1);

View File

@ -480,10 +480,6 @@ impl ff::Field for Fp {
Self::one()
}
fn is_zero(&self) -> bool {
self.ct_is_zero().into()
}
fn double(&self) -> Self {
self.double()
}
@ -538,16 +534,16 @@ impl ff::PrimeField for Fp {
const CAPACITY: u32 = 254;
const S: u32 = S;
fn from_repr(repr: Self::Repr) -> Option<Self> {
Self::from_bytes(&repr).into()
fn from_repr(repr: Self::Repr) -> CtOption<Self> {
Self::from_bytes(&repr)
}
fn to_repr(&self) -> Self::Repr {
self.to_bytes()
}
fn is_odd(&self) -> bool {
self.to_bytes()[0] & 1 == 1
fn is_odd(&self) -> Choice {
Choice::from(self.to_bytes()[0] & 1)
}
fn multiplicative_generator() -> Self {
@ -656,10 +652,6 @@ impl FieldExt for Fp {
FP_TABLES.sqrt_alt(self)
}
fn ct_is_zero(&self) -> Choice {
self.ct_eq(&Self::zero())
}
fn from_u64(v: u64) -> Self {
Fp::from_raw([v as u64, 0, 0, 0])
}

View File

@ -480,10 +480,6 @@ impl ff::Field for Fq {
Self::one()
}
fn is_zero(&self) -> bool {
self.ct_is_zero().into()
}
fn double(&self) -> Self {
self.double()
}
@ -538,16 +534,16 @@ impl ff::PrimeField for Fq {
const CAPACITY: u32 = 254;
const S: u32 = S;
fn from_repr(repr: Self::Repr) -> Option<Self> {
Self::from_bytes(&repr).into()
fn from_repr(repr: Self::Repr) -> CtOption<Self> {
Self::from_bytes(&repr)
}
fn to_repr(&self) -> Self::Repr {
self.to_bytes()
}
fn is_odd(&self) -> bool {
self.to_bytes()[0] & 1 == 1
fn is_odd(&self) -> Choice {
Choice::from(self.to_bytes()[0] & 1)
}
fn multiplicative_generator() -> Self {
@ -656,10 +652,6 @@ impl FieldExt for Fq {
FQ_TABLES.sqrt_alt(self)
}
fn ct_is_zero(&self) -> Choice {
self.ct_eq(&Self::zero())
}
fn from_u64(v: u64) -> Self {
Fq::from_raw([v as u64, 0, 0, 0])
}

View File

@ -137,7 +137,7 @@ pub fn map_to_curve_simple_swu<F: FieldExt, C: CurveExt<Base = F>, I: CurveExt<B
let z_u2 = z * u.square();
let ta = z_u2.square() + z_u2;
let num_x1 = b * (ta + F::one());
let div = a * F::conditional_select(&-ta, &z, ta.ct_is_zero());
let div = a * F::conditional_select(&-ta, &z, ta.is_zero());
let num2_x1 = num_x1.square();
let div2 = div.square();
let div3 = div2 * div;