Skip to main content

ark_ec/models/mnt4/
g2.rs

1use crate::{
2    mnt4::MNT4Config,
3    models::mnt4::MNT4,
4    short_weierstrass::{Affine, Projective},
5    AffineRepr, CurveGroup,
6};
7use ark_ff::fields::{Field, Fp2};
8use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
9use ark_std::{vec, vec::*};
10use educe::Educe;
11use num_traits::One;
12
13pub type G2Affine<P> = Affine<<P as MNT4Config>::G2Config>;
14pub type G2Projective<P> = Projective<<P as MNT4Config>::G2Config>;
15
16#[derive(Educe, CanonicalSerialize, CanonicalDeserialize)]
17#[educe(Clone, Debug, PartialEq, Eq)]
18pub struct G2Prepared<P: MNT4Config> {
19    pub x: Fp2<P::Fp2Config>,
20    pub y: Fp2<P::Fp2Config>,
21    pub x_over_twist: Fp2<P::Fp2Config>,
22    pub y_over_twist: Fp2<P::Fp2Config>,
23    pub double_coefficients: Vec<AteDoubleCoefficients<P>>,
24    pub addition_coefficients: Vec<AteAdditionCoefficients<P>>,
25}
26
27impl<P: MNT4Config> Default for G2Prepared<P> {
28    fn default() -> Self {
29        Self::from(G2Affine::<P>::generator())
30    }
31}
32
33impl<P: MNT4Config> From<G2Affine<P>> for G2Prepared<P> {
34    fn from(g: G2Affine<P>) -> Self {
35        let twist_inv = P::TWIST.inverse().unwrap();
36
37        let mut g_prep = Self {
38            x: g.x,
39            y: g.y,
40            x_over_twist: g.x * &twist_inv,
41            y_over_twist: g.y * &twist_inv,
42            double_coefficients: vec![],
43            addition_coefficients: vec![],
44        };
45
46        let mut r = G2ProjectiveExtended {
47            x: g.x,
48            y: g.y,
49            z: <Fp2<P::Fp2Config>>::one(),
50            t: <Fp2<P::Fp2Config>>::one(),
51        };
52
53        let neg_g = -g;
54        for bit in P::ATE_LOOP_COUNT.iter().skip(1) {
55            let (r2, coeff) = MNT4::doubling_for_flipped_miller_loop(&r);
56            g_prep.double_coefficients.push(coeff);
57            r = r2;
58
59            let (r_temp, add_coeff) = match bit {
60                1 => MNT4::mixed_addition_for_flipped_miller_loop(&g.x, &g.y, &r),
61                -1 => MNT4::mixed_addition_for_flipped_miller_loop(&neg_g.x, &neg_g.y, &r),
62                0 => continue,
63                _ => unreachable!(),
64            };
65            g_prep.addition_coefficients.push(add_coeff);
66            r = r_temp;
67        }
68
69        if P::ATE_IS_LOOP_COUNT_NEG {
70            let rz_inv = r.z.inverse().unwrap();
71            let rz2_inv = rz_inv.square();
72            let rz3_inv = rz_inv * &rz2_inv;
73
74            let minus_r_affine_x = r.x * &rz2_inv;
75            let minus_r_affine_y = -r.y * &rz3_inv;
76
77            let add_result = MNT4::mixed_addition_for_flipped_miller_loop(
78                &minus_r_affine_x,
79                &minus_r_affine_y,
80                &r,
81            );
82            g_prep.addition_coefficients.push(add_result.1);
83        }
84
85        g_prep
86    }
87}
88
89impl<'a, P: MNT4Config> From<&'a G2Affine<P>> for G2Prepared<P> {
90    fn from(g2: &'a G2Affine<P>) -> Self {
91        (*g2).into()
92    }
93}
94
95impl<P: MNT4Config> From<G2Projective<P>> for G2Prepared<P> {
96    fn from(g2: G2Projective<P>) -> Self {
97        g2.into_affine().into()
98    }
99}
100impl<'a, P: MNT4Config> From<&'a G2Projective<P>> for G2Prepared<P> {
101    fn from(g2: &'a G2Projective<P>) -> Self {
102        (*g2).into()
103    }
104}
105
106pub struct G2ProjectiveExtended<P: MNT4Config> {
107    pub x: Fp2<P::Fp2Config>,
108    pub y: Fp2<P::Fp2Config>,
109    pub z: Fp2<P::Fp2Config>,
110    pub t: Fp2<P::Fp2Config>,
111}
112
113#[derive(Educe, CanonicalSerialize, CanonicalDeserialize)]
114#[educe(Clone, Debug, PartialEq, Eq)]
115pub struct AteDoubleCoefficients<P: MNT4Config> {
116    pub c_h: Fp2<P::Fp2Config>,
117    pub c_4c: Fp2<P::Fp2Config>,
118    pub c_j: Fp2<P::Fp2Config>,
119    pub c_l: Fp2<P::Fp2Config>,
120}
121
122#[derive(Educe, CanonicalSerialize, CanonicalDeserialize)]
123#[educe(Clone, Debug, PartialEq, Eq)]
124pub struct AteAdditionCoefficients<P: MNT4Config> {
125    pub c_l1: Fp2<P::Fp2Config>,
126    pub c_rz: Fp2<P::Fp2Config>,
127}