1use std::cell::RefCell;
28use std::convert::TryFrom;
29use std::ops::Add;
30use std::ops::Mul;
31use std::ops::Neg;
32use std::ops::Sub;
33use std::sync::OnceLock;
34
35use ark_bls12_381::Fr as Bls12381ScalarField;
36use ark_bls12_381::G1Projective;
37use ark_ec::Group as ArkGroup;
38use ark_ff::Field 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 libsecp256k1::curve::Affine;
51use libsecp256k1::curve::ECMultContext;
52use libsecp256k1::curve::ECMultGenContext;
53use libsecp256k1::curve::Jacobian;
54use libsecp256k1::curve::Scalar as SecpK1FieldScalar;
55use p256::ProjectivePoint;
56use p256::Scalar as Secp256r1ScalarField;
57use rand::RngCore;
58use rand::SeedableRng;
59use rand_hc::Hc128Rng;
60
61use crate::algebra::AbelianGroup;
62use crate::algebra::CommutativeRing;
63use crate::algebra::Field as AlgebraField;
64use crate::algebra::Module;
65use crate::algebra::One as AlgebraOne;
66use crate::algebra::Zero as AlgebraZero;
67use crate::ecc::PublicKey;
68use crate::ecc::SecretKey;
69use crate::error::Error;
70use crate::error::Result;
71
72pub trait CurveGroup {
94 type Point: Clone;
96 type Scalar: Clone;
98
99 fn identity() -> Self::Point;
101
102 fn generator() -> Self::Point;
104
105 fn generator_mul(scalar: &Self::Scalar) -> Self::Point {
107 let generator = Self::generator();
108 Self::mul(&generator, scalar)
109 }
110
111 fn add(lhs: &Self::Point, rhs: &Self::Point) -> Self::Point;
113
114 fn neg(point: &Self::Point) -> Self::Point;
116
117 fn mul(point: &Self::Point, scalar: &Self::Scalar) -> Self::Point;
119
120 fn eq(lhs: &Self::Point, rhs: &Self::Point) -> bool;
122}
123
124pub trait CurveScalarField: CurveGroup {
136 fn scalar_zero() -> Self::Scalar;
138
139 fn scalar_one() -> Self::Scalar;
141
142 fn scalar_is_zero(scalar: &Self::Scalar) -> bool;
144
145 fn scalar_add(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar;
147
148 fn scalar_sub(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar;
150
151 fn scalar_neg(scalar: &Self::Scalar) -> Self::Scalar;
153
154 fn scalar_mul(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar;
156
157 fn scalar_inverse(scalar: &Self::Scalar) -> Option<Self::Scalar>;
159
160 fn scalar_eq(lhs: &Self::Scalar, rhs: &Self::Scalar) -> bool;
162
163 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar;
165
166 fn random_scalar() -> Self::Scalar {
168 with_group_rng(|rng| Self::random_scalar_with_rng(rng))
169 }
170}
171
172pub trait CyclicModule: AbelianGroup + Sized {
193 type Scalar: AlgebraField;
195
196 fn generator() -> Self;
198
199 fn generator_mul(scalar: &Self::Scalar) -> Self;
201
202 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar;
204
205 fn random_scalar() -> Self::Scalar {
207 with_group_rng(|rng| Self::random_scalar_with_rng(rng))
208 }
209}
210
211#[derive(Debug)]
213pub struct Point<C: CurveGroup> {
214 inner: C::Point,
215}
216
217#[derive(Debug)]
219pub struct Scalar<C: CurveGroup> {
220 inner: C::Scalar,
221}
222
223#[derive(Debug)]
225pub struct Secp256k1;
226
227#[derive(Debug)]
229pub struct Secp256r1;
230
231#[derive(Debug)]
233pub struct Bls12381G1;
234
235#[cfg(feature = "curve-ristretto255")]
237#[derive(Debug)]
238pub struct Ristretto255;
239
240thread_local! {
241 static GROUP_RNG: RefCell<Hc128Rng> = RefCell::new(Hc128Rng::from_entropy());
242}
243
244static SECP256K1_GENERATOR: OnceLock<Jacobian> = OnceLock::new();
245
246impl<C: CurveGroup> Point<C> {
247 pub fn new(inner: C::Point) -> Self {
249 Self { inner }
250 }
251
252 pub fn as_inner(&self) -> &C::Point {
254 &self.inner
255 }
256
257 pub fn into_inner(self) -> C::Point {
259 self.inner
260 }
261}
262
263impl<C: CurveGroup> Scalar<C> {
264 pub fn new(inner: C::Scalar) -> Self {
266 Self { inner }
267 }
268
269 pub fn as_inner(&self) -> &C::Scalar {
271 &self.inner
272 }
273
274 pub fn into_inner(self) -> C::Scalar {
276 self.inner
277 }
278}
279
280impl<C: CurveGroup> Clone for Point<C> {
281 fn clone(&self) -> Self {
282 Self::new(self.inner.clone())
283 }
284}
285
286impl<C> Copy for Point<C>
287where
288 C: CurveGroup,
289 C::Point: Copy,
290{
291}
292
293impl<C: CurveGroup> Clone for Scalar<C> {
294 fn clone(&self) -> Self {
295 Self::new(self.inner.clone())
296 }
297}
298
299impl<C> Copy for Scalar<C>
300where
301 C: CurveGroup,
302 C::Scalar: Copy,
303{
304}
305
306impl<C: CurveGroup> Add for Point<C> {
307 type Output = Self;
308
309 fn add(self, rhs: Self) -> Self::Output {
310 Self::new(C::add(&self.inner, &rhs.inner))
311 }
312}
313
314impl<C: CurveGroup> Neg for Point<C> {
315 type Output = Self;
316
317 fn neg(self) -> Self::Output {
318 Self::new(C::neg(&self.inner))
319 }
320}
321
322impl<C: CurveGroup> Sub for Point<C> {
323 type Output = Self;
324
325 fn sub(self, rhs: Self) -> Self::Output {
326 self + (-rhs)
327 }
328}
329
330impl<C: CurveGroup> Mul<Scalar<C>> for Point<C> {
331 type Output = Self;
332
333 fn mul(self, rhs: Scalar<C>) -> Self::Output {
334 Self::new(C::mul(&self.inner, &rhs.inner))
335 }
336}
337
338impl<C: CurveGroup> PartialEq for Point<C> {
339 fn eq(&self, other: &Self) -> bool {
340 C::eq(&self.inner, &other.inner)
341 }
342}
343
344impl<C: CurveGroup> Eq for Point<C> {}
345
346impl<C: CurveGroup> AlgebraZero for Point<C> {
347 fn zero() -> Self {
348 Self::new(C::identity())
349 }
350
351 fn is_zero(&self) -> bool {
352 C::eq(&self.inner, &C::identity())
353 }
354}
355
356impl<C: CurveGroup> AbelianGroup for Point<C> {}
357
358impl<C: CurveScalarField> Module<Scalar<C>> for Point<C> {}
359
360impl<C: CurveScalarField> CyclicModule for Point<C> {
361 type Scalar = Scalar<C>;
362
363 fn generator() -> Self {
364 Self::new(C::generator())
365 }
366
367 fn generator_mul(scalar: &Self::Scalar) -> Self {
368 Self::new(C::generator_mul(&scalar.inner))
369 }
370
371 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar {
372 Scalar::new(C::random_scalar_with_rng(rng))
373 }
374}
375
376impl<C: CurveScalarField> Add for Scalar<C> {
377 type Output = Self;
378
379 fn add(self, rhs: Self) -> Self::Output {
380 Self::new(C::scalar_add(&self.inner, &rhs.inner))
381 }
382}
383
384impl<C: CurveScalarField> Sub for Scalar<C> {
385 type Output = Self;
386
387 fn sub(self, rhs: Self) -> Self::Output {
388 Self::new(C::scalar_sub(&self.inner, &rhs.inner))
389 }
390}
391
392impl<C: CurveScalarField> Neg for Scalar<C> {
393 type Output = Self;
394
395 fn neg(self) -> Self::Output {
396 Self::new(C::scalar_neg(&self.inner))
397 }
398}
399
400impl<C: CurveScalarField> Mul for Scalar<C> {
401 type Output = Self;
402
403 fn mul(self, rhs: Self) -> Self::Output {
404 Self::new(C::scalar_mul(&self.inner, &rhs.inner))
405 }
406}
407
408impl<C: CurveScalarField> PartialEq for Scalar<C> {
409 fn eq(&self, other: &Self) -> bool {
410 C::scalar_eq(&self.inner, &other.inner)
411 }
412}
413
414impl<C: CurveScalarField> Eq for Scalar<C> {}
415
416impl<C: CurveScalarField> AlgebraZero for Scalar<C> {
417 fn zero() -> Self {
418 Self::new(C::scalar_zero())
419 }
420
421 fn is_zero(&self) -> bool {
422 C::scalar_is_zero(&self.inner)
423 }
424}
425
426impl<C: CurveScalarField> AlgebraOne for Scalar<C> {
427 fn one() -> Self {
428 Self::new(C::scalar_one())
429 }
430}
431
432impl<C: CurveScalarField> AbelianGroup for Scalar<C> {}
433
434impl<C: CurveScalarField> CommutativeRing for Scalar<C> {}
435
436impl<C: CurveScalarField> AlgebraField for Scalar<C> {
437 fn try_inverse(&self) -> Option<Self> {
438 C::scalar_inverse(&self.inner).map(Self::new)
439 }
440}
441
442macro_rules! impl_curve_group_adapter {
450 (
451 $curve:ty {
452 point: $point:ty,
453 scalar: $scalar:ty,
454 identity: $identity:expr,
455 generator: $generator:expr,
456 random_scalar: |$rng:ident| $random_scalar:block,
457 add: $add:expr,
458 neg: $neg:expr,
459 mul: $mul:expr,
460 eq: $eq:expr,
461 scalar_zero: $scalar_zero:expr,
462 scalar_one: $scalar_one:expr,
463 scalar_is_zero: $scalar_is_zero:expr,
464 scalar_add: $scalar_add:expr,
465 scalar_sub: $scalar_sub:expr,
466 scalar_neg: $scalar_neg:expr,
467 scalar_mul: $scalar_mul:expr,
468 scalar_inverse: $scalar_inverse:expr,
469 scalar_eq: $scalar_eq:expr $(,)?
470 }
471 ) => {
472 impl CurveGroup for $curve {
473 type Point = $point;
474 type Scalar = $scalar;
475
476 fn identity() -> Self::Point {
477 $identity
478 }
479
480 fn generator() -> Self::Point {
481 $generator
482 }
483
484 fn add(lhs: &Self::Point, rhs: &Self::Point) -> Self::Point {
485 ($add)(lhs, rhs)
486 }
487
488 fn neg(point: &Self::Point) -> Self::Point {
489 ($neg)(point)
490 }
491
492 fn mul(point: &Self::Point, scalar: &Self::Scalar) -> Self::Point {
493 ($mul)(point, scalar)
494 }
495
496 fn eq(lhs: &Self::Point, rhs: &Self::Point) -> bool {
497 ($eq)(lhs, rhs)
498 }
499 }
500
501 impl CurveScalarField for $curve {
502 fn scalar_zero() -> Self::Scalar {
503 $scalar_zero
504 }
505
506 fn scalar_one() -> Self::Scalar {
507 $scalar_one
508 }
509
510 fn scalar_is_zero(scalar: &Self::Scalar) -> bool {
511 ($scalar_is_zero)(scalar)
512 }
513
514 fn scalar_add(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
515 ($scalar_add)(lhs, rhs)
516 }
517
518 fn scalar_sub(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
519 ($scalar_sub)(lhs, rhs)
520 }
521
522 fn scalar_neg(scalar: &Self::Scalar) -> Self::Scalar {
523 ($scalar_neg)(scalar)
524 }
525
526 fn scalar_mul(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
527 ($scalar_mul)(lhs, rhs)
528 }
529
530 fn scalar_inverse(scalar: &Self::Scalar) -> Option<Self::Scalar> {
531 ($scalar_inverse)(scalar)
532 }
533
534 fn scalar_eq(lhs: &Self::Scalar, rhs: &Self::Scalar) -> bool {
535 ($scalar_eq)(lhs, rhs)
536 }
537
538 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar {
539 let $rng = rng;
540 $random_scalar
541 }
542 }
543
544 impl From<$point> for Point<$curve> {
545 fn from(point: $point) -> Self {
546 Self::new(point)
547 }
548 }
549
550 impl From<Point<$curve>> for $point {
551 fn from(point: Point<$curve>) -> Self {
552 point.inner
553 }
554 }
555 };
556}
557
558impl CurveGroup for Secp256k1 {
559 type Point = Jacobian;
560 type Scalar = SecpK1FieldScalar;
561
562 fn identity() -> Self::Point {
563 secp256k1_identity()
564 }
565
566 fn generator() -> Self::Point {
567 *SECP256K1_GENERATOR.get_or_init(secp256k1_generator)
568 }
569
570 fn generator_mul(scalar: &Self::Scalar) -> Self::Point {
571 let mut result = Jacobian::default();
572 secp256k1_generator_context().ecmult_gen(&mut result, scalar);
573 result
574 }
575
576 fn add(lhs: &Self::Point, rhs: &Self::Point) -> Self::Point {
577 lhs.add_var(rhs, None)
578 }
579
580 fn neg(point: &Self::Point) -> Self::Point {
581 point.neg()
582 }
583
584 fn mul(point: &Self::Point, scalar: &Self::Scalar) -> Self::Point {
585 if point.is_infinity() {
586 return secp256k1_identity();
587 }
588 let mut result = Jacobian::default();
589 secp256k1_multiplication_context().ecmult_const(
590 &mut result,
591 &Affine::from_gej(point),
592 scalar,
593 );
594 result
595 }
596
597 fn eq(lhs: &Self::Point, rhs: &Self::Point) -> bool {
598 secp256k1_jacobian_bytes(*lhs) == secp256k1_jacobian_bytes(*rhs)
599 }
600}
601
602impl CurveScalarField for Secp256k1 {
603 fn scalar_zero() -> Self::Scalar {
604 SecpK1FieldScalar::from_int(0)
605 }
606
607 fn scalar_one() -> Self::Scalar {
608 SecpK1FieldScalar::from_int(1)
609 }
610
611 fn scalar_is_zero(scalar: &Self::Scalar) -> bool {
612 scalar.is_zero()
613 }
614
615 fn scalar_add(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
616 *lhs + *rhs
617 }
618
619 fn scalar_sub(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
620 *lhs + -*rhs
621 }
622
623 fn scalar_neg(scalar: &Self::Scalar) -> Self::Scalar {
624 -*scalar
625 }
626
627 fn scalar_mul(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
628 *lhs * *rhs
629 }
630
631 fn scalar_inverse(scalar: &Self::Scalar) -> Option<Self::Scalar> {
632 if scalar.is_zero() {
633 None
634 } else {
635 Some(scalar.inv())
636 }
637 }
638
639 fn scalar_eq(lhs: &Self::Scalar, rhs: &Self::Scalar) -> bool {
640 lhs == rhs
641 }
642
643 fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar {
644 libsecp256k1::SecretKey::random(rng).into()
645 }
646}
647
648impl_curve_group_adapter! {
649 Secp256r1 {
650 point: ProjectivePoint,
651 scalar: Secp256r1ScalarField,
652 identity: ProjectivePoint::IDENTITY,
653 generator: ProjectivePoint::GENERATOR,
654 random_scalar: |rng| {
655 loop {
656 let scalar = Secp256r1ScalarField::random(&mut *rng);
657 if !bool::from(scalar.is_zero()) {
658 break scalar;
659 }
660 }
661 },
662 add: |lhs: &ProjectivePoint, rhs: &ProjectivePoint| *lhs + *rhs,
663 neg: |point: &ProjectivePoint| -*point,
664 mul: |point: &ProjectivePoint, scalar: &Secp256r1ScalarField| *point * *scalar,
665 eq: |lhs: &ProjectivePoint, rhs: &ProjectivePoint| lhs == rhs,
666 scalar_zero: Secp256r1ScalarField::ZERO,
667 scalar_one: Secp256r1ScalarField::ONE,
668 scalar_is_zero: |scalar: &Secp256r1ScalarField| bool::from(scalar.is_zero()),
669 scalar_add: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| *lhs + *rhs,
670 scalar_sub: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| *lhs - *rhs,
671 scalar_neg: |scalar: &Secp256r1ScalarField| -*scalar,
672 scalar_mul: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| *lhs * *rhs,
673 scalar_inverse: |scalar: &Secp256r1ScalarField| scalar.invert().into_option(),
674 scalar_eq: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| lhs == rhs,
675 }
676}
677
678impl_curve_group_adapter! {
679 Bls12381G1 {
680 point: G1Projective,
681 scalar: Bls12381ScalarField,
682 identity: G1Projective::zero(),
683 generator: G1Projective::generator(),
684 random_scalar: |rng| {
685 loop {
686 let scalar = Bls12381ScalarField::rand(&mut *rng);
687 if !scalar.is_zero() {
688 break scalar;
689 }
690 }
691 },
692 add: |lhs: &G1Projective, rhs: &G1Projective| *lhs + *rhs,
693 neg: |point: &G1Projective| -*point,
694 mul: |point: &G1Projective, scalar: &Bls12381ScalarField| *point * *scalar,
695 eq: |lhs: &G1Projective, rhs: &G1Projective| lhs == rhs,
696 scalar_zero: Bls12381ScalarField::ZERO,
697 scalar_one: Bls12381ScalarField::ONE,
698 scalar_is_zero: |scalar: &Bls12381ScalarField| scalar.is_zero(),
699 scalar_add: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| *lhs + *rhs,
700 scalar_sub: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| *lhs - *rhs,
701 scalar_neg: |scalar: &Bls12381ScalarField| -*scalar,
702 scalar_mul: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| *lhs * *rhs,
703 scalar_inverse: |scalar: &Bls12381ScalarField| scalar.inverse(),
704 scalar_eq: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| lhs == rhs,
705 }
706}
707
708#[cfg(feature = "curve-ristretto255")]
709impl_curve_group_adapter! {
710 Ristretto255 {
711 point: RistrettoPoint,
712 scalar: Ristretto255ScalarField,
713 identity: RistrettoPoint::identity(),
714 generator: RISTRETTO_BASEPOINT_POINT,
715 random_scalar: |rng| {
716 loop {
717 let mut bytes = [0u8; 64];
718 rng.fill_bytes(&mut bytes);
719 let scalar = Ristretto255ScalarField::from_bytes_mod_order_wide(&bytes);
720 if scalar != Ristretto255ScalarField::ZERO {
721 break scalar;
722 }
723 }
724 },
725 add: |lhs: &RistrettoPoint, rhs: &RistrettoPoint| lhs + rhs,
726 neg: |point: &RistrettoPoint| -point,
727 mul: |point: &RistrettoPoint, scalar: &Ristretto255ScalarField| point * scalar,
728 eq: |lhs: &RistrettoPoint, rhs: &RistrettoPoint| lhs == rhs,
729 scalar_zero: Ristretto255ScalarField::ZERO,
730 scalar_one: Ristretto255ScalarField::ONE,
731 scalar_is_zero: |scalar: &Ristretto255ScalarField| *scalar == Ristretto255ScalarField::ZERO,
732 scalar_add: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| *lhs + *rhs,
733 scalar_sub: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| *lhs - *rhs,
734 scalar_neg: |scalar: &Ristretto255ScalarField| -*scalar,
735 scalar_mul: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| *lhs * *rhs,
736 scalar_inverse: |scalar: &Ristretto255ScalarField| {
737 if *scalar == Ristretto255ScalarField::ZERO {
738 None
739 } else {
740 Some(scalar.invert())
741 }
742 },
743 scalar_eq: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| lhs == rhs,
744 }
745}
746
747impl From<SecretKey> for Scalar<Secp256k1> {
748 fn from(secret_key: SecretKey) -> Self {
749 Self::new(secret_key.into())
750 }
751}
752
753impl From<Affine> for Point<Secp256k1> {
754 fn from(point: Affine) -> Self {
755 Self::new(Jacobian::from_ge(&normalize_affine(point)))
756 }
757}
758
759impl From<Point<Secp256k1>> for Affine {
760 fn from(point: Point<Secp256k1>) -> Self {
761 Affine::from_gej(&point.inner)
762 }
763}
764
765impl TryFrom<PublicKey<33>> for Point<Secp256k1> {
766 type Error = Error;
767
768 fn try_from(public_key: PublicKey<33>) -> Result<Self> {
769 let point: Affine = public_key.try_into()?;
770 Ok(point.into())
771 }
772}
773
774impl TryFrom<Point<Secp256k1>> for PublicKey<33> {
775 type Error = Error;
776
777 fn try_from(point: Point<Secp256k1>) -> Result<Self> {
778 if point.inner.is_infinity() {
779 return Err(Error::InvalidPublicKey);
780 }
781 Affine::from(point).try_into()
782 }
783}
784
785fn secp256k1_generator() -> Jacobian {
786 let scalar = SecpK1FieldScalar::from_int(1);
787 let mut point = Jacobian::default();
788 secp256k1_generator_context().ecmult_gen(&mut point, &scalar);
789 point
790}
791
792fn secp256k1_generator_context() -> &'static ECMultGenContext {
801 &libsecp256k1::ECMULT_GEN_CONTEXT
802}
803
804fn secp256k1_multiplication_context() -> &'static ECMultContext {
805 &libsecp256k1::ECMULT_CONTEXT
806}
807
808fn secp256k1_identity() -> Jacobian {
809 let mut point = Jacobian::default();
810 point.set_infinity();
811 point
812}
813
814fn with_group_rng<R>(f: impl FnOnce(&mut Hc128Rng) -> R) -> R {
815 GROUP_RNG.with(|rng| {
816 let mut rng = rng.borrow_mut();
817 f(&mut rng)
818 })
819}
820
821fn normalize_affine(mut point: Affine) -> Affine {
822 point.x.normalize();
823 point.y.normalize();
824 point
825}
826
827fn secp256k1_jacobian_bytes(point: Jacobian) -> Option<([u8; 32], [u8; 32])> {
828 if point.is_infinity() {
829 return None;
830 }
831 let mut affine = Affine::from_gej(&point);
832 affine.x.normalize();
833 affine.y.normalize();
834 Some((affine.x.b32(), affine.y.b32()))
835}
836
837#[cfg(test)]
838mod tests {
839 use super::*;
840 use crate::algebra::assert_field_laws;
841 use crate::algebra::assert_module_action_laws;
842 use crate::algebra::One;
843 use crate::algebra::Zero;
844
845 fn cyclic_module_laws<Element>()
846 where
847 Element: CyclicModule + Module<Element::Scalar> + Clone + Eq + std::fmt::Debug,
848 Element::Scalar: Clone + Eq + std::fmt::Debug,
849 {
850 let scalar_a = Element::random_scalar();
851 let scalar_b = Element::random_scalar();
852 let scalar_c = Element::random_scalar();
853 let a = Element::generator() * scalar_a.clone();
854 let b = Element::generator() * scalar_b;
855 let c = Element::generator() * scalar_c;
856
857 assert_eq!(a.clone() + Element::zero(), a);
858 assert_eq!(Element::zero() + a.clone(), a);
859 assert_eq!(a.clone() + -a.clone(), Element::zero());
860 assert_eq!((a.clone() + b.clone()) + c.clone(), a + (b + c));
861 assert_eq!(
862 Element::generator_mul(&scalar_a),
863 Element::generator() * scalar_a
864 );
865 }
866
867 fn algebra_laws<C>()
868 where
869 C: CurveScalarField,
870 Point<C>: Eq + std::fmt::Debug,
871 Scalar<C>: Eq + std::fmt::Debug,
872 {
873 let scalar_a = Scalar::<C>::new(C::random_scalar());
874 let scalar_b = Scalar::<C>::new(C::random_scalar());
875 let scalar_c = Scalar::<C>::new(C::random_scalar());
876 let scalars = vec![
877 Scalar::<C>::zero(),
878 Scalar::<C>::one(),
879 scalar_a.clone(),
880 scalar_b.clone(),
881 scalar_c.clone(),
882 ];
883
884 let generator = Point::<C>::new(C::generator());
885 let points = vec![
886 Point::<C>::zero(),
887 generator.clone(),
888 generator.clone() * scalar_a,
889 generator.clone() * scalar_b,
890 generator * scalar_c,
891 ];
892
893 assert_field_laws(&scalars);
894 assert_module_action_laws(&scalars, &points);
895 }
896
897 #[test]
898 fn supported_curve_groups_satisfy_basic_laws() {
899 cyclic_module_laws::<Point<Secp256k1>>();
900 cyclic_module_laws::<Point<Secp256r1>>();
901 cyclic_module_laws::<Point<Bls12381G1>>();
902 #[cfg(feature = "curve-ristretto255")]
903 cyclic_module_laws::<Point<Ristretto255>>();
904 }
905
906 #[test]
907 fn supported_curve_groups_satisfy_algebra_laws() {
908 algebra_laws::<Secp256k1>();
909 algebra_laws::<Secp256r1>();
910 algebra_laws::<Bls12381G1>();
911 #[cfg(feature = "curve-ristretto255")]
912 algebra_laws::<Ristretto255>();
913 }
914
915 #[test]
916 fn secp256k1_contexts_are_shared_across_threads() {
917 const THREAD_COUNT: usize = 4;
918
919 let context_addresses = std::thread::scope(|scope| {
920 let handles: Vec<_> = (0..THREAD_COUNT)
921 .map(|_| {
922 scope.spawn(|| {
923 let scalar = SecpK1FieldScalar::from_int(2);
924 let generator = <Secp256k1 as CurveGroup>::generator();
925 let _ = <Secp256k1 as CurveGroup>::generator_mul(&scalar);
926 let _ = <Secp256k1 as CurveGroup>::mul(&generator, &scalar);
927
928 (
929 secp256k1_generator_context() as *const ECMultGenContext as usize,
930 secp256k1_multiplication_context() as *const ECMultContext as usize,
931 )
932 })
933 })
934 .collect();
935
936 let mut addresses = std::collections::BTreeSet::new();
937 for handle in handles {
938 match handle.join() {
939 Ok(address) => {
940 addresses.insert(address);
941 }
942 Err(payload) => std::panic::resume_unwind(payload),
943 }
944 }
945 addresses
946 });
947
948 assert_eq!(
949 context_addresses.len(),
950 1,
951 "secp256k1 precomputed contexts must be process-global"
952 );
953 }
954}