halo2curves_axiom/bn256/
curve.rs

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
115// Generated using https://github.com/ConsenSys/gnark-crypto/blob/master/ecc/utils.go
116// with `bn256::Fr::ZETA`
117// See https://github.com/demining/Endomorphism-Secp256k1/blob/main/README.md
118// to have more details about the endomorphism.
119const ENDO_PARAMS_BN: EndoParameters = EndoParameters {
120    // round(b2/n)
121    gamma1: [0xd91d232ec7e0b3d7, 0x2, 0, 0],
122    // round(-b1/n)
123    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        // "0x30644e72e131a029b85045b68181585e06ceecda572a2489345f2299c0f9fa8d"
151        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        // self * COFACTOR_G2
158        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        // "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"
176        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        // self * GROUP_ORDER;
183
184        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            // Precomputed constants taken from https://github.com/ConsenSys/gnark-crypto/blob/441dc0ffe639294b8d09e394f24ba7575577229c/internal/generator/config/bn254.go#L26-L32.
220            [
221                "4",
222                "10944121435919637611123202872628637544348155578648911831344518947322613104291",
223                "8815841940592487685674414971303048083897117035520822607866",
224                "7296080957279758407415468581752425029565437052432607887563012631548408736189",
225            ],
226            // List of (u, (Q.x, Q.y)) taken from https://github.com/ConsenSys/gnark-crypto/blob/441dc0ffe639294b8d09e394f24ba7575577229c/ecc/bn254/hash_vectors_test.go#L4-L28
227            [
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}