1#![no_std]
2
3extern crate alloc;
4
5pub mod arith;
6mod fields;
7mod groups;
8
9use crate::fields::FieldElement;
10use crate::groups::{G1Params, G2Params, GroupElement, GroupParams};
11
12use alloc::vec::Vec;
13use core::fmt::Display;
14use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
15use num_bigint::BigUint;
16use rand::Rng;
17
18#[derive(Copy, Clone, Debug, PartialEq, Eq)]
19#[repr(C)]
20pub struct Fr(fields::Fr);
21
22impl Fr {
23 pub fn zero() -> Self {
24 Fr(fields::Fr::zero())
25 }
26 pub fn one() -> Self {
27 Fr(fields::Fr::one())
28 }
29 pub fn random<R: Rng>(rng: &mut R) -> Self {
30 Fr(fields::Fr::random(rng))
31 }
32 pub fn pow(&self, exp: Fr) -> Self {
33 Fr(self.0.pow(exp.0))
34 }
35 #[allow(clippy::should_implement_trait)]
36 pub fn from_str(s: &str) -> Option<Self> {
37 fields::Fr::from_str(s).map(Fr)
38 }
39 pub fn inverse(&self) -> Option<Self> {
40 self.0.inverse().map(Fr)
41 }
42 pub fn is_zero(&self) -> bool {
43 self.0.is_zero()
44 }
45 pub fn interpret(buf: &[u8; 64]) -> Fr {
46 Fr(fields::Fr::interpret(buf))
47 }
48 pub fn from_slice(slice: &[u8]) -> Result<Self, FieldError> {
49 arith::U256::from_slice(slice)
50 .map_err(|_| FieldError::InvalidSliceLength) .map(Fr::new_mul_factor)
52 }
53 pub fn from_bytes_be_mod_order(slice: &[u8]) -> Result<Self, FieldError> {
54 let mut modulus_bytes = [0u8; 32];
55 Fr::modulus().to_big_endian(&mut modulus_bytes).unwrap();
56 let modulus = BigUint::from_bytes_be(&modulus_bytes);
57
58 let num = BigUint::from_bytes_be(slice) % modulus;
59
60 Fr::from_slice(&num.to_bytes_be())
61 }
62 pub fn to_big_endian(&self, slice: &mut [u8]) -> Result<(), FieldError> {
63 self.0
65 .to_mont()
66 .to_big_endian(slice)
67 .map_err(|_| FieldError::InvalidSliceLength)
68 }
69 pub fn new(val: arith::U256) -> Option<Self> {
70 fields::Fr::new(val).map(Fr)
71 }
72 pub fn new_mul_factor(val: arith::U256) -> Self {
73 Fr(fields::Fr::new_mul_factor(val))
74 }
75 pub fn modulus() -> arith::U256 {
76 fields::Fr::modulus()
77 }
78 pub fn into_u256(self) -> arith::U256 {
79 (self.0).into()
80 }
81 pub fn set_bit(&mut self, bit: usize, to: bool) {
82 self.0.set_bit(bit, to);
83 }
84}
85
86impl Add<Fr> for Fr {
87 type Output = Fr;
88
89 fn add(self, other: Fr) -> Fr {
90 Fr(self.0 + other.0)
91 }
92}
93
94impl Sub<Fr> for Fr {
95 type Output = Fr;
96
97 fn sub(self, other: Fr) -> Fr {
98 Fr(self.0 - other.0)
99 }
100}
101
102impl Neg for Fr {
103 type Output = Fr;
104
105 fn neg(self) -> Fr {
106 Fr(-self.0)
107 }
108}
109
110impl Mul for Fr {
111 type Output = Fr;
112
113 fn mul(self, other: Fr) -> Fr {
114 Fr(self.0 * other.0)
115 }
116}
117
118impl Div for Fr {
119 type Output = Fr;
120
121 fn div(self, other: Fr) -> Fr {
122 Fr(self.0 / other.0)
123 }
124}
125
126impl AddAssign<Fr> for Fr {
127 fn add_assign(&mut self, other: Fr) {
128 *self = *self + other;
129 }
130}
131
132impl SubAssign<Fr> for Fr {
133 fn sub_assign(&mut self, other: Fr) {
134 *self = *self - other;
135 }
136}
137
138impl MulAssign<Fr> for Fr {
139 fn mul_assign(&mut self, other: Fr) {
140 *self = *self * other;
141 }
142}
143
144impl DivAssign<Fr> for Fr {
145 fn div_assign(&mut self, other: Fr) {
146 *self = *self / other;
147 }
148}
149
150#[derive(Debug)]
151pub enum FieldError {
152 InvalidSliceLength,
153 InvalidU512Encoding,
154 NotMember,
155}
156
157impl Display for FieldError {
158 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
159 match *self {
160 FieldError::InvalidSliceLength => write!(f, "Invalid slice length"),
161 FieldError::InvalidU512Encoding => write!(f, "Invalid U512 encoding"),
162 FieldError::NotMember => write!(f, "Not a member of the field"),
163 }
164 }
165}
166
167#[derive(Debug)]
168pub enum CurveError {
169 InvalidEncoding,
170 NotMember,
171 Field(FieldError),
172 ToAffineConversion,
173}
174
175impl Display for CurveError {
176 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177 match self {
178 CurveError::InvalidEncoding => write!(f, "Invalid encoding"),
179 CurveError::NotMember => write!(f, "Not a member of the curve"),
180 CurveError::Field(fe) => write!(f, "Field error: {:?}", fe),
181 CurveError::ToAffineConversion => write!(f, "Failed to convert to affine coordinates"),
182 }
183 }
184}
185
186impl From<FieldError> for CurveError {
187 fn from(fe: FieldError) -> Self {
188 CurveError::Field(fe)
189 }
190}
191
192pub use crate::groups::Error as GroupError;
193
194#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)]
195#[repr(C)]
196pub struct Fq(pub fields::Fq);
197
198impl Fq {
199 pub fn zero() -> Self {
200 Fq(fields::Fq::zero())
201 }
202 pub fn one() -> Self {
203 Fq(fields::Fq::one())
204 }
205 pub fn random<R: Rng>(rng: &mut R) -> Self {
206 Fq(fields::Fq::random(rng))
207 }
208 pub fn pow(&self, exp: Fq) -> Self {
209 Fq(self.0.pow(exp.0))
210 }
211 #[allow(clippy::should_implement_trait)]
212 pub fn from_str(s: &str) -> Option<Self> {
213 fields::Fq::from_str(s).map(Fq)
214 }
215 pub fn inverse(&self) -> Option<Self> {
216 self.0.inverse().map(Fq)
217 }
218 pub fn is_zero(&self) -> bool {
219 self.0.is_zero()
220 }
221 pub fn interpret(buf: &[u8; 64]) -> Fq {
222 Fq(fields::Fq::interpret(buf))
223 }
224 pub fn from_slice(slice: &[u8]) -> Result<Self, FieldError> {
225 arith::U256::from_slice(slice)
226 .map_err(|_| FieldError::InvalidSliceLength) .and_then(|x| fields::Fq::new(x).ok_or(FieldError::NotMember))
228 .map(Fq)
229 }
230 pub fn from_be_bytes_mod_order(bytes: &[u8]) -> Result<Self, FieldError> {
231 let mut modulus_bytes = [0u8; 32];
232 Fq::modulus().to_big_endian(&mut modulus_bytes).unwrap();
233 let modulus = BigUint::from_bytes_be(&modulus_bytes);
234
235 let num = BigUint::from_bytes_be(bytes) % modulus;
236
237 Fq::from_slice(&num.to_bytes_be())
238 }
239
240 pub fn to_mont_big_endian(&self, slice: &mut [u8]) -> Result<(), FieldError> {
241 let a: arith::U256 = self.0.to_mont().into();
242 a.to_big_endian(slice)
243 .map_err(|_| FieldError::InvalidSliceLength)
244 }
245
246 pub fn to_big_endian(&self, slice: &mut [u8]) -> Result<(), FieldError> {
247 let a: arith::U256 = self.0.into();
248 a.to_big_endian(slice)
249 .map_err(|_| FieldError::InvalidSliceLength)
250 }
251
252 pub fn from_u256(u256: arith::U256) -> Result<Self, FieldError> {
253 Ok(Fq(fields::Fq::new(u256).ok_or(FieldError::NotMember)?))
254 }
255 pub fn into_u256(self) -> arith::U256 {
256 (self.0).into()
257 }
258 pub fn modulus() -> arith::U256 {
259 fields::Fq::modulus()
260 }
261
262 pub fn sqrt(&self) -> Option<Self> {
263 self.0.sqrt().map(Fq)
264 }
265}
266
267impl Add<Fq> for Fq {
268 type Output = Fq;
269
270 fn add(self, other: Fq) -> Fq {
271 Fq(self.0 + other.0)
272 }
273}
274
275impl Sub<Fq> for Fq {
276 type Output = Fq;
277
278 fn sub(self, other: Fq) -> Fq {
279 Fq(self.0 - other.0)
280 }
281}
282
283impl Neg for Fq {
284 type Output = Fq;
285
286 fn neg(self) -> Fq {
287 Fq(-self.0)
288 }
289}
290
291impl Mul for Fq {
292 type Output = Fq;
293
294 fn mul(self, other: Fq) -> Fq {
295 Fq(self.0 * other.0)
296 }
297}
298
299impl Ord for Fq {
300 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
301 self.0.cmp(&other.0)
302 }
303}
304
305#[derive(Copy, Clone, Debug, PartialEq, Eq)]
306#[repr(C)]
307pub struct Fq2(pub fields::Fq2);
308
309impl Fq2 {
310 pub fn one() -> Fq2 {
311 Fq2(fields::Fq2::one())
312 }
313
314 pub fn i() -> Fq2 {
315 Fq2(fields::Fq2::i())
316 }
317
318 pub fn zero() -> Fq2 {
319 Fq2(fields::Fq2::zero())
320 }
321
322 pub fn new(a: Fq, b: Fq) -> Fq2 {
324 Fq2(fields::Fq2::new(a.0, b.0))
325 }
326
327 pub fn is_zero(&self) -> bool {
328 self.0.is_zero()
329 }
330
331 pub fn pow(&self, exp: arith::U256) -> Self {
332 Fq2(self.0.pow(exp))
333 }
334
335 pub fn real(&self) -> Fq {
336 Fq(*self.0.real())
337 }
338
339 pub fn imaginary(&self) -> Fq {
340 Fq(*self.0.imaginary())
341 }
342
343 pub fn sqrt(&self) -> Option<Self> {
344 self.0.sqrt().map(Fq2)
345 }
346
347 pub fn from_slice(bytes: &[u8]) -> Result<Self, FieldError> {
348 let u512 = arith::U512::from_slice(bytes).map_err(|_| FieldError::InvalidU512Encoding)?;
349 let (res, c0) = u512.divrem(&Fq::modulus());
350 Ok(Fq2::new(
351 Fq::from_u256(c0).map_err(|_| FieldError::NotMember)?,
352 Fq::from_u256(res.ok_or(FieldError::NotMember)?).map_err(|_| FieldError::NotMember)?,
353 ))
354 }
355}
356
357impl Add<Fq2> for Fq2 {
358 type Output = Self;
359
360 fn add(self, other: Self) -> Self {
361 Fq2(self.0 + other.0)
362 }
363}
364
365impl Sub<Fq2> for Fq2 {
366 type Output = Self;
367
368 fn sub(self, other: Self) -> Self {
369 Fq2(self.0 - other.0)
370 }
371}
372
373impl Neg for Fq2 {
374 type Output = Self;
375
376 fn neg(self) -> Self {
377 Fq2(-self.0)
378 }
379}
380
381impl Mul for Fq2 {
382 type Output = Self;
383
384 fn mul(self, other: Self) -> Self {
385 Fq2(self.0 * other.0)
386 }
387}
388
389impl Div for Fq2 {
390 type Output = Self;
391
392 fn div(self, other: Self) -> Self {
393 Fq2(self.0 / other.0)
394 }
395}
396
397pub trait Group:
398 Send
399 + Sync
400 + Copy
401 + Clone
402 + PartialEq
403 + Eq
404 + Sized
405 + Add<Self, Output = Self>
406 + Sub<Self, Output = Self>
407 + Neg<Output = Self>
408 + Mul<Fr, Output = Self>
409{
410 fn zero() -> Self;
411 fn one() -> Self;
412 fn random<R: Rng>(rng: &mut R) -> Self;
413 fn is_zero(&self) -> bool;
414 fn normalize(&mut self);
415}
416
417#[derive(Copy, Clone, Debug, PartialEq, Eq)]
418#[repr(C)]
419pub struct G1(groups::G1);
420
421impl G1 {
422 pub fn new(x: Fq, y: Fq, z: Fq) -> Self {
423 G1(groups::G1::new(x.0, y.0, z.0))
424 }
425
426 pub fn zero() -> Self {
427 G1(groups::G1::zero())
428 }
429
430 pub fn x(&self) -> Fq {
431 Fq(*self.0.x())
432 }
433
434 pub fn set_x(&mut self, x: Fq) {
435 *self.0.x_mut() = x.0
436 }
437
438 pub fn y(&self) -> Fq {
439 Fq(*self.0.y())
440 }
441
442 pub fn set_y(&mut self, y: Fq) {
443 *self.0.y_mut() = y.0
444 }
445
446 pub fn z(&self) -> Fq {
447 Fq(*self.0.z())
448 }
449
450 pub fn set_z(&mut self, z: Fq) {
451 *self.0.z_mut() = z.0
452 }
453
454 pub fn b() -> Fq {
455 Fq(G1Params::coeff_b())
456 }
457
458 pub fn from_compressed(bytes: &[u8]) -> Result<Self, CurveError> {
459 if bytes.len() != 33 {
460 return Err(CurveError::InvalidEncoding);
461 }
462
463 let sign = bytes[0];
464 let fq = Fq::from_slice(&bytes[1..])?;
465 let x = fq;
466 let y_squared = (fq * fq * fq) + Self::b();
467
468 let mut y = y_squared.sqrt().ok_or(CurveError::NotMember)?;
469
470 if (sign == 2 && y.into_u256().get_bit(0).expect("bit 0 always exist; qed"))
471 || (sign == 3 && !y.into_u256().get_bit(0).expect("bit 0 always exist; qed"))
472 {
473 y = y.neg();
474 } else if sign != 3 && sign != 2 {
475 return Err(CurveError::InvalidEncoding);
476 }
477 AffineG1::new(x, y)
478 .map_err(|_| CurveError::NotMember)
479 .map(Into::into)
480 }
481
482 pub fn msm(points: &[Self], scalars: &[Fr]) -> Self {
483 G1(groups::G1::msm_variable_base(
484 &points.iter().map(|p| p.0).collect::<Vec<_>>(),
485 &scalars.iter().map(|x| x.0).collect::<Vec<_>>(),
486 ))
487 }
488
489 pub fn double(&self) -> Self {
490 G1(self.0.double())
491 }
492}
493
494impl Group for G1 {
495 fn zero() -> Self {
496 G1(groups::G1::zero())
497 }
498 fn one() -> Self {
499 G1(groups::G1::one())
500 }
501 fn random<R: Rng>(rng: &mut R) -> Self {
502 G1(groups::G1::random(rng))
503 }
504 fn is_zero(&self) -> bool {
505 self.0.is_zero()
506 }
507 fn normalize(&mut self) {
508 let new = match self.0.to_affine() {
509 Some(a) => a,
510 None => return,
511 };
512
513 self.0 = new.to_jacobian();
514 }
515}
516
517impl Add<G1> for G1 {
518 type Output = G1;
519
520 fn add(self, other: G1) -> G1 {
521 G1(self.0 + other.0)
522 }
523}
524
525impl Sub<G1> for G1 {
526 type Output = G1;
527
528 fn sub(self, other: G1) -> G1 {
529 G1(self.0 - other.0)
530 }
531}
532
533impl Neg for G1 {
534 type Output = G1;
535
536 fn neg(self) -> G1 {
537 G1(-self.0)
538 }
539}
540
541impl Mul<Fr> for G1 {
542 type Output = G1;
543
544 fn mul(self, other: Fr) -> G1 {
545 G1(self.0 * other.0)
546 }
547}
548
549#[derive(Copy, Clone, Debug, PartialEq, Eq)]
550#[repr(C)]
551pub struct AffineG1(groups::AffineG1);
552
553impl Default for AffineG1 {
554 fn default() -> Self {
555 AffineG1(groups::AffineG::one())
556 }
557}
558
559impl AffineG1 {
560 pub fn new(x: Fq, y: Fq) -> Result<Self, GroupError> {
561 Ok(AffineG1(groups::AffineG1::new(x.0, y.0)?))
562 }
563
564 pub fn new_unchecked(x: Fq, y: Fq) -> Self {
565 AffineG1(groups::AffineG1::new_unchecked(x.0, y.0))
566 }
567
568 pub fn zero() -> Self {
569 AffineG1(groups::AffineG1::zero())
570 }
571
572 pub fn one() -> Self {
573 AffineG1(groups::AffineG1::one())
574 }
575
576 pub fn x(&self) -> Fq {
577 Fq(*self.0.x())
578 }
579
580 pub fn set_x(&mut self, x: Fq) {
581 *self.0.x_mut() = x.0
582 }
583
584 pub fn y(&self) -> Fq {
585 Fq(*self.0.y())
586 }
587
588 pub fn set_y(&mut self, y: Fq) {
589 *self.0.y_mut() = y.0
590 }
591
592 pub fn from_jacobian(g1: G1) -> Option<Self> {
593 g1.0.to_affine().map(AffineG1)
594 }
595
596 pub fn get_ys_from_x_unchecked(x: Fq) -> Option<(Fq, Fq)> {
597 groups::AffineG1::get_ys_from_x_unchecked(x.0).map(|(neq_y, y)| (Fq(neq_y), Fq(y)))
598 }
599
600 pub fn msm(points: &[Self], scalars: &[Fr]) -> Self {
601 AffineG1(groups::AffineG1::msm_variable_base(
602 &points.iter().map(|p| p.0).collect::<Vec<_>>(),
603 &scalars.iter().map(|x| x.0).collect::<Vec<_>>(),
604 ))
605 }
606}
607
608impl Neg for AffineG1 {
609 type Output = AffineG1;
610
611 fn neg(self) -> AffineG1 {
612 AffineG1(-self.0)
613 }
614}
615
616impl Into<G1> for AffineG1 {
617 fn into(self) -> G1 {
618 G1(self.0.to_jacobian())
619 }
620}
621
622impl Into<AffineG1> for G1 {
623 fn into(self) -> AffineG1 {
624 AffineG1(
625 self.0
626 .to_affine()
627 .expect("Unable to convert G1 to AffineG1"),
628 )
629 }
630}
631
632impl Add<AffineG1> for AffineG1 {
633 type Output = AffineG1;
634
635 fn add(self, other: AffineG1) -> AffineG1 {
636 AffineG1(self.0 + other.0)
637 }
638}
639
640impl Sub<AffineG1> for AffineG1 {
641 type Output = AffineG1;
642
643 fn sub(self, other: AffineG1) -> AffineG1 {
644 AffineG1(self.0 - other.0)
645 }
646}
647
648impl Mul<Fr> for AffineG1 {
649 type Output = AffineG1;
650
651 fn mul(self, other: Fr) -> AffineG1 {
652 AffineG1(self.0 * other.0)
653 }
654}
655
656#[derive(Copy, Clone, Debug, PartialEq, Eq)]
657#[repr(C)]
658pub struct G2(groups::G2);
659
660impl G2 {
661 pub fn new(x: Fq2, y: Fq2, z: Fq2) -> Self {
662 G2(groups::G2::new(x.0, y.0, z.0))
663 }
664
665 pub fn x(&self) -> Fq2 {
666 Fq2(*self.0.x())
667 }
668
669 pub fn set_x(&mut self, x: Fq2) {
670 *self.0.x_mut() = x.0
671 }
672
673 pub fn y(&self) -> Fq2 {
674 Fq2(*self.0.y())
675 }
676
677 pub fn set_y(&mut self, y: Fq2) {
678 *self.0.y_mut() = y.0
679 }
680
681 pub fn z(&self) -> Fq2 {
682 Fq2(*self.0.z())
683 }
684
685 pub fn set_z(&mut self, z: Fq2) {
686 *self.0.z_mut() = z.0
687 }
688
689 pub fn b() -> Fq2 {
690 Fq2(G2Params::coeff_b())
691 }
692
693 pub fn from_compressed(bytes: &[u8]) -> Result<Self, CurveError> {
694 if bytes.len() != 65 {
695 return Err(CurveError::InvalidEncoding);
696 }
697
698 let sign = bytes[0];
699 let x = Fq2::from_slice(&bytes[1..])?;
700
701 let y_squared = (x * x * x) + G2::b();
702 let y = y_squared.sqrt().ok_or(CurveError::NotMember)?;
703 let y_neg = -y;
704 let y_gt = y.0.to_u512() > y_neg.0.to_u512();
705
706 let e_y = if sign == 10 {
707 if y_gt {
708 y_neg
709 } else {
710 y
711 }
712 } else if sign == 11 {
713 if y_gt {
714 y
715 } else {
716 y_neg
717 }
718 } else {
719 return Err(CurveError::InvalidEncoding);
720 };
721
722 AffineG2::new(x, e_y)
723 .map_err(|_| CurveError::NotMember)
724 .map(Into::into)
725 }
726}
727
728impl Group for G2 {
729 fn zero() -> Self {
730 G2(groups::G2::zero())
731 }
732 fn one() -> Self {
733 G2(groups::G2::one())
734 }
735 fn random<R: Rng>(rng: &mut R) -> Self {
736 G2(groups::G2::random(rng))
737 }
738 fn is_zero(&self) -> bool {
739 self.0.is_zero()
740 }
741 fn normalize(&mut self) {
742 let new = match self.0.to_affine() {
743 Some(a) => a,
744 None => return,
745 };
746
747 self.0 = new.to_jacobian();
748 }
749}
750
751impl Add<G2> for G2 {
752 type Output = G2;
753
754 fn add(self, other: G2) -> G2 {
755 G2(self.0 + other.0)
756 }
757}
758
759impl Sub<G2> for G2 {
760 type Output = G2;
761
762 fn sub(self, other: G2) -> G2 {
763 G2(self.0 - other.0)
764 }
765}
766
767impl Neg for G2 {
768 type Output = G2;
769
770 fn neg(self) -> G2 {
771 G2(-self.0)
772 }
773}
774
775impl Mul<Fr> for G2 {
776 type Output = G2;
777
778 fn mul(self, other: Fr) -> G2 {
779 G2(self.0 * other.0)
780 }
781}
782
783#[derive(Copy, Clone, Debug, PartialEq, Eq)]
784#[repr(C)]
785pub struct Gt(fields::Fq12);
786
787impl Gt {
788 pub fn zero() -> Self {
789 Gt(fields::Fq12::zero())
790 }
791 pub fn one() -> Self {
792 Gt(fields::Fq12::one())
793 }
794 pub fn pow(&self, exp: Fr) -> Self {
795 Gt(self.0.pow(exp.0))
796 }
797 pub fn inverse(&self) -> Option<Self> {
798 self.0.inverse().map(Gt)
799 }
800 pub fn final_exponentiation(&self) -> Option<Self> {
801 self.0.final_exponentiation().map(Gt)
802 }
803 pub fn is_zero(&self) -> bool {
804 self.0.is_zero()
805 }
806 pub fn is_one(&self) -> bool {
807 self == &Gt::one()
808 }
809}
810
811impl Mul<Gt> for Gt {
812 type Output = Gt;
813
814 fn mul(self, other: Gt) -> Gt {
815 Gt(self.0 * other.0)
816 }
817}
818
819pub fn pairing(p: G1, q: G2) -> Gt {
820 Gt(groups::pairing(&p.0, &q.0))
821}
822
823pub fn pairing_batch(pairs: &[(G1, G2)]) -> Gt {
824 let mut ps: Vec<groups::G1> = Vec::new();
825 let mut qs: Vec<groups::G2> = Vec::new();
826 for (p, q) in pairs {
827 ps.push(p.0);
828 qs.push(q.0);
829 }
830 Gt(groups::pairing_batch(&ps, &qs))
831}
832
833pub fn miller_loop_batch(pairs: &[(G2, G1)]) -> Result<Gt, CurveError> {
834 let mut ps: Vec<groups::G2Precomp> = Vec::new();
835 let mut qs: Vec<groups::AffineG<groups::G1Params>> = Vec::new();
836 for (p, q) in pairs {
837 ps.push(
838 p.0.to_affine()
839 .ok_or(CurveError::ToAffineConversion)?
840 .precompute(),
841 );
842 qs.push(q.0.to_affine().ok_or(CurveError::ToAffineConversion)?);
843 }
844 Ok(Gt(groups::miller_loop_batch(&ps, &qs)))
845}
846
847#[derive(Copy, Clone, PartialEq, Eq, Debug)]
848#[repr(C)]
849pub struct AffineG2(groups::AffineG2);
850
851impl AffineG2 {
852 pub fn zero() -> Self {
853 AffineG2(groups::AffineG2::zero())
854 }
855
856 pub fn one() -> Self {
857 AffineG2(groups::AffineG2::one())
858 }
859
860 pub fn new(x: Fq2, y: Fq2) -> Result<Self, GroupError> {
861 Ok(AffineG2(groups::AffineG2::new(x.0, y.0)?))
862 }
863
864 pub fn new_unchecked(x: Fq2, y: Fq2) -> Self {
865 AffineG2(groups::AffineG2::new_unchecked(x.0, y.0))
866 }
867
868 pub fn x(&self) -> Fq2 {
869 Fq2(*self.0.x())
870 }
871
872 pub fn set_x(&mut self, x: Fq2) {
873 *self.0.x_mut() = x.0
874 }
875
876 pub fn y(&self) -> Fq2 {
877 Fq2(*self.0.y())
878 }
879
880 pub fn set_y(&mut self, y: Fq2) {
881 *self.0.y_mut() = y.0
882 }
883
884 pub fn from_jacobian(g2: G2) -> Option<Self> {
885 g2.0.to_affine().map(AffineG2)
886 }
887
888 pub fn get_ys_from_x_unchecked(x: Fq2) -> Option<(Fq2, Fq2)> {
889 groups::AffineG2::get_ys_from_x_unchecked(x.0).map(|(neq_y, y)| (Fq2(neq_y), Fq2(y)))
890 }
891}
892
893impl Neg for AffineG2 {
894 type Output = AffineG2;
895
896 fn neg(self) -> AffineG2 {
897 AffineG2(-self.0)
898 }
899}
900
901impl From<AffineG2> for G2 {
902 fn from(affine: AffineG2) -> Self {
903 G2(affine.0.to_jacobian())
904 }
905}
906
907impl From<G2> for AffineG2 {
908 fn from(g2: G2) -> Self {
909 AffineG2::new(g2.x() / g2.z(), g2.y() / g2.z()).expect("Unable to convert G2 to AffineG2")
910 }
911}
912
913#[cfg(test)]
914mod tests {
915 use super::{Fq, Fq2, G1, G2};
916 use alloc::vec::Vec;
917
918 fn hex(s: &'static str) -> Vec<u8> {
919 use rustc_hex::FromHex;
920 s.from_hex().unwrap()
921 }
922
923 #[test]
924 fn g1_from_compressed() {
925 let g1 = G1::from_compressed(&hex(
926 "0230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46",
927 ))
928 .expect("Invalid g1 decompress result");
929 assert_eq!(
930 g1.x(),
931 Fq::from_str(
932 "21888242871839275222246405745257275088696311157297823662689037894645226208582"
933 )
934 .unwrap()
935 );
936 assert_eq!(
937 g1.y(),
938 Fq::from_str(
939 "3969792565221544645472939191694882283483352126195956956354061729942568608776"
940 )
941 .unwrap()
942 );
943 assert_eq!(g1.z(), Fq::one());
944 }
945
946 #[test]
947 fn g2_from_compressed() {
948 let g2 = G2::from_compressed(
949 &hex("0a023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a")
950 ).expect("Valid g2 point hex encoding");
951
952 assert_eq!(
953 g2.x(),
954 Fq2::new(
955 Fq::from_str(
956 "5923585509243758863255447226263146374209884951848029582715967108651637186684"
957 )
958 .unwrap(),
959 Fq::from_str(
960 "5336385337059958111259504403491065820971993066694750945459110579338490853570"
961 )
962 .unwrap(),
963 )
964 );
965
966 assert_eq!(
967 g2.y(),
968 Fq2::new(
969 Fq::from_str(
970 "10374495865873200088116930399159835104695426846400310764827677226300185211748"
971 )
972 .unwrap(),
973 Fq::from_str(
974 "5256529835065685814318509161957442385362539991735248614869838648137856366932"
975 )
976 .unwrap(),
977 )
978 );
979
980 let g2 = -G2::from_compressed(
982 &hex("0b023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a")
983 ).expect("Valid g2 point hex encoding");
984
985 assert_eq!(
986 g2.x(),
987 Fq2::new(
988 Fq::from_str(
989 "5923585509243758863255447226263146374209884951848029582715967108651637186684"
990 )
991 .unwrap(),
992 Fq::from_str(
993 "5336385337059958111259504403491065820971993066694750945459110579338490853570"
994 )
995 .unwrap(),
996 )
997 );
998
999 assert_eq!(
1000 g2.y(),
1001 Fq2::new(
1002 Fq::from_str(
1003 "10374495865873200088116930399159835104695426846400310764827677226300185211748"
1004 )
1005 .unwrap(),
1006 Fq::from_str(
1007 "5256529835065685814318509161957442385362539991735248614869838648137856366932"
1008 )
1009 .unwrap(),
1010 )
1011 );
1012
1013 assert!(
1015 G2::from_compressed(
1016 &hex("0c023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a")
1017 ).is_err()
1018 );
1019 }
1020}