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