snarkjs/src/f2field.js
src/f2field.jsRaw
1/*
2 Copyright 2018 0kims association.
3
4 This file is part of zksnark JavaScript library.
5
6 zksnark JavaScript library is a free software: you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by the
8 Free Software Foundation, either version 3 of the License, or (at your option)
9 any later version.
10
11 zksnark JavaScript library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 more details.
15
16 You should have received a copy of the GNU General Public License along with
17 zksnark JavaScript library. If not, see <https://www.gnu.org/licenses/>.
18*/
19
20const fUtils = require("./futils.js");
21
22class F2Field {
23 constructor(F, nonResidue) {
24 this.F = F;
25 this.zero = [this.F.zero, this.F.zero];
26 this.one = [this.F.one, this.F.zero];
27 this.nonResidue = nonResidue;
28 }
29
30 _mulByNonResidue(a) {
31 return this.F.mul(this.nonResidue, a);
32 }
33
34 copy(a) {
35 return [this.F.copy(a[0]), this.F.copy(a[1])];
36 }
37
38 add(a, b) {
39 return [
40 this.F.add(a[0], b[0]),
41 this.F.add(a[1], b[1])
42 ];
43 }
44
45 double(a) {
46 return this.add(a,a);
47 }
48
49 sub(a, b) {
50 return [
51 this.F.sub(a[0], b[0]),
52 this.F.sub(a[1], b[1])
53 ];
54 }
55
56 neg(a) {
57 return this.sub(this.zero, a);
58 }
59
60 mul(a, b) {
61 const aA = this.F.mul(a[0] , b[0]);
62 const bB = this.F.mul(a[1] , b[1]);
63
64 return [
65 this.F.add( aA , this._mulByNonResidue(bB)),
66 this.F.sub(
67 this.F.mul(
68 this.F.add(a[0], a[1]),
69 this.F.add(b[0], b[1])),
70 this.F.add(aA, bB))];
71 }
72
73 inverse(a) {
74 const t0 = this.F.square(a[0]);
75 const t1 = this.F.square(a[1]);
76 const t2 = this.F.sub(t0, this._mulByNonResidue(t1));
77 const t3 = this.F.inverse(t2);
78 return [
79 this.F.mul(a[0], t3),
80 this.F.neg(this.F.mul( a[1], t3)) ];
81 }
82
83 div(a, b) {
84 return this.mul(a, this.inverse(b));
85 }
86
87 square(a) {
88 const ab = this.F.mul(a[0] , a[1]);
89
90 /*
91 [
92 (a + b) * (a + non_residue * b) - ab - non_residue * ab,
93 ab + ab
94 ];
95 */
96
97 return [
98 this.F.sub(
99 this.F.mul(
100 this.F.add(a[0], a[1]) ,
101 this.F.add(
102 a[0] ,
103 this._mulByNonResidue(a[1]))),
104 this.F.add(
105 ab,
106 this._mulByNonResidue(ab))),
107 this.F.add(ab, ab)
108 ];
109 }
110
111 isZero(a) {
112 return this.F.isZero(a[0]) && this.F.isZero(a[1]);
113 }
114
115 equals(a, b) {
116 return this.F.equals(a[0], b[0]) && this.F.equals(a[1], b[1]);
117 }
118
119 affine(a) {
120 return [this.F.affine(a[0]), this.F.affine(a[1])];
121 }
122
123 mulScalar(base, e) {
124 return fUtils.mulScalar(this, base, e);
125 }
126
127 exp(base, e) {
128 return fUtils.exp(this, base, e);
129 }
130
131 toString(a) {
132 const cp = this.affine(a);
133 return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])} ]`;
134 }
135}
136
137module.exports = F2Field;