substrate_bn/fields/
mod.rs

1mod fp;
2mod fq2;
3mod fq6;
4mod fq12;
5
6use crate::arith::U256;
7use rand::Rng;
8use core::ops::{Add, Mul, Neg, Sub};
9use alloc::fmt::Debug;
10
11pub use self::fp::{const_fq, Fq, Fr};
12pub use self::fq2::{Fq2, fq2_nonresidue};
13pub use self::fq6::Fq6;
14pub use self::fq12::Fq12;
15
16pub trait FieldElement
17    : Sized
18    + Copy
19    + Clone
20    + Add<Output = Self>
21    + Sub<Output = Self>
22    + Mul<Output = Self>
23    + Neg<Output = Self>
24    + PartialEq
25    + Eq
26    + Debug {
27    fn zero() -> Self;
28    fn one() -> Self;
29    fn random<R: Rng>(_: &mut R) -> Self;
30    fn is_zero(&self) -> bool;
31    fn squared(&self) -> Self {
32        (*self) * (*self)
33    }
34    fn inverse(self) -> Option<Self>;
35    fn pow<I: Into<U256>>(&self, by: I) -> Self {
36        let mut res = Self::one();
37
38        for i in by.into().bits() {
39            res = res.squared();
40            if i {
41                res = *self * res;
42            }
43        }
44
45        res
46    }
47}
48
49#[cfg(test)]
50mod tests;
51
52#[test]
53fn test_fr() {
54    tests::field_trials::<Fr>();
55}
56
57#[test]
58fn test_fq() {
59    tests::field_trials::<Fq>();
60}
61
62#[test]
63fn test_fq2() {
64    tests::field_trials::<Fq2>();
65}
66
67#[test]
68fn test_str() {
69    assert_eq!(
70        -Fr::one(),
71        Fr::from_str(
72            "21888242871839275222246405745257275088548364400416034343698204186575808495616"
73        ).unwrap()
74    );
75    assert_eq!(
76        -Fq::one(),
77        Fq::from_str(
78            "21888242871839275222246405745257275088696311157297823662689037894645226208582"
79        ).unwrap()
80    );
81}
82
83#[test]
84fn test_fq6() {
85    tests::field_trials::<Fq6>();
86}
87
88#[test]
89fn test_fq12() {
90    tests::field_trials::<Fq12>();
91}
92
93#[test]
94fn fq12_test_vector() {
95    let start = Fq12::new(
96        Fq6::new(
97            Fq2::new(
98                Fq::from_str(
99                    "19797905000333868150253315089095386158892526856493194078073564469188852136946",
100                ).unwrap(),
101                Fq::from_str(
102                    "10509658143212501778222314067134547632307419253211327938344904628569123178733",
103                ).unwrap(),
104            ),
105            Fq2::new(
106                Fq::from_str(
107                    "208316612133170645758860571704540129781090973693601051684061348604461399206",
108                ).unwrap(),
109                Fq::from_str(
110                    "12617661120538088237397060591907161689901553895660355849494983891299803248390",
111                ).unwrap(),
112            ),
113            Fq2::new(
114                Fq::from_str(
115                    "2897490589776053688661991433341220818937967872052418196321943489809183508515",
116                ).unwrap(),
117                Fq::from_str(
118                    "2730506433347642574983433139433778984782882168213690554721050571242082865799",
119                ).unwrap(),
120            ),
121        ),
122        Fq6::new(
123            Fq2::new(
124                Fq::from_str(
125                    "17870056122431653936196746815433147921488990391314067765563891966783088591110",
126                ).unwrap(),
127                Fq::from_str(
128                    "14314041658607615069703576372547568077123863812415914883625850585470406221594",
129                ).unwrap(),
130            ),
131            Fq2::new(
132                Fq::from_str(
133                    "10123533891707846623287020000407963680629966110211808794181173248765209982878",
134                ).unwrap(),
135                Fq::from_str(
136                    "5062091880848845693514855272640141851746424235009114332841857306926659567101",
137                ).unwrap(),
138            ),
139            Fq2::new(
140                Fq::from_str(
141                    "9839781502639936537333620974973645053542086898304697594692219798017709586567",
142                ).unwrap(),
143                Fq::from_str(
144                    "1583892292110602864638265389721494775152090720173641072176370350017825640703",
145                ).unwrap(),
146            ),
147        ),
148    );
149
150    // Do a bunch of arbitrary stuff to the element
151
152    let mut next = start.clone();
153    for _ in 0..100 {
154        next = next * start;
155    }
156
157    let cpy = next.clone();
158
159    for _ in 0..10 {
160        next = next.squared();
161    }
162
163    for _ in 0..10 {
164        next = next + start;
165        next = next - cpy;
166        next = -next;
167    }
168
169    next = next.squared();
170
171    let finally = Fq12::new(
172        Fq6::new(
173            Fq2::new(
174                Fq::from_str(
175                    "18388750939593263065521177085001223024106699964957029146547831509155008229833",
176                ).unwrap(),
177                Fq::from_str(
178                    "18370529854582635460997127698388761779167953912610241447912705473964014492243",
179                ).unwrap(),
180            ),
181            Fq2::new(
182                Fq::from_str(
183                    "3691824277096717481466579496401243638295254271265821828017111951446539785268",
184                ).unwrap(),
185                Fq::from_str(
186                    "20513494218085713799072115076991457239411567892860153903443302793553884247235",
187                ).unwrap(),
188            ),
189            Fq2::new(
190                Fq::from_str(
191                    "12214155472433286415803224222551966441740960297013786627326456052558698216399",
192                ).unwrap(),
193                Fq::from_str(
194                    "10987494248070743195602580056085773610850106455323751205990078881956262496575",
195                ).unwrap(),
196            ),
197        ),
198        Fq6::new(
199            Fq2::new(
200                Fq::from_str(
201                    "5134522153456102954632718911439874984161223687865160221119284322136466794876",
202                ).unwrap(),
203                Fq::from_str(
204                    "20119236909927036376726859192821071338930785378711977469360149362002019539920",
205                ).unwrap(),
206            ),
207            Fq2::new(
208                Fq::from_str(
209                    "8839766648621210419302228913265679710586991805716981851373026244791934012854",
210                ).unwrap(),
211                Fq::from_str(
212                    "9103032146464138788288547957401673544458789595252696070370942789051858719203",
213                ).unwrap(),
214            ),
215            Fq2::new(
216                Fq::from_str(
217                    "10378379548636866240502412547812481928323945124508039853766409196375806029865",
218                ).unwrap(),
219                Fq::from_str(
220                    "9021627154807648093720460686924074684389554332435186899318369174351765754041",
221                ).unwrap(),
222            ),
223        ),
224    );
225
226    assert_eq!(finally, next);
227}
228
229#[test]
230fn test_cyclotomic_exp() {
231    let orig = Fq12::new(
232        Fq6::new(
233            Fq2::new(
234                Fq::from_str(
235                    "2259924035228092997691937637688451143058635253053054071159756458902878894295",
236                ).unwrap(),
237                Fq::from_str(
238                    "13145690032701362144460254305183927872683620413225364127064863863535255135244",
239                ).unwrap(),
240            ),
241            Fq2::new(
242                Fq::from_str(
243                    "9910063591662383599552477067956819406417086889312288278252482503717089428441",
244                ).unwrap(),
245                Fq::from_str(
246                    "537414042055419261990282459138081732565514913399498746664966841152381183961",
247                ).unwrap(),
248            ),
249            Fq2::new(
250                Fq::from_str(
251                    "15311812409497308894370893420777496684951030254049554818293571309705780605004",
252                ).unwrap(),
253                Fq::from_str(
254                    "13657107176064455789881282546557276003626320193974643644160350907227082365810",
255                ).unwrap(),
256            ),
257        ),
258        Fq6::new(
259            Fq2::new(
260                Fq::from_str(
261                    "4913017949003742946864670837361832856526234260447029873580022776602534856819",
262                ).unwrap(),
263                Fq::from_str(
264                    "7834351480852267338070670220119081676575418514182895774094743209915633114041",
265                ).unwrap(),
266            ),
267            Fq2::new(
268                Fq::from_str(
269                    "12837298223308203788092748646758194441270207338661891973231184407371206766993",
270                ).unwrap(),
271                Fq::from_str(
272                    "12756474445699147370503225379431475413909971718057034061593007812727141391799",
273                ).unwrap(),
274            ),
275            Fq2::new(
276                Fq::from_str(
277                    "9473802207170192255373153510655867502408045964296373712891954747252332944018",
278                ).unwrap(),
279                Fq::from_str(
280                    "4583089109360519374075173304035813179013579459429335467869926761027310749713",
281                ).unwrap(),
282            ),
283        ),
284    );
285
286    let expected = Fq12::new(
287        Fq6::new(
288            Fq2::new(
289                Fq::from_str(
290                    "14722956046055152398903846391223329501345567382234608299399030576415080188350",
291                ).unwrap(),
292                Fq::from_str(
293                    "14280703280777926697010730619606819467080027543707671882210769811674790473417",
294                ).unwrap(),
295            ),
296            Fq2::new(
297                Fq::from_str(
298                    "19969875076083990244184003223190771301761436396530543002586073549972410735411",
299                ).unwrap(),
300                Fq::from_str(
301                    "10717335566913889643303549252432531178405520196706173198634734518494041323243",
302                ).unwrap(),
303            ),
304            Fq2::new(
305                Fq::from_str(
306                    "6063612626166484870786832843320782567259894784043383626084549455432890717937",
307                ).unwrap(),
308                Fq::from_str(
309                    "17089783040131779205038789608891431427943860868115199598200376195935079808729",
310                ).unwrap(),
311            ),
312        ),
313        Fq6::new(
314            Fq2::new(
315                Fq::from_str(
316                    "10029863438921507421569931792104023129735006154272482043027653425575205672906",
317                ).unwrap(),
318                Fq::from_str(
319                    "6406252222753462799887280578845937185621081001436094637606245493619821542775",
320                ).unwrap(),
321            ),
322            Fq2::new(
323                Fq::from_str(
324                    "1048245462913506652602966692378792381004227332967846949234978073448561848050",
325                ).unwrap(),
326                Fq::from_str(
327                    "1444281375189053827455518242624554285012408033699861764136810522738182087554",
328                ).unwrap(),
329            ),
330            Fq2::new(
331                Fq::from_str(
332                    "8839610992666735109106629514135300820412539620261852250193684883379364789120",
333                ).unwrap(),
334                Fq::from_str(
335                    "11347360242067273846784836674906058940820632082713814508736182487171407730718",
336                ).unwrap(),
337            ),
338        ),
339    );
340
341    let e = orig.exp_by_neg_z();
342
343    assert_eq!(e, expected);
344}