mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-11-02 12:27:02 +00:00
Merge branch 'develop'
This commit is contained in:
@@ -1,7 +1,4 @@
|
||||
use ff::{
|
||||
Field, LegendreSymbol, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine,
|
||||
SqrtField,
|
||||
};
|
||||
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField};
|
||||
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
|
||||
use pairing::{Engine, PairingCurveAffine};
|
||||
|
||||
@@ -9,18 +6,143 @@ use rand_core::RngCore;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::num::Wrapping;
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||
|
||||
const MODULUS_R: Wrapping<u32> = Wrapping(64513);
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Fr(Wrapping<u32>);
|
||||
|
||||
impl Default for Fr {
|
||||
fn default() -> Self {
|
||||
<Fr as Field>::zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstantTimeEq for Fr {
|
||||
fn ct_eq(&self, other: &Fr) -> Choice {
|
||||
(self.0).0.ct_eq(&(other.0).0)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Fr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
write!(f, "{}", (self.0).0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConditionallySelectable for Fr {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
Fr(Wrapping(u32::conditional_select(
|
||||
&(a.0).0,
|
||||
&(b.0).0,
|
||||
choice,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Fr {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(mut self) -> Self {
|
||||
if !<Fr as Field>::is_zero(&self) {
|
||||
self.0 = MODULUS_R - self.0;
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Add<&'r Fr> for Fr {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
AddAssign::add_assign(&mut ret, other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Fr {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
self + &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> AddAssign<&'r Fr> for Fr {
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
self.0 = (self.0 + other.0) % MODULUS_R;
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Fr {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
AddAssign::add_assign(self, &other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Sub<&'r Fr> for Fr {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
SubAssign::sub_assign(&mut ret, other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Fr {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self - &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> SubAssign<&'r Fr> for Fr {
|
||||
fn sub_assign(&mut self, other: &Self) {
|
||||
self.0 = ((MODULUS_R + self.0) - other.0) % MODULUS_R;
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Fr {
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
SubAssign::sub_assign(self, &other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Mul<&'r Fr> for Fr {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
MulAssign::mul_assign(&mut ret, other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Fr {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self * &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> MulAssign<&'r Fr> for Fr {
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
self.0 = (self.0 * other.0) % MODULUS_R;
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for Fr {
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
MulAssign::mul_assign(self, &other);
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for Fr {
|
||||
fn random<R: RngCore + ?std::marker::Sized>(rng: &mut R) -> Self {
|
||||
Fr(Wrapping(rng.next_u32()) % MODULUS_R)
|
||||
@@ -38,37 +160,22 @@ impl Field for Fr {
|
||||
(self.0).0 == 0
|
||||
}
|
||||
|
||||
fn square(&mut self) {
|
||||
self.0 = (self.0 * self.0) % MODULUS_R;
|
||||
fn square(&self) -> Self {
|
||||
Fr((self.0 * self.0) % MODULUS_R)
|
||||
}
|
||||
|
||||
fn double(&mut self) {
|
||||
self.0 = (self.0 << 1) % MODULUS_R;
|
||||
fn double(&self) -> Self {
|
||||
Fr((self.0 << 1) % MODULUS_R)
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
if !<Fr as Field>::is_zero(self) {
|
||||
self.0 = MODULUS_R - self.0;
|
||||
}
|
||||
}
|
||||
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
self.0 = (self.0 + other.0) % MODULUS_R;
|
||||
}
|
||||
|
||||
fn sub_assign(&mut self, other: &Self) {
|
||||
self.0 = ((MODULUS_R + self.0) - other.0) % MODULUS_R;
|
||||
}
|
||||
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
self.0 = (self.0 * other.0) % MODULUS_R;
|
||||
}
|
||||
|
||||
fn inverse(&self) -> Option<Self> {
|
||||
fn invert(&self) -> CtOption<Self> {
|
||||
if <Fr as Field>::is_zero(self) {
|
||||
None
|
||||
CtOption::new(<Fr as Field>::zero(), Choice::from(0))
|
||||
} else {
|
||||
Some(self.pow(&[(MODULUS_R.0 as u64) - 2]))
|
||||
CtOption::new(
|
||||
self.pow_vartime(&[(MODULUS_R.0 as u64) - 2]),
|
||||
Choice::from(1),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,58 +185,39 @@ impl Field for Fr {
|
||||
}
|
||||
|
||||
impl SqrtField for Fr {
|
||||
fn legendre(&self) -> LegendreSymbol {
|
||||
// s = self^((r - 1) // 2)
|
||||
let s = self.pow([32256]);
|
||||
if s == <Fr as Field>::zero() {
|
||||
LegendreSymbol::Zero
|
||||
} else if s == <Fr as Field>::one() {
|
||||
LegendreSymbol::QuadraticResidue
|
||||
} else {
|
||||
LegendreSymbol::QuadraticNonResidue
|
||||
}
|
||||
}
|
||||
|
||||
fn sqrt(&self) -> Option<Self> {
|
||||
fn sqrt(&self) -> CtOption<Self> {
|
||||
// Tonelli-Shank's algorithm for q mod 16 = 1
|
||||
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
|
||||
match self.legendre() {
|
||||
LegendreSymbol::Zero => Some(*self),
|
||||
LegendreSymbol::QuadraticNonResidue => None,
|
||||
LegendreSymbol::QuadraticResidue => {
|
||||
let mut c = Fr::root_of_unity();
|
||||
// r = self^((t + 1) // 2)
|
||||
let mut r = self.pow([32]);
|
||||
// t = self^t
|
||||
let mut t = self.pow([63]);
|
||||
let mut m = Fr::S;
|
||||
let mut c = Fr::root_of_unity();
|
||||
// r = self^((t + 1) // 2)
|
||||
let mut r = self.pow_vartime([32]);
|
||||
// t = self^t
|
||||
let mut t = self.pow_vartime([63]);
|
||||
let mut m = Fr::S;
|
||||
|
||||
while t != <Fr as Field>::one() {
|
||||
let mut i = 1;
|
||||
{
|
||||
let mut t2i = t;
|
||||
t2i.square();
|
||||
loop {
|
||||
if t2i == <Fr as Field>::one() {
|
||||
break;
|
||||
}
|
||||
t2i.square();
|
||||
i += 1;
|
||||
}
|
||||
while t != <Fr as Field>::one() {
|
||||
let mut i = 1;
|
||||
{
|
||||
let mut t2i = t.square();
|
||||
loop {
|
||||
if t2i == <Fr as Field>::one() {
|
||||
break;
|
||||
}
|
||||
|
||||
for _ in 0..(m - i - 1) {
|
||||
c.square();
|
||||
}
|
||||
<Fr as Field>::mul_assign(&mut r, &c);
|
||||
c.square();
|
||||
<Fr as Field>::mul_assign(&mut t, &c);
|
||||
m = i;
|
||||
t2i = t2i.square();
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Some(r)
|
||||
}
|
||||
|
||||
for _ in 0..(m - i - 1) {
|
||||
c = c.square();
|
||||
}
|
||||
MulAssign::mul_assign(&mut r, &c);
|
||||
c = c.square();
|
||||
MulAssign::mul_assign(&mut t, &c);
|
||||
m = i;
|
||||
}
|
||||
|
||||
CtOption::new(r, (r * r).ct_eq(self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +314,7 @@ impl PrimeField for Fr {
|
||||
|
||||
fn from_repr(repr: FrRepr) -> Result<Self, PrimeFieldDecodingError> {
|
||||
if repr.0[0] >= (MODULUS_R.0 as u64) {
|
||||
Err(PrimeFieldDecodingError::NotInField(format!("{}", repr)))
|
||||
Err(PrimeFieldDecodingError::NotInField)
|
||||
} else {
|
||||
Ok(Fr(Wrapping(repr.0[0] as u32)))
|
||||
}
|
||||
@@ -280,16 +368,16 @@ impl Engine for DummyEngine {
|
||||
|
||||
for &(a, b) in i {
|
||||
let mut tmp = *a;
|
||||
<Fr as Field>::mul_assign(&mut tmp, b);
|
||||
<Fr as Field>::add_assign(&mut acc, &tmp);
|
||||
MulAssign::mul_assign(&mut tmp, b);
|
||||
AddAssign::add_assign(&mut acc, &tmp);
|
||||
}
|
||||
|
||||
acc
|
||||
}
|
||||
|
||||
/// Perform final exponentiation of the result of a miller loop.
|
||||
fn final_exponentiation(this: &Self::Fqk) -> Option<Self::Fqk> {
|
||||
Some(*this)
|
||||
fn final_exponentiation(this: &Self::Fqk) -> CtOption<Self::Fqk> {
|
||||
CtOption::new(*this, Choice::from(1))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,25 +410,13 @@ impl CurveProjective for Fr {
|
||||
}
|
||||
|
||||
fn double(&mut self) {
|
||||
<Fr as Field>::double(self);
|
||||
}
|
||||
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
<Fr as Field>::add_assign(self, other);
|
||||
}
|
||||
|
||||
fn add_assign_mixed(&mut self, other: &Self) {
|
||||
<Fr as Field>::add_assign(self, other);
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
<Fr as Field>::negate(self);
|
||||
self.0 = <Fr as Field>::double(self).0;
|
||||
}
|
||||
|
||||
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
|
||||
let tmp = Fr::from_repr(other.into()).unwrap();
|
||||
|
||||
<Fr as Field>::mul_assign(self, &tmp);
|
||||
MulAssign::mul_assign(self, &tmp);
|
||||
}
|
||||
|
||||
fn into_affine(&self) -> Fr {
|
||||
@@ -415,15 +491,11 @@ impl CurveAffine for Fr {
|
||||
<Fr as Field>::is_zero(self)
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
<Fr as Field>::negate(self);
|
||||
}
|
||||
|
||||
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective {
|
||||
let mut res = *self;
|
||||
let tmp = Fr::from_repr(other.into()).unwrap();
|
||||
|
||||
<Fr as Field>::mul_assign(&mut res, &tmp);
|
||||
MulAssign::mul_assign(&mut res, &tmp);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user