Skip to main content

airbender_crypto/bn254/curves/
g1.rs

1use core::u64;
2
3#[cfg(any(
4    all(target_arch = "riscv32", feature = "bigint_ops"),
5    test,
6    feature = "proving"
7))]
8use crate::ark_ff_delegation::MontFp;
9use ark_ec::{
10    bn,
11    models::{short_weierstrass::SWCurveConfig, CurveConfig},
12    scalar_mul::glv::GLVConfig,
13    short_weierstrass::{Affine, Projective},
14    AffineRepr,
15};
16#[cfg(not(any(
17    all(target_arch = "riscv32", feature = "bigint_ops"),
18    test,
19    feature = "proving"
20)))]
21use ark_ff::MontFp;
22use ark_ff::{AdditiveGroup, BigInt, Field, PrimeField, Zero};
23use ruint::aliases::U512;
24
25use crate::{
26    bn254::fields::{Fq, Fr},
27    glv_decomposition::GLVConfigNoAllocator,
28};
29
30#[derive(Clone, Default, PartialEq, Eq)]
31pub struct Config;
32
33pub type G1Affine = Affine<Config>;
34
35impl CurveConfig for Config {
36    type BaseField = Fq;
37    type ScalarField = Fr;
38
39    /// COFACTOR = 1
40    const COFACTOR: &'static [u64] = &[0x1];
41
42    /// COFACTOR_INV = COFACTOR^{-1} mod r = 1
43    const COFACTOR_INV: Fr = Fr::ONE;
44}
45
46impl SWCurveConfig for Config {
47    /// COEFF_A = 0
48    const COEFF_A: Fq = Fq::ZERO;
49
50    /// COEFF_B = 3
51    const COEFF_B: Fq = MontFp!("3");
52
53    /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y)
54    const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y);
55
56    #[inline(always)]
57    fn mul_by_a(_: Self::BaseField) -> Self::BaseField {
58        Self::BaseField::zero()
59    }
60
61    #[inline]
62    fn mul_projective(
63        p: &bn::G1Projective<super::Config>,
64        scalar: &[u64],
65    ) -> bn::G1Projective<super::Config> {
66        let s = Self::ScalarField::from_sign_and_limbs(true, scalar);
67        GLVConfig::glv_mul_projective(*p, s)
68    }
69
70    #[inline]
71    fn mul_affine(base: &Affine<Self>, scalar: &[u64]) -> bn::G1Projective<super::Config> {
72        Self::mul_projective(&base.into_group(), scalar)
73    }
74
75    #[inline]
76    fn is_in_correct_subgroup_assuming_on_curve(_p: &G1Affine) -> bool {
77        // G1 = E(Fq) so if the point is on the curve, it is also in the subgroup.
78        true
79    }
80}
81
82impl GLVConfig for Config {
83    const ENDO_COEFFS: &'static [Self::BaseField] = &[MontFp!(
84        "21888242871839275220042445260109153167277707414472061641714758635765020556616"
85    )];
86
87    const LAMBDA: Self::ScalarField = ark_ff::MontFp!(
88        "21888242871839275217838484774961031246154997185409878258781734729429964517155"
89    );
90
91    const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4] = [
92        (false, BigInt!("147946756881789319000765030803803410728")),
93        (true, BigInt!("9931322734385697763")),
94        (false, BigInt!("9931322734385697763")),
95        (false, BigInt!("147946756881789319010696353538189108491")),
96    ];
97
98    fn endomorphism(p: &Projective<Self>) -> Projective<Self> {
99        let mut res = (*p).clone();
100        res.x *= Self::ENDO_COEFFS[0];
101        res
102    }
103    fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self> {
104        let mut res = (*p).clone();
105        res.x *= Self::ENDO_COEFFS[0];
106        res
107    }
108
109    fn scalar_decomposition(
110        k: Self::ScalarField,
111    ) -> ((bool, Self::ScalarField), (bool, Self::ScalarField)) {
112        Self::scalar_decomposition_no_allocator(k)
113    }
114}
115
116impl GLVConfigNoAllocator for Config {
117    const BETA_1: (bool, U512) = (
118        false,
119        U512::from_limbs([
120            7440537858994729442,
121            12177485554411886469,
122            1601953548471081566,
123            1485435879091901900,
124            6023842690951505253,
125            5534624963584316114,
126            2,
127            0,
128        ]),
129    );
130
131    const BETA_2: (bool, U512) = (
132        false,
133        U512::from_limbs([
134            10866705332225114937,
135            3332646303595026058,
136            10351474459561409124,
137            7978627105577135858,
138            15644699364383830999,
139            2,
140            0,
141            0,
142        ]),
143    );
144}
145
146/// G1_GENERATOR_X = 1
147pub const G1_GENERATOR_X: Fq = Fq::ONE;
148
149/// G1_GENERATOR_Y = 2
150pub const G1_GENERATOR_Y: Fq = MontFp!("2");
151
152#[cfg(test)]
153mod tests {
154    use super::GLVConfigNoAllocator;
155    use super::{Config, CurveConfig, GLVConfig, PrimeField};
156    use proptest::{prop_assert_eq, proptest};
157    type ScalarField = <Config as CurveConfig>::ScalarField;
158
159    #[test]
160    fn compare_scalar_decomposition() {
161        proptest!(|(bytes: [u8; 32])| {
162            let k = ScalarField::from_be_bytes_mod_order(&bytes);
163
164            let (k1, k2) = Config::scalar_decomposition(k.clone());
165            let (k1_ref, k2_ref) = Config::scalar_decomposition_ref(k);
166
167            prop_assert_eq!(k1, k1_ref);
168            prop_assert_eq!(k2, k2_ref);
169        })
170    }
171
172    #[test]
173    fn test_betas() {
174        use ark_std::ops::Neg;
175        use num_bigint::{BigInt, BigUint, Sign};
176        use num_integer::Integer;
177        use ruint::aliases::U512;
178
179        let coeff_bigints: [BigInt; 4] = Config::SCALAR_DECOMP_COEFFS.map(|x| {
180            BigInt::from_biguint(x.0.then_some(Sign::Plus).unwrap_or(Sign::Minus), x.1.into())
181        });
182
183        let [_, n12, _, n22] = coeff_bigints;
184
185        let n = 512u64;
186        let r = BigInt::from(<<Config as CurveConfig>::ScalarField>::MODULUS);
187
188        let beta_1_ref = (n22 << n).div_rem(&r).0;
189
190        let sign = Config::BETA_1
191            .0
192            .then_some(Sign::Plus)
193            .unwrap_or(Sign::Minus);
194        let data = BigUint::from_bytes_be(&Config::BETA_1.1.to_be_bytes::<{ U512::BYTES }>());
195        let beta_1 = BigInt::from_biguint(sign, data);
196        assert_eq!(beta_1, beta_1_ref);
197
198        let beta_2_ref = ((n12 << n).neg()).div_rem(&r).0;
199
200        let sign = Config::BETA_2
201            .0
202            .then_some(Sign::Plus)
203            .unwrap_or(Sign::Minus);
204        let data = BigUint::from_bytes_be(&Config::BETA_2.1.to_be_bytes::<{ U512::BYTES }>());
205        let beta_2 = BigInt::from_biguint(sign, data);
206        assert_eq!(beta_2, beta_2_ref);
207    }
208}