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