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