arnaucube
arnaucube/snarkjsPublic Self-hosted repository
snarkjs/src/f2field.js
src/f2field.jsRaw
  1/*
  2    Copyright 2018 0kims association.
  3
  4    This file is part of snarkjs.
  5
  6    snarkjs 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    snarkjs 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    snarkjs. 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;