arnaucube
arnaucube/ark-curves-cherry-pickedPublic Self-hosted repository
ark-curves-cherry-picked/bls12_381/src/curves/g1.rs
bls12_381/src/curves/g1.rsRaw
  1use crate::*;
  2use ark_ec::{
  3    bls12,
  4    bls12::Bls12Parameters,
  5    models::CurveConfig,
  6    short_weierstrass::{Affine, SWCurveConfig},
  7    AffineRepr, Group,
  8};
  9use ark_ff::{Field, MontFp, PrimeField, Zero};
 10use ark_std::{ops::Neg, One};
 11pub type G1Affine = bls12::G1Affine<crate::Parameters>;
 12pub type G1Projective = bls12::G1Projective<crate::Parameters>;
 13
 14#[derive(Clone, Default, PartialEq, Eq)]
 15pub struct Parameters;
 16
 17impl CurveConfig for Parameters {
 18    type BaseField = Fq;
 19    type ScalarField = Fr;
 20
 21    /// COFACTOR = (x - 1)^2 / 3  = 76329603384216526031706109802092473003
 22    const COFACTOR: &'static [u64] = &[0x8c00aaab0000aaab, 0x396c8c005555e156];
 23
 24    /// COFACTOR_INV = COFACTOR^{-1} mod r
 25    /// = 52435875175126190458656871551744051925719901746859129887267498875565241663483
 26    const COFACTOR_INV: Fr =
 27        MontFp!("52435875175126190458656871551744051925719901746859129887267498875565241663483");
 28}
 29
 30impl SWCurveConfig for Parameters {
 31    /// COEFF_A = 0
 32    const COEFF_A: Fq = Fq::ZERO;
 33
 34    /// COEFF_B = 4
 35    const COEFF_B: Fq = MontFp!("4");
 36
 37    /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
 38    const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
 39
 40    #[inline(always)]
 41    fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
 42        Self::BaseField::zero()
 43    }
 44
 45    #[inline]
 46    fn is_in_correct_subgroup_assuming_on_curve(p: &G1Affine) -> bool {
 47        // Algorithm from Section 6 of https://eprint.iacr.org/2021/1130.
 48        //
 49        // Check that endomorphism_p(P) == -[X^2]P
 50
 51        // An early-out optimization described in Section 6.
 52        // If uP == P but P != point of infinity, then the point is not in the right
 53        // subgroup.
 54        let x_times_p = p.mul_bigint(crate::Parameters::X);
 55        if x_times_p.eq(p) && !p.infinity {
 56            return false;
 57        }
 58
 59        let minus_x_squared_times_p = x_times_p.mul_bigint(crate::Parameters::X).neg();
 60        let endomorphism_p = endomorphism(p);
 61        minus_x_squared_times_p.eq(&endomorphism_p)
 62    }
 63
 64    #[inline]
 65    fn clear_cofactor(p: &G1Affine) -> G1Affine {
 66        // Using the effective cofactor, as explained in
 67        // Section 5 of https://eprint.iacr.org/2019/403.pdf.
 68        //
 69        // It is enough to multiply by (1 - x), instead of (x - 1)^2 / 3
 70        let h_eff = one_minus_x().into_bigint();
 71        Parameters::mul_affine(&p, h_eff.as_ref()).into()
 72    }
 73}
 74
 75fn one_minus_x() -> Fr {
 76    const X: Fr = Fr::from_sign_and_limbs(!crate::Parameters::X_IS_NEGATIVE, crate::Parameters::X);
 77    Fr::one() - X
 78}
 79
 80/// G1_GENERATOR_X =
 81/// 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
 82pub const G1_GENERATOR_X: Fq = MontFp!("3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507");
 83
 84/// G1_GENERATOR_Y =
 85/// 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
 86pub const G1_GENERATOR_Y: Fq = MontFp!("1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569");
 87
 88/// BETA is a non-trivial cubic root of unity in Fq.
 89pub const BETA: Fq = MontFp!("793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350");
 90
 91pub fn endomorphism(p: &Affine<Parameters>) -> Affine<Parameters> {
 92    // Endomorphism of the points on the curve.
 93    // endomorphism_p(x,y) = (BETA * x, y)
 94    // where BETA is a non-trivial cubic root of unity in Fq.
 95    let mut res = (*p).clone();
 96    res.x *= BETA;
 97    res
 98}
 99
100#[cfg(test)]
101mod test {
102
103    use super::*;
104    use ark_std::{rand::Rng, UniformRand};
105
106    fn sample_unchecked() -> Affine<g1::Parameters> {
107        let mut rng = ark_std::test_rng();
108        loop {
109            let x = Fq::rand(&mut rng);
110            let greatest = rng.gen();
111
112            if let Some(p) = Affine::get_point_from_x_unchecked(x, greatest) {
113                return p;
114            }
115        }
116    }
117
118    #[test]
119    fn test_cofactor_clearing() {
120        const SAMPLES: usize = 100;
121        for _ in 0..SAMPLES {
122            let p: Affine<g1::Parameters> = sample_unchecked();
123            let p = p.clear_cofactor();
124            assert!(p.is_on_curve());
125            assert!(p.is_in_correct_subgroup_assuming_on_curve());
126        }
127    }
128}