From 66e90730bb13e08443792acb811a8cb781a6e949 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 5 Aug 2021 22:14:19 -0700 Subject: [PATCH] Get groups to compile --- .../curves/short_weierstrass/bls12/mod.rs | 70 +++-- .../curves/short_weierstrass/mnt4/mod.rs | 133 +++++++--- .../curves/short_weierstrass/mnt6/mod.rs | 124 ++++++--- src/groups/curves/short_weierstrass/mod.rs | 157 ++++++------ .../short_weierstrass/non_zero_affine.rs | 34 ++- src/groups/curves/twisted_edwards/mod.rs | 242 +++++++++--------- src/groups/mod.rs | 4 + 7 files changed, 472 insertions(+), 292 deletions(-) diff --git a/src/groups/curves/short_weierstrass/bls12/mod.rs b/src/groups/curves/short_weierstrass/bls12/mod.rs index 9563c050..9ac314c7 100644 --- a/src/groups/curves/short_weierstrass/bls12/mod.rs +++ b/src/groups/curves/short_weierstrass/bls12/mod.rs @@ -6,36 +6,44 @@ use ark_ff::{BitIteratorBE, Field, One}; use ark_relations::r1cs::{Namespace, SynthesisError}; use crate::{ - fields::{fp::FpVar, fp2::Fp2Var, FieldVar}, + fields::{fp2::Fp2Var, FieldVar}, groups::curves::short_weierstrass::*, Vec, }; use core::fmt::Debug; +type FpVar

= <

::Fp as FieldWithVar>::Var; + /// Represents a projective point in G1. -pub type G1Var

= - ProjectiveVar<

::G1Parameters, FpVar<

::Fp>>; +pub type G1Var

= ProjectiveVar<

::G1Parameters>; /// Represents an affine point on G1. Should be used only for comparison and /// when a canonical representation of a point is required, and not for /// arithmetic. -pub type G1AffineVar

= - AffineVar<

::G1Parameters, FpVar<

::Fp>>; +pub type G1AffineVar

= AffineVar<

::G1Parameters>; /// Represents a projective point in G2. -pub type G2Var

= ProjectiveVar<

::G2Parameters, Fp2G

>; +pub type G2Var

= ProjectiveVar<

::G2Parameters>; /// Represents an affine point on G2. Should be used only for comparison and /// when a canonical representation of a point is required, and not for /// arithmetic. -pub type G2AffineVar

= AffineVar<

::G2Parameters, Fp2G

>; +pub type G2AffineVar

= AffineVar<

::G2Parameters>; /// Represents the cached precomputation that can be performed on a G1 element /// which enables speeding up pairing computation. #[derive(Derivative)] -#[derivative(Clone(bound = "G1Var

: Clone"), Debug(bound = "G1Var

: Debug"))] -pub struct G1PreparedVar(pub AffineVar>); +#[derivative( + Clone(bound = "P: Bls12Parameters, P::Fp: FieldWithVar"), + Debug(bound = "P: Bls12Parameters, P::Fp: FieldWithVar") +)] +pub struct G1PreparedVar(pub G1AffineVar

) +where + P::Fp: FieldWithVar; -impl G1PreparedVar

{ +impl G1PreparedVar

+where + P::Fp: FieldWithVar, +{ /// Returns the value assigned to `self` in the underlying constraint /// system. pub fn value(&self) -> Result, SynthesisError> { @@ -53,7 +61,10 @@ impl G1PreparedVar

{ } } -impl AllocVar, P::Fp> for G1PreparedVar

{ +impl AllocVar, P::Fp> for G1PreparedVar

+where + P::Fp: FieldWithVar, +{ fn new_variable>>( cs: impl Into>, f: impl FnOnce() -> Result, @@ -63,19 +74,24 @@ impl AllocVar, P::Fp> for G1PreparedVar

{ let cs = ns.cs(); let g1_prep = f().map(|b| b.borrow().0); - let x = FpVar::new_variable(ark_relations::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; - let y = FpVar::new_variable(ark_relations::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; + let x = + FpVar::

::new_variable(ark_relations::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; + let y = + FpVar::

::new_variable(ark_relations::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; let infinity = Boolean::new_variable( ark_relations::ns!(cs, "inf"), || g1_prep.map(|g| g.infinity), mode, )?; - let g = AffineVar::new(x, y, infinity); + let g = G1AffineVar::

::new(x, y, infinity); Ok(Self(g)) } } -impl ToBytesGadget for G1PreparedVar

{ +impl ToBytesGadget for G1PreparedVar

+where + P::Fp: FieldWithVar, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -104,15 +120,21 @@ type LCoeff

= (Fp2G

, Fp2G

); /// which enables speeding up pairing computation. #[derive(Derivative)] #[derivative( - Clone(bound = "Fp2Var: Clone"), - Debug(bound = "Fp2Var: Debug") + Clone(bound = "P::Fp: FieldWithVar"), + Debug(bound = "P::Fp: FieldWithVar") )] -pub struct G2PreparedVar { +pub struct G2PreparedVar +where + P::Fp: FieldWithVar, +{ #[doc(hidden)] pub ell_coeffs: Vec>, } -impl AllocVar, P::Fp> for G2PreparedVar

{ +impl AllocVar, P::Fp> for G2PreparedVar

+where + P::Fp: FieldWithVar, +{ #[tracing::instrument(target = "r1cs", skip(cs, f, mode))] fn new_variable>>( cs: impl Into>, @@ -170,7 +192,10 @@ impl AllocVar, P::Fp> for G2PreparedVar

{ } } -impl ToBytesGadget for G2PreparedVar

{ +impl ToBytesGadget for G2PreparedVar

+where + P::Fp: FieldWithVar, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -193,7 +218,10 @@ impl ToBytesGadget for G2PreparedVar

{ } } -impl G2PreparedVar

{ +impl G2PreparedVar

+where + P::Fp: FieldWithVar, +{ /// Constructs `Self` from a `G2Var`. #[tracing::instrument(target = "r1cs")] pub fn from_group_var(q: &G2Var

) -> Result { diff --git a/src/groups/curves/short_weierstrass/mnt4/mod.rs b/src/groups/curves/short_weierstrass/mnt4/mod.rs index bd0bdc6a..77bb5ec6 100644 --- a/src/groups/curves/short_weierstrass/mnt4/mod.rs +++ b/src/groups/curves/short_weierstrass/mnt4/mod.rs @@ -6,26 +6,31 @@ use ark_ff::Field; use ark_relations::r1cs::{Namespace, SynthesisError}; use crate::{ - fields::{fp::FpVar, fp2::Fp2Var, FieldVar}, + fields::{fp::FpVar, fp2::Fp2Var, FieldVar, FieldWithVar}, groups::curves::short_weierstrass::ProjectiveVar, - pairing::mnt4::PairingVar, + pairing::mnt4::MNT4Gadget, prelude::*, Vec, }; use core::borrow::Borrow; /// Represents a projective point in G1. -pub type G1Var

= - ProjectiveVar<

::G1Parameters, FpVar<

::Fp>>; +pub type G1Var

= ProjectiveVar<

::G1Parameters>; /// Represents a projective point in G2. -pub type G2Var

= ProjectiveVar<

::G2Parameters, Fp2G

>; +pub type G2Var

= ProjectiveVar<

::G2Parameters>; /// Represents the cached precomputation that can be performed on a G1 element /// which enables speeding up pairing computation. #[derive(Derivative)] -#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))] -pub struct G1PreparedVar { +#[derivative( + Clone(bound = "P: MNT4Parameters, P::Fp: FieldWithVar>"), + Debug(bound = "P: MNT4Parameters, P::Fp: FieldWithVar>") +)] +pub struct G1PreparedVar +where + P::Fp: FieldWithVar>, +{ #[doc(hidden)] pub x: FpVar, #[doc(hidden)] @@ -36,7 +41,10 @@ pub struct G1PreparedVar { pub y_twist: Fp2Var, } -impl AllocVar, P::Fp> for G1PreparedVar

{ +impl AllocVar, P::Fp> for G1PreparedVar

+where + P::Fp: FieldWithVar>, +{ #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( cs: impl Into>, @@ -48,8 +56,16 @@ impl AllocVar, P::Fp> for G1PreparedVar

{ let g1_prep = f().map(|b| *b.borrow()); - let x = FpVar::new_variable(ark_relations::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; - let y = FpVar::new_variable(ark_relations::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; + let x = FpVar::::new_variable( + ark_relations::ns!(cs, "x"), + || g1_prep.map(|g| g.x), + mode, + )?; + let y = FpVar::::new_variable( + ark_relations::ns!(cs, "y"), + || g1_prep.map(|g| g.y), + mode, + )?; let x_twist = Fp2Var::new_variable( ark_relations::ns!(cs, "x_twist"), || g1_prep.map(|g| g.x_twist), @@ -69,7 +85,10 @@ impl AllocVar, P::Fp> for G1PreparedVar

{ } } -impl G1PreparedVar

{ +impl G1PreparedVar

+where + P::Fp: FieldWithVar>, +{ /// Returns the value assigned to `self` in the underlying constraint /// system. pub fn value(&self) -> Result, SynthesisError> { @@ -91,8 +110,8 @@ impl G1PreparedVar

{ #[tracing::instrument(target = "r1cs")] pub fn from_group_var(q: &G1Var

) -> Result { let q = q.to_affine()?; - let x_twist = Fp2Var::new(&q.x * P::TWIST.c0, &q.x * P::TWIST.c1); - let y_twist = Fp2Var::new(&q.y * P::TWIST.c0, &q.y * P::TWIST.c1); + let x_twist = Fp2Var::new(q.x.clone() * P::TWIST.c0, q.x.clone() * P::TWIST.c1); + let y_twist = Fp2Var::new(q.y.clone() * P::TWIST.c0, q.y.clone() * P::TWIST.c1); Ok(G1PreparedVar { x: q.x, y: q.y, @@ -102,7 +121,10 @@ impl G1PreparedVar

{ } } -impl ToBytesGadget for G1PreparedVar

{ +impl ToBytesGadget for G1PreparedVar

+where + P::Fp: FieldWithVar>, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -136,8 +158,14 @@ type Fp2G

= Fp2Var<

::Fp2Params>; /// Represents the cached precomputation that can be performed on a G2 element /// which enables speeding up pairing computation. #[derive(Derivative)] -#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))] -pub struct G2PreparedVar { +#[derivative( + Clone(bound = "P: MNT4Parameters, P::Fp: FieldWithVar>"), + Debug(bound = "P: MNT4Parameters, P::Fp: FieldWithVar>") +)] +pub struct G2PreparedVar +where + P::Fp: FieldWithVar>, +{ #[doc(hidden)] pub x: Fp2Var, #[doc(hidden)] @@ -152,7 +180,10 @@ pub struct G2PreparedVar { pub addition_coefficients: Vec>, } -impl AllocVar, P::Fp> for G2PreparedVar

{ +impl AllocVar, P::Fp> for G2PreparedVar

+where + P::Fp: FieldWithVar>, +{ #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( cs: impl Into>, @@ -198,7 +229,10 @@ impl AllocVar, P::Fp> for G2PreparedVar

{ } } -impl ToBytesGadget for G2PreparedVar

{ +impl ToBytesGadget for G2PreparedVar

+where + P::Fp: FieldWithVar>, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -241,7 +275,10 @@ impl ToBytesGadget for G2PreparedVar

{ } } -impl G2PreparedVar

{ +impl G2PreparedVar

+where + P::Fp: FieldWithVar>, +{ /// Returns the value assigned to `self` in the underlying constraint /// system. pub fn value(&self) -> Result, SynthesisError> { @@ -304,12 +341,12 @@ impl G2PreparedVar

{ } for bit in v.iter().rev() { - let (r2, coeff) = PairingVar::

::doubling_step_for_flipped_miller_loop(&r)?; + let (r2, coeff) = MNT4Gadget::

::doubling_step_for_flipped_miller_loop(&r)?; g2p.double_coefficients.push(coeff); r = r2; if *bit { - let (r2, coeff) = PairingVar::

::mixed_addition_step_for_flipped_miller_loop( + let (r2, coeff) = MNT4Gadget::

::mixed_addition_step_for_flipped_miller_loop( &q.x, &q.y, &r, )?; g2p.addition_coefficients.push(coeff); @@ -328,7 +365,7 @@ impl G2PreparedVar

{ let minus_r_affine_x = &r.x * &rz2_inv; let minus_r_affine_y = r.y.negate()? * &rz3_inv; - let add_result = PairingVar::

::mixed_addition_step_for_flipped_miller_loop( + let add_result = MNT4Gadget::

::mixed_addition_step_for_flipped_miller_loop( &minus_r_affine_x, &minus_r_affine_y, &r, @@ -342,15 +379,24 @@ impl G2PreparedVar

{ #[doc(hidden)] #[derive(Derivative)] -#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))] -pub struct AteDoubleCoefficientsVar { +#[derivative( + Clone(bound = "P: MNT4Parameters, P::Fp: FieldWithVar>"), + Debug(bound = "P: MNT4Parameters, P::Fp: FieldWithVar>") +)] +pub struct AteDoubleCoefficientsVar +where + P::Fp: FieldWithVar>, +{ pub c_h: Fp2Var, pub c_4c: Fp2Var, pub c_j: Fp2Var, pub c_l: Fp2Var, } -impl AllocVar, P::Fp> for AteDoubleCoefficientsVar

{ +impl AllocVar, P::Fp> for AteDoubleCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( cs: impl Into>, @@ -377,7 +423,10 @@ impl AllocVar, P::Fp> for AteDoubleC } } -impl ToBytesGadget for AteDoubleCoefficientsVar

{ +impl ToBytesGadget for AteDoubleCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -406,7 +455,10 @@ impl ToBytesGadget for AteDoubleCoefficientsVar

{ } } -impl AteDoubleCoefficientsVar

{ +impl AteDoubleCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ /// Returns the value assigned to `self` in the underlying constraint /// system. pub fn value(&self) -> Result, SynthesisError> { @@ -427,14 +479,22 @@ impl AteDoubleCoefficientsVar

{ #[doc(hidden)] #[derive(Derivative)] -#[derivative(Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"))] -pub struct AteAdditionCoefficientsVar { +#[derivative( + Clone(bound = "P: MNT4Parameters, P::Fp: FieldWithVar>"), + Debug(bound = "P: MNT4Parameters, P::Fp: FieldWithVar>") +)] +pub struct AteAdditionCoefficientsVar +where + P::Fp: FieldWithVar>, +{ pub c_l1: Fp2Var, pub c_rz: Fp2Var, } impl AllocVar, P::Fp> for AteAdditionCoefficientsVar

+where + P::Fp: FieldWithVar>, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( @@ -456,7 +516,10 @@ impl AllocVar, P::Fp> } } -impl ToBytesGadget for AteAdditionCoefficientsVar

{ +impl ToBytesGadget for AteAdditionCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -477,7 +540,10 @@ impl ToBytesGadget for AteAdditionCoefficientsVar

{ } } -impl AteAdditionCoefficientsVar

{ +impl AteAdditionCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ /// Returns the value assigned to `self` in the underlying constraint /// system. pub fn value(&self) -> Result, SynthesisError> { @@ -487,7 +553,10 @@ impl AteAdditionCoefficientsVar

{ } #[doc(hidden)] -pub struct G2ProjectiveExtendedVar { +pub struct G2ProjectiveExtendedVar +where + P::Fp: FieldWithVar>, +{ pub x: Fp2Var, pub y: Fp2Var, pub z: Fp2Var, diff --git a/src/groups/curves/short_weierstrass/mnt6/mod.rs b/src/groups/curves/short_weierstrass/mnt6/mod.rs index 8234230a..0b989bb3 100644 --- a/src/groups/curves/short_weierstrass/mnt6/mod.rs +++ b/src/groups/curves/short_weierstrass/mnt6/mod.rs @@ -6,26 +6,31 @@ use ark_ff::Field; use ark_relations::r1cs::{Namespace, SynthesisError}; use crate::{ - fields::{fp::FpVar, fp3::Fp3Var, FieldVar}, + fields::{fp::FpVar, fp3::Fp3Var, FieldVar, FieldWithVar}, groups::curves::short_weierstrass::ProjectiveVar, - pairing::mnt6::PairingVar, + pairing::mnt6::MNT6Gadget, prelude::*, Vec, }; use core::borrow::Borrow; /// Represents a projective point in G1. -pub type G1Var

= - ProjectiveVar<

::G1Parameters, FpVar<

::Fp>>; +pub type G1Var

= ProjectiveVar<

::G1Parameters>; /// Represents a projective point in G2. -pub type G2Var

= ProjectiveVar<

::G2Parameters, Fp3G

>; +pub type G2Var

= ProjectiveVar<

::G2Parameters>; /// Represents the cached precomputation that can be performed on a G1 element /// which enables speeding up pairing computation. #[derive(Derivative)] -#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))] -pub struct G1PreparedVar { +#[derivative( + Clone(bound = "P: MNT6Parameters, P::Fp: FieldWithVar>"), + Debug(bound = "P: MNT6Parameters, P::Fp: FieldWithVar>") +)] +pub struct G1PreparedVar +where + P::Fp: FieldWithVar>, +{ #[doc(hidden)] pub x: FpVar, #[doc(hidden)] @@ -36,7 +41,10 @@ pub struct G1PreparedVar { pub y_twist: Fp3Var, } -impl G1PreparedVar

{ +impl G1PreparedVar

+where + P::Fp: FieldWithVar>, +{ /// Returns the value assigned to `self` in the underlying constraint /// system. pub fn value(&self) -> Result, SynthesisError> { @@ -69,7 +77,10 @@ impl G1PreparedVar

{ } } -impl AllocVar, P::Fp> for G1PreparedVar

{ +impl AllocVar, P::Fp> for G1PreparedVar

+where + P::Fp: FieldWithVar>, +{ #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( cs: impl Into>, @@ -81,8 +92,16 @@ impl AllocVar, P::Fp> for G1PreparedVar

{ let g1_prep = f().map(|b| *b.borrow()); - let x = FpVar::new_variable(ark_relations::ns!(cs, "x"), || g1_prep.map(|g| g.x), mode)?; - let y = FpVar::new_variable(ark_relations::ns!(cs, "y"), || g1_prep.map(|g| g.y), mode)?; + let x = FpVar::::new_variable( + ark_relations::ns!(cs, "x"), + || g1_prep.map(|g| g.x), + mode, + )?; + let y = FpVar::::new_variable( + ark_relations::ns!(cs, "y"), + || g1_prep.map(|g| g.y), + mode, + )?; let x_twist = Fp3Var::new_variable( ark_relations::ns!(cs, "x_twist"), || g1_prep.map(|g| g.x_twist), @@ -102,7 +121,10 @@ impl AllocVar, P::Fp> for G1PreparedVar

{ } } -impl ToBytesGadget for G1PreparedVar

{ +impl ToBytesGadget for G1PreparedVar

+where + P::Fp: FieldWithVar>, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -136,8 +158,14 @@ type Fp3G

= Fp3Var<

::Fp3Params>; /// Represents the cached precomputation that can be performed on a G2 element /// which enables speeding up pairing computation. #[derive(Derivative)] -#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))] -pub struct G2PreparedVar { +#[derivative( + Clone(bound = "P: MNT6Parameters, P::Fp: FieldWithVar>"), + Debug(bound = "P: MNT6Parameters, P::Fp: FieldWithVar>") +)] +pub struct G2PreparedVar +where + P::Fp: FieldWithVar>, +{ #[doc(hidden)] pub x: Fp3Var, #[doc(hidden)] @@ -152,7 +180,10 @@ pub struct G2PreparedVar { pub addition_coefficients: Vec>, } -impl AllocVar, P::Fp> for G2PreparedVar

{ +impl AllocVar, P::Fp> for G2PreparedVar

+where + P::Fp: FieldWithVar>, +{ #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( cs: impl Into>, @@ -198,7 +229,10 @@ impl AllocVar, P::Fp> for G2PreparedVar

{ } } -impl ToBytesGadget for G2PreparedVar

{ +impl ToBytesGadget for G2PreparedVar

+where + P::Fp: FieldWithVar>, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -241,7 +275,10 @@ impl ToBytesGadget for G2PreparedVar

{ } } -impl G2PreparedVar

{ +impl G2PreparedVar

+where + P::Fp: FieldWithVar>, +{ /// Returns the value assigned to `self` in the underlying constraint /// system. pub fn value(&self) -> Result, SynthesisError> { @@ -304,12 +341,12 @@ impl G2PreparedVar

{ } for bit in v.iter().rev() { - let (r2, coeff) = PairingVar::

::doubling_step_for_flipped_miller_loop(&r)?; + let (r2, coeff) = MNT6Gadget::

::doubling_step_for_flipped_miller_loop(&r)?; g2p.double_coefficients.push(coeff); r = r2; if *bit { - let (r2, coeff) = PairingVar::

::mixed_addition_step_for_flipped_miller_loop( + let (r2, coeff) = MNT6Gadget::

::mixed_addition_step_for_flipped_miller_loop( &q.x, &q.y, &r, )?; g2p.addition_coefficients.push(coeff); @@ -328,7 +365,7 @@ impl G2PreparedVar

{ let minus_r_affine_x = &r.x * &rz2_inv; let minus_r_affine_y = r.y.negate()? * &rz3_inv; - let add_result = PairingVar::

::mixed_addition_step_for_flipped_miller_loop( + let add_result = MNT6Gadget::

::mixed_addition_step_for_flipped_miller_loop( &minus_r_affine_x, &minus_r_affine_y, &r, @@ -342,15 +379,24 @@ impl G2PreparedVar

{ #[doc(hidden)] #[derive(Derivative)] -#[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))] -pub struct AteDoubleCoefficientsVar { +#[derivative( + Clone(bound = "P: MNT6Parameters, P::Fp: FieldWithVar>"), + Debug(bound = "P: MNT6Parameters, P::Fp: FieldWithVar>") +)] +pub struct AteDoubleCoefficientsVar +where + P::Fp: FieldWithVar>, +{ pub c_h: Fp3Var, pub c_4c: Fp3Var, pub c_j: Fp3Var, pub c_l: Fp3Var, } -impl AllocVar, P::Fp> for AteDoubleCoefficientsVar

{ +impl AllocVar, P::Fp> for AteDoubleCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( cs: impl Into>, @@ -377,7 +423,10 @@ impl AllocVar, P::Fp> for AteDoubleC } } -impl ToBytesGadget for AteDoubleCoefficientsVar

{ +impl ToBytesGadget for AteDoubleCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -406,7 +455,10 @@ impl ToBytesGadget for AteDoubleCoefficientsVar

{ } } -impl AteDoubleCoefficientsVar

{ +impl AteDoubleCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ /// Returns the value assigned to `self` in the underlying constraint /// system. pub fn value(&self) -> Result, SynthesisError> { @@ -426,13 +478,18 @@ impl AteDoubleCoefficientsVar

{ #[doc(hidden)] #[derive(Derivative)] #[derivative(Clone(bound = "P: MNT6Parameters"), Debug(bound = "P: MNT6Parameters"))] -pub struct AteAdditionCoefficientsVar { +pub struct AteAdditionCoefficientsVar +where + P::Fp: FieldWithVar>, +{ pub c_l1: Fp3Var, pub c_rz: Fp3Var, } impl AllocVar, P::Fp> for AteAdditionCoefficientsVar

+where + P::Fp: FieldWithVar>, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( @@ -454,7 +511,10 @@ impl AllocVar, P::Fp> } } -impl ToBytesGadget for AteAdditionCoefficientsVar

{ +impl ToBytesGadget for AteAdditionCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ #[inline] #[tracing::instrument(target = "r1cs")] fn to_bytes(&self) -> Result>, SynthesisError> { @@ -475,7 +535,10 @@ impl ToBytesGadget for AteAdditionCoefficientsVar

{ } } -impl AteAdditionCoefficientsVar

{ +impl AteAdditionCoefficientsVar

+where + P::Fp: FieldWithVar>, +{ /// Returns the value assigned to `self` in the underlying constraint /// system. pub fn value(&self) -> Result, SynthesisError> { @@ -486,7 +549,10 @@ impl AteAdditionCoefficientsVar

{ } #[doc(hidden)] -pub struct G2ProjectiveExtendedVar { +pub struct G2ProjectiveExtendedVar +where + P::Fp: FieldWithVar>, +{ pub x: Fp3Var, pub y: Fp3Var, pub z: Fp3Var, diff --git a/src/groups/curves/short_weierstrass/mod.rs b/src/groups/curves/short_weierstrass/mod.rs index 7c315256..5b8e4dd2 100644 --- a/src/groups/curves/short_weierstrass/mod.rs +++ b/src/groups/curves/short_weierstrass/mod.rs @@ -1,32 +1,37 @@ use ark_ec::{ short_weierstrass_jacobian::{GroupAffine as SWAffine, GroupProjective as SWProjective}, - AffineCurve, ProjectiveCurve, SWModelParameters, ModelParameters + AffineCurve, ModelParameters, ProjectiveCurve, SWModelParameters, }; use ark_ff::{BigInteger, BitIteratorBE, Field, One, PrimeField, Zero}; use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; use core::{borrow::Borrow, marker::PhantomData}; use non_zero_affine::NonZeroAffineVar; -use crate::{fields::{FieldExt, fp::FpVar}, prelude::*, ToConstraintFieldGadget, Vec}; +use crate::{ + fields::{fp::FpVar, FieldWithVar}, + prelude::*, + ToConstraintFieldGadget, Vec, +}; /// This module provides a generic implementation of G1 and G2 for /// the [\[BLS12]\]() family of bilinear groups. -// pub mod bls12; +pub mod bls12; /// This module provides a generic implementation of G1 and G2 for /// the [\[MNT4]\]() /// family of bilinear groups. -// pub mod mnt4; +pub mod mnt4; + /// This module provides a generic implementation of G1 and G2 for /// the [\[MNT6]\]() /// family of bilinear groups. -// pub mod mnt6; +pub mod mnt6; mod non_zero_affine; type BF

=

::BaseField; type CF

= as Field>::BasePrimeField; -type BFVar

= as FieldExt>::Var; +type BFVar

= as FieldWithVar>::Var; /// An implementation of arithmetic for Short Weierstrass curves that relies on /// the complete formulae derived in the paper of @@ -34,12 +39,12 @@ type BFVar

= as FieldExt>::Var; #[derive(Derivative)] #[derivative( Debug(bound = "P: SWModelParameters"), - Clone(bound = "P: SWModelParameters"), + Clone(bound = "P: SWModelParameters") )] #[must_use] -pub struct ProjectiveVar -where - BF

: FieldExt +pub struct ProjectiveVar +where + BF

: FieldWithVar, { /// The x-coordinate. pub x: BFVar

, @@ -53,11 +58,14 @@ where /// An affine representation of a curve point. #[derive(Derivative)] -#[derivative(Debug, Clone)] +#[derivative( + Debug(bound = "P: SWModelParameters, BF

: FieldWithVar"), + Clone(bound = "P: SWModelParameters, BF

: FieldWithVar") +)] #[must_use] -pub struct AffineVar +pub struct AffineVar where - BF

: FieldExt + BF

: FieldWithVar, { /// The x-coordinate. pub x: BFVar

, @@ -71,8 +79,7 @@ where impl AffineVar

where - BF

: FieldExt, - for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, + BF

: FieldWithVar, { fn new(x: BFVar

, y: BFVar

, infinity: Boolean>) -> Self { Self { @@ -96,14 +103,11 @@ where impl

ToConstraintFieldGadget> for AffineVar

where - BF

: FieldExt, + BF

: FieldWithVar, P: SWModelParameters, - for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, BFVar

: ToConstraintFieldGadget>, { - fn to_constraint_field( - &self, - ) -> Result>>, SynthesisError> { + fn to_constraint_field(&self) -> Result>>, SynthesisError> { let mut res = Vec::>>::new(); res.extend_from_slice(&self.x.to_constraint_field()?); @@ -117,8 +121,7 @@ where impl

R1CSVar> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, - for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, + BF

: FieldWithVar, { type Value = SWProjective

; @@ -137,10 +140,9 @@ where } } -impl ProjectiveVar

+impl ProjectiveVar

where - BF

: FieldExt, - for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, + BF

: FieldWithVar, { /// Constructs `Self` from an `(x, y, z)` coordinate triple. pub fn new(x: BFVar

, y: BFVar

, z: BFVar

) -> Self { @@ -152,6 +154,10 @@ where } } + fn is_zero(&self) -> Result>, SynthesisError> { + self.z.is_zero() + } + /// Convert this point into affine form. #[tracing::instrument(target = "r1cs")] pub fn to_affine(&self) -> Result, SynthesisError> { @@ -178,8 +184,8 @@ where // Thus, `z_inv * self.z = !self.is_zero()`. z_inv.mul_equals(&self.z, &BFVar::

::from(infinity.not()))?; - let non_zero_x = &self.x * &z_inv; - let non_zero_y = &self.y * &z_inv; + let non_zero_x = z_inv.clone() * &self.x; + let non_zero_y = z_inv * &self.y; let x = infinity.select(&zero_x, &non_zero_x)?; let y = infinity.select(&zero_y, &non_zero_y)?; @@ -226,7 +232,13 @@ where Ok(Self::new(x, y, z)) } +} +impl ProjectiveVar

+where + BF

: FieldWithVar, + for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, +{ /// Mixed addition, which is useful when `other = (x2, y2)` is known to have z = 1. #[tracing::instrument(target = "r1cs", skip(self, other))] pub(crate) fn add_mixed(&self, other: &NonZeroAffineVar

) -> Result { @@ -358,7 +370,7 @@ where impl

CurveVar, CF

> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { fn constant(g: SWProjective

) -> Self { @@ -553,13 +565,11 @@ where impl

ToConstraintFieldGadget> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, - for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, + BF

: FieldWithVar, BFVar

: ToConstraintFieldGadget>, + for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { - fn to_constraint_field( - &self, - ) -> Result>>, SynthesisError> { + fn to_constraint_field(&self) -> Result>>, SynthesisError> { self.to_affine()?.to_constraint_field() } } @@ -567,7 +577,7 @@ where fn mul_by_coeff_a(f: &BFVar

) -> BFVar

where for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, - BF

: FieldExt, + BF

: FieldWithVar, { if !P::COEFF_A.is_zero() { f * P::COEFF_A @@ -583,28 +593,31 @@ impl_bounded_ops!( add, AddAssign, add_assign, - |mut this: &'a ProjectiveVar

, mut other: &'a ProjectiveVar

| { + |this: &mut ProjectiveVar

, other: &'a ProjectiveVar

| { // Implement complete addition for Short Weierstrass curves, following // the complete addition formula from Renes-Costello-Batina 2015 // (https://eprint.iacr.org/2015/1060). // // We special case handling of constants to get better constraint weight. if this.is_constant() { - // we'll just act like `other` is constant. - core::mem::swap(&mut this, &mut other); + // The value should exist because `other` is a constant. + let this_val = this.value().unwrap(); + if !this_val.is_zero() { + // We'll use mixed addition to add non-zero constants. + let x = BFVar::

::constant(this_val.x); + let y = BFVar::

::constant(this_val.y); + *this = other.add_mixed(&NonZeroAffineVar::new(x, y)).unwrap() + } } if other.is_constant() { // The value should exist because `other` is a constant. let other = other.value().unwrap(); - if other.is_zero() { - // this + 0 = this - this.clone() - } else { + if !other.is_zero() { // We'll use mixed addition to add non-zero constants. let x = BFVar::

::constant(other.x); let y = BFVar::

::constant(other.y); - this.add_mixed(&NonZeroAffineVar::new(x, y)).unwrap() + *this = this.add_mixed(&NonZeroAffineVar::new(x, y)).unwrap() } } else { // Complete addition formula from Renes-Costello-Batina 2015 @@ -639,20 +652,18 @@ impl_bounded_ops!( let bxz3 = &xz_pairs * three_b; // 28 let b3_xz_pairs = mul_by_coeff_a::

(&(&xx - &azz)) + &bxz3; // 30, 31, 32 - let x = (&yy_m_bzz3 * &xy_pairs) - &yz_pairs * &b3_xz_pairs; // 35, 39, 40 - let y = (&yy_p_bzz3 * &yy_m_bzz3) + &xx3_p_azz * b3_xz_pairs; // 24, 36, 37, 38 - let z = (&yy_p_bzz3 * &yz_pairs) + xy_pairs * xx3_p_azz; // 41, 42, 43 - - ProjectiveVar::new(x, y, z) + this.x = (&yy_m_bzz3 * &xy_pairs) - &yz_pairs * &b3_xz_pairs; // 35, 39, 40 + this.y = (&yy_p_bzz3 * &yy_m_bzz3) + &xx3_p_azz * b3_xz_pairs; // 24, 36, 37, 38 + this.z = (yy_p_bzz3 * &yz_pairs) + xy_pairs * xx3_p_azz; // 41, 42, 43 } }, - |this: &'a ProjectiveVar

, other: SWProjective

| { - this + ProjectiveVar::constant(other) + |this: &mut ProjectiveVar

, other: SWProjective

| { + *this = &*this + ProjectiveVar::constant(other) }, (P: SWModelParameters), for <'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

>, - BF

: FieldExt, + BF

: FieldWithVar, ); impl_bounded_ops!( @@ -662,17 +673,17 @@ impl_bounded_ops!( sub, SubAssign, sub_assign, - |this: &'a ProjectiveVar

, other: &'a ProjectiveVar

| this + other.negate().unwrap(), - |this: &'a ProjectiveVar

, other: SWProjective

| this - ProjectiveVar::constant(other), + |this: &mut ProjectiveVar

, other: &'a ProjectiveVar

| *this += other.negate().unwrap(), + |this: &mut ProjectiveVar

, other: SWProjective

| *this = &*this - ProjectiveVar::constant(other), (P: SWModelParameters), for <'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

>, - BF

: FieldExt, + BF

: FieldWithVar, ); impl<'a, P> GroupOpsBounds<'a, SWProjective

, ProjectiveVar

> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, for<'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

>, { } @@ -680,7 +691,7 @@ where impl<'a, P> GroupOpsBounds<'a, SWProjective

, ProjectiveVar

> for &'a ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, for<'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

>, { } @@ -688,7 +699,7 @@ where impl

CondSelectGadget> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { #[inline] @@ -709,14 +720,11 @@ where impl

EqGadget> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { #[tracing::instrument(target = "r1cs")] - fn is_eq( - &self, - other: &Self, - ) -> Result>, 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 +766,7 @@ where impl

AllocVar, CF

> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { fn new_variable>>( @@ -770,11 +778,10 @@ where } } -impl

AllocVar, CF

> - for ProjectiveVar

+impl

AllocVar, CF

> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { fn new_variable>>( @@ -885,13 +892,11 @@ fn div2(limbs: &mut [u64]) { impl

ToBitsGadget> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { #[tracing::instrument(target = "r1cs")] - fn to_bits_le( - &self, - ) -> Result>>, 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()?; @@ -901,9 +906,7 @@ where } #[tracing::instrument(target = "r1cs")] - fn to_non_unique_bits_le( - &self, - ) -> Result>>, 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()?; @@ -916,13 +919,11 @@ where impl

ToBytesGadget> for ProjectiveVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { #[tracing::instrument(target = "r1cs")] - fn to_bytes( - &self, - ) -> Result>>, 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()?; @@ -933,9 +934,7 @@ where } #[tracing::instrument(target = "r1cs")] - fn to_non_unique_bytes( - &self, - ) -> Result>>, 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 b25876d9..c9283a8a 100644 --- a/src/groups/curves/short_weierstrass/non_zero_affine.rs +++ b/src/groups/curves/short_weierstrass/non_zero_affine.rs @@ -5,13 +5,12 @@ use super::*; #[derive(Derivative)] #[derivative( Debug(bound = "P: SWModelParameters"), - Clone(bound = "P: SWModelParameters"), + Clone(bound = "P: SWModelParameters") )] #[must_use] pub struct NonZeroAffineVar - where - BF

: FieldExt, - for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, +where + BF

: FieldWithVar, { /// The x-coordinate. pub x: BFVar

, @@ -24,9 +23,8 @@ pub struct NonZeroAffineVar impl

NonZeroAffineVar

where P: SWModelParameters, - BF

: FieldExt, + BF

: FieldWithVar, BFVar

: FieldVar>, - for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { pub(crate) fn new(x: BFVar

, y: BFVar

) -> Self { Self { @@ -41,14 +39,25 @@ where pub(crate) fn into_projective(&self) -> ProjectiveVar

{ ProjectiveVar::new(self.x.clone(), self.y.clone(), BFVar::

::one()) } +} +impl

NonZeroAffineVar

+where + P: SWModelParameters, + BF

: FieldWithVar, + BFVar

: FieldVar>, + for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, +{ /// Performs an addition without checking that other != ±self. #[tracing::instrument(target = "r1cs", skip(self, other))] pub(crate) fn add_unchecked(&self, other: &Self) -> Result { if [self, other].is_constant() { let result = (self.value()?.into_projective() + other.value()?.into_projective()).into_affine(); - Ok(Self::new(BFVar::

::constant(result.x), BFVar::

::constant(result.y))) + Ok(Self::new( + BFVar::

::constant(result.x), + BFVar::

::constant(result.y), + )) } else { let (x1, y1) = (&self.x, &self.y); let (x2, y2) = (&other.x, &other.y); @@ -75,7 +84,10 @@ where let result = self.value()?.into_projective().double().into_affine(); // Panic if the result is zero. assert!(!result.is_zero()); - Ok(Self::new(BFVar::

::constant(result.x), BFVar::

::constant(result.y))) + Ok(Self::new( + BFVar::

::constant(result.x), + BFVar::

::constant(result.y), + )) } else { let (x1, y1) = (&self.x, &self.y); let x1_sqr = x1.square()?; @@ -138,8 +150,7 @@ where impl

R1CSVar> for NonZeroAffineVar

where P: SWModelParameters, - BF

: FieldExt, - for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, + BF

: FieldWithVar, { type Value = SWAffine

; @@ -155,8 +166,7 @@ where impl

CondSelectGadget> for NonZeroAffineVar

where P: SWModelParameters, - BF

: FieldExt, - for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, + BF

: FieldWithVar, { #[inline] #[tracing::instrument(target = "r1cs")] diff --git a/src/groups/curves/twisted_edwards/mod.rs b/src/groups/curves/twisted_edwards/mod.rs index aed8f825..6614c25f 100644 --- a/src/groups/curves/twisted_edwards/mod.rs +++ b/src/groups/curves/twisted_edwards/mod.rs @@ -1,16 +1,18 @@ use ark_ec::{ twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective}, - AffineCurve, MontgomeryModelParameters, ProjectiveCurve, TEModelParameters, + AffineCurve, ModelParameters, MontgomeryModelParameters, ProjectiveCurve, TEModelParameters, }; use ark_ff::{BigInteger, BitIteratorBE, Field, One, PrimeField, Zero}; use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; -use crate::{prelude::*, ToConstraintFieldGadget, Vec}; +use crate::{fields::FieldWithVar, prelude::*, ToConstraintFieldGadget, Vec}; use crate::fields::fp::FpVar; use core::{borrow::Borrow, marker::PhantomData}; +type BFVar

= <

::BaseField as FieldWithVar>::Var; + /// 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). @@ -18,18 +20,19 @@ use core::{borrow::Borrow, marker::PhantomData}; /// This is intended for use primarily for implementing efficient /// multi-scalar-multiplication in the Bowe-Hopwood-Pedersen hash. #[derive(Derivative)] -#[derivative(Debug, Clone)] +#[derivative( + Debug(bound = "P: TEModelParameters, P::BaseField: FieldWithVar"), + Clone(bound = "P: TEModelParameters, P::BaseField: FieldWithVar") +)] #[must_use] -pub struct MontgomeryAffineVar< - P: TEModelParameters, - F: FieldVar::BasePrimeField>, -> where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, +pub struct MontgomeryAffineVar +where + P::BaseField: FieldWithVar, { /// The x-coordinate. - pub x: F, + pub x: BFVar

, /// The y-coordinate. - pub y: F, + pub y: BFVar

, #[derivative(Debug = "ignore")] _params: PhantomData

, } @@ -40,11 +43,10 @@ mod montgomery_affine_impl { use ark_ff::Field; use core::ops::Add; - impl R1CSVar<::BasePrimeField> for MontgomeryAffineVar + impl

R1CSVar<::BasePrimeField> for MontgomeryAffineVar

where + P::BaseField: FieldWithVar, P: TEModelParameters, - F: FieldVar::BasePrimeField>, - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, { type Value = (P::BaseField, P::BaseField); @@ -59,15 +61,12 @@ mod montgomery_affine_impl { } } - impl< - P: TEModelParameters, - F: FieldVar::BasePrimeField>, - > MontgomeryAffineVar + impl MontgomeryAffineVar

where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, + P::BaseField: FieldWithVar, { /// Constructs `Self` from an `(x, y)` coordinate pair. - pub fn new(x: F, y: F) -> Self { + pub fn new(x: BFVar

, y: BFVar

) -> Self { Self { x, y, @@ -103,14 +102,22 @@ mod montgomery_affine_impl { p: &TEAffine

, ) -> Result { let montgomery_coords = Self::from_edwards_to_coords(p)?; - let u = F::new_witness(ark_relations::ns!(cs, "u"), || Ok(montgomery_coords.0))?; - let v = F::new_witness(ark_relations::ns!(cs, "v"), || Ok(montgomery_coords.1))?; + let u = + BFVar::

::new_witness(ark_relations::ns!(cs, "u"), || Ok(montgomery_coords.0))?; + let v = + BFVar::

::new_witness(ark_relations::ns!(cs, "v"), || Ok(montgomery_coords.1))?; Ok(Self::new(u, v)) } + } + impl MontgomeryAffineVar

+ where + P::BaseField: FieldWithVar, + for<'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

>, + { /// Converts `self` into a Twisted Edwards curve point variable. #[tracing::instrument(target = "r1cs")] - pub fn into_edwards(&self) -> Result, SynthesisError> { + pub fn into_edwards(&self) -> Result, SynthesisError> { let cs = self.cs(); let mode = if cs.is_none() { @@ -120,7 +127,7 @@ mod montgomery_affine_impl { }; // Compute u = x / y - let u = F::new_variable( + let u = BFVar::

::new_variable( ark_relations::ns!(cs, "u"), || { let y_inv = self @@ -135,7 +142,7 @@ mod montgomery_affine_impl { u.mul_equals(&self.y, &self.x)?; - let v = F::new_variable( + let v = BFVar::

::new_variable( ark_relations::ns!(cs, "v"), || { let mut t0 = self.x.value()?; @@ -156,13 +163,13 @@ mod montgomery_affine_impl { } } - impl<'a, P, F> Add<&'a MontgomeryAffineVar> for MontgomeryAffineVar + impl<'a, P> Add<&'a MontgomeryAffineVar

> for MontgomeryAffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField>, - for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, + P::BaseField: FieldWithVar, + for<'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

>, { - type Output = MontgomeryAffineVar; + type Output = MontgomeryAffineVar

; #[tracing::instrument(target = "r1cs")] fn add(self, other: &'a Self) -> Self::Output { @@ -176,7 +183,7 @@ mod montgomery_affine_impl { let coeff_b = P::MontgomeryModelParameters::COEFF_B; let coeff_a = P::MontgomeryModelParameters::COEFF_A; - let lambda = F::new_variable( + let lambda = BFVar::

::new_variable( ark_relations::ns!(cs, "lambda"), || { let n = other.y.value()? - &self.y.value()?; @@ -191,7 +198,7 @@ mod montgomery_affine_impl { lambda_d.mul_equals(&lambda, &lambda_n).unwrap(); // Compute x'' = B*lambda^2 - A - x - x' - let xprime = F::new_variable( + let xprime = BFVar::

::new_variable( ark_relations::ns!(cs, "xprime"), || { Ok(lambda.value()?.square() * &coeff_b @@ -208,7 +215,7 @@ mod montgomery_affine_impl { let lambda_b = &lambda * coeff_b; lambda_b.mul_equals(&lambda, &xprime_lc).unwrap(); - let yprime = F::new_variable( + let yprime = BFVar::

::new_variable( ark_relations::ns!(cs, "yprime"), || { Ok(-(self.y.value()? @@ -230,29 +237,29 @@ mod montgomery_affine_impl { /// the complete formulae for the affine model, as outlined in the /// [EFD](https://www.hyperelliptic.org/EFD/g1p/auto-twisted.html). #[derive(Derivative)] -#[derivative(Debug, Clone)] +#[derivative( + Debug(bound = "P: TEModelParameters, P::BaseField: FieldWithVar"), + Clone(bound = "P: TEModelParameters, P::BaseField: FieldWithVar") +)] #[must_use] -pub struct AffineVar< - P: TEModelParameters, - F: FieldVar::BasePrimeField>, -> where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, +pub struct AffineVar +where + P::BaseField: FieldWithVar, { /// The x-coordinate. - pub x: F, + pub x: BFVar

, /// The y-coordinate. - pub y: F, + pub y: BFVar

, #[derivative(Debug = "ignore")] _params: PhantomData

, } -impl::BasePrimeField>> - AffineVar +impl AffineVar

where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, + P::BaseField: FieldWithVar, { /// Constructs `Self` from an `(x, y)` coordinate triple. - pub fn new(x: F, y: F) -> Self { + pub fn new(x: BFVar

, y: BFVar

) -> Self { Self { x, y, @@ -283,24 +290,23 @@ where ), }; - let x = F::new_variable(ark_relations::ns!(cs, "x"), || x, mode)?; - let y = F::new_variable(ark_relations::ns!(cs, "y"), || y, mode)?; + let x = BFVar::

::new_variable(ark_relations::ns!(cs, "x"), || x, mode)?; + let y = BFVar::

::new_variable(ark_relations::ns!(cs, "y"), || y, mode)?; Ok(Self::new(x, y)) } } -impl::BasePrimeField>> - AffineVar +impl AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField> + P::BaseField: FieldWithVar, + BFVar

: TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField> + ThreeBitCondNegLookupGadget< ::BasePrimeField, TableConstant = P::BaseField, >, - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, + for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { /// Compute a scalar multiplication of `bases` with respect to `scalars`, /// where the elements of `scalars` are length-three slices of bits, and @@ -316,10 +322,10 @@ where J: Borrow<[Boolean<::BasePrimeField>]>, { const CHUNK_SIZE: usize = 3; - let mut ed_result: Option> = None; - let mut result: Option> = None; + let mut ed_result: Option> = None; + let mut result: Option> = None; - let mut process_segment_result = |result: &MontgomeryAffineVar| { + let mut process_segment_result = |result: &MontgomeryAffineVar

| { let sgmt_result = result.into_edwards()?; ed_result = match ed_result.as_ref() { None => Some(sgmt_result), @@ -358,14 +364,14 @@ where let precomp = bits[0].and(&bits[1])?; - let x = F::zero() + let x = BFVar::

::zero() + x_coeffs[0] - + F::from(bits[0].clone()) * (x_coeffs[1] - &x_coeffs[0]) - + F::from(bits[1].clone()) * (x_coeffs[2] - &x_coeffs[0]) - + F::from(precomp.clone()) + + BFVar::

::from(bits[0].clone()) * (x_coeffs[1] - &x_coeffs[0]) + + BFVar::

::from(bits[1].clone()) * (x_coeffs[2] - &x_coeffs[0]) + + BFVar::

::from(precomp.clone()) * (x_coeffs[3] - &x_coeffs[2] - &x_coeffs[1] + &x_coeffs[0]); - let y = F::three_bit_cond_neg_lookup(&bits, &precomp, &y_coeffs)?; + let y = BFVar::

::three_bit_cond_neg_lookup(&bits, &precomp, &y_coeffs)?; let tmp = MontgomeryAffineVar::new(x, y); result = match result.as_ref() { @@ -384,11 +390,10 @@ where } } -impl R1CSVar<::BasePrimeField> for AffineVar +impl

R1CSVar<::BasePrimeField> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField>, - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, + P::BaseField: FieldWithVar, { type Value = TEProjective

; @@ -404,12 +409,13 @@ where } } -impl CurveVar, ::BasePrimeField> for AffineVar +impl

CurveVar, ::BasePrimeField> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, + P::BaseField: FieldWithVar, + BFVar

: + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { fn constant(g: TEProjective

) -> Self { let cs = ConstraintSystemRef::None; @@ -417,7 +423,7 @@ where } fn zero() -> Self { - Self::new(F::zero(), F::one()) + Self::new(BFVar::

::zero(), BFVar::

::one()) } fn is_zero(&self) -> Result::BasePrimeField>, SynthesisError> { @@ -490,7 +496,7 @@ where let a_x2 = &x2 * a; // Compute x3 = (2xy) / (ax^2 + y^2) - let x3 = F::new_witness(ark_relations::ns!(cs, "x3"), || { + let x3 = BFVar::

::new_witness(ark_relations::ns!(cs, "x3"), || { let t0 = xy.value()?.double(); let t1 = a * &x2.value()? + &y2.value()?; Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?) @@ -502,7 +508,7 @@ where // Compute y3 = (y^2 - ax^2) / (2 - ax^2 - y^2) let two = P::BaseField::one().double(); - let y3 = F::new_witness(ark_relations::ns!(cs, "y3"), || { + let y3 = BFVar::

::new_witness(ark_relations::ns!(cs, "y3"), || { let a_x2 = a * &x2.value()?; let t0 = y2.value()? - &a_x2; let t1 = two - &a_x2 - &y2.value()?; @@ -544,8 +550,8 @@ where let x_s = [zero.x, table[0].x, table[1].x, table[2].x]; let y_s = [zero.y, table[0].y, table[1].y, table[2].y]; - let x = F::two_bit_lookup(&bits, &x_s)?; - let y = F::two_bit_lookup(&bits, &y_s)?; + let x = BFVar::

::two_bit_lookup(&bits, &x_s)?; + let y = BFVar::

::two_bit_lookup(&bits, &y_s)?; *self += Self::new(x, y); } else if bits.len() == 1 { let bit = &bits[0]; @@ -558,12 +564,13 @@ where } } -impl AllocVar, ::BasePrimeField> for AffineVar +impl

AllocVar, ::BasePrimeField> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, + P::BaseField: FieldWithVar, + BFVar

: + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( @@ -659,12 +666,13 @@ where } } -impl AllocVar, ::BasePrimeField> for AffineVar +impl

AllocVar, ::BasePrimeField> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, + P::BaseField: FieldWithVar, + BFVar

: + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( @@ -676,12 +684,11 @@ where } } -impl ToConstraintFieldGadget<::BasePrimeField> for AffineVar +impl

ToConstraintFieldGadget<::BasePrimeField> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField>, - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, - F: ToConstraintFieldGadget<::BasePrimeField>, + P::BaseField: FieldWithVar, + BFVar

: ToConstraintFieldGadget<::BasePrimeField>, { fn to_constraint_field( &self, @@ -707,15 +714,14 @@ fn div2(limbs: &mut [u64]) { } impl_bounded_ops!( - AffineVar, + AffineVar

, TEProjective

, Add, add, AddAssign, add_assign, - |this: &'a AffineVar, other: &'a AffineVar| { - - if [this, other].is_constant() { + |this: &mut AffineVar

, other: &'a AffineVar

| { + *this = if [this, other].is_constant() { assert!(this.is_constant() && other.is_constant()); AffineVar::constant(this.value().unwrap() + &other.value().unwrap()) } else { @@ -739,7 +745,7 @@ impl_bounded_ops!( let v2 = &v0 * &v1 * d; // Compute x3 = (v0 + v1) / (1 + v2) - let x3 = F::new_witness(ark_relations::ns!(cs, "x3"), || { + let x3 = BFVar::

::new_witness(ark_relations::ns!(cs, "x3"), || { let t0 = v0.value()? + &v1.value()?; let t1 = P::BaseField::one() + &v2.value()?; Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?) @@ -750,7 +756,7 @@ impl_bounded_ops!( x3.mul_equals(&v2_plus_one, &v0_plus_v1).unwrap(); // Compute y3 = (U + a * v0 - v1) / (1 - v2) - let y3 = F::new_witness(ark_relations::ns!(cs, "y3"), || { + let y3 = BFVar::

::new_witness(ark_relations::ns!(cs, "y3"), || { let t0 = u.value()? + &(a * &v0.value()?) - &v1.value()?; let t1 = P::BaseField::one() - &v2.value()?; Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?) @@ -763,57 +769,58 @@ impl_bounded_ops!( y3.mul_equals(&one_minus_v2, &u_plus_a_v0_minus_v1).unwrap(); AffineVar::new(x3, y3) - } + }; }, - |this: &'a AffineVar, other: TEProjective

| this + AffineVar::constant(other), + |this: &mut AffineVar

, other: TEProjective

| *this = &*this + AffineVar::constant(other), ( - F :FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, P: TEModelParameters, ), - for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, + P::BaseField: FieldWithVar, + BFVar

: TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + for <'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

>, ); impl_bounded_ops!( - AffineVar, + AffineVar

, TEProjective

, Sub, sub, SubAssign, sub_assign, - |this: &'a AffineVar, other: &'a AffineVar| this + other.negate().unwrap(), - |this: &'a AffineVar, other: TEProjective

| this - AffineVar::constant(other), + |this: &mut AffineVar

, other: &'a AffineVar

| *this += other.negate().unwrap(), + |this: &mut AffineVar

, other: TEProjective

| *this = &*this - AffineVar::constant(other), ( - F :FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, P: TEModelParameters, ), - for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F> + P::BaseField: FieldWithVar, + BFVar

: TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + for <'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

> ); -impl<'a, P, F> GroupOpsBounds<'a, TEProjective

, AffineVar> for AffineVar +impl<'a, P> GroupOpsBounds<'a, TEProjective

, AffineVar

> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, - for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, + P::BaseField: FieldWithVar, + BFVar

: + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + for<'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

>, { } -impl<'a, P, F> GroupOpsBounds<'a, TEProjective

, AffineVar> for &'a AffineVar +impl<'a, P> GroupOpsBounds<'a, TEProjective

, AffineVar

> for &'a AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField> - + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, - for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, + P::BaseField: FieldWithVar, + BFVar

: + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + for<'b> &'b BFVar

: FieldOpsBounds<'b, P::BaseField, BFVar

>, { } -impl CondSelectGadget<::BasePrimeField> for AffineVar +impl

CondSelectGadget<::BasePrimeField> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField>, - for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, + P::BaseField: FieldWithVar, { #[inline] #[tracing::instrument(target = "r1cs")] @@ -829,11 +836,10 @@ where } } -impl EqGadget<::BasePrimeField> for AffineVar +impl

EqGadget<::BasePrimeField> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField>, - for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, + P::BaseField: FieldWithVar, { #[tracing::instrument(target = "r1cs")] fn is_eq( @@ -870,11 +876,10 @@ where } } -impl ToBitsGadget<::BasePrimeField> for AffineVar +impl

ToBitsGadget<::BasePrimeField> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField>, - for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, + P::BaseField: FieldWithVar, { #[tracing::instrument(target = "r1cs")] fn to_bits_le( @@ -898,11 +903,10 @@ where } } -impl ToBytesGadget<::BasePrimeField> for AffineVar +impl

ToBytesGadget<::BasePrimeField> for AffineVar

where P: TEModelParameters, - F: FieldVar::BasePrimeField>, - for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>, + P::BaseField: FieldWithVar, { #[tracing::instrument(target = "r1cs")] fn to_bytes( diff --git a/src/groups/mod.rs b/src/groups/mod.rs index 881c5663..e7e0b6fe 100644 --- a/src/groups/mod.rs +++ b/src/groups/mod.rs @@ -23,6 +23,10 @@ pub trait GroupOpsBounds<'a, F, T: 'a>: { } +pub trait CurveWithVar: ProjectiveCurve { + type Var: CurveVar; +} + /// A variable that represents a curve point for /// the curve `C`. pub trait CurveVar: