Merge pull request #227 from str4d/impl-ff-traits
Implement ff traits for bls12_381 and jubjub crates
This commit is contained in:
commit
9f0ee56722
|
@ -20,6 +20,19 @@ name = "groups"
|
||||||
harness = false
|
harness = false
|
||||||
required-features = ["groups"]
|
required-features = ["groups"]
|
||||||
|
|
||||||
|
[dependencies.byteorder]
|
||||||
|
version = "1"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.ff]
|
||||||
|
path = "../ff"
|
||||||
|
version = "0.6"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.rand_core]
|
||||||
|
version = "0.5"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
[dependencies.subtle]
|
[dependencies.subtle]
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
|
@ -162,7 +162,7 @@ impl Fp {
|
||||||
self.ct_eq(&Fp::zero())
|
self.ct_eq(&Fp::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to convert a little-endian byte representation of
|
/// Attempts to convert a big-endian byte representation of
|
||||||
/// a scalar into an `Fp`, failing if the input is not canonical.
|
/// a scalar into an `Fp`, failing if the input is not canonical.
|
||||||
pub fn from_bytes(bytes: &[u8; 48]) -> CtOption<Fp> {
|
pub fn from_bytes(bytes: &[u8; 48]) -> CtOption<Fp> {
|
||||||
let mut tmp = Fp([0, 0, 0, 0, 0, 0]);
|
let mut tmp = Fp([0, 0, 0, 0, 0, 0]);
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
use rand_core::RngCore;
|
||||||
|
|
||||||
|
use ff::{Field, PrimeField};
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
use crate::util::{adc, mac, sbb};
|
use crate::util::{adc, mac, sbb};
|
||||||
|
@ -28,6 +30,12 @@ impl fmt::Debug for Scalar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Scalar {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<u64> for Scalar {
|
impl From<u64> for Scalar {
|
||||||
fn from(val: u64) -> Scalar {
|
fn from(val: u64) -> Scalar {
|
||||||
Scalar([val, 0, 0, 0]) * R2
|
Scalar([val, 0, 0, 0]) * R2
|
||||||
|
@ -70,6 +78,22 @@ const MODULUS: Scalar = Scalar([
|
||||||
0x73ed_a753_299d_7d48,
|
0x73ed_a753_299d_7d48,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const MODULUS_BYTES: [u8; 32] = [
|
||||||
|
0x01, 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,
|
||||||
|
];
|
||||||
|
|
||||||
|
// The number of bits needed to represent the modulus.
|
||||||
|
const MODULUS_BITS: u32 = 255;
|
||||||
|
|
||||||
|
// GENERATOR = 7 (multiplicative generator of r-1 order, that is also quadratic nonresidue)
|
||||||
|
const GENERATOR: Scalar = Scalar([
|
||||||
|
0x0000_000e_ffff_fff1,
|
||||||
|
0x17e3_63d3_0018_9c0f,
|
||||||
|
0xff9c_5787_6f84_57b0,
|
||||||
|
0x3513_3220_8fc5_a8c4,
|
||||||
|
]);
|
||||||
|
|
||||||
impl<'a> Neg for &'a Scalar {
|
impl<'a> Neg for &'a Scalar {
|
||||||
type Output = Scalar;
|
type Output = Scalar;
|
||||||
|
|
||||||
|
@ -145,6 +169,7 @@ const R3: Scalar = Scalar([
|
||||||
0x6e2a_5bb9_c8db_33e9,
|
0x6e2a_5bb9_c8db_33e9,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 2^S * t = MODULUS - 1 with t odd
|
||||||
const S: u32 = 32;
|
const S: u32 = 32;
|
||||||
|
|
||||||
/// GENERATOR^t where t * 2^s + 1 = q
|
/// GENERATOR^t where t * 2^s + 1 = q
|
||||||
|
@ -613,12 +638,95 @@ impl Scalar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Scalar> for [u8; 32] {
|
||||||
|
fn from(value: Scalar) -> [u8; 32] {
|
||||||
|
value.to_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Scalar> for [u8; 32] {
|
impl<'a> From<&'a Scalar> for [u8; 32] {
|
||||||
fn from(value: &'a Scalar) -> [u8; 32] {
|
fn from(value: &'a Scalar) -> [u8; 32] {
|
||||||
value.to_bytes()
|
value.to_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Field for Scalar {
|
||||||
|
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
|
||||||
|
let mut buf = [0; 64];
|
||||||
|
rng.fill_bytes(&mut buf);
|
||||||
|
Self::from_bytes_wide(&buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zero() -> Self {
|
||||||
|
Self::zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn one() -> Self {
|
||||||
|
Self::one()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.ct_eq(&Self::zero()).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
fn square(&self) -> Self {
|
||||||
|
self.square()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
fn double(&self) -> Self {
|
||||||
|
self.double()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invert(&self) -> CtOption<Self> {
|
||||||
|
self.invert()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sqrt(&self) -> CtOption<Self> {
|
||||||
|
self.sqrt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimeField for Scalar {
|
||||||
|
type Repr = [u8; 32];
|
||||||
|
type ReprEndianness = byteorder::LittleEndian;
|
||||||
|
|
||||||
|
fn from_repr(r: Self::Repr) -> Option<Self> {
|
||||||
|
let res = Self::from_bytes(&r);
|
||||||
|
if res.is_some().into() {
|
||||||
|
Some(res.unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_repr(&self) -> Self::Repr {
|
||||||
|
self.to_bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_odd(&self) -> bool {
|
||||||
|
self.to_bytes()[0] & 1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn char() -> Self::Repr {
|
||||||
|
MODULUS_BYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
const NUM_BITS: u32 = MODULUS_BITS;
|
||||||
|
const CAPACITY: u32 = Self::NUM_BITS - 1;
|
||||||
|
|
||||||
|
fn multiplicative_generator() -> Self {
|
||||||
|
GENERATOR
|
||||||
|
}
|
||||||
|
|
||||||
|
const S: u32 = S;
|
||||||
|
|
||||||
|
fn root_of_unity() -> Self {
|
||||||
|
ROOT_OF_UNITY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_inv() {
|
fn test_inv() {
|
||||||
// Compute -(q^{-1} mod 2^64) mod 2^64 by exponentiating
|
// Compute -(q^{-1} mod 2^64) mod 2^64 by exponentiating
|
||||||
|
|
|
@ -18,6 +18,19 @@ path = "../bls12_381"
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.byteorder]
|
||||||
|
version = "1"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.ff]
|
||||||
|
path = "../ff"
|
||||||
|
version = "0.6"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.rand_core]
|
||||||
|
version = "0.5"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
[dependencies.subtle]
|
[dependencies.subtle]
|
||||||
version = "^2.2.1"
|
version = "^2.2.1"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
118
jubjub/src/fr.rs
118
jubjub/src/fr.rs
|
@ -5,6 +5,8 @@ use core::convert::TryInto;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
|
||||||
|
use ff::{Field, PrimeField};
|
||||||
|
use rand_core::RngCore;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
use crate::util::{adc, mac, sbb};
|
use crate::util::{adc, mac, sbb};
|
||||||
|
@ -28,6 +30,12 @@ impl fmt::Debug for Fr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Fr {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<u64> for Fr {
|
impl From<u64> for Fr {
|
||||||
fn from(val: u64) -> Fr {
|
fn from(val: u64) -> Fr {
|
||||||
Fr([val, 0, 0, 0]) * R2
|
Fr([val, 0, 0, 0]) * R2
|
||||||
|
@ -70,6 +78,33 @@ pub const MODULUS: Fr = Fr([
|
||||||
0x0e7d_b4ea_6533_afa9,
|
0x0e7d_b4ea_6533_afa9,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const MODULUS_BYTES: [u8; 32] = [
|
||||||
|
0xb7, 0x2c, 0xf7, 0xd6, 0x5e, 0x0e, 0x97, 0xd0, 0x82, 0x10, 0xc8, 0xcc, 0x93, 0x20, 0x68, 0xa6,
|
||||||
|
0x00, 0x3b, 0x34, 0x01, 0x01, 0x3b, 0x67, 0x06, 0xa9, 0xaf, 0x33, 0x65, 0xea, 0xb4, 0x7d, 0x0e,
|
||||||
|
];
|
||||||
|
|
||||||
|
// The number of bits needed to represent the modulus.
|
||||||
|
const MODULUS_BITS: u32 = 252;
|
||||||
|
|
||||||
|
// GENERATOR = 6 (multiplicative generator of r-1 order, that is also quadratic nonresidue)
|
||||||
|
const GENERATOR: Fr = Fr([
|
||||||
|
0x720b_1b19_d49e_a8f1,
|
||||||
|
0xbf4a_a361_01f1_3a58,
|
||||||
|
0x5fa8_cc96_8193_ccbb,
|
||||||
|
0x0e70_cbdc_7dcc_f3ac,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 2^S * t = MODULUS - 1 with t odd
|
||||||
|
const S: u32 = 1;
|
||||||
|
|
||||||
|
// 2^S root of unity computed by GENERATOR^t
|
||||||
|
const ROOT_OF_UNITY: Fr = Fr([
|
||||||
|
0xaa9f_02ab_1d61_24de,
|
||||||
|
0xb352_4a64_6611_2932,
|
||||||
|
0x7342_2612_15ac_260b,
|
||||||
|
0x04d6_b87b_1da2_59e2,
|
||||||
|
]);
|
||||||
|
|
||||||
impl<'a> Neg for &'a Fr {
|
impl<'a> Neg for &'a Fr {
|
||||||
type Output = Fr;
|
type Output = Fr;
|
||||||
|
|
||||||
|
@ -575,12 +610,95 @@ impl Fr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Fr> for [u8; 32] {
|
||||||
|
fn from(value: Fr) -> [u8; 32] {
|
||||||
|
value.to_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Fr> for [u8; 32] {
|
impl<'a> From<&'a Fr> for [u8; 32] {
|
||||||
fn from(value: &'a Fr) -> [u8; 32] {
|
fn from(value: &'a Fr) -> [u8; 32] {
|
||||||
value.to_bytes()
|
value.to_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Field for Fr {
|
||||||
|
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
|
||||||
|
let mut buf = [0; 64];
|
||||||
|
rng.fill_bytes(&mut buf);
|
||||||
|
Self::from_bytes_wide(&buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zero() -> Self {
|
||||||
|
Self::zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn one() -> Self {
|
||||||
|
Self::one()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.ct_eq(&Self::zero()).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
fn square(&self) -> Self {
|
||||||
|
self.square()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
fn double(&self) -> Self {
|
||||||
|
self.double()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invert(&self) -> CtOption<Self> {
|
||||||
|
self.invert()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sqrt(&self) -> CtOption<Self> {
|
||||||
|
self.sqrt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimeField for Fr {
|
||||||
|
type Repr = [u8; 32];
|
||||||
|
type ReprEndianness = byteorder::LittleEndian;
|
||||||
|
|
||||||
|
fn from_repr(r: Self::Repr) -> Option<Self> {
|
||||||
|
let res = Self::from_bytes(&r);
|
||||||
|
if res.is_some().into() {
|
||||||
|
Some(res.unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_repr(&self) -> Self::Repr {
|
||||||
|
self.to_bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_odd(&self) -> bool {
|
||||||
|
self.to_bytes()[0] & 1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn char() -> Self::Repr {
|
||||||
|
MODULUS_BYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
const NUM_BITS: u32 = MODULUS_BITS;
|
||||||
|
const CAPACITY: u32 = Self::NUM_BITS - 1;
|
||||||
|
|
||||||
|
fn multiplicative_generator() -> Self {
|
||||||
|
GENERATOR
|
||||||
|
}
|
||||||
|
|
||||||
|
const S: u32 = S;
|
||||||
|
|
||||||
|
fn root_of_unity() -> Self {
|
||||||
|
ROOT_OF_UNITY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_inv() {
|
fn test_inv() {
|
||||||
// Compute -(r^{-1} mod 2^64) mod 2^64 by exponentiating
|
// Compute -(r^{-1} mod 2^64) mod 2^64 by exponentiating
|
||||||
|
|
Loading…
Reference in New Issue