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}