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) .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) .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 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 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 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 assert!(
859 G2::from_compressed(
860 &hex("0c023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a")
861 ).is_err()
862 );
863 }
864}