1#[cfg(not(target_family = "wasm"))]
2use crate::xdr::ScVal;
3use crate::{
4 crypto::utils::BigInt,
5 env::internal::{self, BytesObject, U256Val, U64Val},
6 unwrap::{UnwrapInfallible, UnwrapOptimized},
7 Bytes, BytesN, ConversionError, Env, IntoVal, TryFromVal, Val, Vec, U256,
8};
9use core::{
10 cmp::Ordering,
11 fmt::Debug,
12 ops::{Add, Mul, Neg, Sub},
13};
14
15pub const BN254_FP_SERIALIZED_SIZE: usize = 32; pub const BN254_G1_SERIALIZED_SIZE: usize = BN254_FP_SERIALIZED_SIZE * 2; pub const BN254_G2_SERIALIZED_SIZE: usize = BN254_G1_SERIALIZED_SIZE * 2; pub struct Bn254 {
22 env: Env,
23}
24
25#[derive(Clone)]
44#[repr(transparent)]
45pub struct Bn254G1Affine(BytesN<BN254_G1_SERIALIZED_SIZE>);
46
47#[derive(Clone)]
67#[repr(transparent)]
68pub struct Bn254G2Affine(BytesN<BN254_G2_SERIALIZED_SIZE>);
69
70#[derive(Clone)]
76#[repr(transparent)]
77pub struct Bn254Fr(U256);
78
79#[deprecated(note = "use `Bn254Fr` instead to avoid ambiguity with `Bls12381Fr`")]
82pub type Fr = Bn254Fr;
83
84#[derive(Clone)]
90#[repr(transparent)]
91pub struct Bn254Fp(BytesN<BN254_FP_SERIALIZED_SIZE>);
92
93impl_bytesn_repr!(Bn254G1Affine, BN254_G1_SERIALIZED_SIZE);
94impl_bytesn_repr!(Bn254G2Affine, BN254_G2_SERIALIZED_SIZE);
95impl_bytesn_repr!(Bn254Fp, BN254_FP_SERIALIZED_SIZE);
96
97const BN254_FP_MODULUS_BE: [u8; BN254_FP_SERIALIZED_SIZE] = [
100 0x30, 0x64, 0x4e, 0x72, 0xe1, 0x31, 0xa0, 0x29, 0xb8, 0x50, 0x45, 0xb6, 0x81, 0x81, 0x58, 0x5d,
101 0x97, 0x81, 0x6a, 0x91, 0x68, 0x71, 0xca, 0x8d, 0x3c, 0x20, 0x8c, 0x16, 0xd8, 0x7c, 0xfd, 0x47,
102];
103
104fn validate_bn254_fp(bytes: &[u8; BN254_FP_SERIALIZED_SIZE]) {
105 if bytes >= &BN254_FP_MODULUS_BE {
106 sdk_panic!("Bn254: Invalid Fp");
107 }
108}
109
110impl Bn254G1Affine {
111 pub fn from_bytes(bytes: BytesN<BN254_G1_SERIALIZED_SIZE>) -> Self {
114 Self(bytes)
115 }
116}
117
118impl Bn254G2Affine {
119 pub fn from_bytes(bytes: BytesN<BN254_G2_SERIALIZED_SIZE>) -> Self {
122 Self(bytes)
123 }
124}
125
126impl Bn254Fp {
127 pub fn from_bytes(bytes: BytesN<BN254_FP_SERIALIZED_SIZE>) -> Self {
128 validate_bn254_fp(&bytes.to_array());
129 Self(bytes)
130 }
131}
132
133impl Bn254G1Affine {
134 pub fn env(&self) -> &Env {
135 self.0.env()
136 }
137}
138
139impl Bn254Fp {
140 pub fn env(&self) -> &Env {
141 self.0.env()
142 }
143
144 fn checked_neg(&self) -> Option<Bn254Fp> {
150 let fq_bigint: BigInt<4> = (&self.0).into();
151 if fq_bigint.is_zero() {
152 return Some(self.clone());
153 }
154
155 const BN254_MODULUS: [u64; 4] = [
157 4332616871279656263,
158 10917124144477883021,
159 13281191951274694749,
160 3486998266802970665,
161 ];
162 let mut res = BigInt(BN254_MODULUS);
163
164 let borrow = res.sub_with_borrow(&fq_bigint);
166 if borrow {
167 return None;
168 }
169
170 let mut bytes = [0u8; BN254_FP_SERIALIZED_SIZE];
171 res.copy_into_array(&mut bytes);
172 Some(Bn254Fp::from_array(self.env(), &bytes))
173 }
174}
175
176impl Neg for &Bn254Fp {
177 type Output = Bn254Fp;
178
179 fn neg(self) -> Self::Output {
180 match self.checked_neg() {
181 Some(v) => v,
182 None => sdk_panic!("invalid input - Bn254Fp is larger than the field modulus"),
183 }
184 }
185}
186
187impl Neg for Bn254Fp {
188 type Output = Bn254Fp;
189
190 fn neg(self) -> Self::Output {
191 (&self).neg()
192 }
193}
194
195impl Add for Bn254G1Affine {
196 type Output = Bn254G1Affine;
197
198 fn add(self, rhs: Self) -> Self::Output {
199 self.env().crypto().bn254().g1_add(&self, &rhs)
200 }
201}
202
203impl Mul<Bn254Fr> for Bn254G1Affine {
204 type Output = Bn254G1Affine;
205
206 fn mul(self, rhs: Bn254Fr) -> Self::Output {
207 self.env().crypto().bn254().g1_mul(&self, &rhs)
208 }
209}
210
211impl Neg for &Bn254G1Affine {
214 type Output = Bn254G1Affine;
215
216 fn neg(self) -> Self::Output {
217 let mut inner: Bytes = (&self.0).into();
218 let y = Bn254Fp::try_from_val(
219 inner.env(),
220 inner.slice(BN254_FP_SERIALIZED_SIZE as u32..).as_val(),
221 )
222 .unwrap_optimized();
223 let neg_y = -y;
224 inner.copy_from_slice(BN254_FP_SERIALIZED_SIZE as u32, &neg_y.to_array());
225 Bn254G1Affine::from_bytes(
226 BytesN::try_from_val(inner.env(), inner.as_val()).unwrap_optimized(),
227 )
228 }
229}
230
231impl Neg for Bn254G1Affine {
232 type Output = Bn254G1Affine;
233
234 fn neg(self) -> Self::Output {
235 (&self).neg()
236 }
237}
238
239impl Bn254G2Affine {
240 pub fn env(&self) -> &Env {
241 self.0.env()
242 }
243}
244
245impl Bn254Fr {
246 pub fn env(&self) -> &Env {
247 self.0.env()
248 }
249
250 pub fn from_u256(value: U256) -> Self {
251 value.into()
252 }
253
254 pub fn to_u256(&self) -> U256 {
255 self.0.clone()
256 }
257
258 pub fn as_u256(&self) -> &U256 {
259 &self.0
260 }
261
262 pub fn from_bytes(bytes: BytesN<32>) -> Self {
263 U256::from_be_bytes(bytes.env(), bytes.as_ref()).into()
264 }
265
266 pub fn to_bytes(&self) -> BytesN<32> {
267 self.as_u256().to_be_bytes().try_into().unwrap_optimized()
268 }
269
270 pub fn as_val(&self) -> &Val {
271 self.0.as_val()
272 }
273
274 pub fn to_val(&self) -> Val {
275 self.0.to_val()
276 }
277
278 pub fn pow(&self, rhs: u64) -> Self {
279 self.env().crypto().bn254().fr_pow(self, rhs)
280 }
281
282 pub fn inv(&self) -> Self {
283 self.env().crypto().bn254().fr_inv(self)
284 }
285}
286
287impl Add for Bn254Fr {
288 type Output = Bn254Fr;
289
290 fn add(self, rhs: Self) -> Self::Output {
291 self.env().crypto().bn254().fr_add(&self, &rhs)
292 }
293}
294
295impl Sub for Bn254Fr {
296 type Output = Bn254Fr;
297
298 fn sub(self, rhs: Self) -> Self::Output {
299 self.env().crypto().bn254().fr_sub(&self, &rhs)
300 }
301}
302
303impl Mul for Bn254Fr {
304 type Output = Bn254Fr;
305
306 fn mul(self, rhs: Self) -> Self::Output {
307 self.env().crypto().bn254().fr_mul(&self, &rhs)
308 }
309}
310
311const BN254_FR_MODULUS_BE: [u8; 32] = [
314 0x30, 0x64, 0x4e, 0x72, 0xe1, 0x31, 0xa0, 0x29, 0xb8, 0x50, 0x45, 0xb6, 0x81, 0x81, 0x58, 0x5d,
315 0x28, 0x33, 0xe8, 0x48, 0x79, 0xb9, 0x70, 0x91, 0x43, 0xe1, 0xf5, 0x93, 0xf0, 0x00, 0x00, 0x01,
316];
317
318fn fr_modulus(env: &Env) -> U256 {
319 U256::from_be_bytes(env, &Bytes::from_array(env, &BN254_FR_MODULUS_BE))
320}
321
322impl From<U256> for Bn254Fr {
323 fn from(value: U256) -> Self {
324 let modulus = fr_modulus(value.env());
329 if value >= modulus {
330 Self(value.rem_euclid(&modulus))
331 } else {
332 Self(value)
333 }
334 }
335}
336
337impl From<&Bn254Fr> for U256Val {
338 fn from(value: &Bn254Fr) -> Self {
339 value.as_u256().into()
340 }
341}
342
343impl TryFromVal<Env, Val> for Bn254Fr {
344 type Error = ConversionError;
345
346 fn try_from_val(env: &Env, val: &Val) -> Result<Self, Self::Error> {
347 let u = U256::try_from_val(env, val)?;
348 Ok(u.into())
349 }
350}
351
352impl TryFromVal<Env, Bn254Fr> for Val {
353 type Error = ConversionError;
354
355 fn try_from_val(_env: &Env, fr: &Bn254Fr) -> Result<Self, Self::Error> {
356 Ok(fr.to_val())
357 }
358}
359
360impl TryFromVal<Env, &Bn254Fr> for Val {
361 type Error = ConversionError;
362
363 fn try_from_val(_env: &Env, fr: &&Bn254Fr) -> Result<Self, Self::Error> {
364 Ok(fr.to_val())
365 }
366}
367
368#[cfg(not(target_family = "wasm"))]
369impl From<&Bn254Fr> for ScVal {
370 fn from(v: &Bn254Fr) -> Self {
371 Self::from(&v.0)
372 }
373}
374
375#[cfg(not(target_family = "wasm"))]
376impl From<Bn254Fr> for ScVal {
377 fn from(v: Bn254Fr) -> Self {
378 (&v).into()
379 }
380}
381
382impl Eq for Bn254Fr {}
383
384impl PartialEq for Bn254Fr {
385 fn eq(&self, other: &Self) -> bool {
386 self.as_u256().partial_cmp(other.as_u256()) == Some(core::cmp::Ordering::Equal)
387 }
388}
389
390impl Debug for Bn254Fr {
391 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
392 write!(f, "Bn254Fr({:?})", self.as_u256())
393 }
394}
395
396impl Bn254 {
397 pub(crate) fn new(env: &Env) -> Bn254 {
398 Bn254 { env: env.clone() }
399 }
400
401 pub fn env(&self) -> &Env {
402 &self.env
403 }
404
405 pub fn g1_add(&self, p0: &Bn254G1Affine, p1: &Bn254G1Affine) -> Bn254G1Affine {
407 let env = self.env();
408 let bin =
409 internal::Env::bn254_g1_add(env, p0.to_object(), p1.to_object()).unwrap_infallible();
410 unsafe { Bn254G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
411 }
412
413 pub fn g1_mul(&self, p0: &Bn254G1Affine, scalar: &Bn254Fr) -> Bn254G1Affine {
415 let env = self.env();
416 let bin =
417 internal::Env::bn254_g1_mul(env, p0.to_object(), scalar.into()).unwrap_infallible();
418 unsafe { Bn254G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
419 }
420
421 pub fn pairing_check(&self, vp1: Vec<Bn254G1Affine>, vp2: Vec<Bn254G2Affine>) -> bool {
436 let env = self.env();
437 internal::Env::bn254_multi_pairing_check(env, vp1.into(), vp2.into())
438 .unwrap_infallible()
439 .into()
440 }
441
442 pub fn g1_msm(&self, vp: Vec<Bn254G1Affine>, vs: Vec<Bn254Fr>) -> Bn254G1Affine {
444 let env = self.env();
445 let bin = internal::Env::bn254_g1_msm(env, vp.into(), vs.into()).unwrap_infallible();
446 unsafe { Bn254G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
447 }
448
449 pub fn g1_is_on_curve(&self, point: &Bn254G1Affine) -> bool {
451 let env = self.env();
452 internal::Env::bn254_g1_is_on_curve(env, point.to_object())
453 .unwrap_infallible()
454 .into()
455 }
456
457 pub fn fr_add(&self, lhs: &Bn254Fr, rhs: &Bn254Fr) -> Bn254Fr {
461 let env = self.env();
462 let v = internal::Env::bn254_fr_add(env, lhs.into(), rhs.into()).unwrap_infallible();
463 U256::try_from_val(env, &v).unwrap_infallible().into()
464 }
465
466 pub fn fr_sub(&self, lhs: &Bn254Fr, rhs: &Bn254Fr) -> Bn254Fr {
468 let env = self.env();
469 let v = internal::Env::bn254_fr_sub(env, lhs.into(), rhs.into()).unwrap_infallible();
470 U256::try_from_val(env, &v).unwrap_infallible().into()
471 }
472
473 pub fn fr_mul(&self, lhs: &Bn254Fr, rhs: &Bn254Fr) -> Bn254Fr {
475 let env = self.env();
476 let v = internal::Env::bn254_fr_mul(env, lhs.into(), rhs.into()).unwrap_infallible();
477 U256::try_from_val(env, &v).unwrap_infallible().into()
478 }
479
480 pub fn fr_pow(&self, lhs: &Bn254Fr, rhs: u64) -> Bn254Fr {
482 let env = self.env();
483 let rhs = U64Val::try_from_val(env, &rhs).unwrap_optimized();
484 let v = internal::Env::bn254_fr_pow(env, lhs.into(), rhs).unwrap_infallible();
485 U256::try_from_val(env, &v).unwrap_infallible().into()
486 }
487
488 pub fn fr_inv(&self, lhs: &Bn254Fr) -> Bn254Fr {
490 let env = self.env();
491 let v = internal::Env::bn254_fr_inv(env, lhs.into()).unwrap_infallible();
492 U256::try_from_val(env, &v).unwrap_infallible().into()
493 }
494}
495
496#[cfg(test)]
497mod test {
498 use super::*;
499
500 #[test]
501 fn test_g1affine_to_val() {
502 let env = Env::default();
503
504 let g1 = Bn254G1Affine::from_bytes(BytesN::from_array(&env, &[1; 64]));
505 let val: Val = g1.clone().into_val(&env);
506 let rt: Bn254G1Affine = val.into_val(&env);
507
508 assert_eq!(g1, rt);
509 }
510
511 #[test]
512 fn test_ref_g1affine_to_val() {
513 let env = Env::default();
514
515 let g1 = Bn254G1Affine::from_bytes(BytesN::from_array(&env, &[1; 64]));
516 let val: Val = (&g1).into_val(&env);
517 let rt: Bn254G1Affine = val.into_val(&env);
518
519 assert_eq!(g1, rt);
520 }
521
522 #[test]
523 fn test_double_ref_g1affine_to_val() {
524 let env = Env::default();
525
526 let g1 = Bn254G1Affine::from_bytes(BytesN::from_array(&env, &[1; 64]));
527 let val: Val = (&&g1).into_val(&env);
528 let rt: Bn254G1Affine = val.into_val(&env);
529
530 assert_eq!(g1, rt);
531 }
532
533 #[test]
534 fn test_fr_to_val() {
535 let env = Env::default();
536
537 let fr = Bn254Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
538 let val: Val = fr.clone().into_val(&env);
539 let rt: Bn254Fr = val.into_val(&env);
540
541 assert_eq!(fr, rt);
542 }
543
544 #[test]
545 fn test_ref_fr_to_val() {
546 let env = Env::default();
547
548 let fr = Bn254Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
549 let val: Val = (&fr).into_val(&env);
550 let rt: Bn254Fr = val.into_val(&env);
551
552 assert_eq!(fr, rt);
553 }
554
555 #[test]
556 fn test_double_ref_fr_to_val() {
557 let env = Env::default();
558
559 let fr = Bn254Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
560 let val: Val = (&&fr).into_val(&env);
561 let rt: Bn254Fr = val.into_val(&env);
562
563 assert_eq!(fr, rt);
564 }
565
566 #[test]
567 fn test_fr_eq_both_unreduced() {
568 let env = Env::default();
570 let r = fr_modulus(&env);
571 let one = U256::from_u32(&env, 1);
572
573 let a = Bn254Fr::from_u256(r.add(&one)); let b = Bn254Fr::from_u256(one.clone()); assert_eq!(a, b);
576
577 let two_r_plus_one = r.add(&r).add(&one);
579 let c = Bn254Fr::from_u256(two_r_plus_one); assert_eq!(a, c);
581 assert_eq!(b, c);
582 }
583
584 #[test]
585 fn test_fr_eq_unreduced_vs_zero() {
586 let env = Env::default();
588 let r = fr_modulus(&env);
589 let zero = U256::from_u32(&env, 0);
590
591 let a = Bn254Fr::from_u256(r);
592 let b = Bn254Fr::from_u256(zero);
593 assert_eq!(a, b);
594 }
595
596 #[test]
597 fn test_fr_reduced_value_unchanged() {
598 let env = Env::default();
600 let r = fr_modulus(&env);
601 let val = r.sub(&U256::from_u32(&env, 1)); let fr = Bn254Fr::from_u256(val.clone());
604 assert_eq!(fr.to_u256(), val);
605
606 let fr42 = Bn254Fr::from_u256(U256::from_u32(&env, 42));
608 assert_eq!(fr42.to_u256(), U256::from_u32(&env, 42));
609 }
610
611 #[test]
612 fn test_fr_from_bytes_reduces() {
613 let env = Env::default();
615 let one_fr = Bn254Fr::from_u256(U256::from_u32(&env, 1));
616
617 let fr_from_bytes = Bn254Fr::from_bytes(bytesn!(
619 &env,
620 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000002
621 ));
622 assert_eq!(fr_from_bytes, one_fr);
623 }
624
625 #[test]
626 fn test_fr_try_from_val_reduces() {
627 let env = Env::default();
629 let r = fr_modulus(&env);
630 let one = U256::from_u32(&env, 1);
631
632 let unreduced_u256 = r.add(&one);
634 let val: Val = unreduced_u256.into_val(&env);
635 let fr_from_val: Bn254Fr = val.into_val(&env);
636 let fr_one = Bn254Fr::from_u256(one);
637 assert_eq!(fr_from_val, fr_one);
638 }
639
640 #[test]
641 fn test_fr_u256_into_reduces() {
642 let env = Env::default();
644 let r = fr_modulus(&env);
645 let one = U256::from_u32(&env, 1);
646
647 let fr: Bn254Fr = r.add(&one).into(); let fr_one: Bn254Fr = one.into();
649 assert_eq!(fr, fr_one);
650 }
651
652 #[test]
655 fn test_bn254_fp_max_valid_accepted() {
656 let env = Env::default();
657 let mut p_minus_1 = BN254_FP_MODULUS_BE;
659 p_minus_1[BN254_FP_SERIALIZED_SIZE - 1] -= 1;
660 let _ = Bn254Fp::from_array(&env, &p_minus_1);
661 }
662
663 #[test]
664 #[should_panic(expected = "Bn254: Invalid Fp")]
665 fn test_bn254_fp_at_modulus_panics() {
666 let env = Env::default();
667 let _ = Bn254Fp::from_array(&env, &BN254_FP_MODULUS_BE);
668 }
669
670 #[test]
671 #[should_panic(expected = "Bn254: Invalid Fp")]
672 fn test_bn254_fp_above_modulus_panics() {
673 let env = Env::default();
674 let mut above = BN254_FP_MODULUS_BE;
675 above[BN254_FP_SERIALIZED_SIZE - 1] += 1; let _ = Bn254Fp::from_array(&env, &above);
677 }
678
679 #[test]
680 fn test_bn254_fp_from_bytes_validates() {
681 let env = Env::default();
682 let _ = Bn254Fp::from_bytes(BytesN::from_array(&env, &[0u8; BN254_FP_SERIALIZED_SIZE]));
684 }
685
686 #[test]
687 #[should_panic(expected = "Bn254: Invalid Fp")]
688 fn test_bn254_fp_from_bytes_rejects_modulus() {
689 let env = Env::default();
690 let _ = Bn254Fp::from_bytes(BytesN::from_array(&env, &BN254_FP_MODULUS_BE));
691 }
692
693 #[test]
694 #[should_panic(expected = "Bn254: Invalid Fp")]
695 fn test_bn254_fp_try_from_val_rejects_modulus() {
696 let env = Env::default();
697 let bytes = BytesN::from_array(&env, &BN254_FP_MODULUS_BE);
698 let val: Val = bytes.into_val(&env);
699 let _: Bn254Fp = val.into_val(&env);
700 }
701
702 #[test]
703 fn test_bn254_fp_modulus_matches_arkworks() {
704 use ark_bn254::Fq;
705 use ark_ff::{BigInteger, PrimeField};
706
707 let be_bytes = Fq::MODULUS.to_bytes_be();
708 assert_eq!(
709 be_bytes.as_slice(),
710 &BN254_FP_MODULUS_BE,
711 "BN254 Fp modulus does not match arkworks"
712 );
713 }
714
715 #[test]
716 fn test_bn254_fr_modulus_matches_arkworks() {
717 use ark_bn254::Fr as ArkFr;
718 use ark_ff::{BigInteger, PrimeField};
719
720 let be_bytes = ArkFr::MODULUS.to_bytes_be();
721 assert_eq!(
722 be_bytes.as_slice(),
723 &BN254_FR_MODULUS_BE,
724 "BN254 Fr modulus does not match arkworks"
725 );
726 }
727}