diff --git a/Cargo.toml b/Cargo.toml index 6897e12..301da77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,16 +22,16 @@ zeroize = { version = "1.7", default-features = false } num-bigint = { version = "0.4.4", optional = true, default-features = false } # std hashbrown = { version = "0.14.3", optional = true } -ark-relations = { version = "0.4", optional = true } -ark-r1cs-std = { version = "0.4", optional = true } -ark-std = { version = "0.4", optional = true } -ark-ec = { version = "0.4", optional = true } -ark-ff = { version = "0.4", optional = true } -ark-serialize = { version = "0.4", optional = true } -ark-bls12-377 = { version = "0.4", optional = true } -ark-ed-on-bls12-377 = { version = "0.4", optional = true } -ark-groth16 = { version = "0.4", optional = true } -ark-snark = { version = "0.4", optional = true } +ark-relations = { version = "0.5", optional = true } +ark-r1cs-std = { version = "0.5", optional = true } +ark-std = { version = "0.5", optional = true } +ark-ec = { version = "0.5", optional = true } +ark-ff = { version = "0.5", optional = true } +ark-serialize = { version = "0.5", optional = true } +ark-bls12-377 = { version = "0.5", optional = true } +ark-ed-on-bls12-377 = { version = "0.5", optional = true } +ark-groth16 = { version = "0.5", optional = true } +ark-snark = { version = "0.5", optional = true } once_cell = { version = "1.8", optional = true, default-features = false } # This matches what ark-std (a library for no_std compatibility) does, having diff --git a/src/ark_curve/bls12_377.rs b/src/ark_curve/bls12_377.rs index 69f48df..8a201e2 100644 --- a/src/ark_curve/bls12_377.rs +++ b/src/ark_curve/bls12_377.rs @@ -5,7 +5,9 @@ use ark_ec::{ models::CurveConfig, short_weierstrass::Affine, }; -use ark_ff::{fields::models::fp2::Fp2Config, Field, Fp12Config, Fp2, Fp6, Fp6Config}; +use ark_ff::{ + fields::models::fp2::Fp2Config, AdditiveGroup, Field, Fp12Config, Fp2, Fp6, Fp6Config, +}; pub struct F2Config; diff --git a/src/ark_curve/element.rs b/src/ark_curve/element.rs index 79a1366..a449b9c 100644 --- a/src/ark_curve/element.rs +++ b/src/ark_curve/element.rs @@ -1,6 +1,8 @@ -use ark_ec::{AffineRepr, CurveGroup, Group, ScalarMul, VariableBaseMSM}; +use ark_ec::{AffineRepr, CurveGroup, PrimeGroup, ScalarMul, VariableBaseMSM}; +use ark_ff::AdditiveGroup; use ark_serialize::Valid; use ark_std::vec::Vec; +use core::ops::AddAssign; use crate::{ ark_curve::{edwards::EdwardsAffine, Decaf377EdwardsConfig, EdwardsProjective}, @@ -36,25 +38,6 @@ impl ScalarMul for Element { impl VariableBaseMSM for Element {} -impl Group for Element { - type ScalarField = Fr; - - fn double_in_place(&mut self) -> &mut Self { - let inner = *self.inner.double_in_place(); - *self = Element { inner }; - self - } - - fn generator() -> Self { - Self::GENERATOR - } - - fn mul_bigint(&self, other: impl AsRef<[u64]>) -> Self { - let inner = self.inner.mul_bigint(other); - Element { inner } - } -} - impl CurveGroup for Element { // We implement `CurveGroup` as it is required by the `CurveVar` // trait used in the R1CS feature. The `ProjectiveCurve` trait requires @@ -100,7 +83,7 @@ impl AffineRepr for AffinePoint { type Group = Element; - fn xy(&self) -> Option<(&Self::BaseField, &Self::BaseField)> { + fn xy(&self) -> Option<(Self::BaseField, Self::BaseField)> { self.inner.xy() } @@ -165,3 +148,38 @@ impl From<&AffinePoint> for Element { } } } + +impl PrimeGroup for Element { + type ScalarField = Fr; + + fn generator() -> Self { + Self::GENERATOR + } + + fn mul_bigint(&self, other: impl AsRef<[u64]>) -> Self { + let inner = self.inner.mul_bigint(other); + Element { inner } + } +} + +impl AdditiveGroup for Element { + type Scalar = Fr; + + const ZERO: Self = Self::ZERO; + + fn double(&self) -> Self { + let mut copy = *self; + copy.double_in_place(); + copy + } + + fn double_in_place(&mut self) -> &mut Self { + self.add_assign(*self); + self + } + + fn neg_in_place(&mut self) -> &mut Self { + *self = -(*self); + self + } +} diff --git a/src/ark_curve/element/projective.rs b/src/ark_curve/element/projective.rs index de75f83..0ae5da0 100644 --- a/src/ark_curve/element/projective.rs +++ b/src/ark_curve/element/projective.rs @@ -1,15 +1,11 @@ -use core::borrow::Borrow; -use core::hash::Hash; - +use super::super::constants::{B_T, B_X, B_Y, B_Z}; +use crate::{ark_curve::EdwardsProjective, Fq, Fr}; use ark_ff::Zero; use ark_std::fmt::{Display, Formatter, Result as FmtResult}; - +use core::borrow::Borrow; +use core::hash::Hash; use zeroize::Zeroize; -use crate::{ark_curve::EdwardsProjective, Fq, Fr}; - -use super::super::constants::{B_T, B_X, B_Y, B_Z}; - #[derive(Copy, Clone)] pub struct Element { pub(crate) inner: EdwardsProjective, @@ -24,6 +20,10 @@ impl Element { pub const IDENTITY: Self = Self { inner: EdwardsProjective::new_unchecked(Fq::ZERO, Fq::ONE, Fq::ZERO, Fq::ONE), }; + + pub const ZERO: Self = Self { + inner: EdwardsProjective::new_unchecked(Fq::ZERO, Fq::ZERO, Fq::ZERO, Fq::ZERO), + }; } impl Hash for Element { diff --git a/src/ark_curve/on_curve.rs b/src/ark_curve/on_curve.rs index 5506786..ab2a139 100644 --- a/src/ark_curve/on_curve.rs +++ b/src/ark_curve/on_curve.rs @@ -1,6 +1,6 @@ use ark_ec::{ - models::{twisted_edwards::Projective, twisted_edwards::TECurveConfig}, - Group, + models::twisted_edwards::{Projective, TECurveConfig}, + PrimeGroup, }; use ark_ff::{BigInteger, Field, PrimeField, Zero}; use ark_serialize::CanonicalSerialize; diff --git a/src/ark_curve/ops/affine.rs b/src/ark_curve/ops/affine.rs index 2568170..a72766c 100644 --- a/src/ark_curve/ops/affine.rs +++ b/src/ark_curve/ops/affine.rs @@ -56,10 +56,10 @@ impl<'a, 'b> Sub<&'b AffinePoint> for &'a AffinePoint { } impl<'b> Sub<&'b AffinePoint> for AffinePoint { - type Output = AffinePoint; + type Output = Element; - fn sub(self, other: &'b AffinePoint) -> AffinePoint { - &self - other + fn sub(self, other: &'b AffinePoint) -> Element { + (&self - other).into() } } @@ -72,9 +72,43 @@ impl<'a> Sub for &'a AffinePoint { } impl Sub for AffinePoint { - type Output = AffinePoint; + type Output = Element; - fn sub(self, other: AffinePoint) -> AffinePoint { + fn sub(self, other: AffinePoint) -> Element { + (&self - &other).into() + } +} + +impl<'a, 'b> Sub<&'b Element> for &'a AffinePoint { + type Output = Element; + + fn sub(self, other: &'b Element) -> Element { + Element { + inner: self.inner - other.inner, + } + } +} + +impl<'b> Sub<&'b Element> for AffinePoint { + type Output = Element; + + fn sub(self, other: &'b Element) -> Element { + &self - other + } +} + +impl<'a> Sub for &'a AffinePoint { + type Output = Element; + + fn sub(self, other: Element) -> Element { + self - &other + } +} + +impl Sub for AffinePoint { + type Output = Element; + + fn sub(self, other: Element) -> Element { &self - &other } } diff --git a/src/ark_curve/ops/projective.rs b/src/ark_curve/ops/projective.rs index da530bc..09f90a0 100644 --- a/src/ark_curve/ops/projective.rs +++ b/src/ark_curve/ops/projective.rs @@ -1,6 +1,5 @@ -use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; - use crate::{ark_curve::element::projective::Element, ark_curve::AffinePoint, Fr}; +use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; impl<'a, 'b> Add<&'b Element> for &'a Element { type Output = Element; @@ -274,3 +273,57 @@ impl Sub for Element { &self - &other.into() } } + +impl<'a> Add<&'a mut Element> for Element { + type Output = Element; + + fn add(self, other: &'a mut Self) -> Element { + Element { + inner: self.inner + other.inner, + } + } +} + +impl<'a> Sub<&'a mut Element> for Element { + type Output = Element; + + fn sub(self, other: &'a mut Element) -> Element { + Element { + inner: self.inner - other.inner, + } + } +} + +impl<'a> AddAssign<&'a mut Element> for Element { + fn add_assign(&mut self, other: &'a mut Element) { + *self = Element { + inner: self.inner + other.inner, + } + } +} + +impl<'a> SubAssign<&'a mut Element> for Element { + fn sub_assign(&mut self, other: &'a mut Element) { + *self = Element { + inner: self.inner - other.inner, + } + } +} + +impl<'a> Mul<&'a mut Fr> for Element { + type Output = Element; + + fn mul(self, point: &'a mut Fr) -> Self::Output { + let mut p = self.inner; + p *= *point; + Element { inner: p } + } +} + +impl<'a> MulAssign<&'a mut Fr> for Element { + fn mul_assign(&mut self, point: &'a mut Fr) { + let mut p = self.inner; + p *= *point; + *self = Element { inner: p } + } +} diff --git a/src/ark_curve/r1cs/element.rs b/src/ark_curve/r1cs/element.rs index 036b4bd..539a0a5 100644 --- a/src/ark_curve/r1cs/element.rs +++ b/src/ark_curve/r1cs/element.rs @@ -1,17 +1,20 @@ #![allow(non_snake_case)] use core::borrow::Borrow; +use core::ops::{Mul, MulAssign}; use ark_ec::AffineRepr; +use ark_r1cs_std::convert::ToConstraintFieldGadget; +use ark_r1cs_std::fields::emulated_fp::EmulatedFpVar; use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, prelude::*, R1CSVar}; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; use ark_std::vec::Vec; +use super::inner::{Decaf377EdwardsVar, ScalarMultiply, ScalarMultiplyAssign}; use crate::ark_curve::r1cs::{lazy::LazyElementVar, FqVar}; use crate::ark_curve::{edwards::EdwardsAffine, r1cs::inner::ElementVar as InnerElementVar}; use crate::ark_curve::{AffinePoint, Element}; -use crate::Fq; - -use super::inner::Decaf377EdwardsVar; +use crate::{Fq, Fr}; +use ark_r1cs_std::prelude::ToBitsGadget; #[derive(Clone, Debug)] /// Represents the R1CS equivalent of a `decaf377::Element` @@ -187,13 +190,13 @@ impl ToBitsGadget for ElementVar { } impl ToBytesGadget for ElementVar { - fn to_bytes(&self) -> Result>, SynthesisError> { + fn to_bytes_le(&self) -> Result>, SynthesisError> { let compressed_fq = self .inner .element() .expect("element will exist") - .to_bytes()?; - let encoded_bytes = compressed_fq.to_bytes()?; + .to_bytes_le()?; + let encoded_bytes = compressed_fq.to_bytes_le()?; Ok(encoded_bytes) } } @@ -256,3 +259,48 @@ impl CurveVar for ElementVar { }) } } + +// Scalar multiplication +impl ScalarMultiplyAssign, LazyElementVar> for LazyElementVar { + fn mul_assign_scalar(&mut self, scalar: EmulatedFpVar) { + *self = LazyElementVar::new_from_element(self.element().unwrap() * scalar); + } +} + +impl ScalarMultiply, LazyElementVar> for LazyElementVar { + fn mul_with_scalar(&self, scalar: &EmulatedFpVar) -> LazyElementVar { + LazyElementVar::new_from_element(self.element().unwrap() * scalar.clone()) + } +} + +impl MulAssign> for ElementVar { + fn mul_assign(&mut self, scalar: EmulatedFpVar) { + self.inner.mul_assign_scalar(scalar); + } +} + +impl<'a> Mul<&'a EmulatedFpVar> for ElementVar { + type Output = ElementVar; + + fn mul(self, scalar: &'a EmulatedFpVar) -> Self::Output { + ElementVar { + inner: self.inner.mul_with_scalar(scalar), + } + } +} + +impl Mul> for ElementVar { + type Output = ElementVar; + + fn mul(self, scalar: EmulatedFpVar) -> Self::Output { + self * &scalar + } +} + +impl ToConstraintFieldGadget for ElementVar { + fn to_constraint_field( + &self, + ) -> Result>, ark_relations::r1cs::SynthesisError> { + unimplemented!() + } +} diff --git a/src/ark_curve/r1cs/fqvar_ext.rs b/src/ark_curve/r1cs/fqvar_ext.rs index f3014de..95865d8 100644 --- a/src/ark_curve/r1cs/fqvar_ext.rs +++ b/src/ark_curve/r1cs/fqvar_ext.rs @@ -1,11 +1,13 @@ +use crate::ark_curve::{constants::ZETA, r1cs::FqVar}; +use crate::Fq; use ark_r1cs_std::eq::EqGadget; +use ark_r1cs_std::prelude::ToBitsGadget; use ark_r1cs_std::prelude::{AllocVar, Boolean, FieldVar}; use ark_r1cs_std::select::CondSelectGadget; -use ark_r1cs_std::{R1CSVar, ToBitsGadget}; +use ark_r1cs_std::R1CSVar; use ark_relations::r1cs::SynthesisError; - -use crate::ark_curve::{constants::ZETA, r1cs::FqVar}; -use crate::Fq; +use ark_std::println; +use Boolean::*; pub trait FqVarExtension: Sized { fn isqrt(&self) -> Result<(Boolean, FqVar), SynthesisError>; @@ -16,6 +18,10 @@ pub trait FqVarExtension: Sized { fn is_negative(&self) -> Result, SynthesisError>; fn is_nonnegative(&self) -> Result, SynthesisError>; fn abs(self) -> Result; + fn not(boolean: &Boolean) -> Result, SynthesisError>; + fn not_in_place(boolean: Boolean) -> Result, SynthesisError>; + fn and(a: &Boolean, b: &Boolean) -> Result, SynthesisError>; + fn or(a: &Boolean, b: &Boolean) -> Result, SynthesisError>; } impl FqVarExtension for FqVar { @@ -27,6 +33,8 @@ impl FqVarExtension for FqVar { /// - Case 3: `(false, 0)` if `den` is zero; /// - Case 4: `(false, sqrt(zeta*num/den))` if `num` and `den` are both nonzero and `num/den` is nonsquare; fn isqrt(&self) -> Result<(Boolean, FqVar), SynthesisError> { + println!("isSqrt!"); + // During mode `SynthesisMode::Setup`, value() will not provide a field element. let den = self.value().unwrap_or(Fq::ONE); @@ -55,27 +63,29 @@ impl FqVarExtension for FqVar { y_squared_var.conditional_enforce_equal(&den_var_inv, &in_case_1)?; // Case 3: `(false, 0)` if `den` is zero - let was_not_square_var = was_square_var.not(); - let in_case_3 = was_not_square_var.and(&den_var_is_zero)?; + + let was_not_square_var = Self::not(&was_square_var)?; + let in_case_3 = Self::and(&was_not_square_var, &den_var_is_zero)?; // Certify the return value y is 0 when we're in case 3. y_squared_var.conditional_enforce_equal(&FqVar::zero(), &in_case_3)?; // Case 4: `(false, sqrt(zeta*num/den))` if `num` and `den` are both nonzero and `num/den` is nonsquare; let zeta_var = FqVar::new_constant(cs, ZETA)?; let zeta_times_one_over_den_var = zeta_var * den_var_inv; - let in_case_4 = was_not_square_var.and(&den_var_is_zero.not())?; + let is_den_var_is_zero = Self::not(&den_var_is_zero)?; + let in_case_4 = Self::and(&was_not_square_var, &is_den_var_is_zero)?; // Certify the return value y is sqrt(zeta * 1/den) y_squared_var.conditional_enforce_equal(&zeta_times_one_over_den_var, &in_case_4)?; // Ensure that we are in case 1, 3, or 4. - let in_case = in_case_1.or(&in_case_3)?.or(&in_case_4)?; + let in_case = Self::or(&in_case_1, &Self::or(&in_case_3, &in_case_4)?)?; in_case.enforce_equal(&Boolean::TRUE)?; Ok((was_square_var, y_var)) } fn is_negative(&self) -> Result, SynthesisError> { - Ok(self.is_nonnegative()?.not()) + Ok(Self::not(&self.is_nonnegative()?)?) } fn is_nonnegative(&self) -> Result, SynthesisError> { @@ -86,7 +96,7 @@ impl FqVarExtension for FqVar { let false_var = Boolean::::FALSE; // Check least significant bit - let lhs = bitvars[0].and(&true_var)?; + let lhs = Self::and(&bitvars[0], &true_var)?; let is_nonnegative_var = lhs.is_eq(&false_var)?; Ok(is_nonnegative_var) @@ -97,4 +107,38 @@ impl FqVarExtension for FqVar { FqVar::conditionally_select(&self.is_nonnegative()?, &self, &self.negate()?)?; Ok(absolute_value) } + + // The methods for logical operations (and, or, not) were moved from the Boolean + // enum to helper functions in AllocatedBool. Consequently, we need to do some + // cursed redirection for the the Boolean enum to delegate these operations to the + // underlying AllocatedBool when applicable. + fn not(boolean: &Boolean) -> Result, SynthesisError> { + Ok(Self::not_in_place(boolean.clone())?) + } + + fn not_in_place(mut boolean: Boolean) -> Result, SynthesisError> { + match &mut boolean { + Boolean::Constant(c) => *c = !*c, + Boolean::Var(v) => *v = v.not()?, + } + Ok(boolean) + } + + fn and(a: &Boolean, b: &Boolean) -> Result, SynthesisError> { + match (a, b) { + // false AND x is always false + (&Constant(false), _) | (_, &Constant(false)) => Ok(Constant(false)), + // true AND x is always x + (&Constant(true), x) | (x, &Constant(true)) => Ok(x.clone()), + (Var(ref x), Var(ref y)) => Ok(Var(x.and(y)?)), + } + } + + fn or(a: &Boolean, b: &Boolean) -> Result, SynthesisError> { + match (a, b) { + (&Constant(false), x) | (x, &Constant(false)) => Ok(x.clone()), + (&Constant(true), _) | (_, &Constant(true)) => Ok(Constant(true)), + (Var(ref x), Var(ref y)) => Ok(Var(x.or(y)?)), + } + } } diff --git a/src/ark_curve/r1cs/inner.rs b/src/ark_curve/r1cs/inner.rs index 85e8111..a0788df 100644 --- a/src/ark_curve/r1cs/inner.rs +++ b/src/ark_curve/r1cs/inner.rs @@ -1,22 +1,22 @@ #![allow(non_snake_case)] -use core::borrow::Borrow; -use core::ops::{Add, AddAssign, Sub, SubAssign}; - +use crate::ark_curve::{ + constants::ZETA, edwards::EdwardsAffine, r1cs::fqvar_ext::FqVarExtension, r1cs::FqVar, + AffinePoint, Decaf377EdwardsConfig, Element, +}; +use crate::{Fq, Fr}; use ark_ec::{twisted_edwards::TECurveConfig, AffineRepr}; +use ark_r1cs_std::convert::ToConstraintFieldGadget; +use ark_r1cs_std::fields::emulated_fp::EmulatedFpVar; use ark_r1cs_std::{ alloc::AllocVar, eq::EqGadget, groups::curves::twisted_edwards::AffineVar, prelude::*, R1CSVar, }; use ark_relations::ns; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; use ark_std::vec::Vec; - -use crate::ark_curve::{ - constants::ZETA, edwards::EdwardsAffine, r1cs::fqvar_ext::FqVarExtension, r1cs::FqVar, - AffinePoint, Decaf377EdwardsConfig, Element, -}; -use crate::Fq; - +use core::borrow::Borrow; +use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; pub(crate) type Decaf377EdwardsVar = AffineVar; +use ark_r1cs_std::prelude::ToBitsGadget; #[derive(Clone, Debug)] /// Represents the R1CS equivalent of a `decaf377::Element` @@ -306,9 +306,9 @@ impl ToBitsGadget for ElementVar { } impl ToBytesGadget for ElementVar { - fn to_bytes(&self) -> Result>, SynthesisError> { - let compressed_fq = self.inner.to_bytes()?; - let encoded_bytes = compressed_fq.to_bytes()?; + fn to_bytes_le(&self) -> Result>, SynthesisError> { + let compressed_fq = self.inner.to_bytes_le()?; + let encoded_bytes = compressed_fq.to_bytes_le()?; Ok(encoded_bytes) } } @@ -409,6 +409,62 @@ impl AddAssign for ElementVar { } } +impl MulAssign> for ElementVar { + fn mul_assign(&mut self, rhs: EmulatedFpVar) { + *self = ElementVar { + inner: self.inner.clone() * rhs, + }; + } +} + +// Scalar multiplication +pub trait ScalarMultiplyAssign { + fn mul_assign_scalar(&mut self, scalar: Scalar); +} + +impl ScalarMultiplyAssign, Decaf377EdwardsVar> for Decaf377EdwardsVar { + fn mul_assign_scalar(&mut self, scalar: EmulatedFpVar) { + let result = self.clone() * scalar; + *self = result; + } +} + +pub trait ScalarMultiply { + fn mul_with_scalar(&self, scalar: &Scalar) -> Output; +} + +impl ScalarMultiply, Decaf377EdwardsVar> for Decaf377EdwardsVar { + fn mul_with_scalar(&self, scalar: &EmulatedFpVar) -> Decaf377EdwardsVar { + self.clone() * scalar.clone() + } +} + +impl<'a> Mul<&'a EmulatedFpVar> for ElementVar { + type Output = ElementVar; + + fn mul(self, scalar: &'a EmulatedFpVar) -> Self::Output { + ElementVar { + inner: self.inner.mul_with_scalar(scalar), + } + } +} + +impl Mul> for ElementVar { + type Output = ElementVar; + + fn mul(self, scalar: EmulatedFpVar) -> Self::Output { + self * &scalar + } +} + +impl ToConstraintFieldGadget for ElementVar { + fn to_constraint_field( + &self, + ) -> Result>, ark_relations::r1cs::SynthesisError> { + unimplemented!() + } +} + impl<'a> GroupOpsBounds<'a, Element, ElementVar> for ElementVar {} impl CurveVar for ElementVar { diff --git a/src/fields/fp/arkworks.rs b/src/fields/fp/arkworks.rs index 2596019..d70a7aa 100644 --- a/src/fields/fp/arkworks.rs +++ b/src/fields/fp/arkworks.rs @@ -1,12 +1,15 @@ use super::Fp; -use ark_ff::{BigInt, Field, PrimeField, SqrtPrecomputation}; +use ark_ff::{AdditiveGroup, BigInt, Field, PrimeField, SqrtPrecomputation}; use ark_ff::{BigInteger, FftField}; use ark_serialize::{ CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize, - CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, SerializationError, Valid, Validate, + CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, Read, SerializationError, Valid, + Validate, Write, }; +use ark_std::vec::Vec; use ark_std::{rand, str::FromStr, string::ToString, One, Zero}; use core::convert::TryInto; +use core::ops::AddAssign; use core::{ fmt::{Display, Formatter}, iter, @@ -58,7 +61,6 @@ impl PrimeField for Fp { impl Field for Fp { type BasePrimeField = Self; - type BasePrimeFieldIter = iter::Once; const SQRT_PRECOMP: Option> = Some(SqrtPrecomputation::TonelliShanks { @@ -67,8 +69,6 @@ impl Field for Fp { trace_of_modulus_minus_one_div_two: &Self::TRACE_MINUS_ONE_DIV_TWO_LIMBS, }); - const ZERO: Self = Self::ZERO; - // Montomgery representation of one const ONE: Self = Self::ONE; @@ -76,11 +76,14 @@ impl Field for Fp { 1 } - fn to_base_prime_field_elements(&self) -> Self::BasePrimeFieldIter { + fn to_base_prime_field_elements(&self) -> impl Iterator { iter::once(*self) } - fn from_base_prime_field_elems(elems: &[Self::BasePrimeField]) -> Option { + fn from_base_prime_field_elems( + elems: impl IntoIterator, + ) -> Option { + let elems: Vec<_> = elems.into_iter().collect(); if elems.len() != (Self::extension_degree() as usize) { return None; } @@ -91,21 +94,7 @@ impl Field for Fp { elem } - fn double(&self) -> Self { - self.add(self) - } - - fn double_in_place(&mut self) -> &mut Self { - *self = self.add(self); - self - } - - fn neg_in_place(&mut self) -> &mut Self { - *self = Self::ZERO.sub(self); - self - } - - fn from_random_bytes_with_flags(bytes: &[u8]) -> Option<(Self, F)> { + fn from_random_bytes_with_flags(bytes: &[u8]) -> Option<(Self, F)> { Some((Self::from_le_bytes_mod_order(bytes), F::default())) } @@ -151,6 +140,15 @@ impl Field for Fp { fn characteristic() -> &'static [u64] { &Self::MODULUS_LIMBS } + + fn from_random_bytes(bytes: &[u8]) -> Option { + Self::from_random_bytes_with_flags::(bytes).map(|f| f.0) + } + + // Stub + fn mul_by_base_prime_field(&self, _elem: &Self::BasePrimeField) -> Self { + unimplemented!() + } } impl FftField for Fp { @@ -162,6 +160,12 @@ impl FftField for Fp { const LARGE_SUBGROUP_ROOT_OF_UNITY: Option = None; } +impl AdditiveGroup for Fp { + type Scalar = Self; + + const ZERO: Self = Self::ZERO; +} + impl Zero for Fp { #[inline] fn zero() -> Self { @@ -187,7 +191,7 @@ impl One for Fp { } impl CanonicalDeserializeWithFlags for Fp { - fn deserialize_with_flags( + fn deserialize_with_flags( mut reader: R, ) -> Result<(Self, F), SerializationError> { // Enough for the field element + 8 bits of flags. The last byte may or may not contain flags. @@ -214,7 +218,7 @@ impl Valid for Fp { } impl CanonicalDeserialize for Fp { - fn deserialize_with_mode( + fn deserialize_with_mode( reader: R, _compress: Compress, validate: Validate, @@ -230,7 +234,7 @@ impl CanonicalDeserialize for Fp { impl CanonicalSerialize for Fp { #[inline] - fn serialize_with_mode( + fn serialize_with_mode( &self, writer: W, _compress: Compress, @@ -245,7 +249,8 @@ impl CanonicalSerialize for Fp { } impl CanonicalSerializeWithFlags for Fp { - fn serialize_with_flags( + #[inline] + fn serialize_with_flags( &self, mut writer: W, flags: F, @@ -270,6 +275,7 @@ impl CanonicalSerializeWithFlags for Fp { Ok(()) } + #[inline] fn serialized_size_with_flags(&self) -> usize { (Self::MODULUS_BIT_SIZE as usize + F::BIT_SIZE + 7) / 8 } diff --git a/src/fields/fp/ops.rs b/src/fields/fp/ops.rs index 37a2492..0da5d4d 100644 --- a/src/fields/fp/ops.rs +++ b/src/fields/fp/ops.rs @@ -43,6 +43,36 @@ impl From for Fp { } } +impl From for Fp { + fn from(other: i8) -> Self { + i128::from(other).into() + } +} + +impl From for Fp { + fn from(other: i16) -> Self { + i128::from(other).into() + } +} + +impl From for Fp { + fn from(other: i32) -> Self { + i128::from(other).into() + } +} + +impl From for Fp { + fn from(other: i64) -> Self { + i128::from(other).into() + } +} + +impl From for Fp { + fn from(other: i128) -> Self { + i128::from(other).into() + } +} + impl Neg for Fp { type Output = Self; diff --git a/src/fields/fq/arkworks.rs b/src/fields/fq/arkworks.rs index 51fbb41..21a0be8 100644 --- a/src/fields/fq/arkworks.rs +++ b/src/fields/fq/arkworks.rs @@ -1,13 +1,15 @@ use super::Fq; -use ark_ff::{BigInt, Field, PrimeField, SqrtPrecomputation}; +use ark_ff::{AdditiveGroup, BigInt, Field, PrimeField, SqrtPrecomputation}; use ark_ff::{BigInteger, FftField}; use ark_serialize::{ CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize, CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, SerializationError, Valid, Validate, }; use ark_std::iterable::Iterable; +use ark_std::vec::Vec; use ark_std::{rand, str::FromStr, string::ToString, One, Zero}; use core::convert::TryInto; +use core::ops::AddAssign; use core::{ fmt::{Display, Formatter}, iter, @@ -59,7 +61,6 @@ impl PrimeField for Fq { impl Field for Fq { type BasePrimeField = Self; - type BasePrimeFieldIter = iter::Once; const SQRT_PRECOMP: Option> = Some(SqrtPrecomputation::TonelliShanks { @@ -68,8 +69,6 @@ impl Field for Fq { trace_of_modulus_minus_one_div_two: &Self::TRACE_MINUS_ONE_DIV_TWO_LIMBS, }); - const ZERO: Self = Self::ZERO; - // Montomgery representation of one const ONE: Self = Self::ONE; @@ -77,11 +76,14 @@ impl Field for Fq { 1 } - fn to_base_prime_field_elements(&self) -> Self::BasePrimeFieldIter { + fn to_base_prime_field_elements(&self) -> impl Iterator { iter::once(*self) } - fn from_base_prime_field_elems(elems: &[Self::BasePrimeField]) -> Option { + fn from_base_prime_field_elems( + elems: impl IntoIterator, + ) -> Option { + let elems: Vec<_> = elems.into_iter().collect(); if elems.len() != (Self::extension_degree() as usize) { return None; } @@ -92,20 +94,6 @@ impl Field for Fq { elem } - fn double(&self) -> Self { - self.add(self) - } - - fn double_in_place(&mut self) -> &mut Self { - *self = self.add(self); - self - } - - fn neg_in_place(&mut self) -> &mut Self { - *self = Self::ZERO.sub(self); - self - } - fn from_random_bytes_with_flags(bytes: &[u8]) -> Option<(Self, F)> { Some((Self::from_le_bytes_mod_order(bytes), F::default())) } @@ -152,6 +140,10 @@ impl Field for Fq { fn characteristic() -> &'static [u64] { &Self::MODULUS_LIMBS } + + fn mul_by_base_prime_field(&self, _elem: &Self::BasePrimeField) -> Self { + unimplemented!() + } } impl FftField for Fq { @@ -163,6 +155,12 @@ impl FftField for Fq { const LARGE_SUBGROUP_ROOT_OF_UNITY: Option = None; } +impl AdditiveGroup for Fq { + type Scalar = Self; + + const ZERO: Self = Self::ZERO; +} + impl Zero for Fq { #[inline] fn zero() -> Self { diff --git a/src/fields/fq/ops.rs b/src/fields/fq/ops.rs index c56b407..bfa184c 100644 --- a/src/fields/fq/ops.rs +++ b/src/fields/fq/ops.rs @@ -43,6 +43,36 @@ impl From for Fq { } } +impl From for Fq { + fn from(other: i8) -> Self { + i128::from(other).into() + } +} + +impl From for Fq { + fn from(other: i16) -> Self { + i128::from(other).into() + } +} + +impl From for Fq { + fn from(other: i32) -> Self { + i128::from(other).into() + } +} + +impl From for Fq { + fn from(other: i64) -> Self { + i128::from(other).into() + } +} + +impl From for Fq { + fn from(other: i128) -> Self { + i128::from(other).into() + } +} + impl Neg for Fq { type Output = Self; diff --git a/src/fields/fr/arkworks.rs b/src/fields/fr/arkworks.rs index d31e5b5..3b98d69 100644 --- a/src/fields/fr/arkworks.rs +++ b/src/fields/fr/arkworks.rs @@ -1,12 +1,15 @@ use super::Fr; -use ark_ff::{BigInt, Field, PrimeField, SqrtPrecomputation}; +use ark_ff::{AdditiveGroup, BigInt, Field, PrimeField, SqrtPrecomputation}; use ark_ff::{BigInteger, FftField}; use ark_serialize::{ CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize, - CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, SerializationError, Valid, Validate, + CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, Read, SerializationError, Valid, + Validate, Write, }; +use ark_std::vec::Vec; use ark_std::{rand, str::FromStr, string::ToString, One, Zero}; use core::convert::TryInto; +use core::ops::AddAssign; use core::{ fmt::{Display, Formatter}, iter, @@ -58,7 +61,6 @@ impl PrimeField for Fr { impl Field for Fr { type BasePrimeField = Self; - type BasePrimeFieldIter = iter::Once; const SQRT_PRECOMP: Option> = Some(SqrtPrecomputation::Case3Mod4 { modulus_plus_one_div_four: &[ @@ -69,8 +71,6 @@ impl Field for Fr { ], }); - const ZERO: Self = Self::ZERO; - // Montomgery representation of one const ONE: Self = Self::ONE; @@ -78,11 +78,14 @@ impl Field for Fr { 1 } - fn to_base_prime_field_elements(&self) -> Self::BasePrimeFieldIter { + fn to_base_prime_field_elements(&self) -> impl Iterator { iter::once(*self) } - fn from_base_prime_field_elems(elems: &[Self::BasePrimeField]) -> Option { + fn from_base_prime_field_elems( + elems: impl IntoIterator, + ) -> Option { + let elems: Vec<_> = elems.into_iter().collect(); if elems.len() != (Self::extension_degree() as usize) { return None; } @@ -93,20 +96,6 @@ impl Field for Fr { elem } - fn double(&self) -> Self { - self.add(self) - } - - fn double_in_place(&mut self) -> &mut Self { - *self = self.add(self); - self - } - - fn neg_in_place(&mut self) -> &mut Self { - *self = Self::ZERO.sub(self); - self - } - fn from_random_bytes_with_flags(bytes: &[u8]) -> Option<(Self, F)> { Some((Self::from_le_bytes_mod_order(bytes), F::default())) } @@ -153,6 +142,10 @@ impl Field for Fr { fn characteristic() -> &'static [u64] { &Self::MODULUS_LIMBS } + + fn mul_by_base_prime_field(&self, _elem: &Self::BasePrimeField) -> Self { + unimplemented!() + } } impl FftField for Fr { @@ -164,6 +157,12 @@ impl FftField for Fr { const LARGE_SUBGROUP_ROOT_OF_UNITY: Option = None; } +impl AdditiveGroup for Fr { + type Scalar = Self; + + const ZERO: Self = Self::ZERO; +} + impl Zero for Fr { #[inline] fn zero() -> Self { @@ -188,7 +187,7 @@ impl One for Fr { } } impl CanonicalDeserializeWithFlags for Fr { - fn deserialize_with_flags( + fn deserialize_with_flags( mut reader: R, ) -> Result<(Self, F), SerializationError> { // Enough for the field element + 8 bits of flags. The last byte may or may not contain flags. @@ -216,7 +215,7 @@ impl Valid for Fr { } impl CanonicalDeserialize for Fr { - fn deserialize_with_mode( + fn deserialize_with_mode( reader: R, _compress: Compress, validate: Validate, @@ -232,7 +231,7 @@ impl CanonicalDeserialize for Fr { impl CanonicalSerialize for Fr { #[inline] - fn serialize_with_mode( + fn serialize_with_mode( &self, writer: W, _compress: Compress, @@ -247,7 +246,7 @@ impl CanonicalSerialize for Fr { } impl CanonicalSerializeWithFlags for Fr { - fn serialize_with_flags( + fn serialize_with_flags( &self, mut writer: W, flags: F, diff --git a/src/fields/fr/ops.rs b/src/fields/fr/ops.rs index 1301238..2c36269 100644 --- a/src/fields/fr/ops.rs +++ b/src/fields/fr/ops.rs @@ -43,6 +43,36 @@ impl From for Fr { } } +impl From for Fr { + fn from(other: i8) -> Self { + i128::from(other).into() + } +} + +impl From for Fr { + fn from(other: i16) -> Self { + i128::from(other).into() + } +} + +impl From for Fr { + fn from(other: i32) -> Self { + i128::from(other).into() + } +} + +impl From for Fr { + fn from(other: i64) -> Self { + i128::from(other).into() + } +} + +impl From for Fr { + fn from(other: i128) -> Self { + i128::from(other).into() + } +} + impl Neg for Fr { type Output = Self; diff --git a/tests/groth16_gadgets.rs b/tests/groth16_gadgets.rs index 74e1cfd..b3e223f 100644 --- a/tests/groth16_gadgets.rs +++ b/tests/groth16_gadgets.rs @@ -1,11 +1,9 @@ -use ark_ff::UniformRand; use ark_groth16::{r1cs_to_qap::LibsnarkReduction, Groth16, Proof, ProvingKey, VerifyingKey}; use proptest::prelude::*; use ark_r1cs_std::{ - prelude::{AllocVar, CurveVar, EqGadget}, + prelude::{AllocVar, CurveVar, EqGadget, ToBitsGadget}, uint8::UInt8, - ToBitsGadget, }; use ark_relations::r1cs::{ConstraintSynthesizer, ToConstraintField}; use ark_snark::SNARK;