Move Field operations to operator-backed traits

The ff_derive, pairing, zcash_primitives::jubjub, and bellman dummy_engine
changes are minimally implemented on top of the existing *_assign()
functions.
This commit is contained in:
Jack Grigg 2019-12-12 20:57:06 +00:00
parent 2f7dd6094c
commit 27c8f34601
No known key found for this signature in database
GPG Key ID: 9E8255172BBF9898
35 changed files with 771 additions and 233 deletions

View File

@ -13,6 +13,7 @@
use ff::{Field, PrimeField, ScalarEngine};
use group::CurveProjective;
use std::ops::{AddAssign, MulAssign, SubAssign};
use super::SynthesisError;

View File

@ -1,6 +1,7 @@
//! Window table lookup gadgets.
use ff::{Field, ScalarEngine};
use std::ops::AddAssign;
use super::boolean::Boolean;
use super::num::{AllocatedNum, Num};

View File

@ -5,6 +5,7 @@ use super::num::Num;
use super::Assignment;
use crate::{ConstraintSystem, SynthesisError};
use ff::{Field, PrimeField, ScalarEngine};
use std::ops::AddAssign;
/// Takes a sequence of booleans and exposes them as compact
/// public inputs

View File

@ -1,6 +1,7 @@
//! Gadgets representing numbers in the scalar field of the underlying curve.
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, ScalarEngine};
use std::ops::{AddAssign, MulAssign};
use crate::{ConstraintSystem, LinearCombination, SynthesisError, Variable};
@ -416,6 +417,7 @@ mod test {
use pairing::bls12_381::{Bls12, Fr};
use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::SubAssign;
use super::{AllocatedNum, Boolean};
use crate::gadgets::test::*;

View File

@ -6,6 +6,7 @@ use crate::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable
use std::collections::HashMap;
use std::fmt::Write;
use std::ops::{AddAssign, MulAssign};
use byteorder::{BigEndian, ByteOrder};
use std::cmp::Ordering;

View File

@ -1,5 +1,5 @@
use rand_core::RngCore;
use std::ops::{AddAssign, MulAssign};
use std::sync::Arc;
use ff::{Field, PrimeField};

View File

@ -474,6 +474,7 @@ mod test_with_bls12_381 {
use ff::Field;
use pairing::bls12_381::{Bls12, Fr};
use rand::thread_rng;
use std::ops::MulAssign;
#[test]
fn serialization() {

View File

@ -1,5 +1,5 @@
use rand_core::RngCore;
use std::ops::{AddAssign, MulAssign};
use std::sync::Arc;
use futures::Future;

View File

@ -9,6 +9,7 @@ use rand_core::RngCore;
use std::cmp::Ordering;
use std::fmt;
use std::num::Wrapping;
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
const MODULUS_R: Wrapping<u32> = Wrapping(64513);
@ -21,6 +22,96 @@ impl fmt::Display for Fr {
}
}
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>(rng: &mut R) -> Self {
Fr(Wrapping(rng.next_u32()) % MODULUS_R)
@ -52,18 +143,6 @@ impl Field for Fr {
}
}
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> {
if <Fr as Field>::is_zero(self) {
None
@ -121,9 +200,9 @@ impl SqrtField for Fr {
for _ in 0..(m - i - 1) {
c.square();
}
<Fr as Field>::mul_assign(&mut r, &c);
MulAssign::mul_assign(&mut r, &c);
c.square();
<Fr as Field>::mul_assign(&mut t, &c);
MulAssign::mul_assign(&mut t, &c);
m = i;
}
@ -280,8 +359,8 @@ 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
@ -326,11 +405,11 @@ impl CurveProjective for Fr {
}
fn add_assign(&mut self, other: &Self) {
<Fr as Field>::add_assign(self, other);
AddAssign::add_assign(self, other);
}
fn add_assign_mixed(&mut self, other: &Self) {
<Fr as Field>::add_assign(self, other);
AddAssign::add_assign(self, other);
}
fn negate(&mut self) {
@ -340,7 +419,7 @@ impl CurveProjective for Fr {
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 {
@ -423,7 +502,7 @@ impl CurveAffine for Fr {
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
}

View File

@ -5,6 +5,7 @@ mod dummy_engine;
use self::dummy_engine::*;
use std::marker::PhantomData;
use std::ops::{AddAssign, MulAssign, SubAssign};
use crate::{Circuit, ConstraintSystem, SynthesisError};

View File

@ -148,7 +148,7 @@ use std::error::Error;
use std::fmt;
use std::io;
use std::marker::PhantomData;
use std::ops::{Add, Sub};
use std::ops::{Add, MulAssign, Sub};
/// Computations are expressed in terms of arithmetic circuits, in particular
/// rank-1 quadratic constraint systems. The `Circuit` trait represents a

View File

@ -7,6 +7,7 @@ use std::time::{Duration, Instant};
// Bring in some tools for using pairing-friendly curves
use ff::{Field, ScalarEngine};
use pairing::Engine;
use std::ops::{AddAssign, MulAssign};
// We're going to use the BLS12-381 pairing-friendly elliptic curve.
use pairing::bls12_381::Bls12;

View File

@ -833,6 +833,119 @@ fn prime_field_impl(
}
}
impl<'r> ::std::ops::Add<&'r #name> for #name {
type Output = #name;
#[inline]
fn add(self, other: &#name) -> #name {
let mut ret = self;
ret.add_assign(other);
ret
}
}
impl ::std::ops::Add for #name {
type Output = #name;
#[inline]
fn add(self, other: #name) -> Self {
self + &other
}
}
impl<'r> ::std::ops::AddAssign<&'r #name> for #name {
#[inline]
fn add_assign(&mut self, other: &#name) {
// This cannot exceed the backing capacity.
self.0.add_nocarry(&other.0);
// However, it may need to be reduced.
self.reduce();
}
}
impl ::std::ops::AddAssign for #name {
#[inline]
fn add_assign(&mut self, other: #name) {
self.add_assign(&other);
}
}
impl<'r> ::std::ops::Sub<&'r #name> for #name {
type Output = #name;
#[inline]
fn sub(self, other: &#name) -> Self {
let mut ret = self;
ret.sub_assign(other);
ret
}
}
impl ::std::ops::Sub for #name {
type Output = #name;
#[inline]
fn sub(self, other: #name) -> Self {
self - &other
}
}
impl<'r> ::std::ops::SubAssign<&'r #name> for #name {
#[inline]
fn sub_assign(&mut self, other: &#name) {
// If `other` is larger than `self`, we'll need to add the modulus to self first.
if other.0 > self.0 {
self.0.add_nocarry(&MODULUS);
}
self.0.sub_noborrow(&other.0);
}
}
impl ::std::ops::SubAssign for #name {
#[inline]
fn sub_assign(&mut self, other: #name) {
self.sub_assign(&other);
}
}
impl<'r> ::std::ops::Mul<&'r #name> for #name {
type Output = #name;
#[inline]
fn mul(self, other: &#name) -> Self {
let mut ret = self;
ret.mul_assign(other);
ret
}
}
impl ::std::ops::Mul for #name {
type Output = #name;
#[inline]
fn mul(self, other: #name) -> Self {
self * &other
}
}
impl<'r> ::std::ops::MulAssign<&'r #name> for #name {
#[inline]
fn mul_assign(&mut self, other: &#name)
{
#multiply_impl
}
}
impl ::std::ops::MulAssign for #name {
#[inline]
fn mul_assign(&mut self, other: #name)
{
self.mul_assign(&other);
}
}
impl ::ff::PrimeField for #name {
type Repr = #repr;
@ -911,15 +1024,6 @@ fn prime_field_impl(
self.0.is_zero()
}
#[inline]
fn add_assign(&mut self, other: &#name) {
// This cannot exceed the backing capacity.
self.0.add_nocarry(&other.0);
// However, it may need to be reduced.
self.reduce();
}
#[inline]
fn double(&mut self) {
// This cannot exceed the backing capacity.
@ -929,16 +1033,6 @@ fn prime_field_impl(
self.reduce();
}
#[inline]
fn sub_assign(&mut self, other: &#name) {
// If `other` is larger than `self`, we'll need to add the modulus to self first.
if other.0 > self.0 {
self.0.add_nocarry(&MODULUS);
}
self.0.sub_noborrow(&other.0);
}
#[inline]
fn negate(&mut self) {
if !self.is_zero() {
@ -1008,12 +1102,6 @@ fn prime_field_impl(
// This has no effect in a prime field.
}
#[inline]
fn mul_assign(&mut self, other: &#name)
{
#multiply_impl
}
#[inline]
fn square(&mut self)
{

View File

@ -11,10 +11,31 @@ use rand_core::RngCore;
use std::error::Error;
use std::fmt;
use std::io::{self, Read, Write};
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
/// This trait represents an element of a field.
pub trait Field:
Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static
Sized
+ Eq
+ Copy
+ Clone
+ Send
+ Sync
+ fmt::Debug
+ fmt::Display
+ 'static
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ for<'a> Add<&'a Self, Output = Self>
+ for<'a> Mul<&'a Self, Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ MulAssign
+ AddAssign
+ SubAssign
+ for<'a> MulAssign<&'a Self>
+ for<'a> AddAssign<&'a Self>
+ for<'a> SubAssign<&'a Self>
{
/// Returns an element chosen uniformly at random using a user-provided RNG.
fn random<R: RngCore>(rng: &mut R) -> Self;
@ -37,15 +58,6 @@ pub trait Field:
/// Negates this element.
fn negate(&mut self);
/// Adds another element to this element.
fn add_assign(&mut self, other: &Self);
/// Subtracts another element from this element.
fn sub_assign(&mut self, other: &Self);
/// Multiplies another element by this element.
fn mul_assign(&mut self, other: &Self);
/// Computes the multiplicative inverse of this element, if nonzero.
fn inverse(&self) -> Option<Self>;

View File

@ -1,5 +1,6 @@
use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
use pairing::bls12_381::*;

View File

@ -1,5 +1,6 @@
use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ff::Field;
use pairing::bls12_381::*;

View File

@ -1,5 +1,6 @@
use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ff::{Field, SqrtField};
use pairing::bls12_381::*;

View File

@ -1,5 +1,6 @@
use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, SubAssign};
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
use pairing::bls12_381::*;

View File

@ -627,6 +627,7 @@ pub mod g1 {
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use rand_core::RngCore;
use std::fmt;
use std::ops::{AddAssign, MulAssign, SubAssign};
curve_impl!(
"G1",
@ -1296,6 +1297,7 @@ pub mod g2 {
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use rand_core::RngCore;
use std::fmt;
use std::ops::{AddAssign, MulAssign, SubAssign};
curve_impl!(
"G2",

View File

@ -1,5 +1,6 @@
use super::fq2::Fq2;
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
use std::ops::{AddAssign, MulAssign, SubAssign};
// B coefficient of BLS12-381 curve, 4.
pub const B_COEFF: Fq = Fq(FqRepr([

View File

@ -3,6 +3,7 @@ use super::fq2::Fq2;
use super::fq6::Fq6;
use ff::Field;
use rand_core::RngCore;
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
/// An element of Fq12, represented by c0 + c1 * w.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -39,6 +40,112 @@ impl Fq12 {
}
}
impl<'r> Add<&'r Fq12> for Fq12 {
type Output = Self;
fn add(self, other: &Self) -> Self {
Fq12 {
c0: self.c0 + other.c0,
c1: self.c1 + other.c1,
}
}
}
impl Add for Fq12 {
type Output = Self;
fn add(self, other: Self) -> Self {
self + &other
}
}
impl<'r> AddAssign<&'r Fq12> for Fq12 {
fn add_assign(&mut self, other: &'r Self) {
self.c0.add_assign(&other.c0);
self.c1.add_assign(&other.c1);
}
}
impl AddAssign for Fq12 {
fn add_assign(&mut self, other: Self) {
self.add_assign(&other);
}
}
impl<'r> Sub<&'r Fq12> for Fq12 {
type Output = Self;
fn sub(self, other: &Self) -> Self {
Fq12 {
c0: self.c0 - other.c0,
c1: self.c1 - other.c1,
}
}
}
impl Sub for Fq12 {
type Output = Self;
fn sub(self, other: Self) -> Self {
self - &other
}
}
impl<'r> SubAssign<&'r Fq12> for Fq12 {
fn sub_assign(&mut self, other: &'r Self) {
self.c0.sub_assign(&other.c0);
self.c1.sub_assign(&other.c1);
}
}
impl SubAssign for Fq12 {
fn sub_assign(&mut self, other: Self) {
self.sub_assign(&other);
}
}
impl<'r> Mul<&'r Fq12> for Fq12 {
type Output = Self;
fn mul(self, other: &Self) -> Self {
let mut ret = self;
ret.mul_assign(other);
ret
}
}
impl Mul for Fq12 {
type Output = Self;
fn mul(self, other: Self) -> Self {
self * &other
}
}
impl<'r> MulAssign<&'r Fq12> for Fq12 {
fn mul_assign(&mut self, other: &Self) {
let mut aa = self.c0;
aa.mul_assign(&other.c0);
let mut bb = self.c1;
bb.mul_assign(&other.c1);
let mut o = other.c0;
o.add_assign(&other.c1);
self.c1.add_assign(&self.c0);
self.c1.mul_assign(&o);
self.c1.sub_assign(&aa);
self.c1.sub_assign(&bb);
self.c0 = bb;
self.c0.mul_by_nonresidue();
self.c0.add_assign(&aa);
}
}
impl MulAssign for Fq12 {
fn mul_assign(&mut self, other: Self) {
self.mul_assign(&other);
}
}
impl Field for Fq12 {
fn random<R: RngCore>(rng: &mut R) -> Self {
Fq12 {
@ -75,16 +182,6 @@ impl Field for Fq12 {
self.c1.negate();
}
fn add_assign(&mut self, other: &Self) {
self.c0.add_assign(&other.c0);
self.c1.add_assign(&other.c1);
}
fn sub_assign(&mut self, other: &Self) {
self.c0.sub_assign(&other.c0);
self.c1.sub_assign(&other.c1);
}
fn frobenius_map(&mut self, power: usize) {
self.c0.frobenius_map(power);
self.c1.frobenius_map(power);
@ -111,22 +208,6 @@ impl Field for Fq12 {
self.c0 = c0;
}
fn mul_assign(&mut self, other: &Self) {
let mut aa = self.c0;
aa.mul_assign(&other.c0);
let mut bb = self.c1;
bb.mul_assign(&other.c1);
let mut o = other.c0;
o.add_assign(&other.c1);
self.c1.add_assign(&self.c0);
self.c1.mul_assign(&o);
self.c1.sub_assign(&aa);
self.c1.sub_assign(&bb);
self.c0 = bb;
self.c0.mul_by_nonresidue();
self.c0.add_assign(&aa);
}
fn inverse(&self) -> Option<Self> {
let mut c0s = self.c0;
c0s.square();

View File

@ -1,8 +1,8 @@
use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE};
use ff::{Field, SqrtField};
use rand_core::RngCore;
use std::cmp::Ordering;
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
/// An element of Fq2, represented by c0 + c1 * u.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -56,6 +56,111 @@ impl Fq2 {
}
}
impl<'r> Add<&'r Fq2> for Fq2 {
type Output = Self;
fn add(self, other: &Self) -> Self {
Fq2 {
c0: self.c0 + other.c0,
c1: self.c1 + other.c1,
}
}
}
impl Add for Fq2 {
type Output = Self;
fn add(self, other: Self) -> Self {
self + &other
}
}
impl<'r> AddAssign<&'r Fq2> for Fq2 {
fn add_assign(&mut self, other: &'r Self) {
self.c0.add_assign(&other.c0);
self.c1.add_assign(&other.c1);
}
}
impl AddAssign for Fq2 {
fn add_assign(&mut self, other: Self) {
self.add_assign(&other);
}
}
impl<'r> Sub<&'r Fq2> for Fq2 {
type Output = Self;
fn sub(self, other: &Self) -> Self {
Fq2 {
c0: self.c0 - other.c0,
c1: self.c1 - other.c1,
}
}
}
impl Sub for Fq2 {
type Output = Self;
fn sub(self, other: Self) -> Self {
self - &other
}
}
impl<'r> SubAssign<&'r Fq2> for Fq2 {
fn sub_assign(&mut self, other: &'r Self) {
self.c0.sub_assign(&other.c0);
self.c1.sub_assign(&other.c1);
}
}
impl SubAssign for Fq2 {
fn sub_assign(&mut self, other: Self) {
self.sub_assign(&other);
}
}
impl<'r> Mul<&'r Fq2> for Fq2 {
type Output = Self;
fn mul(self, other: &Self) -> Self {
let mut ret = self;
ret.mul_assign(other);
ret
}
}
impl Mul for Fq2 {
type Output = Self;
fn mul(self, other: Self) -> Self {
self * &other
}
}
impl<'r> MulAssign<&'r Fq2> for Fq2 {
fn mul_assign(&mut self, other: &Self) {
let mut aa = self.c0;
aa.mul_assign(&other.c0);
let mut bb = self.c1;
bb.mul_assign(&other.c1);
let mut o = other.c0;
o.add_assign(&other.c1);
self.c1.add_assign(&self.c0);
self.c1.mul_assign(&o);
self.c1.sub_assign(&aa);
self.c1.sub_assign(&bb);
self.c0 = aa;
self.c0.sub_assign(&bb);
}
}
impl MulAssign for Fq2 {
fn mul_assign(&mut self, other: Self) {
self.mul_assign(&other);
}
}
impl Field for Fq2 {
fn random<R: RngCore>(rng: &mut R) -> Self {
Fq2 {
@ -108,31 +213,6 @@ impl Field for Fq2 {
self.c1.negate();
}
fn add_assign(&mut self, other: &Self) {
self.c0.add_assign(&other.c0);
self.c1.add_assign(&other.c1);
}
fn sub_assign(&mut self, other: &Self) {
self.c0.sub_assign(&other.c0);
self.c1.sub_assign(&other.c1);
}
fn mul_assign(&mut self, other: &Self) {
let mut aa = self.c0;
aa.mul_assign(&other.c0);
let mut bb = self.c1;
bb.mul_assign(&other.c1);
let mut o = other.c0;
o.add_assign(&other.c1);
self.c1.add_assign(&self.c0);
self.c1.mul_assign(&o);
self.c1.sub_assign(&aa);
self.c1.sub_assign(&bb);
self.c0 = aa;
self.c0.sub_assign(&bb);
}
fn inverse(&self) -> Option<Self> {
let mut t1 = self.c1;
t1.square();

View File

@ -2,6 +2,7 @@ use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2};
use super::fq2::Fq2;
use ff::Field;
use rand_core::RngCore;
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
/// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2).
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -99,101 +100,93 @@ impl Fq6 {
}
}
impl Field for Fq6 {
fn random<R: RngCore>(rng: &mut R) -> Self {
impl<'r> Add<&'r Fq6> for Fq6 {
type Output = Self;
fn add(self, other: &Self) -> Self {
Fq6 {
c0: Fq2::random(rng),
c1: Fq2::random(rng),
c2: Fq2::random(rng),
c0: self.c0 + other.c0,
c1: self.c1 + other.c1,
c2: self.c2 + other.c2,
}
}
}
fn zero() -> Self {
Fq6 {
c0: Fq2::zero(),
c1: Fq2::zero(),
c2: Fq2::zero(),
}
impl Add for Fq6 {
type Output = Self;
fn add(self, other: Self) -> Self {
self + &other
}
}
fn one() -> Self {
Fq6 {
c0: Fq2::one(),
c1: Fq2::zero(),
c2: Fq2::zero(),
}
}
fn is_zero(&self) -> bool {
self.c0.is_zero() && self.c1.is_zero() && self.c2.is_zero()
}
fn double(&mut self) {
self.c0.double();
self.c1.double();
self.c2.double();
}
fn negate(&mut self) {
self.c0.negate();
self.c1.negate();
self.c2.negate();
}
fn add_assign(&mut self, other: &Self) {
impl<'r> AddAssign<&'r Fq6> for Fq6 {
fn add_assign(&mut self, other: &'r Self) {
self.c0.add_assign(&other.c0);
self.c1.add_assign(&other.c1);
self.c2.add_assign(&other.c2);
}
}
fn sub_assign(&mut self, other: &Self) {
impl AddAssign for Fq6 {
fn add_assign(&mut self, other: Self) {
self.add_assign(&other);
}
}
impl<'r> Sub<&'r Fq6> for Fq6 {
type Output = Self;
fn sub(self, other: &Self) -> Self {
Fq6 {
c0: self.c0 - other.c0,
c1: self.c1 - other.c1,
c2: self.c2 - other.c2,
}
}
}
impl Sub for Fq6 {
type Output = Self;
fn sub(self, other: Self) -> Self {
self - &other
}
}
impl<'r> SubAssign<&'r Fq6> for Fq6 {
fn sub_assign(&mut self, other: &'r Self) {
self.c0.sub_assign(&other.c0);
self.c1.sub_assign(&other.c1);
self.c2.sub_assign(&other.c2);
}
}
fn frobenius_map(&mut self, power: usize) {
self.c0.frobenius_map(power);
self.c1.frobenius_map(power);
self.c2.frobenius_map(power);
self.c1.mul_assign(&FROBENIUS_COEFF_FQ6_C1[power % 6]);
self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]);
impl SubAssign for Fq6 {
fn sub_assign(&mut self, other: Self) {
self.sub_assign(&other);
}
}
fn square(&mut self) {
let mut s0 = self.c0;
s0.square();
let mut ab = self.c0;
ab.mul_assign(&self.c1);
let mut s1 = ab;
s1.double();
let mut s2 = self.c0;
s2.sub_assign(&self.c1);
s2.add_assign(&self.c2);
s2.square();
let mut bc = self.c1;
bc.mul_assign(&self.c2);
let mut s3 = bc;
s3.double();
let mut s4 = self.c2;
s4.square();
impl<'r> Mul<&'r Fq6> for Fq6 {
type Output = Self;
self.c0 = s3;
self.c0.mul_by_nonresidue();
self.c0.add_assign(&s0);
self.c1 = s4;
self.c1.mul_by_nonresidue();
self.c1.add_assign(&s1);
self.c2 = s1;
self.c2.add_assign(&s2);
self.c2.add_assign(&s3);
self.c2.sub_assign(&s0);
self.c2.sub_assign(&s4);
fn mul(self, other: &Self) -> Self {
let mut ret = self;
ret.mul_assign(other);
ret
}
}
impl Mul for Fq6 {
type Output = Self;
fn mul(self, other: Self) -> Self {
self * &other
}
}
impl<'r> MulAssign<&'r Fq6> for Fq6 {
fn mul_assign(&mut self, other: &Self) {
let mut a_a = self.c0;
let mut b_b = self.c1;
@ -244,6 +237,96 @@ impl Field for Fq6 {
self.c1 = t2;
self.c2 = t3;
}
}
impl MulAssign for Fq6 {
fn mul_assign(&mut self, other: Self) {
self.mul_assign(&other);
}
}
impl Field for Fq6 {
fn random<R: RngCore>(rng: &mut R) -> Self {
Fq6 {
c0: Fq2::random(rng),
c1: Fq2::random(rng),
c2: Fq2::random(rng),
}
}
fn zero() -> Self {
Fq6 {
c0: Fq2::zero(),
c1: Fq2::zero(),
c2: Fq2::zero(),
}
}
fn one() -> Self {
Fq6 {
c0: Fq2::one(),
c1: Fq2::zero(),
c2: Fq2::zero(),
}
}
fn is_zero(&self) -> bool {
self.c0.is_zero() && self.c1.is_zero() && self.c2.is_zero()
}
fn double(&mut self) {
self.c0.double();
self.c1.double();
self.c2.double();
}
fn negate(&mut self) {
self.c0.negate();
self.c1.negate();
self.c2.negate();
}
fn frobenius_map(&mut self, power: usize) {
self.c0.frobenius_map(power);
self.c1.frobenius_map(power);
self.c2.frobenius_map(power);
self.c1.mul_assign(&FROBENIUS_COEFF_FQ6_C1[power % 6]);
self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]);
}
fn square(&mut self) {
let mut s0 = self.c0;
s0.square();
let mut ab = self.c0;
ab.mul_assign(&self.c1);
let mut s1 = ab;
s1.double();
let mut s2 = self.c0;
s2.sub_assign(&self.c1);
s2.add_assign(&self.c2);
s2.square();
let mut bc = self.c1;
bc.mul_assign(&self.c2);
let mut s3 = bc;
s3.double();
let mut s4 = self.c2;
s4.square();
self.c0 = s3;
self.c0.mul_by_nonresidue();
self.c0.add_assign(&s0);
self.c1 = s4;
self.c1.mul_by_nonresidue();
self.c1.add_assign(&s1);
self.c2 = s1;
self.c2.add_assign(&s2);
self.c2.add_assign(&s3);
self.c2.sub_assign(&s0);
self.c2.sub_assign(&s4);
}
fn inverse(&self) -> Option<Self> {
let mut c0 = self.c2;

View File

@ -1,4 +1,5 @@
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
use std::ops::{AddAssign, MulAssign, SubAssign};
#[derive(PrimeField)]
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]

View File

@ -25,6 +25,7 @@ use super::{Engine, PairingCurveAffine};
use ff::{BitIterator, Field, ScalarEngine};
use group::CurveAffine;
use std::ops::{AddAssign, MulAssign, SubAssign};
// The BLS parameter x for BLS12-381 is -0xd201000000010000
const BLS_X: u64 = 0xd201000000010000;

View File

@ -1,6 +1,7 @@
use group::{CurveAffine, CurveProjective};
use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::MulAssign;
use crate::{Engine, Field, PairingCurveAffine, PrimeField};

View File

@ -1,4 +1,5 @@
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use std::ops::{AddAssign, MulAssign, SubAssign};
use super::{montgomery, JubjubEngine, JubjubParams, PrimeOrder, Unknown};

View File

@ -5,6 +5,7 @@ use ff::{
PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField,
};
use rand_core::RngCore;
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
use super::ToUniform;
@ -268,6 +269,141 @@ impl From<Fs> for FsRepr {
}
}
impl<'r> Add<&'r Fs> for Fs {
type Output = Self;
#[inline]
fn add(self, other: &Self) -> Self {
let mut ret = self;
ret.add_assign(other);
ret
}
}
impl Add for Fs {
type Output = Self;
#[inline]
fn add(self, other: Self) -> Self {
self + &other
}
}
impl<'r> AddAssign<&'r Fs> for Fs {
#[inline]
fn add_assign(&mut self, other: &Self) {
// This cannot exceed the backing capacity.
self.0.add_nocarry(&other.0);
// However, it may need to be reduced.
self.reduce();
}
}
impl AddAssign for Fs {
#[inline]
fn add_assign(&mut self, other: Self) {
self.add_assign(&other);
}
}
impl<'r> Sub<&'r Fs> for Fs {
type Output = Self;
#[inline]
fn sub(self, other: &Self) -> Self {
let mut ret = self;
ret.sub_assign(other);
ret
}
}
impl Sub for Fs {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self {
self - &other
}
}
impl<'r> SubAssign<&'r Fs> for Fs {
#[inline]
fn sub_assign(&mut self, other: &Self) {
// If `other` is larger than `self`, we'll need to add the modulus to self first.
if other.0 > self.0 {
self.0.add_nocarry(&MODULUS);
}
self.0.sub_noborrow(&other.0);
}
}
impl SubAssign for Fs {
#[inline]
fn sub_assign(&mut self, other: Self) {
self.sub_assign(&other);
}
}
impl<'r> Mul<&'r Fs> for Fs {
type Output = Self;
#[inline]
fn mul(self, other: &Self) -> Self {
let mut ret = self;
ret.mul_assign(other);
ret
}
}
impl Mul for Fs {
type Output = Self;
#[inline]
fn mul(self, other: Self) -> Self {
self * &other
}
}
impl<'r> MulAssign<&'r Fs> for Fs {
#[inline]
fn mul_assign(&mut self, other: &Self) {
let mut carry = 0;
let r0 = mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry);
let r1 = mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry);
let r2 = mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry);
let r3 = mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry);
let r4 = carry;
let mut carry = 0;
let r1 = mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry);
let r2 = mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry);
let r3 = mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry);
let r4 = mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry);
let r5 = carry;
let mut carry = 0;
let r2 = mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry);
let r3 = mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry);
let r4 = mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry);
let r5 = mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry);
let r6 = carry;
let mut carry = 0;
let r3 = mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry);
let r4 = mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry);
let r5 = mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry);
let r6 = mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry);
let r7 = carry;
self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7);
}
}
impl MulAssign for Fs {
#[inline]
fn mul_assign(&mut self, other: Self) {
self.mul_assign(&other);
}
}
impl PrimeField for Fs {
type Repr = FsRepr;
@ -351,15 +487,6 @@ impl Field for Fs {
self.0.is_zero()
}
#[inline]
fn add_assign(&mut self, other: &Fs) {
// This cannot exceed the backing capacity.
self.0.add_nocarry(&other.0);
// However, it may need to be reduced.
self.reduce();
}
#[inline]
fn double(&mut self) {
// This cannot exceed the backing capacity.
@ -369,16 +496,6 @@ impl Field for Fs {
self.reduce();
}
#[inline]
fn sub_assign(&mut self, other: &Fs) {
// If `other` is larger than `self`, we'll need to add the modulus to self first.
if other.0 > self.0 {
self.0.add_nocarry(&MODULUS);
}
self.0.sub_noborrow(&other.0);
}
#[inline]
fn negate(&mut self) {
if !self.is_zero() {
@ -448,35 +565,6 @@ impl Field for Fs {
// This has no effect in a prime field.
}
#[inline]
fn mul_assign(&mut self, other: &Fs) {
let mut carry = 0;
let r0 = mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry);
let r1 = mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry);
let r2 = mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry);
let r3 = mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry);
let r4 = carry;
let mut carry = 0;
let r1 = mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry);
let r2 = mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry);
let r3 = mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry);
let r4 = mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry);
let r5 = carry;
let mut carry = 0;
let r2 = mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry);
let r3 = mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry);
let r4 = mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry);
let r5 = mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry);
let r6 = carry;
let mut carry = 0;
let r3 = mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry);
let r4 = mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry);
let r5 = mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry);
let r6 = mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry);
let r7 = carry;
self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7);
}
#[inline]
fn square(&mut self) {
let mut carry = 0;

View File

@ -1,4 +1,5 @@
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use std::ops::{AddAssign, MulAssign, SubAssign};
use super::{edwards, JubjubEngine, JubjubParams, PrimeOrder, Unknown};

View File

@ -1,6 +1,7 @@
use super::{edwards, montgomery, JubjubEngine, JubjubParams, PrimeOrder};
use ff::{Field, LegendreSymbol, PrimeField, PrimeFieldRepr, SqrtField};
use std::ops::{AddAssign, MulAssign, SubAssign};
use rand_core::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

View File

@ -2,6 +2,7 @@
use crate::jubjub::*;
use ff::{Field, PrimeField, PrimeFieldRepr};
use std::ops::AddAssign;
#[derive(Copy, Clone)]
pub enum Personalization {

View File

@ -7,6 +7,7 @@ use crate::jubjub::{edwards::Point, FixedGenerators, JubjubEngine, JubjubParams,
use ff::{Field, PrimeField, PrimeFieldRepr};
use rand_core::RngCore;
use std::io::{self, Read, Write};
use std::ops::{AddAssign, MulAssign};
use crate::util::hash_to_scalar;

View File

@ -5,9 +5,9 @@
use aes::Aes256;
use blake2b_simd::Params as Blake2bParams;
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use ff::Field;
use fpe::ff1::{BinaryNumeralString, FF1};
use pairing::bls12_381::Bls12;
use std::ops::AddAssign;
use crate::{
jubjub::{fs::Fs, FixedGenerators, JubjubEngine, JubjubParams, ToUniform},

View File

@ -2,6 +2,7 @@
use ff::Field;
use pairing::Engine;
use std::ops::{AddAssign, MulAssign, SubAssign};
use bellman::{ConstraintSystem, SynthesisError};
@ -668,6 +669,7 @@ mod test {
use pairing::bls12_381::{Bls12, Fr};
use rand_core::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;
use std::ops::SubAssign;
use bellman::gadgets::test::*;
use zcash_primitives::jubjub::fs::Fs;

View File

@ -5,6 +5,7 @@ use bellman::{
use ff::Field;
use pairing::bls12_381::{Bls12, Fr};
use rand_core::OsRng;
use std::ops::AddAssign;
use zcash_primitives::{
jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown},
primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment},