1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
use crate::{ mnt4::MNT4Parameters, models::mnt4::MNT4, short_weierstrass_jacobian::{GroupAffine, GroupProjective}, AffineCurve, }; use ark_ff::{ bytes::ToBytes, fields::{Field, Fp2}, }; use ark_std::{ io::{Result as IoResult, Write}, vec::Vec, }; use num_traits::One; pub type G2Affine<P> = GroupAffine<<P as MNT4Parameters>::G2Parameters>; pub type G2Projective<P> = GroupProjective<<P as MNT4Parameters>::G2Parameters>; #[derive(Derivative)] #[derivative( Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"), PartialEq(bound = "P: MNT4Parameters"), Eq(bound = "P: MNT4Parameters") )] pub struct G2Prepared<P: MNT4Parameters> { pub x: Fp2<P::Fp2Params>, pub y: Fp2<P::Fp2Params>, pub x_over_twist: Fp2<P::Fp2Params>, pub y_over_twist: Fp2<P::Fp2Params>, pub double_coefficients: Vec<AteDoubleCoefficients<P>>, pub addition_coefficients: Vec<AteAdditionCoefficients<P>>, } impl<P: MNT4Parameters> Default for G2Prepared<P> { fn default() -> Self { Self::from(G2Affine::<P>::prime_subgroup_generator()) } } impl<P: MNT4Parameters> ToBytes for G2Prepared<P> { fn write<W: Write>(&self, _writer: W) -> IoResult<()> { unimplemented!() } } impl<P: MNT4Parameters> From<G2Affine<P>> for G2Prepared<P> { fn from(g2: G2Affine<P>) -> Self { let twist_inv = P::TWIST.inverse().unwrap(); let mut g2p = G2Prepared { x: g2.x, y: g2.y, x_over_twist: g2.x * &twist_inv, y_over_twist: g2.y * &twist_inv, double_coefficients: vec![], addition_coefficients: vec![], }; let mut r = G2ProjectiveExtended { x: g2.x, y: g2.y, z: <Fp2<P::Fp2Params>>::one(), t: <Fp2<P::Fp2Params>>::one(), }; for (idx, value) in P::ATE_LOOP_COUNT.iter().rev().enumerate() { let mut tmp = *value; let skip_extraneous_bits = 64 - value.leading_zeros(); let mut v = Vec::with_capacity(16); for i in 0..64 { if idx == 0 && (i == 0 || i >= skip_extraneous_bits) { continue; } v.push(tmp & 1 == 1); tmp >>= 1; } for bit in v.iter().rev() { let (r2, coeff) = MNT4::<P>::doubling_step_for_flipped_miller_loop(&r); g2p.double_coefficients.push(coeff); r = r2; if *bit { let (r2, coeff) = MNT4::<P>::mixed_addition_step_for_flipped_miller_loop(&g2.x, &g2.y, &r); g2p.addition_coefficients.push(coeff); r = r2; } tmp >>= 1; } } if P::ATE_IS_LOOP_COUNT_NEG { let rz_inv = r.z.inverse().unwrap(); let rz2_inv = rz_inv.square(); let rz3_inv = rz_inv * &rz2_inv; let minus_r_affine_x = r.x * &rz2_inv; let minus_r_affine_y = -r.y * &rz3_inv; let add_result = MNT4::<P>::mixed_addition_step_for_flipped_miller_loop( &minus_r_affine_x, &minus_r_affine_y, &r, ); g2p.addition_coefficients.push(add_result.1); } g2p } } pub(super) struct G2ProjectiveExtended<P: MNT4Parameters> { pub(crate) x: Fp2<P::Fp2Params>, pub(crate) y: Fp2<P::Fp2Params>, pub(crate) z: Fp2<P::Fp2Params>, pub(crate) t: Fp2<P::Fp2Params>, } #[derive(Derivative)] #[derivative( Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"), PartialEq(bound = "P: MNT4Parameters"), Eq(bound = "P: MNT4Parameters") )] pub struct AteDoubleCoefficients<P: MNT4Parameters> { pub c_h: Fp2<P::Fp2Params>, pub c_4c: Fp2<P::Fp2Params>, pub c_j: Fp2<P::Fp2Params>, pub c_l: Fp2<P::Fp2Params>, } #[derive(Derivative)] #[derivative( Clone(bound = "P: MNT4Parameters"), Debug(bound = "P: MNT4Parameters"), PartialEq(bound = "P: MNT4Parameters"), Eq(bound = "P: MNT4Parameters") )] pub struct AteAdditionCoefficients<P: MNT4Parameters> { pub c_l1: Fp2<P::Fp2Params>, pub c_rz: Fp2<P::Fp2Params>, }