From 1ff3a902bdcd71a6bb3544dfa6793fb1fd0f9a55 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Wed, 27 Dec 2023 22:07:35 -0500 Subject: [PATCH] Add `Mul for Group` (#134) --- .github/workflows/ci.yml | 29 ++- src/bits/uint8.rs | 2 +- src/fields/nonnative/allocated_field_var.rs | 39 ++-- src/fields/nonnative/reduce.rs | 25 +- src/groups/curves/short_weierstrass/mod.rs | 203 ++++++++-------- .../short_weierstrass/non_zero_affine.rs | 10 +- src/groups/curves/twisted_edwards/mod.rs | 220 +++++++++--------- src/groups/mod.rs | 17 +- src/macros.rs | 107 ++++++++- src/pairing/bls12/mod.rs | 2 +- src/pairing/mnt4/mod.rs | 2 +- src/pairing/mnt6/mod.rs | 2 +- src/pairing/mod.rs | 26 +-- src/poly/mod.rs | 2 + 14 files changed, 392 insertions(+), 294 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af20cde..b4f5893 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,12 @@ jobs: - ed_on_bls12_381 steps: - name: Checkout curves - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: - repository: arkworks-rs/curves + repository: arkworks-rs/algebra - name: Checkout r1cs-std - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: r1cs-std @@ -166,6 +166,7 @@ jobs: - name: Patch cargo.toml run: | + 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 @@ -173,15 +174,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 = { path = '../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-r1cs-std = { path = 'r1cs-std' }" + 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: "cd ${{ matrix.curve }} && cargo test --features 'r1cs'" + cd ${{ matrix.curve }} && cargo test --features 'r1cs' \ No newline at end of file diff --git a/src/bits/uint8.rs b/src/bits/uint8.rs index f161271..a8dd57f 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 aadbe1a..ee4e243 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(); @@ -206,25 +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: ::BigInt = - BaseField::one().into_bigint(); - let mut pad_top_limb_repr: ::BigInt = 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.muln((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.muln( - (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); @@ -236,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 { @@ -341,7 +336,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 31e5fe7..b7de396 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 c21822f..ea721fe 100644 --- a/src/groups/curves/short_weierstrass/mod.rs +++ b/src/groups/curves/short_weierstrass/mod.rs @@ -1,14 +1,13 @@ use ark_ec::{ - short_weierstrass::{ - Affine as SWAffine, Projective as SWProjective, SWCurveConfig as SWModelParameters, - }, - AffineRepr, CurveGroup, + short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig}, + 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 +32,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 +57,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,18 +68,18 @@ 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

, } impl AffineVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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 +98,15 @@ where } } -impl ToConstraintFieldGadget<::BasePrimeField> for AffineVar +impl ToConstraintFieldGadget> for AffineVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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 +116,15 @@ where } } -impl R1CSVar<::BasePrimeField> for ProjectiveVar +impl R1CSVar> for ProjectiveVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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 +139,7 @@ where } } -impl::BasePrimeField>> - ProjectiveVar +impl>> ProjectiveVar where for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { @@ -200,7 +195,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 { @@ -288,7 +283,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; @@ -371,11 +366,10 @@ where } } -impl CurveVar, ::BasePrimeField> - for ProjectiveVar +impl CurveVar, BasePrimeField

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

) -> Self { @@ -387,13 +381,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 { @@ -503,7 +497,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() { @@ -565,7 +559,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 @@ -577,26 +571,19 @@ where } } -impl ToConstraintFieldGadget<::BasePrimeField> for ProjectiveVar +impl ToConstraintFieldGadget> for ProjectiveVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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>, { @@ -681,7 +668,7 @@ impl_bounded_ops!( |this: &'a ProjectiveVar, other: SWProjective

| { this + ProjectiveVar::constant(other) }, - (F: FieldVar::BasePrimeField>, P: SWModelParameters), + (F: FieldVar>, P: SWCurveConfig), for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, ); @@ -694,36 +681,59 @@ 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: SWCurveConfig), 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: SWCurveConfig), + 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>, + P: SWCurveConfig, + F: FieldVar>, for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, { } impl<'a, P, F> GroupOpsBounds<'a, SWProjective

, ProjectiveVar> for &'a ProjectiveVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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>, + P: SWCurveConfig, + 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 { @@ -735,17 +745,14 @@ where } } -impl EqGadget<::BasePrimeField> for ProjectiveVar +impl EqGadget> for ProjectiveVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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)?; @@ -758,7 +765,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))?; @@ -775,7 +782,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 @@ -784,14 +791,14 @@ where } } -impl AllocVar, ::BasePrimeField> for ProjectiveVar +impl AllocVar, BasePrimeField

> for ProjectiveVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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 { @@ -803,15 +810,14 @@ where } } -impl AllocVar, ::BasePrimeField> - for ProjectiveVar +impl AllocVar, BasePrimeField

> for ProjectiveVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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 { @@ -864,8 +870,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(); @@ -915,16 +920,14 @@ fn div2(limbs: &mut [u64]) { } } -impl ToBitsGadget<::BasePrimeField> for ProjectiveVar +impl ToBitsGadget> for ProjectiveVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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()?; @@ -934,9 +937,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()?; @@ -946,16 +947,14 @@ where } } -impl ToBytesGadget<::BasePrimeField> for ProjectiveVar +impl ToBytesGadget> for ProjectiveVar where - P: SWModelParameters, - F: FieldVar::BasePrimeField>, + P: SWCurveConfig, + 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()?; @@ -966,9 +965,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/short_weierstrass/non_zero_affine.rs b/src/groups/curves/short_weierstrass/non_zero_affine.rs index 52e61c1..c1de416 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>, { diff --git a/src/groups/curves/twisted_edwards/mod.rs b/src/groups/curves/twisted_edwards/mod.rs index 4b92d6b..861ecfa 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 fb8c746..84c6335 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 2770a7e..1564f49 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/bls12/mod.rs b/src/pairing/bls12/mod.rs index 727f1e9..4e7c395 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 73e43dd..07fcab0 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 b469549..27252f9 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 55cc139..dbdb648 100644 --- a/src/pairing/mod.rs +++ b/src/pairing/mod.rs @@ -1,6 +1,5 @@ use crate::prelude::*; -use ark_ec::{pairing::Pairing, CurveGroup}; -use ark_ff::Field; +use ark_ec::pairing::Pairing; use ark_relations::r1cs::SynthesisError; use core::fmt::Debug; @@ -11,38 +10,35 @@ 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::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 - + 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`. - 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; diff --git a/src/poly/mod.rs b/src/poly/mod.rs index f17cb27..78cb3fe 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;