zeropool_bn/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3extern crate byteorder;
4#[macro_use]
5extern crate crunchy;
6#[cfg(feature = "borsh")]
7extern crate borsh;
8extern crate rand;
9#[macro_use]
10extern crate lazy_static;
11
12#[macro_use]
13#[cfg(not(feature = "std"))]
14extern crate alloc;
15#[cfg(feature = "std")]
16extern crate std as alloc;
17
18pub mod arith;
19mod fields;
20mod groups;
21
22#[cfg(feature = "borsh")]
23use borsh::{BorshDeserialize, BorshSerialize};
24use fields::FieldElement;
25use groups::{G1Params, G2Params, GroupElement, GroupParams};
26
27use alloc::vec::Vec;
28use rand::Rng;
29use core::ops::{Add, Mul, Neg, Sub};
30
31#[derive(Copy, Clone, Debug, PartialEq, Eq)]
32#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
33#[repr(C)]
34pub struct Fr(fields::Fr);
35
36impl Fr {
37    pub fn zero() -> Self {
38        Fr(fields::Fr::zero())
39    }
40    pub fn one() -> Self {
41        Fr(fields::Fr::one())
42    }
43    pub fn random<R: Rng>(rng: &mut R) -> Self {
44        Fr(fields::Fr::random(rng))
45    }
46    pub fn pow(&self, exp: Fr) -> Self {
47        Fr(self.0.pow(exp.0))
48    }
49    pub fn from_str(s: &str) -> Option<Self> {
50        fields::Fr::from_str(s).map(|e| Fr(e))
51    }
52    pub fn inverse(&self) -> Option<Self> {
53        self.0.inverse().map(|e| Fr(e))
54    }
55    pub fn is_zero(&self) -> bool {
56        self.0.is_zero()
57    }
58    pub fn interpret(buf: &[u8; 64]) -> Fr {
59        Fr(fields::Fr::interpret(buf))
60    }
61    pub fn from_slice(slice: &[u8]) -> Result<Self, FieldError> {
62        arith::U256::from_slice(slice)
63            .map_err(|_| FieldError::InvalidSliceLength) // todo: maybe more sensful error handling
64            .map(|x| Fr::new_mul_factor(x))
65    }
66    pub fn to_big_endian(&self, slice: &mut [u8]) -> Result<(), FieldError> {
67        self.0
68            .raw()
69            .to_big_endian(slice)
70            .map_err(|_| FieldError::InvalidSliceLength)
71    }
72    pub fn new(val: arith::U256) -> Option<Self> {
73        fields::Fr::new(val).map(|x| Fr(x))
74    }
75    pub fn new_mul_factor(val: arith::U256) -> Self {
76        Fr(fields::Fr::new_mul_factor(val))
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
118#[derive(Debug)]
119pub enum FieldError {
120    InvalidSliceLength,
121    InvalidU512Encoding,
122    NotMember,
123}
124
125#[derive(Debug)]
126pub enum CurveError {
127    InvalidEncoding,
128    NotMember,
129    Field(FieldError),
130    ToAffineConversion,
131}
132
133impl From<FieldError> for CurveError {
134    fn from(fe: FieldError) -> Self {
135        CurveError::Field(fe)
136    }
137}
138
139pub use groups::Error as GroupError;
140
141#[derive(Copy, Clone, Debug, PartialEq, Eq)]
142#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
143#[repr(C)]
144pub struct Fq(fields::Fq);
145
146impl Fq {
147    pub fn zero() -> Self {
148        Fq(fields::Fq::zero())
149    }
150    pub fn one() -> Self {
151        Fq(fields::Fq::one())
152    }
153    pub fn random<R: Rng>(rng: &mut R) -> Self {
154        Fq(fields::Fq::random(rng))
155    }
156    pub fn pow(&self, exp: Fq) -> Self {
157        Fq(self.0.pow(exp.0))
158    }
159    pub fn from_str(s: &str) -> Option<Self> {
160        fields::Fq::from_str(s).map(|e| Fq(e))
161    }
162    pub fn inverse(&self) -> Option<Self> {
163        self.0.inverse().map(|e| Fq(e))
164    }
165    pub fn is_zero(&self) -> bool {
166        self.0.is_zero()
167    }
168    pub fn interpret(buf: &[u8; 64]) -> Fq {
169        Fq(fields::Fq::interpret(buf))
170    }
171    pub fn from_slice(slice: &[u8]) -> Result<Self, FieldError> {
172        arith::U256::from_slice(slice)
173            .map_err(|_| FieldError::InvalidSliceLength) // todo: maybe more sensful error handling
174            .and_then(|x| fields::Fq::new(x).ok_or(FieldError::NotMember))
175            .map(|x| Fq(x))
176    }
177    pub fn to_big_endian(&self, slice: &mut [u8]) -> Result<(), FieldError> {
178        let mut a: arith::U256 = self.0.into();
179        // convert from Montgomery representation
180        a.mul(
181            &fields::Fq::one().raw(),
182            &fields::Fq::modulus(),
183            self.0.inv(),
184        );
185        a.to_big_endian(slice)
186            .map_err(|_| FieldError::InvalidSliceLength)
187    }
188    pub fn from_u256(u256: arith::U256) -> Result<Self, FieldError> {
189        Ok(Fq(fields::Fq::new(u256).ok_or(FieldError::NotMember)?))
190    }
191    pub fn into_u256(self) -> arith::U256 {
192        (self.0).into()
193    }
194    pub fn modulus() -> arith::U256 {
195        fields::Fq::modulus()
196    }
197
198    pub fn sqrt(&self) -> Option<Self> {
199        self.0.sqrt().map(Fq)
200    }
201}
202
203impl Add<Fq> for Fq {
204    type Output = Fq;
205
206    fn add(self, other: Fq) -> Fq {
207        Fq(self.0 + other.0)
208    }
209}
210
211impl Sub<Fq> for Fq {
212    type Output = Fq;
213
214    fn sub(self, other: Fq) -> Fq {
215        Fq(self.0 - other.0)
216    }
217}
218
219impl Neg for Fq {
220    type Output = Fq;
221
222    fn neg(self) -> Fq {
223        Fq(-self.0)
224    }
225}
226
227impl Mul for Fq {
228    type Output = Fq;
229
230    fn mul(self, other: Fq) -> Fq {
231        Fq(self.0 * other.0)
232    }
233}
234
235#[derive(Copy, Clone, Debug, PartialEq, Eq)]
236#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
237#[repr(C)]
238pub struct Fq2(fields::Fq2);
239
240impl Fq2 {
241    pub fn one() -> Fq2 {
242        Fq2(fields::Fq2::one())
243    }
244
245    pub fn i() -> Fq2 {
246        Fq2(fields::Fq2::i())
247    }
248
249    pub fn zero() -> Fq2 {
250        Fq2(fields::Fq2::zero())
251    }
252
253    /// Initalizes new F_q2(a + bi, a is real coeff, b is imaginary)
254    pub fn new(a: Fq, b: Fq) -> Fq2 {
255        Fq2(fields::Fq2::new(a.0, b.0))
256    }
257
258    pub fn is_zero(&self) -> bool {
259        self.0.is_zero()
260    }
261
262    pub fn pow(&self, exp: arith::U256) -> Self {
263        Fq2(self.0.pow(exp))
264    }
265
266    pub fn real(&self) -> Fq {
267        Fq(*self.0.real())
268    }
269
270    pub fn imaginary(&self) -> Fq {
271        Fq(*self.0.imaginary())
272    }
273
274    pub fn sqrt(&self) -> Option<Self> {
275        self.0.sqrt().map(Fq2)
276    }
277
278    pub fn from_slice(bytes: &[u8]) -> Result<Self, FieldError> {
279        let u512 = arith::U512::from_slice(bytes).map_err(|_| FieldError::InvalidU512Encoding)?;
280        let (res, c0) = u512.divrem(&Fq::modulus());
281        Ok(Fq2::new(
282            Fq::from_u256(c0).map_err(|_| FieldError::NotMember)?,
283            Fq::from_u256(res.ok_or(FieldError::NotMember)?).map_err(|_| FieldError::NotMember)?,
284        ))
285    }
286}
287
288impl Add<Fq2> for Fq2 {
289    type Output = Self;
290
291    fn add(self, other: Self) -> Self {
292        Fq2(self.0 + other.0)
293    }
294}
295
296impl Sub<Fq2> for Fq2 {
297    type Output = Self;
298
299    fn sub(self, other: Self) -> Self {
300        Fq2(self.0 - other.0)
301    }
302}
303
304impl Neg for Fq2 {
305    type Output = Self;
306
307    fn neg(self) -> Self {
308        Fq2(-self.0)
309    }
310}
311
312impl Mul for Fq2 {
313    type Output = Self;
314
315    fn mul(self, other: Self) -> Self {
316        Fq2(self.0 * other.0)
317    }
318}
319
320pub trait Group:
321    Send
322    + Sync
323    + Copy
324    + Clone
325    + PartialEq
326    + Eq
327    + Sized
328    + Add<Self, Output = Self>
329    + Sub<Self, Output = Self>
330    + Neg<Output = Self>
331    + Mul<Fr, Output = Self>
332{
333    fn zero() -> Self;
334    fn one() -> Self;
335    fn random<R: Rng>(rng: &mut R) -> Self;
336    fn is_zero(&self) -> bool;
337    fn normalize(&mut self);
338    fn multiexp(items: &[(Self, Fr)]) -> Self;
339}
340
341#[derive(Copy, Clone, Debug, PartialEq, Eq)]
342#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
343#[repr(C)]
344pub struct G1(groups::G1);
345
346impl G1 {
347    pub fn new(x: Fq, y: Fq, z: Fq) -> Self {
348        G1(groups::G1::new(x.0, y.0, z.0))
349    }
350
351    pub fn x(&self) -> Fq {
352        Fq(self.0.x().clone())
353    }
354
355    pub fn set_x(&mut self, x: Fq) {
356        *self.0.x_mut() = x.0
357    }
358
359    pub fn y(&self) -> Fq {
360        Fq(self.0.y().clone())
361    }
362
363    pub fn set_y(&mut self, y: Fq) {
364        *self.0.y_mut() = y.0
365    }
366
367    pub fn z(&self) -> Fq {
368        Fq(self.0.z().clone())
369    }
370
371    pub fn set_z(&mut self, z: Fq) {
372        *self.0.z_mut() = z.0
373    }
374
375    pub fn b() -> Fq {
376        Fq(G1Params::coeff_b())
377    }
378
379    pub fn from_compressed(bytes: &[u8]) -> Result<Self, CurveError> {
380        if bytes.len() != 33 {
381            return Err(CurveError::InvalidEncoding);
382        }
383
384        let sign = bytes[0];
385        let fq = Fq::from_slice(&bytes[1..])?;
386        let x = fq;
387        let y_squared = (fq * fq * fq) + Self::b();
388
389        let mut y = y_squared.sqrt().ok_or(CurveError::NotMember)?;
390
391        if sign == 2 && y.into_u256().get_bit(0).expect("bit 0 always exist; qed") {
392            y = y.neg();
393        } else if sign == 3 && !y.into_u256().get_bit(0).expect("bit 0 always exist; qed") {
394            y = y.neg();
395        } else if sign != 3 && sign != 2 {
396            return Err(CurveError::InvalidEncoding);
397        }
398        AffineG1::new(x, y)
399            .map_err(|_| CurveError::NotMember)
400            .map(Into::into)
401    }
402}
403
404impl Group for G1 {
405    fn multiexp(items: &[(Self, Fr)]) -> Self {
406        let items = items
407            .iter()
408            .filter_map(|e| match e.0 .0.to_affine() {
409                None => None,
410                Some(p) => Some((p, e.1.into_u256())),
411            })
412            .collect::<Vec<_>>();
413        Self(crate::groups::pippenger(&items[..]))
414    }
415
416    fn zero() -> Self {
417        G1(groups::G1::zero())
418    }
419    fn one() -> Self {
420        G1(groups::G1::one())
421    }
422    fn random<R: Rng>(rng: &mut R) -> Self {
423        G1(groups::G1::random(rng))
424    }
425    fn is_zero(&self) -> bool {
426        self.0.is_zero()
427    }
428    fn normalize(&mut self) {
429        let new = match self.0.to_affine() {
430            Some(a) => a,
431            None => return,
432        };
433
434        self.0 = new.to_jacobian();
435    }
436}
437
438impl Add<G1> for G1 {
439    type Output = G1;
440
441    fn add(self, other: G1) -> G1 {
442        G1(self.0 + other.0)
443    }
444}
445
446impl Sub<G1> for G1 {
447    type Output = G1;
448
449    fn sub(self, other: G1) -> G1 {
450        G1(self.0 - other.0)
451    }
452}
453
454impl Neg for G1 {
455    type Output = G1;
456
457    fn neg(self) -> G1 {
458        G1(-self.0)
459    }
460}
461
462impl Mul<Fr> for G1 {
463    type Output = G1;
464
465    fn mul(self, other: Fr) -> G1 {
466        G1(self.0 * other.0)
467    }
468}
469
470#[derive(Copy, Clone, Debug, PartialEq, Eq)]
471#[repr(C)]
472pub struct AffineG1(groups::AffineG1);
473
474impl AffineG1 {
475    pub fn new(x: Fq, y: Fq) -> Result<Self, GroupError> {
476        Ok(AffineG1(groups::AffineG1::new(x.0, y.0)?))
477    }
478
479    pub fn x(&self) -> Fq {
480        Fq(self.0.x().clone())
481    }
482
483    pub fn set_x(&mut self, x: Fq) {
484        *self.0.x_mut() = x.0
485    }
486
487    pub fn y(&self) -> Fq {
488        Fq(self.0.y().clone())
489    }
490
491    pub fn set_y(&mut self, y: Fq) {
492        *self.0.y_mut() = y.0
493    }
494
495    pub fn from_jacobian(g1: G1) -> Option<Self> {
496        g1.0.to_affine().map(|x| AffineG1(x))
497    }
498}
499
500impl From<AffineG1> for G1 {
501    fn from(affine: AffineG1) -> Self {
502        G1(affine.0.to_jacobian())
503    }
504}
505
506#[derive(Copy, Clone, Debug, PartialEq, Eq)]
507#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
508#[repr(C)]
509pub struct G2(groups::G2);
510
511impl G2 {
512    pub fn new(x: Fq2, y: Fq2, z: Fq2) -> Self {
513        G2(groups::G2::new(x.0, y.0, z.0))
514    }
515
516    pub fn x(&self) -> Fq2 {
517        Fq2(self.0.x().clone())
518    }
519
520    pub fn set_x(&mut self, x: Fq2) {
521        *self.0.x_mut() = x.0
522    }
523
524    pub fn y(&self) -> Fq2 {
525        Fq2(self.0.y().clone())
526    }
527
528    pub fn set_y(&mut self, y: Fq2) {
529        *self.0.y_mut() = y.0
530    }
531
532    pub fn z(&self) -> Fq2 {
533        Fq2(self.0.z().clone())
534    }
535
536    pub fn set_z(&mut self, z: Fq2) {
537        *self.0.z_mut() = z.0
538    }
539
540    pub fn b() -> Fq2 {
541        Fq2(G2Params::coeff_b())
542    }
543
544    pub fn from_compressed(bytes: &[u8]) -> Result<Self, CurveError> {
545        if bytes.len() != 65 {
546            return Err(CurveError::InvalidEncoding);
547        }
548
549        let sign = bytes[0];
550        let x = Fq2::from_slice(&bytes[1..])?;
551
552        let y_squared = (x * x * x) + G2::b();
553        let y = y_squared.sqrt().ok_or(CurveError::NotMember)?;
554        let y_neg = -y;
555
556        let y_gt = y.0.to_u512() > y_neg.0.to_u512();
557
558        let e_y = if sign == 10 {
559            if y_gt {
560                y_neg
561            } else {
562                y
563            }
564        } else if sign == 11 {
565            if y_gt {
566                y
567            } else {
568                y_neg
569            }
570        } else {
571            return Err(CurveError::InvalidEncoding);
572        };
573
574        AffineG2::new(x, e_y)
575            .map_err(|_| CurveError::NotMember)
576            .map(Into::into)
577    }
578}
579
580impl Group for G2 {
581    fn multiexp(items: &[(Self, Fr)]) -> Self {
582        let items = items
583            .iter()
584            .filter_map(|e| match e.0 .0.to_affine() {
585                None => None,
586                Some(p) => Some((p, e.1.into_u256())),
587            })
588            .collect::<Vec<_>>();
589        Self(crate::groups::pippenger(&items[..]))
590    }
591
592    fn zero() -> Self {
593        G2(groups::G2::zero())
594    }
595    fn one() -> Self {
596        G2(groups::G2::one())
597    }
598    fn random<R: Rng>(rng: &mut R) -> Self {
599        G2(groups::G2::random(rng))
600    }
601    fn is_zero(&self) -> bool {
602        self.0.is_zero()
603    }
604    fn normalize(&mut self) {
605        let new = match self.0.to_affine() {
606            Some(a) => a,
607            None => return,
608        };
609
610        self.0 = new.to_jacobian();
611    }
612}
613
614impl Add<G2> for G2 {
615    type Output = G2;
616
617    fn add(self, other: G2) -> G2 {
618        G2(self.0 + other.0)
619    }
620}
621
622impl Sub<G2> for G2 {
623    type Output = G2;
624
625    fn sub(self, other: G2) -> G2 {
626        G2(self.0 - other.0)
627    }
628}
629
630impl Neg for G2 {
631    type Output = G2;
632
633    fn neg(self) -> G2 {
634        G2(-self.0)
635    }
636}
637
638impl Mul<Fr> for G2 {
639    type Output = G2;
640
641    fn mul(self, other: Fr) -> G2 {
642        G2(self.0 * other.0)
643    }
644}
645
646#[derive(Copy, Clone, PartialEq, Eq)]
647#[repr(C)]
648pub struct Gt(fields::Fq12);
649
650impl Gt {
651    pub fn one() -> Self {
652        Gt(fields::Fq12::one())
653    }
654    pub fn pow(&self, exp: Fr) -> Self {
655        Gt(self.0.pow(exp.0))
656    }
657    pub fn inverse(&self) -> Option<Self> {
658        self.0.inverse().map(Gt)
659    }
660    pub fn final_exponentiation(&self) -> Option<Self> {
661        self.0.final_exponentiation().map(Gt)
662    }
663}
664
665impl Mul<Gt> for Gt {
666    type Output = Gt;
667
668    fn mul(self, other: Gt) -> Gt {
669        Gt(self.0 * other.0)
670    }
671}
672
673pub fn pairing(p: G1, q: G2) -> Gt {
674    Gt(groups::pairing(&p.0, &q.0))
675}
676
677pub fn pairing_batch(pairs: &[(G1, G2)]) -> Gt {
678    let mut ps: Vec<groups::G1> = Vec::new();
679    let mut qs: Vec<groups::G2> = Vec::new();
680    for (p, q) in pairs {
681        ps.push(p.0);
682        qs.push(q.0);
683    }
684    Gt(groups::pairing_batch(&ps, &qs))
685}
686
687pub fn miller_loop_batch(pairs: &[(G2, G1)]) -> Result<Gt, CurveError> {
688    let mut ps: Vec<groups::G2Precomp> = Vec::new();
689    let mut qs: Vec<groups::AffineG<groups::G1Params>> = Vec::new();
690    for (p, q) in pairs {
691        ps.push(
692            p.0.to_affine()
693                .ok_or(CurveError::ToAffineConversion)?
694                .precompute(),
695        );
696        qs.push(q.0.to_affine().ok_or(CurveError::ToAffineConversion)?);
697    }
698    Ok(Gt(groups::miller_loop_batch(&ps, &qs)))
699}
700
701#[derive(Copy, Clone, PartialEq, Eq)]
702#[repr(C)]
703pub struct AffineG2(groups::AffineG2);
704
705impl AffineG2 {
706    pub fn new(x: Fq2, y: Fq2) -> Result<Self, GroupError> {
707        Ok(AffineG2(groups::AffineG2::new(x.0, y.0)?))
708    }
709
710    pub fn x(&self) -> Fq2 {
711        Fq2(self.0.x().clone())
712    }
713
714    pub fn set_x(&mut self, x: Fq2) {
715        *self.0.x_mut() = x.0
716    }
717
718    pub fn y(&self) -> Fq2 {
719        Fq2(self.0.y().clone())
720    }
721
722    pub fn set_y(&mut self, y: Fq2) {
723        *self.0.y_mut() = y.0
724    }
725
726    pub fn from_jacobian(g2: G2) -> Option<Self> {
727        g2.0.to_affine().map(|x| AffineG2(x))
728    }
729}
730
731pub fn ilog(n:u64) -> u64 {
732    assert!(n>0);
733    const T:[u64; 45] = [1, 3, 8, 21, 55, 149, 404, 1097, 2981, 8104, 22027, 59875, 162755, 442414, 1202605, 3269018, 8886111, 24154953, 65659970, 178482301, 485165196, 1318815735, 3584912847, 9744803447, 26489122130, 72004899338, 195729609429, 532048240602, 1446257064292, 3931334297145, 10686474581525, 29048849665248, 78962960182681, 214643579785917, 583461742527455, 1586013452313431, 4311231547115196, 11719142372802612, 31855931757113757, 86593400423993747, 235385266837019986, 639843493530054950, 1739274941520501048, 4727839468229346562, 12851600114359308276];
734    fn binsearch(l:usize, r:usize, n:u64, t:&[u64]) -> usize {
735        if r-l==1 {
736            return l
737        } else {
738            let m = (r+l)/2;
739            if n < t[m] {
740                binsearch(l, m, n, t)
741            } else {
742                binsearch(m, r, n, t)
743            }
744        }
745    }
746    binsearch(0, T.len(), n, T.as_ref()) as u64
747}
748
749
750impl From<AffineG2> for G2 {
751    fn from(affine: AffineG2) -> Self {
752        G2(affine.0.to_jacobian())
753    }
754}
755
756#[cfg(test)]
757mod tests {
758    extern crate rustc_hex as hex;
759    use super::{Fq, Fq2, G1, G2};
760    use alloc::vec::Vec;
761
762    fn hex(s: &'static str) -> Vec<u8> {
763        use self::hex::FromHex;
764        s.from_hex().unwrap()
765    }
766
767    #[test]
768    fn g1_from_compressed() {
769        let g1 = G1::from_compressed(&hex(
770            "0230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46",
771        ))
772        .expect("Invalid g1 decompress result");
773        assert_eq!(
774            g1.x(),
775            Fq::from_str(
776                "21888242871839275222246405745257275088696311157297823662689037894645226208582"
777            )
778            .unwrap()
779        );
780        assert_eq!(
781            g1.y(),
782            Fq::from_str(
783                "3969792565221544645472939191694882283483352126195956956354061729942568608776"
784            )
785            .unwrap()
786        );
787        assert_eq!(g1.z(), Fq::one());
788    }
789
790    #[test]
791    fn g2_from_compressed() {
792        let g2 = G2::from_compressed(
793            &hex("0a023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a")
794        ).expect("Valid g2 point hex encoding");
795
796        assert_eq!(
797            g2.x(),
798            Fq2::new(
799                Fq::from_str(
800                    "5923585509243758863255447226263146374209884951848029582715967108651637186684"
801                )
802                .unwrap(),
803                Fq::from_str(
804                    "5336385337059958111259504403491065820971993066694750945459110579338490853570"
805                )
806                .unwrap(),
807            )
808        );
809
810        assert_eq!(
811            g2.y(),
812            Fq2::new(
813                Fq::from_str(
814                    "10374495865873200088116930399159835104695426846400310764827677226300185211748"
815                )
816                .unwrap(),
817                Fq::from_str(
818                    "5256529835065685814318509161957442385362539991735248614869838648137856366932"
819                )
820                .unwrap(),
821            )
822        );
823
824        // 0b prefix is point reflection on the curve
825        let g2 = -G2::from_compressed(
826            &hex("0b023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a")
827        ).expect("Valid g2 point hex encoding");
828
829        assert_eq!(
830            g2.x(),
831            Fq2::new(
832                Fq::from_str(
833                    "5923585509243758863255447226263146374209884951848029582715967108651637186684"
834                )
835                .unwrap(),
836                Fq::from_str(
837                    "5336385337059958111259504403491065820971993066694750945459110579338490853570"
838                )
839                .unwrap(),
840            )
841        );
842
843        assert_eq!(
844            g2.y(),
845            Fq2::new(
846                Fq::from_str(
847                    "10374495865873200088116930399159835104695426846400310764827677226300185211748"
848                )
849                .unwrap(),
850                Fq::from_str(
851                    "5256529835065685814318509161957442385362539991735248614869838648137856366932"
852                )
853                .unwrap(),
854            )
855        );
856
857        // valid point but invalid sign prefix
858        assert!(
859            G2::from_compressed(
860                &hex("0c023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a")
861            ).is_err()
862        );
863    }
864}