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, BitIteratorBE, 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 result = Self::zero();
259        for b in BitIteratorBE::without_leading_zeros(r_minus_1) {
260            result.double_in_place()?;
261
262            if b {
263                result += self;
264            }
265        }
266        self.negate()?.enforce_equal(&result)?;
267        Ok(())
268    }
269
270    #[inline]
271    fn double_in_place(&mut self) -> Result<(), SynthesisError> {
272        // Complete doubling formula from Renes-Costello-Batina 2015
273        // Algorithm 3
274        // (https://eprint.iacr.org/2015/1060).
275        //
276        // Adapted from code in
277        // https://github.com/RustCrypto/elliptic-curves/blob/master/p256/src/arithmetic.rs
278        let three_b = P::COEFF_B.double() + &P::COEFF_B;
279
280        let xx = self.x.square()?; // 1
281        let yy = self.y.square()?; // 2
282        let zz = self.z.square()?; // 3
283        let xy2 = (&self.x * &self.y).double()?; // 4, 5
284        let xz2 = (&self.x * &self.z).double()?; // 6, 7
285
286        let axz2 = mul_by_coeff_a::<P, F>(&xz2); // 8
287
288        let bzz3_part = &axz2 + &zz * three_b; // 9, 10
289        let yy_m_bzz3 = &yy - &bzz3_part; // 11
290        let yy_p_bzz3 = &yy + &bzz3_part; // 12
291        let y_frag = yy_p_bzz3 * &yy_m_bzz3; // 13
292        let x_frag = yy_m_bzz3 * &xy2; // 14
293
294        let bxz3 = xz2 * three_b; // 15
295        let azz = mul_by_coeff_a::<P, F>(&zz); // 16
296        let b3_xz_pairs = mul_by_coeff_a::<P, F>(&(&xx - &azz)) + &bxz3; // 15, 16, 17, 18, 19
297        let xx3_p_azz = (xx.double()? + &xx + &azz) * &b3_xz_pairs; // 23, 24, 25
298
299        let y = y_frag + &xx3_p_azz; // 26, 27
300        let yz2 = (&self.y * &self.z).double()?; // 28, 29
301        let x = x_frag - &(b3_xz_pairs * &yz2); // 30, 31
302        let z = (yz2 * &yy).double()?.double()?; // 32, 33, 34
303        self.x = x;
304        self.y = y;
305        self.z = z;
306        Ok(())
307    }
308
309    fn negate(&self) -> Result<Self, SynthesisError> {
310        Ok(Self::new(self.x.clone(), self.y.negate()?, self.z.clone()))
311    }
312}
313
314fn mul_by_coeff_a<
315    P: SWModelParameters,
316    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
317>(
318    f: &F,
319) -> F
320where
321    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
322{
323    if !P::COEFF_A.is_zero() {
324        f * P::COEFF_A
325    } else {
326        F::zero()
327    }
328}
329
330impl_bounded_ops!(
331    ProjectiveVar<P, F>,
332    SWProjective<P>,
333    Add,
334    add,
335    AddAssign,
336    add_assign,
337    |this: &'a ProjectiveVar<P, F>, other: &'a ProjectiveVar<P, F>| {
338        // Complete addition formula from Renes-Costello-Batina 2015
339        // Algorithm 1
340        // (https://eprint.iacr.org/2015/1060).
341        //
342        // Adapted from code in
343        // https://github.com/RustCrypto/elliptic-curves/blob/master/p256/src/arithmetic.rs
344
345        let three_b = P::COEFF_B.double() + &P::COEFF_B;
346
347        let xx = &this.x * &other.x; // 1
348        let yy = &this.y * &other.y; // 2
349        let zz = &this.z * &other.z; // 3
350        let xy_pairs = ((&this.x + &this.y) * &(&other.x + &other.y)) - (&xx + &yy); // 4, 5, 6, 7, 8
351        let xz_pairs = ((&this.x + &this.z) * &(&other.x + &other.z)) - (&xx + &zz); // 9, 10, 11, 12, 13
352        let yz_pairs = ((&this.y + &this.z) * &(&other.y + &other.z)) - (&yy + &zz); // 14, 15, 16, 17, 18
353
354        let axz = mul_by_coeff_a::<P, F>(&xz_pairs); // 19
355
356        let bzz3_part = &axz + &zz * three_b; // 20, 21
357
358        let yy_m_bzz3 = &yy - &bzz3_part; // 22
359        let yy_p_bzz3 = &yy + &bzz3_part; // 23
360
361        let azz = mul_by_coeff_a::<P, F>(&zz);
362        let xx3_p_azz = xx.double().unwrap() + &xx + &azz; // 25, 26, 27, 29
363
364        let bxz3 = &xz_pairs * three_b; // 28
365        let b3_xz_pairs = mul_by_coeff_a::<P, F>(&(&xx - &azz)) + &bxz3; // 30, 31, 32
366
367        let x = (&yy_m_bzz3 * &xy_pairs) - &yz_pairs * &b3_xz_pairs; // 35, 39, 40
368        let y = (&yy_p_bzz3 * &yy_m_bzz3) + &xx3_p_azz * b3_xz_pairs; // 24, 36, 37, 38
369        let z = (&yy_p_bzz3 * &yz_pairs) + xy_pairs * xx3_p_azz; // 41, 42, 43
370
371        ProjectiveVar::new(x, y, z)
372    },
373    |this: &'a ProjectiveVar<P, F>, other: SWProjective<P>| {
374        this + ProjectiveVar::constant(other)
375    },
376    (F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>, P: SWModelParameters),
377    for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
378);
379
380impl_bounded_ops!(
381    ProjectiveVar<P, F>,
382    SWProjective<P>,
383    Sub,
384    sub,
385    SubAssign,
386    sub_assign,
387    |this: &'a ProjectiveVar<P, F>, other: &'a ProjectiveVar<P, F>| this + other.negate().unwrap(),
388    |this: &'a ProjectiveVar<P, F>, other: SWProjective<P>| this - ProjectiveVar::constant(other),
389    (F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>, P: SWModelParameters),
390    for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>
391);
392
393impl<'a, P, F> GroupOpsBounds<'a, SWProjective<P>, ProjectiveVar<P, F>> for ProjectiveVar<P, F>
394where
395    P: SWModelParameters,
396    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
397    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
398{
399}
400
401impl<'a, P, F> GroupOpsBounds<'a, SWProjective<P>, ProjectiveVar<P, F>> for &'a ProjectiveVar<P, F>
402where
403    P: SWModelParameters,
404    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
405    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
406{
407}
408
409impl<P, F> CondSelectGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
410where
411    P: SWModelParameters,
412    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
413    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
414{
415    #[inline]
416    fn conditionally_select(
417        cond: &Boolean<<P::BaseField as Field>::BasePrimeField>,
418        true_value: &Self,
419        false_value: &Self,
420    ) -> Result<Self, SynthesisError> {
421        let x = cond.select(&true_value.x, &false_value.x)?;
422        let y = cond.select(&true_value.y, &false_value.y)?;
423        let z = cond.select(&true_value.z, &false_value.z)?;
424
425        Ok(Self::new(x, y, z))
426    }
427}
428
429impl<P, F> EqGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
430where
431    P: SWModelParameters,
432    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
433    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
434{
435    fn is_eq(
436        &self,
437        other: &Self,
438    ) -> Result<Boolean<<P::BaseField as Field>::BasePrimeField>, SynthesisError> {
439        let x_equal = (&self.x * &other.z).is_eq(&(&other.x * &self.z))?;
440        let y_equal = (&self.y * &other.z).is_eq(&(&other.y * &self.z))?;
441        let coordinates_equal = x_equal.and(&y_equal)?;
442        let both_are_zero = self.is_zero()?.and(&other.is_zero()?)?;
443        both_are_zero.or(&coordinates_equal)
444    }
445
446    #[inline]
447    fn conditional_enforce_equal(
448        &self,
449        other: &Self,
450        condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
451    ) -> Result<(), SynthesisError> {
452        let x_equal = (&self.x * &other.z).is_eq(&(&other.x * &self.z))?;
453        let y_equal = (&self.y * &other.z).is_eq(&(&other.y * &self.z))?;
454        let coordinates_equal = x_equal.and(&y_equal)?;
455        let both_are_zero = self.is_zero()?.and(&other.is_zero()?)?;
456        both_are_zero
457            .or(&coordinates_equal)?
458            .conditional_enforce_equal(&Boolean::Constant(true), condition)?;
459        Ok(())
460    }
461
462    #[inline]
463    fn conditional_enforce_not_equal(
464        &self,
465        other: &Self,
466        condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
467    ) -> Result<(), SynthesisError> {
468        let is_equal = self.is_eq(other)?;
469        is_equal
470            .and(condition)?
471            .enforce_equal(&Boolean::Constant(false))
472    }
473}
474
475impl<P, F> AllocVar<SWAffine<P>, <P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
476where
477    P: SWModelParameters,
478    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
479    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
480{
481    fn new_variable<T: Borrow<SWAffine<P>>>(
482        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
483        f: impl FnOnce() -> Result<T, SynthesisError>,
484        mode: AllocationMode,
485    ) -> Result<Self, SynthesisError> {
486        Self::new_variable(cs, || f().map(|b| b.borrow().into_projective()), mode)
487    }
488}
489
490impl<P, F> AllocVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>
491    for ProjectiveVar<P, F>
492where
493    P: SWModelParameters,
494    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
495    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
496{
497    fn new_variable<T: Borrow<SWProjective<P>>>(
498        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
499        f: impl FnOnce() -> Result<T, SynthesisError>,
500        mode: AllocationMode,
501    ) -> Result<Self, SynthesisError> {
502        let ns = cs.into();
503        let cs = ns.cs();
504        let f = || Ok(*f()?.borrow());
505        match mode {
506            AllocationMode::Constant => Self::new_variable_omit_prime_order_check(cs, f, mode),
507            AllocationMode::Input => Self::new_variable_omit_prime_order_check(cs, f, mode),
508            AllocationMode::Witness => {
509                // if cofactor.is_even():
510                //   divide until you've removed all even factors
511                // else:
512                //   just directly use double and add.
513                let mut power_of_2: u32 = 0;
514                let mut cofactor = P::COFACTOR.to_vec();
515                while cofactor[0] % 2 == 0 {
516                    div2(&mut cofactor);
517                    power_of_2 += 1;
518                }
519
520                let cofactor_weight = BitIteratorBE::new(cofactor.as_slice())
521                    .filter(|b| *b)
522                    .count();
523                let modulus_minus_1 = (-P::ScalarField::one()).into_repr(); // r - 1
524                let modulus_minus_1_weight =
525                    BitIteratorBE::new(modulus_minus_1).filter(|b| *b).count();
526
527                // We pick the most efficient method of performing the prime order check:
528                // If the cofactor has lower hamming weight than the scalar field's modulus,
529                // we first multiply by the inverse of the cofactor, and then, after allocating,
530                // multiply by the cofactor. This ensures the resulting point has no cofactors
531                //
532                // Else, we multiply by the scalar field's modulus and ensure that the result
533                // equals the identity.
534
535                let (mut ge, iter) = if cofactor_weight < modulus_minus_1_weight {
536                    let ge = Self::new_variable_omit_prime_order_check(
537                        cs.ns("Witness without subgroup check with cofactor mul"),
538                        || f().map(|g| g.borrow().into_affine().mul_by_cofactor_inv().into()),
539                        mode,
540                    )?;
541                    (
542                        ge,
543                        BitIteratorBE::without_leading_zeros(cofactor.as_slice()),
544                    )
545                } else {
546                    let ge = Self::new_variable_omit_prime_order_check(
547                        cs.ns("Witness without subgroup check with `r` check"),
548                        || {
549                            f().map(|g| {
550                                let g = g.into_affine();
551                                let mut power_of_two = P::ScalarField::one().into_repr();
552                                power_of_two.muln(power_of_2);
553                                let power_of_two_inv = P::ScalarField::from_repr(power_of_two)
554                                    .and_then(|n| n.inverse())
555                                    .unwrap();
556                                g.mul(power_of_two_inv)
557                            })
558                        },
559                        mode,
560                    )?;
561
562                    (
563                        ge,
564                        BitIteratorBE::without_leading_zeros(modulus_minus_1.as_ref()),
565                    )
566                };
567                // Remove the even part of the cofactor
568                for _ in 0..power_of_2 {
569                    ge.double_in_place()?;
570                }
571
572                let mut result = Self::zero();
573                for b in iter {
574                    result.double_in_place()?;
575
576                    if b {
577                        result += &ge
578                    }
579                }
580                if cofactor_weight < modulus_minus_1_weight {
581                    Ok(result)
582                } else {
583                    ge.enforce_equal(&ge)?;
584                    Ok(ge)
585                }
586            }
587        }
588    }
589}
590
591#[inline]
592fn div2(limbs: &mut [u64]) {
593    let mut t = 0;
594    for i in limbs.iter_mut().rev() {
595        let t2 = *i << 63;
596        *i >>= 1;
597        *i |= t;
598        t = t2;
599    }
600}
601
602impl<P, F> ToBitsGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
603where
604    P: SWModelParameters,
605    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
606    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
607{
608    fn to_bits_le(
609        &self,
610    ) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
611        let g = self.to_affine()?;
612        let mut bits = g.x.to_bits_le()?;
613        let y_bits = g.y.to_bits_le()?;
614        bits.extend_from_slice(&y_bits);
615        bits.push(g.infinity);
616        Ok(bits)
617    }
618
619    fn to_non_unique_bits_le(
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_non_unique_bits_le()?;
624        let y_bits = g.y.to_non_unique_bits_le()?;
625        bits.extend_from_slice(&y_bits);
626        bits.push(g.infinity);
627        Ok(bits)
628    }
629}
630
631impl<P, F> ToBytesGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
632where
633    P: SWModelParameters,
634    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
635    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
636{
637    fn to_bytes(
638        &self,
639    ) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
640        let g = self.to_affine()?;
641        let mut bytes = g.x.to_bytes()?;
642        let y_bytes = g.y.to_bytes()?;
643        let inf_bytes = g.infinity.to_bytes()?;
644        bytes.extend_from_slice(&y_bytes);
645        bytes.extend_from_slice(&inf_bytes);
646        Ok(bytes)
647    }
648
649    fn to_non_unique_bytes(
650        &self,
651    ) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
652        let g = self.to_affine()?;
653        let mut bytes = g.x.to_non_unique_bytes()?;
654        let y_bytes = g.y.to_non_unique_bytes()?;
655        let inf_bytes = g.infinity.to_non_unique_bytes()?;
656        bytes.extend_from_slice(&y_bytes);
657        bytes.extend_from_slice(&inf_bytes);
658        Ok(bytes)
659    }
660}
661
662#[cfg(test)]
663#[allow(dead_code)]
664pub(crate) fn test<P, GG>() -> Result<(), SynthesisError>
665where
666    P: SWModelParameters,
667    GG: CurveVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>,
668    for<'a> &'a GG: GroupOpsBounds<'a, SWProjective<P>, GG>,
669{
670    use crate::prelude::*;
671    use algebra::{test_rng, BitIteratorLE, Group, UniformRand};
672    use r1cs_core::ConstraintSystem;
673
674    crate::groups::test::group_test::<SWProjective<P>, _, GG>()?;
675
676    let mut rng = test_rng();
677
678    let cs = ConstraintSystem::<<P::BaseField as Field>::BasePrimeField>::new_ref();
679
680    let a = SWProjective::<P>::rand(&mut rng);
681    let b = SWProjective::<P>::rand(&mut rng);
682    let a_affine = a.into_affine();
683    let b_affine = b.into_affine();
684
685    println!("Allocating things");
686    let ns = cs.ns("allocating variables");
687    println!("{:?}", cs.current_namespace());
688    let mut gadget_a = GG::new_witness(cs.ns("a"), || Ok(a))?;
689    let gadget_b = GG::new_witness(cs.ns("b"), || Ok(b))?;
690    println!("{:?}", cs.current_namespace());
691    ns.leave_namespace();
692    println!("Done Allocating things");
693    assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x);
694    assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y);
695    assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x);
696    assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y);
697    assert_eq!(cs.which_is_unsatisfied(), None);
698
699    println!("Checking addition");
700    // Check addition
701    let ab = a + &b;
702    let ab_affine = ab.into_affine();
703    let gadget_ab = &gadget_a + &gadget_b;
704    let gadget_ba = &gadget_b + &gadget_a;
705    gadget_ba.enforce_equal(&gadget_ab)?;
706
707    let ab_val = gadget_ab.value()?.into_affine();
708    assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
709    assert!(cs.is_satisfied().unwrap());
710    println!("Done checking addition");
711
712    println!("Checking doubling");
713    // Check doubling
714    let aa = Group::double(&a);
715    let aa_affine = aa.into_affine();
716    gadget_a.double_in_place()?;
717    let aa_val = gadget_a.value()?.into_affine();
718    assert_eq!(
719        aa_val, aa_affine,
720        "Gadget and native values are unequal after double."
721    );
722    assert!(cs.is_satisfied().unwrap());
723    println!("Done checking doubling");
724
725    println!("Checking mul_bits");
726    // Check mul_bits
727    let scalar = P::ScalarField::rand(&mut rng);
728    let native_result = aa.into_affine().mul(scalar);
729    let native_result = native_result.into_affine();
730
731    let scalar: Vec<bool> = BitIteratorLE::new(scalar.into_repr()).collect();
732    let input: Vec<Boolean<_>> = Vec::new_witness(cs.ns("bits"), || Ok(scalar)).unwrap();
733    let result = gadget_a.scalar_mul_le(input.iter())?;
734    let result_val = result.value()?.into_affine();
735    assert_eq!(
736        result_val, native_result,
737        "gadget & native values are diff. after scalar mul"
738    );
739    assert!(cs.is_satisfied().unwrap());
740    println!("Done checking mul_bits");
741
742    if !cs.is_satisfied().unwrap() {
743        println!("Not satisfied");
744        println!("{:?}", cs.which_is_unsatisfied().unwrap());
745    }
746
747    assert!(cs.is_satisfied().unwrap());
748    Ok(())
749}