snarkvm_curves/bls12_377/
fq6.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use snarkvm_fields::{
17    Fp2Parameters,
18    field,
19    fp6_3over2::{Fp6, Fp6Parameters},
20};
21use snarkvm_utilities::biginteger::BigInteger384;
22
23use crate::bls12_377::{Fq, Fq2, Fq2Parameters};
24
25pub type Fq6 = Fp6<Fq6Parameters>;
26
27#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
28pub struct Fq6Parameters;
29
30impl Fp6Parameters for Fq6Parameters {
31    type Fp2Params = Fq2Parameters;
32
33    const FROBENIUS_COEFF_FP6_C1: [Fq2; 6] = [
34        // Fp2::NONRESIDUE^(((q^0) - 1) / 3)
35        field!(
36            Fq2,
37            field!(
38                Fq,
39                BigInteger384([
40                    0x2cdffffffffff68,
41                    0x51409f837fffffb1,
42                    0x9f7db3a98a7d3ff2,
43                    0x7b4e97b76e7c6305,
44                    0x4cf495bf803c84e8,
45                    0x8d6661e2fdf49a,
46                ])
47            ),
48            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
49        ),
50        // Fp2::NONRESIDUE^(((q^1) - 1) / 3)
51        field!(
52            Fq2,
53            field!(
54                Fq,
55                BigInteger384([
56                    0x5892506da58478da,
57                    0x133366940ac2a74b,
58                    0x9b64a150cdf726cf,
59                    0x5cc426090a9c587e,
60                    0x5cf848adfdcd640c,
61                    0x4702bf3ac02380,
62                ])
63            ),
64            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
65        ),
66        // Fp2::NONRESIDUE^(((q^2) - 1) / 3)
67        field!(
68            Fq2,
69            field!(
70                Fq,
71                BigInteger384([
72                    0xdacd106da5847973,
73                    0xd8fe2454bac2a79a,
74                    0x1ada4fd6fd832edc,
75                    0xfb9868449d150908,
76                    0xd63eb8aeea32285e,
77                    0x167d6a36f873fd0,
78                ])
79            ),
80            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
81        ),
82        // Fp2::NONRESIDUE^(((q^3) - 1) / 3)
83        field!(
84            Fq2,
85            field!(
86                Fq,
87                BigInteger384([
88                    0x823ac00000000099,
89                    0xc5cabdc0b000004f,
90                    0x7f75ae862f8c080d,
91                    0x9ed4423b9278b089,
92                    0x79467000ec64c452,
93                    0x120d3e434c71c50,
94                ])
95            ),
96            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
97        ),
98        // Fp2::NONRESIDUE^(((q^4) - 1) / 3)
99        field!(
100            Fq2,
101            field!(
102                Fq,
103                BigInteger384([
104                    0x2c766f925a7b8727,
105                    0x3d7f6b0253d58b5,
106                    0x838ec0deec122131,
107                    0xbd5eb3e9f658bb10,
108                    0x6942bd126ed3e52e,
109                    0x1673786dd04ed6a,
110                ])
111            ),
112            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
113        ),
114        // Fp2::NONRESIDUE^(((q^5) - 1) / 3)
115        field!(
116            Fq2,
117            field!(
118                Fq,
119                BigInteger384([
120                    0xaa3baf925a7b868e,
121                    0x3e0d38ef753d5865,
122                    0x4191258bc861923,
123                    0x1e8a71ae63e00a87,
124                    0xeffc4d11826f20dc,
125                    0x4663a2a83dd119,
126                ])
127            ),
128            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
129        ),
130    ];
131    const FROBENIUS_COEFF_FP6_C2: [Fq2; 6] = [
132        // Fp2::NONRESIDUE^((2*(q^0) - 2) / 3)
133        field!(
134            Fq2,
135            field!(
136                Fq,
137                BigInteger384([
138                    0x2cdffffffffff68,
139                    0x51409f837fffffb1,
140                    0x9f7db3a98a7d3ff2,
141                    0x7b4e97b76e7c6305,
142                    0x4cf495bf803c84e8,
143                    0x8d6661e2fdf49a,
144                ])
145            ),
146            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
147        ),
148        // Fp2::NONRESIDUE^((2*(q^1) - 2) / 3)
149        field!(
150            Fq2,
151            field!(
152                Fq,
153                BigInteger384([
154                    0xdacd106da5847973,
155                    0xd8fe2454bac2a79a,
156                    0x1ada4fd6fd832edc,
157                    0xfb9868449d150908,
158                    0xd63eb8aeea32285e,
159                    0x167d6a36f873fd0,
160                ])
161            ),
162            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
163        ),
164        // Fp2::NONRESIDUE^((2*(q^2) - 2) / 3)
165        field!(
166            Fq2,
167            field!(
168                Fq,
169                BigInteger384([
170                    0x2c766f925a7b8727,
171                    0x3d7f6b0253d58b5,
172                    0x838ec0deec122131,
173                    0xbd5eb3e9f658bb10,
174                    0x6942bd126ed3e52e,
175                    0x1673786dd04ed6a,
176                ])
177            ),
178            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
179        ),
180        // Fp2::NONRESIDUE^((2*(q^3) - 2) / 3)
181        field!(
182            Fq2,
183            field!(
184                Fq,
185                BigInteger384([
186                    0x2cdffffffffff68,
187                    0x51409f837fffffb1,
188                    0x9f7db3a98a7d3ff2,
189                    0x7b4e97b76e7c6305,
190                    0x4cf495bf803c84e8,
191                    0x8d6661e2fdf49a,
192                ])
193            ),
194            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
195        ),
196        // Fp2::NONRESIDUE^((2*(q^4) - 2) / 3)
197        field!(
198            Fq2,
199            field!(
200                Fq,
201                BigInteger384([
202                    0xdacd106da5847973,
203                    0xd8fe2454bac2a79a,
204                    0x1ada4fd6fd832edc,
205                    0xfb9868449d150908,
206                    0xd63eb8aeea32285e,
207                    0x167d6a36f873fd0,
208                ])
209            ),
210            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
211        ),
212        // Fp2::NONRESIDUE^((2*(q^5) - 2) / 3)
213        field!(
214            Fq2,
215            field!(
216                Fq,
217                BigInteger384([
218                    0x2c766f925a7b8727,
219                    0x3d7f6b0253d58b5,
220                    0x838ec0deec122131,
221                    0xbd5eb3e9f658bb10,
222                    0x6942bd126ed3e52e,
223                    0x1673786dd04ed6a,
224                ])
225            ),
226            field!(Fq, BigInteger384([0x0, 0x0, 0x0, 0x0, 0x0, 0x0])),
227        ),
228    ];
229    /// NONRESIDUE = U
230    const NONRESIDUE: Fq2 = field!(
231        Fq2,
232        field!(Fq, BigInteger384([0, 0, 0, 0, 0, 0])),
233        field!(
234            Fq,
235            BigInteger384([
236                202099033278250856u64,
237                5854854902718660529u64,
238                11492539364873682930u64,
239                8885205928937022213u64,
240                5545221690922665192u64,
241                39800542322357402u64,
242            ])
243        ),
244    );
245
246    #[inline(always)]
247    fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
248        // Karatsuba multiplication with constant other = u.
249        let c0 = Fq2Parameters::mul_fp_by_nonresidue(&fe.c1);
250        let c1 = fe.c0;
251        field!(Fq2, c0, c1)
252    }
253}
254
255#[cfg(test)]
256mod test {
257    use snarkvm_fields::{One, Zero};
258    use snarkvm_utilities::rand::{TestRng, Uniform};
259
260    use super::*;
261
262    #[test]
263    fn test_fq2_mul_nonresidue() {
264        let mut rng = TestRng::default();
265
266        let nqr = Fq2::new(Fq::zero(), Fq::one());
267        println!("One: {:?}", Fq::one());
268
269        for _ in 0..1000 {
270            let mut a = Fq2::rand(&mut rng);
271            let mut b = a;
272            a *= &Fq6Parameters::NONRESIDUE;
273            b *= &nqr;
274
275            assert_eq!(a, b);
276        }
277    }
278}