From e333a064d0d537633eda8edbcfc11f01137cc6d0 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 25 Dec 2023 22:41:52 -0500 Subject: [PATCH 01/13] Add mul by non-native field var --- src/fields/nonnative/allocated_field_var.rs | 27 ++- src/fields/nonnative/reduce.rs | 25 +-- src/groups/curves/short_weierstrass/mod.rs | 173 ++++++++------- src/groups/curves/twisted_edwards/mod.rs | 220 ++++++++++---------- src/groups/mod.rs | 17 +- src/macros.rs | 107 +++++++++- src/pairing/mod.rs | 7 +- 7 files changed, 342 insertions(+), 234 deletions(-) diff --git a/src/fields/nonnative/allocated_field_var.rs b/src/fields/nonnative/allocated_field_var.rs index aadbe1a3..dd4dfae4 100644 --- a/src/fields/nonnative/allocated_field_var.rs +++ b/src/fields/nonnative/allocated_field_var.rs @@ -57,14 +57,13 @@ impl optimization_type, ); - let mut base_repr: ::BigInt = TargetField::one().into_bigint(); - // Convert 2^{(params.bits_per_limb - 1)} into the TargetField and then double // the base This is because 2^{(params.bits_per_limb)} might indeed be // larger than the target field's prime. - base_repr.muln((params.bits_per_limb - 1) as u32); - let mut base: TargetField = TargetField::from_bigint(base_repr).unwrap(); - base = base + &base; + let base_repr = TargetField::ONE.into_bigint() >> (params.bits_per_limb - 1) as u32; + + let mut base = TargetField::from_bigint(base_repr).unwrap(); + base.double_in_place(); let mut result = TargetField::zero(); let mut power = TargetField::one(); @@ -210,18 +209,16 @@ impl } // Step 2: construct the padding - let mut pad_non_top_limb_repr: ::BigInt = - BaseField::one().into_bigint(); - let mut pad_top_limb_repr: ::BigInt = pad_non_top_limb_repr; + let mut pad_non_top_limb_repr = BaseField::one().into_bigint(); + let mut pad_top_limb_repr = pad_non_top_limb_repr; - pad_non_top_limb_repr.muln((surfeit + params.bits_per_limb) as u32); + pad_non_top_limb_repr <<= (surfeit + params.bits_per_limb) as u32; let pad_non_top_limb = BaseField::from_bigint(pad_non_top_limb_repr).unwrap(); - pad_top_limb_repr.muln( - (surfeit - + (TargetField::MODULUS_BIT_SIZE as usize - - params.bits_per_limb * (params.num_limbs - 1))) as u32, - ); + pad_top_limb_repr <<= (surfeit + + (TargetField::MODULUS_BIT_SIZE as usize + - params.bits_per_limb * (params.num_limbs - 1))) + as u32; let pad_top_limb = BaseField::from_bigint(pad_top_limb_repr).unwrap(); let mut pad_limbs = Vec::new(); @@ -341,7 +338,7 @@ impl &cur_bits[cur_bits.len() - params.bits_per_limb..], ); // therefore, the lowest `bits_per_non_top_limb` bits is what we want. limbs.push(BaseField::from_bigint(cur_mod_r).unwrap()); - cur.divn(params.bits_per_limb as u32); + cur >>= params.bits_per_limb as u32; } // then we reserve, so that the limbs are ``big limb first'' diff --git a/src/fields/nonnative/reduce.rs b/src/fields/nonnative/reduce.rs index 31e5fe7a..b7de396f 100644 --- a/src/fields/nonnative/reduce.rs +++ b/src/fields/nonnative/reduce.rs @@ -240,7 +240,7 @@ impl Reducer Reducer::BigInt = - BaseField::one().into_bigint(); - - pad_limb_repr.muln( - (surfeit - + (bits_per_limb - shift_per_limb) - + shift_per_limb * num_limb_in_this_group - + 1 - + 1) as u32, - ); + let mut pad_limb_repr = BaseField::ONE.into_bigint(); + + pad_limb_repr <<= (surfeit + + (bits_per_limb - shift_per_limb) + + shift_per_limb * num_limb_in_this_group + + 1 + + 1) as u32; let pad_limb = BaseField::from_bigint(pad_limb_repr).unwrap(); let left_total_limb_value = left_total_limb.value().unwrap_or_default(); @@ -298,12 +295,12 @@ impl Reducer> (shift_per_limb * num_limb_in_this_group) as u32; carry_value = BaseField::from_bigint(carry_repr).unwrap(); - let carry = FpVar::::new_witness(cs.clone(), || Ok(carry_value))?; + let carry = FpVar::new_witness(cs.clone(), || Ok(carry_value))?; accumulated_extra += limbs_to_bigint(bits_per_limb, &[pad_limb]); diff --git a/src/groups/curves/short_weierstrass/mod.rs b/src/groups/curves/short_weierstrass/mod.rs index f2453343..b2d4ed59 100644 --- a/src/groups/curves/short_weierstrass/mod.rs +++ b/src/groups/curves/short_weierstrass/mod.rs @@ -2,13 +2,14 @@ use ark_ec::{ short_weierstrass::{ Affine as SWAffine, Projective as SWProjective, SWCurveConfig as SWModelParameters, }, - AffineRepr, CurveGroup, + AffineRepr, CurveConfig, CurveGroup, }; -use ark_ff::{AdditiveGroup, BigInteger, BitIteratorBE, Field, One, PrimeField, Zero}; +use ark_ff::{AdditiveGroup, BitIteratorBE, Field, One, PrimeField, Zero}; use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; use ark_std::{borrow::Borrow, marker::PhantomData, ops::Mul}; use non_zero_affine::NonZeroAffineVar; +use crate::fields::nonnative::NonNativeFieldVar; use crate::{fields::fp::FpVar, prelude::*, ToConstraintFieldGadget, Vec}; /// This module provides a generic implementation of G1 and G2 for @@ -33,16 +34,17 @@ pub mod mnt6; /// to zero. The [ProjectiveVar] gadget is the recommended way of working with /// elliptic curve points. pub mod non_zero_affine; + +type BasePrimeField

= <

::BaseField as Field>::BasePrimeField; + /// An implementation of arithmetic for Short Weierstrass curves that relies on /// the complete formulae derived in the paper of /// [[Renes, Costello, Batina 2015]](). #[derive(Derivative)] #[derivative(Debug, Clone)] #[must_use] -pub struct ProjectiveVar< - P: SWModelParameters, - F: FieldVar::BasePrimeField>, -> where +pub struct ProjectiveVar>> +where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { /// The x-coordinate. @@ -57,12 +59,10 @@ pub struct ProjectiveVar< /// An affine representation of a curve point. #[derive(Derivative)] -#[derivative(Debug, Clone)] +#[derivative(Debug(bound = "F: ark_std::fmt::Debug"), Clone(bound = "F: Clone"))] #[must_use] -pub struct AffineVar< - P: SWModelParameters, - F: FieldVar::BasePrimeField>, -> where +pub struct AffineVar>> +where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { /// The x-coordinate. @@ -70,7 +70,7 @@ pub struct AffineVar< /// The y-coordinate. pub y: F, /// Is `self` the point at infinity. - pub infinity: Boolean<::BasePrimeField>, + pub infinity: Boolean>, #[derivative(Debug = "ignore")] _params: PhantomData

, } @@ -78,10 +78,10 @@ pub struct AffineVar< impl AffineVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { - fn new(x: F, y: F, infinity: Boolean<::BasePrimeField>) -> Self { + fn new(x: F, y: F, infinity: Boolean>) -> Self { Self { x, y, @@ -100,17 +100,15 @@ where } } -impl ToConstraintFieldGadget<::BasePrimeField> for AffineVar +impl ToConstraintFieldGadget> for AffineVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, - F: ToConstraintFieldGadget<::BasePrimeField>, + F: ToConstraintFieldGadget>, { - fn to_constraint_field( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { - let mut res = Vec::::BasePrimeField>>::new(); + fn to_constraint_field(&self) -> Result>>, SynthesisError> { + let mut res = Vec::>>::new(); res.extend_from_slice(&self.x.to_constraint_field()?); res.extend_from_slice(&self.y.to_constraint_field()?); @@ -120,15 +118,15 @@ where } } -impl R1CSVar<::BasePrimeField> for ProjectiveVar +impl R1CSVar> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { type Value = SWProjective

; - fn cs(&self) -> ConstraintSystemRef<::BasePrimeField> { + fn cs(&self) -> ConstraintSystemRef> { self.x.cs().or(self.y.cs()).or(self.z.cs()) } @@ -143,8 +141,7 @@ where } } -impl::BasePrimeField>> - ProjectiveVar +impl>> ProjectiveVar where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -199,7 +196,7 @@ where /// is a constant or is a public input). #[tracing::instrument(target = "r1cs", skip(cs, f))] pub fn new_variable_omit_on_curve_check( - cs: impl Into::BasePrimeField>>, + cs: impl Into>>, f: impl FnOnce() -> Result, SynthesisError>, mode: AllocationMode, ) -> Result { @@ -285,7 +282,7 @@ where &self, mul_result: &mut Self, multiple_of_power_of_two: &mut NonZeroAffineVar, - bits: &[&Boolean<::BasePrimeField>], + bits: &[&Boolean>], ) -> Result<(), SynthesisError> { let scalar_modulus_bits = ::MODULUS_BIT_SIZE as usize; @@ -368,11 +365,10 @@ where } } -impl CurveVar, ::BasePrimeField> - for ProjectiveVar +impl CurveVar, BasePrimeField

> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { fn constant(g: SWProjective

) -> Self { @@ -384,13 +380,13 @@ where Self::new(F::zero(), F::one(), F::zero()) } - fn is_zero(&self) -> Result::BasePrimeField>, SynthesisError> { + fn is_zero(&self) -> Result>, SynthesisError> { self.z.is_zero() } #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable_omit_prime_order_check( - cs: impl Into::BasePrimeField>>, + cs: impl Into>>, f: impl FnOnce() -> Result, SynthesisError>, mode: AllocationMode, ) -> Result { @@ -500,7 +496,7 @@ where #[tracing::instrument(target = "r1cs", skip(bits))] fn scalar_mul_le<'a>( &self, - bits: impl Iterator::BasePrimeField>>, + bits: impl Iterator>>, ) -> Result { if self.is_constant() { if self.value().unwrap().is_zero() { @@ -552,7 +548,7 @@ where ) -> Result<(), SynthesisError> where I: Iterator)>, - B: Borrow::BasePrimeField>>, + B: Borrow>>, { // We just ignore the provided bases and use the faster scalar multiplication. let (bits, bases): (Vec<_>, Vec<_>) = scalar_bits_with_bases @@ -564,26 +560,19 @@ where } } -impl ToConstraintFieldGadget<::BasePrimeField> for ProjectiveVar +impl ToConstraintFieldGadget> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, - F: ToConstraintFieldGadget<::BasePrimeField>, + F: ToConstraintFieldGadget>, { - fn to_constraint_field( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_constraint_field(&self) -> Result>>, SynthesisError> { self.to_affine()?.to_constraint_field() } } -fn mul_by_coeff_a< - P: SWModelParameters, - F: FieldVar::BasePrimeField>, ->( - f: &F, -) -> F +fn mul_by_coeff_a>>(f: &F) -> F where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -668,7 +657,7 @@ impl_bounded_ops!( |this: &'a ProjectiveVar, other: SWProjective

| { this + ProjectiveVar::constant(other) }, - (F: FieldVar::BasePrimeField>, P: SWModelParameters), + (F: FieldVar>, P: SWModelParameters), for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, ); @@ -681,14 +670,37 @@ impl_bounded_ops!( sub_assign, |this: &'a ProjectiveVar, other: &'a ProjectiveVar| this + other.negate().unwrap(), |this: &'a ProjectiveVar, other: SWProjective

| this - ProjectiveVar::constant(other), - (F: FieldVar::BasePrimeField>, P: SWModelParameters), + (F: FieldVar>, P: SWModelParameters), for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F> ); +impl_bounded_ops_diff!( + ProjectiveVar, + SWProjective

, + NonNativeFieldVar>, + P::ScalarField, + Mul, + mul, + MulAssign, + mul_assign, + |this: &'a ProjectiveVar, other: &'a NonNativeFieldVar>| { + if this.is_constant() && other.is_constant() { + assert!(this.is_constant() && other.is_constant()); + ProjectiveVar::constant(this.value().unwrap() * &other.value().unwrap()) + } else { + let bits = other.to_bits_le().unwrap(); + this.scalar_mul_le(bits.iter()).unwrap() + } + }, + |this: &'a ProjectiveVar, other: P::ScalarField| this * NonNativeFieldVar::constant(other), + (F: FieldVar>, P: SWModelParameters), + for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, +); + impl<'a, P, F> GroupOpsBounds<'a, SWProjective

, ProjectiveVar> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { } @@ -696,21 +708,21 @@ where impl<'a, P, F> GroupOpsBounds<'a, SWProjective

, ProjectiveVar> for &'a ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { } -impl CondSelectGadget<::BasePrimeField> for ProjectiveVar +impl CondSelectGadget> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { #[inline] #[tracing::instrument(target = "r1cs")] fn conditionally_select( - cond: &Boolean<::BasePrimeField>, + cond: &Boolean>, true_value: &Self, false_value: &Self, ) -> Result { @@ -722,17 +734,14 @@ where } } -impl EqGadget<::BasePrimeField> for ProjectiveVar +impl EqGadget> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { #[tracing::instrument(target = "r1cs")] - fn is_eq( - &self, - other: &Self, - ) -> Result::BasePrimeField>, SynthesisError> { + fn is_eq(&self, other: &Self) -> Result>, SynthesisError> { let x_equal = (&self.x * &other.z).is_eq(&(&other.x * &self.z))?; let y_equal = (&self.y * &other.z).is_eq(&(&other.y * &self.z))?; let coordinates_equal = x_equal.and(&y_equal)?; @@ -745,7 +754,7 @@ where fn conditional_enforce_equal( &self, other: &Self, - condition: &Boolean<::BasePrimeField>, + condition: &Boolean>, ) -> Result<(), SynthesisError> { let x_equal = (&self.x * &other.z).is_eq(&(&other.x * &self.z))?; let y_equal = (&self.y * &other.z).is_eq(&(&other.y * &self.z))?; @@ -762,7 +771,7 @@ where fn conditional_enforce_not_equal( &self, other: &Self, - condition: &Boolean<::BasePrimeField>, + condition: &Boolean>, ) -> Result<(), SynthesisError> { let is_equal = self.is_eq(other)?; is_equal @@ -771,14 +780,14 @@ where } } -impl AllocVar, ::BasePrimeField> for ProjectiveVar +impl AllocVar, BasePrimeField

> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { fn new_variable>>( - cs: impl Into::BasePrimeField>>, + cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -790,15 +799,14 @@ where } } -impl AllocVar, ::BasePrimeField> - for ProjectiveVar +impl AllocVar, BasePrimeField

> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { fn new_variable>>( - cs: impl Into::BasePrimeField>>, + cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -851,8 +859,7 @@ where || { f().map(|g| { let g = g.into_affine(); - let mut power_of_two = P::ScalarField::one().into_bigint(); - power_of_two.muln(power_of_2); + let power_of_two = P::ScalarField::ONE.into_bigint() << power_of_2; let power_of_two_inv = P::ScalarField::from_bigint(power_of_two) .and_then(|n| n.inverse()) .unwrap(); @@ -902,16 +909,14 @@ fn div2(limbs: &mut [u64]) { } } -impl ToBitsGadget<::BasePrimeField> for ProjectiveVar +impl ToBitsGadget> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { #[tracing::instrument(target = "r1cs")] - fn to_bits_le( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_bits_le(&self) -> Result>>, SynthesisError> { let g = self.to_affine()?; let mut bits = g.x.to_bits_le()?; let y_bits = g.y.to_bits_le()?; @@ -921,9 +926,7 @@ where } #[tracing::instrument(target = "r1cs")] - fn to_non_unique_bits_le( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_non_unique_bits_le(&self) -> Result>>, SynthesisError> { let g = self.to_affine()?; let mut bits = g.x.to_non_unique_bits_le()?; let y_bits = g.y.to_non_unique_bits_le()?; @@ -933,16 +936,14 @@ where } } -impl ToBytesGadget<::BasePrimeField> for ProjectiveVar +impl ToBytesGadget> for ProjectiveVar where P: SWModelParameters, - F: FieldVar::BasePrimeField>, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { #[tracing::instrument(target = "r1cs")] - fn to_bytes( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_bytes(&self) -> Result>>, SynthesisError> { let g = self.to_affine()?; let mut bytes = g.x.to_bytes()?; let y_bytes = g.y.to_bytes()?; @@ -953,9 +954,7 @@ where } #[tracing::instrument(target = "r1cs")] - fn to_non_unique_bytes( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_non_unique_bytes(&self) -> Result>>, SynthesisError> { let g = self.to_affine()?; let mut bytes = g.x.to_non_unique_bytes()?; let y_bytes = g.y.to_non_unique_bytes()?; diff --git a/src/groups/curves/twisted_edwards/mod.rs b/src/groups/curves/twisted_edwards/mod.rs index 4b92d6ba..861ecfac 100644 --- a/src/groups/curves/twisted_edwards/mod.rs +++ b/src/groups/curves/twisted_edwards/mod.rs @@ -1,18 +1,21 @@ use ark_ec::{ + models::CurveConfig, twisted_edwards::{ - Affine as TEAffine, MontCurveConfig as MontgomeryModelParameter, - Projective as TEProjective, TECurveConfig as TEModelParameters, + Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig, }, AdditiveGroup, AffineRepr, CurveGroup, }; -use ark_ff::{BigInteger, BitIteratorBE, Field, One, PrimeField, Zero}; +use ark_ff::{BitIteratorBE, Field, One, PrimeField, Zero}; use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; +use crate::fields::nonnative::NonNativeFieldVar; use crate::{prelude::*, ToConstraintFieldGadget, Vec}; use crate::fields::fp::FpVar; use ark_std::{borrow::Borrow, marker::PhantomData, ops::Mul}; +type BasePrimeField

= <

::BaseField as Field>::BasePrimeField; + /// An implementation of arithmetic for Montgomery curves that relies on /// incomplete addition formulae for the affine model, as outlined in the /// [EFD](https://www.hyperelliptic.org/EFD/g1p/auto-montgom.html). @@ -22,10 +25,8 @@ use ark_std::{borrow::Borrow, marker::PhantomData, ops::Mul}; #[derive(Derivative)] #[derivative(Debug, Clone)] #[must_use] -pub struct MontgomeryAffineVar< - P: TEModelParameters, - F: FieldVar::BasePrimeField>, -> where +pub struct MontgomeryAffineVar>> +where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { /// The x-coordinate. @@ -42,15 +43,15 @@ mod montgomery_affine_impl { use ark_ff::Field; use core::ops::Add; - impl R1CSVar<::BasePrimeField> for MontgomeryAffineVar + impl R1CSVar> for MontgomeryAffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField>, + P: TECurveConfig, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { type Value = (P::BaseField, P::BaseField); - fn cs(&self) -> ConstraintSystemRef<::BasePrimeField> { + fn cs(&self) -> ConstraintSystemRef> { self.x.cs().or(self.y.cs()) } @@ -61,10 +62,7 @@ mod montgomery_affine_impl { } } - impl< - P: TEModelParameters, - F: FieldVar::BasePrimeField>, - > MontgomeryAffineVar + impl>> MontgomeryAffineVar where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -101,7 +99,7 @@ mod montgomery_affine_impl { /// corresponding affine Montgomery curve point. #[tracing::instrument(target = "r1cs")] pub fn new_witness_from_edwards( - cs: ConstraintSystemRef<::BasePrimeField>, + cs: ConstraintSystemRef>, p: &TEAffine

, ) -> Result { let montgomery_coords = Self::from_edwards_to_coords(p)?; @@ -160,8 +158,8 @@ mod montgomery_affine_impl { impl<'a, P, F> Add<&'a MontgomeryAffineVar> for MontgomeryAffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField>, + P: TECurveConfig, + F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { type Output = MontgomeryAffineVar; @@ -234,10 +232,8 @@ mod montgomery_affine_impl { #[derive(Derivative)] #[derivative(Debug, Clone)] #[must_use] -pub struct AffineVar< - P: TEModelParameters, - F: FieldVar::BasePrimeField>, -> where +pub struct AffineVar>> +where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { /// The x-coordinate. @@ -248,8 +244,7 @@ pub struct AffineVar< _params: PhantomData

, } -impl::BasePrimeField>> - AffineVar +impl>> AffineVar where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -267,7 +262,7 @@ where /// is a constant or is a public input). #[tracing::instrument(target = "r1cs", skip(cs, f))] pub fn new_variable_omit_on_curve_check>>( - cs: impl Into::BasePrimeField>>, + cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -292,16 +287,12 @@ where } } -impl::BasePrimeField>> - AffineVar +impl>> AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField> - + ThreeBitCondNegLookupGadget< - ::BasePrimeField, - TableConstant = P::BaseField, - >, + P: TECurveConfig, + F: FieldVar> + + TwoBitLookupGadget, TableConstant = P::BaseField> + + ThreeBitCondNegLookupGadget, TableConstant = P::BaseField>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { /// Compute a scalar multiplication of `bases` with respect to `scalars`, @@ -315,7 +306,7 @@ where scalars: &[impl Borrow<[J]>], ) -> Result where - J: Borrow<[Boolean<::BasePrimeField>]>, + J: Borrow<[Boolean>]>, { const CHUNK_SIZE: usize = 3; let mut ed_result: Option> = None; @@ -385,15 +376,15 @@ where } } -impl R1CSVar<::BasePrimeField> for AffineVar +impl R1CSVar> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField>, + P: TECurveConfig, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { type Value = TEProjective

; - fn cs(&self) -> ConstraintSystemRef<::BasePrimeField> { + fn cs(&self) -> ConstraintSystemRef> { self.x.cs().or(self.y.cs()) } @@ -405,11 +396,11 @@ where } } -impl CurveVar, ::BasePrimeField> for AffineVar +impl CurveVar, BasePrimeField

> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + P: TECurveConfig, + F: FieldVar> + + TwoBitLookupGadget, TableConstant = P::BaseField>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { fn constant(g: TEProjective

) -> Self { @@ -421,13 +412,13 @@ where Self::new(F::zero(), F::one()) } - fn is_zero(&self) -> Result::BasePrimeField>, SynthesisError> { + fn is_zero(&self) -> Result>, SynthesisError> { self.x.is_zero()?.and(&self.y.is_one()?) } #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable_omit_prime_order_check( - cs: impl Into::BasePrimeField>>, + cs: impl Into>>, f: impl FnOnce() -> Result, SynthesisError>, mode: AllocationMode, ) -> Result { @@ -531,7 +522,7 @@ where ) -> Result<(), SynthesisError> where I: Iterator)>, - B: Borrow::BasePrimeField>>, + B: Borrow>>, { let (bits, multiples): (Vec<_>, Vec<_>) = scalar_bits_with_base_multiples .map(|(bit, base)| (bit.borrow().clone(), *base)) @@ -559,16 +550,16 @@ where } } -impl AllocVar, ::BasePrimeField> for AffineVar +impl AllocVar, BasePrimeField

> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + P: TECurveConfig, + F: FieldVar> + + TwoBitLookupGadget, TableConstant = P::BaseField>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( - cs: impl Into::BasePrimeField>>, + cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -621,8 +612,7 @@ where || { f().map(|g| { let g = g.into_affine(); - let mut power_of_two = P::ScalarField::one().into_bigint(); - power_of_two.muln(power_of_2); + let power_of_two = P::ScalarField::ONE.into_bigint() << power_of_2; let power_of_two_inv = P::ScalarField::from_bigint(power_of_two) .and_then(|n| n.inverse()) .unwrap(); @@ -660,16 +650,16 @@ where } } -impl AllocVar, ::BasePrimeField> for AffineVar +impl AllocVar, BasePrimeField

> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + P: TECurveConfig, + F: FieldVar> + + TwoBitLookupGadget, TableConstant = P::BaseField>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( - cs: impl Into::BasePrimeField>>, + cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -681,16 +671,14 @@ where } } -impl ToConstraintFieldGadget<::BasePrimeField> for AffineVar +impl ToConstraintFieldGadget> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField>, + P: TECurveConfig, + F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, - F: ToConstraintFieldGadget<::BasePrimeField>, + F: ToConstraintFieldGadget>, { - fn to_constraint_field( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_constraint_field(&self) -> Result>>, SynthesisError> { let mut res = Vec::new(); res.extend_from_slice(&self.x.to_constraint_field()?); @@ -772,9 +760,9 @@ impl_bounded_ops!( }, |this: &'a AffineVar, other: TEProjective

| this + AffineVar::constant(other), ( - F :FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, - P: TEModelParameters, + F :FieldVar> + + TwoBitLookupGadget, TableConstant = P::BaseField>, + P: TECurveConfig, ), for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, ); @@ -789,41 +777,68 @@ impl_bounded_ops!( |this: &'a AffineVar, other: &'a AffineVar| this + other.negate().unwrap(), |this: &'a AffineVar, other: TEProjective

| this - AffineVar::constant(other), ( - F :FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, - P: TEModelParameters, + F :FieldVar> + + TwoBitLookupGadget, TableConstant = P::BaseField>, + P: TECurveConfig, ), for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F> ); +impl_bounded_ops_diff!( + AffineVar, + TEProjective

, + NonNativeFieldVar>, + P::ScalarField, + Mul, + mul, + MulAssign, + mul_assign, + |this: &'a AffineVar, other: &'a NonNativeFieldVar>| { + if this.is_constant() && other.is_constant() { + assert!(this.is_constant() && other.is_constant()); + AffineVar::constant(this.value().unwrap() * &other.value().unwrap()) + } else { + let bits = other.to_bits_le().unwrap(); + this.scalar_mul_le(bits.iter()).unwrap() + } + }, + |this: &'a AffineVar, other: P::ScalarField| this * NonNativeFieldVar::constant(other), + ( + F :FieldVar> + + TwoBitLookupGadget, TableConstant = P::BaseField>, + P: TECurveConfig, + ), + for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, +); + impl<'a, P, F> GroupOpsBounds<'a, TEProjective

, AffineVar> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + P: TECurveConfig, + F: FieldVar> + + TwoBitLookupGadget, TableConstant = P::BaseField>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { } impl<'a, P, F> GroupOpsBounds<'a, TEProjective

, AffineVar> for &'a AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + P: TECurveConfig, + F: FieldVar> + + TwoBitLookupGadget, TableConstant = P::BaseField>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { } -impl CondSelectGadget<::BasePrimeField> for AffineVar +impl CondSelectGadget> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField>, + P: TECurveConfig, + F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { #[inline] #[tracing::instrument(target = "r1cs")] fn conditionally_select( - cond: &Boolean<::BasePrimeField>, + cond: &Boolean>, true_value: &Self, false_value: &Self, ) -> Result { @@ -834,17 +849,14 @@ where } } -impl EqGadget<::BasePrimeField> for AffineVar +impl EqGadget> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField>, + P: TECurveConfig, + F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { #[tracing::instrument(target = "r1cs")] - fn is_eq( - &self, - other: &Self, - ) -> Result::BasePrimeField>, SynthesisError> { + fn is_eq(&self, other: &Self) -> Result>, SynthesisError> { let x_equal = self.x.is_eq(&other.x)?; let y_equal = self.y.is_eq(&other.y)?; x_equal.and(&y_equal) @@ -855,7 +867,7 @@ where fn conditional_enforce_equal( &self, other: &Self, - condition: &Boolean<::BasePrimeField>, + condition: &Boolean>, ) -> Result<(), SynthesisError> { self.x.conditional_enforce_equal(&other.x, condition)?; self.y.conditional_enforce_equal(&other.y, condition)?; @@ -867,7 +879,7 @@ where fn conditional_enforce_not_equal( &self, other: &Self, - condition: &Boolean<::BasePrimeField>, + condition: &Boolean>, ) -> Result<(), SynthesisError> { self.is_eq(other)? .and(condition)? @@ -875,16 +887,14 @@ where } } -impl ToBitsGadget<::BasePrimeField> for AffineVar +impl ToBitsGadget> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField>, + P: TECurveConfig, + F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { #[tracing::instrument(target = "r1cs")] - fn to_bits_le( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_bits_le(&self) -> Result>>, SynthesisError> { let mut x_bits = self.x.to_bits_le()?; let y_bits = self.y.to_bits_le()?; x_bits.extend_from_slice(&y_bits); @@ -892,9 +902,7 @@ where } #[tracing::instrument(target = "r1cs")] - fn to_non_unique_bits_le( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_non_unique_bits_le(&self) -> Result>>, SynthesisError> { let mut x_bits = self.x.to_non_unique_bits_le()?; let y_bits = self.y.to_non_unique_bits_le()?; x_bits.extend_from_slice(&y_bits); @@ -903,16 +911,14 @@ where } } -impl ToBytesGadget<::BasePrimeField> for AffineVar +impl ToBytesGadget> for AffineVar where - P: TEModelParameters, - F: FieldVar::BasePrimeField>, + P: TECurveConfig, + F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { #[tracing::instrument(target = "r1cs")] - fn to_bytes( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_bytes(&self) -> Result>>, SynthesisError> { let mut x_bytes = self.x.to_bytes()?; let y_bytes = self.y.to_bytes()?; x_bytes.extend_from_slice(&y_bytes); @@ -920,9 +926,7 @@ where } #[tracing::instrument(target = "r1cs")] - fn to_non_unique_bytes( - &self, - ) -> Result::BasePrimeField>>, SynthesisError> { + fn to_non_unique_bytes(&self) -> Result>>, SynthesisError> { let mut x_bytes = self.x.to_non_unique_bytes()?; let y_bytes = self.y.to_non_unique_bytes()?; x_bytes.extend_from_slice(&y_bytes); diff --git a/src/groups/mod.rs b/src/groups/mod.rs index fb8c7461..84c63352 100644 --- a/src/groups/mod.rs +++ b/src/groups/mod.rs @@ -1,7 +1,7 @@ -use crate::prelude::*; -use ark_ff::Field; +use crate::{fields::nonnative::NonNativeFieldVar, prelude::*}; +use ark_ff::PrimeField; use ark_relations::r1cs::{Namespace, SynthesisError}; -use core::ops::{Add, AddAssign, Sub, SubAssign}; +use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; use ark_ec::CurveGroup; use core::{borrow::Borrow, fmt::Debug}; @@ -12,20 +12,20 @@ pub mod curves; pub use self::curves::short_weierstrass::{bls12, mnt4, mnt6}; /// A hack used to work around the lack of implied bounds. -pub trait GroupOpsBounds<'a, F, T: 'a>: +pub trait GroupOpsBounds<'a, G, T: 'a>: Sized + Add<&'a T, Output = T> + Sub<&'a T, Output = T> + Add + Sub - + Add - + Sub + + Add + + Sub { } /// A variable that represents a curve point for /// the curve `C`. -pub trait CurveVar: +pub trait CurveVar: 'static + Sized + Clone @@ -44,6 +44,9 @@ pub trait CurveVar: + SubAssign + AddAssign + SubAssign + + Mul, Output = Self> + + for<'a> Mul<&'a NonNativeFieldVar, Output = Self> + + MulAssign> { /// Returns the constant `F::zero()`. This is the identity /// of the group. diff --git a/src/macros.rs b/src/macros.rs index 2770a7e3..1564f491 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -51,7 +51,7 @@ macro_rules! impl_bounded_ops { #[tracing::instrument(target = "r1cs", skip(self))] #[allow(unused_braces, clippy::redundant_closure_call)] - fn $fn(self, other: Self) -> Self::Output { + fn $fn(self, other: &'a $type) -> Self::Output { ($impl)(self, other) } } @@ -165,3 +165,108 @@ macro_rules! impl_bounded_ops { } } } + +/// Implements arithmetic traits (eg: `Add`, `Sub`, `Mul`) for the given type +/// using the impl in `$impl`. +/// +/// Used primarily for implementing these traits for `FieldVar`s and +/// `GroupVar`s. +/// +/// When compared to `impl_ops`, this macro allows specifying additional trait +/// bounds. +#[macro_export] +macro_rules! impl_bounded_ops_diff { + ( + $type: ty, + $native: ty, + $other_type: ty, + $other_native: ty, + $trait: ident, + $fn: ident, + $assign_trait: ident, + $assign_fn: ident, + $impl: expr, + $constant_impl: expr, + ($($params:tt)+), + $($bounds:tt)* + ) => { + impl<'a, $($params)+> core::ops::$trait<&'a $other_type> for &'a $type + where + $($bounds)* + { + type Output = $type; + + #[tracing::instrument(target = "r1cs", skip(self))] + #[allow(unused_braces, clippy::redundant_closure_call)] + fn $fn(self, other: &'a $other_type) -> Self::Output { + ($impl)(self, other) + } + } + + impl<'a, $($params)+> core::ops::$trait<$other_type> for &'a $type + where + $($bounds)* + { + type Output = $type; + + #[tracing::instrument(target = "r1cs", skip(self))] + #[allow(unused_braces)] + fn $fn(self, other: $other_type) -> Self::Output { + core::ops::$trait::$fn(self, &other) + } + } + + impl<'a, $($params)+> core::ops::$trait<&'a $other_type> for $type + where + $($bounds)* + { + type Output = $type; + + #[tracing::instrument(target = "r1cs", skip(self))] + #[allow(unused_braces)] + fn $fn(self, other: &'a $other_type) -> Self::Output { + core::ops::$trait::$fn(&self, other) + } + } + + impl<$($params)+> core::ops::$trait<$other_type> for $type + where + + $($bounds)* + { + type Output = $type; + + #[tracing::instrument(target = "r1cs", skip(self))] + #[allow(unused_braces)] + fn $fn(self, other: $other_type) -> Self::Output { + core::ops::$trait::$fn(&self, &other) + } + } + + impl<$($params)+> core::ops::$assign_trait<$other_type> for $type + where + + $($bounds)* + { + #[tracing::instrument(target = "r1cs", skip(self))] + #[allow(unused_braces)] + fn $assign_fn(&mut self, other: $other_type) { + let result = core::ops::$trait::$fn(&*self, &other); + *self = result + } + } + + impl<'a, $($params)+> core::ops::$assign_trait<&'a $other_type> for $type + where + + $($bounds)* + { + #[tracing::instrument(target = "r1cs", skip(self))] + #[allow(unused_braces)] + fn $assign_fn(&mut self, other: &'a $other_type) { + let result = core::ops::$trait::$fn(&*self, other); + *self = result + } + } + } +} diff --git a/src/pairing/mod.rs b/src/pairing/mod.rs index 958134e1..1686489b 100644 --- a/src/pairing/mod.rs +++ b/src/pairing/mod.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use ark_ec::pairing::Pairing; use ark_ec::CurveGroup; -use ark_ff::Field; +use ark_ff::PrimeField; use ark_relations::r1cs::SynthesisError; use core::fmt::Debug; @@ -14,7 +14,10 @@ pub mod mnt6; /// Specifies the constraints for computing a pairing in the yybilinear group /// `E`. -pub trait PairingVar::G1 as CurveGroup>::BaseField> +pub trait PairingVar< + E: Pairing, + ConstraintF: PrimeField = <::G1 as CurveGroup>::BaseField, +> { /// An variable representing an element of `G1`. /// This is the R1CS equivalent of `E::G1Projective`. From 58a8a2db6a8b88fd9b78ea0fa27f0af412d87368 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 25 Dec 2023 23:24:14 -0500 Subject: [PATCH 02/13] Fix --- src/bits/uint8.rs | 2 +- src/fields/nonnative/allocated_field_var.rs | 28 ++++++++++----------- src/pairing/mod.rs | 10 +++----- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/bits/uint8.rs b/src/bits/uint8.rs index f1612719..a8dd57f4 100644 --- a/src/bits/uint8.rs +++ b/src/bits/uint8.rs @@ -342,7 +342,7 @@ impl AllocVar for UInt8 { /// `ConstraintF::MODULUS_BIT_SIZE - 1` chunks and converts each chunk, which is /// assumed to be little-endian, to its `FpVar` representation. /// This is the gadget counterpart to the `[u8]` implementation of -/// [ToConstraintField](ark_ff::ToConstraintField). +/// [`ToConstraintField`]. impl ToConstraintFieldGadget for [UInt8] { #[tracing::instrument(target = "r1cs")] fn to_constraint_field(&self) -> Result>, SynthesisError> { diff --git a/src/fields/nonnative/allocated_field_var.rs b/src/fields/nonnative/allocated_field_var.rs index dd4dfae4..ee4e2439 100644 --- a/src/fields/nonnative/allocated_field_var.rs +++ b/src/fields/nonnative/allocated_field_var.rs @@ -60,7 +60,7 @@ impl // Convert 2^{(params.bits_per_limb - 1)} into the TargetField and then double // the base This is because 2^{(params.bits_per_limb)} might indeed be // larger than the target field's prime. - let base_repr = TargetField::ONE.into_bigint() >> (params.bits_per_limb - 1) as u32; + let base_repr = TargetField::ONE.into_bigint() << (params.bits_per_limb - 1) as u32; let mut base = TargetField::from_bigint(base_repr).unwrap(); base.double_in_place(); @@ -205,23 +205,21 @@ impl > BaseField::MODULUS_BIT_SIZE as usize - 1) { Reducer::reduce(&mut other)?; - surfeit = overhead!(other.num_of_additions_over_normal_form + BaseField::one()) + 1; + surfeit = overhead!(other.num_of_additions_over_normal_form + BaseField::ONE) + 1; } // Step 2: construct the padding - let mut pad_non_top_limb_repr = BaseField::one().into_bigint(); - let mut pad_top_limb_repr = pad_non_top_limb_repr; + let mut pad_non_top_limb = BaseField::ONE.into_bigint(); + let mut pad_top_limb = pad_non_top_limb; - pad_non_top_limb_repr <<= (surfeit + params.bits_per_limb) as u32; - let pad_non_top_limb = BaseField::from_bigint(pad_non_top_limb_repr).unwrap(); + pad_non_top_limb <<= (surfeit + params.bits_per_limb) as u32; + let pad_non_top_limb = BaseField::from_bigint(pad_non_top_limb).unwrap(); - pad_top_limb_repr <<= (surfeit - + (TargetField::MODULUS_BIT_SIZE as usize - - params.bits_per_limb * (params.num_limbs - 1))) - as u32; - let pad_top_limb = BaseField::from_bigint(pad_top_limb_repr).unwrap(); + pad_top_limb <<= (surfeit + TargetField::MODULUS_BIT_SIZE as usize + - params.bits_per_limb * (params.num_limbs - 1)) as u32; + let pad_top_limb = BaseField::from_bigint(pad_top_limb).unwrap(); - let mut pad_limbs = Vec::new(); + let mut pad_limbs = Vec::with_capacity(self.limbs.len()); pad_limbs.push(pad_top_limb); for _ in 0..self.limbs.len() - 1 { pad_limbs.push(pad_non_top_limb); @@ -233,12 +231,12 @@ impl Self::get_limbs_representations(&pad_to_kp_gap, self.get_optimization_type())?; // Step 4: the result is self + pad + pad_to_kp - other - let mut limbs = Vec::new(); + let mut limbs = Vec::with_capacity(self.limbs.len()); for (i, ((this_limb, other_limb), pad_to_kp_limb)) in self .limbs .iter() - .zip(other.limbs.iter()) - .zip(pad_to_kp_limbs.iter()) + .zip(&other.limbs) + .zip(&pad_to_kp_limbs) .enumerate() { if i != 0 { diff --git a/src/pairing/mod.rs b/src/pairing/mod.rs index 166b23cf..48d955f2 100644 --- a/src/pairing/mod.rs +++ b/src/pairing/mod.rs @@ -1,5 +1,5 @@ use crate::prelude::*; -use ark_ec::{pairing::Pairing, CurveGroup}; +use ark_ec::pairing::Pairing; use ark_ff::PrimeField; use ark_relations::r1cs::SynthesisError; use core::fmt::Debug; @@ -11,13 +11,11 @@ pub mod mnt4; /// This module implements pairings for MNT6 bilinear groups. pub mod mnt6; +type BasePrimeField = <::BaseField as ark_ff::Field>::BasePrimeField; + /// Specifies the constraints for computing a pairing in the yybilinear group /// `E`. -pub trait PairingVar< - E: Pairing, - ConstraintF: PrimeField = <::G1 as CurveGroup>::BaseField, -> -{ +pub trait PairingVar> { /// An variable representing an element of `G1`. /// This is the R1CS equivalent of `E::G1Projective`. type G1Var: CurveVar From 8b3bc0d87cd1b1811be00ee24d57809daa38314f Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 25 Dec 2023 23:25:45 -0500 Subject: [PATCH 03/13] rename --- src/groups/curves/short_weierstrass/mod.rs | 44 +++++++++---------- .../short_weierstrass/non_zero_affine.rs | 10 ++--- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/groups/curves/short_weierstrass/mod.rs b/src/groups/curves/short_weierstrass/mod.rs index e2f286cc..ea721fe2 100644 --- a/src/groups/curves/short_weierstrass/mod.rs +++ b/src/groups/curves/short_weierstrass/mod.rs @@ -1,7 +1,5 @@ use ark_ec::{ - short_weierstrass::{ - Affine as SWAffine, Projective as SWProjective, SWCurveConfig as SWModelParameters, - }, + short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig}, AffineRepr, CurveConfig, CurveGroup, }; use ark_ff::{AdditiveGroup, BitIteratorBE, Field, One, PrimeField, Zero}; @@ -43,7 +41,7 @@ type BasePrimeField

= <

::BaseField as Field>::BasePrimeFiel #[derive(Derivative)] #[derivative(Debug, Clone)] #[must_use] -pub struct ProjectiveVar>> +pub struct ProjectiveVar>> where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -61,7 +59,7 @@ where #[derive(Derivative)] #[derivative(Debug(bound = "F: ark_std::fmt::Debug"), Clone(bound = "F: Clone"))] #[must_use] -pub struct AffineVar>> +pub struct AffineVar>> where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -77,7 +75,7 @@ where impl AffineVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -102,7 +100,7 @@ where impl ToConstraintFieldGadget> for AffineVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, F: ToConstraintFieldGadget>, @@ -120,7 +118,7 @@ where impl R1CSVar> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -141,7 +139,7 @@ where } } -impl>> ProjectiveVar +impl>> ProjectiveVar where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -370,7 +368,7 @@ where impl CurveVar, BasePrimeField

> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -575,7 +573,7 @@ where impl ToConstraintFieldGadget> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, F: ToConstraintFieldGadget>, @@ -585,7 +583,7 @@ where } } -fn mul_by_coeff_a>>(f: &F) -> F +fn mul_by_coeff_a>>(f: &F) -> F where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -670,7 +668,7 @@ impl_bounded_ops!( |this: &'a ProjectiveVar, other: SWProjective

| { this + ProjectiveVar::constant(other) }, - (F: FieldVar>, P: SWModelParameters), + (F: FieldVar>, P: SWCurveConfig), for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, ); @@ -683,7 +681,7 @@ impl_bounded_ops!( sub_assign, |this: &'a ProjectiveVar, other: &'a ProjectiveVar| this + other.negate().unwrap(), |this: &'a ProjectiveVar, other: SWProjective

| this - ProjectiveVar::constant(other), - (F: FieldVar>, P: SWModelParameters), + (F: FieldVar>, P: SWCurveConfig), for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F> ); @@ -706,13 +704,13 @@ impl_bounded_ops_diff!( } }, |this: &'a ProjectiveVar, other: P::ScalarField| this * NonNativeFieldVar::constant(other), - (F: FieldVar>, P: SWModelParameters), + (F: FieldVar>, P: SWCurveConfig), for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, ); impl<'a, P, F> GroupOpsBounds<'a, SWProjective

, ProjectiveVar> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { @@ -720,7 +718,7 @@ where impl<'a, P, F> GroupOpsBounds<'a, SWProjective

, ProjectiveVar> for &'a ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { @@ -728,7 +726,7 @@ where impl CondSelectGadget> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -749,7 +747,7 @@ where impl EqGadget> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -795,7 +793,7 @@ where impl AllocVar, BasePrimeField

> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -814,7 +812,7 @@ where impl AllocVar, BasePrimeField

> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -924,7 +922,7 @@ fn div2(limbs: &mut [u64]) { impl ToBitsGadget> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -951,7 +949,7 @@ where impl ToBytesGadget> for ProjectiveVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { diff --git a/src/groups/curves/short_weierstrass/non_zero_affine.rs b/src/groups/curves/short_weierstrass/non_zero_affine.rs index 52e61c12..c1de4161 100644 --- a/src/groups/curves/short_weierstrass/non_zero_affine.rs +++ b/src/groups/curves/short_weierstrass/non_zero_affine.rs @@ -8,7 +8,7 @@ use ark_std::ops::Add; #[derivative(Debug, Clone)] #[must_use] pub struct NonZeroAffineVar< - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar::BasePrimeField>, > where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, @@ -23,7 +23,7 @@ pub struct NonZeroAffineVar< impl NonZeroAffineVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar::BasePrimeField>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -140,7 +140,7 @@ where impl R1CSVar<::BasePrimeField> for NonZeroAffineVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar::BasePrimeField>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -157,7 +157,7 @@ where impl CondSelectGadget<::BasePrimeField> for NonZeroAffineVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar::BasePrimeField>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -177,7 +177,7 @@ where impl EqGadget<::BasePrimeField> for NonZeroAffineVar where - P: SWModelParameters, + P: SWCurveConfig, F: FieldVar::BasePrimeField>, for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { From 9a589f9cdb7fcf7d1e524d80ac029348f59e36b4 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 25 Dec 2023 23:39:37 -0500 Subject: [PATCH 04/13] remove type parameters --- src/pairing/bls12/mod.rs | 2 +- src/pairing/mnt4/mod.rs | 2 +- src/pairing/mnt6/mod.rs | 2 +- src/pairing/mod.rs | 25 ++++++++++++------------- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/pairing/bls12/mod.rs b/src/pairing/bls12/mod.rs index 727f1e93..4e7c3958 100644 --- a/src/pairing/bls12/mod.rs +++ b/src/pairing/bls12/mod.rs @@ -59,7 +59,7 @@ impl PairingVar

{ } } -impl PG, P::Fp> for PairingVar

{ +impl PG> for PairingVar

{ type G1Var = G1Var

; type G2Var = G2Var

; type G1PreparedVar = G1PreparedVar

; diff --git a/src/pairing/mnt4/mod.rs b/src/pairing/mnt4/mod.rs index 73e43ddc..07fcab0b 100644 --- a/src/pairing/mnt4/mod.rs +++ b/src/pairing/mnt4/mod.rs @@ -196,7 +196,7 @@ impl PairingVar

{ } } -impl PG, P::Fp> for PairingVar

{ +impl PG> for PairingVar

{ type G1Var = G1Var

; type G2Var = G2Var

; type G1PreparedVar = G1PreparedVar

; diff --git a/src/pairing/mnt6/mod.rs b/src/pairing/mnt6/mod.rs index b469549c..27252f9b 100644 --- a/src/pairing/mnt6/mod.rs +++ b/src/pairing/mnt6/mod.rs @@ -191,7 +191,7 @@ impl PairingVar

{ } } -impl PG, P::Fp> for PairingVar

{ +impl PG> for PairingVar

{ type G1Var = G1Var

; type G2Var = G2Var

; type G1PreparedVar = G1PreparedVar

; diff --git a/src/pairing/mod.rs b/src/pairing/mod.rs index 48d955f2..8e0bfe27 100644 --- a/src/pairing/mod.rs +++ b/src/pairing/mod.rs @@ -1,6 +1,5 @@ use crate::prelude::*; use ark_ec::pairing::Pairing; -use ark_ff::PrimeField; use ark_relations::r1cs::SynthesisError; use core::fmt::Debug; @@ -15,35 +14,35 @@ type BasePrimeField = <::BaseField as ark_ff::Field>::BasePrime /// Specifies the constraints for computing a pairing in the yybilinear group /// `E`. -pub trait PairingVar> { +pub trait PairingVar { /// An variable representing an element of `G1`. /// This is the R1CS equivalent of `E::G1Projective`. - type G1Var: CurveVar - + AllocVar - + AllocVar; + type G1Var: CurveVar> + + AllocVar> + + AllocVar>; /// An variable representing an element of `G2`. /// This is the R1CS equivalent of `E::G2Projective`. - type G2Var: CurveVar - + AllocVar - + AllocVar; + type G2Var: CurveVar> + + AllocVar> + + AllocVar>; /// An variable representing an element of `GT`. /// This is the R1CS equivalent of `E::GT`. - type GTVar: FieldVar; + type GTVar: FieldVar>; /// An variable representing cached precomputation that can speed up /// pairings computations. This is the R1CS equivalent of /// `E::G1Prepared`. - type G1PreparedVar: ToBytesGadget - + AllocVar + type G1PreparedVar: ToBytesGadget> + + AllocVar> + Clone + Debug; /// An variable representing cached precomputation that can speed up /// pairings computations. This is the R1CS equivalent of /// `E::G2Prepared`. - type G2PreparedVar: ToBytesGadget - + AllocVar + type G2PreparedVar: ToBytesGadget> + + AllocVar> + Clone + Debug; From e76ffdc6b4c761666d4f343d8e82828eaddaeacf Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 21:11:49 -0500 Subject: [PATCH 05/13] Tweak --- src/poly/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/poly/mod.rs b/src/poly/mod.rs index f17cb273..78cb3fe9 100644 --- a/src/poly/mod.rs +++ b/src/poly/mod.rs @@ -1,4 +1,6 @@ +/// Evaluation domains for polynomials. pub mod domain; +/// Evaluations of polynomials over domains. pub mod evaluations; /// Modules for working with polynomials in coefficient forms. pub mod polynomial; From dc441e33ad26697fb977d7806289f80b3737f09c Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 21:15:43 -0500 Subject: [PATCH 06/13] Update CI --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af20cde2..cdea800f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,7 +154,7 @@ jobs: - name: Checkout curves uses: actions/checkout@v2 with: - repository: arkworks-rs/curves + repository: arkworks-rs/algebra - name: Checkout r1cs-std uses: actions/checkout@v2 @@ -164,6 +164,10 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable + - name: Change directory to curves + run: cd algebra + + - name: Patch cargo.toml run: | if grep -q "\[patch.crates-io\]" Cargo.toml ; then @@ -180,7 +184,7 @@ jobs: echo "ark-serialize = { git = 'https://github.com/arkworks-rs/algebra' }" echo "ark-algebra-bench-templates = { git = 'https://github.com/arkworks-rs/algebra' }" echo "ark-algebra-test-templates = { git = 'https://github.com/arkworks-rs/algebra' }" - echo "ark-r1cs-std = { path = 'r1cs-std' }" + echo "ark-r1cs-std = { path = '../r1cs-std' }" } >> Cargo.toml - name: Test on ${{ matrix.curve }} From 1149bf43157f0b8b2edc07f5d02ff974cc76704c Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 21:17:49 -0500 Subject: [PATCH 07/13] Tweak --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cdea800f..6e4d32fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -165,8 +165,7 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Change directory to curves - run: cd algebra - + run: cd curves - name: Patch cargo.toml run: | From 8e44464d52a738f5994a87d5885610df0c2c928f Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 21:18:53 -0500 Subject: [PATCH 08/13] Tweak --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e4d32fe..1da0a284 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -165,7 +165,7 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Change directory to curves - run: cd curves + run: ls; cd curves - name: Patch cargo.toml run: | @@ -187,4 +187,4 @@ jobs: } >> Cargo.toml - name: Test on ${{ matrix.curve }} - run: "cd ${{ matrix.curve }} && cargo test --features 'r1cs'" + run: "ls; cd ${{ matrix.curve }} && cargo test --features 'r1cs'" From f82cceebef20db9870ad290f54f548930d76dcec Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 21:23:03 -0500 Subject: [PATCH 09/13] Tweak --- .github/workflows/ci.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1da0a284..ae747146 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -164,11 +164,10 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable - - name: Change directory to curves - run: ls; cd curves - - name: Patch cargo.toml run: | + ls + cd curves if grep -q "\[patch.crates-io\]" Cargo.toml ; then MATCH=$(awk '/\[patch.crates-io\]/{ print NR; exit }' Cargo.toml); sed -i "$MATCH,\$d" Cargo.toml @@ -176,15 +175,13 @@ jobs: { echo "[patch.crates-io]" echo "ark-std = { git = 'https://github.com/arkworks-rs/std' }" - echo "ark-ec = { git = 'https://github.com/arkworks-rs/algebra' }" - echo "ark-ff = { git = 'https://github.com/arkworks-rs/algebra' }" - echo "ark-poly = { git = 'https://github.com/arkworks-rs/algebra' }" + echo "ark-ec = { path = '../ec' }" + echo "ark-ff = { path = '../ff' }" + echo "ark-poly = { git = '../poly' }" echo "ark-relations = { git = 'https://github.com/arkworks-rs/snark' }" - echo "ark-serialize = { git = 'https://github.com/arkworks-rs/algebra' }" - echo "ark-algebra-bench-templates = { git = 'https://github.com/arkworks-rs/algebra' }" - echo "ark-algebra-test-templates = { git = 'https://github.com/arkworks-rs/algebra' }" + echo "ark-serialize = { path = '../serialize' }" + echo "ark-algebra-bench-templates = { path = '../bench-templates' }" + echo "ark-algebra-test-templates = { path = '../test-templates' }" echo "ark-r1cs-std = { path = '../r1cs-std' }" } >> Cargo.toml - - - name: Test on ${{ matrix.curve }} - run: "ls; cd ${{ matrix.curve }} && cargo test --features 'r1cs'" + cd ${{ matrix.curve }} && cargo test --features 'r1cs' \ No newline at end of file From 8312bc87c3eb8dc6b0c0547df65176ef578e93f6 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 21:25:12 -0500 Subject: [PATCH 10/13] Tweak --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae747146..d5e59f84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -177,7 +177,7 @@ jobs: echo "ark-std = { git = 'https://github.com/arkworks-rs/std' }" echo "ark-ec = { path = '../ec' }" echo "ark-ff = { path = '../ff' }" - echo "ark-poly = { git = '../poly' }" + echo "ark-poly = { path = '../poly' }" echo "ark-relations = { git = 'https://github.com/arkworks-rs/snark' }" echo "ark-serialize = { path = '../serialize' }" echo "ark-algebra-bench-templates = { path = '../bench-templates' }" From 65557139f4ec4b0ac9c7ae9b528431ca9d19a3fe Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 21:48:37 -0500 Subject: [PATCH 11/13] Work --- src/pairing/mod.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/pairing/mod.rs b/src/pairing/mod.rs index 8e0bfe27..dbdb6483 100644 --- a/src/pairing/mod.rs +++ b/src/pairing/mod.rs @@ -17,15 +17,11 @@ type BasePrimeField = <::BaseField as ark_ff::Field>::BasePrime pub trait PairingVar { /// An variable representing an element of `G1`. /// This is the R1CS equivalent of `E::G1Projective`. - type G1Var: CurveVar> - + AllocVar> - + AllocVar>; + type G1Var: CurveVar>; /// An variable representing an element of `G2`. /// This is the R1CS equivalent of `E::G2Projective`. - type G2Var: CurveVar> - + AllocVar> - + AllocVar>; + type G2Var: CurveVar>; /// An variable representing an element of `GT`. /// This is the R1CS equivalent of `E::GT`. From aeacf5fbf8d03a43908ff678e23af81b16a15f32 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 21:57:59 -0500 Subject: [PATCH 12/13] Temp tweak --- .github/workflows/ci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5e59f84..d0508c9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,14 +109,14 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Install Rust (${{ matrix.rust }}) + - name: Install Rust uses: dtolnay/rust-toolchain@stable id: toolchain-thumbv6m with: target: thumbv6m-none-eabi - run: rustup override set ${{steps.toolchain-thumbv6m.outputs.name}} - - name: Install Rust ARM64 (${{ matrix.rust }}) + - name: Install Rust ARM64 uses: dtolnay/rust-toolchain@stable id: toolchain-aarch64 with: @@ -152,12 +152,13 @@ jobs: - ed_on_bls12_381 steps: - name: Checkout curves - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: repository: arkworks-rs/algebra + ref: curve-constraint-test-fix - name: Checkout r1cs-std - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: r1cs-std From f07eeb647f4f436af03a1d78a34b5ab306324ed3 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 22:03:21 -0500 Subject: [PATCH 13/13] Undo branch tweak --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0508c9f..b4f5893a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -155,7 +155,6 @@ jobs: uses: actions/checkout@v4 with: repository: arkworks-rs/algebra - ref: curve-constraint-test-fix - name: Checkout r1cs-std uses: actions/checkout@v4 @@ -167,7 +166,6 @@ jobs: - name: Patch cargo.toml run: | - ls cd curves if grep -q "\[patch.crates-io\]" Cargo.toml ; then MATCH=$(awk '/\[patch.crates-io\]/{ print NR; exit }' Cargo.toml);