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 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: 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}