1#[cfg(not(target_family = "wasm"))]
2use crate::xdr::ScVal;
3use crate::{
4 crypto::utils::BigInt,
5 env::internal::{self, BytesObject, U256Val, U64Val},
6 impl_bytesn_repr,
7 unwrap::{UnwrapInfallible, UnwrapOptimized},
8 Bytes, BytesN, ConversionError, Env, IntoVal, TryFromVal, Val, Vec, U256,
9};
10use core::{
11 cmp::Ordering,
12 fmt::Debug,
13 ops::{Add, Mul, Neg, Sub},
14};
15
16pub const FP_SERIALIZED_SIZE: usize = 48; pub const FP2_SERIALIZED_SIZE: usize = FP_SERIALIZED_SIZE * 2;
18pub const G1_SERIALIZED_SIZE: usize = FP_SERIALIZED_SIZE * 2; pub const G2_SERIALIZED_SIZE: usize = FP2_SERIALIZED_SIZE * 2; pub struct Bls12_381 {
24 env: Env,
25}
26
27#[derive(Clone)]
54#[repr(transparent)]
55pub struct Bls12381G1Affine(BytesN<G1_SERIALIZED_SIZE>);
56
57pub type G1Affine = Bls12381G1Affine;
59
60#[derive(Clone)]
77#[repr(transparent)]
78pub struct Bls12381G2Affine(BytesN<G2_SERIALIZED_SIZE>);
79
80pub type G2Affine = Bls12381G2Affine;
82
83#[derive(Clone)]
90#[repr(transparent)]
91pub struct Bls12381Fp(BytesN<FP_SERIALIZED_SIZE>);
92
93pub type Fp = Bls12381Fp;
95
96#[derive(Clone)]
105#[repr(transparent)]
106pub struct Bls12381Fp2(BytesN<FP2_SERIALIZED_SIZE>);
107
108pub type Fp2 = Bls12381Fp2;
110
111#[derive(Clone)]
116#[repr(transparent)]
117pub struct Fr(U256);
118
119impl_bytesn_repr!(Bls12381G1Affine, G1_SERIALIZED_SIZE);
120impl_bytesn_repr!(Bls12381G2Affine, G2_SERIALIZED_SIZE);
121impl_bytesn_repr!(Bls12381Fp, FP_SERIALIZED_SIZE);
122impl_bytesn_repr!(Bls12381Fp2, FP2_SERIALIZED_SIZE);
123
124impl Fp {
125 pub fn env(&self) -> &Env {
126 self.0.env()
127 }
128
129 fn checked_neg(&self) -> Option<Fp> {
135 let fp_bigint: BigInt<6> = (&self.0).into();
136 if fp_bigint.is_zero() {
137 return Some(self.clone());
138 }
139
140 const BLS12_381_MODULUS: [u64; 6] = [
142 13402431016077863595,
143 2210141511517208575,
144 7435674573564081700,
145 7239337960414712511,
146 5412103778470702295,
147 1873798617647539866,
148 ];
149 let mut res = BigInt(BLS12_381_MODULUS);
150
151 let borrow = res.sub_with_borrow(&fp_bigint);
153 if borrow {
154 return None;
155 }
156
157 let mut bytes = [0u8; FP_SERIALIZED_SIZE];
158 res.copy_into_array(&mut bytes);
159 Some(Fp::from_array(self.env(), &bytes))
160 }
161
162 pub fn map_to_g1(&self) -> G1Affine {
175 self.env().crypto().bls12_381().map_fp_to_g1(self)
176 }
177}
178
179impl From<Fp> for BigInt<6> {
180 fn from(fp: Fp) -> Self {
181 let inner: Bytes = fp.0.into();
182 let mut limbs = [0u64; 6];
183 for i in 0..6u32 {
184 let start = i * 8;
185 let mut slice = [0u8; 8];
186 inner.slice(start..start + 8).copy_into_slice(&mut slice);
187 limbs[5 - i as usize] = u64::from_be_bytes(slice);
188 }
189 BigInt(limbs)
190 }
191}
192
193impl Neg for &Fp {
194 type Output = Fp;
195
196 fn neg(self) -> Self::Output {
197 match self.checked_neg() {
198 Some(v) => v,
199 None => sdk_panic!("invalid input - Fp is larger than the field modulus"),
200 }
201 }
202}
203
204impl Neg for Fp {
205 type Output = Fp;
206
207 fn neg(self) -> Self::Output {
208 (&self).neg()
209 }
210}
211
212impl G1Affine {
213 pub fn env(&self) -> &Env {
214 self.0.env()
215 }
216
217 pub fn is_in_subgroup(&self) -> bool {
218 self.env().crypto().bls12_381().g1_is_in_subgroup(self)
219 }
220
221 pub fn checked_add(&self, rhs: &Self) -> Option<Self> {
222 self.env().crypto().bls12_381().g1_checked_add(self, rhs)
223 }
224}
225
226impl Add for G1Affine {
227 type Output = G1Affine;
228
229 fn add(self, rhs: Self) -> Self::Output {
230 self.env().crypto().bls12_381().g1_add(&self, &rhs)
231 }
232}
233
234impl Mul<Fr> for G1Affine {
235 type Output = G1Affine;
236
237 fn mul(self, rhs: Fr) -> Self::Output {
238 self.env().crypto().bls12_381().g1_mul(&self, &rhs)
239 }
240}
241
242impl Neg for &G1Affine {
245 type Output = G1Affine;
246
247 fn neg(self) -> Self::Output {
248 let mut inner: Bytes = (&self.0).into();
249 let y = Fp::try_from_val(
250 inner.env(),
251 inner.slice(FP_SERIALIZED_SIZE as u32..).as_val(),
252 )
253 .unwrap_optimized();
254 let neg_y = -y;
255 inner.copy_from_slice(FP_SERIALIZED_SIZE as u32, &neg_y.to_array());
256 G1Affine::from_bytes(BytesN::try_from_val(inner.env(), inner.as_val()).unwrap_optimized())
257 }
258}
259
260impl Neg for G1Affine {
261 type Output = G1Affine;
262
263 fn neg(self) -> Self::Output {
264 (&self).neg()
265 }
266}
267
268impl Fp2 {
269 pub fn env(&self) -> &Env {
270 self.0.env()
271 }
272
273 fn checked_neg(&self) -> Option<Fp2> {
278 let mut inner = self.to_array();
279 let mut slice0 = [0; FP_SERIALIZED_SIZE];
280 let mut slice1 = [0; FP_SERIALIZED_SIZE];
281 slice0.copy_from_slice(&inner[0..FP_SERIALIZED_SIZE]);
282 slice1.copy_from_slice(&inner[FP_SERIALIZED_SIZE..FP2_SERIALIZED_SIZE]);
283
284 let c0 = Fp::from_array(self.env(), &slice0);
286 let c1 = Fp::from_array(self.env(), &slice1);
287
288 let neg_c0 = c0.checked_neg()?;
290 let neg_c1 = c1.checked_neg()?;
291
292 inner[0..FP_SERIALIZED_SIZE].copy_from_slice(&neg_c0.to_array());
294 inner[FP_SERIALIZED_SIZE..FP2_SERIALIZED_SIZE].copy_from_slice(&neg_c1.to_array());
295
296 Some(Fp2::from_array(self.env(), &inner))
297 }
298
299 pub fn map_to_g2(&self) -> G2Affine {
312 self.env().crypto().bls12_381().map_fp2_to_g2(self)
313 }
314}
315
316impl Neg for &Fp2 {
317 type Output = Fp2;
318
319 fn neg(self) -> Self::Output {
320 match self.checked_neg() {
321 Some(v) => v,
322 None => sdk_panic!("invalid input - Fp2 component is larger than the field modulus"),
323 }
324 }
325}
326
327impl Neg for Fp2 {
328 type Output = Fp2;
329
330 fn neg(self) -> Self::Output {
331 (&self).neg()
332 }
333}
334
335impl G2Affine {
336 pub fn env(&self) -> &Env {
337 self.0.env()
338 }
339
340 pub fn is_in_subgroup(&self) -> bool {
341 self.env().crypto().bls12_381().g2_is_in_subgroup(self)
342 }
343
344 pub fn checked_add(&self, rhs: &Self) -> Option<Self> {
345 self.env().crypto().bls12_381().g2_checked_add(self, rhs)
346 }
347}
348
349impl Add for G2Affine {
350 type Output = G2Affine;
351
352 fn add(self, rhs: Self) -> Self::Output {
353 self.env().crypto().bls12_381().g2_add(&self, &rhs)
354 }
355}
356
357impl Mul<Fr> for G2Affine {
358 type Output = G2Affine;
359
360 fn mul(self, rhs: Fr) -> Self::Output {
361 self.env().crypto().bls12_381().g2_mul(&self, &rhs)
362 }
363}
364
365impl Neg for &G2Affine {
368 type Output = G2Affine;
369
370 fn neg(self) -> Self::Output {
371 let mut inner: Bytes = (&self.0).into();
372 let y = Fp2::try_from_val(
373 inner.env(),
374 inner.slice(FP2_SERIALIZED_SIZE as u32..).as_val(),
375 )
376 .unwrap_optimized();
377 let neg_y = -y;
378 inner.copy_from_slice(FP2_SERIALIZED_SIZE as u32, &neg_y.to_array());
379 G2Affine::from_bytes(BytesN::try_from_val(inner.env(), inner.as_val()).unwrap_optimized())
380 }
381}
382
383impl Neg for G2Affine {
384 type Output = G2Affine;
385
386 fn neg(self) -> Self::Output {
387 (&self).neg()
388 }
389}
390
391impl Fr {
392 pub fn env(&self) -> &Env {
393 self.0.env()
394 }
395
396 pub fn from_u256(value: U256) -> Self {
397 value.into()
398 }
399
400 pub fn to_u256(&self) -> U256 {
401 self.0.clone()
402 }
403
404 pub fn as_u256(&self) -> &U256 {
405 &self.0
406 }
407
408 pub fn from_bytes(bytes: BytesN<32>) -> Self {
409 U256::from_be_bytes(bytes.env(), bytes.as_ref()).into()
410 }
411
412 pub fn to_bytes(&self) -> BytesN<32> {
413 self.as_u256().to_be_bytes().try_into().unwrap_optimized()
414 }
415
416 pub fn as_val(&self) -> &Val {
417 self.0.as_val()
418 }
419
420 pub fn to_val(&self) -> Val {
421 self.0.to_val()
422 }
423
424 pub fn pow(&self, rhs: u64) -> Self {
425 self.env().crypto().bls12_381().fr_pow(self, rhs)
426 }
427
428 pub fn inv(&self) -> Self {
429 self.env().crypto().bls12_381().fr_inv(self)
430 }
431}
432
433impl From<U256> for Fr {
434 fn from(value: U256) -> Self {
435 Self(value)
436 }
437}
438
439impl From<&Fr> for U256Val {
440 fn from(value: &Fr) -> Self {
441 value.as_u256().into()
442 }
443}
444
445impl TryFromVal<Env, Val> for Fr {
446 type Error = ConversionError;
447
448 fn try_from_val(env: &Env, val: &Val) -> Result<Self, Self::Error> {
449 let u = U256::try_from_val(env, val)?;
450 Ok(Fr(u))
451 }
452}
453
454impl TryFromVal<Env, Fr> for Val {
455 type Error = ConversionError;
456
457 fn try_from_val(_env: &Env, fr: &Fr) -> Result<Self, Self::Error> {
458 Ok(fr.to_val())
459 }
460}
461
462impl TryFromVal<Env, &Fr> for Val {
463 type Error = ConversionError;
464
465 fn try_from_val(_env: &Env, fr: &&Fr) -> Result<Self, Self::Error> {
466 Ok(fr.to_val())
467 }
468}
469
470#[cfg(not(target_family = "wasm"))]
471impl From<&Fr> for ScVal {
472 fn from(v: &Fr) -> Self {
473 Self::from(&v.0)
474 }
475}
476
477#[cfg(not(target_family = "wasm"))]
478impl From<Fr> for ScVal {
479 fn from(v: Fr) -> Self {
480 (&v).into()
481 }
482}
483
484impl Eq for Fr {}
485
486impl PartialEq for Fr {
487 fn eq(&self, other: &Self) -> bool {
488 self.as_u256().partial_cmp(other.as_u256()) == Some(Ordering::Equal)
489 }
490}
491
492impl Debug for Fr {
493 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
494 write!(f, "Fr({:?})", self.as_u256())
495 }
496}
497
498impl Add for Fr {
499 type Output = Fr;
500
501 fn add(self, rhs: Self) -> Self::Output {
502 self.env().crypto().bls12_381().fr_add(&self, &rhs)
503 }
504}
505
506impl Sub for Fr {
507 type Output = Fr;
508
509 fn sub(self, rhs: Self) -> Self::Output {
510 self.env().crypto().bls12_381().fr_sub(&self, &rhs)
511 }
512}
513
514impl Mul for Fr {
515 type Output = Fr;
516
517 fn mul(self, rhs: Self) -> Self::Output {
518 self.env().crypto().bls12_381().fr_mul(&self, &rhs)
519 }
520}
521
522impl Bls12_381 {
523 pub(crate) fn new(env: &Env) -> Bls12_381 {
524 Bls12_381 { env: env.clone() }
525 }
526
527 pub fn env(&self) -> &Env {
528 &self.env
529 }
530
531 pub fn g1_is_in_subgroup(&self, p: &G1Affine) -> bool {
535 let env = self.env();
536 let res = internal::Env::bls12_381_check_g1_is_in_subgroup(env, p.to_object())
537 .unwrap_infallible();
538 res.into()
539 }
540
541 pub fn g1_add(&self, p0: &G1Affine, p1: &G1Affine) -> G1Affine {
543 let env = self.env();
544 let bin = internal::Env::bls12_381_g1_add(env, p0.to_object(), p1.to_object())
545 .unwrap_infallible();
546 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
547 }
548
549 pub fn g1_checked_add(&self, p0: &G1Affine, p1: &G1Affine) -> Option<G1Affine> {
555 let env = self.env();
556 let bin = internal::Env::bls12_381_g1_add(env, p0.to_object(), p1.to_object())
557 .unwrap_infallible();
558 let res = unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) };
559 let is_in_correct_subgroup: bool =
560 internal::Env::bls12_381_check_g1_is_in_subgroup(env, res.to_object())
561 .unwrap_optimized()
562 .into();
563 match is_in_correct_subgroup {
564 true => Some(res),
565 false => None,
566 }
567 }
568
569 pub fn g1_mul(&self, p0: &G1Affine, scalar: &Fr) -> G1Affine {
571 let env = self.env();
572 let bin =
573 internal::Env::bls12_381_g1_mul(env, p0.to_object(), scalar.into()).unwrap_infallible();
574 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
575 }
576
577 pub fn g1_msm(&self, vp: Vec<G1Affine>, vs: Vec<Fr>) -> G1Affine {
579 let env = self.env();
580 let bin = internal::Env::bls12_381_g1_msm(env, vp.into(), vs.into()).unwrap_infallible();
581 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
582 }
583
584 pub fn map_fp_to_g1(&self, fp: &Fp) -> G1Affine {
586 let env = self.env();
587 let bin = internal::Env::bls12_381_map_fp_to_g1(env, fp.to_object()).unwrap_infallible();
588 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
589 }
590
591 pub fn hash_to_g1(&self, msg: &Bytes, dst: &Bytes) -> G1Affine {
593 let env = self.env();
594 let bin = internal::Env::bls12_381_hash_to_g1(env, msg.into(), dst.to_object())
595 .unwrap_infallible();
596 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
597 }
598
599 pub fn g2_is_in_subgroup(&self, p: &G2Affine) -> bool {
603 let env = self.env();
604 let res = internal::Env::bls12_381_check_g2_is_in_subgroup(env, p.to_object())
605 .unwrap_infallible();
606 res.into()
607 }
608
609 pub fn g2_add(&self, p0: &G2Affine, p1: &G2Affine) -> G2Affine {
611 let env = self.env();
612 let bin = internal::Env::bls12_381_g2_add(env, p0.to_object(), p1.to_object())
613 .unwrap_infallible();
614 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
615 }
616
617 pub fn g2_checked_add(&self, p0: &G2Affine, p1: &G2Affine) -> Option<G2Affine> {
623 let env = self.env();
624 let bin = internal::Env::bls12_381_g2_add(env, p0.to_object(), p1.to_object())
625 .unwrap_infallible();
626 let res = unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) };
627 let is_in_correct_subgroup: bool =
628 internal::Env::bls12_381_check_g2_is_in_subgroup(env, res.to_object())
629 .unwrap_optimized()
630 .into();
631 match is_in_correct_subgroup {
632 true => Some(res),
633 false => None,
634 }
635 }
636
637 pub fn g2_mul(&self, p0: &G2Affine, scalar: &Fr) -> G2Affine {
639 let env = self.env();
640 let bin =
641 internal::Env::bls12_381_g2_mul(env, p0.to_object(), scalar.into()).unwrap_infallible();
642 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
643 }
644
645 pub fn g2_msm(&self, vp: Vec<G2Affine>, vs: Vec<Fr>) -> G2Affine {
647 let env = self.env();
648 let bin = internal::Env::bls12_381_g2_msm(env, vp.into(), vs.into()).unwrap_infallible();
649 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
650 }
651
652 pub fn map_fp2_to_g2(&self, fp2: &Fp2) -> G2Affine {
654 let env = self.env();
655 let bin = internal::Env::bls12_381_map_fp2_to_g2(env, fp2.to_object()).unwrap_infallible();
656 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
657 }
658
659 pub fn hash_to_g2(&self, msg: &Bytes, dst: &Bytes) -> G2Affine {
661 let env = self.env();
662 let bin = internal::Env::bls12_381_hash_to_g2(env, msg.into(), dst.to_object())
663 .unwrap_infallible();
664 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
665 }
666
667 pub fn pairing_check(&self, vp1: Vec<G1Affine>, vp2: Vec<G2Affine>) -> bool {
682 let env = self.env();
683 internal::Env::bls12_381_multi_pairing_check(env, vp1.into(), vp2.into())
684 .unwrap_infallible()
685 .into()
686 }
687
688 pub fn fr_add(&self, lhs: &Fr, rhs: &Fr) -> Fr {
692 let env = self.env();
693 let v = internal::Env::bls12_381_fr_add(env, lhs.into(), rhs.into()).unwrap_infallible();
694 U256::try_from_val(env, &v).unwrap_infallible().into()
695 }
696
697 pub fn fr_sub(&self, lhs: &Fr, rhs: &Fr) -> Fr {
699 let env = self.env();
700 let v = internal::Env::bls12_381_fr_sub(env, lhs.into(), rhs.into()).unwrap_infallible();
701 U256::try_from_val(env, &v).unwrap_infallible().into()
702 }
703
704 pub fn fr_mul(&self, lhs: &Fr, rhs: &Fr) -> Fr {
706 let env = self.env();
707 let v = internal::Env::bls12_381_fr_mul(env, lhs.into(), rhs.into()).unwrap_infallible();
708 U256::try_from_val(env, &v).unwrap_infallible().into()
709 }
710
711 pub fn fr_pow(&self, lhs: &Fr, rhs: u64) -> Fr {
713 let env = self.env();
714 let rhs = U64Val::try_from_val(env, &rhs).unwrap_optimized();
715 let v = internal::Env::bls12_381_fr_pow(env, lhs.into(), rhs).unwrap_infallible();
716 U256::try_from_val(env, &v).unwrap_infallible().into()
717 }
718
719 pub fn fr_inv(&self, lhs: &Fr) -> Fr {
721 let env = self.env();
722 let v = internal::Env::bls12_381_fr_inv(env, lhs.into()).unwrap_infallible();
723 U256::try_from_val(env, &v).unwrap_infallible().into()
724 }
725}
726
727#[cfg(test)]
728mod test {
729 use super::*;
730
731 #[test]
732 fn test_g1affine_to_val() {
733 let env = Env::default();
734
735 let g1 = G1Affine::from_bytes(BytesN::from_array(&env, &[1; 96]));
736 let val: Val = g1.clone().into_val(&env);
737 let rt: G1Affine = val.into_val(&env);
738
739 assert_eq!(g1, rt);
740 }
741
742 #[test]
743 fn test_ref_g1affine_to_val() {
744 let env = Env::default();
745
746 let g1 = G1Affine::from_bytes(BytesN::from_array(&env, &[1; 96]));
747 let val: Val = (&g1).into_val(&env);
748 let rt: G1Affine = val.into_val(&env);
749
750 assert_eq!(g1, rt);
751 }
752
753 #[test]
754 fn test_doule_ref_g1affine_to_val() {
755 let env = Env::default();
756
757 let g1 = G1Affine::from_bytes(BytesN::from_array(&env, &[1; 96]));
758 let val: Val = (&&g1).into_val(&env);
759 let rt: G1Affine = val.into_val(&env);
760
761 assert_eq!(g1, rt);
762 }
763
764 #[test]
765 fn test_fr_to_val() {
766 let env = Env::default();
767
768 let fr = Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
769 let val: Val = fr.clone().into_val(&env);
770 let rt: Fr = val.into_val(&env);
771
772 assert_eq!(fr, rt);
773 }
774
775 #[test]
776 fn test_ref_fr_to_val() {
777 let env = Env::default();
778
779 let fr = Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
780 let val: Val = (&fr).into_val(&env);
781 let rt: Fr = val.into_val(&env);
782
783 assert_eq!(fr, rt);
784 }
785
786 #[test]
787 fn test_double_ref_fr_to_val() {
788 let env = Env::default();
789
790 let fr = Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
791 let val: Val = (&&fr).into_val(&env);
792 let rt: Fr = val.into_val(&env);
793
794 assert_eq!(fr, rt);
795 }
796}