1use core::{
5 borrow::Borrow,
6 cmp,
7 convert::TryInto,
8 fmt,
9 iter::{Product, Sum},
10 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
11};
12
13use blst::*;
14use byte_slice_cast::AsByteSlice;
15use ff::{Field, FieldBits, PrimeField, PrimeFieldBits};
16use rand_core::RngCore;
17use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
18
19#[derive(Default, Clone, Copy)]
24#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
25#[repr(transparent)]
26pub struct Scalar(pub(crate) blst_fr);
27
28const GENERATOR: Scalar = Scalar(blst_fr {
30 l: [
31 0x0000_000e_ffff_fff1,
32 0x17e3_63d3_0018_9c0f,
33 0xff9c_5787_6f84_57b0,
34 0x3513_3220_8fc5_a8c4,
35 ],
36});
37
38#[allow(dead_code)]
40const MODULUS: [u64; 4] = [
41 0xffff_ffff_0000_0001,
42 0x53bd_a402_fffe_5bfe,
43 0x3339_d808_09a1_d805,
44 0x73ed_a753_299d_7d48,
45];
46
47#[cfg(not(target_pointer_width = "64"))]
49const MODULUS_LIMBS_32: [u32; 8] = [
50 0x0000_0001,
51 0xffff_ffff,
52 0xfffe_5bfe,
53 0x53bd_a402,
54 0x09a1_d805,
55 0x3339_d808,
56 0x299d_7d48,
57 0x73ed_a753,
58];
59
60const MODULUS_REPR: [u8; 32] = [
62 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0x02, 0xa4, 0xbd, 0x53,
63 0x05, 0xd8, 0xa1, 0x09, 0x08, 0xd8, 0x39, 0x33, 0x48, 0x7d, 0x9d, 0x29, 0x53, 0xa7, 0xed, 0x73,
64];
65
66const ROOT_OF_UNITY: Scalar = Scalar(blst_fr {
68 l: [
69 0xb9b5_8d8c_5f0e_466a,
70 0x5b1b_4c80_1819_d7ec,
71 0x0af5_3ae3_52a3_1e64,
72 0x5bf3_adda_19e9_b27b,
73 ],
74});
75
76const ZERO: Scalar = Scalar(blst_fr { l: [0, 0, 0, 0] });
77
78const R: Scalar = Scalar(blst_fr {
84 l: [
85 0x0000_0001_ffff_fffe,
86 0x5884_b7fa_0003_4802,
87 0x998c_4fef_ecbc_4ff5,
88 0x1824_b159_acc5_056f,
89 ],
90});
91
92#[allow(dead_code)]
97const R2: Scalar = Scalar(blst_fr {
98 l: [
99 0xc999_e990_f3f2_9c6d,
100 0x2b6c_edcb_8792_5c23,
101 0x05d3_1496_7254_398f,
102 0x0748_d9d9_9f59_ff11,
103 ],
104});
105
106pub const S: u32 = 32;
107
108impl fmt::Debug for Scalar {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 let be_bytes = self.to_bytes_be();
111 write!(f, "Scalar(0x")?;
112 for &b in be_bytes.iter() {
113 write!(f, "{:02x}", b)?;
114 }
115 write!(f, ")")?;
116 Ok(())
117 }
118}
119
120impl fmt::Display for Scalar {
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 write!(f, "{:?}", self)
123 }
124}
125
126impl Ord for Scalar {
127 #[allow(clippy::comparison_chain)]
128 fn cmp(&self, other: &Scalar) -> cmp::Ordering {
129 for (a, b) in self.to_bytes_be().iter().zip(other.to_bytes_be().iter()) {
130 if a > b {
131 return cmp::Ordering::Greater;
132 } else if a < b {
133 return cmp::Ordering::Less;
134 }
135 }
136 cmp::Ordering::Equal
137 }
138}
139
140impl PartialOrd for Scalar {
141 #[inline(always)]
142 fn partial_cmp(&self, other: &Scalar) -> Option<cmp::Ordering> {
143 Some(self.cmp(other))
144 }
145}
146
147impl PartialEq for Scalar {
148 #[inline]
149 fn eq(&self, other: &Self) -> bool {
150 self.0.l == other.0.l
151 }
152}
153
154impl Eq for Scalar {}
155
156impl ConstantTimeEq for Scalar {
157 fn ct_eq(&self, other: &Self) -> Choice {
158 self.0.l[0].ct_eq(&other.0.l[0])
159 & self.0.l[1].ct_eq(&other.0.l[1])
160 & self.0.l[2].ct_eq(&other.0.l[2])
161 & self.0.l[3].ct_eq(&other.0.l[3])
162 }
163}
164
165impl ConditionallySelectable for Scalar {
166 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
167 Scalar(blst_fr {
168 l: [
169 u64::conditional_select(&a.0.l[0], &b.0.l[0], choice),
170 u64::conditional_select(&a.0.l[1], &b.0.l[1], choice),
171 u64::conditional_select(&a.0.l[2], &b.0.l[2], choice),
172 u64::conditional_select(&a.0.l[3], &b.0.l[3], choice),
173 ],
174 })
175 }
176}
177
178impl From<Scalar> for blst_fr {
179 fn from(val: Scalar) -> blst_fr {
180 val.0
181 }
182}
183
184impl From<blst_fr> for Scalar {
185 fn from(val: blst_fr) -> Scalar {
186 Scalar(val)
187 }
188}
189
190impl From<u64> for Scalar {
191 fn from(val: u64) -> Scalar {
192 let mut repr = [0u8; 32];
193 repr[..8].copy_from_slice(&val.to_le_bytes());
194 Scalar::from_bytes_le(&repr).unwrap()
195 }
196}
197
198#[allow(clippy::from_over_into)]
199impl Into<blst_scalar> for Scalar {
200 fn into(self) -> blst_scalar {
201 let mut out = blst_scalar::default();
202 unsafe {
203 blst_scalar_from_fr(&mut out, &self.0);
204 }
205
206 out
207 }
208}
209
210#[derive(Debug, Clone)]
211pub struct NotInFieldError;
212
213impl fmt::Display for NotInFieldError {
214 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
215 write!(f, "Not in field")
216 }
217}
218
219impl std::error::Error for NotInFieldError {}
220
221impl TryInto<Scalar> for blst_scalar {
222 type Error = NotInFieldError;
223
224 fn try_into(self) -> Result<Scalar, Self::Error> {
225 if !unsafe { blst_scalar_fr_check(&self) } {
226 return Err(NotInFieldError);
227 }
228
229 let mut out = blst_fr::default();
230
231 unsafe { blst_fr_from_scalar(&mut out, &self) };
232
233 Ok(Scalar(out))
234 }
235}
236
237impl Neg for &Scalar {
238 type Output = Scalar;
239
240 #[inline]
241 fn neg(self) -> Scalar {
242 let mut neg = *self;
243 unsafe { blst_fr_cneg(&mut neg.0, &self.0, true) };
244 neg
245 }
246}
247
248impl Neg for Scalar {
249 type Output = Scalar;
250
251 #[inline]
252 fn neg(self) -> Scalar {
253 -&self
254 }
255}
256
257impl Add<&Scalar> for &Scalar {
258 type Output = Scalar;
259
260 #[inline]
261 fn add(self, rhs: &Scalar) -> Scalar {
262 let mut out = *self;
263 out += rhs;
264 out
265 }
266}
267
268impl Sub<&Scalar> for &Scalar {
269 type Output = Scalar;
270
271 #[inline]
272 fn sub(self, rhs: &Scalar) -> Scalar {
273 let mut out = *self;
274 out -= rhs;
275 out
276 }
277}
278
279impl Mul<&Scalar> for &Scalar {
280 type Output = Scalar;
281
282 #[inline]
283 fn mul(self, rhs: &Scalar) -> Scalar {
284 let mut out = *self;
285 out *= rhs;
286 out
287 }
288}
289
290impl AddAssign<&Scalar> for Scalar {
291 #[inline]
292 fn add_assign(&mut self, rhs: &Scalar) {
293 unsafe { blst_fr_add(&mut self.0, &self.0, &rhs.0) };
294 }
295}
296
297impl SubAssign<&Scalar> for Scalar {
298 #[inline]
299 fn sub_assign(&mut self, rhs: &Scalar) {
300 unsafe { blst_fr_sub(&mut self.0, &self.0, &rhs.0) };
301 }
302}
303
304impl MulAssign<&Scalar> for Scalar {
305 #[inline]
306 fn mul_assign(&mut self, rhs: &Scalar) {
307 unsafe { blst_fr_mul(&mut self.0, &self.0, &rhs.0) };
308 }
309}
310
311impl<T> Sum<T> for Scalar
312where
313 T: Borrow<Scalar>,
314{
315 fn sum<I>(iter: I) -> Self
316 where
317 I: Iterator<Item = T>,
318 {
319 iter.fold(Scalar::ZERO, |sum, x| sum + x.borrow())
320 }
321}
322
323impl<T> Product<T> for Scalar
324where
325 T: Borrow<Scalar>,
326{
327 fn product<I>(iter: I) -> Self
328 where
329 I: Iterator<Item = T>,
330 {
331 iter.fold(Scalar::ONE, |product, x| product * x.borrow())
332 }
333}
334
335impl_add_sub!(Scalar);
336impl_add_sub_assign!(Scalar);
337impl_mul!(Scalar);
338impl_mul_assign!(Scalar);
339
340const REPR_SHAVE_BITS: usize = 256 - Scalar::NUM_BITS as usize;
342
343impl Field for Scalar {
344 fn random(mut rng: impl RngCore) -> Self {
345 loop {
346 let mut raw = [0u64; 4];
347 for int in raw.iter_mut() {
348 *int = rng.next_u64();
349 }
350
351 raw[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
353
354 if let Some(scalar) = Scalar::from_u64s_le(&raw).into() {
355 return scalar;
356 }
357 }
358 }
359
360 const ZERO: Self = ZERO;
361
362 const ONE: Self = R;
363
364 fn is_zero(&self) -> Choice {
365 self.ct_eq(&ZERO)
366 }
367
368 fn square(&self) -> Self {
369 let mut out = *self;
370 out.square_assign();
371 out
372 }
373
374 fn double(&self) -> Self {
375 let mut out = *self;
376 out += self;
377 out
378 }
379
380 fn invert(&self) -> CtOption<Self> {
381 let mut inv = blst_fr::default();
382 unsafe { blst_fr_eucl_inverse(&mut inv, &self.0) };
383 let is_invertible = !self.ct_eq(&Scalar::ZERO);
384 CtOption::new(Scalar(inv), is_invertible)
385 }
386
387 fn sqrt(&self) -> CtOption<Self> {
388 ff::helpers::sqrt_tonelli_shanks(
390 self,
391 [
392 0x7fff_2dff_7fff_ffff,
393 0x04d0_ec02_a9de_d201,
394 0x94ce_bea4_199c_ec04,
395 0x0000_0000_39f6_d3a9,
396 ],
397 )
398 }
399
400 fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
401 ff::helpers::sqrt_ratio_generic(num, div)
402 }
403}
404
405#[allow(clippy::comparison_chain)]
408fn is_valid(a: &[u64]) -> bool {
409 debug_assert_eq!(a.len(), 4);
410 for (a, b) in a.iter().zip(MODULUS.iter()).rev() {
411 if a > b {
412 return false;
413 } else if a < b {
414 return true;
415 }
416 }
417
418 false
419}
420
421#[inline]
422fn u64s_from_bytes(bytes: &[u8; 32]) -> [u64; 4] {
423 [
424 u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
425 u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
426 u64::from_le_bytes(bytes[16..24].try_into().unwrap()),
427 u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
428 ]
429}
430
431impl PrimeField for Scalar {
432 type Repr = [u8; 32];
434
435 const NUM_BITS: u32 = 255;
436 const CAPACITY: u32 = Self::NUM_BITS - 1;
437 const S: u32 = S;
438
439 const TWO_INV: Scalar = Scalar(blst_fr {
441 l: [
442 0x0000_0000_ffff_ffff,
443 0xac42_5bfd_0001_a401,
444 0xccc6_27f7_f65e_27fa,
445 0x0c12_58ac_d662_82b7,
446 ],
447 });
448
449 const ROOT_OF_UNITY_INV: Scalar = Scalar(blst_fr {
451 l: [
452 0x4256_481a_dcf3_219a,
453 0x45f3_7b7f_96b6_cad3,
454 0xf9c3_f1d7_5f7a_3b27,
455 0x2d2f_c049_658a_fd43,
456 ],
457 });
458
459 const DELTA: Scalar = Scalar(blst_fr {
462 l: [
463 0x70e3_10d3_d146_f96a,
464 0x4b64_c089_19e2_99e6,
465 0x51e1_1418_6a8b_970d,
466 0x6185_d066_27c0_67cb,
467 ],
468 });
469
470 const MODULUS: &'static str =
472 "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001";
473
474 fn from_repr(repr: Self::Repr) -> CtOption<Self> {
476 Self::from_bytes_le(&repr)
477 }
478
479 fn from_repr_vartime(repr: Self::Repr) -> Option<Self> {
480 let bytes_u64 = u64s_from_bytes(&repr);
481
482 if !is_valid(&bytes_u64) {
483 return None;
484 }
485 let mut out = blst_fr::default();
486 unsafe { blst_fr_from_uint64(&mut out, bytes_u64.as_ptr()) };
487 Some(Scalar(out))
488 }
489
490 fn to_repr(&self) -> Self::Repr {
492 self.to_bytes_le()
493 }
494
495 fn is_odd(&self) -> Choice {
496 Choice::from(self.to_repr()[0] & 1)
497 }
498
499 const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;
500
501 const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
502}
503
504#[cfg(not(target_pointer_width = "64"))]
505type ReprBits = [u32; 8];
506
507#[cfg(target_pointer_width = "64")]
508type ReprBits = [u64; 4];
509
510impl PrimeFieldBits for Scalar {
511 type ReprBits = ReprBits;
513
514 #[cfg(target_pointer_width = "64")]
515 fn to_le_bits(&self) -> FieldBits<Self::ReprBits> {
516 let mut limbs = [0u64; 4];
517 unsafe { blst_uint64_from_fr(limbs.as_mut_ptr(), &self.0) };
518
519 FieldBits::new(limbs)
520 }
521
522 #[cfg(not(target_pointer_width = "64"))]
523 fn to_le_bits(&self) -> FieldBits<Self::ReprBits> {
524 let bytes = self.to_bytes_le();
525 let limbs = [
526 u32::from_le_bytes(bytes[0..4].try_into().unwrap()),
527 u32::from_le_bytes(bytes[4..8].try_into().unwrap()),
528 u32::from_le_bytes(bytes[8..12].try_into().unwrap()),
529 u32::from_le_bytes(bytes[12..16].try_into().unwrap()),
530 u32::from_le_bytes(bytes[16..20].try_into().unwrap()),
531 u32::from_le_bytes(bytes[20..24].try_into().unwrap()),
532 u32::from_le_bytes(bytes[24..28].try_into().unwrap()),
533 u32::from_le_bytes(bytes[28..32].try_into().unwrap()),
534 ];
535 FieldBits::new(limbs)
536 }
537
538 fn char_le_bits() -> FieldBits<Self::ReprBits> {
539 #[cfg(not(target_pointer_width = "64"))]
540 {
541 FieldBits::new(MODULUS_LIMBS_32)
542 }
543
544 #[cfg(target_pointer_width = "64")]
545 FieldBits::new(MODULUS)
546 }
547}
548
549impl Scalar {
550 pub fn from_bytes_le(bytes: &[u8; 32]) -> CtOption<Scalar> {
553 let is_some =
554 Choice::from(unsafe { blst_scalar_fr_check(&blst_scalar { b: *bytes }) as u8 });
555
556 let mut out = blst_fr::default();
557 let bytes_u64 = u64s_from_bytes(bytes);
558
559 unsafe { blst_fr_from_uint64(&mut out, bytes_u64.as_ptr()) };
560
561 CtOption::new(Scalar(out), is_some)
562 }
563
564 pub fn from_bytes_be(be_bytes: &[u8; 32]) -> CtOption<Scalar> {
567 let mut le_bytes = *be_bytes;
568 le_bytes.reverse();
569 Self::from_bytes_le(&le_bytes)
570 }
571
572 #[inline]
575 pub fn to_bytes_le(&self) -> [u8; 32] {
576 let mut out = [0u64; 4];
577 unsafe { blst_uint64_from_fr(out.as_mut_ptr(), &self.0) };
578 out.as_byte_slice().try_into().unwrap()
579 }
580
581 pub fn to_bytes_be(&self) -> [u8; 32] {
584 let mut bytes = self.to_bytes_le();
585 bytes.reverse();
586 bytes
587 }
588
589 pub fn from_u64s_le(bytes: &[u64; 4]) -> CtOption<Self> {
591 let mut raw = blst_scalar::default();
592 let mut out = blst_fr::default();
593
594 unsafe { blst_scalar_from_uint64(&mut raw, bytes.as_ptr()) };
595 let is_some = Choice::from(unsafe { blst_scalar_fr_check(&raw) as u8 });
596 unsafe { blst_fr_from_scalar(&mut out, &raw) };
597
598 CtOption::new(Scalar(out), is_some)
599 }
600
601 #[allow(clippy::match_like_matches_macro)]
602 pub fn is_quad_res(&self) -> Choice {
603 match self.legendre() {
604 0 | 1 => Choice::from(1u8),
605 _ => Choice::from(0u8),
606 }
607 }
608
609 pub fn legendre(&self) -> i8 {
610 const MOD_MINUS_1_OVER_2: [u64; 4] = [
611 0x7fffffff80000000,
612 0xa9ded2017fff2dff,
613 0x199cec0404d0ec02,
614 0x39f6d3a994cebea4,
615 ];
616 let s = self.pow_vartime(MOD_MINUS_1_OVER_2);
618 if s == Self::ZERO {
619 0
620 } else if s == Self::ONE {
621 1
622 } else {
623 -1
624 }
625 }
626
627 pub fn char() -> <Self as PrimeField>::Repr {
628 MODULUS_REPR
629 }
630
631 pub fn num_bits(&self) -> u32 {
632 let mut ret = 256;
633 for i in self.to_bytes_be().iter() {
634 let leading = i.leading_zeros();
635 ret -= leading;
636 if leading != 8 {
637 break;
638 }
639 }
640
641 ret
642 }
643
644 pub fn mul3(&self) -> Self {
646 let mut out = blst_fr::default();
647
648 unsafe { blst_fr_mul_by_3(&mut out, &self.0) };
649
650 Scalar(out)
651 }
652
653 pub fn shl(&self, count: usize) -> Self {
655 let mut out = blst_fr::default();
656
657 unsafe { blst_fr_lshift(&mut out, &self.0, count) };
658
659 Scalar(out)
660 }
661
662 pub fn shr(&self, count: usize) -> Self {
664 let mut out = blst_fr::default();
665
666 unsafe { blst_fr_rshift(&mut out, &self.0, count) };
667
668 Scalar(out)
669 }
670
671 #[inline]
673 pub fn square_assign(&mut self) {
674 unsafe { blst_fr_sqr(&mut self.0, &self.0) };
675 }
676}
677
678#[cfg(feature = "gpu")]
679impl ec_gpu::GpuName for Scalar {
680 fn name() -> String {
681 ec_gpu::name!()
682 }
683}
684
685#[cfg(feature = "gpu")]
686impl ec_gpu::GpuField for Scalar {
687 fn one() -> Vec<u32> {
688 crate::u64_to_u32(&R.0.l[..])
689 }
690
691 fn r2() -> Vec<u32> {
692 crate::u64_to_u32(&R2.0.l[..])
693 }
694
695 fn modulus() -> Vec<u32> {
696 crate::u64_to_u32(&MODULUS[..])
697 }
698}
699
700#[cfg(test)]
701mod tests {
702 use super::*;
703
704 use rand_core::SeedableRng;
705 use rand_xorshift::XorShiftRng;
706
707 const INV: u64 = 0xfffffffeffffffff;
709
710 const LARGEST: Scalar = Scalar(blst::blst_fr {
711 l: [
712 0xffffffff00000000,
713 0x53bda402fffe5bfe,
714 0x3339d80809a1d805,
715 0x73eda753299d7d48,
716 ],
717 });
718
719 #[test]
720 fn test_inv() {
721 let mut inv = 1u64;
725 for _ in 0..63 {
726 inv = inv.wrapping_mul(inv);
727 inv = inv.wrapping_mul(MODULUS[0]);
728 }
729 inv = inv.wrapping_neg();
730
731 assert_eq!(inv, INV);
732 }
733
734 #[test]
735 fn test_debug() {
736 assert_eq!(
737 format!("{:?}", Scalar::ZERO),
738 "Scalar(0x0000000000000000000000000000000000000000000000000000000000000000)"
739 );
740 assert_eq!(
741 format!("{:?}", Scalar::ONE),
742 "Scalar(0x0000000000000000000000000000000000000000000000000000000000000001)"
743 );
744 assert_eq!(
745 format!("{:?}", R2),
746 "Scalar(0x1824b159acc5056f998c4fefecbc4ff55884b7fa0003480200000001fffffffe)"
747 );
748 }
749
750 #[test]
751 fn test_equality() {
752 assert_eq!(Scalar::ZERO, Scalar::ZERO);
753 assert_eq!(Scalar::ONE, Scalar::ONE);
754
755 assert_ne!(Scalar::ZERO, Scalar::ONE);
756 assert_ne!(Scalar::ONE, R2);
757 }
758
759 #[test]
760 fn test_to_bytes() {
761 assert_eq!(
762 Scalar::ZERO.to_bytes_le(),
763 [
764 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
765 0, 0, 0, 0
766 ]
767 );
768
769 assert_eq!(
770 Scalar::ONE.to_bytes_le(),
771 [
772 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
773 0, 0, 0, 0
774 ]
775 );
776
777 assert_eq!(
778 R2.to_bytes_le(),
779 [
780 254, 255, 255, 255, 1, 0, 0, 0, 2, 72, 3, 0, 250, 183, 132, 88, 245, 79, 188, 236,
781 239, 79, 140, 153, 111, 5, 197, 172, 89, 177, 36, 24
782 ]
783 );
784
785 assert_eq!(
786 (-&Scalar::ONE).to_bytes_le(),
787 [
788 0, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9,
789 8, 216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115
790 ]
791 );
792 }
793
794 #[test]
795 fn test_from_bytes() {
796 assert_eq!(
797 Scalar::from_bytes_le(&[
798 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
799 0, 0, 0, 0
800 ])
801 .unwrap(),
802 Scalar::ZERO
803 );
804
805 assert_eq!(
806 Scalar::from_bytes_le(&[
807 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
808 0, 0, 0, 0
809 ])
810 .unwrap(),
811 Scalar::ONE
812 );
813
814 assert_eq!(
815 Scalar::from_bytes_le(&[
816 254, 255, 255, 255, 1, 0, 0, 0, 2, 72, 3, 0, 250, 183, 132, 88, 245, 79, 188, 236,
817 239, 79, 140, 153, 111, 5, 197, 172, 89, 177, 36, 24
818 ])
819 .unwrap(),
820 R2,
821 );
822
823 assert!(bool::from(
825 Scalar::from_bytes_le(&[
826 0, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9,
827 8, 216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115
828 ])
829 .is_some()
830 ));
831
832 assert!(bool::from(Scalar::from_bytes_le(&MODULUS_REPR).is_none()));
834
835 assert!(bool::from(
837 Scalar::from_bytes_le(&[
838 2, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9,
839 8, 216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115
840 ])
841 .is_none()
842 ));
843 assert!(bool::from(
844 Scalar::from_bytes_le(&[
845 1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9,
846 8, 216, 58, 51, 72, 125, 157, 41, 83, 167, 237, 115
847 ])
848 .is_none()
849 ));
850 assert!(bool::from(
851 Scalar::from_bytes_le(&[
852 1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9,
853 8, 216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 116
854 ])
855 .is_none()
856 ));
857 }
858
859 #[test]
860 fn test_zero() {
861 assert_eq!(Scalar::ZERO, -&Scalar::ZERO);
862 assert_eq!(Scalar::ZERO, Scalar::ZERO + Scalar::ZERO);
863 assert_eq!(Scalar::ZERO, Scalar::ZERO - Scalar::ZERO);
864 assert_eq!(Scalar::ZERO, Scalar::ZERO * Scalar::ZERO);
865 }
866
867 #[test]
868 fn test_addition() {
869 let mut tmp = LARGEST;
870 tmp += &LARGEST;
871
872 assert_eq!(
873 tmp,
874 Scalar(blst::blst_fr {
875 l: [
876 0xfffffffeffffffff,
877 0x53bda402fffe5bfe,
878 0x3339d80809a1d805,
879 0x73eda753299d7d48
880 ]
881 })
882 );
883
884 let mut tmp = LARGEST;
885 tmp += &Scalar(blst::blst_fr { l: [1, 0, 0, 0] });
886
887 assert_eq!(tmp, Scalar::ZERO);
888 }
889
890 #[test]
891 fn test_negation() {
892 let tmp = -&LARGEST;
893
894 assert_eq!(tmp, Scalar(blst::blst_fr { l: [1, 0, 0, 0] }));
895
896 let tmp = -&Scalar::ZERO;
897 assert_eq!(tmp, Scalar::ZERO);
898 let tmp = -&Scalar(blst::blst_fr { l: [1, 0, 0, 0] });
899 assert_eq!(tmp, LARGEST);
900
901 {
902 let mut a = Scalar::ZERO;
903 a = -a;
904
905 assert!(bool::from(a.is_zero()));
906 }
907
908 let mut rng = XorShiftRng::from_seed([
909 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
910 0xbc, 0xe5,
911 ]);
912
913 for _ in 0..1000 {
914 let mut a = Scalar::random(&mut rng);
916 let mut b = a;
917 b = -b;
918 a += &b;
919
920 assert!(bool::from(a.is_zero()));
921 }
922 }
923
924 #[test]
925 fn test_subtraction() {
926 let mut tmp = LARGEST;
927 tmp -= &LARGEST;
928
929 assert_eq!(tmp, Scalar::ZERO);
930
931 let mut tmp = Scalar::ZERO;
932 tmp -= &LARGEST;
933
934 let mut tmp2 = Scalar(blst::blst_fr { l: MODULUS });
935 tmp2 -= &LARGEST;
936
937 assert_eq!(tmp, tmp2);
938 }
939
940 #[test]
941 fn test_multiplication() {
942 let mut tmp = Scalar(blst::blst_fr {
943 l: [
944 0x6b7e9b8faeefc81a,
945 0xe30a8463f348ba42,
946 0xeff3cb67a8279c9c,
947 0x3d303651bd7c774d,
948 ],
949 });
950 tmp *= &Scalar(blst::blst_fr {
951 l: [
952 0x13ae28e3bc35ebeb,
953 0xa10f4488075cae2c,
954 0x8160e95a853c3b5d,
955 0x5ae3f03b561a841d,
956 ],
957 });
958 assert!(
959 tmp == Scalar(blst::blst_fr {
960 l: [
961 0x23717213ce710f71,
962 0xdbee1fe53a16e1af,
963 0xf565d3e1c2a48000,
964 0x4426507ee75df9d7
965 ]
966 })
967 );
968
969 let mut rng = XorShiftRng::from_seed([
970 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
971 0xbc, 0xe5,
972 ]);
973
974 for _ in 0..1000000 {
975 let a = Scalar::random(&mut rng);
977 let b = Scalar::random(&mut rng);
978 let c = Scalar::random(&mut rng);
979
980 let mut tmp1 = a;
981 tmp1 *= &b;
982 tmp1 *= &c;
983
984 let mut tmp2 = b;
985 tmp2 *= &c;
986 tmp2 *= &a;
987
988 assert_eq!(tmp1, tmp2);
989 }
990
991 for _ in 0..1000000 {
992 let r = Scalar::random(&mut rng);
995 let mut a = Scalar::random(&mut rng);
996 let mut b = Scalar::random(&mut rng);
997 let mut c = Scalar::random(&mut rng);
998
999 let mut tmp1 = a;
1000 tmp1 += &b;
1001 tmp1 += &c;
1002 tmp1 *= &r;
1003
1004 a *= &r;
1005 b *= &r;
1006 c *= &r;
1007
1008 a += &b;
1009 a += &c;
1010
1011 assert_eq!(tmp1, a);
1012 }
1013 }
1014
1015 #[test]
1016 fn test_inverse_is_pow() {
1017 let q_minus_2 = [
1018 0xfffffffeffffffff,
1019 0x53bda402fffe5bfe,
1020 0x3339d80809a1d805,
1021 0x73eda753299d7d48,
1022 ];
1023
1024 let mut r1 = R;
1025 let mut r2 = r1;
1026
1027 for _ in 0..100 {
1028 r1 = r1.invert().unwrap();
1029 r2 = r2.pow_vartime(q_minus_2);
1030
1031 assert_eq!(r1, r2);
1032 r1 += R;
1034 r2 = r1;
1035 }
1036 }
1037
1038 #[test]
1039 fn test_sqrt() {
1040 {
1041 assert_eq!(Scalar::ZERO.sqrt().unwrap(), Scalar::ZERO);
1042 }
1043
1044 let mut square = Scalar(blst::blst_fr {
1045 l: [
1046 0x46cd85a5f273077e,
1047 0x1d30c47dd68fc735,
1048 0x77f656f60beca0eb,
1049 0x494aa01bdf32468d,
1050 ],
1051 });
1052
1053 let mut none_count = 0;
1054
1055 for _ in 0..100 {
1056 let square_root = square.sqrt();
1057 if square_root.is_none().into() {
1058 none_count += 1;
1059 } else {
1060 assert_eq!(square_root.unwrap() * square_root.unwrap(), square);
1061 }
1062 square -= Scalar::ONE;
1063 }
1064
1065 assert_eq!(49, none_count);
1066 }
1067
1068 #[test]
1069 fn test_double() {
1070 let a = Scalar::from_u64s_le(&[
1071 0x1fff3231233ffffd,
1072 0x4884b7fa00034802,
1073 0x998c4fefecbc4ff3,
1074 0x1824b159acc50562,
1075 ])
1076 .unwrap();
1077
1078 assert_eq!(a.double(), a + a);
1079 }
1080
1081 #[test]
1082 fn test_scalar_ordering() {
1083 fn assert_equality(a: Scalar, b: Scalar) {
1084 assert_eq!(a, b);
1085 assert!(a.cmp(&b) == core::cmp::Ordering::Equal);
1086 }
1087
1088 fn assert_lt(a: Scalar, b: Scalar) {
1089 assert!(a < b);
1090 assert!(b > a);
1091 }
1092
1093 assert_equality(
1094 Scalar::from_u64s_le(&[9999, 9999, 9999, 9999]).unwrap(),
1095 Scalar::from_u64s_le(&[9999, 9999, 9999, 9999]).unwrap(),
1096 );
1097 assert_equality(
1098 Scalar::from_u64s_le(&[9999, 9998, 9999, 9999]).unwrap(),
1099 Scalar::from_u64s_le(&[9999, 9998, 9999, 9999]).unwrap(),
1100 );
1101 assert_equality(
1102 Scalar::from_u64s_le(&[9999, 9999, 9999, 9997]).unwrap(),
1103 Scalar::from_u64s_le(&[9999, 9999, 9999, 9997]).unwrap(),
1104 );
1105 assert_lt(
1106 Scalar::from_u64s_le(&[9999, 9997, 9999, 9998]).unwrap(),
1107 Scalar::from_u64s_le(&[9999, 9997, 9999, 9999]).unwrap(),
1108 );
1109 assert_lt(
1110 Scalar::from_u64s_le(&[9999, 9997, 9998, 9999]).unwrap(),
1111 Scalar::from_u64s_le(&[9999, 9997, 9999, 9999]).unwrap(),
1112 );
1113 assert_lt(
1114 Scalar::from_u64s_le(&[9, 9999, 9999, 9997]).unwrap(),
1115 Scalar::from_u64s_le(&[9999, 9999, 9999, 9997]).unwrap(),
1116 );
1117 }
1118
1119 #[test]
1120 fn test_scalar_from_u64() {
1121 let a = Scalar::from(100);
1122 let mut expected_bytes = [0u8; 32];
1123 expected_bytes[0] = 100;
1124 assert_eq!(a.to_bytes_le(), expected_bytes);
1125 }
1126
1127 #[test]
1128 fn test_scalar_is_odd() {
1129 assert!(bool::from(Scalar::from(0).is_even()));
1130 assert!(bool::from(Scalar::from(1).is_odd()));
1131 assert!(bool::from(Scalar::from(324834872).is_even()));
1132 assert!(bool::from(Scalar::from(324834873).is_odd()));
1133 }
1134
1135 #[test]
1136 fn test_scalar_is_zero() {
1137 assert!(bool::from(Scalar::from(0).is_zero()));
1138 assert!(!bool::from(Scalar::from(1).is_zero()));
1139 assert!(!bool::from(
1140 Scalar::from_u64s_le(&[0, 0, 1, 0]).unwrap().is_zero()
1141 ));
1142 }
1143
1144 #[test]
1145 fn test_scalar_num_bits() {
1146 assert_eq!(Scalar::NUM_BITS, 255);
1147 assert_eq!(Scalar::CAPACITY, 254);
1148
1149 let mut a = Scalar::from(0);
1150 assert_eq!(0, a.num_bits());
1151 a = Scalar::from(1);
1152 assert_eq!(1, a.num_bits());
1153 for i in 2..Scalar::NUM_BITS {
1154 a = a.shl(1);
1155 assert_eq!(i, a.num_bits());
1156 }
1157 }
1158
1159 #[test]
1160 fn test_scalar_legendre() {
1161 assert_eq!(Scalar::ZERO.sqrt().unwrap(), Scalar::ZERO);
1162 assert_eq!(Scalar::ONE.sqrt().unwrap(), Scalar::ONE);
1163
1164 let e = Scalar::from_u64s_le(&[
1165 0x0dbc5349cd5664da,
1166 0x8ac5b6296e3ae29d,
1167 0x127cb819feceaa3b,
1168 0x3a6b21fb03867191,
1169 ])
1170 .unwrap();
1171 assert!(bool::from(e.is_quad_res()));
1172
1173 let e = Scalar::from_u64s_le(&[
1174 0x96341aefd047c045,
1175 0x9b5f4254500a4d65,
1176 0x1ee08223b68ac240,
1177 0x31d9cd545c0ec7c6,
1178 ])
1179 .unwrap();
1180 assert!(!bool::from(e.is_quad_res()));
1181 }
1182
1183 #[test]
1184 fn test_scalar_add_assign() {
1185 {
1186 let mut tmp = Scalar(blst::blst_fr {
1188 l: [
1189 0x437ce7616d580765,
1190 0xd42d1ccb29d1235b,
1191 0xed8f753821bd1423,
1192 0x4eede1c9c89528ca,
1193 ],
1194 });
1195 tmp.add_assign(&Scalar(blst::blst_fr { l: [0, 0, 0, 0] }));
1198 assert_eq!(
1199 tmp,
1200 Scalar(blst::blst_fr {
1201 l: [
1202 0x437ce7616d580765,
1203 0xd42d1ccb29d1235b,
1204 0xed8f753821bd1423,
1205 0x4eede1c9c89528ca
1206 ]
1207 })
1208 );
1209 tmp.add_assign(&Scalar(blst::blst_fr { l: [1, 0, 0, 0] }));
1211 assert_eq!(
1212 tmp,
1213 Scalar(blst::blst_fr {
1214 l: [
1215 0x437ce7616d580766,
1216 0xd42d1ccb29d1235b,
1217 0xed8f753821bd1423,
1218 0x4eede1c9c89528ca
1219 ]
1220 })
1221 );
1222 tmp.add_assign(&Scalar(blst::blst_fr {
1224 l: [
1225 0x946f435944f7dc79,
1226 0xb55e7ee6533a9b9b,
1227 0x1e43b84c2f6194ca,
1228 0x58717ab525463496,
1229 ],
1230 }));
1231 assert_eq!(
1232 tmp,
1233 Scalar(blst::blst_fr {
1234 l: [
1235 0xd7ec2abbb24fe3de,
1236 0x35cdf7ae7d0d62f7,
1237 0xd899557c477cd0e9,
1238 0x3371b52bc43de018
1239 ]
1240 })
1241 );
1242 tmp = Scalar(blst::blst_fr {
1244 l: [
1245 0xffffffff00000000,
1246 0x53bda402fffe5bfe,
1247 0x3339d80809a1d805,
1248 0x73eda753299d7d48,
1249 ],
1250 });
1251 tmp.add_assign(&Scalar(blst::blst_fr { l: [1, 0, 0, 0] }));
1252 assert!(bool::from(tmp.is_zero()));
1253 tmp = Scalar(blst::blst_fr {
1255 l: [
1256 0xade5adacdccb6190,
1257 0xaa21ee0f27db3ccd,
1258 0x2550f4704ae39086,
1259 0x591d1902e7c5ba27,
1260 ],
1261 });
1262 tmp.add_assign(&Scalar(blst::blst_fr {
1263 l: [
1264 0x521a525223349e70,
1265 0xa99bb5f3d8231f31,
1266 0xde8e397bebe477e,
1267 0x1ad08e5041d7c321,
1268 ],
1269 }));
1270 assert_eq!(
1271 tmp,
1272 Scalar(blst::blst_fr {
1273 l: [
1274 0xffffffff00000000,
1275 0x53bda402fffe5bfe,
1276 0x3339d80809a1d805,
1277 0x73eda753299d7d48
1278 ]
1279 })
1280 );
1281 tmp.add_assign(&Scalar(blst::blst_fr { l: [1, 0, 0, 0] }));
1283 assert!(bool::from(tmp.is_zero()));
1284 }
1285
1286 let mut rng = XorShiftRng::from_seed([
1289 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1290 0xbc, 0xe5,
1291 ]);
1292
1293 for i in 0..1000 {
1294 let a = Scalar::random(&mut rng);
1296 let b = Scalar::random(&mut rng);
1297 let c = Scalar::random(&mut rng);
1298
1299 let mut tmp1 = a;
1300 tmp1.add_assign(&b);
1301 tmp1.add_assign(&c);
1302
1303 let mut tmp2 = b;
1304 tmp2.add_assign(&c);
1305 tmp2.add_assign(&a);
1306
1307 assert_eq!(tmp1, tmp2, "round {}", i);
1310 }
1311 }
1312
1313 #[test]
1314 fn test_scalar_sub_assign() {
1315 {
1316 let mut tmp = Scalar(blst::blst_fr {
1318 l: [
1319 0x6a68c64b6f735a2b,
1320 0xd5f4d143fe0a1972,
1321 0x37c17f3829267c62,
1322 0xa2f37391f30915c,
1323 ],
1324 });
1325 tmp.sub_assign(&Scalar(blst::blst_fr {
1326 l: [
1327 0xade5adacdccb6190,
1328 0xaa21ee0f27db3ccd,
1329 0x2550f4704ae39086,
1330 0x591d1902e7c5ba27,
1331 ],
1332 }));
1333 assert_eq!(
1334 tmp,
1335 Scalar(blst::blst_fr {
1336 l: [
1337 0xbc83189d92a7f89c,
1338 0x7f908737d62d38a3,
1339 0x45aa62cfe7e4c3e1,
1340 0x24ffc5896108547d
1341 ]
1342 })
1343 );
1344
1345 tmp = Scalar(blst::blst_fr {
1347 l: [
1348 0xade5adacdccb6190,
1349 0xaa21ee0f27db3ccd,
1350 0x2550f4704ae39086,
1351 0x591d1902e7c5ba27,
1352 ],
1353 });
1354 tmp.sub_assign(&Scalar(blst::blst_fr {
1355 l: [
1356 0x6a68c64b6f735a2b,
1357 0xd5f4d143fe0a1972,
1358 0x37c17f3829267c62,
1359 0xa2f37391f30915c,
1360 ],
1361 }));
1362 assert_eq!(
1363 tmp,
1364 Scalar(blst::blst_fr {
1365 l: [
1366 0x437ce7616d580765,
1367 0xd42d1ccb29d1235b,
1368 0xed8f753821bd1423,
1369 0x4eede1c9c89528ca
1370 ]
1371 })
1372 );
1373
1374 tmp = Scalar(blst::blst_fr { l: [0, 0, 0, 0] });
1376 tmp.sub_assign(&Scalar(blst::blst_fr { l: [0, 0, 0, 0] }));
1377 assert!(bool::from(tmp.is_zero()));
1378
1379 tmp = Scalar(blst::blst_fr {
1380 l: [
1381 0x437ce7616d580765,
1382 0xd42d1ccb29d1235b,
1383 0xed8f753821bd1423,
1384 0x4eede1c9c89528ca,
1385 ],
1386 });
1387 tmp.sub_assign(&Scalar(blst::blst_fr { l: [0, 0, 0, 0] }));
1388 assert_eq!(
1389 tmp,
1390 Scalar(blst::blst_fr {
1391 l: [
1392 0x437ce7616d580765,
1393 0xd42d1ccb29d1235b,
1394 0xed8f753821bd1423,
1395 0x4eede1c9c89528ca
1396 ]
1397 })
1398 );
1399 }
1400
1401 let mut rng = XorShiftRng::from_seed([
1402 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1403 0xbc, 0xe5,
1404 ]);
1405
1406 for _ in 0..1000 {
1407 let a = Scalar::random(&mut rng);
1409 let b = Scalar::random(&mut rng);
1410
1411 let mut tmp1 = a;
1412 tmp1.sub_assign(&b);
1413
1414 let mut tmp2 = b;
1415 tmp2.sub_assign(&a);
1416
1417 tmp1.add_assign(&tmp2);
1418 assert!(bool::from(tmp1.is_zero()));
1419 }
1420 }
1421
1422 #[test]
1423 fn test_scalar_mul_assign() {
1424 let mut tmp = Scalar(blst::blst_fr {
1425 l: [
1426 0x6b7e9b8faeefc81a,
1427 0xe30a8463f348ba42,
1428 0xeff3cb67a8279c9c,
1429 0x3d303651bd7c774d,
1430 ],
1431 });
1432 tmp.mul_assign(&Scalar(blst::blst_fr {
1433 l: [
1434 0x13ae28e3bc35ebeb,
1435 0xa10f4488075cae2c,
1436 0x8160e95a853c3b5d,
1437 0x5ae3f03b561a841d,
1438 ],
1439 }));
1440 assert!(
1441 tmp == Scalar(blst::blst_fr {
1442 l: [
1443 0x23717213ce710f71,
1444 0xdbee1fe53a16e1af,
1445 0xf565d3e1c2a48000,
1446 0x4426507ee75df9d7
1447 ]
1448 })
1449 );
1450
1451 let mut rng = XorShiftRng::from_seed([
1452 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1453 0xbc, 0xe5,
1454 ]);
1455
1456 for _ in 0..1000000 {
1457 let a = Scalar::random(&mut rng);
1459 let b = Scalar::random(&mut rng);
1460 let c = Scalar::random(&mut rng);
1461
1462 let mut tmp1 = a;
1463 tmp1.mul_assign(&b);
1464 tmp1.mul_assign(&c);
1465
1466 let mut tmp2 = b;
1467 tmp2.mul_assign(&c);
1468 tmp2.mul_assign(&a);
1469
1470 assert_eq!(tmp1, tmp2);
1471 }
1472
1473 for _ in 0..1000000 {
1474 let r = Scalar::random(&mut rng);
1477 let mut a = Scalar::random(&mut rng);
1478 let mut b = Scalar::random(&mut rng);
1479 let mut c = Scalar::random(&mut rng);
1480
1481 let mut tmp1 = a;
1482 tmp1.add_assign(&b);
1483 tmp1.add_assign(&c);
1484 tmp1.mul_assign(&r);
1485
1486 a.mul_assign(&r);
1487 b.mul_assign(&r);
1488 c.mul_assign(&r);
1489
1490 a.add_assign(&b);
1491 a.add_assign(&c);
1492
1493 assert_eq!(tmp1, a);
1494 }
1495 }
1496
1497 #[test]
1498 fn test_scalar_squaring() {
1499 let a = Scalar(blst::blst_fr {
1500 l: [
1501 0xffffffffffffffff,
1502 0xffffffffffffffff,
1503 0xffffffffffffffff,
1504 0x73eda753299d7d47,
1505 ],
1506 });
1507 assert_eq!(
1509 a.square(),
1510 Scalar::from_u64s_le(&[
1511 0xc0d698e7bde077b8,
1512 0xb79a310579e76ec2,
1513 0xac1da8d0a9af4e5f,
1514 0x13f629c49bf23e97
1515 ])
1516 .unwrap()
1517 );
1518
1519 let mut rng = XorShiftRng::from_seed([
1520 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1521 0xbc, 0xe5,
1522 ]);
1523
1524 for _ in 0..1000000 {
1525 let a = Scalar::random(&mut rng);
1527
1528 let tmp = a.square();
1529
1530 let mut tmp2 = a;
1531 tmp2.mul_assign(&a);
1532
1533 assert_eq!(tmp, tmp2);
1534 }
1535 }
1536
1537 #[test]
1538 fn test_scalar_inverse() {
1539 assert_eq!(Scalar::ZERO.invert().is_none().unwrap_u8(), 1);
1540
1541 let mut rng = XorShiftRng::from_seed([
1542 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1543 0xbc, 0xe5,
1544 ]);
1545
1546 let one = Scalar::ONE;
1547
1548 for i in 0..1000 {
1549 let mut a = Scalar::random(&mut rng);
1551 let ainv = a.invert().unwrap();
1552 a.mul_assign(&ainv);
1553 assert_eq!(a, one, "round {}", i);
1554 }
1555 }
1556
1557 #[test]
1558 fn test_scalar_double() {
1559 let mut rng = XorShiftRng::from_seed([
1560 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1561 0xbc, 0xe5,
1562 ]);
1563
1564 for _ in 0..1000 {
1565 let a = Scalar::random(&mut rng);
1567 let mut b = a;
1568 b.add_assign(&a);
1569 assert_eq!(a.double(), b);
1570 }
1571 }
1572
1573 #[test]
1574 fn test_scalar_negate() {
1575 {
1576 let a = Scalar::ZERO;
1577 assert!(bool::from((-a).is_zero()));
1578 }
1579
1580 let mut rng = XorShiftRng::from_seed([
1581 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1582 0xbc, 0xe5,
1583 ]);
1584
1585 for _ in 0..1000 {
1586 let mut a = Scalar::random(&mut rng);
1588 a.add_assign(-a);
1589 assert!(bool::from(a.is_zero()));
1590 }
1591 }
1592
1593 #[test]
1594 fn test_scalar_pow() {
1595 let mut rng = XorShiftRng::from_seed([
1596 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1597 0xbc, 0xe5,
1598 ]);
1599
1600 for i in 0..1000 {
1601 let a = Scalar::random(&mut rng);
1604 let target = a.pow_vartime([i]);
1605 let mut c = Scalar::ONE;
1606 for _ in 0..i {
1607 c.mul_assign(&a);
1608 }
1609 assert_eq!(c, target);
1610 }
1611
1612 for _ in 0..1000 {
1613 let a = Scalar::random(&mut rng);
1615
1616 assert_eq!(a, a.pow_vartime(MODULUS));
1617 }
1618 }
1619
1620 #[test]
1621 fn test_scalar_sqrt() {
1622 let mut rng = XorShiftRng::from_seed([
1623 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1624 0xbc, 0xe5,
1625 ]);
1626
1627 assert_eq!(Scalar::ZERO.sqrt().unwrap(), Scalar::ZERO);
1628 assert_eq!(Scalar::ONE.sqrt().unwrap(), Scalar::ONE);
1629
1630 for _ in 0..1000 {
1631 let a = Scalar::random(&mut rng);
1633 let a_new = a.square().sqrt().unwrap();
1634 assert!(a_new == a || a_new == -a);
1635 }
1636
1637 for _ in 0..1000 {
1638 let a = Scalar::random(&mut rng);
1640 let sqrt = a.sqrt();
1641 if sqrt.is_some().into() {
1642 assert_eq!(sqrt.unwrap().square(), a);
1643 }
1644 }
1645 }
1646
1647 #[test]
1648 fn test_scalar_from_into_repr() {
1649 assert!(bool::from(
1651 Scalar::from_u64s_le(&[
1652 0xffffffff00000002,
1653 0x53bda402fffe5bfe,
1654 0x3339d80809a1d805,
1655 0x73eda753299d7d48
1656 ])
1657 .is_none()
1658 ));
1659
1660 assert!(bool::from(Scalar::from_repr(Scalar::char()).is_none()));
1662 assert!(Scalar::from_repr_vartime(Scalar::char()).is_none());
1663
1664 let mut a = Scalar::from_u64s_le(&[
1666 0x25ebe3a3ad3c0c6a,
1667 0x6990e39d092e817c,
1668 0x941f900d42f5658e,
1669 0x44f8a103b38a71e0,
1670 ])
1671 .unwrap();
1672 let b = Scalar::from_u64s_le(&[
1673 0x264e9454885e2475,
1674 0x46f7746bb0308370,
1675 0x4683ef5347411f9,
1676 0x58838d7f208d4492,
1677 ])
1678 .unwrap();
1679 let c = Scalar::from_u64s_le(&[
1680 0x48a09ab93cfc740d,
1681 0x3a6600fbfc7a671,
1682 0x838567017501d767,
1683 0x7161d6da77745512,
1684 ])
1685 .unwrap();
1686 a.mul_assign(&b);
1687 assert_eq!(a, c);
1688
1689 assert!(bool::from(Scalar::from_repr([0u8; 32]).unwrap().is_zero()));
1691 assert!(bool::from(
1692 Scalar::from_repr_vartime([0u8; 32]).unwrap().is_zero()
1693 ));
1694
1695 let mut rng = XorShiftRng::from_seed([
1696 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
1697 0xbc, 0xe5,
1698 ]);
1699
1700 for i in 0..1000 {
1701 let a = Scalar::random(&mut rng);
1703 let a_again = Scalar::from_repr(a.to_repr()).unwrap();
1704 assert_eq!(a, a_again, "{}", i);
1705 let a_yet_again = Scalar::from_repr_vartime(a.to_repr()).unwrap();
1706 assert_eq!(a, a_yet_again);
1707 }
1708 }
1709
1710 #[test]
1711 fn test_scalar_display() {
1712 assert_eq!(
1713 format!(
1714 "{}",
1715 Scalar::from_u64s_le(&[
1716 0xc3cae746a3b5ecc7,
1717 0x185ec8eb3f5b5aee,
1718 0x684499ffe4b9dd99,
1719 0x7c9bba7afb68faa
1720 ])
1721 .unwrap()
1722 ),
1723 "Scalar(0x07c9bba7afb68faa684499ffe4b9dd99185ec8eb3f5b5aeec3cae746a3b5ecc7)"
1724 .to_string()
1725 );
1726 assert_eq!(
1727 format!(
1728 "{}",
1729 Scalar::from_u64s_le(&[
1730 0x44c71298ff198106,
1731 0xb0ad10817df79b6a,
1732 0xd034a80a2b74132b,
1733 0x41cf9a1336f50719
1734 ])
1735 .unwrap()
1736 ),
1737 "Scalar(0x41cf9a1336f50719d034a80a2b74132bb0ad10817df79b6a44c71298ff198106)"
1738 .to_string()
1739 );
1740 }
1741
1742 #[test]
1743 fn test_scalar_root_of_unity() {
1744 assert_eq!(Scalar::S, 32);
1745 assert_eq!(Scalar::MULTIPLICATIVE_GENERATOR, Scalar::from(7));
1746 assert_eq!(
1747 Scalar::MULTIPLICATIVE_GENERATOR.pow_vartime([
1748 0xfffe5bfeffffffff,
1749 0x9a1d80553bda402,
1750 0x299d7d483339d808,
1751 0x73eda753
1752 ]),
1753 Scalar::ROOT_OF_UNITY
1754 );
1755 assert_eq!(
1756 Scalar::ROOT_OF_UNITY.pow_vartime([1 << Scalar::S]),
1757 Scalar::ONE
1758 );
1759 assert!(!bool::from(Scalar::MULTIPLICATIVE_GENERATOR.is_quad_res()));
1760 }
1761
1762 #[test]
1763 fn scalar_field_tests() {
1764 crate::tests::field::random_field_tests::<Scalar>();
1765 crate::tests::field::random_sqrt_tests::<Scalar>();
1766 crate::tests::field::from_str_tests::<Scalar>();
1767 }
1768
1769 #[test]
1770 fn test_scalar_repr_conversion() {
1771 let a = Scalar::from(1);
1772 let mut expected_bytes = [0u8; 32];
1773 expected_bytes[0] = 1;
1774 assert_eq!(a, Scalar::from_repr(a.to_repr()).unwrap());
1775 assert_eq!(a.to_repr(), expected_bytes);
1776 assert_eq!(a, Scalar::from_repr(expected_bytes).unwrap());
1777
1778 let a = Scalar::from(12);
1779 let mut expected_bytes = [0u8; 32];
1780 expected_bytes[0] = 12;
1781 assert_eq!(a, Scalar::from_repr(a.to_repr()).unwrap());
1782 assert_eq!(a.to_repr(), expected_bytes);
1783 assert_eq!(a, Scalar::from_repr(expected_bytes).unwrap());
1784 }
1785
1786 #[test]
1787 fn test_scalar_repr_vartime_conversion() {
1788 let a = Scalar::from(1);
1789 let mut expected_bytes = [0u8; 32];
1790 expected_bytes[0] = 1;
1791 assert_eq!(a, Scalar::from_repr_vartime(a.to_repr()).unwrap());
1792 assert_eq!(a.to_repr(), expected_bytes);
1793 assert_eq!(a, Scalar::from_repr_vartime(expected_bytes).unwrap());
1794
1795 let a = Scalar::from(12);
1796 let mut expected_bytes = [0u8; 32];
1797 expected_bytes[0] = 12;
1798 assert_eq!(a, Scalar::from_repr_vartime(a.to_repr()).unwrap());
1799 assert_eq!(a.to_repr(), expected_bytes);
1800 assert_eq!(a, Scalar::from_repr_vartime(expected_bytes).unwrap());
1801 }
1802
1803 #[test]
1804 fn test_scalar_to_le_bits() {
1805 let mut bits = Scalar::ONE.to_le_bits().into_iter();
1806 assert!(bits.next().unwrap());
1807 for bit in bits {
1808 assert!(!bit);
1809 }
1810
1811 let mut bits = Scalar::from(u64::MAX).to_le_bits().into_iter();
1812 for _ in 0..64 {
1813 assert!(bits.next().unwrap());
1814 }
1815 for _ in 64..Scalar::NUM_BITS {
1816 assert!(!bits.next().unwrap());
1817 }
1818 assert!(!bits.next().unwrap());
1821 assert!(bits.next().is_none());
1824
1825 let mut neg1_bits = (-Scalar::ONE).to_le_bits().into_iter();
1826 let mut modulus_bits = Scalar::char_le_bits().into_iter();
1827 assert_ne!(neg1_bits.next().unwrap(), modulus_bits.next().unwrap());
1828 for (b1, b2) in neg1_bits.zip(modulus_bits) {
1829 assert_eq!(b1, b2);
1830 }
1831 }
1832
1833 #[test]
1834 fn m1_inv_bug() {
1835 let bad = Scalar::ZERO - Scalar::from(7);
1837
1838 let inv = bad.invert().unwrap();
1839 let check = inv * bad;
1840 assert_eq!(Scalar::ONE, check);
1841 }
1842 #[test]
1843 fn m1_inv_bug_more() {
1844 let mut bad = Vec::new();
1845 for i in 1..1000000 {
1846 let a = Scalar::ZERO - Scalar::from(i);
1848 let ainv = a.invert().unwrap();
1849 let check = a * ainv;
1850 let one = Scalar::ONE;
1851
1852 if check != one {
1853 bad.push((i, a));
1854 }
1855 }
1856 assert_eq!(0, bad.len());
1857 }
1858
1859 fn scalar_from_u64s(parts: [u64; 4]) -> Scalar {
1860 let mut le_bytes = [0u8; 32];
1861 le_bytes[0..8].copy_from_slice(&parts[0].to_le_bytes());
1862 le_bytes[8..16].copy_from_slice(&parts[1].to_le_bytes());
1863 le_bytes[16..24].copy_from_slice(&parts[2].to_le_bytes());
1864 le_bytes[24..32].copy_from_slice(&parts[3].to_le_bytes());
1865 let mut repr = <Scalar as PrimeField>::Repr::default();
1866 repr.as_mut().copy_from_slice(&le_bytes[..]);
1867 Scalar::from_repr_vartime(repr).expect("u64s exceed BLS12-381 scalar field modulus")
1868 }
1869
1870 #[test]
1871 fn m1_inv_bug_special() {
1872 let maybe_bad = [scalar_from_u64s([
1873 0xb3fb72ea181b4e82,
1874 0x9435fcaf3a85c901,
1875 0x9eaf4fa6b9635037,
1876 0x2164d020b3bd14cc,
1877 ])];
1878
1879 let mut yep_bad = Vec::new();
1880
1881 for a in maybe_bad.iter() {
1882 let ainv = a.invert().unwrap();
1883 let check = a * ainv;
1884 let one = Scalar::ONE;
1885
1886 if check != one {
1887 yep_bad.push(a);
1888 }
1889 }
1890 assert_eq!(0, yep_bad.len());
1891 }
1892}