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}