1use std::cell::RefCell;
28use std::convert::TryFrom;
29use std::ops::Add;
30use std::ops::Mul;
31use std::ops::Neg;
32use std::ops::Sub;
33
34use ark_bls12_381::Fr as Bls12381ScalarField;
35use ark_bls12_381::G1Projective;
36use ark_ec::PrimeGroup as _;
37use ark_ff::Field as _;
38use ark_ff::One as _;
39use ark_ff::Zero as _;
40use ark_std::UniformRand;
41#[cfg(feature = "curve-ristretto255")]
42use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
43#[cfg(feature = "curve-ristretto255")]
44use curve25519_dalek::ristretto::RistrettoPoint;
45#[cfg(feature = "curve-ristretto255")]
46use curve25519_dalek::scalar::Scalar as Ristretto255ScalarField;
47#[cfg(feature = "curve-ristretto255")]
48use curve25519_dalek::traits::Identity as _;
49use elliptic_curve::ff::Field as _;
50use k256::AffinePoint as K256AffinePoint;
51use k256::ProjectivePoint as K256ProjectivePoint;
52use k256::Scalar as K256Scalar;
53use p256::ProjectivePoint as Secp256r1ProjectivePoint;
54use p256::Scalar as Secp256r1ScalarField;
55use rand::RngCore;
56use rand::SeedableRng;
57use rand_hc::Hc128Rng;
58
59use crate::algebra::AbelianGroup;
60use crate::algebra::CommutativeRing;
61use crate::algebra::Field as AlgebraField;
62use crate::algebra::Module;
63use crate::algebra::One as AlgebraOne;
64use crate::algebra::Zero as AlgebraZero;
65use crate::ecc::PublicKey;
66use crate::ecc::SecretKey;
67use crate::error::Error;
68use crate::error::Result;
69
70pub trait CurveGroup {
92 type Point: Clone;
94 type Scalar: Clone;
96
97 fn identity() -> Self::Point;
99
100 fn generator() -> Self::Point;
102
103 fn generator_mul(scalar: &Self::Scalar) -> Self::Point {
105 let generator = Self::generator();
106 Self::mul(&generator, scalar)
107 }
108
109 fn add(lhs: &Self::Point, rhs: &Self::Point) -> Self::Point;
111
112 fn neg(point: &Self::Point) -> Self::Point;
114
115 fn mul(point: &Self::Point, scalar: &Self::Scalar) -> Self::Point;
117
118 fn eq(lhs: &Self::Point, rhs: &Self::Point) -> bool;
120}
121
122pub trait CurveScalarField: CurveGroup {
134 fn scalar_zero() -> Self::Scalar;
136
137 fn scalar_one() -> Self::Scalar;
139
140 fn scalar_is_zero(scalar: &Self::Scalar) -> bool;
142
143 fn scalar_add(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar;
145
146 fn scalar_sub(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar;
148
149 fn scalar_neg(scalar: &Self::Scalar) -> Self::Scalar;
151
152 fn scalar_mul(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar;
154
155 fn scalar_inverse(scalar: &Self::Scalar) -> Option<Self::Scalar>;
157
158 fn scalar_eq(lhs: &Self::Scalar, rhs: &Self::Scalar) -> bool;
160
161 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar;
163
164 fn random_scalar() -> Self::Scalar {
166 with_group_rng(|rng| Self::random_scalar_with_rng(rng))
167 }
168}
169
170pub trait CyclicModule: AbelianGroup + Sized {
191 type Scalar: AlgebraField;
193
194 fn generator() -> Self;
196
197 fn generator_mul(scalar: &Self::Scalar) -> Self;
199
200 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar;
202
203 fn random_scalar() -> Self::Scalar {
205 with_group_rng(|rng| Self::random_scalar_with_rng(rng))
206 }
207}
208
209#[derive(Debug)]
211pub struct Point<C: CurveGroup> {
212 inner: C::Point,
213}
214
215#[derive(Debug)]
217pub struct Scalar<C: CurveGroup> {
218 inner: C::Scalar,
219}
220
221#[derive(Debug)]
223pub struct Secp256k1;
224
225#[derive(Debug)]
227pub struct Secp256r1;
228
229#[derive(Debug)]
231pub struct Bls12381G1;
232
233#[cfg(feature = "curve-ristretto255")]
235#[derive(Debug)]
236pub struct Ristretto255;
237
238thread_local! {
239 static GROUP_RNG: RefCell<Hc128Rng> = RefCell::new(Hc128Rng::from_entropy());
240}
241
242impl<C: CurveGroup> Point<C> {
243 pub fn new(inner: C::Point) -> Self {
245 Self { inner }
246 }
247
248 pub fn as_inner(&self) -> &C::Point {
250 &self.inner
251 }
252
253 pub fn into_inner(self) -> C::Point {
255 self.inner
256 }
257}
258
259impl<C: CurveGroup> Scalar<C> {
260 pub fn new(inner: C::Scalar) -> Self {
262 Self { inner }
263 }
264
265 pub fn as_inner(&self) -> &C::Scalar {
267 &self.inner
268 }
269
270 pub fn into_inner(self) -> C::Scalar {
272 self.inner
273 }
274}
275
276impl<C: CurveGroup> Clone for Point<C> {
277 fn clone(&self) -> Self {
278 Self::new(self.inner.clone())
279 }
280}
281
282impl<C> Copy for Point<C>
283where
284 C: CurveGroup,
285 C::Point: Copy,
286{
287}
288
289impl<C: CurveGroup> Clone for Scalar<C> {
290 fn clone(&self) -> Self {
291 Self::new(self.inner.clone())
292 }
293}
294
295impl<C> Copy for Scalar<C>
296where
297 C: CurveGroup,
298 C::Scalar: Copy,
299{
300}
301
302impl<C: CurveGroup> Add for Point<C> {
303 type Output = Self;
304
305 fn add(self, rhs: Self) -> Self::Output {
306 Self::new(C::add(&self.inner, &rhs.inner))
307 }
308}
309
310impl<C: CurveGroup> Neg for Point<C> {
311 type Output = Self;
312
313 fn neg(self) -> Self::Output {
314 Self::new(C::neg(&self.inner))
315 }
316}
317
318impl<C: CurveGroup> Sub for Point<C> {
319 type Output = Self;
320
321 fn sub(self, rhs: Self) -> Self::Output {
322 self + (-rhs)
323 }
324}
325
326impl<C: CurveGroup> Mul<Scalar<C>> for Point<C> {
327 type Output = Self;
328
329 fn mul(self, rhs: Scalar<C>) -> Self::Output {
330 Self::new(C::mul(&self.inner, &rhs.inner))
331 }
332}
333
334impl<C: CurveGroup> PartialEq for Point<C> {
335 fn eq(&self, other: &Self) -> bool {
336 C::eq(&self.inner, &other.inner)
337 }
338}
339
340impl<C: CurveGroup> Eq for Point<C> {}
341
342impl<C: CurveGroup> AlgebraZero for Point<C> {
343 fn zero() -> Self {
344 Self::new(C::identity())
345 }
346
347 fn is_zero(&self) -> bool {
348 C::eq(&self.inner, &C::identity())
349 }
350}
351
352impl<C: CurveGroup> AbelianGroup for Point<C> {}
353
354impl<C: CurveScalarField> Module<Scalar<C>> for Point<C> {}
355
356impl<C: CurveScalarField> CyclicModule for Point<C> {
357 type Scalar = Scalar<C>;
358
359 fn generator() -> Self {
360 Self::new(C::generator())
361 }
362
363 fn generator_mul(scalar: &Self::Scalar) -> Self {
364 Self::new(C::generator_mul(&scalar.inner))
365 }
366
367 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar {
368 Scalar::new(C::random_scalar_with_rng(rng))
369 }
370}
371
372impl<C: CurveScalarField> Add for Scalar<C> {
373 type Output = Self;
374
375 fn add(self, rhs: Self) -> Self::Output {
376 Self::new(C::scalar_add(&self.inner, &rhs.inner))
377 }
378}
379
380impl<C: CurveScalarField> Sub for Scalar<C> {
381 type Output = Self;
382
383 fn sub(self, rhs: Self) -> Self::Output {
384 Self::new(C::scalar_sub(&self.inner, &rhs.inner))
385 }
386}
387
388impl<C: CurveScalarField> Neg for Scalar<C> {
389 type Output = Self;
390
391 fn neg(self) -> Self::Output {
392 Self::new(C::scalar_neg(&self.inner))
393 }
394}
395
396impl<C: CurveScalarField> Mul for Scalar<C> {
397 type Output = Self;
398
399 fn mul(self, rhs: Self) -> Self::Output {
400 Self::new(C::scalar_mul(&self.inner, &rhs.inner))
401 }
402}
403
404impl<C: CurveScalarField> PartialEq for Scalar<C> {
405 fn eq(&self, other: &Self) -> bool {
406 C::scalar_eq(&self.inner, &other.inner)
407 }
408}
409
410impl<C: CurveScalarField> Eq for Scalar<C> {}
411
412impl<C: CurveScalarField> AlgebraZero for Scalar<C> {
413 fn zero() -> Self {
414 Self::new(C::scalar_zero())
415 }
416
417 fn is_zero(&self) -> bool {
418 C::scalar_is_zero(&self.inner)
419 }
420}
421
422impl<C: CurveScalarField> AlgebraOne for Scalar<C> {
423 fn one() -> Self {
424 Self::new(C::scalar_one())
425 }
426}
427
428impl<C: CurveScalarField> AbelianGroup for Scalar<C> {}
429
430impl<C: CurveScalarField> CommutativeRing for Scalar<C> {}
431
432impl<C: CurveScalarField> AlgebraField for Scalar<C> {
433 fn try_inverse(&self) -> Option<Self> {
434 C::scalar_inverse(&self.inner).map(Self::new)
435 }
436}
437
438macro_rules! impl_curve_group_adapter {
444 (
445 $curve:ty {
446 point: $point:ty,
447 scalar: $scalar:ty,
448 identity: $identity:expr,
449 generator: $generator:expr,
450 random_scalar: |$rng:ident| $random_scalar:block,
451 add: $add:expr,
452 neg: $neg:expr,
453 mul: $mul:expr,
454 eq: $eq:expr,
455 scalar_zero: $scalar_zero:expr,
456 scalar_one: $scalar_one:expr,
457 scalar_is_zero: $scalar_is_zero:expr,
458 scalar_add: $scalar_add:expr,
459 scalar_sub: $scalar_sub:expr,
460 scalar_neg: $scalar_neg:expr,
461 scalar_mul: $scalar_mul:expr,
462 scalar_inverse: $scalar_inverse:expr,
463 scalar_eq: $scalar_eq:expr $(,)?
464 }
465 ) => {
466 impl CurveGroup for $curve {
467 type Point = $point;
468 type Scalar = $scalar;
469
470 fn identity() -> Self::Point {
471 $identity
472 }
473
474 fn generator() -> Self::Point {
475 $generator
476 }
477
478 fn add(lhs: &Self::Point, rhs: &Self::Point) -> Self::Point {
479 ($add)(lhs, rhs)
480 }
481
482 fn neg(point: &Self::Point) -> Self::Point {
483 ($neg)(point)
484 }
485
486 fn mul(point: &Self::Point, scalar: &Self::Scalar) -> Self::Point {
487 ($mul)(point, scalar)
488 }
489
490 fn eq(lhs: &Self::Point, rhs: &Self::Point) -> bool {
491 ($eq)(lhs, rhs)
492 }
493 }
494
495 impl CurveScalarField for $curve {
496 fn scalar_zero() -> Self::Scalar {
497 $scalar_zero
498 }
499
500 fn scalar_one() -> Self::Scalar {
501 $scalar_one
502 }
503
504 fn scalar_is_zero(scalar: &Self::Scalar) -> bool {
505 ($scalar_is_zero)(scalar)
506 }
507
508 fn scalar_add(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
509 ($scalar_add)(lhs, rhs)
510 }
511
512 fn scalar_sub(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
513 ($scalar_sub)(lhs, rhs)
514 }
515
516 fn scalar_neg(scalar: &Self::Scalar) -> Self::Scalar {
517 ($scalar_neg)(scalar)
518 }
519
520 fn scalar_mul(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
521 ($scalar_mul)(lhs, rhs)
522 }
523
524 fn scalar_inverse(scalar: &Self::Scalar) -> Option<Self::Scalar> {
525 ($scalar_inverse)(scalar)
526 }
527
528 fn scalar_eq(lhs: &Self::Scalar, rhs: &Self::Scalar) -> bool {
529 ($scalar_eq)(lhs, rhs)
530 }
531
532 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar {
533 let $rng = rng;
534 $random_scalar
535 }
536 }
537
538 impl From<$point> for Point<$curve> {
539 fn from(point: $point) -> Self {
540 Self::new(point)
541 }
542 }
543
544 impl From<Point<$curve>> for $point {
545 fn from(point: Point<$curve>) -> Self {
546 point.inner
547 }
548 }
549 };
550}
551
552impl CurveGroup for Secp256k1 {
553 type Point = K256ProjectivePoint;
554 type Scalar = K256Scalar;
555
556 fn identity() -> Self::Point {
557 K256ProjectivePoint::IDENTITY
558 }
559
560 fn generator() -> Self::Point {
561 K256ProjectivePoint::GENERATOR
562 }
563
564 fn add(lhs: &Self::Point, rhs: &Self::Point) -> Self::Point {
565 *lhs + *rhs
566 }
567
568 fn neg(point: &Self::Point) -> Self::Point {
569 -*point
570 }
571
572 fn mul(point: &Self::Point, scalar: &Self::Scalar) -> Self::Point {
573 *point * *scalar
574 }
575
576 fn eq(lhs: &Self::Point, rhs: &Self::Point) -> bool {
577 lhs == rhs
578 }
579}
580
581impl CurveScalarField for Secp256k1 {
582 fn scalar_zero() -> Self::Scalar {
583 K256Scalar::ZERO
584 }
585
586 fn scalar_one() -> Self::Scalar {
587 K256Scalar::ONE
588 }
589
590 fn scalar_is_zero(scalar: &Self::Scalar) -> bool {
591 bool::from(scalar.is_zero())
592 }
593
594 fn scalar_add(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
595 *lhs + *rhs
596 }
597
598 fn scalar_sub(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
599 *lhs - *rhs
600 }
601
602 fn scalar_neg(scalar: &Self::Scalar) -> Self::Scalar {
603 -*scalar
604 }
605
606 fn scalar_mul(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
607 *lhs * *rhs
608 }
609
610 fn scalar_inverse(scalar: &Self::Scalar) -> Option<Self::Scalar> {
611 scalar.invert().into_option()
612 }
613
614 fn scalar_eq(lhs: &Self::Scalar, rhs: &Self::Scalar) -> bool {
615 lhs == rhs
616 }
617
618 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar {
619 loop {
620 let scalar = K256Scalar::generate_vartime(rng);
621 if !bool::from(scalar.is_zero()) {
622 break scalar;
623 }
624 }
625 }
626}
627
628impl_curve_group_adapter! {
629 Secp256r1 {
630 point: Secp256r1ProjectivePoint,
631 scalar: Secp256r1ScalarField,
632 identity: Secp256r1ProjectivePoint::IDENTITY,
633 generator: Secp256r1ProjectivePoint::GENERATOR,
634 random_scalar: |rng| {
635 loop {
636 let scalar = Secp256r1ScalarField::random(&mut *rng);
637 if !bool::from(scalar.is_zero()) {
638 break scalar;
639 }
640 }
641 },
642 add: |lhs: &Secp256r1ProjectivePoint, rhs: &Secp256r1ProjectivePoint| *lhs + *rhs,
643 neg: |point: &Secp256r1ProjectivePoint| -*point,
644 mul: |point: &Secp256r1ProjectivePoint, scalar: &Secp256r1ScalarField| *point * *scalar,
645 eq: |lhs: &Secp256r1ProjectivePoint, rhs: &Secp256r1ProjectivePoint| lhs == rhs,
646 scalar_zero: Secp256r1ScalarField::ZERO,
647 scalar_one: Secp256r1ScalarField::ONE,
648 scalar_is_zero: |scalar: &Secp256r1ScalarField| bool::from(scalar.is_zero()),
649 scalar_add: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| *lhs + *rhs,
650 scalar_sub: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| *lhs - *rhs,
651 scalar_neg: |scalar: &Secp256r1ScalarField| -*scalar,
652 scalar_mul: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| *lhs * *rhs,
653 scalar_inverse: |scalar: &Secp256r1ScalarField| scalar.invert().into_option(),
654 scalar_eq: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| lhs == rhs,
655 }
656}
657
658impl_curve_group_adapter! {
659 Bls12381G1 {
660 point: G1Projective,
661 scalar: Bls12381ScalarField,
662 identity: G1Projective::zero(),
663 generator: G1Projective::generator(),
664 random_scalar: |rng| {
665 loop {
666 let scalar = Bls12381ScalarField::rand(&mut *rng);
667 if !scalar.is_zero() {
668 break scalar;
669 }
670 }
671 },
672 add: |lhs: &G1Projective, rhs: &G1Projective| *lhs + *rhs,
673 neg: |point: &G1Projective| -*point,
674 mul: |point: &G1Projective, scalar: &Bls12381ScalarField| *point * *scalar,
675 eq: |lhs: &G1Projective, rhs: &G1Projective| lhs == rhs,
676 scalar_zero: Bls12381ScalarField::zero(),
677 scalar_one: Bls12381ScalarField::one(),
678 scalar_is_zero: |scalar: &Bls12381ScalarField| scalar.is_zero(),
679 scalar_add: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| *lhs + *rhs,
680 scalar_sub: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| *lhs - *rhs,
681 scalar_neg: |scalar: &Bls12381ScalarField| -*scalar,
682 scalar_mul: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| *lhs * *rhs,
683 scalar_inverse: |scalar: &Bls12381ScalarField| scalar.inverse(),
684 scalar_eq: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| lhs == rhs,
685 }
686}
687
688#[cfg(feature = "curve-ristretto255")]
689impl_curve_group_adapter! {
690 Ristretto255 {
691 point: RistrettoPoint,
692 scalar: Ristretto255ScalarField,
693 identity: RistrettoPoint::identity(),
694 generator: RISTRETTO_BASEPOINT_POINT,
695 random_scalar: |rng| {
696 loop {
697 let mut bytes = [0u8; 64];
698 rng.fill_bytes(&mut bytes);
699 let scalar = Ristretto255ScalarField::from_bytes_mod_order_wide(&bytes);
700 if scalar != Ristretto255ScalarField::ZERO {
701 break scalar;
702 }
703 }
704 },
705 add: |lhs: &RistrettoPoint, rhs: &RistrettoPoint| lhs + rhs,
706 neg: |point: &RistrettoPoint| -point,
707 mul: |point: &RistrettoPoint, scalar: &Ristretto255ScalarField| point * scalar,
708 eq: |lhs: &RistrettoPoint, rhs: &RistrettoPoint| lhs == rhs,
709 scalar_zero: Ristretto255ScalarField::ZERO,
710 scalar_one: Ristretto255ScalarField::ONE,
711 scalar_is_zero: |scalar: &Ristretto255ScalarField| *scalar == Ristretto255ScalarField::ZERO,
712 scalar_add: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| *lhs + *rhs,
713 scalar_sub: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| *lhs - *rhs,
714 scalar_neg: |scalar: &Ristretto255ScalarField| -*scalar,
715 scalar_mul: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| *lhs * *rhs,
716 scalar_inverse: |scalar: &Ristretto255ScalarField| {
717 if *scalar == Ristretto255ScalarField::ZERO {
718 None
719 } else {
720 Some(scalar.invert())
721 }
722 },
723 scalar_eq: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| lhs == rhs,
724 }
725}
726
727impl From<SecretKey> for Scalar<Secp256k1> {
728 fn from(secret_key: SecretKey) -> Self {
729 Self::new(secret_key.secp256k1_scalar())
730 }
731}
732
733impl From<K256AffinePoint> for Point<Secp256k1> {
734 fn from(point: K256AffinePoint) -> Self {
735 Self::new(K256ProjectivePoint::from(point))
736 }
737}
738
739impl From<Point<Secp256k1>> for K256AffinePoint {
740 fn from(point: Point<Secp256k1>) -> Self {
741 point.inner.to_affine()
742 }
743}
744
745impl TryFrom<PublicKey<33>> for Point<Secp256k1> {
746 type Error = Error;
747
748 fn try_from(public_key: PublicKey<33>) -> Result<Self> {
749 let point: K256AffinePoint = public_key.try_into()?;
750 Ok(point.into())
751 }
752}
753
754impl TryFrom<Point<Secp256k1>> for PublicKey<33> {
755 type Error = Error;
756
757 fn try_from(point: Point<Secp256k1>) -> Result<Self> {
758 if point.inner == K256ProjectivePoint::IDENTITY {
759 return Err(Error::InvalidPublicKey);
760 }
761 K256AffinePoint::from(point).try_into()
762 }
763}
764
765fn with_group_rng<R>(f: impl FnOnce(&mut Hc128Rng) -> R) -> R {
766 GROUP_RNG.with(|rng| {
767 let mut rng = rng.borrow_mut();
768 f(&mut rng)
769 })
770}
771
772#[cfg(test)]
773mod tests {
774 use super::*;
775 use crate::algebra::assert_field_laws;
776 use crate::algebra::assert_module_action_laws;
777 use crate::algebra::One;
778 use crate::algebra::Zero;
779
780 fn cyclic_module_laws<Element>()
781 where
782 Element: CyclicModule + Module<Element::Scalar> + Clone + Eq + std::fmt::Debug,
783 Element::Scalar: Clone + Eq + std::fmt::Debug,
784 {
785 let scalar_a = Element::random_scalar();
786 let scalar_b = Element::random_scalar();
787 let scalar_c = Element::random_scalar();
788 let a = Element::generator() * scalar_a.clone();
789 let b = Element::generator() * scalar_b;
790 let c = Element::generator() * scalar_c;
791
792 assert_eq!(a.clone() + Element::zero(), a);
793 assert_eq!(Element::zero() + a.clone(), a);
794 assert_eq!(a.clone() + -a.clone(), Element::zero());
795 assert_eq!((a.clone() + b.clone()) + c.clone(), a + (b + c));
796 assert_eq!(
797 Element::generator_mul(&scalar_a),
798 Element::generator() * scalar_a
799 );
800 }
801
802 fn algebra_laws<C>()
803 where
804 C: CurveScalarField,
805 Point<C>: Eq + std::fmt::Debug,
806 Scalar<C>: Eq + std::fmt::Debug,
807 {
808 let scalar_a = Scalar::<C>::new(C::random_scalar());
809 let scalar_b = Scalar::<C>::new(C::random_scalar());
810 let scalar_c = Scalar::<C>::new(C::random_scalar());
811 let scalars = vec![
812 Scalar::<C>::zero(),
813 Scalar::<C>::one(),
814 scalar_a.clone(),
815 scalar_b.clone(),
816 scalar_c.clone(),
817 ];
818
819 let generator = Point::<C>::new(C::generator());
820 let points = vec![
821 Point::<C>::zero(),
822 generator.clone(),
823 generator.clone() * scalar_a,
824 generator.clone() * scalar_b,
825 generator * scalar_c,
826 ];
827
828 assert_field_laws(&scalars);
829 assert_module_action_laws(&scalars, &points);
830 }
831
832 #[test]
833 fn test_supported_curve_groups_satisfy_basic_laws() {
834 cyclic_module_laws::<Point<Secp256k1>>();
835 cyclic_module_laws::<Point<Secp256r1>>();
836 cyclic_module_laws::<Point<Bls12381G1>>();
837 #[cfg(feature = "curve-ristretto255")]
838 cyclic_module_laws::<Point<Ristretto255>>();
839 }
840
841 #[test]
842 fn test_supported_curve_groups_satisfy_algebra_laws() {
843 algebra_laws::<Secp256k1>();
844 algebra_laws::<Secp256r1>();
845 algebra_laws::<Bls12381G1>();
846 #[cfg(feature = "curve-ristretto255")]
847 algebra_laws::<Ristretto255>();
848 }
849}