arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/r1cs-std/src/groups/curves/short_weierstrass/mod.rs
r1cs-std/src/groups/curves/short_weierstrass/mod.rsRaw
  1use algebra::{
  2    curves::{
  3        short_weierstrass_jacobian::{GroupAffine as SWAffine, GroupProjective as SWProjective},
  4        SWModelParameters,
  5    },
  6    AffineCurve, BigInteger, BitIterator, Field, One, PrimeField, ProjectiveCurve, Zero,
  7};
  8use core::{borrow::Borrow, marker::PhantomData};
  9use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError};
 10
 11use crate::{prelude::*, Vec};
 12
 13pub mod bls12;
 14pub mod mnt4;
 15pub mod mnt6;
 16
 17/// An implementation of arithmetic for Short Weierstrass curves that relies on
 18/// the complete formulae derived in the paper of
 19/// [[Renes, Costello, Batina 2015]](https://eprint.iacr.org/2015/1060).
 20#[derive(Derivative)]
 21#[derivative(Debug, Clone)]
 22#[must_use]
 23pub struct ProjectiveVar<
 24    P: SWModelParameters,
 25    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 26> where
 27    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 28{
 29    /// The x-coordinate.
 30    pub x: F,
 31    /// The y-coordinate.
 32    pub y: F,
 33    /// The z-coordinate.
 34    pub z: F,
 35    #[derivative(Debug = "ignore")]
 36    _params: PhantomData<P>,
 37}
 38
 39/// An affine representation of a curve point.
 40#[derive(Derivative)]
 41#[derivative(Debug, Clone)]
 42#[must_use]
 43pub struct AffineVar<
 44    P: SWModelParameters,
 45    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 46> where
 47    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 48{
 49    /// The x-coordinate.
 50    pub x: F,
 51    /// The y-coordinate.
 52    pub y: F,
 53    /// Is `self` the point at infinity.
 54    pub infinity: Boolean<<P::BaseField as Field>::BasePrimeField>,
 55    #[derivative(Debug = "ignore")]
 56    _params: PhantomData<P>,
 57}
 58
 59impl<P, F> AffineVar<P, F>
 60where
 61    P: SWModelParameters,
 62    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 63    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 64{
 65    fn new(x: F, y: F, infinity: Boolean<<P::BaseField as Field>::BasePrimeField>) -> Self {
 66        Self {
 67            x,
 68            y,
 69            infinity,
 70            _params: PhantomData,
 71        }
 72    }
 73
 74    pub fn value(&self) -> Result<SWAffine<P>, SynthesisError> {
 75        Ok(SWAffine::new(
 76            self.x.value()?,
 77            self.y.value()?,
 78            self.infinity.value()?,
 79        ))
 80    }
 81}
 82
 83impl<P, F> R1CSVar<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
 84where
 85    P: SWModelParameters,
 86    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 87    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 88{
 89    type Value = SWProjective<P>;
 90
 91    fn cs(&self) -> Option<ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField>> {
 92        self.x.cs().or(self.y.cs()).or(self.z.cs())
 93    }
 94
 95    fn value(&self) -> Result<Self::Value, SynthesisError> {
 96        let (x, y, z) = (self.x.value()?, self.y.value()?, self.z.value()?);
 97        let result = if let Some(z_inv) = z.inverse() {
 98            SWAffine::new(x * &z_inv, y * &z_inv, false)
 99        } else {
100            SWAffine::zero()
101        };
102        Ok(result.into())
103    }
104}
105
106impl<P: SWModelParameters, F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>>
107    ProjectiveVar<P, F>
108where
109    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
110{
111    pub fn new(x: F, y: F, z: F) -> Self {
112        Self {
113            x,
114            y,
115            z,
116            _params: PhantomData,
117        }
118    }
119
120    /// Convert this point into affine form.
121    pub fn to_affine(&self) -> Result<AffineVar<P, F>, SynthesisError> {
122        let cs = self.cs().unwrap_or(ConstraintSystemRef::None);
123        let mode = if self.is_constant() {
124            AllocationMode::Constant
125        } else {
126            AllocationMode::Witness
127        };
128
129        let infinity = self.is_zero()?;
130        let zero_x = F::zero();
131        let zero_y = F::one();
132
133        let non_zero_x = F::new_variable(
134            cs.ns("non-zero x"),
135            || {
136                let z_inv = self.z.value()?.inverse().unwrap_or(P::BaseField::zero());
137                Ok(self.x.value()? * &z_inv)
138            },
139            mode,
140        )?;
141        let non_zero_y = F::new_variable(
142            cs.ns("non-zero y"),
143            || {
144                let z_inv = self.z.value()?.inverse().unwrap_or(P::BaseField::zero());
145                Ok(self.y.value()? * &z_inv)
146            },
147            mode,
148        )?;
149        let x = infinity.select(&zero_x, &non_zero_x)?;
150        let y = infinity.select(&zero_y, &non_zero_y)?;
151        Ok(AffineVar::new(x, y, infinity))
152    }
153
154    /// Allocates a new variable without performing an on-curve check, which is
155    /// useful if the variable is known to be on the curve (eg., if the point
156    /// is a constant or is a public input).
157    pub fn new_variable_omit_on_curve_check(
158        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
159        f: impl FnOnce() -> Result<SWProjective<P>, SynthesisError>,
160        mode: AllocationMode,
161    ) -> Result<Self, SynthesisError> {
162        let ns = cs.into();
163        let cs = ns.cs();
164
165        let (x, y, z) = match f() {
166            Ok(ge) => {
167                let ge = ge.into_affine();
168                if ge.is_zero() {
169                    (
170                        Ok(P::BaseField::zero()),
171                        Ok(P::BaseField::one()),
172                        Ok(P::BaseField::zero()),
173                    )
174                } else {
175                    (Ok(ge.x), Ok(ge.y), Ok(P::BaseField::one()))
176                }
177            }
178            _ => (
179                Err(SynthesisError::AssignmentMissing),
180                Err(SynthesisError::AssignmentMissing),
181                Err(SynthesisError::AssignmentMissing),
182            ),
183        };
184
185        let x = F::new_variable(cs.ns("x"), || x, mode)?;
186        let y = F::new_variable(cs.ns("y"), || y, mode)?;
187        let z = F::new_variable(cs.ns("z"), || z, mode)?;
188
189        Ok(Self::new(x, y, z))
190    }
191}
192
193impl<P, F> CurveVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>
194    for ProjectiveVar<P, F>
195where
196    P: SWModelParameters,
197    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
198    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
199{
200    fn constant(g: SWProjective<P>) -> Self {
201        let cs = ConstraintSystemRef::None;
202        Self::new_variable_omit_on_curve_check(cs, || Ok(g), AllocationMode::Constant).unwrap()
203    }
204
205    fn zero() -> Self {
206        Self::new(F::zero(), F::one(), F::zero())
207    }
208
209    fn is_zero(&self) -> Result<Boolean<<P::BaseField as Field>::BasePrimeField>, SynthesisError> {
210        self.z.is_zero()
211    }
212
213    fn new_variable_omit_prime_order_check(
214        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
215        f: impl FnOnce() -> Result<SWProjective<P>, SynthesisError>,
216        mode: AllocationMode,
217    ) -> Result<Self, SynthesisError> {
218        let ns = cs.into();
219        let cs = ns.cs();
220        // Curve equation in projective form:
221        // E: Y² * Z = X³ + aX * Z² + bZ³
222        //
223        // This can be re-written as
224        // E: Y² * Z - bZ³ = X³ + aX * Z²
225        // E: Z * (Y² - bZ²) = X * (X² + aZ²)
226        // so, compute X², Y², Z²,
227        //     compute temp = X * (X² + aZ²)
228        //     check Z.mul_equals((Y² - bZ²), temp)
229        //
230        //     A total of 5 multiplications
231
232        let g = Self::new_variable_omit_on_curve_check(cs, f, mode)?;
233
234        if mode != AllocationMode::Constant {
235            // Perform on-curve check.
236            let b = P::COEFF_B;
237            let a = P::COEFF_A;
238
239            let x2 = g.x.square()?;
240            let y2 = g.y.square()?;
241            let z2 = g.z.square()?;
242            let t = &g.x * (x2 + &z2 * a);
243
244            g.z.mul_equals(&(y2 - z2 * b), &t)?;
245        }
246        Ok(g)
247    }
248
249    /// Enforce that `self` is in the prime-order subgroup.
250    ///
251    /// Does so by multiplying by the prime order, and checking that the result
252    /// is unchanged.
253    // TODO: at the moment this doesn't work, because the addition and doubling
254    // formulae are incomplete for even-order points.
255    fn enforce_prime_order(&self) -> Result<(), SynthesisError> {
256        let r_minus_1 = (-P::ScalarField::one()).into_repr();
257
258        let mut seen_one = false;
259        let mut result = Self::zero();
260        for b in BitIterator::new(r_minus_1) {
261            let old_seen_one = seen_one;
262            if seen_one {
263                result.double_in_place()?;
264            } else {
265                seen_one = b;
266            }
267
268            if b {
269                result = if old_seen_one {
270                    result + self
271                } else {
272                    self.clone()
273                };
274            }
275        }
276        self.negate()?.enforce_equal(&result)?;
277        Ok(())
278    }
279
280    #[inline]
281    fn double_in_place(&mut self) -> Result<(), SynthesisError> {
282        // Complete doubling formula from Renes-Costello-Batina 2015
283        // Algorithm 3
284        // (https://eprint.iacr.org/2015/1060).
285        //
286        // Adapted from code in
287        // https://github.com/RustCrypto/elliptic-curves/blob/master/p256/src/arithmetic.rs
288        let three_b = P::COEFF_B.double() + &P::COEFF_B;
289
290        let xx = self.x.square()?; // 1
291        let yy = self.y.square()?; // 2
292        let zz = self.z.square()?; // 3
293        let xy2 = (&self.x * &self.y).double()?; // 4, 5
294        let xz2 = (&self.x * &self.z).double()?; // 6, 7
295
296        let axz2 = mul_by_coeff_a::<P, F>(&xz2); // 8
297
298        let bzz3_part = &axz2 + &zz * three_b; // 9, 10
299        let yy_m_bzz3 = &yy - &bzz3_part; // 11
300        let yy_p_bzz3 = &yy + &bzz3_part; // 12
301        let y_frag = yy_p_bzz3 * &yy_m_bzz3; // 13
302        let x_frag = yy_m_bzz3 * &xy2; // 14
303
304        let bxz3 = xz2 * three_b; // 15
305        let azz = mul_by_coeff_a::<P, F>(&zz); // 16
306        let b3_xz_pairs = mul_by_coeff_a::<P, F>(&(&xx - &azz)) + &bxz3; // 15, 16, 17, 18, 19
307        let xx3_p_azz = (xx.double()? + &xx + &azz) * &b3_xz_pairs; // 23, 24, 25
308
309        let y = y_frag + &xx3_p_azz; // 26, 27
310        let yz2 = (&self.y * &self.z).double()?; // 28, 29
311        let x = x_frag - &(b3_xz_pairs * &yz2); // 30, 31
312        let z = (yz2 * &yy).double()?.double()?; // 32, 33, 34
313        self.x = x;
314        self.y = y;
315        self.z = z;
316        Ok(())
317    }
318
319    fn negate(&self) -> Result<Self, SynthesisError> {
320        Ok(Self::new(self.x.clone(), self.y.negate()?, self.z.clone()))
321    }
322}
323
324fn mul_by_coeff_a<
325    P: SWModelParameters,
326    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
327>(
328    f: &F,
329) -> F
330where
331    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
332{
333    if !P::COEFF_A.is_zero() {
334        f * P::COEFF_A
335    } else {
336        F::zero()
337    }
338}
339
340impl_bounded_ops!(
341    ProjectiveVar<P, F>,
342    SWProjective<P>,
343    Add,
344    add,
345    AddAssign,
346    add_assign,
347    |this: &'a ProjectiveVar<P, F>, other: &'a ProjectiveVar<P, F>| {
348        // Complete addition formula from Renes-Costello-Batina 2015
349        // Algorithm 1
350        // (https://eprint.iacr.org/2015/1060).
351        //
352        // Adapted from code in
353        // https://github.com/RustCrypto/elliptic-curves/blob/master/p256/src/arithmetic.rs
354
355        let three_b = P::COEFF_B.double() + &P::COEFF_B;
356
357        let xx = &this.x * &other.x; // 1
358        let yy = &this.y * &other.y; // 2
359        let zz = &this.z * &other.z; // 3
360        let xy_pairs = ((&this.x + &this.y) * &(&other.x + &other.y)) - (&xx + &yy); // 4, 5, 6, 7, 8
361        let xz_pairs = ((&this.x + &this.z) * &(&other.x + &other.z)) - (&xx + &zz); // 9, 10, 11, 12, 13
362        let yz_pairs = ((&this.y + &this.z) * &(&other.y + &other.z)) - (&yy + &zz); // 14, 15, 16, 17, 18
363
364        let axz = mul_by_coeff_a::<P, F>(&xz_pairs); // 19
365
366        let bzz3_part = &axz + &zz * three_b; // 20, 21
367
368        let yy_m_bzz3 = &yy - &bzz3_part; // 22
369        let yy_p_bzz3 = &yy + &bzz3_part; // 23
370
371        let azz = mul_by_coeff_a::<P, F>(&zz);
372        let xx3_p_azz = xx.double().unwrap() + &xx + &azz; // 25, 26, 27, 29
373
374        let bxz3 = &xz_pairs * three_b; // 28
375        let b3_xz_pairs = mul_by_coeff_a::<P, F>(&(&xx - &azz)) + &bxz3; // 30, 31, 32
376
377        let x = (&yy_m_bzz3 * &xy_pairs) - &yz_pairs * &b3_xz_pairs; // 35, 39, 40
378        let y = (&yy_p_bzz3 * &yy_m_bzz3) + &xx3_p_azz * b3_xz_pairs; // 24, 36, 37, 38
379        let z = (&yy_p_bzz3 * &yz_pairs) + xy_pairs * xx3_p_azz; // 41, 42, 43
380
381        ProjectiveVar::new(x, y, z)
382    },
383    |this: &'a ProjectiveVar<P, F>, other: SWProjective<P>| {
384        this + ProjectiveVar::constant(other)
385    },
386    (F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>, P: SWModelParameters),
387    for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
388);
389
390impl_bounded_ops!(
391    ProjectiveVar<P, F>,
392    SWProjective<P>,
393    Sub,
394    sub,
395    SubAssign,
396    sub_assign,
397    |this: &'a ProjectiveVar<P, F>, other: &'a ProjectiveVar<P, F>| this + other.negate().unwrap(),
398    |this: &'a ProjectiveVar<P, F>, other: SWProjective<P>| this - ProjectiveVar::constant(other),
399    (F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>, P: SWModelParameters),
400    for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>
401);
402
403impl<'a, P, F> GroupOpsBounds<'a, SWProjective<P>, ProjectiveVar<P, F>> for ProjectiveVar<P, F>
404where
405    P: SWModelParameters,
406    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
407    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
408{
409}
410
411impl<'a, P, F> GroupOpsBounds<'a, SWProjective<P>, ProjectiveVar<P, F>> for &'a ProjectiveVar<P, F>
412where
413    P: SWModelParameters,
414    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
415    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
416{
417}
418
419impl<P, F> CondSelectGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
420where
421    P: SWModelParameters,
422    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
423    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
424{
425    #[inline]
426    fn conditionally_select(
427        cond: &Boolean<<P::BaseField as Field>::BasePrimeField>,
428        true_value: &Self,
429        false_value: &Self,
430    ) -> Result<Self, SynthesisError> {
431        let x = cond.select(&true_value.x, &false_value.x)?;
432        let y = cond.select(&true_value.y, &false_value.y)?;
433        let z = cond.select(&true_value.z, &false_value.z)?;
434
435        Ok(Self::new(x, y, z))
436    }
437}
438
439impl<P, F> EqGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
440where
441    P: SWModelParameters,
442    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
443    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
444{
445    fn is_eq(
446        &self,
447        other: &Self,
448    ) -> Result<Boolean<<P::BaseField as Field>::BasePrimeField>, SynthesisError> {
449        let x_equal = (&self.x * &other.z).is_eq(&(&other.x * &self.z))?;
450        let y_equal = (&self.y * &other.z).is_eq(&(&other.y * &self.z))?;
451        let coordinates_equal = x_equal.and(&y_equal)?;
452        let both_are_zero = self.is_zero()?.and(&other.is_zero()?)?;
453        both_are_zero.or(&coordinates_equal)
454    }
455
456    #[inline]
457    fn conditional_enforce_equal(
458        &self,
459        other: &Self,
460        condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
461    ) -> Result<(), SynthesisError> {
462        let x_equal = (&self.x * &other.z).is_eq(&(&other.x * &self.z))?;
463        let y_equal = (&self.y * &other.z).is_eq(&(&other.y * &self.z))?;
464        let coordinates_equal = x_equal.and(&y_equal)?;
465        let both_are_zero = self.is_zero()?.and(&other.is_zero()?)?;
466        both_are_zero
467            .or(&coordinates_equal)?
468            .conditional_enforce_equal(&Boolean::Constant(true), condition)?;
469        Ok(())
470    }
471
472    #[inline]
473    fn conditional_enforce_not_equal(
474        &self,
475        other: &Self,
476        condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
477    ) -> Result<(), SynthesisError> {
478        let is_equal = self.is_eq(other)?;
479        is_equal
480            .and(condition)?
481            .enforce_equal(&Boolean::Constant(false))
482    }
483}
484
485impl<P, F> AllocVar<SWAffine<P>, <P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
486where
487    P: SWModelParameters,
488    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
489    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
490{
491    fn new_variable<T: Borrow<SWAffine<P>>>(
492        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
493        f: impl FnOnce() -> Result<T, SynthesisError>,
494        mode: AllocationMode,
495    ) -> Result<Self, SynthesisError> {
496        Self::new_variable(cs, || f().map(|b| b.borrow().into_projective()), mode)
497    }
498}
499
500impl<P, F> AllocVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>
501    for ProjectiveVar<P, F>
502where
503    P: SWModelParameters,
504    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
505    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
506{
507    fn new_variable<T: Borrow<SWProjective<P>>>(
508        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
509        f: impl FnOnce() -> Result<T, SynthesisError>,
510        mode: AllocationMode,
511    ) -> Result<Self, SynthesisError> {
512        let ns = cs.into();
513        let cs = ns.cs();
514        let f = || Ok(*f()?.borrow());
515        match mode {
516            AllocationMode::Constant => Self::new_variable_omit_prime_order_check(cs, f, mode),
517            AllocationMode::Input => Self::new_variable_omit_prime_order_check(cs, f, mode),
518            AllocationMode::Witness => {
519                // if cofactor.is_even():
520                //   divide until you've removed all even factors
521                // else:
522                //   just directly use double and add.
523                let mut power_of_2: u32 = 0;
524                let mut cofactor = P::COFACTOR.to_vec();
525                while cofactor[0] % 2 == 0 {
526                    div2(&mut cofactor);
527                    power_of_2 += 1;
528                }
529
530                let cofactor_weight = BitIterator::new(cofactor.as_slice()).filter(|b| *b).count();
531                let modulus_minus_1 = (-P::ScalarField::one()).into_repr(); // r - 1
532                let modulus_minus_1_weight =
533                    BitIterator::new(modulus_minus_1).filter(|b| *b).count();
534
535                // We pick the most efficient method of performing the prime order check:
536                // If the cofactor has lower hamming weight than the scalar field's modulus,
537                // we first multiply by the inverse of the cofactor, and then, after allocating,
538                // multiply by the cofactor. This ensures the resulting point has no cofactors
539                //
540                // Else, we multiply by the scalar field's modulus and ensure that the result
541                // equals the identity.
542
543                let (mut ge, iter) = if cofactor_weight < modulus_minus_1_weight {
544                    let ge = Self::new_variable_omit_prime_order_check(
545                        cs.ns("Witness without subgroup check with cofactor mul"),
546                        || f().map(|g| g.borrow().into_affine().mul_by_cofactor_inv().into()),
547                        mode,
548                    )?;
549                    (ge, BitIterator::new(cofactor.as_slice()))
550                } else {
551                    let ge = Self::new_variable_omit_prime_order_check(
552                        cs.ns("Witness without subgroup check with `r` check"),
553                        || {
554                            f().map(|g| {
555                                let g = g.into_affine();
556                                let mut power_of_two = P::ScalarField::one().into_repr();
557                                power_of_two.muln(power_of_2);
558                                let power_of_two_inv =
559                                    P::ScalarField::from(power_of_two).inverse().unwrap();
560                                g.mul(power_of_two_inv)
561                            })
562                        },
563                        mode,
564                    )?;
565
566                    (ge, BitIterator::new(modulus_minus_1.as_ref()))
567                };
568                // Remove the even part of the cofactor
569                for _ in 0..power_of_2 {
570                    ge.double_in_place()?;
571                }
572
573                let mut seen_one = false;
574                let mut result = Self::zero();
575                for b in iter {
576                    let old_seen_one = seen_one;
577                    if seen_one {
578                        result.double_in_place()?;
579                    } else {
580                        seen_one = b;
581                    }
582
583                    if b {
584                        result = if old_seen_one {
585                            result + &ge
586                        } else {
587                            ge.clone()
588                        };
589                    }
590                }
591                if cofactor_weight < modulus_minus_1_weight {
592                    Ok(result)
593                } else {
594                    ge.enforce_equal(&ge)?;
595                    Ok(ge)
596                }
597            }
598        }
599    }
600}
601
602#[inline]
603fn div2(limbs: &mut [u64]) {
604    let mut t = 0;
605    for i in limbs.iter_mut().rev() {
606        let t2 = *i << 63;
607        *i >>= 1;
608        *i |= t;
609        t = t2;
610    }
611}
612
613impl<P, F> ToBitsGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
614where
615    P: SWModelParameters,
616    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
617    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
618{
619    fn to_bits(
620        &self,
621    ) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
622        let g = self.to_affine()?;
623        let mut bits = g.x.to_bits()?;
624        let y_bits = g.y.to_bits()?;
625        bits.extend_from_slice(&y_bits);
626        bits.push(g.infinity);
627        Ok(bits)
628    }
629
630    fn to_non_unique_bits(
631        &self,
632    ) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
633        let g = self.to_affine()?;
634        let mut bits = g.x.to_non_unique_bits()?;
635        let y_bits = g.y.to_non_unique_bits()?;
636        bits.extend_from_slice(&y_bits);
637        bits.push(g.infinity);
638        Ok(bits)
639    }
640}
641
642impl<P, F> ToBytesGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
643where
644    P: SWModelParameters,
645    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
646    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
647{
648    fn to_bytes(
649        &self,
650    ) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
651        let g = self.to_affine()?;
652        let mut bytes = g.x.to_bytes()?;
653        let y_bytes = g.y.to_bytes()?;
654        let inf_bytes = g.infinity.to_bytes()?;
655        bytes.extend_from_slice(&y_bytes);
656        bytes.extend_from_slice(&inf_bytes);
657        Ok(bytes)
658    }
659
660    fn to_non_unique_bytes(
661        &self,
662    ) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
663        let g = self.to_affine()?;
664        let mut bytes = g.x.to_non_unique_bytes()?;
665        let y_bytes = g.y.to_non_unique_bytes()?;
666        let inf_bytes = g.infinity.to_non_unique_bytes()?;
667        bytes.extend_from_slice(&y_bytes);
668        bytes.extend_from_slice(&inf_bytes);
669        Ok(bytes)
670    }
671}
672
673#[cfg(test)]
674#[allow(dead_code)]
675pub(crate) fn test<P, GG>() -> Result<(), SynthesisError>
676where
677    P: SWModelParameters,
678    GG: CurveVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>,
679    for<'a> &'a GG: GroupOpsBounds<'a, SWProjective<P>, GG>,
680{
681    use crate::prelude::*;
682    use algebra::{test_rng, Group, UniformRand};
683    use r1cs_core::ConstraintSystem;
684
685    crate::groups::test::group_test::<SWProjective<P>, _, GG>()?;
686
687    let mut rng = test_rng();
688
689    let cs = ConstraintSystem::<<P::BaseField as Field>::BasePrimeField>::new_ref();
690
691    let a = SWProjective::<P>::rand(&mut rng);
692    let b = SWProjective::<P>::rand(&mut rng);
693    let a_affine = a.into_affine();
694    let b_affine = b.into_affine();
695
696    println!("Allocating things");
697    let ns = cs.ns("allocating variables");
698    println!("{:?}", cs.current_namespace());
699    let mut gadget_a = GG::new_witness(cs.ns("a"), || Ok(a))?;
700    let gadget_b = GG::new_witness(cs.ns("b"), || Ok(b))?;
701    println!("{:?}", cs.current_namespace());
702    ns.leave_namespace();
703    println!("Done Allocating things");
704    assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x);
705    assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y);
706    assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x);
707    assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y);
708    assert_eq!(cs.which_is_unsatisfied(), None);
709
710    println!("Checking addition");
711    // Check addition
712    let ab = a + &b;
713    let ab_affine = ab.into_affine();
714    let gadget_ab = &gadget_a + &gadget_b;
715    let gadget_ba = &gadget_b + &gadget_a;
716    gadget_ba.enforce_equal(&gadget_ab)?;
717
718    let ab_val = gadget_ab.value()?.into_affine();
719    assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
720    assert!(cs.is_satisfied().unwrap());
721    println!("Done checking addition");
722
723    println!("Checking doubling");
724    // Check doubling
725    let aa = Group::double(&a);
726    let aa_affine = aa.into_affine();
727    gadget_a.double_in_place()?;
728    let aa_val = gadget_a.value()?.into_affine();
729    assert_eq!(
730        aa_val, aa_affine,
731        "Gadget and native values are unequal after double."
732    );
733    assert!(cs.is_satisfied().unwrap());
734    println!("Done checking doubling");
735
736    println!("Checking mul_bits");
737    // Check mul_bits
738    let scalar = P::ScalarField::rand(&mut rng);
739    let native_result = aa.into_affine().mul(scalar);
740    let native_result = native_result.into_affine();
741
742    let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
743    // Get the scalar bits into little-endian form.
744    scalar.reverse();
745    let input: Vec<Boolean<_>> = Vec::new_witness(cs.ns("bits"), || Ok(scalar)).unwrap();
746    let result = gadget_a.mul_bits(input.iter())?;
747    let result_val = result.value()?.into_affine();
748    assert_eq!(
749        result_val, native_result,
750        "gadget & native values are diff. after scalar mul"
751    );
752    assert!(cs.is_satisfied().unwrap());
753    println!("Done checking mul_bits");
754
755    if !cs.is_satisfied().unwrap() {
756        println!("Not satisfied");
757        println!("{:?}", cs.which_is_unsatisfied().unwrap());
758    }
759
760    assert!(cs.is_satisfied().unwrap());
761    Ok(())
762}