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, BitIterator, Field, PrimeField, ProjectiveCurve,
  7};
  8use num_traits::{One, Zero};
  9use r1cs_core::{ConstraintSystem, SynthesisError};
 10use std::{borrow::Borrow, marker::PhantomData, ops::Neg};
 11
 12use crate::{prelude::*, Assignment};
 13
 14pub mod bls12;
 15
 16#[derive(Derivative)]
 17#[derivative(Debug, Clone)]
 18#[must_use]
 19pub struct AffineGadget<
 20    P: SWModelParameters,
 21    ConstraintF: Field,
 22    F: FieldGadget<P::BaseField, ConstraintF>,
 23> {
 24    pub x:   F,
 25    pub y:   F,
 26    pub infinity: Boolean,
 27    _params: PhantomData<P>,
 28    _engine: PhantomData<ConstraintF>,
 29}
 30
 31impl<P: SWModelParameters, ConstraintF: Field, F: FieldGadget<P::BaseField, ConstraintF>>
 32    AffineGadget<P, ConstraintF, F>
 33{
 34    pub fn new(x: F, y: F, infinity: Boolean) -> Self {
 35        Self {
 36            x,
 37            y,
 38            infinity,
 39            _params: PhantomData,
 40            _engine: PhantomData,
 41        }
 42    }
 43
 44    pub fn alloc_without_check<FN, CS: ConstraintSystem<ConstraintF>>(
 45        mut cs: CS,
 46        value_gen: F,
 47    ) -> Result<Self, SynthesisError>
 48    where
 49        F: FnOnce() -> Result<SWProjective<P>, SynthesisError>,
 50    {
 51        let (x, y, infinity) = match value_gen() {
 52            Ok(ge) => {
 53                let ge = ge.into_affine();
 54                (Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
 55            },
 56            _ => (
 57                Err(SynthesisError::AssignmentMissing),
 58                Err(SynthesisError::AssignmentMissing),
 59                Err(SynthesisError::AssignmentMissing),
 60            ),
 61        };
 62
 63        let x = F::alloc(&mut cs.ns(|| "x"), || x)?;
 64        let y = F::alloc(&mut cs.ns(|| "y"), || y)?;
 65        let infinity = Boolean::alloc(&mut cs.ns(|| "infinity"), || infinity)?;
 66
 67        Ok(Self::new(x, y, infinity))
 68    }
 69}
 70
 71impl<P, ConstraintF, F> PartialEq for AffineGadget<P, ConstraintF, F>
 72where
 73    P: SWModelParameters,
 74    ConstraintF: Field,
 75    F: FieldGadget<P::BaseField, ConstraintF>,
 76{
 77    fn eq(&self, other: &Self) -> bool {
 78        self.x == other.x && self.y == other.y
 79    }
 80}
 81
 82impl<P, ConstraintF, F> Eq for AffineGadget<P, ConstraintF, F>
 83where
 84    P: SWModelParameters,
 85    ConstraintF: Field,
 86    F: FieldGadget<P::BaseField, ConstraintF>,
 87{
 88}
 89
 90impl<P, ConstraintF, F> GroupGadget<SWProjective<P>, ConstraintF>
 91    for AffineGadget<P, ConstraintF, F>
 92where
 93    P: SWModelParameters,
 94    ConstraintF: Field,
 95    F: FieldGadget<P::BaseField, ConstraintF>,
 96{
 97    type Value = SWProjective<P>;
 98    type Variable = (F::Variable, F::Variable);
 99
100    #[inline]
101    fn get_value(&self) -> Option<Self::Value> {
102        match (self.x.get_value(), self.y.get_value(), self.infinity.get_value()) {
103            (Some(x), Some(y), Some(infinity)) => {
104                Some(SWAffine::new(x, y, infinity).into_projective())
105            },
106            (None, None, None) => None,
107            _ => unreachable!(),
108        }
109    }
110
111    #[inline]
112    fn get_variable(&self) -> Self::Variable {
113        (self.x.get_variable(), self.y.get_variable())
114    }
115
116    #[inline]
117    fn zero<CS: ConstraintSystem<ConstraintF>>(mut cs: CS) -> Result<Self, SynthesisError> {
118        Ok(Self::new(
119            F::zero(cs.ns(|| "zero"))?,
120            F::one(cs.ns(|| "one"))?,
121            Boolean::Constant(true),
122        ))
123    }
124
125    #[inline]
126    /// Incomplete addition: neither `self` nor `other` can be the neutral
127    /// element.
128    fn add<CS: ConstraintSystem<ConstraintF>>(
129        &self,
130        mut cs: CS,
131        other: &Self,
132    ) -> Result<Self, SynthesisError> {
133        // lambda = (B.y - A.y)/(B.x - A.x)
134        // C.x = lambda^2 - A.x - B.x
135        // C.y = lambda(A.x - C.x) - A.y
136        //
137        // Special cases:
138        //
139        // doubling: if B.y = A.y and B.x = A.x then lambda is unbound and
140        // C = (lambda^2, lambda^3)
141        //
142        // addition of negative point: if B.y = -A.y and B.x = A.x then no
143        // lambda can satisfy the first equation unless B.y - A.y = 0. But
144        // then this reduces to doubling.
145        //
146        // So we need to check that A.x - B.x != 0, which can be done by
147        // enforcing I * (B.x - A.x) = 1
148        // This is done below when we calculate inv (by F::inverse)
149
150        let x2_minus_x1 = other.x.sub(cs.ns(|| "x2 - x1"), &self.x)?;
151        let y2_minus_y1 = other.y.sub(cs.ns(|| "y2 - y1"), &self.y)?;
152
153        let inv = x2_minus_x1.inverse(cs.ns(|| "compute inv"))?;
154
155        let lambda = F::alloc(cs.ns(|| "lambda"), || {
156            Ok(y2_minus_y1.get_value().get()? * &inv.get_value().get()?)
157        })?;
158
159        let x_3 = F::alloc(&mut cs.ns(|| "x_3"), || {
160            let lambda_val = lambda.get_value().get()?;
161            let x1 = self.x.get_value().get()?;
162            let x2 = other.x.get_value().get()?;
163            Ok((lambda_val.square() - &x1) - &x2)
164        })?;
165
166        let y_3 = F::alloc(&mut cs.ns(|| "y_3"), || {
167            let lambda_val = lambda.get_value().get()?;
168            let x_1 = self.x.get_value().get()?;
169            let y_1 = self.y.get_value().get()?;
170            let x_3 = x_3.get_value().get()?;
171            Ok(lambda_val * &(x_1 - &x_3) - &y_1)
172        })?;
173
174        // Check lambda
175        lambda.mul_equals(cs.ns(|| "check lambda"), &x2_minus_x1, &y2_minus_y1)?;
176
177        // Check x3
178        let x3_plus_x1_plus_x2 = x_3
179            .add(cs.ns(|| "x3 + x1"), &self.x)?
180            .add(cs.ns(|| "x3 + x1 + x2"), &other.x)?;
181        lambda.mul_equals(cs.ns(|| "check x3"), &lambda, &x3_plus_x1_plus_x2)?;
182
183        // Check y3
184        let y3_plus_y1 = y_3.add(cs.ns(|| "y3 + y1"), &self.y)?;
185        let x1_minus_x3 = self.x.sub(cs.ns(|| "x1 - x3"), &x_3)?;
186
187        lambda.mul_equals(cs.ns(|| ""), &x1_minus_x3, &y3_plus_y1)?;
188
189        Ok(Self::new(x_3, y_3, Boolean::Constant(false)))
190    }
191
192    /// Incomplete addition: neither `self` nor `other` can be the neutral
193    /// element.
194    fn add_constant<CS: ConstraintSystem<ConstraintF>>(
195        &self,
196        mut cs: CS,
197        other: &SWProjective<P>,
198    ) -> Result<Self, SynthesisError> {
199        // lambda = (B.y - A.y)/(B.x - A.x)
200        // C.x = lambda^2 - A.x - B.x
201        // C.y = lambda(A.x - C.x) - A.y
202        //
203        // Special cases:
204        //
205        // doubling: if B.y = A.y and B.x = A.x then lambda is unbound and
206        // C = (lambda^2, lambda^3)
207        //
208        // addition of negative point: if B.y = -A.y and B.x = A.x then no
209        // lambda can satisfy the first equation unless B.y - A.y = 0. But
210        // then this reduces to doubling.
211        //
212        // So we need to check that A.x - B.x != 0, which can be done by
213        // enforcing I * (B.x - A.x) = 1
214        if other.is_zero() {
215            return Err(SynthesisError::AssignmentMissing);
216        }
217        let other = other.into_affine();
218        let other_x = other.x;
219        let other_y = other.y;
220
221        let x2_minus_x1 = self
222            .x
223            .sub_constant(cs.ns(|| "x2 - x1"), &other_x)?
224            .negate(cs.ns(|| "neg1"))?;
225        let y2_minus_y1 = self
226            .y
227            .sub_constant(cs.ns(|| "y2 - y1"), &other_y)?
228            .negate(cs.ns(|| "neg2"))?;
229
230        let inv = x2_minus_x1.inverse(cs.ns(|| "compute inv"))?;
231
232        let lambda = F::alloc(cs.ns(|| "lambda"), || {
233            Ok(y2_minus_y1.get_value().get()? * &inv.get_value().get()?)
234        })?;
235
236        let x_3 = F::alloc(&mut cs.ns(|| "x_3"), || {
237            let lambda_val = lambda.get_value().get()?;
238            let x1 = self.x.get_value().get()?;
239            let x2 = other_x;
240            Ok((lambda_val.square() - &x1) - &x2)
241        })?;
242
243        let y_3 = F::alloc(&mut cs.ns(|| "y_3"), || {
244            let lambda_val = lambda.get_value().get()?;
245            let x_1 = self.x.get_value().get()?;
246            let y_1 = self.y.get_value().get()?;
247            let x_3 = x_3.get_value().get()?;
248            Ok(lambda_val * &(x_1 - &x_3) - &y_1)
249        })?;
250
251        // Check lambda
252        lambda.mul_equals(cs.ns(|| "check lambda"), &x2_minus_x1, &y2_minus_y1)?;
253
254        // Check x3
255        let x3_plus_x1_plus_x2 = x_3
256            .add(cs.ns(|| "x3 + x1"), &self.x)?
257            .add_constant(cs.ns(|| "x3 + x1 + x2"), &other_x)?;
258        lambda.mul_equals(cs.ns(|| "check x3"), &lambda, &x3_plus_x1_plus_x2)?;
259
260        // Check y3
261        let y3_plus_y1 = y_3.add(cs.ns(|| "y3 + y1"), &self.y)?;
262        let x1_minus_x3 = self.x.sub(cs.ns(|| "x1 - x3"), &x_3)?;
263
264        lambda.mul_equals(cs.ns(|| ""), &x1_minus_x3, &y3_plus_y1)?;
265
266        Ok(Self::new(x_3, y_3, Boolean::Constant(false)))
267    }
268
269    #[inline]
270    fn double_in_place<CS: ConstraintSystem<ConstraintF>>(
271        &mut self,
272        mut cs: CS,
273    ) -> Result<(), SynthesisError> {
274        let a = P::COEFF_A;
275        let x_squared = self.x.square(cs.ns(|| "x^2"))?;
276
277        let one = P::BaseField::one();
278        let two = one.double();
279        let three = two + &one;
280
281        let three_x_squared = x_squared.mul_by_constant(cs.ns(|| "3 * x^2"), &three)?;
282        let three_x_squared_plus_a = three_x_squared.add_constant(cs.ns(|| "3 * x^2 + a"), &a)?;
283
284        let two_y = self.y.double(cs.ns(|| "2y"))?;
285
286        let lambda = F::alloc(cs.ns(|| "lambda"), || {
287            let y_doubled_inv = two_y.get_value().get()?.inverse().get()?;
288            Ok(three_x_squared_plus_a.get_value().get()? * &y_doubled_inv)
289        })?;
290
291        // Check lambda
292        lambda.mul_equals(cs.ns(|| "check lambda"), &two_y, &three_x_squared_plus_a)?;
293
294        let x = lambda
295            .square(cs.ns(|| "lambda^2"))?
296            .sub(cs.ns(|| "lambda^2 - x"), &self.x)?
297            .sub(cs.ns(|| "lambda^2 - 2x"), &self.x)?;
298
299        let y = self
300            .x
301            .sub(cs.ns(|| "x - self.x"), &x)?
302            .mul(cs.ns(|| "times lambda"), &lambda)?
303            .sub(cs.ns(|| "plus self.y"), &self.y)?;
304
305        *self = Self::new(x, y, Boolean::Constant(false));
306        Ok(())
307    }
308
309    fn negate<CS: ConstraintSystem<ConstraintF>>(
310        &self,
311        mut cs: CS,
312    ) -> Result<Self, SynthesisError> {
313        Ok(Self::new(
314            self.x.clone(),
315            self.y.negate(cs.ns(|| "negate y"))?,
316            self.infinity,
317        ))
318    }
319
320    fn cost_of_add() -> usize {
321        3 * F::cost_of_mul() + F::cost_of_inv()
322    }
323
324    fn cost_of_double() -> usize {
325        4 * F::cost_of_mul()
326    }
327}
328
329impl<P, ConstraintF, F> CondSelectGadget<ConstraintF> for AffineGadget<P, ConstraintF, F>
330where
331    P: SWModelParameters,
332    ConstraintF: Field,
333    F: FieldGadget<P::BaseField, ConstraintF>,
334{
335    #[inline]
336    fn conditionally_select<CS: ConstraintSystem<ConstraintF>>(
337        mut cs: CS,
338        cond: &Boolean,
339        first: &Self,
340        second: &Self,
341    ) -> Result<Self, SynthesisError> {
342        let x = F::conditionally_select(&mut cs.ns(|| "x"), cond, &first.x, &second.x)?;
343        let y = F::conditionally_select(&mut cs.ns(|| "y"), cond, &first.y, &second.y)?;
344        let infinity = Boolean::conditionally_select(&mut cs.ns(|| "infinity"), cond, &first.infinity, &second.infinity)?;
345
346        Ok(Self::new(x, y, infinity))
347    }
348
349    fn cost() -> usize {
350        2 * <F as CondSelectGadget<ConstraintF>>::cost() +
351        <Boolean as CondSelectGadget<ConstraintF>>::cost()
352    }
353}
354
355impl<P, ConstraintF, F> EqGadget<ConstraintF> for AffineGadget<P, ConstraintF, F>
356where
357    P: SWModelParameters,
358    ConstraintF: Field,
359    F: FieldGadget<P::BaseField, ConstraintF>,
360{
361}
362
363impl<P, ConstraintF, F> ConditionalEqGadget<ConstraintF> for AffineGadget<P, ConstraintF, F>
364where
365    P: SWModelParameters,
366    ConstraintF: Field,
367    F: FieldGadget<P::BaseField, ConstraintF>,
368{
369    #[inline]
370    fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
371        &self,
372        mut cs: CS,
373        other: &Self,
374        condition: &Boolean,
375    ) -> Result<(), SynthesisError> {
376        self.x.conditional_enforce_equal(
377            &mut cs.ns(|| "X Coordinate Conditional Equality"),
378            &other.x,
379            condition,
380        )?;
381        self.y.conditional_enforce_equal(
382            &mut cs.ns(|| "Y Coordinate Conditional Equality"),
383            &other.y,
384            condition,
385        )?;
386        self.infinity.conditional_enforce_equal(
387            &mut cs.ns(|| "Infinity Conditional Equality"),
388            &other.infinity,
389            condition,
390        )?;
391        Ok(())
392    }
393
394    fn cost() -> usize {
395        2 * <F as ConditionalEqGadget<ConstraintF>>::cost()
396    }
397}
398
399impl<P, ConstraintF, F> NEqGadget<ConstraintF> for AffineGadget<P, ConstraintF, F>
400where
401    P: SWModelParameters,
402    ConstraintF: Field,
403    F: FieldGadget<P::BaseField, ConstraintF>,
404{
405    #[inline]
406    fn enforce_not_equal<CS: ConstraintSystem<ConstraintF>>(
407        &self,
408        mut cs: CS,
409        other: &Self,
410    ) -> Result<(), SynthesisError> {
411        self.x
412            .enforce_not_equal(&mut cs.ns(|| "X Coordinate Inequality"), &other.x)?;
413        self.y
414            .enforce_not_equal(&mut cs.ns(|| "Y Coordinate Inequality"), &other.y)?;
415        Ok(())
416    }
417
418    fn cost() -> usize {
419        2 * <F as NEqGadget<ConstraintF>>::cost()
420    }
421}
422
423impl<P, ConstraintF, F> AllocGadget<SWProjective<P>, ConstraintF>
424    for AffineGadget<P, ConstraintF, F>
425where
426    P: SWModelParameters,
427    ConstraintF: Field,
428    F: FieldGadget<P::BaseField, ConstraintF>,
429{
430    #[inline]
431    fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
432        mut cs: CS,
433        value_gen: FN,
434    ) -> Result<Self, SynthesisError>
435    where
436        FN: FnOnce() -> Result<T, SynthesisError>,
437        T: Borrow<SWProjective<P>>,
438    {
439        let (x, y, infinity) = match value_gen() {
440            Ok(ge) => {
441                let ge = ge.borrow().into_affine();
442                (Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
443            },
444            _ => (
445                Err(SynthesisError::AssignmentMissing),
446                Err(SynthesisError::AssignmentMissing),
447                Err(SynthesisError::AssignmentMissing),
448            ),
449        };
450
451        // Perform on-curve check.
452        let b = P::COEFF_B;
453        let a = P::COEFF_A;
454
455        let x = F::alloc(&mut cs.ns(|| "x"), || x)?;
456        let y = F::alloc(&mut cs.ns(|| "y"), || y)?;
457        let infinity = Boolean::alloc(&mut cs.ns(|| "infinity"), || infinity)?;
458
459        // Check that y^2 = x^3 + ax +b
460        // We do this by checking that y^2 - b = x * (x^2 +a)
461        let x2 = x.square(&mut cs.ns(|| "x^2"))?;
462        let y2 = y.square(&mut cs.ns(|| "y^2"))?;
463
464        let x2_plus_a = x2.add_constant(cs.ns(|| "x^2 + a"), &a)?;
465        let y2_minus_b = y2.add_constant(cs.ns(|| "y^2 - b"), &b.neg())?;
466
467        x2_plus_a.mul_equals(cs.ns(|| "on curve check"), &x, &y2_minus_b)?;
468
469        Ok(Self::new(x, y, infinity))
470    }
471
472    #[inline]
473    fn alloc_checked<FN, T, CS: ConstraintSystem<ConstraintF>>(
474        mut cs: CS,
475        value_gen: FN,
476    ) -> Result<Self, SynthesisError>
477    where
478        FN: FnOnce() -> Result<T, SynthesisError>,
479        T: Borrow<SWProjective<P>>,
480    {
481        let cofactor_weight = BitIterator::new(P::COFACTOR).filter(|b| *b).count();
482        // If we multiply by r, we actually multiply by r - 2.
483        let r_minus_1 = (-P::ScalarField::one()).into_repr();
484        let r_weight = BitIterator::new(&r_minus_1).filter(|b| *b).count();
485
486        // We pick the most efficient method of performing the prime order check:
487        // If the cofactor has lower hamming weight than the scalar field's modulus,
488        // we first multiply by the inverse of the cofactor, and then, after allocating,
489        // multiply by the cofactor. This ensures the resulting point has no cofactors
490        //
491        // Else, we multiply by the scalar field's modulus and ensure that the result
492        // is zero.
493        if cofactor_weight < r_weight {
494            let ge = Self::alloc(cs.ns(|| "Alloc checked"), || {
495                value_gen().map(|ge| {
496                    ge.borrow()
497                        .into_affine()
498                        .mul_by_cofactor_inv()
499                        .into_projective()
500                })
501            })?;
502            let mut seen_one = false;
503            let mut result = Self::zero(cs.ns(|| "result"))?;
504            for (i, b) in BitIterator::new(P::COFACTOR).enumerate() {
505                let mut cs = cs.ns(|| format!("Iteration {}", i));
506
507                let old_seen_one = seen_one;
508                if seen_one {
509                    result.double_in_place(cs.ns(|| "Double"))?;
510                } else {
511                    seen_one = b;
512                }
513
514                if b {
515                    result = if old_seen_one {
516                        result.add(cs.ns(|| "Add"), &ge)?
517                    } else {
518                        ge.clone()
519                    };
520                }
521            }
522            Ok(result)
523        } else {
524            let ge = Self::alloc(cs.ns(|| "Alloc checked"), value_gen)?;
525            let mut seen_one = false;
526            let mut result = Self::zero(cs.ns(|| "result"))?;
527            // Returns bits in big-endian order
528            for (i, b) in BitIterator::new(r_minus_1).enumerate() {
529                let mut cs = cs.ns(|| format!("Iteration {}", i));
530
531                let old_seen_one = seen_one;
532                if seen_one {
533                    result.double_in_place(cs.ns(|| "Double"))?;
534                } else {
535                    seen_one = b;
536                }
537
538                if b {
539                    result = if old_seen_one {
540                        result.add(cs.ns(|| "Add"), &ge)?
541                    } else {
542                        ge.clone()
543                    };
544                }
545            }
546            let neg_ge = ge.negate(cs.ns(|| "Negate ge"))?;
547            neg_ge.enforce_equal(cs.ns(|| "Check equals"), &result)?;
548            Ok(ge)
549        }
550    }
551
552    #[inline]
553    fn alloc_input<FN, T, CS: ConstraintSystem<ConstraintF>>(
554        mut cs: CS,
555        value_gen: FN,
556    ) -> Result<Self, SynthesisError>
557    where
558        FN: FnOnce() -> Result<T, SynthesisError>,
559        T: Borrow<SWProjective<P>>,
560    {
561        // When allocating the input we assume that the verifier has performed 
562        // any on curve checks already.
563        let (x, y, infinity) = match value_gen() {
564            Ok(ge) => {
565                let ge = ge.borrow().into_affine();
566                (Ok(ge.x), Ok(ge.y), Ok(ge.infinity))
567            },
568            _ => (
569                Err(SynthesisError::AssignmentMissing),
570                Err(SynthesisError::AssignmentMissing),
571                Err(SynthesisError::AssignmentMissing),
572            ),
573        };
574
575        let x = F::alloc_input(&mut cs.ns(|| "x"), || x)?;
576        let y = F::alloc_input(&mut cs.ns(|| "y"), || y)?;
577        let infinity = Boolean::alloc_input(&mut cs.ns(|| "infinity"), || infinity)?;
578
579        Ok(Self::new(x, y, infinity))
580    }
581}
582
583impl<P, ConstraintF, F> ToBitsGadget<ConstraintF> for AffineGadget<P, ConstraintF, F>
584where
585    P: SWModelParameters,
586    ConstraintF: Field,
587    F: FieldGadget<P::BaseField, ConstraintF>,
588{
589    fn to_bits<CS: ConstraintSystem<ConstraintF>>(
590        &self,
591        mut cs: CS,
592    ) -> Result<Vec<Boolean>, SynthesisError> {
593        let mut x_bits = self.x.to_bits(&mut cs.ns(|| "X Coordinate To Bits"))?;
594        let y_bits = self.y.to_bits(&mut cs.ns(|| "Y Coordinate To Bits"))?;
595        x_bits.extend_from_slice(&y_bits);
596        x_bits.push(self.infinity);
597        Ok(x_bits)
598    }
599
600    fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
601        &self,
602        mut cs: CS,
603    ) -> Result<Vec<Boolean>, SynthesisError> {
604        let mut x_bits = self
605            .x
606            .to_bits_strict(&mut cs.ns(|| "X Coordinate To Bits"))?;
607        let y_bits = self
608            .y
609            .to_bits_strict(&mut cs.ns(|| "Y Coordinate To Bits"))?;
610        x_bits.extend_from_slice(&y_bits);
611        x_bits.push(self.infinity);
612
613        Ok(x_bits)
614    }
615}
616
617impl<P, ConstraintF, F> ToBytesGadget<ConstraintF> for AffineGadget<P, ConstraintF, F>
618where
619    P: SWModelParameters,
620    ConstraintF: Field,
621    F: FieldGadget<P::BaseField, ConstraintF>,
622{
623    fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
624        &self,
625        mut cs: CS,
626    ) -> Result<Vec<UInt8>, SynthesisError> {
627        let mut x_bytes = self.x.to_bytes(&mut cs.ns(|| "X Coordinate To Bytes"))?;
628        let y_bytes = self.y.to_bytes(&mut cs.ns(|| "Y Coordinate To Bytes"))?;
629        let inf_bytes = self.infinity.to_bytes(&mut cs.ns(|| "Infinity to Bytes"))?;
630        x_bytes.extend_from_slice(&y_bytes);
631        x_bytes.extend_from_slice(&inf_bytes);
632        Ok(x_bytes)
633    }
634
635    fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
636        &self,
637        mut cs: CS,
638    ) -> Result<Vec<UInt8>, SynthesisError> {
639        let mut x_bytes = self
640            .x
641            .to_bytes_strict(&mut cs.ns(|| "X Coordinate To Bytes"))?;
642        let y_bytes = self
643            .y
644            .to_bytes_strict(&mut cs.ns(|| "Y Coordinate To Bytes"))?;
645        let inf_bytes = self.infinity.to_bytes(&mut cs.ns(|| "Infinity to Bytes"))?;
646        x_bytes.extend_from_slice(&y_bytes);
647        x_bytes.extend_from_slice(&inf_bytes);
648
649        Ok(x_bytes)
650    }
651}