1use crate::{
2 mnt6::MNT6Config,
3 models::mnt6::MNT6,
4 short_weierstrass::{Affine, Projective},
5 AffineRepr, CurveGroup,
6};
7use ark_ff::fields::{Field, Fp3};
8use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
9use ark_std::{ops::Neg, vec::*};
10use educe::Educe;
11use num_traits::One;
12
13pub type G2Affine<P> = Affine<<P as MNT6Config>::G2Config>;
14pub type G2Projective<P> = Projective<<P as MNT6Config>::G2Config>;
15
16#[derive(Educe, CanonicalSerialize, CanonicalDeserialize)]
17#[educe(Clone, Debug, PartialEq, Eq)]
18pub struct G2Prepared<P: MNT6Config> {
19 pub x: Fp3<P::Fp3Config>,
20 pub y: Fp3<P::Fp3Config>,
21 pub x_over_twist: Fp3<P::Fp3Config>,
22 pub y_over_twist: Fp3<P::Fp3Config>,
23 pub double_coefficients: Vec<AteDoubleCoefficients<P>>,
24 pub addition_coefficients: Vec<AteAdditionCoefficients<P>>,
25}
26
27impl<P: MNT6Config> Default for G2Prepared<P> {
28 fn default() -> Self {
29 Self::from(G2Affine::<P>::generator())
30 }
31}
32
33impl<P: MNT6Config> 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 = G2Prepared {
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: <Fp3<P::Fp3Config>>::one(),
50 t: <Fp3<P::Fp3Config>>::one(),
51 };
52
53 let neg_g = g.neg();
54 for bit in P::ATE_LOOP_COUNT.iter().skip(1) {
55 let (r2, coeff) = MNT6::<P>::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 => MNT6::<P>::mixed_addition_for_flipper_miller_loop(&g.x, &g.y, &r),
61 -1 => MNT6::<P>::mixed_addition_for_flipper_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_x = r.x * &rz2_inv;
75 let minus_r_y = -r.y * &rz3_inv;
76
77 let add_result =
78 MNT6::<P>::mixed_addition_for_flipper_miller_loop(&minus_r_x, &minus_r_y, &r);
79 g_prep.addition_coefficients.push(add_result.1);
80 }
81
82 g_prep
83 }
84}
85
86impl<'a, P: MNT6Config> From<&'a G2Affine<P>> for G2Prepared<P> {
87 fn from(g2: &'a G2Affine<P>) -> Self {
88 (*g2).into()
89 }
90}
91
92impl<P: MNT6Config> From<G2Projective<P>> for G2Prepared<P> {
93 fn from(g2: G2Projective<P>) -> Self {
94 g2.into_affine().into()
95 }
96}
97impl<'a, P: MNT6Config> From<&'a G2Projective<P>> for G2Prepared<P> {
98 fn from(g2: &'a G2Projective<P>) -> Self {
99 (*g2).into()
100 }
101}
102
103pub struct G2ProjectiveExtended<P: MNT6Config> {
104 pub x: Fp3<P::Fp3Config>,
105 pub y: Fp3<P::Fp3Config>,
106 pub z: Fp3<P::Fp3Config>,
107 pub t: Fp3<P::Fp3Config>,
108}
109
110#[derive(Educe, CanonicalSerialize, CanonicalDeserialize)]
111#[educe(Clone, Debug, PartialEq, Eq)]
112pub struct AteDoubleCoefficients<P: MNT6Config> {
113 pub c_h: Fp3<P::Fp3Config>,
114 pub c_4c: Fp3<P::Fp3Config>,
115 pub c_j: Fp3<P::Fp3Config>,
116 pub c_l: Fp3<P::Fp3Config>,
117}
118
119#[derive(Educe, CanonicalSerialize, CanonicalDeserialize)]
120#[educe(Clone, Debug, PartialEq, Eq)]
121pub struct AteAdditionCoefficients<P: MNT6Config> {
122 pub c_l1: Fp3<P::Fp3Config>,
123 pub c_rz: Fp3<P::Fp3Config>,
124}