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_without_from_bytes,
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_without_from_bytes!(Bls12381G1Affine, G1_SERIALIZED_SIZE);
120impl_bytesn_repr_without_from_bytes!(Bls12381G2Affine, G2_SERIALIZED_SIZE);
121impl_bytesn_repr_without_from_bytes!(Bls12381Fp, FP_SERIALIZED_SIZE);
122impl_bytesn_repr_without_from_bytes!(Bls12381Fp2, FP2_SERIALIZED_SIZE);
123
124const BLS12_381_FP_MODULUS_BE: [u8; FP_SERIALIZED_SIZE] = [
127 0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b, 0xac, 0xd7,
128 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0, 0xf6, 0xb0, 0xf6, 0x24,
129 0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xab,
130];
131
132fn validate_fp(bytes: &[u8; FP_SERIALIZED_SIZE]) {
133 if bytes >= &BLS12_381_FP_MODULUS_BE {
134 sdk_panic!("Bls12-381: Invalid Fp");
135 }
136}
137
138fn validate_fp2(bytes: &[u8; FP2_SERIALIZED_SIZE]) {
139 validate_fp(bytes[0..FP_SERIALIZED_SIZE].try_into().unwrap());
140 validate_fp(bytes[FP_SERIALIZED_SIZE..].try_into().unwrap());
141}
142
143impl Bls12381G1Affine {
144 pub fn from_bytes(bytes: BytesN<G1_SERIALIZED_SIZE>) -> Self {
145 Self(bytes)
146 }
147}
148
149impl Bls12381G2Affine {
150 pub fn from_bytes(bytes: BytesN<G2_SERIALIZED_SIZE>) -> Self {
151 Self(bytes)
152 }
153}
154
155impl Bls12381Fp {
156 pub fn from_bytes(bytes: BytesN<FP_SERIALIZED_SIZE>) -> Self {
157 validate_fp(&bytes.to_array());
158 Self(bytes)
159 }
160}
161
162impl Bls12381Fp2 {
163 pub fn from_bytes(bytes: BytesN<FP2_SERIALIZED_SIZE>) -> Self {
164 validate_fp2(&bytes.to_array());
165 Self(bytes)
166 }
167}
168
169impl Fp {
170 pub fn env(&self) -> &Env {
171 self.0.env()
172 }
173
174 fn checked_neg(&self) -> Option<Fp> {
180 let fp_bigint: BigInt<6> = (&self.0).into();
181 if fp_bigint.is_zero() {
182 return Some(self.clone());
183 }
184
185 const BLS12_381_MODULUS: [u64; 6] = [
187 13402431016077863595,
188 2210141511517208575,
189 7435674573564081700,
190 7239337960414712511,
191 5412103778470702295,
192 1873798617647539866,
193 ];
194 let mut res = BigInt(BLS12_381_MODULUS);
195
196 let borrow = res.sub_with_borrow(&fp_bigint);
198 if borrow {
199 return None;
200 }
201
202 let mut bytes = [0u8; FP_SERIALIZED_SIZE];
203 res.copy_into_array(&mut bytes);
204 Some(Fp::from_array(self.env(), &bytes))
205 }
206
207 pub fn map_to_g1(&self) -> G1Affine {
220 self.env().crypto().bls12_381().map_fp_to_g1(self)
221 }
222}
223
224impl From<Fp> for BigInt<6> {
225 fn from(fp: Fp) -> Self {
226 let inner: Bytes = fp.0.into();
227 let mut limbs = [0u64; 6];
228 for i in 0..6u32 {
229 let start = i * 8;
230 let mut slice = [0u8; 8];
231 inner.slice(start..start + 8).copy_into_slice(&mut slice);
232 limbs[5 - i as usize] = u64::from_be_bytes(slice);
233 }
234 BigInt(limbs)
235 }
236}
237
238impl Neg for &Fp {
239 type Output = Fp;
240
241 fn neg(self) -> Self::Output {
242 match self.checked_neg() {
243 Some(v) => v,
244 None => sdk_panic!("invalid input - Fp is larger than the field modulus"),
245 }
246 }
247}
248
249impl Neg for Fp {
250 type Output = Fp;
251
252 fn neg(self) -> Self::Output {
253 (&self).neg()
254 }
255}
256
257impl G1Affine {
258 pub fn env(&self) -> &Env {
259 self.0.env()
260 }
261
262 pub fn is_in_subgroup(&self) -> bool {
263 self.env().crypto().bls12_381().g1_is_in_subgroup(self)
264 }
265
266 pub fn checked_add(&self, rhs: &Self) -> Option<Self> {
267 self.env().crypto().bls12_381().g1_checked_add(self, rhs)
268 }
269}
270
271impl Add for G1Affine {
272 type Output = G1Affine;
273
274 fn add(self, rhs: Self) -> Self::Output {
275 self.env().crypto().bls12_381().g1_add(&self, &rhs)
276 }
277}
278
279impl Mul<Fr> for G1Affine {
280 type Output = G1Affine;
281
282 fn mul(self, rhs: Fr) -> Self::Output {
283 self.env().crypto().bls12_381().g1_mul(&self, &rhs)
284 }
285}
286
287impl Neg for &G1Affine {
290 type Output = G1Affine;
291
292 fn neg(self) -> Self::Output {
293 let mut inner: Bytes = (&self.0).into();
294 let y = Fp::try_from_val(
295 inner.env(),
296 inner.slice(FP_SERIALIZED_SIZE as u32..).as_val(),
297 )
298 .unwrap_optimized();
299 let neg_y = -y;
300 inner.copy_from_slice(FP_SERIALIZED_SIZE as u32, &neg_y.to_array());
301 G1Affine::from_bytes(BytesN::try_from_val(inner.env(), inner.as_val()).unwrap_optimized())
302 }
303}
304
305impl Neg for G1Affine {
306 type Output = G1Affine;
307
308 fn neg(self) -> Self::Output {
309 (&self).neg()
310 }
311}
312
313impl Fp2 {
314 pub fn env(&self) -> &Env {
315 self.0.env()
316 }
317
318 fn checked_neg(&self) -> Option<Fp2> {
323 let mut inner = self.to_array();
324 let mut slice0 = [0; FP_SERIALIZED_SIZE];
325 let mut slice1 = [0; FP_SERIALIZED_SIZE];
326 slice0.copy_from_slice(&inner[0..FP_SERIALIZED_SIZE]);
327 slice1.copy_from_slice(&inner[FP_SERIALIZED_SIZE..FP2_SERIALIZED_SIZE]);
328
329 let c0 = Fp::from_array(self.env(), &slice0);
331 let c1 = Fp::from_array(self.env(), &slice1);
332
333 let neg_c0 = c0.checked_neg()?;
335 let neg_c1 = c1.checked_neg()?;
336
337 inner[0..FP_SERIALIZED_SIZE].copy_from_slice(&neg_c0.to_array());
339 inner[FP_SERIALIZED_SIZE..FP2_SERIALIZED_SIZE].copy_from_slice(&neg_c1.to_array());
340
341 Some(Fp2::from_array(self.env(), &inner))
342 }
343
344 pub fn map_to_g2(&self) -> G2Affine {
357 self.env().crypto().bls12_381().map_fp2_to_g2(self)
358 }
359}
360
361impl Neg for &Fp2 {
362 type Output = Fp2;
363
364 fn neg(self) -> Self::Output {
365 match self.checked_neg() {
366 Some(v) => v,
367 None => sdk_panic!("invalid input - Fp2 component is larger than the field modulus"),
368 }
369 }
370}
371
372impl Neg for Fp2 {
373 type Output = Fp2;
374
375 fn neg(self) -> Self::Output {
376 (&self).neg()
377 }
378}
379
380impl G2Affine {
381 pub fn env(&self) -> &Env {
382 self.0.env()
383 }
384
385 pub fn is_in_subgroup(&self) -> bool {
386 self.env().crypto().bls12_381().g2_is_in_subgroup(self)
387 }
388
389 pub fn checked_add(&self, rhs: &Self) -> Option<Self> {
390 self.env().crypto().bls12_381().g2_checked_add(self, rhs)
391 }
392}
393
394impl Add for G2Affine {
395 type Output = G2Affine;
396
397 fn add(self, rhs: Self) -> Self::Output {
398 self.env().crypto().bls12_381().g2_add(&self, &rhs)
399 }
400}
401
402impl Mul<Fr> for G2Affine {
403 type Output = G2Affine;
404
405 fn mul(self, rhs: Fr) -> Self::Output {
406 self.env().crypto().bls12_381().g2_mul(&self, &rhs)
407 }
408}
409
410impl Neg for &G2Affine {
413 type Output = G2Affine;
414
415 fn neg(self) -> Self::Output {
416 let mut inner: Bytes = (&self.0).into();
417 let y = Fp2::try_from_val(
418 inner.env(),
419 inner.slice(FP2_SERIALIZED_SIZE as u32..).as_val(),
420 )
421 .unwrap_optimized();
422 let neg_y = -y;
423 inner.copy_from_slice(FP2_SERIALIZED_SIZE as u32, &neg_y.to_array());
424 G2Affine::from_bytes(BytesN::try_from_val(inner.env(), inner.as_val()).unwrap_optimized())
425 }
426}
427
428impl Neg for G2Affine {
429 type Output = G2Affine;
430
431 fn neg(self) -> Self::Output {
432 (&self).neg()
433 }
434}
435
436impl Fr {
437 pub fn env(&self) -> &Env {
438 self.0.env()
439 }
440
441 pub fn from_u256(value: U256) -> Self {
442 value.into()
443 }
444
445 pub fn to_u256(&self) -> U256 {
446 self.0.clone()
447 }
448
449 pub fn as_u256(&self) -> &U256 {
450 &self.0
451 }
452
453 pub fn from_bytes(bytes: BytesN<32>) -> Self {
454 U256::from_be_bytes(bytes.env(), bytes.as_ref()).into()
455 }
456
457 pub fn to_bytes(&self) -> BytesN<32> {
458 self.as_u256().to_be_bytes().try_into().unwrap_optimized()
459 }
460
461 pub fn as_val(&self) -> &Val {
462 self.0.as_val()
463 }
464
465 pub fn to_val(&self) -> Val {
466 self.0.to_val()
467 }
468
469 pub fn pow(&self, rhs: u64) -> Self {
470 self.env().crypto().bls12_381().fr_pow(self, rhs)
471 }
472
473 pub fn inv(&self) -> Self {
474 self.env().crypto().bls12_381().fr_inv(self)
475 }
476}
477
478const BLS12_381_FR_MODULUS_BE: [u8; 32] = [
481 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, 0xd8, 0x05,
482 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
483];
484
485fn fr_modulus(env: &Env) -> U256 {
486 U256::from_be_bytes(env, &Bytes::from_array(env, &BLS12_381_FR_MODULUS_BE))
487}
488
489impl From<U256> for Fr {
490 fn from(value: U256) -> Self {
491 let modulus = fr_modulus(value.env());
496 if value >= modulus {
497 Self(value.rem_euclid(&modulus))
498 } else {
499 Self(value)
500 }
501 }
502}
503
504impl From<&Fr> for U256Val {
505 fn from(value: &Fr) -> Self {
506 value.as_u256().into()
507 }
508}
509
510impl TryFromVal<Env, Val> for Fr {
511 type Error = ConversionError;
512
513 fn try_from_val(env: &Env, val: &Val) -> Result<Self, Self::Error> {
514 let u = U256::try_from_val(env, val)?;
515 Ok(u.into())
516 }
517}
518
519impl TryFromVal<Env, Fr> for Val {
520 type Error = ConversionError;
521
522 fn try_from_val(_env: &Env, fr: &Fr) -> Result<Self, Self::Error> {
523 Ok(fr.to_val())
524 }
525}
526
527impl TryFromVal<Env, &Fr> for Val {
528 type Error = ConversionError;
529
530 fn try_from_val(_env: &Env, fr: &&Fr) -> Result<Self, Self::Error> {
531 Ok(fr.to_val())
532 }
533}
534
535#[cfg(not(target_family = "wasm"))]
536impl From<&Fr> for ScVal {
537 fn from(v: &Fr) -> Self {
538 Self::from(&v.0)
539 }
540}
541
542#[cfg(not(target_family = "wasm"))]
543impl From<Fr> for ScVal {
544 fn from(v: Fr) -> Self {
545 (&v).into()
546 }
547}
548
549impl Eq for Fr {}
550
551impl PartialEq for Fr {
552 fn eq(&self, other: &Self) -> bool {
553 self.as_u256().partial_cmp(other.as_u256()) == Some(Ordering::Equal)
554 }
555}
556
557impl Debug for Fr {
558 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
559 write!(f, "Fr({:?})", self.as_u256())
560 }
561}
562
563impl Add for Fr {
564 type Output = Fr;
565
566 fn add(self, rhs: Self) -> Self::Output {
567 self.env().crypto().bls12_381().fr_add(&self, &rhs)
568 }
569}
570
571impl Sub for Fr {
572 type Output = Fr;
573
574 fn sub(self, rhs: Self) -> Self::Output {
575 self.env().crypto().bls12_381().fr_sub(&self, &rhs)
576 }
577}
578
579impl Mul for Fr {
580 type Output = Fr;
581
582 fn mul(self, rhs: Self) -> Self::Output {
583 self.env().crypto().bls12_381().fr_mul(&self, &rhs)
584 }
585}
586
587impl Bls12_381 {
588 pub(crate) fn new(env: &Env) -> Bls12_381 {
589 Bls12_381 { env: env.clone() }
590 }
591
592 pub fn env(&self) -> &Env {
593 &self.env
594 }
595
596 pub fn g1_is_in_subgroup(&self, p: &G1Affine) -> bool {
600 let env = self.env();
601 let res = internal::Env::bls12_381_check_g1_is_in_subgroup(env, p.to_object())
602 .unwrap_infallible();
603 res.into()
604 }
605
606 pub fn g1_add(&self, p0: &G1Affine, p1: &G1Affine) -> G1Affine {
608 let env = self.env();
609 let bin = internal::Env::bls12_381_g1_add(env, p0.to_object(), p1.to_object())
610 .unwrap_infallible();
611 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
612 }
613
614 pub fn g1_checked_add(&self, p0: &G1Affine, p1: &G1Affine) -> Option<G1Affine> {
620 let env = self.env();
621 let bin = internal::Env::bls12_381_g1_add(env, p0.to_object(), p1.to_object())
622 .unwrap_infallible();
623 let res = unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) };
624 let is_in_correct_subgroup: bool =
625 internal::Env::bls12_381_check_g1_is_in_subgroup(env, res.to_object())
626 .unwrap_optimized()
627 .into();
628 match is_in_correct_subgroup {
629 true => Some(res),
630 false => None,
631 }
632 }
633
634 pub fn g1_mul(&self, p0: &G1Affine, scalar: &Fr) -> G1Affine {
636 let env = self.env();
637 let bin =
638 internal::Env::bls12_381_g1_mul(env, p0.to_object(), scalar.into()).unwrap_infallible();
639 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
640 }
641
642 pub fn g1_msm(&self, vp: Vec<G1Affine>, vs: Vec<Fr>) -> G1Affine {
644 let env = self.env();
645 let bin = internal::Env::bls12_381_g1_msm(env, vp.into(), vs.into()).unwrap_infallible();
646 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
647 }
648
649 pub fn map_fp_to_g1(&self, fp: &Fp) -> G1Affine {
651 let env = self.env();
652 let bin = internal::Env::bls12_381_map_fp_to_g1(env, fp.to_object()).unwrap_infallible();
653 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
654 }
655
656 pub fn hash_to_g1(&self, msg: &Bytes, dst: &Bytes) -> G1Affine {
658 let env = self.env();
659 let bin = internal::Env::bls12_381_hash_to_g1(env, msg.into(), dst.to_object())
660 .unwrap_infallible();
661 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
662 }
663
664 pub fn g2_is_in_subgroup(&self, p: &G2Affine) -> bool {
668 let env = self.env();
669 let res = internal::Env::bls12_381_check_g2_is_in_subgroup(env, p.to_object())
670 .unwrap_infallible();
671 res.into()
672 }
673
674 pub fn g2_add(&self, p0: &G2Affine, p1: &G2Affine) -> G2Affine {
676 let env = self.env();
677 let bin = internal::Env::bls12_381_g2_add(env, p0.to_object(), p1.to_object())
678 .unwrap_infallible();
679 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
680 }
681
682 pub fn g2_checked_add(&self, p0: &G2Affine, p1: &G2Affine) -> Option<G2Affine> {
688 let env = self.env();
689 let bin = internal::Env::bls12_381_g2_add(env, p0.to_object(), p1.to_object())
690 .unwrap_infallible();
691 let res = unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) };
692 let is_in_correct_subgroup: bool =
693 internal::Env::bls12_381_check_g2_is_in_subgroup(env, res.to_object())
694 .unwrap_optimized()
695 .into();
696 match is_in_correct_subgroup {
697 true => Some(res),
698 false => None,
699 }
700 }
701
702 pub fn g2_mul(&self, p0: &G2Affine, scalar: &Fr) -> G2Affine {
704 let env = self.env();
705 let bin =
706 internal::Env::bls12_381_g2_mul(env, p0.to_object(), scalar.into()).unwrap_infallible();
707 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
708 }
709
710 pub fn g2_msm(&self, vp: Vec<G2Affine>, vs: Vec<Fr>) -> G2Affine {
712 let env = self.env();
713 let bin = internal::Env::bls12_381_g2_msm(env, vp.into(), vs.into()).unwrap_infallible();
714 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
715 }
716
717 pub fn map_fp2_to_g2(&self, fp2: &Fp2) -> G2Affine {
719 let env = self.env();
720 let bin = internal::Env::bls12_381_map_fp2_to_g2(env, fp2.to_object()).unwrap_infallible();
721 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
722 }
723
724 pub fn hash_to_g2(&self, msg: &Bytes, dst: &Bytes) -> G2Affine {
726 let env = self.env();
727 let bin = internal::Env::bls12_381_hash_to_g2(env, msg.into(), dst.to_object())
728 .unwrap_infallible();
729 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
730 }
731
732 pub fn pairing_check(&self, vp1: Vec<G1Affine>, vp2: Vec<G2Affine>) -> bool {
747 let env = self.env();
748 internal::Env::bls12_381_multi_pairing_check(env, vp1.into(), vp2.into())
749 .unwrap_infallible()
750 .into()
751 }
752
753 pub fn fr_add(&self, lhs: &Fr, rhs: &Fr) -> Fr {
757 let env = self.env();
758 let v = internal::Env::bls12_381_fr_add(env, lhs.into(), rhs.into()).unwrap_infallible();
759 U256::try_from_val(env, &v).unwrap_infallible().into()
760 }
761
762 pub fn fr_sub(&self, lhs: &Fr, rhs: &Fr) -> Fr {
764 let env = self.env();
765 let v = internal::Env::bls12_381_fr_sub(env, lhs.into(), rhs.into()).unwrap_infallible();
766 U256::try_from_val(env, &v).unwrap_infallible().into()
767 }
768
769 pub fn fr_mul(&self, lhs: &Fr, rhs: &Fr) -> Fr {
771 let env = self.env();
772 let v = internal::Env::bls12_381_fr_mul(env, lhs.into(), rhs.into()).unwrap_infallible();
773 U256::try_from_val(env, &v).unwrap_infallible().into()
774 }
775
776 pub fn fr_pow(&self, lhs: &Fr, rhs: u64) -> Fr {
778 let env = self.env();
779 let rhs = U64Val::try_from_val(env, &rhs).unwrap_optimized();
780 let v = internal::Env::bls12_381_fr_pow(env, lhs.into(), rhs).unwrap_infallible();
781 U256::try_from_val(env, &v).unwrap_infallible().into()
782 }
783
784 pub fn fr_inv(&self, lhs: &Fr) -> Fr {
786 let env = self.env();
787 let v = internal::Env::bls12_381_fr_inv(env, lhs.into()).unwrap_infallible();
788 U256::try_from_val(env, &v).unwrap_infallible().into()
789 }
790}
791
792#[cfg(test)]
793mod test {
794 use super::*;
795 use crate::bytesn;
796
797 #[test]
798 fn test_g1affine_to_val() {
799 let env = Env::default();
800
801 let g1 = G1Affine::from_bytes(BytesN::from_array(&env, &[1; 96]));
802 let val: Val = g1.clone().into_val(&env);
803 let rt: G1Affine = val.into_val(&env);
804
805 assert_eq!(g1, rt);
806 }
807
808 #[test]
809 fn test_ref_g1affine_to_val() {
810 let env = Env::default();
811
812 let g1 = G1Affine::from_bytes(BytesN::from_array(&env, &[1; 96]));
813 let val: Val = (&g1).into_val(&env);
814 let rt: G1Affine = val.into_val(&env);
815
816 assert_eq!(g1, rt);
817 }
818
819 #[test]
820 fn test_doule_ref_g1affine_to_val() {
821 let env = Env::default();
822
823 let g1 = G1Affine::from_bytes(BytesN::from_array(&env, &[1; 96]));
824 let val: Val = (&&g1).into_val(&env);
825 let rt: G1Affine = val.into_val(&env);
826
827 assert_eq!(g1, rt);
828 }
829
830 #[test]
831 fn test_fr_to_val() {
832 let env = Env::default();
833
834 let fr = Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
835 let val: Val = fr.clone().into_val(&env);
836 let rt: Fr = val.into_val(&env);
837
838 assert_eq!(fr, rt);
839 }
840
841 #[test]
842 fn test_ref_fr_to_val() {
843 let env = Env::default();
844
845 let fr = Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
846 let val: Val = (&fr).into_val(&env);
847 let rt: Fr = val.into_val(&env);
848
849 assert_eq!(fr, rt);
850 }
851
852 #[test]
853 fn test_double_ref_fr_to_val() {
854 let env = Env::default();
855
856 let fr = Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
857 let val: Val = (&&fr).into_val(&env);
858 let rt: Fr = val.into_val(&env);
859
860 assert_eq!(fr, rt);
861 }
862
863 #[test]
864 fn test_fr_eq_both_unreduced() {
865 let env = Env::default();
866 let r = fr_modulus(&env);
867 let one = U256::from_u32(&env, 1);
868
869 let a = Fr::from_u256(r.add(&one));
870 let b = Fr::from_u256(one.clone());
871 assert_eq!(a, b);
872
873 let two_r_plus_one = r.add(&r).add(&one);
874 let c = Fr::from_u256(two_r_plus_one);
875 assert_eq!(a, c);
876 assert_eq!(b, c);
877 }
878
879 #[test]
880 fn test_fr_eq_unreduced_vs_zero() {
881 let env = Env::default();
882 let r = fr_modulus(&env);
883 let zero = U256::from_u32(&env, 0);
884
885 let a = Fr::from_u256(r);
886 let b = Fr::from_u256(zero);
887 assert_eq!(a, b);
888 }
889
890 #[test]
891 fn test_fr_reduced_value_unchanged() {
892 let env = Env::default();
893 let r = fr_modulus(&env);
894 let val = r.sub(&U256::from_u32(&env, 1));
895
896 let fr = Fr::from_u256(val.clone());
897 assert_eq!(fr.to_u256(), val);
898
899 let fr42 = Fr::from_u256(U256::from_u32(&env, 42));
900 assert_eq!(fr42.to_u256(), U256::from_u32(&env, 42));
901 }
902
903 #[test]
904 fn test_fr_from_bytes_reduces() {
905 let env = Env::default();
906 let one_fr = Fr::from_u256(U256::from_u32(&env, 1));
907
908 let fr_from_bytes = Fr::from_bytes(bytesn!(
910 &env,
911 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000002
912 ));
913 assert_eq!(fr_from_bytes, one_fr);
914 }
915
916 #[test]
917 fn test_fr_try_from_val_reduces() {
918 let env = Env::default();
919 let r = fr_modulus(&env);
920 let one = U256::from_u32(&env, 1);
921
922 let unreduced_u256 = r.add(&one);
923 let val: Val = unreduced_u256.into_val(&env);
924 let fr_from_val: Fr = val.into_val(&env);
925 let fr_one = Fr::from_u256(one);
926 assert_eq!(fr_from_val, fr_one);
927 }
928
929 #[test]
930 fn test_fr_u256_into_reduces() {
931 let env = Env::default();
933 let r = fr_modulus(&env);
934 let one = U256::from_u32(&env, 1);
935
936 let fr: Fr = r.add(&one).into(); let fr_one: Fr = one.into();
938 assert_eq!(fr, fr_one);
939 }
940
941 #[test]
942 fn test_fr_eq_unreduced_vs_host_computed() {
943 let env = Env::default();
945 let bls = Bls12_381::new(&env);
946 let r = fr_modulus(&env);
947 let five = U256::from_u32(&env, 5);
948
949 let user_fr = Fr::from_u256(r.add(&five));
951 let host_fr = bls.fr_add(
953 &Fr::from_u256(U256::from_u32(&env, 2)),
954 &Fr::from_u256(U256::from_u32(&env, 3)),
955 );
956 assert_eq!(user_fr, host_fr);
957 }
958
959 #[test]
962 fn test_fp_max_valid_accepted() {
963 let env = Env::default();
964 let mut p_minus_1 = BLS12_381_FP_MODULUS_BE;
966 p_minus_1[FP_SERIALIZED_SIZE - 1] -= 1;
967 let _ = Fp::from_array(&env, &p_minus_1);
968 }
969
970 #[test]
971 #[should_panic(expected = "Bls12-381: Invalid Fp")]
972 fn test_fp_at_modulus_panics() {
973 let env = Env::default();
974 let _ = Fp::from_array(&env, &BLS12_381_FP_MODULUS_BE);
975 }
976
977 #[test]
978 #[should_panic(expected = "Bls12-381: Invalid Fp")]
979 fn test_fp_above_modulus_panics() {
980 let env = Env::default();
981 let mut above = BLS12_381_FP_MODULUS_BE;
982 above[FP_SERIALIZED_SIZE - 1] += 1; let _ = Fp::from_array(&env, &above);
984 }
985
986 #[test]
987 fn test_fp_from_bytes_validates() {
988 let env = Env::default();
989 let _ = Fp::from_bytes(BytesN::from_array(&env, &[0u8; FP_SERIALIZED_SIZE]));
991 }
992
993 #[test]
994 #[should_panic(expected = "Bls12-381: Invalid Fp")]
995 fn test_fp_from_bytes_rejects_modulus() {
996 let env = Env::default();
997 let _ = Fp::from_bytes(BytesN::from_array(&env, &BLS12_381_FP_MODULUS_BE));
998 }
999
1000 #[test]
1001 #[should_panic(expected = "Bls12-381: Invalid Fp")]
1002 fn test_fp_try_from_val_rejects_modulus() {
1003 let env = Env::default();
1004 let bytes = BytesN::from_array(&env, &BLS12_381_FP_MODULUS_BE);
1005 let val: Val = bytes.into_val(&env);
1006 let _: Fp = val.into_val(&env);
1007 }
1008
1009 #[test]
1010 #[should_panic(expected = "Bls12-381: Invalid Fp")]
1011 fn test_fp2_component_above_modulus_panics() {
1012 let env = Env::default();
1013 let mut fp2_bytes = [0u8; FP2_SERIALIZED_SIZE];
1015 fp2_bytes[0..FP_SERIALIZED_SIZE].copy_from_slice(&BLS12_381_FP_MODULUS_BE);
1016 let _ = Fp2::from_array(&env, &fp2_bytes);
1017 }
1018
1019 #[test]
1020 #[should_panic(expected = "Bls12-381: Invalid Fp")]
1021 fn test_fp2_second_component_above_modulus_panics() {
1022 let env = Env::default();
1023 let mut fp2_bytes = [0u8; FP2_SERIALIZED_SIZE];
1025 fp2_bytes[FP_SERIALIZED_SIZE..].copy_from_slice(&BLS12_381_FP_MODULUS_BE);
1026 let _ = Fp2::from_array(&env, &fp2_bytes);
1027 }
1028
1029 #[test]
1030 fn test_fp2_max_valid_accepted() {
1031 let env = Env::default();
1032 let mut p_minus_1 = BLS12_381_FP_MODULUS_BE;
1034 p_minus_1[FP_SERIALIZED_SIZE - 1] -= 1;
1035 let mut fp2_bytes = [0u8; FP2_SERIALIZED_SIZE];
1036 fp2_bytes[0..FP_SERIALIZED_SIZE].copy_from_slice(&p_minus_1);
1037 fp2_bytes[FP_SERIALIZED_SIZE..].copy_from_slice(&p_minus_1);
1038 let _ = Fp2::from_array(&env, &fp2_bytes);
1039 }
1040
1041 #[test]
1042 fn test_bls12_381_fp_modulus_matches_arkworks() {
1043 use ark_bls12_381::Fq;
1044 use ark_ff::{BigInteger, PrimeField};
1045
1046 let be_bytes = Fq::MODULUS.to_bytes_be();
1047 assert_eq!(
1048 be_bytes.as_slice(),
1049 &BLS12_381_FP_MODULUS_BE,
1050 "BLS12-381 Fp modulus does not match arkworks"
1051 );
1052 }
1053
1054 #[test]
1055 fn test_bls12_381_fr_modulus_matches_arkworks() {
1056 use ark_bls12_381::Fr as ArkFr;
1057 use ark_ff::{BigInteger, PrimeField};
1058
1059 let be_bytes = ArkFr::MODULUS.to_bytes_be();
1060 assert_eq!(
1061 be_bytes.as_slice(),
1062 &BLS12_381_FR_MODULUS_BE,
1063 "BLS12-381 Fr modulus does not match arkworks"
1064 );
1065 }
1066}