k256 0.14.0

secp256k1 elliptic curve library written in pure Rust with support for ECDSA signing/verification/public-key recovery, Taproot Schnorr signatures (BIP340), Elliptic Curve Diffie-Hellman (ECDH), and general-purpose secp256k1 elliptic curve group operations which can be used to implement arbitrary protocols
Documentation
//! Projective arithmetic tests.

#![cfg(feature = "arithmetic")]

use elliptic_curve::{
    BatchNormalize,
    array::Array,
    consts::U32,
    ops::{LinearCombination, MulVartime, Reduce, ReduceNonZero},
    point::NonIdentity,
};
use k256::{FieldBytes, NonZeroScalar, ProjectivePoint, Scalar};
use proptest::{prelude::any, prop_compose, proptest};

prop_compose! {
    fn non_identity()(bytes in any::<[u8; 32]>()) -> NonIdentity<ProjectivePoint> {
        NonIdentity::mul_by_generator(&NonZeroScalar::reduce_nonzero(&FieldBytes::from(bytes)))
    }
}

prop_compose! {
    fn projective()(bytes in any::<[u8; 32]>()) -> ProjectivePoint {
        ProjectivePoint::mul_by_generator(&Scalar::reduce(&Array::<u8, U32>::from(bytes)))
    }
}

prop_compose! {
    fn scalar()(bytes in any::<[u8; 32]>()) -> Scalar {
        Scalar::reduce(&Array::<u8, U32>::from(bytes))
    }
}

proptest! {
    #[test]
    fn batch_normalize(
        a in non_identity(),
        b in non_identity(),
    ) {
        let points = [*a, *b];
        let affine_points = ProjectivePoint::batch_normalize(&points);

        for (point, affine_point) in points.into_iter().zip(affine_points) {
            assert_eq!(affine_point, point.to_affine());
        }
    }

    #[test]
    fn batch_normalize_vartime(
        a in non_identity(),
        b in non_identity(),
    ) {
        let points = [*a, *b];
        let affine_points = ProjectivePoint::batch_normalize_vartime(&points);

        for (point, affine_point) in points.into_iter().zip(affine_points) {
            assert_eq!(affine_point, point.to_affine());
        }
    }

    #[test]
    #[cfg(feature = "alloc")]
    fn batch_normalize_alloc(
        a in non_identity(),
        b in non_identity(),
    ) {
        let points = vec![*a, *b];
        let affine_points = ProjectivePoint::batch_normalize(points.as_slice());

        for (point, affine_point) in points.into_iter().zip(affine_points) {
            assert_eq!(affine_point, point.to_affine());
        }
    }

    #[test]
    fn lincomb(
        p1 in projective(),
        s1 in scalar(),
        p2 in projective(),
        s2 in scalar(),
        p3 in projective(),
        s3 in scalar(),
    ) {
        let reference = p1 * s1 + p2 * s2 + p3 * s3;
        let test = ProjectivePoint::lincomb(&[(p1, s1), (p2, s2), (p3, s3)]);
        assert_eq!(reference, test);
    }

    #[test]
    #[cfg(feature = "alloc")]
    fn lincomb_alloc(
        p1 in projective(),
        s1 in scalar(),
        p2 in projective(),
        s2 in scalar(),
        p3 in projective(),
        s3 in scalar(),
    ) {
        let reference = p1 * s1 + p2 * s2 + p3 * s3;
        let test = ProjectivePoint::lincomb(vec![(p1, s1), (p2, s2), (p3, s3)].as_slice());
        assert_eq!(reference, test);
    }

    #[test]
    #[cfg(feature = "alloc")]
    fn lincomb_vartime(
        p1 in projective(),
        s1 in scalar(),
        p2 in projective(),
        s2 in scalar(),
        p3 in projective(),
        s3 in scalar(),
    ) {
        let reference = p1 * s1 + p2 * s2 + p3 * s3;
        let test = ProjectivePoint::lincomb_vartime(vec![(p1, s1), (p2, s2), (p3, s3)].as_slice());
        assert_eq!(reference, test);
    }

    #[test]
    fn mul_by_generator(s1 in scalar()) {
        let reference = ProjectivePoint::GENERATOR * s1;
        let test = ProjectivePoint::mul_by_generator(&s1);
        assert_eq!(reference, test);
    }

    #[test]
    fn mul_by_generator_vartime(s1 in scalar()) {
        let reference = ProjectivePoint::GENERATOR * s1;
        let test = ProjectivePoint::mul_by_generator_vartime(&s1);
        assert_eq!(reference, test);
    }

    #[test]
    fn mul_vartime(
        p1 in projective(),
        s1 in scalar()
    ) {
        let reference = p1 * s1;
        let test = p1.mul_vartime(&s1);
        assert_eq!(reference, test);
    }
}