ark_bls12_381_ext/curves/
g2.rs1use ark_bls12_381::{fq2::Fq2, g2::Config as ArkConfig, Fq};
2use ark_ec::AdditiveGroup;
3use ark_ff::{Field, MontFp};
4use ark_models_ext::{
5 bls12, bls12::Bls12Config, short_weierstrass::SWCurveConfig, AffineRepr, CurveConfig,
6 CurveGroup, PrimeGroup,
7};
8use ark_serialize::{Compress, SerializationError, Validate};
9use ark_std::{
10 io::{Read, Write},
11 marker::PhantomData,
12 ops::Neg,
13};
14
15use crate::{
16 util::{
17 read_g2_compressed, read_g2_uncompressed, serialize_fq, EncodingFlags, G2_SERIALIZED_SIZE,
18 },
19 CurveHooks,
20};
21
22pub use ark_bls12_381::g2::{
23 G2_GENERATOR_X, G2_GENERATOR_X_C0, G2_GENERATOR_X_C1, G2_GENERATOR_Y, G2_GENERATOR_Y_C0,
24 G2_GENERATOR_Y_C1,
25};
26
27const P_POWER_ENDOMORPHISM_COEFF_0 : Fq2 = Fq2::new(
29 Fq::ZERO,
30 MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437")
31);
32
33const P_POWER_ENDOMORPHISM_COEFF_1: Fq2 = Fq2::new(
35 MontFp!("2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"),
36 MontFp!("1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257")
37);
38
39const DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0: Fq2 = Fq2::new(
41 MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"),
42 Fq::ZERO
43);
44
45pub type G2Affine<H> = bls12::G2Affine<crate::Config<H>>;
46pub type G2Projective<H> = bls12::G2Projective<crate::Config<H>>;
47
48#[derive(Clone, Copy)]
49pub struct Config<H: CurveHooks>(PhantomData<fn() -> H>);
50
51impl<H: CurveHooks> CurveConfig for Config<H> {
52 const COFACTOR: &'static [u64] = <ArkConfig as CurveConfig>::COFACTOR;
53 const COFACTOR_INV: Self::ScalarField = <ArkConfig as CurveConfig>::COFACTOR_INV;
54
55 type BaseField = <ArkConfig as CurveConfig>::BaseField;
56 type ScalarField = <ArkConfig as CurveConfig>::ScalarField;
57}
58
59impl<H: CurveHooks> SWCurveConfig for Config<H> {
60 const COEFF_A: Self::BaseField = <ArkConfig as SWCurveConfig>::COEFF_A;
61 const COEFF_B: Self::BaseField = <ArkConfig as SWCurveConfig>::COEFF_B;
62
63 const GENERATOR: G2Affine<H> = G2Affine::<H>::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y);
64
65 #[inline(always)]
67 fn msm(bases: &[G2Affine<H>], scalars: &[Self::ScalarField]) -> Result<G2Projective<H>, usize> {
68 if bases.len() != scalars.len() {
69 return Err(bases.len().min(scalars.len()));
70 }
71 Ok(H::msm_g2(bases, scalars))
72 }
73
74 #[inline(always)]
76 fn mul_projective(base: &G2Projective<H>, scalar: &[u64]) -> G2Projective<H> {
77 H::mul_projective_g2(base, scalar)
78 }
79
80 #[inline(always)]
82 fn mul_affine(base: &G2Affine<H>, scalar: &[u64]) -> G2Projective<H> {
83 Self::mul_projective(&(*base).into(), scalar)
84 }
85
86 #[inline(always)]
87 fn mul_by_a(elem: Self::BaseField) -> Self::BaseField {
88 <ArkConfig as SWCurveConfig>::mul_by_a(elem)
89 }
90
91 #[inline(always)]
95 fn is_in_correct_subgroup_assuming_on_curve(point: &G2Affine<H>) -> bool {
96 let mut x_times_point = point.mul_bigint(crate::Config::<H>::X);
97 if crate::Config::<H>::X_IS_NEGATIVE {
98 x_times_point = -x_times_point;
99 }
100
101 let p_times_point = p_power_endomorphism(point);
102
103 x_times_point.eq(&p_times_point)
104 }
105
106 #[inline]
110 fn clear_cofactor(p: &G2Affine<H>) -> G2Affine<H> {
111 let x: &'static [u64] = crate::Config::<H>::X;
119 let p_projective = p.into_group();
120
121 let x_p = Config::mul_affine(p, x).neg();
123 let psi_p = p_power_endomorphism(p);
125 let mut psi2_p2 = double_p_power_endomorphism(&p_projective.double());
127
128 let mut tmp = x_p;
130 tmp += &psi_p;
131
132 let mut tmp2: G2Projective<H> = tmp;
134 tmp2 = tmp2.mul_bigint(x).neg();
135
136 psi2_p2 += tmp2;
138 psi2_p2 -= x_p;
139 psi2_p2 += &-psi_p;
140 (psi2_p2 - p_projective).into_affine()
141 }
142
143 fn deserialize_with_mode<R: Read>(
147 mut reader: R,
148 compress: Compress,
149 validate: Validate,
150 ) -> Result<G2Affine<H>, SerializationError> {
151 let p = if compress == Compress::Yes {
152 read_g2_compressed(&mut reader)?
153 } else {
154 read_g2_uncompressed(&mut reader)?
155 };
156
157 if validate == Validate::Yes && !p.is_in_correct_subgroup_assuming_on_curve() {
158 return Err(SerializationError::InvalidData);
159 }
160 Ok(p)
161 }
162
163 fn serialize_with_mode<W: Write>(
167 item: &G2Affine<H>,
168 mut writer: W,
169 compress: Compress,
170 ) -> Result<(), SerializationError> {
171 let encoding = EncodingFlags {
172 is_compressed: compress == Compress::Yes,
173 is_infinity: item.is_zero(),
174 is_lexographically_largest: item.y > -item.y,
175 };
176 let mut p = *item;
177 if encoding.is_infinity {
178 p = G2Affine::<H>::zero();
179 }
180
181 let mut x_bytes = [0u8; G2_SERIALIZED_SIZE];
182 let c1_bytes = serialize_fq(p.x.c1);
183 let c0_bytes = serialize_fq(p.x.c0);
184 x_bytes[0..48].copy_from_slice(&c1_bytes[..]);
185 x_bytes[48..96].copy_from_slice(&c0_bytes[..]);
186 if encoding.is_compressed {
187 let mut bytes: [u8; G2_SERIALIZED_SIZE] = x_bytes;
188
189 encoding.encode_flags(&mut bytes);
190 writer.write_all(&bytes)?;
191 } else {
192 let mut bytes = [0u8; 2 * G2_SERIALIZED_SIZE];
193
194 let mut y_bytes = [0u8; G2_SERIALIZED_SIZE];
195 let c1_bytes = serialize_fq(p.y.c1);
196 let c0_bytes = serialize_fq(p.y.c0);
197 y_bytes[0..48].copy_from_slice(&c1_bytes[..]);
198 y_bytes[48..96].copy_from_slice(&c0_bytes[..]);
199 bytes[0..G2_SERIALIZED_SIZE].copy_from_slice(&x_bytes);
200 bytes[G2_SERIALIZED_SIZE..].copy_from_slice(&y_bytes);
201
202 encoding.encode_flags(&mut bytes);
203 writer.write_all(&bytes)?;
204 };
205
206 Ok(())
207 }
208
209 fn serialized_size(compress: Compress) -> usize {
213 <ArkConfig as SWCurveConfig>::serialized_size(compress)
214 }
215}
216
217fn p_power_endomorphism<H: CurveHooks>(p: &G2Affine<H>) -> G2Affine<H> {
219 let mut res = *p;
234 res.x.frobenius_map_in_place(1);
235 res.y.frobenius_map_in_place(1);
236
237 let tmp_x = res.x;
238 res.x.c0 = -P_POWER_ENDOMORPHISM_COEFF_0.c1 * tmp_x.c1;
239 res.x.c1 = P_POWER_ENDOMORPHISM_COEFF_0.c1 * tmp_x.c0;
240 res.y *= P_POWER_ENDOMORPHISM_COEFF_1;
241
242 res
243}
244
245fn double_p_power_endomorphism<H: CurveHooks>(p: &G2Projective<H>) -> G2Projective<H> {
247 let mut res = *p;
248
249 res.x *= DOUBLE_P_POWER_ENDOMORPHISM_COEFF_0;
250 res.y = res.y.neg();
251
252 res
253}