Skip to main content

substrate_bn_succinct_rs/
lib.rs

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) // todo: maybe more sensful error handling
51            .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        // NOTE: serialized in Montgomery form (as in the original bn crate)
64        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) // todo: maybe more sensful error handling
227            .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    /// Initalizes new F_q2(a + bi, a is real coeff, b is imaginary)
323    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        // 0b prefix is point reflection on the curve
981        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        // valid point but invalid sign prefix
1014        assert!(
1015            G2::from_compressed(
1016                &hex("0c023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a")
1017            ).is_err()
1018        );
1019    }
1020}