snarkvm_curves/bls12_377/
g2.rs1use snarkvm_fields::{Field, PrimeField, Zero, field};
17use snarkvm_utilities::{
18 BigInteger,
19 BitIteratorBE,
20 biginteger::{BigInteger256, BigInteger384},
21};
22
23use crate::{
24 AffineCurve,
25 ProjectiveCurve,
26 bls12_377::{Fq, Fq2, Fr, g1::Bls12_377G1Parameters},
27 traits::{ModelParameters, ShortWeierstrassParameters},
28};
29
30use std::ops::Neg;
31
32#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
33pub struct Bls12_377G2Parameters;
34
35impl ModelParameters for Bls12_377G2Parameters {
36 type BaseField = Fq2;
37 type ScalarField = Fr;
38}
39
40impl ShortWeierstrassParameters for Bls12_377G2Parameters {
41 const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = (G2_GENERATOR_X, G2_GENERATOR_Y);
43 const B1: Fr = field!(
45 Fr,
46 BigInteger256([12574070832645531618, 10005695704657941814, 1564543351912391449, 657300228442948690])
47 );
48 const B2: Fr = field!(
50 Fr,
51 BigInteger256([2417046298041509844, 11783911742408086824, 14689097366802547462, 270119112518072728])
52 );
53 const COFACTOR: &'static [u64] = &[
56 0x0000000000000001,
57 0x452217cc90000000,
58 0xa0f3622fba094800,
59 0xd693e8c36676bd09,
60 0x8c505634fae2e189,
61 0xfbb36b00e1dcc40c,
62 0xddd88d99a6f6a829,
63 0x26ba558ae9562a,
64 ];
65 const COFACTOR_INV: Fr = field!(
68 Fr,
69 BigInteger256([15499857013495546999, 4613531467548868169, 14546778081091178013, 549402535258503313,])
70 );
71 const PHI: Fq2 = field!(
72 Fq2,
73 field!(Fq, BigInteger384([0, 0, 0, 0, 0, 0])),
74 field!(
75 Fq,
76 BigInteger384([
77 0x2c766f925a7b8727,
78 0x03d7f6b0253d58b5,
79 0x838ec0deec122131,
80 0xbd5eb3e9f658bb10,
81 0x6942bd126ed3e52e,
82 0x01673786dd04ed6a,
83 ])
84 ),
85 );
86 const R128: Fr = field!(
88 Fr,
89 BigInteger256([13717662654766427599, 14709524173037165000, 15342848074630952979, 736762107895475646])
90 );
91 const WEIERSTRASS_A: Fq2 = field!(Fq2, Bls12_377G1Parameters::WEIERSTRASS_A, Bls12_377G1Parameters::WEIERSTRASS_A,);
93 const WEIERSTRASS_B: Fq2 = field!(
100 Fq2,
101 field!(Fq, BigInteger384([0, 0, 0, 0, 0, 0])),
102 field!(
103 Fq,
104 BigInteger384([
105 9255502405446297221,
106 10229180150694123945,
107 9215585410771530959,
108 13357015519562362907,
109 5437107869987383107,
110 16259554076827459,
111 ])
112 ),
113 );
114
115 #[inline(always)]
116 fn mul_by_a(_: &Self::BaseField) -> Self::BaseField {
117 Self::BaseField::zero()
118 }
119
120 fn is_in_correct_subgroup_assuming_on_curve(
121 p: &crate::templates::short_weierstrass_jacobian::Affine<Self>,
122 ) -> bool {
123 p.mul_bits(BitIteratorBE::new(Self::ScalarField::characteristic())).is_zero()
124 }
125
126 fn glv_endomorphism(
127 mut p: crate::templates::short_weierstrass_jacobian::Affine<Self>,
128 ) -> crate::templates::short_weierstrass_jacobian::Affine<Self> {
129 p.x.mul_by_fp(&Self::PHI.c1);
130 p
131 }
132
133 fn mul_projective(
134 p: crate::templates::short_weierstrass_jacobian::Projective<Self>,
135 by: Self::ScalarField,
136 ) -> crate::templates::short_weierstrass_jacobian::Projective<Self> {
137 type ScalarBigInt = <Fr as PrimeField>::BigInteger;
138
139 const GLV_WINDOW_SIZE: usize = 4;
141
142 const TABLE_SIZE: i64 = 1 << (GLV_WINDOW_SIZE + 1);
144 const HALF_TABLE_SIZE: i64 = 1 << (GLV_WINDOW_SIZE);
145 const MASK_FOR_MOD_TABLE_SIZE: u64 = (TABLE_SIZE as u64) - 1;
146 const L: usize = 1 << (GLV_WINDOW_SIZE - 1);
148
149 let decomposition = by.decompose(&Self::Q1, &Self::Q2, Self::B1, Self::B2, Self::R128, &Self::HALF_R);
150
151 let mut t_1 = Vec::with_capacity(L);
153 let double = crate::templates::short_weierstrass_jacobian::Affine::<Self>::from(p.double());
154 t_1.push(p);
155 for i in 1..L {
156 t_1.push(t_1[i - 1].add_mixed(&double));
157 }
158 let t_1 =
159 crate::templates::short_weierstrass_jacobian::Projective::<Self>::batch_normalization_into_affine(t_1);
160
161 let t_2 = t_1.iter().copied().map(Self::glv_endomorphism).collect::<Vec<_>>();
162
163 let mod_signed = |d| {
164 let d_mod_window_size = i64::try_from(d & MASK_FOR_MOD_TABLE_SIZE).unwrap();
165 if d_mod_window_size >= HALF_TABLE_SIZE { d_mod_window_size - TABLE_SIZE } else { d_mod_window_size }
166 };
167 let to_wnaf = |e: Self::ScalarField| -> Vec<i32> {
168 let mut naf = vec![];
169 let mut e = e.to_bigint();
170 while !e.is_zero() {
171 let next = if e.is_odd() {
172 let naf_sign = mod_signed(e.as_ref()[0]);
173 if naf_sign < 0 {
174 e.add_nocarry(&ScalarBigInt::from(-naf_sign as u64));
175 } else {
176 e.sub_noborrow(&ScalarBigInt::from(naf_sign as u64));
177 }
178 naf_sign.try_into().unwrap()
179 } else {
180 0
181 };
182 naf.push(next);
183 e.div2();
184 }
185
186 naf
187 };
188
189 let wnaf = |k1: Self::ScalarField, k2: Self::ScalarField, s1: bool, s2: bool| -> (Vec<i32>, Vec<i32>) {
190 let mut wnaf_1 = to_wnaf(k1);
191 let mut wnaf_2 = to_wnaf(k2);
192
193 if s1 {
194 wnaf_1.iter_mut().for_each(|e| *e = -*e);
195 }
196 if !s2 {
197 wnaf_2.iter_mut().for_each(|e| *e = -*e);
198 }
199
200 (wnaf_1, wnaf_2)
201 };
202
203 let naf_add = |table: &[crate::templates::short_weierstrass_jacobian::Affine<Self>],
204 naf: i32,
205 acc: &mut crate::templates::short_weierstrass_jacobian::Projective<Self>| {
206 if naf != 0 {
207 let mut p_1 = table[(naf.abs() >> 1) as usize];
208 if naf < 0 {
209 p_1 = p_1.neg();
210 }
211 acc.add_assign_mixed(&p_1);
212 }
213 };
214
215 let (naf_1, naf_2) = wnaf(decomposition.0, decomposition.1, decomposition.2, decomposition.3);
217 let max_len = naf_1.len().max(naf_2.len());
218 let mut acc = crate::templates::short_weierstrass_jacobian::Projective::<Self>::zero();
219 for i in (0..max_len).rev() {
220 if i < naf_1.len() {
221 naf_add(&t_1, naf_1[i], &mut acc)
222 }
223
224 if i < naf_2.len() {
225 naf_add(&t_2, naf_2[i], &mut acc)
226 }
227
228 if i != 0 {
229 acc.double_in_place();
230 }
231 }
232
233 acc
234 }
235}
236
237pub const G2_GENERATOR_X: Fq2 = field!(Fq2, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1);
238pub const G2_GENERATOR_Y: Fq2 = field!(Fq2, G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1);
239
240pub const G2_GENERATOR_X_C0: Fq = field!(
247 Fq,
248 BigInteger384::new([
249 1394603105513884269,
250 11069732150289508451,
251 4261960060090787184,
252 13457254148541472797,
253 3177258746859163322,
254 82258727112085846
255 ])
256);
257
258pub const G2_GENERATOR_X_C1: Fq = field!(
265 Fq,
266 BigInteger384::new([
267 12672065269715576738,
268 3451530808602826578,
269 9486610028138952262,
270 5031487885431614078,
271 9858745210421513581,
272 63301617551232910
273 ])
274);
275
276pub const G2_GENERATOR_Y_C0: Fq = field!(
283 Fq,
284 BigInteger384::new([
285 1855632670224768760,
286 2989378521406112342,
287 9748867374972564648,
288 3204895972998458874,
289 16520689795595505429,
290 61918742406142643
291 ])
292);
293
294pub const G2_GENERATOR_Y_C1: Fq = field!(
301 Fq,
302 BigInteger384::new([
303 1532128906028652860,
304 14539073382194201855,
305 10828918286556702479,
306 14664598863867299115,
307 483199896405477997,
308 73741830940675480
309 ])
310);