1use crate::arithmetic::mul_512;
2use crate::arithmetic::sbb;
3use crate::arithmetic::EndoParameters;
4use crate::arithmetic::{CurveAffineExt, CurveEndo};
5use crate::bn256::Fq;
6use crate::bn256::Fq2;
7use crate::bn256::Fr;
8use crate::endo;
9use crate::ff::WithSmallOrderMulGroup;
10use crate::ff::{Field, PrimeField};
11use crate::group::Curve;
12use crate::group::{cofactor::CofactorGroup, prime::PrimeCurveAffine, Group, GroupEncoding};
13use crate::hash_to_curve::svdw_hash_to_curve;
14use crate::{
15 impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output,
16 impl_binops_multiplicative, impl_binops_multiplicative_mixed, impl_sub_binop_specify_output,
17 new_curve_impl,
18};
19use crate::{Coordinates, CurveAffine, CurveExt};
20use core::cmp;
21use core::fmt::Debug;
22use core::iter::Sum;
23use core::ops::{Add, Mul, Neg, Sub};
24use rand::RngCore;
25use std::convert::TryInto;
26use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
27
28#[cfg(feature = "derive_serde")]
29use serde::{Deserialize, Serialize};
30
31new_curve_impl!(
32 (pub),
33 G1,
34 G1Affine,
35 false,
36 Fq,
37 Fr,
38 (G1_GENERATOR_X,G1_GENERATOR_Y),
39 G1_A,
40 G1_B,
41 "bn256_g1",
42 |curve_id, domain_prefix| svdw_hash_to_curve(curve_id, domain_prefix, G1::SVDW_Z),
43);
44
45new_curve_impl!(
46 (pub),
47 G2,
48 G2Affine,
49 false,
50 Fq2,
51 Fr,
52 (G2_GENERATOR_X, G2_GENERATOR_Y),
53 G2_A,
54 G2_B,
55 "bn256_g2",
56 |_, _| unimplemented!(),
57);
58
59const G1_GENERATOR_X: Fq = Fq::one();
60const G1_GENERATOR_Y: Fq = Fq::from_raw([2, 0, 0, 0]);
61const G1_A: Fq = Fq::from_raw([0, 0, 0, 0]);
62const G1_B: Fq = Fq::from_raw([3, 0, 0, 0]);
63
64const G2_A: Fq2 = Fq2 {
65 c0: Fq::from_raw([0, 0, 0, 0]),
66 c1: Fq::from_raw([0, 0, 0, 0]),
67};
68
69const G2_B: Fq2 = Fq2 {
70 c0: Fq::from_raw([
71 0x3267e6dc24a138e5,
72 0xb5b4c5e559dbefa3,
73 0x81be18991be06ac3,
74 0x2b149d40ceb8aaae,
75 ]),
76 c1: Fq::from_raw([
77 0xe4a2bd0685c315d2,
78 0xa74fa084e52d1852,
79 0xcd2cafadeed8fdf4,
80 0x009713b03af0fed4,
81 ]),
82};
83
84const G2_GENERATOR_X: Fq2 = Fq2 {
85 c0: Fq::from_raw([
86 0x46debd5cd992f6ed,
87 0x674322d4f75edadd,
88 0x426a00665e5c4479,
89 0x1800deef121f1e76,
90 ]),
91 c1: Fq::from_raw([
92 0x97e485b7aef312c2,
93 0xf1aa493335a9e712,
94 0x7260bfb731fb5d25,
95 0x198e9393920d483a,
96 ]),
97};
98
99const G2_GENERATOR_Y: Fq2 = Fq2 {
100 c0: Fq::from_raw([
101 0x4ce6cc0166fa7daa,
102 0xe3d1e7690c43d37b,
103 0x4aab71808dcb408f,
104 0x12c85ea5db8c6deb,
105 ]),
106
107 c1: Fq::from_raw([
108 0x55acdadcd122975b,
109 0xbc4b313370b38ef3,
110 0xec9e99ad690c3395,
111 0x090689d0585ff075,
112 ]),
113};
114
115const ENDO_PARAMS_BN: EndoParameters = EndoParameters {
120 gamma1: [0xd91d232ec7e0b3d7, 0x2, 0, 0],
122 gamma2: [0x5398fd0300ff6565, 0x4ccef014a773d2d2, 0x02, 0],
124 b1: [0x89d3256894d213e3, 0, 0, 0],
125 b2: [0x0be4e1541221250b, 0x6f4d8248eeb859fd, 0, 0],
126};
127
128endo!(G1, Fr, ENDO_PARAMS_BN);
129
130impl group::cofactor::CofactorGroup for G1 {
131 type Subgroup = G1;
132
133 fn clear_cofactor(&self) -> Self {
134 *self
135 }
136
137 fn into_subgroup(self) -> CtOption<Self::Subgroup> {
138 CtOption::new(self, 1.into())
139 }
140
141 fn is_torsion_free(&self) -> Choice {
142 1.into()
143 }
144}
145
146impl CofactorGroup for G2 {
147 type Subgroup = G2;
148
149 fn clear_cofactor(&self) -> Self {
150 let e: [u8; 32] = [
152 0x30, 0x64, 0x4e, 0x72, 0xe1, 0x31, 0xa0, 0x29, 0xb8, 0x50, 0x45, 0xb6, 0x81, 0x81,
153 0x58, 0x5e, 0x06, 0xce, 0xec, 0xda, 0x57, 0x2a, 0x24, 0x89, 0x34, 0x5f, 0x22, 0x99,
154 0xc0, 0xf9, 0xfa, 0x8d,
155 ];
156
157 let mut acc = G2::identity();
159 for bit in e
160 .iter()
161 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
162 .skip(1)
163 {
164 acc = acc.double();
165 acc = G2::conditional_select(&acc, &(acc + self), bit);
166 }
167 acc
168 }
169
170 fn into_subgroup(self) -> CtOption<Self::Subgroup> {
171 unimplemented!();
172 }
173
174 fn is_torsion_free(&self) -> Choice {
175 let e: [u8; 32] = [
177 0x30, 0x64, 0x4e, 0x72, 0xe1, 0x31, 0xa0, 0x29, 0xb8, 0x50, 0x45, 0xb6, 0x81, 0x81,
178 0x58, 0x5d, 0x28, 0x33, 0xe8, 0x48, 0x79, 0xb9, 0x70, 0x91, 0x43, 0xe1, 0xf5, 0x93,
179 0xf0, 0x00, 0x00, 0x01,
180 ];
181
182 let mut acc = G2::identity();
185 for bit in e
186 .iter()
187 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
188 .skip(1)
189 {
190 acc = acc.double();
191 acc = G2::conditional_select(&acc, &(acc + self), bit);
192 }
193 acc.is_identity()
194 }
195}
196
197impl G1 {
198 const SVDW_Z: Fq = Fq::ONE;
199}
200
201#[cfg(test)]
202mod tests {
203 use crate::arithmetic::CurveEndo;
204 use crate::bn256::{Fr, G1, G2};
205 use crate::CurveExt;
206 use ff::Field;
207 use ff::{PrimeField, WithSmallOrderMulGroup};
208 use rand_core::OsRng;
209
210 #[test]
211 fn test_hash_to_curve() {
212 crate::tests::curve::hash_to_curve_test::<G1>();
213 }
214
215 #[test]
216 fn test_map_to_curve() {
217 crate::tests::curve::svdw_map_to_curve_test::<G1>(
218 G1::SVDW_Z,
219 [
221 "4",
222 "10944121435919637611123202872628637544348155578648911831344518947322613104291",
223 "8815841940592487685674414971303048083897117035520822607866",
224 "7296080957279758407415468581752425029565437052432607887563012631548408736189",
225 ],
226 [
228 (
229 "0xcb81538a98a2e3580076eed495256611813f6dae9e16d3d4f8de7af0e9833e1",
230 (
231 "0x1bb8810e2ceaf04786d4efd216fc2820ddd9363712efc736ada11049d8af5925",
232 "0x1efbf8d54c60d865cce08437668ea30f5bf90d287dbd9b5af31da852915e8f11",
233 ),
234 ),
235 (
236 "0xba35e127276e9000b33011860904ddee28f1d48ddd3577e2a797ef4a5e62319",
237 (
238 "0xda4a96147df1f35b0f820bd35c6fac3b80e8e320de7c536b1e054667b22c332",
239 "0x189bd3fbffe4c8740d6543754d95c790e44cd2d162858e3b733d2b8387983bb7",
240 ),
241 ),
242 (
243 "0x11852286660cd970e9d7f46f99c7cca2b75554245e91b9b19d537aa6147c28fc",
244 (
245 "0x2ff727cfaaadb3acab713fa22d91f5fddab3ed77948f3ef6233d7ea9b03f4da1",
246 "0x304080768fd2f87a852155b727f97db84b191e41970506f0326ed4046d1141aa",
247 ),
248 ),
249 (
250 "0x174d1c85d8a690a876cc1deba0166d30569fafdb49cb3ed28405bd1c5357a1cc",
251 (
252 "0x11a2eaa8e3e89de056d1b3a288a7f733c8a1282efa41d28e71af065ab245df9b",
253 "0x60f37c447ac29fd97b9bb83be98ddccf15e34831a9cdf5493b7fede0777ae06",
254 ),
255 ),
256 (
257 "0x73b81432b4cf3a8a9076201500d1b94159539f052a6e0928db7f2df74bff672",
258 (
259 "0x27409dccc6ee4ce90e24744fda8d72c0bc64e79766f778da0c1c0ef1c186ea84",
260 "0x1ac201a542feca15e77f30370da183514dc99d8a0b2c136d64ede35cd0b51dc0",
261 ),
262 ),
263 ],
264 );
265 }
266
267 #[test]
268 fn test_curve() {
269 crate::tests::curve::curve_tests::<G1>();
270 crate::tests::curve::curve_tests::<G2>();
271 }
272
273 #[test]
274 fn test_endo() {
275 let z_impl = Fr::ZETA;
276 let z_other = Fr::from_raw([
277 0x8b17ea66b99c90dd,
278 0x5bfc41088d8daaa7,
279 0xb3c4d79d41a91758,
280 0x00,
281 ]);
282 assert_eq!(z_impl * z_impl + z_impl, -Fr::ONE);
283 assert_eq!(z_other * z_other + z_other, -Fr::ONE);
284
285 let g = G1::generator();
286 assert_eq!(g * Fr::ZETA, g.endo());
287 let g = G2::generator();
288 assert_eq!(g * Fr::ZETA, g.endo());
289 for _ in 0..100000 {
290 let k = Fr::random(OsRng);
291 let (k1, k1_neg, k2, k2_neg) = G1::decompose_scalar(&k);
292 if k1_neg & k2_neg {
293 assert_eq!(k, -Fr::from_u128(k1) + Fr::ZETA * Fr::from_u128(k2))
294 } else if k1_neg {
295 assert_eq!(k, -Fr::from_u128(k1) - Fr::ZETA * Fr::from_u128(k2))
296 } else if k2_neg {
297 assert_eq!(k, Fr::from_u128(k1) + Fr::ZETA * Fr::from_u128(k2))
298 } else {
299 assert_eq!(k, Fr::from_u128(k1) - Fr::ZETA * Fr::from_u128(k2))
300 }
301 }
302 }
303
304 #[test]
305 fn test_serialization() {
306 crate::tests::curve::random_serialization_test::<G1>();
307 crate::tests::curve::random_serialization_test::<G2>();
308 #[cfg(feature = "derive_serde")]
309 {
310 crate::tests::curve::random_serde_test::<G1>();
311 crate::tests::curve::random_serde_test::<G2>();
312 }
313 }
314}