1use noah_algebra::bls12_381::BLSScalar;
2use noah_algebra::prelude::*;
3use noah_algebra::str::FromStr;
4use num_bigint::BigUint;
5use num_integer::Integer;
6use std::marker::PhantomData;
7
8pub trait SimFrParams: Clone + Default {
10 const NUM_OF_LIMBS: usize;
12 const BIT_PER_LIMB: usize;
14 const BIT_IN_TOP_LIMB: usize;
16 const NUM_OF_LIMBS_MUL: usize = Self::NUM_OF_LIMBS * 2 - 1;
18 const NUM_OF_GROUPS: usize;
20
21 fn scalar_field_in_biguint() -> BigUint;
23
24 fn scalar_field_in_limbs() -> Vec<BLSScalar>;
26
27 fn scalar_field_sub_pad_in_limbs() -> Vec<BLSScalar>;
32
33 fn scalar_field_sub_pad_in_biguint() -> BigUint;
35}
36
37#[derive(Clone, Default, Eq, PartialEq, Debug)]
39pub struct SimFrParamsRistretto;
40
41impl SimFrParams for SimFrParamsRistretto {
42 const NUM_OF_LIMBS: usize = 6;
43 const BIT_PER_LIMB: usize = 43;
44 const BIT_IN_TOP_LIMB: usize = 38;
45 const NUM_OF_GROUPS: usize = 6;
46
47 fn scalar_field_in_biguint() -> BigUint {
48 BigUint::from_str(
49 "7237005577332262213973186563042994240857116359379907606001950938285454250989",
50 )
51 .unwrap()
52 }
53
54 fn scalar_field_in_limbs() -> Vec<BLSScalar> {
55 [
56 BLSScalar::from_str("3411763647469").unwrap(),
57 BLSScalar::from_str("7643343815244").unwrap(),
58 BLSScalar::from_str("358561053323").unwrap(),
59 BLSScalar::from_str("0").unwrap(),
60 BLSScalar::from_str("0").unwrap(),
61 BLSScalar::from_str("137438953472").unwrap(),
62 ]
63 .to_vec()
64 }
65
66 fn scalar_field_sub_pad_in_limbs() -> Vec<BLSScalar> {
67 [
68 BLSScalar::from_str("10235290942407").unwrap(),
69 BLSScalar::from_str("14133938423524").unwrap(),
70 BLSScalar::from_str("9871776182178").unwrap(),
71 BLSScalar::from_str("17592186044415").unwrap(),
72 BLSScalar::from_str("17592186044414").unwrap(),
73 BLSScalar::from_str("412316860414").unwrap(),
74 ]
75 .to_vec()
76 }
77
78 fn scalar_field_sub_pad_in_biguint() -> BigUint {
79 BigUint::from_str(
80 "21711016731996786641919559689128982722571349078139722818005852814856362752967",
81 )
82 .unwrap()
83 }
84}
85
86#[derive(Clone, Default, Eq, PartialEq, Debug)]
88pub struct SimFrParamsSecq256k1;
89
90impl SimFrParams for SimFrParamsSecq256k1 {
91 const NUM_OF_LIMBS: usize = 6;
92 const BIT_PER_LIMB: usize = 44;
93 const BIT_IN_TOP_LIMB: usize = 36;
94 const NUM_OF_GROUPS: usize = 6;
95
96 fn scalar_field_in_biguint() -> BigUint {
97 BigUint::from_str(
98 "115792089237316195423570985008687907853269984665640564039457584007908834671663",
99 )
100 .unwrap()
101 }
102
103 fn scalar_field_in_limbs() -> Vec<BLSScalar> {
104 [
105 BLSScalar::from_str("17587891076143").unwrap(),
106 BLSScalar::from_str("17592186044415").unwrap(),
107 BLSScalar::from_str("17592186044415").unwrap(),
108 BLSScalar::from_str("17592186044415").unwrap(),
109 BLSScalar::from_str("17592186044415").unwrap(),
110 BLSScalar::from_str("68719476735").unwrap(),
111 ]
112 .to_vec()
113 }
114
115 fn scalar_field_sub_pad_in_limbs() -> Vec<BLSScalar> {
116 [
117 BLSScalar::from_str("35175782152286").unwrap(),
118 BLSScalar::from_str("35184372088830").unwrap(),
119 BLSScalar::from_str("35184372088830").unwrap(),
120 BLSScalar::from_str("35184372088830").unwrap(),
121 BLSScalar::from_str("35184372088830").unwrap(),
122 BLSScalar::from_str("137438953470").unwrap(),
123 ]
124 .to_vec()
125 }
126
127 fn scalar_field_sub_pad_in_biguint() -> BigUint {
128 BigUint::from_str(
129 "231584178474632390847141970017375815706539969331281128078915168015817669343326",
130 )
131 .unwrap()
132 }
133}
134
135#[derive(Clone, Default, Eq, PartialEq, Debug)]
137pub struct SimFrParamsZorro;
138
139impl SimFrParams for SimFrParamsZorro {
140 const NUM_OF_LIMBS: usize = 6;
141 const BIT_PER_LIMB: usize = 44;
142 const BIT_IN_TOP_LIMB: usize = 36;
143 const NUM_OF_GROUPS: usize = 6;
144
145 fn scalar_field_in_biguint() -> BigUint {
146 BigUint::from_str(
147 "57896044618658097711785492504343953926634992332820282019728792003956564819949",
148 )
149 .unwrap()
150 }
151
152 fn scalar_field_in_limbs() -> Vec<BLSScalar> {
153 [
154 BLSScalar::from_str("17592186044397").unwrap(),
155 BLSScalar::from_str("17592186044415").unwrap(),
156 BLSScalar::from_str("17592186044415").unwrap(),
157 BLSScalar::from_str("17592186044415").unwrap(),
158 BLSScalar::from_str("17592186044415").unwrap(),
159 BLSScalar::from_str("34359738367").unwrap(),
160 ]
161 .to_vec()
162 }
163
164 fn scalar_field_sub_pad_in_limbs() -> Vec<BLSScalar> {
165 [
166 BLSScalar::from_str("35184372088794").unwrap(),
167 BLSScalar::from_str("35184372088830").unwrap(),
168 BLSScalar::from_str("35184372088830").unwrap(),
169 BLSScalar::from_str("35184372088830").unwrap(),
170 BLSScalar::from_str("35184372088830").unwrap(),
171 BLSScalar::from_str("68719476734").unwrap(),
172 ]
173 .to_vec()
174 }
175
176 fn scalar_field_sub_pad_in_biguint() -> BigUint {
177 BigUint::from_str(
178 "115792089237316195423570985008687907853269984665640564039457584007913129639898",
179 )
180 .unwrap()
181 }
182}
183
184#[derive(Eq, PartialEq, Clone)]
186pub enum SimReducibility {
187 StrictlyNotReducible,
189 AtMostReducibleByOne,
191 Others(BigUint),
193}
194
195impl<'a> From<&'a SimReducibility> for BigUint {
196 fn from(src: &'a SimReducibility) -> Self {
197 match src {
198 SimReducibility::StrictlyNotReducible => BigUint::zero(),
199 SimReducibility::AtMostReducibleByOne => BigUint::one(),
200 SimReducibility::Others(x) => x.clone(),
201 }
202 }
203}
204
205#[derive(Clone)]
208pub struct SimFr<P: SimFrParams> {
209 pub limbs: Vec<BLSScalar>,
211 pub val: BigUint,
213 pub num_of_additions_over_normal_form: SimReducibility,
215 pub params_phantom: PhantomData<P>,
217}
218
219impl<P: SimFrParams> Default for SimFr<P> {
220 fn default() -> Self {
221 Self {
222 limbs: vec![BLSScalar::zero(); P::NUM_OF_LIMBS],
223 val: BigUint::zero(),
224 num_of_additions_over_normal_form: SimReducibility::StrictlyNotReducible,
225 params_phantom: PhantomData::default(),
226 }
227 }
228}
229
230impl<P: SimFrParams> Sub<&SimFr<P>> for &SimFr<P> {
231 type Output = SimFr<P>;
232
233 fn sub(self, rhs: &SimFr<P>) -> SimFr<P> {
234 assert!(
239 rhs.num_of_additions_over_normal_form == SimReducibility::StrictlyNotReducible
240 || rhs.num_of_additions_over_normal_form == SimReducibility::AtMostReducibleByOne
241 );
242
243 let mut res = SimFr::<P>::default();
244 let r_limbs = P::scalar_field_sub_pad_in_limbs();
245 let r_biguint = P::scalar_field_sub_pad_in_biguint();
246
247 for i in 0..P::NUM_OF_LIMBS {
248 res.limbs[i] = self.limbs[i].add(&r_limbs[i]).sub(&rhs.limbs[i]);
249 }
250 res.val = (&self.val).add(&r_biguint).sub(&rhs.val);
251
252 res.num_of_additions_over_normal_form = SimReducibility::Others(
253 BigUint::from(&self.num_of_additions_over_normal_form) + BigUint::from(3u32),
254 );
255
256 res
257 }
258}
259
260impl<P: SimFrParams> Mul<&SimFr<P>> for &SimFr<P> {
261 type Output = SimFrMul<P>;
262
263 fn mul(self, rhs: &SimFr<P>) -> SimFrMul<P> {
264 let mut mul_res = SimFrMul::<P>::default();
265 for i in 0..P::NUM_OF_LIMBS {
266 for j in 0..P::NUM_OF_LIMBS {
267 mul_res.limbs[i + j].add_assign(&self.limbs[i].mul(&rhs.limbs[j]));
268 }
269 }
270 mul_res.val = (&self.val).mul(&rhs.val);
271 mul_res.prod_of_num_of_additions = BigUint::from(&self.num_of_additions_over_normal_form)
272 .add(&BigUint::one())
273 .mul(&BigUint::from(&rhs.num_of_additions_over_normal_form).add(&BigUint::one()));
274
275 mul_res
276 }
277}
278
279impl<P: SimFrParams> From<&BigUint> for SimFr<P> {
280 fn from(src: &BigUint) -> Self {
281 let mut rem = src.clone();
282
283 let step = BigUint::from(1u32).shl(P::BIT_PER_LIMB);
284
285 let mut res = SimFr::<P>::default();
286 res.val = rem.clone();
287 for i in 0..P::NUM_OF_LIMBS {
288 let (new_rem, limb) = rem.div_rem(&step);
289 rem = new_rem;
290 res.limbs[i] = BLSScalar::from(&limb);
291 }
292 res.num_of_additions_over_normal_form = SimReducibility::StrictlyNotReducible;
293
294 res
295 }
296}
297
298impl<P: SimFrParams> Into<BigUint> for &SimFr<P> {
299 fn into(self) -> BigUint {
300 let step = BigUint::from(1u32).shl(P::BIT_PER_LIMB);
301 let mut res = BigUint::zero();
302 for limb in self.limbs.iter().rev() {
303 res.mul_assign(&step);
304 res.add_assign(&limb.clone().into());
305 }
306 assert_eq!(res, self.val);
307 res
308 }
309}
310
311impl<P: SimFrParams> SimFr<P> {
312 pub fn is_zero(&self) -> bool {
316 let self_biguint: BigUint = self.into();
317 let r_biguint = P::scalar_field_in_biguint();
318
319 let (_, rem) = self_biguint.div_rem(&r_biguint);
320 rem.is_zero()
321 }
322}
323
324#[derive(Clone)]
328pub struct SimFrMul<P: SimFrParams> {
329 pub limbs: Vec<BLSScalar>,
331 pub val: BigUint,
333 pub prod_of_num_of_additions: BigUint,
335 pub params_phantom: PhantomData<P>,
337}
338
339impl<P: SimFrParams> Default for SimFrMul<P> {
340 fn default() -> Self {
341 Self {
342 limbs: vec![BLSScalar::zero(); P::NUM_OF_LIMBS_MUL],
343 val: BigUint::zero(),
344 prod_of_num_of_additions: BigUint::zero(),
345 params_phantom: PhantomData::default(),
346 }
347 }
348}
349
350impl<P: SimFrParams> Into<BigUint> for &SimFrMul<P> {
351 fn into(self) -> BigUint {
352 let step = BigUint::from(1u32).shl(P::BIT_PER_LIMB);
353 let mut res = BigUint::zero();
354 for limb in self.limbs.iter().rev() {
355 res.mul_assign(&step);
356 res.add_assign(&limb.clone().into());
357 }
358 assert_eq!(self.val, res);
359 res
360 }
361}
362
363impl<P: SimFrParams> Add<&SimFrMul<P>> for &SimFrMul<P> {
364 type Output = SimFrMul<P>;
365
366 fn add(self, rhs: &SimFrMul<P>) -> SimFrMul<P> {
367 let mut res = (*self).clone();
368
369 for i in 0..P::NUM_OF_LIMBS_MUL {
370 res.limbs[i] = res.limbs[i].add(&rhs.limbs[i]);
371 }
372 res.val = &res.val + &rhs.val;
373 res.prod_of_num_of_additions =
374 &res.prod_of_num_of_additions + &rhs.prod_of_num_of_additions;
375
376 res
377 }
378}
379
380impl<P: SimFrParams> Sub<&SimFr<P>> for &SimFrMul<P> {
381 type Output = SimFrMul<P>;
382
383 fn sub(self, rhs: &SimFr<P>) -> SimFrMul<P> {
384 assert!(BigUint::from(&rhs.num_of_additions_over_normal_form) <= BigUint::from(4u32));
388
389 let mut res = (*self).clone();
390 let r_limbs = P::scalar_field_sub_pad_in_limbs();
391 let r_biguint = P::scalar_field_sub_pad_in_biguint();
392
393 for i in 0..P::NUM_OF_LIMBS {
394 res.limbs[i] = res.limbs[i]
395 .add(&r_limbs[i])
396 .add(&r_limbs[i])
397 .add(&r_limbs[i])
398 .add(&r_limbs[i])
399 .sub(&rhs.limbs[i]);
400 }
401 res.val = &res.val + &r_biguint + &r_biguint + &r_biguint + &r_biguint - &rhs.val;
402 res.prod_of_num_of_additions = &res.prod_of_num_of_additions + &BigUint::from(12u32);
403
404 res
405 }
406}
407
408impl<P: SimFrParams> SimFrMul<P> {
409 pub fn enforce_zero(&self) {
424 assert!(self.prod_of_num_of_additions.bits() as usize <= 5);
427 let surfeit = 5; let cur_val: BigUint = self.into();
430 let r_biguint = P::scalar_field_in_biguint();
431
432 let (k, rem) = cur_val.div_rem(&r_biguint);
437 assert!(rem.is_zero());
438 assert!(k <= r_biguint.clone().shl(5u32));
439
440 let r_limbs = P::scalar_field_in_limbs().to_vec();
442 let k_limbs = SimFr::<P>::from(&k).limbs.to_vec();
443
444 let mut rk_limbs = vec![BLSScalar::zero(); P::NUM_OF_LIMBS_MUL];
445 for i in 0..P::NUM_OF_LIMBS {
446 for j in 0..P::NUM_OF_LIMBS {
447 rk_limbs[i + j] = rk_limbs[i + j].add(&r_limbs[i].mul(&k_limbs[j]));
448 }
449 }
450
451 let mut left_group = Vec::with_capacity(P::NUM_OF_GROUPS);
454 let mut right_group = Vec::with_capacity(P::NUM_OF_GROUPS);
455 let mut num_limbs_in_group = Vec::with_capacity(P::NUM_OF_GROUPS);
456
457 let step = BLSScalar::from(&BigUint::from(1u32).shl(P::BIT_PER_LIMB));
458 for chunk in self.limbs.chunks(2) {
459 if chunk.len() == 2 {
460 left_group.push(chunk[0].add(&chunk[1].mul(&step)));
461 } else {
462 left_group.push(chunk[0]);
463 }
464 num_limbs_in_group.push(chunk.len());
465 }
466 for chunk in rk_limbs.chunks(2) {
467 if chunk.len() == 2 {
468 right_group.push(chunk[0].add(&chunk[1].mul(&step)));
469 } else {
470 right_group.push(chunk[0]);
471 }
472 }
473
474 let mut carry_in = BLSScalar::zero();
479 let mut accumulated_extra = BigUint::zero();
480 for (group_id, ((left_group_limb, right_group_limb), num_limbs_in_this_group)) in left_group
481 .iter()
482 .zip(right_group.iter())
483 .zip(num_limbs_in_group.iter())
484 .enumerate()
485 {
486 let pad = BigUint::from(1u32).shl(
487 (num_limbs_in_this_group + 1) * P::BIT_PER_LIMB + num_limbs_in_this_group + surfeit,
488 );
489 let pad_limb = BLSScalar::from(&pad);
490 assert!(pad > <BLSScalar as Into<BigUint>>::into(right_group_limb.clone()));
491
492 let mut carry = left_group_limb
494 .add(&carry_in)
495 .add(&pad_limb)
496 .sub(&right_group_limb);
497 let carry_biguint: BigUint = carry.into();
498 carry = BLSScalar::from(&carry_biguint.shr(num_limbs_in_this_group * P::BIT_PER_LIMB));
499 accumulated_extra += BigUint::from_bytes_le(&pad_limb.to_bytes());
500
501 let (new_accumulated_extra, remainder_biguint) = accumulated_extra
502 .div_rem(&BigUint::from(1u64).shl(P::BIT_PER_LIMB * num_limbs_in_this_group));
503 let remainder = BLSScalar::from(&remainder_biguint);
504
505 let eqn_left = left_group_limb
506 .add(&pad_limb)
507 .add(&carry_in)
508 .sub(&right_group_limb);
509
510 let eqn_right = (&carry)
511 .mul(&(&BigUint::from(1u32).shl(P::BIT_PER_LIMB * num_limbs_in_this_group)).into())
512 .add(&remainder);
513
514 assert_eq!(eqn_left, eqn_right);
515
516 accumulated_extra = new_accumulated_extra;
517 carry_in = carry;
518
519 if group_id == left_group.len() - 1 {
520 assert_eq!(carry, (&accumulated_extra).into());
521 } else {
522 assert!(BigUint::from(1u32)
524 .shl(surfeit + P::BIT_PER_LIMB * 2)
525 .gt(&carry.into()));
526 }
527 }
528 }
529}
530
531#[cfg(test)]
532mod test_ristretto {
533 use crate::field_simulation::{SimFr, SimFrParams, SimFrParamsRistretto};
534 use noah_algebra::prelude::*;
535 use num_bigint::{BigUint, RandBigInt};
536 use num_integer::Integer;
537
538 type SimFrTest = SimFr<SimFrParamsRistretto>;
539
540 #[test]
541 fn test_sim_fr_biguint_conversion() {
542 let mut prng = test_rng();
543 let r_biguint = SimFrParamsRistretto::scalar_field_in_biguint();
544
545 for _ in 0..100 {
546 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
547 let a_sim_fr = SimFrTest::from(&a);
548 let a_recovered: BigUint = (&a_sim_fr).into();
549
550 assert_eq!(a, a_recovered);
551 }
552 }
553
554 #[test]
555 fn test_sub() {
556 let mut prng = test_rng();
557 let r_biguint = SimFrParamsRistretto::scalar_field_in_biguint();
558
559 for _ in 0..100 {
560 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
561 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
562
563 let a_sim_fr = SimFrTest::from(&a);
564 let b_sim_fr = SimFrTest::from(&b);
565 let sum_sim_fr = &a_sim_fr - &b_sim_fr;
566
567 let (_, sum) = a.add(&r_biguint).sub(&b).div_rem(&r_biguint);
568 let (_, sum_recovered) =
569 <&SimFrTest as Into<BigUint>>::into(&sum_sim_fr).div_rem(&r_biguint);
570
571 assert_eq!(sum, sum_recovered);
572 }
573 }
574
575 #[test]
576 fn test_mul() {
577 let mut prng = test_rng();
578 let r_biguint = SimFrParamsRistretto::scalar_field_in_biguint();
579
580 for _ in 0..100 {
581 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
582 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
583
584 let a_sim_fr = SimFrTest::from(&a);
585 let b_sim_fr = SimFrTest::from(&b);
586
587 let prod_sim_fr_mul = a_sim_fr.mul(&b_sim_fr);
588 let prod_sim_fr_mul_recovered: BigUint = (&prod_sim_fr_mul).into();
589
590 let prod = &a * &b;
591
592 assert_eq!(prod, prod_sim_fr_mul_recovered);
593 }
594 }
595
596 #[test]
597 fn test_enforce_zero_trivial() {
598 let zero_fr = SimFrTest::from(&BigUint::zero());
599 let zero_fr_mul = (&zero_fr) * (&zero_fr);
600
601 zero_fr_mul.enforce_zero();
602 }
603
604 #[test]
605 fn test_enforce_zero() {
606 let mut prng = test_rng();
607 let r_biguint = SimFrParamsRistretto::scalar_field_in_biguint();
608
609 for _ in 0..1000 {
610 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
611 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
612
613 let a_fr = SimFrTest::from(&a);
614 let b_fr = SimFrTest::from(&b);
615
616 let ab_fr_mul = &a_fr * &b_fr;
617 let ab_fr = &a * &b;
618 assert_eq!(ab_fr, (&ab_fr_mul).into());
619
620 let ab_fr_reduced = &ab_fr % &r_biguint;
621 let ab_reduced = SimFrTest::from(&ab_fr_reduced);
622
623 let zero_supposed = &ab_fr_mul - &ab_reduced;
624 let zero_supposed_biguint: BigUint = (&zero_supposed).into();
625 assert_eq!(BigUint::zero(), &zero_supposed_biguint % &r_biguint);
626 zero_supposed.enforce_zero();
627 }
628 }
629
630 #[test]
631 #[should_panic]
632 fn test_enforce_zero_panic() {
633 let mut prng = test_rng();
634 let r_biguint = SimFrParamsRistretto::scalar_field_in_biguint();
635
636 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
637 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
638
639 let a_fr = SimFrTest::from(&a);
640 let b_fr = SimFrTest::from(&b);
641
642 let ab_fr_mul = &a_fr * &b_fr;
643 let ab_fr = &a * &b;
644 assert_eq!(ab_fr, (&ab_fr_mul).into());
645
646 let ab_fr_reduced_manipulated = &ab_fr % &r_biguint + &BigUint::from(10u64);
647 let ab_reduced_manipulated = SimFrTest::from(&ab_fr_reduced_manipulated);
648
649 let zero_supposed_manipulated = &ab_fr_mul - &ab_reduced_manipulated;
650 zero_supposed_manipulated.enforce_zero();
651 }
652}
653
654#[cfg(test)]
655mod test_secq256k1 {
656 use crate::field_simulation::{SimFr, SimFrParams, SimFrParamsSecq256k1};
657 use noah_algebra::prelude::*;
658 use num_bigint::{BigUint, RandBigInt};
659 use num_integer::Integer;
660
661 type SimFrTest = SimFr<SimFrParamsSecq256k1>;
662
663 #[test]
664 fn test_sim_fr_biguint_conversion() {
665 let mut prng = test_rng();
666 let r_biguint = SimFrParamsSecq256k1::scalar_field_in_biguint();
667
668 for _ in 0..100 {
669 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
670 let a_sim_fr = SimFrTest::from(&a);
671 let a_recovered: BigUint = (&a_sim_fr).into();
672
673 assert_eq!(a, a_recovered);
674 }
675 }
676
677 #[test]
678 fn test_sub() {
679 let mut prng = test_rng();
680 let r_biguint = SimFrParamsSecq256k1::scalar_field_in_biguint();
681
682 for _ in 0..100 {
683 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
684 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
685
686 let a_sim_fr = SimFrTest::from(&a);
687 let b_sim_fr = SimFrTest::from(&b);
688 let sum_sim_fr = &a_sim_fr - &b_sim_fr;
689
690 let (_, sum) = a.add(&r_biguint).sub(&b).div_rem(&r_biguint);
691 let (_, sum_recovered) =
692 <&SimFrTest as Into<BigUint>>::into(&sum_sim_fr).div_rem(&r_biguint);
693
694 assert_eq!(sum, sum_recovered);
695 }
696 }
697
698 #[test]
699 fn test_mul() {
700 let mut prng = test_rng();
701 let r_biguint = SimFrParamsSecq256k1::scalar_field_in_biguint();
702
703 for _ in 0..100 {
704 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
705 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
706
707 let a_sim_fr = SimFrTest::from(&a);
708 let b_sim_fr = SimFrTest::from(&b);
709
710 let prod_sim_fr_mul = a_sim_fr.mul(&b_sim_fr);
711 let prod_sim_fr_mul_recovered: BigUint = (&prod_sim_fr_mul).into();
712
713 let prod = &a * &b;
714
715 assert_eq!(prod, prod_sim_fr_mul_recovered);
716 }
717 }
718
719 #[test]
720 fn test_enforce_zero_trivial() {
721 let zero_fr = SimFrTest::from(&BigUint::zero());
722 let zero_fr_mul = (&zero_fr) * (&zero_fr);
723
724 zero_fr_mul.enforce_zero();
725 }
726
727 #[test]
728 fn test_enforce_zero() {
729 let mut prng = test_rng();
730 let r_biguint = SimFrParamsSecq256k1::scalar_field_in_biguint();
731
732 for _ in 0..1000 {
733 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
734 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
735
736 let a_fr = SimFrTest::from(&a);
737 let b_fr = SimFrTest::from(&b);
738
739 let ab_fr_mul = &a_fr * &b_fr;
740 let ab_fr = &a * &b;
741 assert_eq!(ab_fr, (&ab_fr_mul).into());
742
743 let ab_fr_reduced = &ab_fr % &r_biguint;
744 let ab_reduced = SimFrTest::from(&ab_fr_reduced);
745
746 let zero_supposed = &ab_fr_mul - &ab_reduced;
747 let zero_supposed_biguint: BigUint = (&zero_supposed).into();
748 assert_eq!(BigUint::zero(), &zero_supposed_biguint % &r_biguint);
749 zero_supposed.enforce_zero();
750 }
751 }
752
753 #[test]
754 #[should_panic]
755 fn test_enforce_zero_panic() {
756 let mut prng = test_rng();
757 let r_biguint = SimFrParamsSecq256k1::scalar_field_in_biguint();
758
759 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
760 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
761
762 let a_fr = SimFrTest::from(&a);
763 let b_fr = SimFrTest::from(&b);
764
765 let ab_fr_mul = &a_fr * &b_fr;
766 let ab_fr = &a * &b;
767 assert_eq!(ab_fr, (&ab_fr_mul).into());
768
769 let ab_fr_reduced_manipulated = &ab_fr % &r_biguint + &BigUint::from(10u64);
770 let ab_reduced_manipulated = SimFrTest::from(&ab_fr_reduced_manipulated);
771
772 let zero_supposed_manipulated = &ab_fr_mul - &ab_reduced_manipulated;
773 zero_supposed_manipulated.enforce_zero();
774 }
775}
776
777#[cfg(test)]
778mod test_zorro {
779 use crate::field_simulation::{SimFr, SimFrParams, SimFrParamsZorro};
780 use noah_algebra::prelude::*;
781 use num_bigint::{BigUint, RandBigInt};
782 use num_integer::Integer;
783
784 type SimFrTest = SimFr<SimFrParamsZorro>;
785
786 #[test]
787 fn test_sim_fr_biguint_conversion() {
788 let mut prng = test_rng();
789 let r_biguint = SimFrParamsZorro::scalar_field_in_biguint();
790
791 for _ in 0..100 {
792 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
793 let a_sim_fr = SimFrTest::from(&a);
794 let a_recovered: BigUint = (&a_sim_fr).into();
795
796 assert_eq!(a, a_recovered);
797 }
798 }
799
800 #[test]
801 fn test_sub() {
802 let mut prng = test_rng();
803 let r_biguint = SimFrParamsZorro::scalar_field_in_biguint();
804
805 for _ in 0..100 {
806 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
807 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
808
809 let a_sim_fr = SimFrTest::from(&a);
810 let b_sim_fr = SimFrTest::from(&b);
811 let sum_sim_fr = &a_sim_fr - &b_sim_fr;
812
813 let (_, sum) = a.add(&r_biguint).sub(&b).div_rem(&r_biguint);
814 let (_, sum_recovered) =
815 <&SimFrTest as Into<BigUint>>::into(&sum_sim_fr).div_rem(&r_biguint);
816
817 assert_eq!(sum, sum_recovered);
818 }
819 }
820
821 #[test]
822 fn test_mul() {
823 let mut prng = test_rng();
824 let r_biguint = SimFrParamsZorro::scalar_field_in_biguint();
825
826 for _ in 0..100 {
827 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
828 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
829
830 let a_sim_fr = SimFrTest::from(&a);
831 let b_sim_fr = SimFrTest::from(&b);
832
833 let prod_sim_fr_mul = a_sim_fr.mul(&b_sim_fr);
834 let prod_sim_fr_mul_recovered: BigUint = (&prod_sim_fr_mul).into();
835
836 let prod = &a * &b;
837
838 assert_eq!(prod, prod_sim_fr_mul_recovered);
839 }
840 }
841
842 #[test]
843 fn test_enforce_zero_trivial() {
844 let zero_fr = SimFrTest::from(&BigUint::zero());
845 let zero_fr_mul = (&zero_fr) * (&zero_fr);
846
847 zero_fr_mul.enforce_zero();
848 }
849
850 #[test]
851 fn test_enforce_zero() {
852 let mut prng = test_rng();
853 let r_biguint = SimFrParamsZorro::scalar_field_in_biguint();
854
855 for _ in 0..1000 {
856 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
857 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
858
859 let a_fr = SimFrTest::from(&a);
860 let b_fr = SimFrTest::from(&b);
861
862 let ab_fr_mul = &a_fr * &b_fr;
863 let ab_fr = &a * &b;
864 assert_eq!(ab_fr, (&ab_fr_mul).into());
865
866 let ab_fr_reduced = &ab_fr % &r_biguint;
867 let ab_reduced = SimFrTest::from(&ab_fr_reduced);
868
869 let zero_supposed = &ab_fr_mul - &ab_reduced;
870 let zero_supposed_biguint: BigUint = (&zero_supposed).into();
871 assert_eq!(BigUint::zero(), &zero_supposed_biguint % &r_biguint);
872 zero_supposed.enforce_zero();
873 }
874 }
875
876 #[test]
877 #[should_panic]
878 fn test_enforce_zero_panic() {
879 let mut prng = test_rng();
880 let r_biguint = SimFrParamsZorro::scalar_field_in_biguint();
881
882 let a = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
883 let b = prng.gen_biguint_range(&BigUint::zero(), &r_biguint);
884
885 let a_fr = SimFrTest::from(&a);
886 let b_fr = SimFrTest::from(&b);
887
888 let ab_fr_mul = &a_fr * &b_fr;
889 let ab_fr = &a * &b;
890 assert_eq!(ab_fr, (&ab_fr_mul).into());
891
892 let ab_fr_reduced_manipulated = &ab_fr % &r_biguint + &BigUint::from(10u64);
893 let ab_reduced_manipulated = SimFrTest::from(&ab_fr_reduced_manipulated);
894
895 let zero_supposed_manipulated = &ab_fr_mul - &ab_reduced_manipulated;
896 zero_supposed_manipulated.enforce_zero();
897 }
898}