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