diff --git a/build/main.cjs b/build/main.cjs
index 9283f0d..b252d9f 100644
--- a/build/main.cjs
+++ b/build/main.cjs
@@ -4,17 +4,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
var bigInt = require('big-integer');
var crypto = require('crypto');
-var wasmcurves = require('wasmcurves');
-var os = require('os');
-var Worker = require('web-worker');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var bigInt__default = /*#__PURE__*/_interopDefaultLegacy(bigInt);
var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
-var wasmcurves__default = /*#__PURE__*/_interopDefaultLegacy(wasmcurves);
-var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
-var Worker__default = /*#__PURE__*/_interopDefaultLegacy(Worker);
/* global BigInt */
const hexLen = [ 0, 1, 2, 2, 3, 3, 3, 3, 4 ,4 ,4 ,4 ,4 ,4 ,4 ,4];
@@ -645,5725 +639,1196 @@ var _Scalar = /*#__PURE__*/Object.freeze({
snarkjs. If not, see .
*/
-/*
- This library does operations on polynomials with coefficients in a field F.
-
- A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented
- by the array [ p0, p1, p2, ... , pn ].
- */
-class PolField {
- constructor (F) {
- this.F = F;
-
- let rem = F.sqrt_t;
- let s = F.sqrt_s;
+/*
+exports.mulScalar = (F, base, e) =>{
+ let res = F.zero;
+ let rem = bigInt(e);
+ let exp = base;
- const five = this.F.add(this.F.add(this.F.two, this.F.two), this.F.one);
+ while (! rem.eq(bigInt.zero)) {
+ if (rem.and(bigInt.one).eq(bigInt.one)) {
+ res = F.add(res, exp);
+ }
+ exp = F.double(exp);
+ rem = rem.shiftRight(1);
+ }
- this.w = new Array(s+1);
- this.wi = new Array(s+1);
- this.w[s] = this.F.pow(five, rem);
- this.wi[s] = this.F.inv(this.w[s]);
+ return res;
+};
+*/
- let n=s-1;
- while (n>=0) {
- this.w[n] = this.F.square(this.w[n+1]);
- this.wi[n] = this.F.square(this.wi[n+1]);
- n--;
- }
+function exp(F, base, e) {
- this.roots = [];
-/* for (let i=0; i<16; i++) {
- let r = this.F.one;
- n = 1 << i;
- const rootsi = new Array(n);
- for (let j=0; j this.F.sqrt_s) n = this.s;
- for (let i=n; (i>=0) && (!this.roots[i]); i--) {
- let r = this.F.one;
- const nroots = 1 << i;
- const rootsi = new Array(nroots);
- for (let j=0; j=0; i--) {
- sub(a, b) {
- const m = Math.max(a.length, b.length);
- const res = new Array(m);
- for (let i=0; i a.length) {
- [b, a] = [a, b];
+function buildSqrt (F) {
+ if ((F.m % 2) == 1) {
+ if (eq(mod(F.p, 4), 1 )) {
+ if (eq(mod(F.p, 8), 1 )) {
+ if (eq(mod(F.p, 16), 1 )) {
+ // alg7_muller(F);
+ alg5_tonelliShanks(F);
+ } else if (eq(mod(F.p, 16), 9 )) {
+ alg4_kong(F);
+ } else {
+ throw new Error("Field withot sqrt");
+ }
+ } else if (eq(mod(F.p, 8), 5 )) {
+ alg3_atkin(F);
+ } else {
+ throw new Error("Field withot sqrt");
+ }
+ } else if (eq(mod(F.p, 4), 3 )) {
+ alg2_shanks(F);
}
-
- if ((b.length <= 2) || (b.length < log2$1(a.length))) {
- return this.mulNormal(a,b);
+ } else {
+ const pm2mod4 = mod(pow(F.p, F.m/2), 4);
+ if (pm2mod4 == 1) {
+ alg10_adj(F);
+ } else if (pm2mod4 == 3) {
+ alg9_adj(F);
} else {
- return this.mulFFT(a,b);
+ alg8_complex(F);
}
- }
- mulNormal(a, b) {
- let res = [];
- for (let i=0; i0) {
- const z = new Array(n).fill(this.F.zero);
- return z.concat(p);
- } else {
- if (-n >= p.length) return [];
- return p.slice(-n);
+ w = z;
+ for (let i=0; i> 1),
- F.mul(
- x,
- _eval(p, newX, offset+step , step << 1, n >> 1)));
- return res;
- }
- }
+function alg3_atkin(F) {
+ F.sqrt = function() {
+ throw new Error("Sqrt alg 3 not implemented");
+ };
+}
- lagrange(points) {
- let roots = [this.F.one];
- for (let i=0; i>>0;
+ }
}
+ }
+ else { // NodeJS
+ crypto__default['default'].randomFillSync(array);
+ }
+ return array;
+}
- return resn;
+/* global BigInt */
- }
+class ZqField$1 {
+ constructor(p) {
+ this.type="F1";
+ this.one = BigInt(1);
+ this.zero = BigInt(0);
+ this.p = BigInt(p);
+ this.m = 1;
+ this.negone = this.p-this.one;
+ this.two = BigInt(2);
+ this.half = this.p >> this.one;
+ this.bitLength = bitLength(this.p);
+ this.mask = (this.one << BigInt(this.bitLength)) - this.one;
- _fft(pall, bits, offset, step) {
+ this.n64 = Math.floor((this.bitLength - 1) / 64)+1;
+ this.n32 = this.n64*2;
+ this.n8 = this.n64*8;
+ this.R = this.e(this.one << BigInt(this.n64*64));
+ this.Ri = this.inv(this.R);
- const n = 1 << bits;
- if (n==1) {
- return [ pall[offset] ];
+ const e = this.negone >> this.one;
+ this.nqr = this.two;
+ let r = this.pow(this.nqr, e);
+ while (!this.eq(r, this.negone)) {
+ this.nqr = this.nqr + this.one;
+ r = this.pow(this.nqr, e);
}
- const ndiv2 = n >> 1;
- const p1 = this._fft(pall, bits-1, offset, step*2);
- const p2 = this._fft(pall, bits-1, offset+step, step*2);
- const out = new Array(n);
+ this.s = 0;
+ this.t = this.negone;
- let m= this.F.one;
- for (let i=0; i> this.one;
}
- return out;
- }
-
- extend(p, e) {
- if (e == p.length) return p;
- const z = new Array(e-p.length).fill(this.F.zero);
-
- return p.concat(z);
- }
+ this.nqr_to_t = this.pow(this.nqr, this.t);
- reduce(p) {
- if (p.length == 0) return p;
- if (! this.F.eq(p[p.length-1], this.F.zero) ) return p;
- let i=p.length-1;
- while( i>0 && this.F.eq(p[i], this.F.zero) ) i--;
- return p.slice(0, i+1);
+ buildSqrt(this);
}
- eq(a, b) {
- const pa = this.reduce(a);
- const pb = this.reduce(b);
-
- if (pa.length != pb.length) return false;
- for (let i=0; i= this.p) nres = nres % this.p;
+ return this.p - nres;
+ } else {
+ return (res>= this.p) ? res%this.p : res;
}
- return true;
}
- ruffini(p, r) {
- const res = new Array(p.length-1);
- res[res.length-1] = p[p.length-1];
- for (let i = res.length-2; i>=0; i--) {
- res[i] = this.F.add(this.F.mul(res[i+1], r), p[i+1]);
- }
- return res;
+ add(a, b) {
+ const res = a + b;
+ return res >= this.p ? res-this.p : res;
}
- _next2Power(v) {
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v++;
- return v;
+ sub(a, b) {
+ return (a >= b) ? a-b : this.p-b+a;
}
- toString(p) {
- const ap = this.normalize(p);
- let S = "";
- for (let i=ap.length-1; i>=0; i--) {
- if (!this.F.eq(p[i], this.F.zero)) {
- if (S!="") S += " + ";
- S = S + p[i].toString(10);
- if (i>0) {
- S = S + "x";
- if (i>1) {
- S = S + "^" +i;
- }
- }
- }
- }
- return S;
+ neg(a) {
+ return a ? this.p-a : a;
}
- normalize(p) {
- const res = new Array(p.length);
- for (let i=0; i this.half) ? a - this.p : a;
+ const bb = (b > this.half) ? b - this.p : b;
+ return aa < bb;
+ }
- // rec = x^(k - 2) / v* x^scaleV =>
- // rec = x^(k-2-scaleV)/ v
- //
- // res = x^m/v = x^(m + (2*k-2 - scaleV) - (2*k-2 - scaleV)) /v =>
- // res = rec * x^(m - (2*k-2 - scaleV)) =>
- // res = rec * x^(m - 2*k + 2 + scaleV)
+ gt(a, b) {
+ const aa = (a > this.half) ? a - this.p : a;
+ const bb = (b > this.half) ? b - this.p : b;
+ return aa > bb;
+ }
- const rec = this._reciprocal(this.scaleX(v, scaleV), kbits);
- const res = this.scaleX(rec, m - 2*k + 2 + scaleV);
+ leq(a, b) {
+ const aa = (a > this.half) ? a - this.p : a;
+ const bb = (b > this.half) ? b - this.p : b;
+ return aa <= bb;
+ }
- return res;
+ geq(a, b) {
+ const aa = (a > this.half) ? a - this.p : a;
+ const bb = (b > this.half) ? b - this.p : b;
+ return aa >= bb;
}
- div(_u, _v) {
- if (_u.length < _v.length) return [];
- const kbits = log2$1(_v.length-1)+1;
- const k = 1 << kbits;
+ div(a, b) {
+ return this.mul(a, this.inv(b));
+ }
- const u = this.scaleX(_u, k-_v.length);
- const v = this.scaleX(_v, k-_v.length);
+ idiv(a, b) {
+ if (!b) throw new Error("Division by zero");
+ return a / b;
+ }
- const n = v.length-1;
- let m = u.length-1;
+ inv(a) {
+ if (!a) throw new Error("Division by zero");
- const s = this._reciprocal(v, kbits);
- let t;
- if (m>2*n) {
- t = this.sub(this.scaleX([this.F.one], 2*n), this.mul(s, v));
+ let t = this.zero;
+ let r = this.p;
+ let newt = this.one;
+ let newr = a % this.p;
+ while (newr) {
+ let q = r/newr;
+ [t, newt] = [newt, t-q*newt];
+ [r, newr] = [newr, r-q*newr];
}
+ if (t 2*n ) {
- ut = this.mul(rem, t);
- rem = this.scaleX(ut, -2*n);
- m = rem.length-1;
- } else {
- finish = true;
- }
- }
+ mod(a, b) {
+ return a % b;
+ }
- return q;
+ pow(b, e) {
+ return exp(this, b, e);
}
+ exp(b, e) {
+ return exp(this, b, e);
+ }
- // returns the ith nth-root of one
- oneRoot(n, i) {
- let nbits = log2$1(n-1)+1;
- let res = this.F.one;
- let r = i;
+ band(a, b) {
+ const res = ((a & b) & this.mask);
+ return res >= this.p ? res-this.p : res;
+ }
- if(i>=n) {
- throw new Error("Given 'i' should be lower than 'n'");
- }
- else if (1<= this.p ? res-this.p : res;
+ }
- while (r>0) {
- if (r & 1 == 1) {
- res = this.F.mul(res, this.w[nbits]);
- }
- r = r >> 1;
- nbits --;
- }
- return res;
+ bxor(a, b) {
+ const res = ((a ^ b) & this.mask);
+ return res >= this.p ? res-this.p : res;
}
- computeVanishingPolinomial(bits, t) {
- const m = 1 << bits;
- return this.F.sub(this.F.pow(t, m), this.F.one);
+ bnot(a) {
+ const res = a ^ this.mask;
+ return res >= this.p ? res-this.p : res;
}
- evaluateLagrangePolynomials(bits, t) {
- const m= 1 << bits;
- const tm = this.F.pow(t, m);
- const u= new Array(m).fill(this.F.zero);
- this._setRoots(bits);
- const omega = this.w[bits];
-
- if (this.F.eq(tm, this.F.one)) {
- for (let i = 0; i < m; i++) {
- if (this.F.eq(this.roots[bits][0],t)) { // i.e., t equals omega^i
- u[i] = this.F.one;
- return u;
- }
+ shl(a, b) {
+ if (Number(b) < this.bitLength) {
+ const res = (a << b) & this.mask;
+ return res >= this.p ? res-this.p : res;
+ } else {
+ const nb = this.p - b;
+ if (Number(nb) < this.bitLength) {
+ return a >> nb;
+ } else {
+ return this.zero;
}
}
+ }
- const z = this.F.sub(tm, this.F.one);
- // let l = this.F.mul(z, this.F.pow(this.F.twoinv, m));
- let l = this.F.mul(z, this.F.inv(this.F.e(m)));
- for (let i = 0; i < m; i++) {
- u[i] = this.F.mul(l, this.F.inv(this.F.sub(t,this.roots[bits][i])));
- l = this.F.mul(l, omega);
+ shr(a, b) {
+ if (Number(b) < this.bitLength) {
+ return a >> b;
+ } else {
+ const nb = this.p - b;
+ if (Number(nb) < this.bitLength) {
+ const res = (a << nb) & this.mask;
+ return res >= this.p ? res-this.p : res;
+ } else {
+ return 0;
+ }
}
-
- return u;
}
- log2(V) {
- return log2$1(V);
+ land(a, b) {
+ return (a && b) ? this.one : this.zero;
}
-}
-
-function log2$1( V )
-{
- return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
-}
-
-function __fft(PF, pall, bits, offset, step) {
-
- const n = 1 << bits;
- if (n==1) {
- return [ pall[offset] ];
- } else if (n==2) {
- return [
- PF.F.add(pall[offset], pall[offset + step]),
- PF.F.sub(pall[offset], pall[offset + step])];
+ lor(a, b) {
+ return (a || b) ? this.one : this.zero;
}
- const ndiv2 = n >> 1;
- const p1 = __fft(PF, pall, bits-1, offset, step*2);
- const p2 = __fft(PF, pall, bits-1, offset+step, step*2);
-
- const out = new Array(n);
-
- for (let i=0; i> this.one);
+ if ( res != this.one ) return null;
- const ndiv2 = n >> 1;
- const p1 = __fft2(PF, pall.slice(0, ndiv2), bits-1);
- const p2 = __fft2(PF, pall.slice(ndiv2), bits-1);
+ let m = this.s;
+ let c = this.nqr_to_t;
+ let t = this.pow(n, this.t);
+ let r = this.pow(n, this.add(this.t, this.one) >> this.one );
- const out = new Array(n);
+ while ( t != this.one ) {
+ let sq = this.square(t);
+ let i = 1;
+ while (sq != this.one ) {
+ i++;
+ sq = this.square(sq);
+ }
- for (let i=0; i (this.p >> this.one)) {
+ r = this.neg(r);
+ }
-function _revSlow$1(idx, bits) {
- let res =0;
- let a = idx;
- for (let i=0; i>=1;
+ return r;
}
- return res;
-}
-
-function rev(idx, bits) {
- return (
- _revTable$1[idx >>> 24] |
- (_revTable$1[(idx >>> 16) & 0xFF] << 8) |
- (_revTable$1[(idx >>> 8) & 0xFF] << 16) |
- (_revTable$1[idx & 0xFF] << 24)
- ) >>> (32-bits);
-}
-function __bitReverse(p, bits) {
- for (let k=0; kk) {
- const tmp= p[k];
- p[k] = p[r];
- p[r] = tmp;
+ normalize(a, b) {
+ a = BigInt(a,b);
+ if (a < 0) {
+ let na = -a;
+ if (na >= this.p) na = na % this.p;
+ return this.p - na;
+ } else {
+ return (a>= this.p) ? a%this.p : a;
}
}
-}
-
-/*
- Copyright 2018 0kims association.
-
- This file is part of snarkjs.
-
- snarkjs is a free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License as published by the
- Free Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- snarkjs is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- snarkjs. If not, see .
-*/
-
-
-function mulScalar(F, base, e) {
- let res;
-
- if (isZero(e)) return F.zero;
-
- const n = naf(e);
-
- if (n[n.length-1] == 1) {
- res = base;
- } else if (n[n.length-1] == -1) {
- res = F.neg(base);
- } else {
- throw new Error("invlaud NAF");
+ random() {
+ const nBytes = (this.bitLength*2 / 8);
+ let res =this.zero;
+ for (let i=0; i=0; i--) {
-
- res = F.double(res);
-
- if (n[i] == 1) {
- res = F.add(res, base);
- } else if (n[i] == -1) {
- res = F.sub(res, base);
+ toString(a, base) {
+ let vs;
+ if (a > this.half) {
+ const v = this.p-a;
+ vs = "-"+v.toString(base);
+ } else {
+ vs = a.toString(base);
}
+ return vs;
}
- return res;
-}
+ isZero(a) {
+ return a == this.zero;
+ }
-
-/*
-exports.mulScalar = (F, base, e) =>{
- let res = F.zero;
- let rem = bigInt(e);
- let exp = base;
-
- while (! rem.eq(bigInt.zero)) {
- if (rem.and(bigInt.one).eq(bigInt.one)) {
- res = F.add(res, exp);
- }
- exp = F.double(exp);
- rem = rem.shiftRight(1);
+ fromRng(rng) {
+ let v;
+ do {
+ v=this.zero;
+ for (let i=0; i= this.p);
+ v = (v * this.Ri) % this.p; // Convert from montgomery
+ return v;
}
- return res;
-};
-*/
+}
+class ZqField {
+ constructor(p) {
+ this.type="F1";
+ this.one = bigInt__default['default'].one;
+ this.zero = bigInt__default['default'].zero;
+ this.p = bigInt__default['default'](p);
+ this.m = 1;
+ this.negone = this.p.minus(bigInt__default['default'].one);
+ this.two = bigInt__default['default'](2);
+ this.half = this.p.shiftRight(1);
+ this.bitLength = this.p.bitLength();
+ this.mask = bigInt__default['default'].one.shiftLeft(this.bitLength).minus(bigInt__default['default'].one);
-function exp(F, base, e) {
+ this.n64 = Math.floor((this.bitLength - 1) / 64)+1;
+ this.n32 = this.n64*2;
+ this.n8 = this.n64*8;
+ this.R = bigInt__default['default'].one.shiftLeft(this.n64*64);
+ this.Ri = this.inv(this.R);
- if (isZero(e)) return F.one;
+ const e = this.negone.shiftRight(this.one);
+ this.nqr = this.two;
+ let r = this.pow(this.nqr, e);
+ while (!r.equals(this.negone)) {
+ this.nqr = this.nqr.add(this.one);
+ r = this.pow(this.nqr, e);
+ }
- const n = bits(e);
+ this.s = this.zero;
+ this.t = this.negone;
- if (n.legth==0) return F.one;
+ while (!this.t.isOdd()) {
+ this.s = this.s.add(this.one);
+ this.t = this.t.shiftRight(this.one);
+ }
- let res = base;
+ this.nqr_to_t = this.pow(this.nqr, this.t);
- for (let i=n.length-2; i>=0; i--) {
+ buildSqrt(this);
+ }
- res = F.square(res);
+ e(a,b) {
- if (n[i]) {
- res = F.mul(res, base);
- }
- }
+ const res = bigInt__default['default'](a,b);
- return res;
-}
+ return this.normalize(res);
-// Check here: https://eprint.iacr.org/2012/685.pdf
+ }
-function buildSqrt (F) {
- if ((F.m % 2) == 1) {
- if (eq(mod(F.p, 4), 1 )) {
- if (eq(mod(F.p, 8), 1 )) {
- if (eq(mod(F.p, 16), 1 )) {
- // alg7_muller(F);
- alg5_tonelliShanks(F);
- } else if (eq(mod(F.p, 16), 9 )) {
- alg4_kong(F);
- } else {
- throw new Error("Field withot sqrt");
- }
- } else if (eq(mod(F.p, 8), 5 )) {
- alg3_atkin(F);
- } else {
- throw new Error("Field withot sqrt");
- }
- } else if (eq(mod(F.p, 4), 3 )) {
- alg2_shanks(F);
+ add(a, b) {
+ let res = a.add(b);
+ if (res.geq(this.p)) {
+ res = res.minus(this.p);
}
- } else {
- const pm2mod4 = mod(pow(F.p, F.m/2), 4);
- if (pm2mod4 == 1) {
- alg10_adj(F);
- } else if (pm2mod4 == 3) {
- alg9_adj(F);
+ return res;
+ }
+
+ sub(a, b) {
+ if (a.geq(b)) {
+ return a.minus(b);
} else {
- alg8_complex(F);
+ return this.p.minus(b.minus(a));
}
-
}
-}
+ neg(a) {
+ if (a.isZero()) return a;
+ return this.p.minus(a);
+ }
-function alg5_tonelliShanks(F) {
- F.sqrt_q = pow(F.p, F.m);
+ mul(a, b) {
+ return a.times(b).mod(this.p);
+ }
- F.sqrt_s = 0;
- F.sqrt_t = sub(F.sqrt_q, 1);
+ mulScalar(base, s) {
+ return base.times(bigInt__default['default'](s)).mod(this.p);
+ }
- while (!isOdd(F.sqrt_t)) {
- F.sqrt_s = F.sqrt_s + 1;
- F.sqrt_t = div(F.sqrt_t, 2);
+ square(a) {
+ return a.square().mod(this.p);
}
- let c0 = F.one;
+ eq(a, b) {
+ return a.eq(b);
+ }
- while (F.eq(c0, F.one)) {
- const c = F.random();
- F.sqrt_z = F.pow(c, F.sqrt_t);
- c0 = F.pow(F.sqrt_z, 2 ** (F.sqrt_s-1) );
+ neq(a, b) {
+ return a.neq(b);
}
- F.sqrt_tm1d2 = div(sub(F.sqrt_t, 1),2);
+ lt(a, b) {
+ const aa = a.gt(this.half) ? a.minus(this.p) : a;
+ const bb = b.gt(this.half) ? b.minus(this.p) : b;
+ return aa.lt(bb);
+ }
- F.sqrt = function(a) {
- const F=this;
- if (F.isZero(a)) return F.zero;
- let w = F.pow(a, F.sqrt_tm1d2);
- const a0 = F.pow( F.mul(F.square(w), a), 2 ** (F.sqrt_s-1) );
- if (F.eq(a0, F.negone)) return null;
+ gt(a, b) {
+ const aa = a.gt(this.half) ? a.minus(this.p) : a;
+ const bb = b.gt(this.half) ? b.minus(this.p) : b;
+ return aa.gt(bb);
+ }
- let v = F.sqrt_s;
- let x = F.mul(a, w);
- let b = F.mul(x, w);
- let z = F.sqrt_z;
- while (!F.eq(b, F.one)) {
- let b2k = F.square(b);
- let k=1;
- while (!F.eq(b2k, F.one)) {
- b2k = F.square(b2k);
- k++;
- }
+ leq(a, b) {
+ const aa = a.gt(this.half) ? a.minus(this.p) : a;
+ const bb = b.gt(this.half) ? b.minus(this.p) : b;
+ return aa.leq(bb);
+ }
- w = z;
- for (let i=0; i>> 0;
- st[d] = (st[d] ^ st[a]) >>> 0;
- st[d] = ((st[d] << 16) | ((st[d]>>>16) & 0xFFFF)) >>> 0;
+ sqrt_old(n) {
- st[c] = (st[c] + st[d]) >>> 0;
- st[b] = (st[b] ^ st[c]) >>> 0;
- st[b] = ((st[b] << 12) | ((st[b]>>>20) & 0xFFF)) >>> 0;
+ if (n.equals(this.zero)) return this.zero;
- st[a] = (st[a] + st[b]) >>> 0;
- st[d] = (st[d] ^ st[a]) >>> 0;
- st[d] = ((st[d] << 8) | ((st[d]>>>24) & 0xFF)) >>> 0;
+ // Test that have solution
+ const res = this.pow(n, this.negone.shiftRight(this.one));
+ if (!res.equals(this.one)) return null;
- st[c] = (st[c] + st[d]) >>> 0;
- st[b] = (st[b] ^ st[c]) >>> 0;
- st[b] = ((st[b] << 7) | ((st[b]>>>25) & 0x7F)) >>> 0;
-}
+ let m = parseInt(this.s);
+ let c = this.nqr_to_t;
+ let t = this.pow(n, this.t);
+ let r = this.pow(n, this.add(this.t, this.one).shiftRight(this.one) );
-function doubleRound(st) {
- quarterRound(st, 0, 4, 8,12);
- quarterRound(st, 1, 5, 9,13);
- quarterRound(st, 2, 6,10,14);
- quarterRound(st, 3, 7,11,15);
+ while (!t.equals(this.one)) {
+ let sq = this.square(t);
+ let i = 1;
+ while (!sq.equals(this.one)) {
+ i++;
+ sq = this.square(sq);
+ }
- quarterRound(st, 0, 5,10,15);
- quarterRound(st, 1, 6,11,12);
- quarterRound(st, 2, 7, 8,13);
- quarterRound(st, 3, 4, 9,14);
-}
+ // b = c ^ m-i-1
+ let b = c;
+ for (let j=0; j< m-i-1; j ++) b = this.square(b);
-class ChaCha {
-
- constructor(seed) {
- seed = seed || [0,0,0,0,0,0,0,0];
- this.state = [
- 0x61707865,
- 0x3320646E,
- 0x79622D32,
- 0x6B206574,
- seed[0],
- seed[1],
- seed[2],
- seed[3],
- seed[4],
- seed[5],
- seed[6],
- seed[7],
- 0,
- 0,
- 0,
- 0
- ];
- this.idx = 16;
- this.buff = new Array(16);
- }
+ m = i;
+ c = this.square(b);
+ t = this.mul(t, c);
+ r = this.mul(r, b);
+ }
- nextU32() {
- if (this.idx == 16) this.update();
- return this.buff[this.idx++];
- }
+ if (r.greater(this.p.shiftRight(this.one))) {
+ r = this.neg(r);
+ }
- nextU64() {
- return add(mul(this.nextU32(), 0x100000000), this.nextU32());
+ return r;
}
- nextBool() {
- return (this.nextU32() & 1) == 1;
+ normalize(a) {
+ a = bigInt__default['default'](a);
+ if (a.isNegative()) {
+ return this.p.minus(a.abs().mod(this.p));
+ } else {
+ return a.mod(this.p);
+ }
}
- update() {
- // Copy the state
- for (let i=0; i<16; i++) this.buff[i] = this.state[i];
-
- // Apply the rounds
- for (let i=0; i<10; i++) doubleRound(this.buff);
-
- // Add to the initial
- for (let i=0; i<16; i++) this.buff[i] = (this.buff[i] + this.state[i]) >>> 0;
-
- this.idx = 0;
-
- this.state[12] = (this.state[12] + 1) >>> 0;
- if (this.state[12] != 0) return;
- this.state[13] = (this.state[13] + 1) >>> 0;
- if (this.state[13] != 0) return;
- this.state[14] = (this.state[14] + 1) >>> 0;
- if (this.state[14] != 0) return;
- this.state[15] = (this.state[15] + 1) >>> 0;
+ random() {
+ let res = bigInt__default['default'](0);
+ let n = bigInt__default['default'](this.p.square());
+ while (!n.isZero()) {
+ res = res.shiftLeft(8).add(bigInt__default['default'](getRandomBytes(1)[0]));
+ n = n.shiftRight(8);
+ }
+ return res.mod(this.p);
}
-}
-
-/* global window */
-function getRandomBytes(n) {
- let array = new Uint8Array(n);
- if (typeof window !== "undefined") { // Browser
- if (typeof window.crypto !== "undefined") { // Supported
- window.crypto.getRandomValues(array);
- } else { // fallback
- for (let i=0; i>>0;
- }
+ toString(a, base) {
+ let vs;
+ if (!a.lesserOrEquals(this.p.shiftRight(bigInt__default['default'](1)))) {
+ const v = this.p.minus(a);
+ vs = "-"+v.toString(base);
+ } else {
+ vs = a.toString(base);
}
+
+ return vs;
}
- else { // NodeJS
- crypto__default['default'].randomFillSync(array);
+
+ isZero(a) {
+ return a.isZero();
}
- return array;
-}
-function getRandomSeed() {
- const arr = getRandomBytes(32);
- const arrV = new Uint32Array(arr.buffer);
- const seed = [];
- for (let i=0; i<8; i++) {
- seed.push(arrV[i]);
+ fromRng(rng) {
+ let v;
+ do {
+ v = bigInt__default['default'](0);
+ for (let i=0; i> this.one;
- this.bitLength = bitLength(this.p);
- this.mask = (this.one << BigInt(this.bitLength)) - this.one;
-
- this.n64 = Math.floor((this.bitLength - 1) / 64)+1;
- this.n32 = this.n64*2;
- this.n8 = this.n64*8;
- this.R = this.e(this.one << BigInt(this.n64*64));
- this.Ri = this.inv(this.R);
-
- const e = this.negone >> this.one;
- this.nqr = this.two;
- let r = this.pow(this.nqr, e);
- while (!this.eq(r, this.negone)) {
- this.nqr = this.nqr + this.one;
- r = this.pow(this.nqr, e);
- }
-
-
- this.s = 0;
- this.t = this.negone;
-
- while ((this.t & this.one) == this.zero) {
- this.s = this.s + 1;
- this.t = this.t >> this.one;
- }
+const supportsNativeBigInt$1 = typeof BigInt === "function";
+let _F1Field;
+if (supportsNativeBigInt$1) {
+ _F1Field = ZqField$1;
+} else {
+ _F1Field = ZqField;
+}
- this.nqr_to_t = this.pow(this.nqr, this.t);
+class F1Field extends _F1Field {
- buildSqrt(this);
+ // Returns a buffer with Little Endian Representation
+ toRprLE(buff, o, e) {
+ toRprLE(buff, o, e, this.n64*8);
}
- e(a,b) {
- let res;
- if (!b) {
- res = BigInt(a);
- } else if (b==16) {
- res = BigInt("0x"+a);
- }
- if (res < 0) {
- let nres = -res;
- if (nres >= this.p) nres = nres % this.p;
- return this.p - nres;
- } else {
- return (res>= this.p) ? res%this.p : res;
- }
-
+ // Returns a buffer with Big Endian Representation
+ toRprBE(buff, o, e) {
+ toRprBE(buff, o, e, this.n64*8);
}
- add(a, b) {
- const res = a + b;
- return res >= this.p ? res-this.p : res;
+ // Returns a buffer with Big Endian Montgomery Representation
+ toRprBEM(buff, o, e) {
+ return this.toRprBE(buff, o, this.mul(this.R, e));
}
- sub(a, b) {
- return (a >= b) ? a-b : this.p-b+a;
+ toRprLEM(buff, o, e) {
+ return this.toRprLE(buff, o, this.mul(this.R, e));
}
- neg(a) {
- return a ? this.p-a : a;
- }
- mul(a, b) {
- return (a*b)%this.p;
+ // Pases a buffer with Little Endian Representation
+ fromRprLE(buff, o) {
+ return fromRprLE(buff, o, this.n8);
}
- mulScalar(base, s) {
- return (base * this.e(s)) % this.p;
+ // Pases a buffer with Big Endian Representation
+ fromRprBE(buff, o) {
+ return fromRprBE(buff, o, this.n8);
}
- square(a) {
- return (a*a) % this.p;
+ fromRprLEM(buff, o) {
+ return this.mul(this.fromRprLE(buff, o), this.Ri);
}
- eq(a, b) {
- return a==b;
+ fromRprBEM(buff, o) {
+ return this.mul(this.fromRprBE(buff, o), this.Ri);
}
- neq(a, b) {
- return a!=b;
- }
+}
- lt(a, b) {
- const aa = (a > this.half) ? a - this.p : a;
- const bb = (b > this.half) ? b - this.p : b;
- return aa < bb;
- }
-
- gt(a, b) {
- const aa = (a > this.half) ? a - this.p : a;
- const bb = (b > this.half) ? b - this.p : b;
- return aa > bb;
- }
-
- leq(a, b) {
- const aa = (a > this.half) ? a - this.p : a;
- const bb = (b > this.half) ? b - this.p : b;
- return aa <= bb;
- }
-
- geq(a, b) {
- const aa = (a > this.half) ? a - this.p : a;
- const bb = (b > this.half) ? b - this.p : b;
- return aa >= bb;
- }
-
- div(a, b) {
- return this.mul(a, this.inv(b));
- }
-
- idiv(a, b) {
- if (!b) throw new Error("Division by zero");
- return a / b;
- }
-
- inv(a) {
- if (!a) throw new Error("Division by zero");
-
- let t = this.zero;
- let r = this.p;
- let newt = this.one;
- let newr = a % this.p;
- while (newr) {
- let q = r/newr;
- [t, newt] = [newt, t-q*newt];
- [r, newr] = [newr, r-q*newr];
- }
- if (t<0n) t += this.p;
- return t;
- }
-
- mod(a, b) {
- return a % b;
- }
-
- pow(b, e) {
- return exp(this, b, e);
- }
-
- exp(b, e) {
- return exp(this, b, e);
- }
-
- band(a, b) {
- const res = ((a & b) & this.mask);
- return res >= this.p ? res-this.p : res;
- }
-
- bor(a, b) {
- const res = ((a | b) & this.mask);
- return res >= this.p ? res-this.p : res;
- }
-
- bxor(a, b) {
- const res = ((a ^ b) & this.mask);
- return res >= this.p ? res-this.p : res;
- }
-
- bnot(a) {
- const res = a ^ this.mask;
- return res >= this.p ? res-this.p : res;
- }
-
- shl(a, b) {
- if (Number(b) < this.bitLength) {
- const res = (a << b) & this.mask;
- return res >= this.p ? res-this.p : res;
- } else {
- const nb = this.p - b;
- if (Number(nb) < this.bitLength) {
- return a >> nb;
- } else {
- return this.zero;
- }
- }
- }
-
- shr(a, b) {
- if (Number(b) < this.bitLength) {
- return a >> b;
- } else {
- const nb = this.p - b;
- if (Number(nb) < this.bitLength) {
- const res = (a << nb) & this.mask;
- return res >= this.p ? res-this.p : res;
- } else {
- return 0;
- }
- }
- }
-
- land(a, b) {
- return (a && b) ? this.one : this.zero;
- }
-
- lor(a, b) {
- return (a || b) ? this.one : this.zero;
- }
-
- lnot(a) {
- return (a) ? this.zero : this.one;
- }
-
- sqrt_old(n) {
-
- if (n == this.zero) return this.zero;
-
- // Test that have solution
- const res = this.pow(n, this.negone >> this.one);
- if ( res != this.one ) return null;
-
- let m = this.s;
- let c = this.nqr_to_t;
- let t = this.pow(n, this.t);
- let r = this.pow(n, this.add(this.t, this.one) >> this.one );
-
- while ( t != this.one ) {
- let sq = this.square(t);
- let i = 1;
- while (sq != this.one ) {
- i++;
- sq = this.square(sq);
- }
-
- // b = c ^ m-i-1
- let b = c;
- for (let j=0; j< m-i-1; j ++) b = this.square(b);
-
- m = i;
- c = this.square(b);
- t = this.mul(t, c);
- r = this.mul(r, b);
- }
-
- if (r > (this.p >> this.one)) {
- r = this.neg(r);
- }
-
- return r;
- }
-
- normalize(a, b) {
- a = BigInt(a,b);
- if (a < 0) {
- let na = -a;
- if (na >= this.p) na = na % this.p;
- return this.p - na;
- } else {
- return (a>= this.p) ? a%this.p : a;
- }
- }
-
- random() {
- const nBytes = (this.bitLength*2 / 8);
- let res =this.zero;
- for (let i=0; i this.half) {
- const v = this.p-a;
- vs = "-"+v.toString(base);
- } else {
- vs = a.toString(base);
- }
- return vs;
- }
-
- isZero(a) {
- return a == this.zero;
- }
-
- fromRng(rng) {
- let v;
- do {
- v=this.zero;
- for (let i=0; i= this.p);
- v = (v * this.Ri) % this.p; // Convert from montgomery
- return v;
- }
-
-}
-
-class ZqField {
- constructor(p) {
- this.type="F1";
- this.one = bigInt__default['default'].one;
- this.zero = bigInt__default['default'].zero;
- this.p = bigInt__default['default'](p);
- this.m = 1;
- this.negone = this.p.minus(bigInt__default['default'].one);
- this.two = bigInt__default['default'](2);
- this.half = this.p.shiftRight(1);
- this.bitLength = this.p.bitLength();
- this.mask = bigInt__default['default'].one.shiftLeft(this.bitLength).minus(bigInt__default['default'].one);
-
- this.n64 = Math.floor((this.bitLength - 1) / 64)+1;
- this.n32 = this.n64*2;
- this.n8 = this.n64*8;
- this.R = bigInt__default['default'].one.shiftLeft(this.n64*64);
- this.Ri = this.inv(this.R);
-
- const e = this.negone.shiftRight(this.one);
- this.nqr = this.two;
- let r = this.pow(this.nqr, e);
- while (!r.equals(this.negone)) {
- this.nqr = this.nqr.add(this.one);
- r = this.pow(this.nqr, e);
- }
-
- this.s = this.zero;
- this.t = this.negone;
-
- while (!this.t.isOdd()) {
- this.s = this.s.add(this.one);
- this.t = this.t.shiftRight(this.one);
- }
-
- this.nqr_to_t = this.pow(this.nqr, this.t);
-
- buildSqrt(this);
- }
-
- e(a,b) {
-
- const res = bigInt__default['default'](a,b);
-
- return this.normalize(res);
-
- }
-
- add(a, b) {
- let res = a.add(b);
- if (res.geq(this.p)) {
- res = res.minus(this.p);
- }
- return res;
- }
-
- sub(a, b) {
- if (a.geq(b)) {
- return a.minus(b);
- } else {
- return this.p.minus(b.minus(a));
- }
- }
-
- neg(a) {
- if (a.isZero()) return a;
- return this.p.minus(a);
- }
-
- mul(a, b) {
- return a.times(b).mod(this.p);
- }
-
- mulScalar(base, s) {
- return base.times(bigInt__default['default'](s)).mod(this.p);
- }
-
- square(a) {
- return a.square().mod(this.p);
- }
-
- eq(a, b) {
- return a.eq(b);
- }
-
- neq(a, b) {
- return a.neq(b);
- }
-
- lt(a, b) {
- const aa = a.gt(this.half) ? a.minus(this.p) : a;
- const bb = b.gt(this.half) ? b.minus(this.p) : b;
- return aa.lt(bb);
- }
-
- gt(a, b) {
- const aa = a.gt(this.half) ? a.minus(this.p) : a;
- const bb = b.gt(this.half) ? b.minus(this.p) : b;
- return aa.gt(bb);
- }
-
- leq(a, b) {
- const aa = a.gt(this.half) ? a.minus(this.p) : a;
- const bb = b.gt(this.half) ? b.minus(this.p) : b;
- return aa.leq(bb);
- }
-
- geq(a, b) {
- const aa = a.gt(this.half) ? a.minus(this.p) : a;
- const bb = b.gt(this.half) ? b.minus(this.p) : b;
- return aa.geq(bb);
- }
-
- div(a, b) {
- if (b.isZero()) throw new Error("Division by zero");
- return a.times(b.modInv(this.p)).mod(this.p);
- }
-
- idiv(a, b) {
- if (b.isZero()) throw new Error("Division by zero");
- return a.divide(b);
- }
-
- inv(a) {
- if (a.isZero()) throw new Error("Division by zero");
- return a.modInv(this.p);
- }
-
- mod(a, b) {
- return a.mod(b);
- }
-
- pow(a, b) {
- return a.modPow(b, this.p);
- }
-
- exp(a, b) {
- return a.modPow(b, this.p);
- }
-
- band(a, b) {
- return a.and(b).and(this.mask).mod(this.p);
- }
-
- bor(a, b) {
- return a.or(b).and(this.mask).mod(this.p);
- }
-
- bxor(a, b) {
- return a.xor(b).and(this.mask).mod(this.p);
- }
-
- bnot(a) {
- return a.xor(this.mask).mod(this.p);
- }
-
- shl(a, b) {
- if (b.lt(this.bitLength)) {
- return a.shiftLeft(b).and(this.mask).mod(this.p);
- } else {
- const nb = this.p.minus(b);
- if (nb.lt(this.bitLength)) {
- return this.shr(a, nb);
- } else {
- return bigInt__default['default'].zero;
- }
- }
- }
-
- shr(a, b) {
- if (b.lt(this.bitLength)) {
- return a.shiftRight(b);
- } else {
- const nb = this.p.minus(b);
- if (nb.lt(this.bitLength)) {
- return this.shl(a, nb);
- } else {
- return bigInt__default['default'].zero;
- }
- }
- }
-
- land(a, b) {
- return (a.isZero() || b.isZero()) ? bigInt__default['default'].zero : bigInt__default['default'].one;
- }
-
- lor(a, b) {
- return (a.isZero() && b.isZero()) ? bigInt__default['default'].zero : bigInt__default['default'].one;
- }
-
- lnot(a) {
- return a.isZero() ? bigInt__default['default'].one : bigInt__default['default'].zero;
- }
-
- sqrt_old(n) {
-
- if (n.equals(this.zero)) return this.zero;
-
- // Test that have solution
- const res = this.pow(n, this.negone.shiftRight(this.one));
- if (!res.equals(this.one)) return null;
-
- let m = parseInt(this.s);
- let c = this.nqr_to_t;
- let t = this.pow(n, this.t);
- let r = this.pow(n, this.add(this.t, this.one).shiftRight(this.one) );
-
- while (!t.equals(this.one)) {
- let sq = this.square(t);
- let i = 1;
- while (!sq.equals(this.one)) {
- i++;
- sq = this.square(sq);
- }
-
- // b = c ^ m-i-1
- let b = c;
- for (let j=0; j< m-i-1; j ++) b = this.square(b);
-
- m = i;
- c = this.square(b);
- t = this.mul(t, c);
- r = this.mul(r, b);
- }
-
- if (r.greater(this.p.shiftRight(this.one))) {
- r = this.neg(r);
- }
-
- return r;
- }
-
- normalize(a) {
- a = bigInt__default['default'](a);
- if (a.isNegative()) {
- return this.p.minus(a.abs().mod(this.p));
- } else {
- return a.mod(this.p);
- }
- }
-
- random() {
- let res = bigInt__default['default'](0);
- let n = bigInt__default['default'](this.p.square());
- while (!n.isZero()) {
- res = res.shiftLeft(8).add(bigInt__default['default'](getRandomBytes(1)[0]));
- n = n.shiftRight(8);
- }
- return res.mod(this.p);
- }
-
- toString(a, base) {
- let vs;
- if (!a.lesserOrEquals(this.p.shiftRight(bigInt__default['default'](1)))) {
- const v = this.p.minus(a);
- vs = "-"+v.toString(base);
- } else {
- vs = a.toString(base);
- }
-
- return vs;
- }
-
- isZero(a) {
- return a.isZero();
- }
-
- fromRng(rng) {
- let v;
- do {
- v = bigInt__default['default'](0);
- for (let i=0; i.
-*/
-
-class F2Field {
- constructor(F, nonResidue) {
- this.type="F2";
- this.F = F;
- this.zero = [this.F.zero, this.F.zero];
- this.one = [this.F.one, this.F.zero];
- this.negone = this.neg(this.one);
- this.nonResidue = nonResidue;
- this.m = F.m*2;
- this.p = F.p;
- this.n64 = F.n64*2;
- this.n32 = this.n64*2;
- this.n8 = this.n64*8;
-
- buildSqrt(this);
- }
-
- _mulByNonResidue(a) {
- return this.F.mul(this.nonResidue, a);
- }
-
- copy(a) {
- return [this.F.copy(a[0]), this.F.copy(a[1])];
- }
-
- add(a, b) {
- return [
- this.F.add(a[0], b[0]),
- this.F.add(a[1], b[1])
- ];
- }
-
- double(a) {
- return this.add(a,a);
- }
-
- sub(a, b) {
- return [
- this.F.sub(a[0], b[0]),
- this.F.sub(a[1], b[1])
- ];
- }
-
- neg(a) {
- return this.sub(this.zero, a);
- }
-
- conjugate(a) {
- return [
- a[0],
- this.F.neg(a[1])
- ];
- }
-
- mul(a, b) {
- const aA = this.F.mul(a[0] , b[0]);
- const bB = this.F.mul(a[1] , b[1]);
-
- return [
- this.F.add( aA , this._mulByNonResidue(bB)),
- this.F.sub(
- this.F.mul(
- this.F.add(a[0], a[1]),
- this.F.add(b[0], b[1])),
- this.F.add(aA, bB))];
- }
-
- inv(a) {
- const t0 = this.F.square(a[0]);
- const t1 = this.F.square(a[1]);
- const t2 = this.F.sub(t0, this._mulByNonResidue(t1));
- const t3 = this.F.inv(t2);
- return [
- this.F.mul(a[0], t3),
- this.F.neg(this.F.mul( a[1], t3)) ];
- }
-
- div(a, b) {
- return this.mul(a, this.inv(b));
- }
-
- square(a) {
- const ab = this.F.mul(a[0] , a[1]);
-
- /*
- [
- (a + b) * (a + non_residue * b) - ab - non_residue * ab,
- ab + ab
- ];
- */
-
- return [
- this.F.sub(
- this.F.mul(
- this.F.add(a[0], a[1]) ,
- this.F.add(
- a[0] ,
- this._mulByNonResidue(a[1]))),
- this.F.add(
- ab,
- this._mulByNonResidue(ab))),
- this.F.add(ab, ab)
- ];
- }
-
- isZero(a) {
- return this.F.isZero(a[0]) && this.F.isZero(a[1]);
- }
-
- eq(a, b) {
- return this.F.eq(a[0], b[0]) && this.F.eq(a[1], b[1]);
- }
-
- mulScalar(base, e) {
- return mulScalar(this, base, e);
- }
-
- pow(base, e) {
- return exp(this, base, e);
- }
-
- exp(base, e) {
- return exp(this, base, e);
- }
-
- toString(a) {
- return `[ ${this.F.toString(a[0])} , ${this.F.toString(a[1])} ]`;
- }
-
- fromRng(rng) {
- const c0 = this.F.fromRng(rng);
- const c1 = this.F.fromRng(rng);
- return [c0, c1];
- }
-
- gt(a, b) {
- if (this.F.gt(a[0], b[0])) return true;
- if (this.F.gt(b[0], a[0])) return false;
- if (this.F.gt(a[1], b[1])) return true;
- return false;
- }
-
- geq(a, b) {
- return this.gt(a, b) || this.eq(a, b);
- }
-
- lt(a, b) {
- return !this.geq(a,b);
- }
-
- leq(a, b) {
- return !this.gt(a,b);
- }
-
- neq(a, b) {
- return !this.eq(a,b);
- }
-
- random() {
- return [this.F.random(), this.F.random()];
- }
-
-
- toRprLE(buff, o, e) {
- this.F.toRprLE(buff, o, e[0]);
- this.F.toRprLE(buff, o+this.F.n8, e[1]);
- }
-
- toRprBE(buff, o, e) {
- this.F.toRprBE(buff, o, e[1]);
- this.F.toRprBE(buff, o+this.F.n8, e[0]);
- }
-
- toRprLEM(buff, o, e) {
- this.F.toRprLEM(buff, o, e[0]);
- this.F.toRprLEM(buff, o+this.F.n8, e[1]);
- }
-
-
- toRprBEM(buff, o, e) {
- this.F.toRprBEM(buff, o, e[1]);
- this.F.toRprBEM(buff, o+this.F.n8, e[0]);
- }
-
- fromRprLE(buff, o) {
- o = o || 0;
- const c0 = this.F.fromRprLE(buff, o);
- const c1 = this.F.fromRprLE(buff, o+this.F.n8);
- return [c0, c1];
- }
-
- fromRprBE(buff, o) {
- o = o || 0;
- const c1 = this.F.fromRprBE(buff, o);
- const c0 = this.F.fromRprBE(buff, o+this.F.n8);
- return [c0, c1];
- }
-
- fromRprLEM(buff, o) {
- o = o || 0;
- const c0 = this.F.fromRprLEM(buff, o);
- const c1 = this.F.fromRprLEM(buff, o+this.F.n8);
- return [c0, c1];
- }
-
- fromRprBEM(buff, o) {
- o = o || 0;
- const c1 = this.F.fromRprBEM(buff, o);
- const c0 = this.F.fromRprBEM(buff, o+this.F.n8);
- return [c0, c1];
- }
-
-}
-
-/*
- Copyright 2018 0kims association.
-
- This file is part of snarkjs.
-
- snarkjs is a free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License as published by the
- Free Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- snarkjs is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- snarkjs. If not, see .
-*/
-
-class F3Field {
- constructor(F, nonResidue) {
- this.type="F3";
- this.F = F;
- this.zero = [this.F.zero, this.F.zero, this.F.zero];
- this.one = [this.F.one, this.F.zero, this.F.zero];
- this.negone = this.neg(this.one);
- this.nonResidue = nonResidue;
- this.m = F.m*3;
- this.p = F.p;
- this.n64 = F.n64*3;
- this.n32 = this.n64*2;
- this.n8 = this.n64*8;
- }
-
- _mulByNonResidue(a) {
- return this.F.mul(this.nonResidue, a);
- }
-
- copy(a) {
- return [this.F.copy(a[0]), this.F.copy(a[1]), this.F.copy(a[2])];
- }
-
- add(a, b) {
- return [
- this.F.add(a[0], b[0]),
- this.F.add(a[1], b[1]),
- this.F.add(a[2], b[2])
- ];
- }
-
- double(a) {
- return this.add(a,a);
- }
-
- sub(a, b) {
- return [
- this.F.sub(a[0], b[0]),
- this.F.sub(a[1], b[1]),
- this.F.sub(a[2], b[2])
- ];
- }
-
- neg(a) {
- return this.sub(this.zero, a);
- }
-
- mul(a, b) {
-
- const aA = this.F.mul(a[0] , b[0]);
- const bB = this.F.mul(a[1] , b[1]);
- const cC = this.F.mul(a[2] , b[2]);
-
- return [
- this.F.add(
- aA,
- this._mulByNonResidue(
- this.F.sub(
- this.F.mul(
- this.F.add(a[1], a[2]),
- this.F.add(b[1], b[2])),
- this.F.add(bB, cC)))), // aA + non_residue*((b+c)*(B+C)-bB-cC),
-
- this.F.add(
- this.F.sub(
- this.F.mul(
- this.F.add(a[0], a[1]),
- this.F.add(b[0], b[1])),
- this.F.add(aA, bB)),
- this._mulByNonResidue( cC)), // (a+b)*(A+B)-aA-bB+non_residue*cC
-
- this.F.add(
- this.F.sub(
- this.F.mul(
- this.F.add(a[0], a[2]),
- this.F.add(b[0], b[2])),
- this.F.add(aA, cC)),
- bB)]; // (a+c)*(A+C)-aA+bB-cC)
- }
-
- inv(a) {
- const t0 = this.F.square(a[0]); // t0 = a^2 ;
- const t1 = this.F.square(a[1]); // t1 = b^2 ;
- const t2 = this.F.square(a[2]); // t2 = c^2;
- const t3 = this.F.mul(a[0],a[1]); // t3 = ab
- const t4 = this.F.mul(a[0],a[2]); // t4 = ac
- const t5 = this.F.mul(a[1],a[2]); // t5 = bc;
- // c0 = t0 - non_residue * t5;
- const c0 = this.F.sub(t0, this._mulByNonResidue(t5));
- // c1 = non_residue * t2 - t3;
- const c1 = this.F.sub(this._mulByNonResidue(t2), t3);
- const c2 = this.F.sub(t1, t4); // c2 = t1-t4
-
- // t6 = (a * c0 + non_residue * (c * c1 + b * c2)).inv();
- const t6 =
- this.F.inv(
- this.F.add(
- this.F.mul(a[0], c0),
- this._mulByNonResidue(
- this.F.add(
- this.F.mul(a[2], c1),
- this.F.mul(a[1], c2)))));
-
- return [
- this.F.mul(t6, c0), // t6*c0
- this.F.mul(t6, c1), // t6*c1
- this.F.mul(t6, c2)]; // t6*c2
- }
-
- div(a, b) {
- return this.mul(a, this.inv(b));
- }
-
- square(a) {
- const s0 = this.F.square(a[0]); // s0 = a^2
- const ab = this.F.mul(a[0], a[1]); // ab = a*b
- const s1 = this.F.add(ab, ab); // s1 = 2ab;
- const s2 = this.F.square(
- this.F.add(this.F.sub(a[0],a[1]), a[2])); // s2 = (a - b + c)^2;
- const bc = this.F.mul(a[1],a[2]); // bc = b*c
- const s3 = this.F.add(bc, bc); // s3 = 2*bc
- const s4 = this.F.square(a[2]); // s4 = c^2
-
-
- return [
- this.F.add(
- s0,
- this._mulByNonResidue(s3)), // s0 + non_residue * s3,
- this.F.add(
- s1,
- this._mulByNonResidue(s4)), // s1 + non_residue * s4,
- this.F.sub(
- this.F.add( this.F.add(s1, s2) , s3 ),
- this.F.add(s0, s4))]; // s1 + s2 + s3 - s0 - s4
- }
-
- isZero(a) {
- return this.F.isZero(a[0]) && this.F.isZero(a[1]) && this.F.isZero(a[2]);
- }
-
- eq(a, b) {
- return this.F.eq(a[0], b[0]) && this.F.eq(a[1], b[1]) && this.F.eq(a[2], b[2]);
- }
-
- affine(a) {
- return [this.F.affine(a[0]), this.F.affine(a[1]), this.F.affine(a[2])];
- }
-
- mulScalar(base, e) {
- return mulScalar(this, base, e);
- }
-
- pow(base, e) {
- return exp(this, base, e);
- }
-
- exp(base, e) {
- return exp(this, base, e);
- }
-
- toString(a) {
- return `[ ${this.F.toString(a[0])} , ${this.F.toString(a[1])}, ${this.F.toString(a[2])} ]`;
- }
-
- fromRng(rng) {
- const c0 = this.F.fromRng(rng);
- const c1 = this.F.fromRng(rng);
- const c2 = this.F.fromRng(rng);
- return [c0, c1, c2];
- }
-
- gt(a, b) {
- if (this.F.gt(a[0], b[0])) return true;
- if (this.F.gt(b[0], a[0])) return false;
- if (this.F.gt(a[1], b[1])) return true;
- if (this.F.gt(b[1], a[1])) return false;
- if (this.F.gt(a[2], b[2])) return true;
- return false;
- }
-
-
- geq(a, b) {
- return this.gt(a, b) || this.eq(a, b);
- }
-
- lt(a, b) {
- return !this.geq(a,b);
- }
-
- leq(a, b) {
- return !this.gt(a,b);
- }
-
- neq(a, b) {
- return !this.eq(a,b);
- }
-
- random() {
- return [this.F.random(), this.F.random(), this.F.random()];
- }
-
-
- toRprLE(buff, o, e) {
- this.F.toRprLE(buff, o, e[0]);
- this.F.toRprLE(buff, o+this.F.n8, e[1]);
- this.F.toRprLE(buff, o+this.F.n8*2, e[2]);
- }
-
- toRprBE(buff, o, e) {
- this.F.toRprBE(buff, o, e[2]);
- this.F.toRprBE(buff, o+this.F.n8, e[1]);
- this.F.toRprBE(buff, o+this.F.n8*2, e[0]);
- }
-
- toRprLEM(buff, o, e) {
- this.F.toRprLEM(buff, o, e[0]);
- this.F.toRprLEM(buff, o+this.F.n8, e[1]);
- this.F.toRprLEM(buff, o+this.F.n8*2, e[2]);
- }
-
-
- toRprBEM(buff, o, e) {
- this.F.toRprBEM(buff, o, e[2]);
- this.F.toRprBEM(buff, o+this.F.n8, e[1]);
- this.F.toRprBEM(buff, o+this.F.n8*2, e[0]);
- }
-
- fromRprLE(buff, o) {
- o = o || 0;
- const c0 = this.F.fromRprLE(buff, o);
- const c1 = this.F.fromRprLE(buff, o+this.n8);
- const c2 = this.F.fromRprLE(buff, o+this.n8*2);
- return [c0, c1, c2];
- }
-
- fromRprBE(buff, o) {
- o = o || 0;
- const c2 = this.F.fromRprBE(buff, o);
- const c1 = this.F.fromRprBE(buff, o+this.n8);
- const c0 = this.F.fromRprBE(buff, o+this.n8*2);
- return [c0, c1, c2];
- }
-
- fromRprLEM(buff, o) {
- o = o || 0;
- const c0 = this.F.fromRprLEM(buff, o);
- const c1 = this.F.fromRprLEM(buff, o+this.n8);
- const c2 = this.F.fromRprLEM(buff, o+this.n8*2);
- return [c0, c1, c2];
- }
-
- fromRprBEM(buff, o) {
- o = o || 0;
- const c2 = this.F.fromRprBEM(buff, o);
- const c1 = this.F.fromRprBEM(buff, o+this.n8);
- const c0 = this.F.fromRprBEM(buff, o+this.n8*2);
- return [c0, c1, c2];
- }
-
-}
-
-/*
- Copyright 2018 0kims association.
-
- This file is part of snarkjs.
-
- snarkjs is a free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License as published by the
- Free Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- snarkjs is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- snarkjs. If not, see .
-*/
-
-
-function isGreatest(F, a) {
- if (Array.isArray(a)) {
- for (let i=a.length-1; i>=0; i--) {
- if (!F.F.isZero(a[i])) {
- return isGreatest(F.F, a[i]);
- }
- }
- return 0;
- } else {
- const na = F.neg(a);
- return gt(a, na);
- }
-}
-
-
-class EC {
-
- constructor(F, g) {
- this.F = F;
- this.g = g;
- if (this.g.length == 2) this.g[2] = this.F.one;
- this.zero = [this.F.zero, this.F.one, this.F.zero];
- }
-
- add(p1, p2) {
-
- const F = this.F;
-
- if (this.eq(p1, this.zero)) return p2;
- if (this.eq(p2, this.zero)) return p1;
-
- const res = new Array(3);
-
- const Z1Z1 = F.square( p1[2] );
- const Z2Z2 = F.square( p2[2] );
-
- const U1 = F.mul( p1[0] , Z2Z2 ); // U1 = X1 * Z2Z2
- const U2 = F.mul( p2[0] , Z1Z1 ); // U2 = X2 * Z1Z1
-
- const Z1_cubed = F.mul( p1[2] , Z1Z1);
- const Z2_cubed = F.mul( p2[2] , Z2Z2);
-
- const S1 = F.mul( p1[1] , Z2_cubed); // S1 = Y1 * Z2 * Z2Z2
- const S2 = F.mul( p2[1] , Z1_cubed); // S2 = Y2 * Z1 * Z1Z1
-
- if (F.eq(U1,U2) && F.eq(S1,S2)) {
- return this.double(p1);
- }
-
- const H = F.sub( U2 , U1 ); // H = U2-U1
-
- const S2_minus_S1 = F.sub( S2 , S1 );
-
- const I = F.square( F.add(H,H) ); // I = (2 * H)^2
- const J = F.mul( H , I ); // J = H * I
-
- const r = F.add( S2_minus_S1 , S2_minus_S1 ); // r = 2 * (S2-S1)
- const V = F.mul( U1 , I ); // V = U1 * I
-
- res[0] =
- F.sub(
- F.sub( F.square(r) , J ),
- F.add( V , V )); // X3 = r^2 - J - 2 * V
-
- const S1_J = F.mul( S1 , J );
-
- res[1] =
- F.sub(
- F.mul( r , F.sub(V,res[0])),
- F.add( S1_J,S1_J )); // Y3 = r * (V-X3)-2 S1 J
-
- res[2] =
- F.mul(
- H,
- F.sub(
- F.square( F.add(p1[2],p2[2]) ),
- F.add( Z1Z1 , Z2Z2 ))); // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H
-
- return res;
- }
-
- neg(p) {
- return [p[0], this.F.neg(p[1]), p[2]];
- }
-
- sub(a, b) {
- return this.add(a, this.neg(b));
- }
-
- double(p) {
- const F = this.F;
-
- const res = new Array(3);
-
- if (this.eq(p, this.zero)) return p;
-
- const A = F.square( p[0] ); // A = X1^2
- const B = F.square( p[1] ); // B = Y1^2
- const C = F.square( B ); // C = B^2
-
- let D =
- F.sub(
- F.square( F.add(p[0] , B )),
- F.add( A , C));
- D = F.add(D,D); // D = 2 * ((X1 + B)^2 - A - C)
-
- const E = F.add( F.add(A,A), A); // E = 3 * A
- const FF =F.square( E ); // F = E^2
-
- res[0] = F.sub( FF , F.add(D,D) ); // X3 = F - 2 D
-
- let eightC = F.add( C , C );
- eightC = F.add( eightC , eightC );
- eightC = F.add( eightC , eightC );
-
- res[1] =
- F.sub(
- F.mul(
- E,
- F.sub( D, res[0] )),
- eightC); // Y3 = E * (D - X3) - 8 * C
-
- const Y1Z1 = F.mul( p[1] , p[2] );
- res[2] = F.add( Y1Z1 , Y1Z1 ); // Z3 = 2 * Y1 * Z1
-
- return res;
- }
-
- timesScalar(base, e) {
- return mulScalar(this, base, e);
- }
-
- mulScalar(base, e) {
- return mulScalar(this, base, e);
- }
-
- affine(p) {
- const F = this.F;
- if (this.isZero(p)) {
- return this.zero;
- } else if (F.eq(p[2], F.one)) {
- return p;
- } else {
- const Z_inv = F.inv(p[2]);
- const Z2_inv = F.square(Z_inv);
- const Z3_inv = F.mul(Z2_inv, Z_inv);
-
- const res = new Array(3);
- res[0] = F.mul(p[0],Z2_inv);
- res[1] = F.mul(p[1],Z3_inv);
- res[2] = F.one;
-
- return res;
- }
- }
-
- multiAffine(arr) {
- const keys = Object.keys(arr);
- const F = this.F;
- const accMul = new Array(keys.length+1);
- accMul[0] = F.one;
- for (let i = 0; i< keys.length; i++) {
- if (F.eq(arr[keys[i]][2], F.zero)) {
- accMul[i+1] = accMul[i];
- } else {
- accMul[i+1] = F.mul(accMul[i], arr[keys[i]][2]);
- }
- }
-
- accMul[keys.length] = F.inv(accMul[keys.length]);
-
- for (let i = keys.length-1; i>=0; i--) {
- if (F.eq(arr[keys[i]][2], F.zero)) {
- accMul[i] = accMul[i+1];
- arr[keys[i]] = this.zero;
- } else {
- const Z_inv = F.mul(accMul[i], accMul[i+1]);
- accMul[i] = F.mul(arr[keys[i]][2], accMul[i+1]);
-
- const Z2_inv = F.square(Z_inv);
- const Z3_inv = F.mul(Z2_inv, Z_inv);
-
- arr[keys[i]][0] = F.mul(arr[keys[i]][0],Z2_inv);
- arr[keys[i]][1] = F.mul(arr[keys[i]][1],Z3_inv);
- arr[keys[i]][2] = F.one;
- }
- }
-
- }
-
- eq(p1, p2) {
- const F = this.F;
-
- if (this.F.eq(p1[2], this.F.zero)) return this.F.eq(p2[2], this.F.zero);
- if (this.F.eq(p2[2], this.F.zero)) return false;
-
- const Z1Z1 = F.square( p1[2] );
- const Z2Z2 = F.square( p2[2] );
-
- const U1 = F.mul( p1[0] , Z2Z2 );
- const U2 = F.mul( p2[0] , Z1Z1 );
-
- const Z1_cubed = F.mul( p1[2] , Z1Z1);
- const Z2_cubed = F.mul( p2[2] , Z2Z2);
-
- const S1 = F.mul( p1[1] , Z2_cubed);
- const S2 = F.mul( p2[1] , Z1_cubed);
-
- return (F.eq(U1,U2) && F.eq(S1,S2));
- }
-
- isZero(p) {
- return this.F.isZero(p[2]);
- }
-
- toString(p) {
- const cp = this.affine(p);
- return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])} ]`;
- }
-
- fromRng(rng) {
- const F = this.F;
- let P = [];
- let greatest;
- do {
- P[0] = F.fromRng(rng);
- greatest = rng.nextBool();
- const x3b = F.add(F.mul(F.square(P[0]), P[0]), this.b);
- P[1] = F.sqrt(x3b);
- } while ((P[1] == null)||(F.isZero[P]));
-
- const s = isGreatest(F, P[1]);
- if (greatest ^ s) P[1] = F.neg(P[1]);
- P[2] = F.one;
-
- if (this.cofactor) {
- P = this.mulScalar(P, this.cofactor);
- }
-
- P = this.affine(P);
-
- return P;
-
- }
-
- toRprLE(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprLE(buff, o, p[0]);
- this.F.toRprLE(buff, o+this.F.n8, p[1]);
- }
-
- toRprBE(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprBE(buff, o, p[0]);
- this.F.toRprBE(buff, o+this.F.n8, p[1]);
- }
-
- toRprLEM(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprLEM(buff, o, p[0]);
- this.F.toRprLEM(buff, o+this.F.n8, p[1]);
- }
-
- toRprLEJM(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprLEM(buff, o, p[0]);
- this.F.toRprLEM(buff, o+this.F.n8, p[1]);
- this.F.toRprLEM(buff, o+2*this.F.n8, p[2]);
- }
-
-
- toRprBEM(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprBEM(buff, o, p[0]);
- this.F.toRprBEM(buff, o+this.F.n8, p[1]);
- }
-
- fromRprLE(buff, o) {
- o = o || 0;
- const x = this.F.fromRprLE(buff, o);
- const y = this.F.fromRprLE(buff, o+this.F.n8);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, this.F.one];
- }
-
- fromRprBE(buff, o) {
- o = o || 0;
- const x = this.F.fromRprBE(buff, o);
- const y = this.F.fromRprBE(buff, o+this.F.n8);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, this.F.one];
- }
-
- fromRprLEM(buff, o) {
- o = o || 0;
- const x = this.F.fromRprLEM(buff, o);
- const y = this.F.fromRprLEM(buff, o+this.F.n8);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, this.F.one];
- }
-
- fromRprLEJM(buff, o) {
- o = o || 0;
- const x = this.F.fromRprLEM(buff, o);
- const y = this.F.fromRprLEM(buff, o+this.F.n8);
- const z = this.F.fromRprLEM(buff, o+this.F.n8*2);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, z];
- }
-
- fromRprBEM(buff, o) {
- o = o || 0;
- const x = this.F.fromRprBEM(buff, o);
- const y = this.F.fromRprBEM(buff, o+this.F.n8);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, this.F.one];
- }
-
- fromRprCompressed(buff, o) {
- const F = this.F;
- const v = new Uint8Array(buff.buffer, o, F.n8);
- if (v[0] & 0x40) return this.zero;
- const P = new Array(3);
-
- const greatest = ((v[0] & 0x80) != 0);
- v[0] = v[0] & 0x7F;
- P[0] = F.fromRprBE(buff, o);
- if (greatest) v[0] = v[0] | 0x80; // set back again the old value
-
- const x3b = F.add(F.mul(F.square(P[0]), P[0]), this.b);
- P[1] = F.sqrt(x3b);
-
- if (P[1] === null) {
- throw new Error("Invalid Point!");
- }
-
- const s = isGreatest(F, P[1]);
- if (greatest ^ s) P[1] = F.neg(P[1]);
- P[2] = F.one;
-
- return P;
- }
-
- toRprCompressed(buff, o, p) {
- p = this.affine(p);
- const v = new Uint8Array(buff.buffer, o, this.F.n8);
- if (this.isZero(p)) {
- v.fill(0);
- v[0] = 0x40;
- return;
- }
- this.F.toRprBE(buff, o, p[0]);
-
- if (isGreatest(this.F, p[1])) {
- v[0] = v[0] | 0x80;
- }
- }
-
-
- fromRprUncompressed(buff, o) {
- if (buff[0] & 0x40) return this.zero;
-
- return this.fromRprBE(buff, o);
- }
-
- toRprUncompressed(buff, o, p) {
- this.toRprBE(buff, o, p);
-
- if (this.isZero(p)) {
- buff[o] = buff[o] | 0x40;
- }
- }
-
-
-}
-
-/* global BigInt */
-
-function stringifyBigInts$2(o) {
- if ((typeof(o) == "bigint") || o.eq !== undefined) {
- return o.toString(10);
- } else if (o instanceof Uint8Array) {
- return fromRprLE(o, 0);
- } else if (Array.isArray(o)) {
- return o.map(stringifyBigInts$2);
- } else if (typeof o == "object") {
- const res = {};
- const keys = Object.keys(o);
- keys.forEach( (k) => {
- res[k] = stringifyBigInts$2(o[k]);
- });
- return res;
- } else {
- return o;
- }
-}
-
-function unstringifyBigInts$2(o) {
- if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
- return BigInt(o);
- } else if (Array.isArray(o)) {
- return o.map(unstringifyBigInts$2);
- } else if (typeof o == "object") {
- if (o===null) return null;
- const res = {};
- const keys = Object.keys(o);
- keys.forEach( (k) => {
- res[k] = unstringifyBigInts$2(o[k]);
- });
- return res;
- } else {
- return o;
- }
-}
-
-function beBuff2int$2(buff) {
- let res = 0n;
- let i = buff.length;
- let offset = 0;
- const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
- while (i>0) {
- if (i >= 4) {
- i -= 4;
- res += BigInt(buffV.getUint32(i)) << BigInt(offset*8);
- offset += 4;
- } else if (i >= 2) {
- i -= 2;
- res += BigInt(buffV.getUint16(i)) << BigInt(offset*8);
- offset += 2;
- } else {
- i -= 1;
- res += BigInt(buffV.getUint8(i)) << BigInt(offset*8);
- offset += 1;
- }
- }
- return res;
-}
-
-function beInt2Buff$2(n, len) {
- let r = n;
- const buff = new Uint8Array(len);
- const buffV = new DataView(buff.buffer);
- let o = len;
- while (o > 0) {
- if (o-4 >= 0) {
- o -= 4;
- buffV.setUint32(o, Number(r & 0xFFFFFFFFn));
- r = r >> 32n;
- } else if (o-2 >= 0) {
- o -= 2;
- buffV.setUint16(o, Number(r & 0xFFFFn));
- r = r >> 16n;
- } else {
- o -= 1;
- buffV.setUint8(o, Number(r & 0xFFn));
- r = r >> 8n;
- }
- }
- if (r) {
- throw new Error("Number does not fit in this length");
- }
- return buff;
-}
-
-
-function leBuff2int$2(buff) {
- let res = 0n;
- let i = 0;
- const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
- while (i> 32n;
- } else if (o+2 <= len) {
- buffV.setUint16(Number(o, r & 0xFFFFn), true );
- o += 2;
- r = r >> 16n;
- } else {
- buffV.setUint8(Number(o, r & 0xFFn), true );
- o += 1;
- r = r >> 8n;
- }
- }
- if (r) {
- throw new Error("Number does not fit in this length");
- }
- return buff;
-}
-
-var utils_native = /*#__PURE__*/Object.freeze({
- __proto__: null,
- stringifyBigInts: stringifyBigInts$2,
- unstringifyBigInts: unstringifyBigInts$2,
- beBuff2int: beBuff2int$2,
- beInt2Buff: beInt2Buff$2,
- leBuff2int: leBuff2int$2,
- leInt2Buff: leInt2Buff$2
-});
-
-function stringifyBigInts$1(o) {
- if ((typeof(o) == "bigint") || o.eq !== undefined) {
- return o.toString(10);
- } else if (Array.isArray(o)) {
- return o.map(stringifyBigInts$1);
- } else if (typeof o == "object") {
- const res = {};
- const keys = Object.keys(o);
- keys.forEach( (k) => {
- res[k] = stringifyBigInts$1(o[k]);
- });
- return res;
- } else {
- return o;
- }
-}
-
-function unstringifyBigInts$1(o) {
- if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
- return bigInt__default['default'](o);
- } else if (Array.isArray(o)) {
- return o.map(unstringifyBigInts$1);
- } else if (typeof o == "object") {
- const res = {};
- const keys = Object.keys(o);
- keys.forEach( (k) => {
- res[k] = unstringifyBigInts$1(o[k]);
- });
- return res;
- } else {
- return o;
- }
-}
-
-function beBuff2int$1(buff) {
- let res = bigInt__default['default'].zero;
- for (let i=0; i=0)) {
- let c = Number(r.and(bigInt__default['default']("255")));
- buff[o] = c;
- o--;
- r = r.shiftRight(8);
- }
- if (!r.eq(bigInt__default['default'].zero)) {
- throw new Error("Number does not fit in this length");
- }
- return buff;
-}
-
-
-function leBuff2int$1 (buff) {
- let res = bigInt__default['default'].zero;
- for (let i=0; i>=1;
- }
- return res;
-}
-
-utils$1.bitReverse = function bitReverse(idx, bits) {
- return (
- _revTable[idx >>> 24] |
- (_revTable[(idx >>> 16) & 0xFF] << 8) |
- (_revTable[(idx >>> 8) & 0xFF] << 16) |
- (_revTable[idx & 0xFF] << 24)
- ) >>> (32-bits);
-};
-
-
-utils$1.log2 = function log2( V )
-{
- return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
-};
-
-utils$1.buffReverseBits = function buffReverseBits(buff, eSize) {
- const n = buff.byteLength /eSize;
- const bits = utils$1.log2(n);
- if (n != (1 << bits)) {
- throw new Error("Invalid number of pointers");
- }
- for (let i=0; ir) {
- const tmp = buff.slice(i*eSize, (i+1)*eSize);
- buff.set( buff.slice(r*eSize, (r+1)*eSize), i*eSize);
- buff.set(tmp, r*eSize);
- }
- }
-};
-
-let {
- bitReverse,
- log2,
- buffReverseBits,
- stringifyBigInts,
- unstringifyBigInts,
- beBuff2int,
- beInt2Buff,
- leBuff2int,
- leInt2Buff,
-} = utils$1;
-
-var _utils = /*#__PURE__*/Object.freeze({
- __proto__: null,
- bitReverse: bitReverse,
- log2: log2,
- buffReverseBits: buffReverseBits,
- stringifyBigInts: stringifyBigInts,
- unstringifyBigInts: unstringifyBigInts,
- beBuff2int: beBuff2int,
- beInt2Buff: beInt2Buff,
- leBuff2int: leBuff2int,
- leInt2Buff: leInt2Buff
-});
-
-const PAGE_SIZE = 1<<30;
-
-class BigBuffer {
-
- constructor(size) {
- this.buffers = [];
- this.byteLength = size;
- for (let i=0; i0) {
- // bytes to copy from this page
- const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r;
- const srcView = new Uint8Array(this.buffers[p].buffer, this.buffers[p].byteOffset+o, l);
- if (l == len) return srcView.slice();
- if (!buff) {
- if (len <= PAGE_SIZE) {
- buff = new Uint8Array(len);
- } else {
- buff = new BigBuffer(len);
- }
- }
- buff.set(srcView, len-r);
- r = r-l;
- p ++;
- o = 0;
- }
-
- return buff;
- }
-
- set(buff, offset) {
- if (offset === undefined) offset = 0;
-
- const len = buff.byteLength;
-
- if (len==0) return;
-
- const firstPage = Math.floor(offset / PAGE_SIZE);
- const lastPage = Math.floor((offset+len-1) / PAGE_SIZE);
-
- if (firstPage == lastPage)
- return this.buffers[firstPage].set(buff, offset % PAGE_SIZE);
-
-
- let p = firstPage;
- let o = offset % PAGE_SIZE;
- let r = len;
- while (r>0) {
- const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r;
- const srcView = buff.slice( len -r, len -r+l);
- const dstView = new Uint8Array(this.buffers[p].buffer, this.buffers[p].byteOffset + o, l);
- dstView.set(srcView);
- r = r-l;
- p ++;
- o = 0;
- }
-
- }
-}
-
-function buildBatchConvert(tm, fnName, sIn, sOut) {
- return async function batchConvert(buffIn) {
- const nPoints = Math.floor(buffIn.byteLength / sIn);
- if ( nPoints * sIn !== buffIn.byteLength) {
- throw new Error("Invalid buffer size");
- }
- const pointsPerChunk = Math.floor(nPoints/tm.concurrency);
- const opPromises = [];
- for (let i=0; i=0; i--) {
- this.w[i] = this.square(this.w[i+1]);
- }
-
- if (!this.eq(this.w[0], this.one)) {
- throw new Error("Error calculating roots of unity");
- }
-
- this.batchToMontgomery = buildBatchConvert(tm, prefix + "_batchToMontgomery", this.n8, this.n8);
- this.batchFromMontgomery = buildBatchConvert(tm, prefix + "_batchFromMontgomery", this.n8, this.n8);
- }
-
-
- op2(opName, a, b) {
- this.tm.setBuff(this.pOp1, a);
- this.tm.setBuff(this.pOp2, b);
- this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2, this.pOp3);
- return this.tm.getBuff(this.pOp3, this.n8);
- }
-
- op2Bool(opName, a, b) {
- this.tm.setBuff(this.pOp1, a);
- this.tm.setBuff(this.pOp2, b);
- return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2);
- }
-
- op1(opName, a) {
- this.tm.setBuff(this.pOp1, a);
- this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
- return this.tm.getBuff(this.pOp3, this.n8);
- }
-
- op1Bool(opName, a) {
- this.tm.setBuff(this.pOp1, a);
- return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
- }
-
- add(a,b) {
- return this.op2("_add", a, b);
- }
-
-
- eq(a,b) {
- return this.op2Bool("_eq", a, b);
- }
-
- isZero(a) {
- return this.op1Bool("_isZero", a);
- }
-
- sub(a,b) {
- return this.op2("_sub", a, b);
- }
-
- neg(a) {
- return this.op1("_neg", a);
- }
-
- inv(a) {
- return this.op1("_inverse", a);
- }
-
- toMontgomery(a) {
- return this.op1("_toMontgomery", a);
- }
-
- fromMontgomery(a) {
- return this.op1("_fromMontgomery", a);
- }
-
- mul(a,b) {
- return this.op2("_mul", a, b);
- }
-
- div(a, b) {
- this.tm.setBuff(this.pOp1, a);
- this.tm.setBuff(this.pOp2, b);
- this.tm.instance.exports[this.prefix + "_inverse"](this.pOp2, this.pOp2);
- this.tm.instance.exports[this.prefix + "_mul"](this.pOp1, this.pOp2, this.pOp3);
- return this.tm.getBuff(this.pOp3, this.n8);
- }
-
- square(a) {
- return this.op1("_square", a);
- }
-
- isSquare(a) {
- return this.op1Bool("_isSquare", a);
- }
-
- sqrt(a) {
- return this.op1("_sqrt", a);
- }
-
- exp(a, b) {
- if (!(b instanceof Uint8Array)) {
- b = toLEBuff(e(b));
- }
- this.tm.setBuff(this.pOp1, a);
- this.tm.setBuff(this.pOp2, b);
- this.tm.instance.exports[this.prefix + "_exp"](this.pOp1, this.pOp2, b.byteLength, this.pOp3);
- return this.tm.getBuff(this.pOp3, this.n8);
- }
-
- isNegative(a) {
- return this.op1Bool("_isNegative", a);
- }
-
- e(a, b) {
- if (a instanceof Uint8Array) return a;
- let ra = e(a, b);
- if (isNegative(ra)) {
- ra = neg(ra);
- if (gt(ra, this.p)) {
- ra = mod(ra, this.p);
- }
- ra = sub(this.p, ra);
- } else {
- if (gt(ra, this.p)) {
- ra = mod(ra, this.p);
- }
- }
- const buff = leInt2Buff(ra, this.n8);
- return this.toMontgomery(buff);
- }
-
- toString(a, radix) {
- const an = this.fromMontgomery(a);
- const s = fromRprLE(an, 0);
- return toString(s, radix);
- }
-
- fromRng(rng) {
- let v;
- const buff = new Uint8Array(this.n8);
- do {
- v = zero;
- for (let i=0; i memory.buffer.byteLength) {
- const currentPages = memory.buffer.byteLength / 0x10000;
- let requiredPages = Math.floor((u32[0] + length) / 0x10000)+1;
- if (requiredPages>MAXMEM) requiredPages=MAXMEM;
- memory.grow(requiredPages-currentPages);
- }
- return res;
- }
-
- function allocBuffer(buffer) {
- const p = alloc(buffer.byteLength);
- setBuffer(p, buffer);
- return p;
- }
-
- function getBuffer(pointer, length) {
- const u8 = new Uint8Array(memory.buffer);
- return new Uint8Array(u8.buffer, u8.byteOffset + pointer, length);
- }
-
- function setBuffer(pointer, buffer) {
- const u8 = new Uint8Array(memory.buffer);
- u8.set(new Uint8Array(buffer), pointer);
- }
-
- function runTask(task) {
- if (task[0].cmd == "INIT") {
- return init(task[0]);
- }
- const ctx = {
- vars: [],
- out: []
- };
- const u32a = new Uint32Array(memory.buffer, 0, 1);
- const oldAlloc = u32a[0];
- for (let i=0; i.
-*/
-
-// const MEM_SIZE = 1000; // Memory size in 64K Pakes (512Mb)
-const MEM_SIZE = 25; // Memory size in 64K Pakes (1600Kb)
-
-class Deferred {
- constructor() {
- this.promise = new Promise((resolve, reject)=> {
- this.reject = reject;
- this.resolve = resolve;
- });
- }
-}
-
-function sleep(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
-}
-
-function base64ToArrayBuffer(base64) {
- if (process.browser) {
- var binary_string = window.atob(base64);
- var len = binary_string.length;
- var bytes = new Uint8Array(len);
- for (var i = 0; i < len; i++) {
- bytes[i] = binary_string.charCodeAt(i);
- }
- return bytes;
- } else {
- return new Uint8Array(Buffer.from(base64, "base64"));
- }
-}
-
-function stringToBase64(str) {
- if (process.browser) {
- return window.btoa(str);
- } else {
- return Buffer.from(str).toString("base64");
- }
-}
-
-const threadSource = stringToBase64("(" + thread.toString() + ")(self)");
-const workerSource = "data:application/javascript;base64," + threadSource;
-
-
-
-async function buildThreadManager(wasm, singleThread) {
- const tm = new ThreadManager();
-
- tm.memory = new WebAssembly.Memory({initial:MEM_SIZE});
- tm.u8 = new Uint8Array(tm.memory.buffer);
- tm.u32 = new Uint32Array(tm.memory.buffer);
-
- const wasmModule = await WebAssembly.compile(base64ToArrayBuffer(wasm.code));
-
- tm.instance = await WebAssembly.instantiate(wasmModule, {
- env: {
- "memory": tm.memory
- }
- });
-
- tm.singleThread = singleThread;
- tm.initalPFree = tm.u32[0]; // Save the Pointer to free space.
- tm.pq = wasm.pq;
- tm.pr = wasm.pr;
- tm.pG1gen = wasm.pG1gen;
- tm.pG1zero = wasm.pG1zero;
- tm.pG2gen = wasm.pG2gen;
- tm.pG2zero = wasm.pG2zero;
- tm.pOneT = wasm.pOneT;
-
- // tm.pTmp0 = tm.alloc(curve.G2.F.n8*3);
- // tm.pTmp1 = tm.alloc(curve.G2.F.n8*3);
-
-
- if (singleThread) {
- tm.code = base64ToArrayBuffer(wasm.code);
- tm.taskManager = thread();
- await tm.taskManager([{
- cmd: "INIT",
- init: MEM_SIZE,
- code: tm.code.slice()
- }]);
- tm.concurrency = 1;
- } else {
- tm.workers = [];
- tm.pendingDeferreds = [];
- tm.working = [];
-
- let concurrency;
-
- if ((typeof(navigator) === "object") && navigator.hardwareConcurrency) {
- concurrency = navigator.hardwareConcurrency;
- } else {
- concurrency = os__default['default'].cpus().length;
- }
- // Limit to 64 threads for memory reasons.
- if (concurrency>64) concurrency=64;
- tm.concurrency = concurrency;
-
- for (let i = 0; i 0); i++) {
- if (this.working[i] == false) {
- const work = this.actionQueue.shift();
- this.postAction(i, work.data, work.transfers, work.deferred);
- }
- }
- }
-
- queueAction(actionData, transfers) {
- const d = new Deferred();
-
- if (this.singleThread) {
- const res = this.taskManager(actionData);
- d.resolve(res);
- } else {
- this.actionQueue.push({
- data: actionData,
- transfers: transfers,
- deferred: d
- });
- this.processWorks();
- }
- return d.promise;
- }
-
- resetMemory() {
- this.u32[0] = this.initalPFree;
- }
-
- allocBuff(buff) {
- const pointer = this.alloc(buff.byteLength);
- this.setBuff(pointer, buff);
- return pointer;
- }
-
- getBuff(pointer, length) {
- return this.u8.slice(pointer, pointer+ length);
- }
-
- setBuff(pointer, buffer) {
- this.u8.set(new Uint8Array(buffer), pointer);
- }
-
- alloc(length) {
- while (this.u32[0] & 3) this.u32[0]++; // Return always aligned pointers
- const res = this.u32[0];
- this.u32[0] += length;
- return res;
- }
-
- async terminate() {
- for (let i=0; i=0; i--) {
- if (!G.isZero(res)) {
- for (let j=0; jMAX_CHUNK_SIZE) chunkSize = MAX_CHUNK_SIZE;
- if (chunkSize {
- if (logger) logger.debug(`Multiexp end: ${logText}: ${i}/${nPoints}`);
- return r;
- }));
- }
-
- const result = await Promise.all(opPromises);
-
- let res = G.zero;
- for (let i=result.length-1; i>=0; i--) {
- res = G.add(res, result[i]);
- }
+/* global BigInt */
+function stringifyBigInts$2(o) {
+ if ((typeof(o) == "bigint") || o.eq !== undefined) {
+ return o.toString(10);
+ } else if (o instanceof Uint8Array) {
+ return fromRprLE(o, 0);
+ } else if (Array.isArray(o)) {
+ return o.map(stringifyBigInts$2);
+ } else if (typeof o == "object") {
+ const res = {};
+ const keys = Object.keys(o);
+ keys.forEach( (k) => {
+ res[k] = stringifyBigInts$2(o[k]);
+ });
return res;
+ } else {
+ return o;
}
-
- G.multiExp = async function multiExpAffine(buffBases, buffScalars, logger, logText) {
- return await _multiExp(buffBases, buffScalars, "jacobian", logger, logText);
- };
- G.multiExpAffine = async function multiExpAffine(buffBases, buffScalars, logger, logText) {
- return await _multiExp(buffBases, buffScalars, "affine", logger, logText);
- };
}
-function buildFFT(curve, groupName) {
- const G = curve[groupName];
- const Fr = curve.Fr;
- const tm = G.tm;
- async function _fft(buff, inverse, inType, outType, logger, loggerTxt) {
-
- inType = inType || "affine";
- outType = outType || "affine";
- const MAX_BITS_THREAD = 14;
-
- let sIn, sMid, sOut, fnIn2Mid, fnMid2Out, fnFFTMix, fnFFTJoin, fnFFTFinal;
- if (groupName == "G1") {
- if (inType == "affine") {
- sIn = G.F.n8*2;
- fnIn2Mid = "g1m_batchToJacobian";
- } else {
- sIn = G.F.n8*3;
- }
- sMid = G.F.n8*3;
- if (inverse) {
- fnFFTFinal = "g1m_fftFinal";
- }
- fnFFTJoin = "g1m_fftJoin";
- fnFFTMix = "g1m_fftMix";
-
- if (outType == "affine") {
- sOut = G.F.n8*2;
- fnMid2Out = "g1m_batchToAffine";
- } else {
- sOut = G.F.n8*3;
- }
-
- } else if (groupName == "G2") {
- if (inType == "affine") {
- sIn = G.F.n8*2;
- fnIn2Mid = "g2m_batchToJacobian";
- } else {
- sIn = G.F.n8*3;
- }
- sMid = G.F.n8*3;
- if (inverse) {
- fnFFTFinal = "g2m_fftFinal";
- }
- fnFFTJoin = "g2m_fftJoin";
- fnFFTMix = "g2m_fftMix";
- if (outType == "affine") {
- sOut = G.F.n8*2;
- fnMid2Out = "g2m_batchToAffine";
- } else {
- sOut = G.F.n8*3;
- }
- } else if (groupName == "Fr") {
- sIn = G.n8;
- sMid = G.n8;
- sOut = G.n8;
- if (inverse) {
- fnFFTFinal = "frm_fftFinal";
- }
- fnFFTMix = "frm_fftMix";
- fnFFTJoin = "frm_fftJoin";
- }
-
-
- let returnArray = false;
- if (Array.isArray(buff)) {
- buff = curve.array2buffer(buff, sIn);
- returnArray = true;
- }
-
- const nPoints = buff.byteLength / sIn;
- const bits = log2(nPoints);
-
- if ((1 << bits) != nPoints) {
- throw new Error("fft must be multiple of 2" );
- }
-
- if (bits == Fr.s +1) {
- let buffOut;
-
- if (inverse) {
- buffOut = await _fftExtInv(buff, inType, outType, logger, loggerTxt);
- } else {
- buffOut = await _fftExt(buff, inType, outType, logger, loggerTxt);
- }
-
- if (returnArray) {
- return curve.buffer2array(buffOut, sOut);
- } else {
- return buffOut;
- }
- }
-
- let inv;
- if (inverse) {
- inv = Fr.inv(Fr.e(nPoints));
- }
-
- let buffOut;
-
- buffReverseBits(buff, sIn);
-
- let chunks;
- let pointsInChunk = Math.min(1 << MAX_BITS_THREAD, nPoints);
- let nChunks = nPoints / pointsInChunk;
-
- while ((nChunks < tm.concurrency)&&(pointsInChunk>=16)) {
- nChunks *= 2;
- pointsInChunk /= 2;
- }
-
- const l2Chunk = log2(pointsInChunk);
-
- const promises = [];
- for (let i = 0; i< nChunks; i++) {
- if (logger) logger.debug(`${loggerTxt}: fft ${bits} mix start: ${i}/${nChunks}`);
- const task = [];
- task.push({cmd: "ALLOC", var: 0, len: sMid*pointsInChunk});
- const buffChunk = buff.slice( (pointsInChunk * i)*sIn, (pointsInChunk * (i+1))*sIn);
- task.push({cmd: "SET", var: 0, buff: buffChunk});
- if (fnIn2Mid) {
- task.push({cmd: "CALL", fnName:fnIn2Mid, params: [{var:0}, {val: pointsInChunk}, {var: 0}]});
- }
- for (let j=1; j<=l2Chunk;j++) {
- task.push({cmd: "CALL", fnName:fnFFTMix, params: [{var:0}, {val: pointsInChunk}, {val: j}]});
- }
-
- if (l2Chunk==bits) {
- if (fnFFTFinal) {
- task.push({cmd: "ALLOCSET", var: 1, buff: inv});
- task.push({cmd: "CALL", fnName: fnFFTFinal, params:[
- {var: 0},
- {val: pointsInChunk},
- {var: 1},
- ]});
- }
- if (fnMid2Out) {
- task.push({cmd: "CALL", fnName:fnMid2Out, params: [{var:0}, {val: pointsInChunk}, {var: 0}]});
- }
- task.push({cmd: "GET", out: 0, var: 0, len: pointsInChunk*sOut});
- } else {
- task.push({cmd: "GET", out:0, var: 0, len: sMid*pointsInChunk});
- }
- promises.push(tm.queueAction(task).then( (r) => {
- if (logger) logger.debug(`${loggerTxt}: fft ${bits} mix end: ${i}/${nChunks}`);
- return r;
- }));
- }
-
- chunks = await Promise.all(promises);
- for (let i = 0; i< nChunks; i++) chunks[i] = chunks[i][0];
-
- for (let i = l2Chunk+1; i<=bits; i++) {
- if (logger) logger.debug(`${loggerTxt}: fft ${bits} join: ${i}/${bits}`);
- const nGroups = 1 << (bits - i);
- const nChunksPerGroup = nChunks / nGroups;
- const opPromises = [];
- for (let j=0; j {
- if (logger) logger.debug(`${loggerTxt}: fft ${bits} join ${i}/${bits} ${j+1}/${nGroups} ${k}/${nChunksPerGroup/2}`);
- return r;
- }));
- }
- }
-
- const res = await Promise.all(opPromises);
- for (let j=0; j0; i--) {
- buffOut.set(chunks[i], p);
- p += pointsInChunk*sOut;
- delete chunks[i]; // Liberate mem
- }
- buffOut.set(chunks[0].slice(0, (pointsInChunk-1)*sOut), p);
- delete chunks[0];
- } else {
- for (let i=0; i (1<<28)) {
- buffOut = new BigBuffer(res1[0].byteLength*2);
- } else {
- buffOut = new Uint8Array(res1[0].byteLength*2);
- }
-
- buffOut.set(res1[0]);
- buffOut.set(res1[1], res1[0].byteLength);
-
- return buffOut;
- }
-
- async function _fftExtInv(buff, inType, outType, logger, loggerTxt) {
- let b1, b2;
- b1 = buff.slice( 0 , buff.byteLength/2);
- b2 = buff.slice( buff.byteLength/2, buff.byteLength);
-
- const promises = [];
-
- promises.push( _fft(b1, true, inType, "jacobian", logger, loggerTxt));
- promises.push( _fft(b2, true, inType, "jacobian", logger, loggerTxt));
-
- [b1, b2] = await Promise.all(promises);
-
- const res1 = await _fftJoinExt(b1, b2, "fftJoinExtInv", Fr.one, Fr.shiftInv, "jacobian", outType, logger, loggerTxt);
-
- let buffOut;
- if (res1[0].byteLength > (1<<28)) {
- buffOut = new BigBuffer(res1[0].byteLength*2);
- } else {
- buffOut = new Uint8Array(res1[0].byteLength*2);
- }
-
- buffOut.set(res1[0]);
- buffOut.set(res1[1], res1[0].byteLength);
-
- return buffOut;
- }
-
-
- async function _fftJoinExt(buff1, buff2, fn, first, inc, inType, outType, logger, loggerTxt) {
- const MAX_CHUNK_SIZE = 1<<16;
- const MIN_CHUNK_SIZE = 1<<4;
-
- let fnName;
- let fnIn2Mid, fnMid2Out;
- let sOut, sIn, sMid;
-
- if (groupName == "G1") {
- if (inType == "affine") {
- sIn = G.F.n8*2;
- fnIn2Mid = "g1m_batchToJacobian";
- } else {
- sIn = G.F.n8*3;
- }
- sMid = G.F.n8*3;
- fnName = "g1m_"+fn;
- if (outType == "affine") {
- fnMid2Out = "g1m_batchToAffine";
- sOut = G.F.n8*2;
- } else {
- sOut = G.F.n8*3;
- }
- } else if (groupName == "G2") {
- if (inType == "affine") {
- sIn = G.F.n8*2;
- fnIn2Mid = "g2m_batchToJacobian";
- } else {
- sIn = G.F.n8*3;
- }
- fnName = "g2m_"+fn;
- sMid = G.F.n8*3;
- if (outType == "affine") {
- fnMid2Out = "g2m_batchToAffine";
- sOut = G.F.n8*2;
- } else {
- sOut = G.F.n8*3;
- }
- } else if (groupName == "Fr") {
- sIn = Fr.n8;
- sOut = Fr.n8;
- sMid = Fr.n8;
- fnName = "frm_" + fn;
- } else {
- throw new Error("Invalid group");
- }
-
- if (buff1.byteLength != buff2.byteLength) {
- throw new Error("Invalid buffer size");
- }
- const nPoints = Math.floor(buff1.byteLength / sIn);
- if (nPoints != 1 << log2(nPoints)) {
- throw new Error("Invalid number of points");
- }
-
- let chunkSize = Math.floor(nPoints /tm.concurrency);
- if (chunkSize < MIN_CHUNK_SIZE) chunkSize = MIN_CHUNK_SIZE;
- if (chunkSize > MAX_CHUNK_SIZE) chunkSize = MAX_CHUNK_SIZE;
-
- const opPromises = [];
-
- for (let i=0; i {
- if (logger) logger.debug(`${loggerTxt}: fftJoinExt End: ${i}/${nPoints}`);
- return r;
- })
- );
- }
-
- const result = await Promise.all(opPromises);
-
- let fullBuffOut1;
- let fullBuffOut2;
- if (nPoints * sOut > 1<<28) {
- fullBuffOut1 = new BigBuffer(nPoints*sOut);
- fullBuffOut2 = new BigBuffer(nPoints*sOut);
- } else {
- fullBuffOut1 = new Uint8Array(nPoints*sOut);
- fullBuffOut2 = new Uint8Array(nPoints*sOut);
- }
-
- let p =0;
- for (let i=0; i {
+ res[k] = unstringifyBigInts$2(o[k]);
+ });
+ return res;
+ } else {
+ return o;
}
+}
-
- G.fft = async function(buff, inType, outType, logger, loggerTxt) {
- return await _fft(buff, false, inType, outType, logger, loggerTxt);
- };
-
- G.ifft = async function(buff, inType, outType, logger, loggerTxt) {
- return await _fft(buff, true, inType, outType, logger, loggerTxt);
- };
-
- G.lagrangeEvaluations = async function (buff, inType, outType, logger, loggerTxt) {
- inType = inType || "affine";
- outType = outType || "affine";
-
- let sIn;
- if (groupName == "G1") {
- if (inType == "affine") {
- sIn = G.F.n8*2;
- } else {
- sIn = G.F.n8*3;
- }
- } else if (groupName == "G2") {
- if (inType == "affine") {
- sIn = G.F.n8*2;
- } else {
- sIn = G.F.n8*3;
- }
- } else if (groupName == "Fr") {
- sIn = Fr.n8;
- } else {
- throw new Error("Invalid group");
- }
-
- const nPoints = buff.byteLength /sIn;
- const bits = log2(nPoints);
-
- if ((2 ** bits)*sIn != buff.byteLength) {
- if (logger) logger.error("lagrangeEvaluations iinvalid input size");
- throw new Error("lagrangeEvaluations invalid Input size");
- }
-
- if (bits <= Fr.s) {
- return await G.ifft(buff, inType, outType, logger, loggerTxt);
- }
-
- if (bits > Fr.s+1) {
- if (logger) logger.error("lagrangeEvaluations input too big");
- throw new Error("lagrangeEvaluations input too big");
- }
-
- let t0 = buff.slice(0, buff.byteLength/2);
- let t1 = buff.slice(buff.byteLength/2, buff.byteLength);
-
-
- const shiftToSmallM = Fr.exp(Fr.shift, nPoints/2);
- const sConst = Fr.inv( Fr.sub(Fr.one, shiftToSmallM));
-
- [t0, t1] = await _fftJoinExt(t0, t1, "prepareLagrangeEvaluation", sConst, Fr.shiftInv, inType, "jacobian", logger, loggerTxt + " prep");
-
- const promises = [];
-
- promises.push( _fft(t0, true, "jacobian", outType, logger, loggerTxt + " t0"));
- promises.push( _fft(t1, true, "jacobian", outType, logger, loggerTxt + " t1"));
-
- [t0, t1] = await Promise.all(promises);
-
- let buffOut;
- if (t0.byteLength > (1<<28)) {
- buffOut = new BigBuffer(t0.byteLength*2);
- } else {
- buffOut = new Uint8Array(t0.byteLength*2);
- }
-
- buffOut.set(t0);
- buffOut.set(t1, t0.byteLength);
-
- return buffOut;
- };
-
- G.fftMix = async function fftMix(buff) {
- const sG = G.F.n8*3;
- let fnName, fnFFTJoin;
- if (groupName == "G1") {
- fnName = "g1m_fftMix";
- fnFFTJoin = "g1m_fftJoin";
- } else if (groupName == "G2") {
- fnName = "g2m_fftMix";
- fnFFTJoin = "g2m_fftJoin";
- } else if (groupName == "Fr") {
- fnName = "frm_fftMix";
- fnFFTJoin = "frm_fftJoin";
- } else {
- throw new Error("Invalid group");
- }
-
- const nPoints = Math.floor(buff.byteLength / sG);
- const power = log2(nPoints);
-
- let nChunks = 1 << log2(tm.concurrency);
-
- if (nPoints <= nChunks*2) nChunks = 1;
-
- const pointsPerChunk = nPoints / nChunks;
-
- const powerChunk = log2(pointsPerChunk);
-
- const opPromises = [];
- for (let i=0; i0) {
+ if (i >= 4) {
+ i -= 4;
+ res += BigInt(buffV.getUint32(i)) << BigInt(offset*8);
+ offset += 4;
+ } else if (i >= 2) {
+ i -= 2;
+ res += BigInt(buffV.getUint16(i)) << BigInt(offset*8);
+ offset += 2;
} else {
- throw new Error("Invalid group");
- }
-
- const nPoints = Math.floor(buff.byteLength / sG);
- if (nPoints != 1 << log2(nPoints)) {
- throw new Error("Invalid number of points");
+ i -= 1;
+ res += BigInt(buffV.getUint8(i)) << BigInt(offset*8);
+ offset += 1;
}
+ }
+ return res;
+}
- const pointsPerChunk = Math.floor(nPoints / tm.concurrency);
-
- const opPromises = [];
- for (let i=0; i 0) {
+ if (o-4 >= 0) {
+ o -= 4;
+ buffV.setUint32(o, Number(r & BigInt(0xFFFFFFFF)));
+ r = r >> BigInt(32);
+ } else if (o-2 >= 0) {
+ o -= 2;
+ buffV.setUint16(o, Number(r & BigInt(0xFFFF)));
+ r = r >> BigInt(16);
+ } else {
+ o -= 1;
+ buffV.setUint8(o, Number(r & BigInt(0xFF)));
+ r = r >> BigInt(8);
}
+ }
+ if (r) {
+ throw new Error("Number does not fit in this length");
+ }
+ return buff;
+}
- const result = await Promise.all(opPromises);
- let fullBuffOut;
- if (buff instanceof BigBuffer) {
- fullBuffOut = new BigBuffer(nPoints*sGout);
+function leBuff2int$2(buff) {
+ let res = BigInt(0);
+ let i = 0;
+ const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
+ while (i=0; i--) {
- fullBuffOut.set(result[i][0], p);
- p+=result[i][0].byteLength;
+ res += BigInt(buffV.getUint8(i, true)) << BigInt( i*8);
+ i += 1;
}
-
- return fullBuffOut;
- };
+ }
+ return res;
}
-async function buildEngine(params) {
-
- const tm = await buildThreadManager(params.wasm, params.singleThread);
-
-
- const curve = {};
-
- curve.q = e(params.wasm.q);
- curve.r = e(params.wasm.r);
- curve.name = params.name;
- curve.tm = tm;
- curve.prePSize = params.wasm.prePSize;
- curve.preQSize = params.wasm.preQSize;
- curve.Fr = new WasmField1(tm, "frm", params.n8r, params.r);
- curve.F1 = new WasmField1(tm, "f1m", params.n8q, params.q);
- curve.F2 = new WasmField2(tm, "f2m", curve.F1);
- curve.G1 = new WasmCurve(tm, "g1m", curve.F1, params.wasm.pG1gen, params.wasm.pG1b, params.cofactorG1);
- curve.G2 = new WasmCurve(tm, "g2m", curve.F2, params.wasm.pG2gen, params.wasm.pG2b, params.cofactorG2);
- curve.F6 = new WasmField3(tm, "f6m", curve.F2);
- curve.F12 = new WasmField2(tm, "ftm", curve.F6);
-
- curve.Gt = curve.F12;
-
- buildBatchApplyKey(curve, "G1");
- buildBatchApplyKey(curve, "G2");
- buildBatchApplyKey(curve, "Fr");
-
- buildMultiexp(curve, "G1");
- buildMultiexp(curve, "G2");
-
- buildFFT(curve, "G1");
- buildFFT(curve, "G2");
- buildFFT(curve, "Fr");
-
- buildPairing(curve);
-
- curve.array2buffer = function(arr, sG) {
- const buff = new Uint8Array(sG*arr.length);
-
- for (let i=0; i> BigInt(32);
+ } else if (o+2 <= len) {
+ buffV.setUint16(Number(o, r & BigInt(0xFFFF)), true );
+ o += 2;
+ r = r >> BigInt(16);
+ } else {
+ buffV.setUint8(Number(o, r & BigInt(0xFF)), true );
+ o += 1;
+ r = r >> BigInt(8);
}
+ }
+ if (r) {
+ throw new Error("Number does not fit in this length");
+ }
+ return buff;
+}
- return buff;
- };
-
- curve.buffer2array = function(buff , sG) {
- const n= buff.byteLength / sG;
- const arr = new Array(n);
- for (let i=0; i {
+ res[k] = stringifyBigInts$1(o[k]);
+ });
+ return res;
+ } else {
+ return o;
+ }
}
-global.curve_bn128 = null;
+function unstringifyBigInts$1(o) {
+ if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
+ return bigInt__default['default'](o);
+ } else if (Array.isArray(o)) {
+ return o.map(unstringifyBigInts$1);
+ } else if (typeof o == "object") {
+ const res = {};
+ const keys = Object.keys(o);
+ keys.forEach( (k) => {
+ res[k] = unstringifyBigInts$1(o[k]);
+ });
+ return res;
+ } else {
+ return o;
+ }
+}
-async function buildBn128(singleThread) {
+function beBuff2int$1(buff) {
+ let res = bigInt__default['default'].zero;
+ for (let i=0; i=0)) {
+ let c = Number(r.and(bigInt__default['default']("255")));
+ buff[o] = c;
+ o--;
+ r = r.shiftRight(8);
+ }
+ if (!r.eq(bigInt__default['default'].zero)) {
+ throw new Error("Number does not fit in this length");
+ }
+ return buff;
+}
- const curve = await buildEngine(params);
- curve.terminate = async function() {
- if (!params.singleThread) {
- global.curve_bn128 = null;
- await this.tm.terminate();
- }
- };
- if (!singleThread) {
- global.curve_bn128 = curve;
+function leBuff2int$1 (buff) {
+ let res = bigInt__default['default'].zero;
+ for (let i=0; i>=1;
}
- return curve;
+ return res;
}
-async function getCurveFromName(name, singleThread) {
- let curve;
- const normName = normalizeName(name);
- if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) {
- curve = await buildBn128(singleThread);
- } else if (["BLS12381"].indexOf(normName) >= 0) {
- curve = await buildBn128(singleThread);
- } else {
- throw new Error(`Curve not supported: ${name}`);
- }
- return curve;
+utils$1.bitReverse = function bitReverse(idx, bits) {
+ return (
+ _revTable[idx >>> 24] |
+ (_revTable[(idx >>> 16) & 0xFF] << 8) |
+ (_revTable[(idx >>> 8) & 0xFF] << 16) |
+ (_revTable[idx & 0xFF] << 24)
+ ) >>> (32-bits);
+};
+
+
+utils$1.log2 = function log2( V )
+{
+ return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
+};
- function normalizeName(n) {
- return n.toUpperCase().match(/[A-Za-z0-9]+/g).join("");
+utils$1.buffReverseBits = function buffReverseBits(buff, eSize) {
+ const n = buff.byteLength /eSize;
+ const bits = utils$1.log2(n);
+ if (n != (1 << bits)) {
+ throw new Error("Invalid number of pointers");
+ }
+ for (let i=0; ir) {
+ const tmp = buff.slice(i*eSize, (i+1)*eSize);
+ buff.set( buff.slice(r*eSize, (r+1)*eSize), i*eSize);
+ buff.set(tmp, r*eSize);
+ }
}
+};
-}
+let {
+ bitReverse,
+ log2,
+ buffReverseBits,
+ stringifyBigInts,
+ unstringifyBigInts,
+ beBuff2int,
+ beInt2Buff,
+ leBuff2int,
+ leInt2Buff,
+} = utils$1;
+
+var _utils = /*#__PURE__*/Object.freeze({
+ __proto__: null,
+ bitReverse: bitReverse,
+ log2: log2,
+ buffReverseBits: buffReverseBits,
+ stringifyBigInts: stringifyBigInts,
+ unstringifyBigInts: unstringifyBigInts,
+ beBuff2int: beBuff2int,
+ beInt2Buff: beInt2Buff,
+ leBuff2int: leBuff2int,
+ leInt2Buff: leInt2Buff
+});
-const Scalar=_Scalar;
+const Scalar = _Scalar;
const utils = _utils;
-exports.BigBuffer = BigBuffer;
-exports.ChaCha = ChaCha;
-exports.EC = EC;
-exports.F1Field = F1Field;
-exports.F2Field = F2Field;
-exports.F3Field = F3Field;
-exports.PolField = PolField;
exports.Scalar = Scalar;
exports.ZqField = F1Field;
-exports.buildBls12381 = buildBls12381;
-exports.buildBn128 = buildBn128;
-exports.getCurveFromName = getCurveFromName;
-exports.getCurveFromQ = getCurveFromQ;
-exports.getCurveFromR = getCurveFromR;
exports.utils = utils;
diff --git a/main.js b/main.js
index 1981557..3b24310 100644
--- a/main.js
+++ b/main.js
@@ -1,24 +1,7 @@
+import * as _Scalar from "./src/scalar.js";
+export const Scalar = _Scalar;
-import * as _Scalar from "./src/scalar.js";
-export const Scalar=_Scalar;
-
-export {default as PolField} from "./src/polfield.js";
-export {default as F1Field} from "./src/f1field.js";
-export {default as F2Field} from "./src/f2field.js";
-export {default as F3Field} from "./src/f3field.js";
-
-export {default as ZqField} from "./src/f1field.js";
-
-export {default as EC} from "./src/ec.js";
-
-export {default as buildBn128} from "./src/bn128.js";
-export {default as buildBls12381} from "./src/bls12381.js";
+export { default as ZqField } from "./src/f1field.js";
import * as _utils from "./src/utils.js";
export const utils = _utils;
-export {default as ChaCha} from "./src/chacha.js";
-
-export {default as BigBuffer} from "./src/bigbuffer.js";
-
-export {getCurveFromR, getCurveFromQ, getCurveFromName} from "./src/curves.js";
-
diff --git a/src/bigbuffer.js b/src/bigbuffer.js
deleted file mode 100644
index 91fb93b..0000000
--- a/src/bigbuffer.js
+++ /dev/null
@@ -1,82 +0,0 @@
-
-const PAGE_SIZE = 1<<30;
-
-export default class BigBuffer {
-
- constructor(size) {
- this.buffers = [];
- this.byteLength = size;
- for (let i=0; i0) {
- // bytes to copy from this page
- const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r;
- const srcView = new Uint8Array(this.buffers[p].buffer, this.buffers[p].byteOffset+o, l);
- if (l == len) return srcView.slice();
- if (!buff) {
- if (len <= PAGE_SIZE) {
- buff = new Uint8Array(len);
- } else {
- buff = new BigBuffer(len);
- }
- }
- buff.set(srcView, len-r);
- r = r-l;
- p ++;
- o = 0;
- }
-
- return buff;
- }
-
- set(buff, offset) {
- if (offset === undefined) offset = 0;
-
- const len = buff.byteLength;
-
- if (len==0) return;
-
- const firstPage = Math.floor(offset / PAGE_SIZE);
- const lastPage = Math.floor((offset+len-1) / PAGE_SIZE);
-
- if (firstPage == lastPage)
- return this.buffers[firstPage].set(buff, offset % PAGE_SIZE);
-
-
- let p = firstPage;
- let o = offset % PAGE_SIZE;
- let r = len;
- while (r>0) {
- const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r;
- const srcView = buff.slice( len -r, len -r+l);
- const dstView = new Uint8Array(this.buffers[p].buffer, this.buffers[p].byteOffset + o, l);
- dstView.set(srcView);
- r = r-l;
- p ++;
- o = 0;
- }
-
- }
-}
diff --git a/src/bls12381.js b/src/bls12381.js
deleted file mode 100644
index f7a8e27..0000000
--- a/src/bls12381.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import wasmcurves from "wasmcurves";
-import buildEngine from "./engine.js";
-import * as Scalar from "./scalar.js";
-
-global.curve_bls12381 = null;
-
-export default async function buildBls12381(singleThread) {
-
- if ((!singleThread)&&(global.curve_bls12381)) return global.curve_bls12381;
- const params = {
- name: "bls12381",
- wasm: wasmcurves.bls12381_wasm,
- q: Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16),
- r: Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16),
- n8q: 48,
- n8r: 32,
- cofactorG1: Scalar.e("0x396c8c005555e1568c00aaab0000aaab", 16),
- cofactorG2: Scalar.e("0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5", 16),
- singleThread: singleThread ? true : false
- };
-
- const curve = await buildEngine(params);
- curve.terminate = async function() {
- if (!params.singleThread) {
- global.curve_bls12381 = null;
- await this.tm.terminate();
- }
- };
-
- return curve;
-}
-
diff --git a/src/bn128.js b/src/bn128.js
deleted file mode 100644
index 90888bf..0000000
--- a/src/bn128.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import wasmcurves from "wasmcurves";
-import buildEngine from "./engine.js";
-import * as Scalar from "./scalar.js";
-
-global.curve_bn128 = null;
-
-export default async function buildBn128(singleThread) {
-
- if ((!singleThread)&&(global.curve_bn128)) return global.curve_bn128;
- const params = {
- name: "bn128",
- wasm: wasmcurves.bn128_wasm,
- q: Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583"),
- r: Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617"),
- n8q: 32,
- n8r: 32,
- cofactorG2: Scalar.e("30644e72e131a029b85045b68181585e06ceecda572a2489345f2299c0f9fa8d", 16),
- singleThread: singleThread ? true : false
- };
-
- const curve = await buildEngine(params);
- curve.terminate = async function() {
- if (!params.singleThread) {
- global.curve_bn128 = null;
- await this.tm.terminate();
- }
- };
-
- if (!singleThread) {
- global.curve_bn128 = curve;
- }
-
- return curve;
-}
-
diff --git a/src/curves.js b/src/curves.js
deleted file mode 100644
index 806d01f..0000000
--- a/src/curves.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import * as Scalar from "./scalar.js";
-import {default as buildBn128} from "./bn128.js";
-import {default as buildBls12381} from "./bn128.js";
-
-const bls12381r = Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16);
-const bn128r = Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617");
-
-const bls12381q = Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16);
-const bn128q = Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583");
-
-export async function getCurveFromR(r, singleThread) {
- let curve;
- if (Scalar.eq(r, bn128r)) {
- curve = await buildBn128(singleThread);
- } else if (Scalar.eq(r, bls12381r)) {
- curve = await buildBls12381(singleThread);
- } else {
- throw new Error(`Curve not supported: ${Scalar.toString(r)}`);
- }
- return curve;
-}
-
-export async function getCurveFromQ(q, singleThread) {
- let curve;
- if (Scalar.eq(q, bn128q)) {
- curve = await buildBn128(singleThread);
- } else if (Scalar.eq(q, bls12381q)) {
- curve = await buildBls12381(singleThread);
- } else {
- throw new Error(`Curve not supported: ${Scalar.toString(q)}`);
- }
- return curve;
-}
-
-export async function getCurveFromName(name, singleThread) {
- let curve;
- const normName = normalizeName(name);
- if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) {
- curve = await buildBn128(singleThread);
- } else if (["BLS12381"].indexOf(normName) >= 0) {
- curve = await buildBls12381(singleThread);
- } else {
- throw new Error(`Curve not supported: ${name}`);
- }
- return curve;
-
- function normalizeName(n) {
- return n.toUpperCase().match(/[A-Za-z0-9]+/g).join("");
- }
-
-}
diff --git a/src/ec.js b/src/ec.js
deleted file mode 100644
index 0559006..0000000
--- a/src/ec.js
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- Copyright 2018 0kims association.
-
- This file is part of snarkjs.
-
- snarkjs is a free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License as published by the
- Free Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- snarkjs is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- snarkjs. If not, see .
-*/
-
-
-
-import * as fUtils from "./futils.js";
-import * as Scalar from "./scalar.js";
-
-
-function isGreatest(F, a) {
- if (Array.isArray(a)) {
- for (let i=a.length-1; i>=0; i--) {
- if (!F.F.isZero(a[i])) {
- return isGreatest(F.F, a[i]);
- }
- }
- return 0;
- } else {
- const na = F.neg(a);
- return Scalar.gt(a, na);
- }
-}
-
-
-export default class EC {
-
- constructor(F, g) {
- this.F = F;
- this.g = g;
- if (this.g.length == 2) this.g[2] = this.F.one;
- this.zero = [this.F.zero, this.F.one, this.F.zero];
- }
-
- add(p1, p2) {
-
- const F = this.F;
-
- if (this.eq(p1, this.zero)) return p2;
- if (this.eq(p2, this.zero)) return p1;
-
- const res = new Array(3);
-
- const Z1Z1 = F.square( p1[2] );
- const Z2Z2 = F.square( p2[2] );
-
- const U1 = F.mul( p1[0] , Z2Z2 ); // U1 = X1 * Z2Z2
- const U2 = F.mul( p2[0] , Z1Z1 ); // U2 = X2 * Z1Z1
-
- const Z1_cubed = F.mul( p1[2] , Z1Z1);
- const Z2_cubed = F.mul( p2[2] , Z2Z2);
-
- const S1 = F.mul( p1[1] , Z2_cubed); // S1 = Y1 * Z2 * Z2Z2
- const S2 = F.mul( p2[1] , Z1_cubed); // S2 = Y2 * Z1 * Z1Z1
-
- if (F.eq(U1,U2) && F.eq(S1,S2)) {
- return this.double(p1);
- }
-
- const H = F.sub( U2 , U1 ); // H = U2-U1
-
- const S2_minus_S1 = F.sub( S2 , S1 );
-
- const I = F.square( F.add(H,H) ); // I = (2 * H)^2
- const J = F.mul( H , I ); // J = H * I
-
- const r = F.add( S2_minus_S1 , S2_minus_S1 ); // r = 2 * (S2-S1)
- const V = F.mul( U1 , I ); // V = U1 * I
-
- res[0] =
- F.sub(
- F.sub( F.square(r) , J ),
- F.add( V , V )); // X3 = r^2 - J - 2 * V
-
- const S1_J = F.mul( S1 , J );
-
- res[1] =
- F.sub(
- F.mul( r , F.sub(V,res[0])),
- F.add( S1_J,S1_J )); // Y3 = r * (V-X3)-2 S1 J
-
- res[2] =
- F.mul(
- H,
- F.sub(
- F.square( F.add(p1[2],p2[2]) ),
- F.add( Z1Z1 , Z2Z2 ))); // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H
-
- return res;
- }
-
- neg(p) {
- return [p[0], this.F.neg(p[1]), p[2]];
- }
-
- sub(a, b) {
- return this.add(a, this.neg(b));
- }
-
- double(p) {
- const F = this.F;
-
- const res = new Array(3);
-
- if (this.eq(p, this.zero)) return p;
-
- const A = F.square( p[0] ); // A = X1^2
- const B = F.square( p[1] ); // B = Y1^2
- const C = F.square( B ); // C = B^2
-
- let D =
- F.sub(
- F.square( F.add(p[0] , B )),
- F.add( A , C));
- D = F.add(D,D); // D = 2 * ((X1 + B)^2 - A - C)
-
- const E = F.add( F.add(A,A), A); // E = 3 * A
- const FF =F.square( E ); // F = E^2
-
- res[0] = F.sub( FF , F.add(D,D) ); // X3 = F - 2 D
-
- let eightC = F.add( C , C );
- eightC = F.add( eightC , eightC );
- eightC = F.add( eightC , eightC );
-
- res[1] =
- F.sub(
- F.mul(
- E,
- F.sub( D, res[0] )),
- eightC); // Y3 = E * (D - X3) - 8 * C
-
- const Y1Z1 = F.mul( p[1] , p[2] );
- res[2] = F.add( Y1Z1 , Y1Z1 ); // Z3 = 2 * Y1 * Z1
-
- return res;
- }
-
- timesScalar(base, e) {
- return fUtils.mulScalar(this, base, e);
- }
-
- mulScalar(base, e) {
- return fUtils.mulScalar(this, base, e);
- }
-
- affine(p) {
- const F = this.F;
- if (this.isZero(p)) {
- return this.zero;
- } else if (F.eq(p[2], F.one)) {
- return p;
- } else {
- const Z_inv = F.inv(p[2]);
- const Z2_inv = F.square(Z_inv);
- const Z3_inv = F.mul(Z2_inv, Z_inv);
-
- const res = new Array(3);
- res[0] = F.mul(p[0],Z2_inv);
- res[1] = F.mul(p[1],Z3_inv);
- res[2] = F.one;
-
- return res;
- }
- }
-
- multiAffine(arr) {
- const keys = Object.keys(arr);
- const F = this.F;
- const accMul = new Array(keys.length+1);
- accMul[0] = F.one;
- for (let i = 0; i< keys.length; i++) {
- if (F.eq(arr[keys[i]][2], F.zero)) {
- accMul[i+1] = accMul[i];
- } else {
- accMul[i+1] = F.mul(accMul[i], arr[keys[i]][2]);
- }
- }
-
- accMul[keys.length] = F.inv(accMul[keys.length]);
-
- for (let i = keys.length-1; i>=0; i--) {
- if (F.eq(arr[keys[i]][2], F.zero)) {
- accMul[i] = accMul[i+1];
- arr[keys[i]] = this.zero;
- } else {
- const Z_inv = F.mul(accMul[i], accMul[i+1]);
- accMul[i] = F.mul(arr[keys[i]][2], accMul[i+1]);
-
- const Z2_inv = F.square(Z_inv);
- const Z3_inv = F.mul(Z2_inv, Z_inv);
-
- arr[keys[i]][0] = F.mul(arr[keys[i]][0],Z2_inv);
- arr[keys[i]][1] = F.mul(arr[keys[i]][1],Z3_inv);
- arr[keys[i]][2] = F.one;
- }
- }
-
- }
-
- eq(p1, p2) {
- const F = this.F;
-
- if (this.F.eq(p1[2], this.F.zero)) return this.F.eq(p2[2], this.F.zero);
- if (this.F.eq(p2[2], this.F.zero)) return false;
-
- const Z1Z1 = F.square( p1[2] );
- const Z2Z2 = F.square( p2[2] );
-
- const U1 = F.mul( p1[0] , Z2Z2 );
- const U2 = F.mul( p2[0] , Z1Z1 );
-
- const Z1_cubed = F.mul( p1[2] , Z1Z1);
- const Z2_cubed = F.mul( p2[2] , Z2Z2);
-
- const S1 = F.mul( p1[1] , Z2_cubed);
- const S2 = F.mul( p2[1] , Z1_cubed);
-
- return (F.eq(U1,U2) && F.eq(S1,S2));
- }
-
- isZero(p) {
- return this.F.isZero(p[2]);
- }
-
- toString(p) {
- const cp = this.affine(p);
- return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])} ]`;
- }
-
- fromRng(rng) {
- const F = this.F;
- let P = [];
- let greatest;
- do {
- P[0] = F.fromRng(rng);
- greatest = rng.nextBool();
- const x3b = F.add(F.mul(F.square(P[0]), P[0]), this.b);
- P[1] = F.sqrt(x3b);
- } while ((P[1] == null)||(F.isZero[P]));
-
- const s = isGreatest(F, P[1]);
- if (greatest ^ s) P[1] = F.neg(P[1]);
- P[2] = F.one;
-
- if (this.cofactor) {
- P = this.mulScalar(P, this.cofactor);
- }
-
- P = this.affine(P);
-
- return P;
-
- }
-
- toRprLE(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprLE(buff, o, p[0]);
- this.F.toRprLE(buff, o+this.F.n8, p[1]);
- }
-
- toRprBE(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprBE(buff, o, p[0]);
- this.F.toRprBE(buff, o+this.F.n8, p[1]);
- }
-
- toRprLEM(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprLEM(buff, o, p[0]);
- this.F.toRprLEM(buff, o+this.F.n8, p[1]);
- }
-
- toRprLEJM(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprLEM(buff, o, p[0]);
- this.F.toRprLEM(buff, o+this.F.n8, p[1]);
- this.F.toRprLEM(buff, o+2*this.F.n8, p[2]);
- }
-
-
- toRprBEM(buff, o, p) {
- p = this.affine(p);
- if (this.isZero(p)) {
- const BuffV = new Uint8Array(buff, o, this.F.n8*2);
- BuffV.fill(0);
- return;
- }
- this.F.toRprBEM(buff, o, p[0]);
- this.F.toRprBEM(buff, o+this.F.n8, p[1]);
- }
-
- fromRprLE(buff, o) {
- o = o || 0;
- const x = this.F.fromRprLE(buff, o);
- const y = this.F.fromRprLE(buff, o+this.F.n8);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, this.F.one];
- }
-
- fromRprBE(buff, o) {
- o = o || 0;
- const x = this.F.fromRprBE(buff, o);
- const y = this.F.fromRprBE(buff, o+this.F.n8);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, this.F.one];
- }
-
- fromRprLEM(buff, o) {
- o = o || 0;
- const x = this.F.fromRprLEM(buff, o);
- const y = this.F.fromRprLEM(buff, o+this.F.n8);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, this.F.one];
- }
-
- fromRprLEJM(buff, o) {
- o = o || 0;
- const x = this.F.fromRprLEM(buff, o);
- const y = this.F.fromRprLEM(buff, o+this.F.n8);
- const z = this.F.fromRprLEM(buff, o+this.F.n8*2);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, z];
- }
-
- fromRprBEM(buff, o) {
- o = o || 0;
- const x = this.F.fromRprBEM(buff, o);
- const y = this.F.fromRprBEM(buff, o+this.F.n8);
- if (this.F.isZero(x) && this.F.isZero(y)) {
- return this.zero;
- }
- return [x, y, this.F.one];
- }
-
- fromRprCompressed(buff, o) {
- const F = this.F;
- const v = new Uint8Array(buff.buffer, o, F.n8);
- if (v[0] & 0x40) return this.zero;
- const P = new Array(3);
-
- const greatest = ((v[0] & 0x80) != 0);
- v[0] = v[0] & 0x7F;
- P[0] = F.fromRprBE(buff, o);
- if (greatest) v[0] = v[0] | 0x80; // set back again the old value
-
- const x3b = F.add(F.mul(F.square(P[0]), P[0]), this.b);
- P[1] = F.sqrt(x3b);
-
- if (P[1] === null) {
- throw new Error("Invalid Point!");
- }
-
- const s = isGreatest(F, P[1]);
- if (greatest ^ s) P[1] = F.neg(P[1]);
- P[2] = F.one;
-
- return P;
- }
-
- toRprCompressed(buff, o, p) {
- p = this.affine(p);
- const v = new Uint8Array(buff.buffer, o, this.F.n8);
- if (this.isZero(p)) {
- v.fill(0);
- v[0] = 0x40;
- return;
- }
- this.F.toRprBE(buff, o, p[0]);
-
- if (isGreatest(this.F, p[1])) {
- v[0] = v[0] | 0x80;
- }
- }
-
-
- fromRprUncompressed(buff, o) {
- if (buff[0] & 0x40) return this.zero;
-
- return this.fromRprBE(buff, o);
- }
-
- toRprUncompressed(buff, o, p) {
- this.toRprBE(buff, o, p);
-
- if (this.isZero(p)) {
- buff[o] = buff[o] | 0x40;
- }
- }
-
-
-}
-
-
diff --git a/src/engine.js b/src/engine.js
deleted file mode 100644
index 1f8a25c..0000000
--- a/src/engine.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import WasmField1 from "./wasm_field1.js";
-import WasmField2 from "./wasm_field2.js";
-import WasmField3 from "./wasm_field3.js";
-import WasmCurve from "./wasm_curve.js";
-import buildThreadManager from "./threadman.js";
-import * as Scalar from "./scalar.js";
-import buildBatchApplyKey from "./engine_applykey.js";
-import buildPairing from "./engine_pairing.js";
-import buildMultiExp from "./engine_multiexp.js";
-import buildFFT from "./engine_fft.js";
-
-export default async function buildEngine(params) {
-
- const tm = await buildThreadManager(params.wasm, params.singleThread);
-
-
- const curve = {};
-
- curve.q = Scalar.e(params.wasm.q);
- curve.r = Scalar.e(params.wasm.r);
- curve.name = params.name;
- curve.tm = tm;
- curve.prePSize = params.wasm.prePSize;
- curve.preQSize = params.wasm.preQSize;
- curve.Fr = new WasmField1(tm, "frm", params.n8r, params.r);
- curve.F1 = new WasmField1(tm, "f1m", params.n8q, params.q);
- curve.F2 = new WasmField2(tm, "f2m", curve.F1);
- curve.G1 = new WasmCurve(tm, "g1m", curve.F1, params.wasm.pG1gen, params.wasm.pG1b, params.cofactorG1);
- curve.G2 = new WasmCurve(tm, "g2m", curve.F2, params.wasm.pG2gen, params.wasm.pG2b, params.cofactorG2);
- curve.F6 = new WasmField3(tm, "f6m", curve.F2);
- curve.F12 = new WasmField2(tm, "ftm", curve.F6);
-
- curve.Gt = curve.F12;
-
- buildBatchApplyKey(curve, "G1");
- buildBatchApplyKey(curve, "G2");
- buildBatchApplyKey(curve, "Fr");
-
- buildMultiExp(curve, "G1");
- buildMultiExp(curve, "G2");
-
- buildFFT(curve, "G1");
- buildFFT(curve, "G2");
- buildFFT(curve, "Fr");
-
- buildPairing(curve);
-
- curve.array2buffer = function(arr, sG) {
- const buff = new Uint8Array(sG*arr.length);
-
- for (let i=0; i=16)) {
- nChunks *= 2;
- pointsInChunk /= 2;
- }
-
- const l2Chunk = log2(pointsInChunk);
-
- const promises = [];
- for (let i = 0; i< nChunks; i++) {
- if (logger) logger.debug(`${loggerTxt}: fft ${bits} mix start: ${i}/${nChunks}`);
- const task = [];
- task.push({cmd: "ALLOC", var: 0, len: sMid*pointsInChunk});
- const buffChunk = buff.slice( (pointsInChunk * i)*sIn, (pointsInChunk * (i+1))*sIn);
- task.push({cmd: "SET", var: 0, buff: buffChunk});
- if (fnIn2Mid) {
- task.push({cmd: "CALL", fnName:fnIn2Mid, params: [{var:0}, {val: pointsInChunk}, {var: 0}]});
- }
- for (let j=1; j<=l2Chunk;j++) {
- task.push({cmd: "CALL", fnName:fnFFTMix, params: [{var:0}, {val: pointsInChunk}, {val: j}]});
- }
-
- if (l2Chunk==bits) {
- if (fnFFTFinal) {
- task.push({cmd: "ALLOCSET", var: 1, buff: inv});
- task.push({cmd: "CALL", fnName: fnFFTFinal, params:[
- {var: 0},
- {val: pointsInChunk},
- {var: 1},
- ]});
- }
- if (fnMid2Out) {
- task.push({cmd: "CALL", fnName:fnMid2Out, params: [{var:0}, {val: pointsInChunk}, {var: 0}]});
- }
- task.push({cmd: "GET", out: 0, var: 0, len: pointsInChunk*sOut});
- } else {
- task.push({cmd: "GET", out:0, var: 0, len: sMid*pointsInChunk});
- }
- promises.push(tm.queueAction(task).then( (r) => {
- if (logger) logger.debug(`${loggerTxt}: fft ${bits} mix end: ${i}/${nChunks}`);
- return r;
- }));
- }
-
- chunks = await Promise.all(promises);
- for (let i = 0; i< nChunks; i++) chunks[i] = chunks[i][0];
-
- for (let i = l2Chunk+1; i<=bits; i++) {
- if (logger) logger.debug(`${loggerTxt}: fft ${bits} join: ${i}/${bits}`);
- const nGroups = 1 << (bits - i);
- const nChunksPerGroup = nChunks / nGroups;
- const opPromises = [];
- for (let j=0; j {
- if (logger) logger.debug(`${loggerTxt}: fft ${bits} join ${i}/${bits} ${j+1}/${nGroups} ${k}/${nChunksPerGroup/2}`);
- return r;
- }));
- }
- }
-
- const res = await Promise.all(opPromises);
- for (let j=0; j0; i--) {
- buffOut.set(chunks[i], p);
- p += pointsInChunk*sOut;
- delete chunks[i]; // Liberate mem
- }
- buffOut.set(chunks[0].slice(0, (pointsInChunk-1)*sOut), p);
- delete chunks[0];
- } else {
- for (let i=0; i (1<<28)) {
- buffOut = new BigBuffer(res1[0].byteLength*2);
- } else {
- buffOut = new Uint8Array(res1[0].byteLength*2);
- }
-
- buffOut.set(res1[0]);
- buffOut.set(res1[1], res1[0].byteLength);
-
- return buffOut;
- }
-
- async function _fftExtInv(buff, inType, outType, logger, loggerTxt) {
- let b1, b2;
- b1 = buff.slice( 0 , buff.byteLength/2);
- b2 = buff.slice( buff.byteLength/2, buff.byteLength);
-
- const promises = [];
-
- promises.push( _fft(b1, true, inType, "jacobian", logger, loggerTxt));
- promises.push( _fft(b2, true, inType, "jacobian", logger, loggerTxt));
-
- [b1, b2] = await Promise.all(promises);
-
- const res1 = await _fftJoinExt(b1, b2, "fftJoinExtInv", Fr.one, Fr.shiftInv, "jacobian", outType, logger, loggerTxt);
-
- let buffOut;
- if (res1[0].byteLength > (1<<28)) {
- buffOut = new BigBuffer(res1[0].byteLength*2);
- } else {
- buffOut = new Uint8Array(res1[0].byteLength*2);
- }
-
- buffOut.set(res1[0]);
- buffOut.set(res1[1], res1[0].byteLength);
-
- return buffOut;
- }
-
-
- async function _fftJoinExt(buff1, buff2, fn, first, inc, inType, outType, logger, loggerTxt) {
- const MAX_CHUNK_SIZE = 1<<16;
- const MIN_CHUNK_SIZE = 1<<4;
-
- let fnName;
- let fnIn2Mid, fnMid2Out;
- let sOut, sIn, sMid;
-
- if (groupName == "G1") {
- if (inType == "affine") {
- sIn = G.F.n8*2;
- fnIn2Mid = "g1m_batchToJacobian";
- } else {
- sIn = G.F.n8*3;
- }
- sMid = G.F.n8*3;
- fnName = "g1m_"+fn;
- if (outType == "affine") {
- fnMid2Out = "g1m_batchToAffine";
- sOut = G.F.n8*2;
- } else {
- sOut = G.F.n8*3;
- }
- } else if (groupName == "G2") {
- if (inType == "affine") {
- sIn = G.F.n8*2;
- fnIn2Mid = "g2m_batchToJacobian";
- } else {
- sIn = G.F.n8*3;
- }
- fnName = "g2m_"+fn;
- sMid = G.F.n8*3;
- if (outType == "affine") {
- fnMid2Out = "g2m_batchToAffine";
- sOut = G.F.n8*2;
- } else {
- sOut = G.F.n8*3;
- }
- } else if (groupName == "Fr") {
- sIn = Fr.n8;
- sOut = Fr.n8;
- sMid = Fr.n8;
- fnName = "frm_" + fn;
- } else {
- throw new Error("Invalid group");
- }
-
- if (buff1.byteLength != buff2.byteLength) {
- throw new Error("Invalid buffer size");
- }
- const nPoints = Math.floor(buff1.byteLength / sIn);
- if (nPoints != 1 << log2(nPoints)) {
- throw new Error("Invalid number of points");
- }
-
- let chunkSize = Math.floor(nPoints /tm.concurrency);
- if (chunkSize < MIN_CHUNK_SIZE) chunkSize = MIN_CHUNK_SIZE;
- if (chunkSize > MAX_CHUNK_SIZE) chunkSize = MAX_CHUNK_SIZE;
-
- const opPromises = [];
-
- for (let i=0; i {
- if (logger) logger.debug(`${loggerTxt}: fftJoinExt End: ${i}/${nPoints}`);
- return r;
- })
- );
- }
-
- const result = await Promise.all(opPromises);
-
- let fullBuffOut1;
- let fullBuffOut2;
- if (nPoints * sOut > 1<<28) {
- fullBuffOut1 = new BigBuffer(nPoints*sOut);
- fullBuffOut2 = new BigBuffer(nPoints*sOut);
- } else {
- fullBuffOut1 = new Uint8Array(nPoints*sOut);
- fullBuffOut2 = new Uint8Array(nPoints*sOut);
- }
-
- let p =0;
- for (let i=0; i Fr.s+1) {
- if (logger) logger.error("lagrangeEvaluations input too big");
- throw new Error("lagrangeEvaluations input too big");
- }
-
- let t0 = buff.slice(0, buff.byteLength/2);
- let t1 = buff.slice(buff.byteLength/2, buff.byteLength);
-
-
- const shiftToSmallM = Fr.exp(Fr.shift, nPoints/2);
- const sConst = Fr.inv( Fr.sub(Fr.one, shiftToSmallM));
-
- [t0, t1] = await _fftJoinExt(t0, t1, "prepareLagrangeEvaluation", sConst, Fr.shiftInv, inType, "jacobian", logger, loggerTxt + " prep");
-
- const promises = [];
-
- promises.push( _fft(t0, true, "jacobian", outType, logger, loggerTxt + " t0"));
- promises.push( _fft(t1, true, "jacobian", outType, logger, loggerTxt + " t1"));
-
- [t0, t1] = await Promise.all(promises);
-
- let buffOut;
- if (t0.byteLength > (1<<28)) {
- buffOut = new BigBuffer(t0.byteLength*2);
- } else {
- buffOut = new Uint8Array(t0.byteLength*2);
- }
-
- buffOut.set(t0);
- buffOut.set(t1, t0.byteLength);
-
- return buffOut;
- };
-
- G.fftMix = async function fftMix(buff) {
- const sG = G.F.n8*3;
- let fnName, fnFFTJoin;
- if (groupName == "G1") {
- fnName = "g1m_fftMix";
- fnFFTJoin = "g1m_fftJoin";
- } else if (groupName == "G2") {
- fnName = "g2m_fftMix";
- fnFFTJoin = "g2m_fftJoin";
- } else if (groupName == "Fr") {
- fnName = "frm_fftMix";
- fnFFTJoin = "frm_fftJoin";
- } else {
- throw new Error("Invalid group");
- }
-
- const nPoints = Math.floor(buff.byteLength / sG);
- const power = log2(nPoints);
-
- let nChunks = 1 << log2(tm.concurrency);
-
- if (nPoints <= nChunks*2) nChunks = 1;
-
- const pointsPerChunk = nPoints / nChunks;
-
- const powerChunk = log2(pointsPerChunk);
-
- const opPromises = [];
- for (let i=0; i=0; i--) {
- fullBuffOut.set(result[i][0], p);
- p+=result[i][0].byteLength;
- }
-
- return fullBuffOut;
- };
-}
diff --git a/src/engine_multiexp.js b/src/engine_multiexp.js
deleted file mode 100644
index 3db5ac4..0000000
--- a/src/engine_multiexp.js
+++ /dev/null
@@ -1,154 +0,0 @@
-import { log2 } from "./utils.js";
-
-const pTSizes = [
- 1 , 1, 1, 1, 2, 3, 4, 5,
- 6 , 7, 7, 8, 9, 10, 11, 12,
- 13, 13, 14, 15, 16, 16, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17
-];
-
-export default function buildMultiexp(curve, groupName) {
- const G = curve[groupName];
- const tm = G.tm;
- async function _multiExpChunk(buffBases, buffScalars, inType, logger, logText) {
- if ( ! (buffBases instanceof Uint8Array) ) {
- if (logger) logger.error(`${logText} _multiExpChunk buffBases is not Uint8Array`);
- throw new Error(`${logText} _multiExpChunk buffBases is not Uint8Array`);
- }
- if ( ! (buffScalars instanceof Uint8Array) ) {
- if (logger) logger.error(`${logText} _multiExpChunk buffScalars is not Uint8Array`);
- throw new Error(`${logText} _multiExpChunk buffScalars is not Uint8Array`);
- }
- inType = inType || "affine";
-
- let sGIn;
- let fnName;
- if (groupName == "G1") {
- if (inType == "affine") {
- fnName = "g1m_multiexpAffine_chunk";
- sGIn = G.F.n8*2;
- } else {
- fnName = "g1m_multiexp_chunk";
- sGIn = G.F.n8*3;
- }
- } else if (groupName == "G2") {
- if (inType == "affine") {
- fnName = "g2m_multiexpAffine_chunk";
- sGIn = G.F.n8*2;
- } else {
- fnName = "g2m_multiexp_chunk";
- sGIn = G.F.n8*3;
- }
- } else {
- throw new Error("Invalid group");
- }
- const nPoints = Math.floor(buffBases.byteLength / sGIn);
-
- if (nPoints == 0) return G.zero;
- const sScalar = Math.floor(buffScalars.byteLength / nPoints);
- if( sScalar * nPoints != buffScalars.byteLength) {
- throw new Error("Scalar size does not match");
- }
-
- const bitChunkSize = pTSizes[log2(nPoints)];
- const nChunks = Math.floor((sScalar*8 - 1) / bitChunkSize) +1;
-
- const opPromises = [];
- for (let i=0; i=0; i--) {
- if (!G.isZero(res)) {
- for (let j=0; jMAX_CHUNK_SIZE) chunkSize = MAX_CHUNK_SIZE;
- if (chunkSize {
- if (logger) logger.debug(`Multiexp end: ${logText}: ${i}/${nPoints}`);
- return r;
- }));
- }
-
- const result = await Promise.all(opPromises);
-
- let res = G.zero;
- for (let i=result.length-1; i>=0; i--) {
- res = G.add(res, result[i]);
- }
-
- return res;
- }
-
- G.multiExp = async function multiExpAffine(buffBases, buffScalars, logger, logText) {
- return await _multiExp(buffBases, buffScalars, "jacobian", logger, logText);
- };
- G.multiExpAffine = async function multiExpAffine(buffBases, buffScalars, logger, logText) {
- return await _multiExp(buffBases, buffScalars, "affine", logger, logText);
- };
-}
diff --git a/src/engine_pairing.js b/src/engine_pairing.js
deleted file mode 100644
index 5a802ce..0000000
--- a/src/engine_pairing.js
+++ /dev/null
@@ -1,130 +0,0 @@
-
-export default function buildPairing(curve) {
- const tm = curve.tm;
- curve.pairing = function pairing(a, b) {
-
- tm.startSyncOp();
- const pA = tm.allocBuff(curve.G1.toJacobian(a));
- const pB = tm.allocBuff(curve.G2.toJacobian(b));
- const pRes = tm.alloc(curve.Gt.n8);
- tm.instance.exports[curve.name + "_pairing"](pA, pB, pRes);
-
- const res = tm.getBuff(pRes, curve.Gt.n8);
-
- tm.endSyncOp();
- return res;
- };
-
- curve.pairingEq = async function pairingEq() {
- let buffCt;
- let nEqs;
- if ((arguments.length % 2) == 1) {
- buffCt = arguments[arguments.length-1];
- nEqs = (arguments.length -1) /2;
- } else {
- buffCt = curve.Gt.one;
- nEqs = arguments.length /2;
- }
-
- const opPromises = [];
- for (let i=0; i.
-*/
-
-import * as fUtils from "./futils.js";
-import buildSqrt from "./fsqrt.js";
-
-export default class F2Field {
- constructor(F, nonResidue) {
- this.type="F2";
- this.F = F;
- this.zero = [this.F.zero, this.F.zero];
- this.one = [this.F.one, this.F.zero];
- this.negone = this.neg(this.one);
- this.nonResidue = nonResidue;
- this.m = F.m*2;
- this.p = F.p;
- this.n64 = F.n64*2;
- this.n32 = this.n64*2;
- this.n8 = this.n64*8;
-
- buildSqrt(this);
- }
-
- _mulByNonResidue(a) {
- return this.F.mul(this.nonResidue, a);
- }
-
- copy(a) {
- return [this.F.copy(a[0]), this.F.copy(a[1])];
- }
-
- add(a, b) {
- return [
- this.F.add(a[0], b[0]),
- this.F.add(a[1], b[1])
- ];
- }
-
- double(a) {
- return this.add(a,a);
- }
-
- sub(a, b) {
- return [
- this.F.sub(a[0], b[0]),
- this.F.sub(a[1], b[1])
- ];
- }
-
- neg(a) {
- return this.sub(this.zero, a);
- }
-
- conjugate(a) {
- return [
- a[0],
- this.F.neg(a[1])
- ];
- }
-
- mul(a, b) {
- const aA = this.F.mul(a[0] , b[0]);
- const bB = this.F.mul(a[1] , b[1]);
-
- return [
- this.F.add( aA , this._mulByNonResidue(bB)),
- this.F.sub(
- this.F.mul(
- this.F.add(a[0], a[1]),
- this.F.add(b[0], b[1])),
- this.F.add(aA, bB))];
- }
-
- inv(a) {
- const t0 = this.F.square(a[0]);
- const t1 = this.F.square(a[1]);
- const t2 = this.F.sub(t0, this._mulByNonResidue(t1));
- const t3 = this.F.inv(t2);
- return [
- this.F.mul(a[0], t3),
- this.F.neg(this.F.mul( a[1], t3)) ];
- }
-
- div(a, b) {
- return this.mul(a, this.inv(b));
- }
-
- square(a) {
- const ab = this.F.mul(a[0] , a[1]);
-
- /*
- [
- (a + b) * (a + non_residue * b) - ab - non_residue * ab,
- ab + ab
- ];
- */
-
- return [
- this.F.sub(
- this.F.mul(
- this.F.add(a[0], a[1]) ,
- this.F.add(
- a[0] ,
- this._mulByNonResidue(a[1]))),
- this.F.add(
- ab,
- this._mulByNonResidue(ab))),
- this.F.add(ab, ab)
- ];
- }
-
- isZero(a) {
- return this.F.isZero(a[0]) && this.F.isZero(a[1]);
- }
-
- eq(a, b) {
- return this.F.eq(a[0], b[0]) && this.F.eq(a[1], b[1]);
- }
-
- mulScalar(base, e) {
- return fUtils.mulScalar(this, base, e);
- }
-
- pow(base, e) {
- return fUtils.exp(this, base, e);
- }
-
- exp(base, e) {
- return fUtils.exp(this, base, e);
- }
-
- toString(a) {
- return `[ ${this.F.toString(a[0])} , ${this.F.toString(a[1])} ]`;
- }
-
- fromRng(rng) {
- const c0 = this.F.fromRng(rng);
- const c1 = this.F.fromRng(rng);
- return [c0, c1];
- }
-
- gt(a, b) {
- if (this.F.gt(a[0], b[0])) return true;
- if (this.F.gt(b[0], a[0])) return false;
- if (this.F.gt(a[1], b[1])) return true;
- return false;
- }
-
- geq(a, b) {
- return this.gt(a, b) || this.eq(a, b);
- }
-
- lt(a, b) {
- return !this.geq(a,b);
- }
-
- leq(a, b) {
- return !this.gt(a,b);
- }
-
- neq(a, b) {
- return !this.eq(a,b);
- }
-
- random() {
- return [this.F.random(), this.F.random()];
- }
-
-
- toRprLE(buff, o, e) {
- this.F.toRprLE(buff, o, e[0]);
- this.F.toRprLE(buff, o+this.F.n8, e[1]);
- }
-
- toRprBE(buff, o, e) {
- this.F.toRprBE(buff, o, e[1]);
- this.F.toRprBE(buff, o+this.F.n8, e[0]);
- }
-
- toRprLEM(buff, o, e) {
- this.F.toRprLEM(buff, o, e[0]);
- this.F.toRprLEM(buff, o+this.F.n8, e[1]);
- }
-
-
- toRprBEM(buff, o, e) {
- this.F.toRprBEM(buff, o, e[1]);
- this.F.toRprBEM(buff, o+this.F.n8, e[0]);
- }
-
- fromRprLE(buff, o) {
- o = o || 0;
- const c0 = this.F.fromRprLE(buff, o);
- const c1 = this.F.fromRprLE(buff, o+this.F.n8);
- return [c0, c1];
- }
-
- fromRprBE(buff, o) {
- o = o || 0;
- const c1 = this.F.fromRprBE(buff, o);
- const c0 = this.F.fromRprBE(buff, o+this.F.n8);
- return [c0, c1];
- }
-
- fromRprLEM(buff, o) {
- o = o || 0;
- const c0 = this.F.fromRprLEM(buff, o);
- const c1 = this.F.fromRprLEM(buff, o+this.F.n8);
- return [c0, c1];
- }
-
- fromRprBEM(buff, o) {
- o = o || 0;
- const c1 = this.F.fromRprBEM(buff, o);
- const c0 = this.F.fromRprBEM(buff, o+this.F.n8);
- return [c0, c1];
- }
-
-}
-
diff --git a/src/f3field.js b/src/f3field.js
deleted file mode 100644
index 3df2435..0000000
--- a/src/f3field.js
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- Copyright 2018 0kims association.
-
- This file is part of snarkjs.
-
- snarkjs is a free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License as published by the
- Free Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- snarkjs is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- snarkjs. If not, see .
-*/
-
-import * as fUtils from "./futils.js";
-
-export default class F3Field {
- constructor(F, nonResidue) {
- this.type="F3";
- this.F = F;
- this.zero = [this.F.zero, this.F.zero, this.F.zero];
- this.one = [this.F.one, this.F.zero, this.F.zero];
- this.negone = this.neg(this.one);
- this.nonResidue = nonResidue;
- this.m = F.m*3;
- this.p = F.p;
- this.n64 = F.n64*3;
- this.n32 = this.n64*2;
- this.n8 = this.n64*8;
- }
-
- _mulByNonResidue(a) {
- return this.F.mul(this.nonResidue, a);
- }
-
- copy(a) {
- return [this.F.copy(a[0]), this.F.copy(a[1]), this.F.copy(a[2])];
- }
-
- add(a, b) {
- return [
- this.F.add(a[0], b[0]),
- this.F.add(a[1], b[1]),
- this.F.add(a[2], b[2])
- ];
- }
-
- double(a) {
- return this.add(a,a);
- }
-
- sub(a, b) {
- return [
- this.F.sub(a[0], b[0]),
- this.F.sub(a[1], b[1]),
- this.F.sub(a[2], b[2])
- ];
- }
-
- neg(a) {
- return this.sub(this.zero, a);
- }
-
- mul(a, b) {
-
- const aA = this.F.mul(a[0] , b[0]);
- const bB = this.F.mul(a[1] , b[1]);
- const cC = this.F.mul(a[2] , b[2]);
-
- return [
- this.F.add(
- aA,
- this._mulByNonResidue(
- this.F.sub(
- this.F.mul(
- this.F.add(a[1], a[2]),
- this.F.add(b[1], b[2])),
- this.F.add(bB, cC)))), // aA + non_residue*((b+c)*(B+C)-bB-cC),
-
- this.F.add(
- this.F.sub(
- this.F.mul(
- this.F.add(a[0], a[1]),
- this.F.add(b[0], b[1])),
- this.F.add(aA, bB)),
- this._mulByNonResidue( cC)), // (a+b)*(A+B)-aA-bB+non_residue*cC
-
- this.F.add(
- this.F.sub(
- this.F.mul(
- this.F.add(a[0], a[2]),
- this.F.add(b[0], b[2])),
- this.F.add(aA, cC)),
- bB)]; // (a+c)*(A+C)-aA+bB-cC)
- }
-
- inv(a) {
- const t0 = this.F.square(a[0]); // t0 = a^2 ;
- const t1 = this.F.square(a[1]); // t1 = b^2 ;
- const t2 = this.F.square(a[2]); // t2 = c^2;
- const t3 = this.F.mul(a[0],a[1]); // t3 = ab
- const t4 = this.F.mul(a[0],a[2]); // t4 = ac
- const t5 = this.F.mul(a[1],a[2]); // t5 = bc;
- // c0 = t0 - non_residue * t5;
- const c0 = this.F.sub(t0, this._mulByNonResidue(t5));
- // c1 = non_residue * t2 - t3;
- const c1 = this.F.sub(this._mulByNonResidue(t2), t3);
- const c2 = this.F.sub(t1, t4); // c2 = t1-t4
-
- // t6 = (a * c0 + non_residue * (c * c1 + b * c2)).inv();
- const t6 =
- this.F.inv(
- this.F.add(
- this.F.mul(a[0], c0),
- this._mulByNonResidue(
- this.F.add(
- this.F.mul(a[2], c1),
- this.F.mul(a[1], c2)))));
-
- return [
- this.F.mul(t6, c0), // t6*c0
- this.F.mul(t6, c1), // t6*c1
- this.F.mul(t6, c2)]; // t6*c2
- }
-
- div(a, b) {
- return this.mul(a, this.inv(b));
- }
-
- square(a) {
- const s0 = this.F.square(a[0]); // s0 = a^2
- const ab = this.F.mul(a[0], a[1]); // ab = a*b
- const s1 = this.F.add(ab, ab); // s1 = 2ab;
- const s2 = this.F.square(
- this.F.add(this.F.sub(a[0],a[1]), a[2])); // s2 = (a - b + c)^2;
- const bc = this.F.mul(a[1],a[2]); // bc = b*c
- const s3 = this.F.add(bc, bc); // s3 = 2*bc
- const s4 = this.F.square(a[2]); // s4 = c^2
-
-
- return [
- this.F.add(
- s0,
- this._mulByNonResidue(s3)), // s0 + non_residue * s3,
- this.F.add(
- s1,
- this._mulByNonResidue(s4)), // s1 + non_residue * s4,
- this.F.sub(
- this.F.add( this.F.add(s1, s2) , s3 ),
- this.F.add(s0, s4))]; // s1 + s2 + s3 - s0 - s4
- }
-
- isZero(a) {
- return this.F.isZero(a[0]) && this.F.isZero(a[1]) && this.F.isZero(a[2]);
- }
-
- eq(a, b) {
- return this.F.eq(a[0], b[0]) && this.F.eq(a[1], b[1]) && this.F.eq(a[2], b[2]);
- }
-
- affine(a) {
- return [this.F.affine(a[0]), this.F.affine(a[1]), this.F.affine(a[2])];
- }
-
- mulScalar(base, e) {
- return fUtils.mulScalar(this, base, e);
- }
-
- pow(base, e) {
- return fUtils.exp(this, base, e);
- }
-
- exp(base, e) {
- return fUtils.exp(this, base, e);
- }
-
- toString(a) {
- return `[ ${this.F.toString(a[0])} , ${this.F.toString(a[1])}, ${this.F.toString(a[2])} ]`;
- }
-
- fromRng(rng) {
- const c0 = this.F.fromRng(rng);
- const c1 = this.F.fromRng(rng);
- const c2 = this.F.fromRng(rng);
- return [c0, c1, c2];
- }
-
- gt(a, b) {
- if (this.F.gt(a[0], b[0])) return true;
- if (this.F.gt(b[0], a[0])) return false;
- if (this.F.gt(a[1], b[1])) return true;
- if (this.F.gt(b[1], a[1])) return false;
- if (this.F.gt(a[2], b[2])) return true;
- return false;
- }
-
-
- geq(a, b) {
- return this.gt(a, b) || this.eq(a, b);
- }
-
- lt(a, b) {
- return !this.geq(a,b);
- }
-
- leq(a, b) {
- return !this.gt(a,b);
- }
-
- neq(a, b) {
- return !this.eq(a,b);
- }
-
- random() {
- return [this.F.random(), this.F.random(), this.F.random()];
- }
-
-
- toRprLE(buff, o, e) {
- this.F.toRprLE(buff, o, e[0]);
- this.F.toRprLE(buff, o+this.F.n8, e[1]);
- this.F.toRprLE(buff, o+this.F.n8*2, e[2]);
- }
-
- toRprBE(buff, o, e) {
- this.F.toRprBE(buff, o, e[2]);
- this.F.toRprBE(buff, o+this.F.n8, e[1]);
- this.F.toRprBE(buff, o+this.F.n8*2, e[0]);
- }
-
- toRprLEM(buff, o, e) {
- this.F.toRprLEM(buff, o, e[0]);
- this.F.toRprLEM(buff, o+this.F.n8, e[1]);
- this.F.toRprLEM(buff, o+this.F.n8*2, e[2]);
- }
-
-
- toRprBEM(buff, o, e) {
- this.F.toRprBEM(buff, o, e[2]);
- this.F.toRprBEM(buff, o+this.F.n8, e[1]);
- this.F.toRprBEM(buff, o+this.F.n8*2, e[0]);
- }
-
- fromRprLE(buff, o) {
- o = o || 0;
- const c0 = this.F.fromRprLE(buff, o);
- const c1 = this.F.fromRprLE(buff, o+this.n8);
- const c2 = this.F.fromRprLE(buff, o+this.n8*2);
- return [c0, c1, c2];
- }
-
- fromRprBE(buff, o) {
- o = o || 0;
- const c2 = this.F.fromRprBE(buff, o);
- const c1 = this.F.fromRprBE(buff, o+this.n8);
- const c0 = this.F.fromRprBE(buff, o+this.n8*2);
- return [c0, c1, c2];
- }
-
- fromRprLEM(buff, o) {
- o = o || 0;
- const c0 = this.F.fromRprLEM(buff, o);
- const c1 = this.F.fromRprLEM(buff, o+this.n8);
- const c2 = this.F.fromRprLEM(buff, o+this.n8*2);
- return [c0, c1, c2];
- }
-
- fromRprBEM(buff, o) {
- o = o || 0;
- const c2 = this.F.fromRprBEM(buff, o);
- const c1 = this.F.fromRprBEM(buff, o+this.n8);
- const c0 = this.F.fromRprBEM(buff, o+this.n8*2);
- return [c0, c1, c2];
- }
-
-}
diff --git a/src/fft.js b/src/fft.js
deleted file mode 100644
index 7e9f8af..0000000
--- a/src/fft.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- Copyright 2018 0kims association.
-
- This file is part of snarkjs.
-
- snarkjs is a free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License as published by the
- Free Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- snarkjs is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- snarkjs. If not, see .
-*/
-
-/*
- This library does operations on polynomials with coefficients in a field F.
-
- A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented
- by the array [ p0, p1, p2, ... , pn ].
- */
-
-export default class FFT {
- constructor (G, F, opMulGF) {
- this.F = F;
- this.G = G;
- this.opMulGF = opMulGF;
-
- let rem = F.sqrt_t;
- let s = F.sqrt_s;
-
- let nqr = F.one;
- while (F.eq(F.pow(nqr, F.half), F.one)) nqr = F.add(nqr, F.one);
-
- this.w = new Array(s+1);
- this.wi = new Array(s+1);
- this.w[s] = this.F.pow(nqr, rem);
- this.wi[s] = this.F.inv(this.w[s]);
-
- let n=s-1;
- while (n>=0) {
- this.w[n] = this.F.square(this.w[n+1]);
- this.wi[n] = this.F.square(this.wi[n+1]);
- n--;
- }
-
-
- this.roots = [];
- /*
- for (let i=0; i<16; i++) {
- let r = this.F.one;
- n = 1 << i;
- const rootsi = new Array(n);
- for (let j=0; j=0) && (!this.roots[i]); i--) {
- let r = this.F.one;
- const nroots = 1 << i;
- const rootsi = new Array(nroots);
- for (let j=0; j> 1;
- const p1 = __fft(PF, pall, bits-1, offset, step*2);
- const p2 = __fft(PF, pall, bits-1, offset+step, step*2);
-
- const out = new Array(n);
-
- for (let i=0; i.
-*/
-
-/*
- This library does operations on polynomials with coefficients in a field F.
-
- A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented
- by the array [ p0, p1, p2, ... , pn ].
- */
-
-export default class PolField {
- constructor (F) {
- this.F = F;
-
- let rem = F.sqrt_t;
- let s = F.sqrt_s;
-
- const five = this.F.add(this.F.add(this.F.two, this.F.two), this.F.one);
-
- this.w = new Array(s+1);
- this.wi = new Array(s+1);
- this.w[s] = this.F.pow(five, rem);
- this.wi[s] = this.F.inv(this.w[s]);
-
- let n=s-1;
- while (n>=0) {
- this.w[n] = this.F.square(this.w[n+1]);
- this.wi[n] = this.F.square(this.wi[n+1]);
- n--;
- }
-
-
- this.roots = [];
-/* for (let i=0; i<16; i++) {
- let r = this.F.one;
- n = 1 << i;
- const rootsi = new Array(n);
- for (let j=0; j this.F.sqrt_s) n = this.s;
- for (let i=n; (i>=0) && (!this.roots[i]); i--) {
- let r = this.F.one;
- const nroots = 1 << i;
- const rootsi = new Array(nroots);
- for (let j=0; j a.length) {
- [b, a] = [a, b];
- }
-
- if ((b.length <= 2) || (b.length < log2(a.length))) {
- return this.mulNormal(a,b);
- } else {
- return this.mulFFT(a,b);
- }
- }
-
- mulNormal(a, b) {
- let res = [];
- for (let i=0; i0) {
- const z = new Array(n).fill(this.F.zero);
- return z.concat(p);
- } else {
- if (-n >= p.length) return [];
- return p.slice(-n);
- }
- }
-
- eval2(p, x) {
- let v = this.F.zero;
- let ix = this.F.one;
- for (let i=0; i> 1),
- F.mul(
- x,
- _eval(p, newX, offset+step , step << 1, n >> 1)));
- return res;
- }
- }
-
- lagrange(points) {
- let roots = [this.F.one];
- for (let i=0; i> 1;
- const p1 = this._fft(pall, bits-1, offset, step*2);
- const p2 = this._fft(pall, bits-1, offset+step, step*2);
-
- const out = new Array(n);
-
- let m= this.F.one;
- for (let i=0; i0 && this.F.eq(p[i], this.F.zero) ) i--;
- return p.slice(0, i+1);
- }
-
- eq(a, b) {
- const pa = this.reduce(a);
- const pb = this.reduce(b);
-
- if (pa.length != pb.length) return false;
- for (let i=0; i=0; i--) {
- res[i] = this.F.add(this.F.mul(res[i+1], r), p[i+1]);
- }
- return res;
- }
-
- _next2Power(v) {
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v++;
- return v;
- }
-
- toString(p) {
- const ap = this.normalize(p);
- let S = "";
- for (let i=ap.length-1; i>=0; i--) {
- if (!this.F.eq(p[i], this.F.zero)) {
- if (S!="") S += " + ";
- S = S + p[i].toString(10);
- if (i>0) {
- S = S + "x";
- if (i>1) {
- S = S + "^" +i;
- }
- }
- }
- }
- return S;
- }
-
- normalize(p) {
- const res = new Array(p.length);
- for (let i=0; i
- // rec = x^(k-2-scaleV)/ v
- //
- // res = x^m/v = x^(m + (2*k-2 - scaleV) - (2*k-2 - scaleV)) /v =>
- // res = rec * x^(m - (2*k-2 - scaleV)) =>
- // res = rec * x^(m - 2*k + 2 + scaleV)
-
- const rec = this._reciprocal(this.scaleX(v, scaleV), kbits);
- const res = this.scaleX(rec, m - 2*k + 2 + scaleV);
-
- return res;
- }
-
- div(_u, _v) {
- if (_u.length < _v.length) return [];
- const kbits = log2(_v.length-1)+1;
- const k = 1 << kbits;
-
- const u = this.scaleX(_u, k-_v.length);
- const v = this.scaleX(_v, k-_v.length);
-
- const n = v.length-1;
- let m = u.length-1;
-
- const s = this._reciprocal(v, kbits);
- let t;
- if (m>2*n) {
- t = this.sub(this.scaleX([this.F.one], 2*n), this.mul(s, v));
- }
-
- let q = [];
- let rem = u;
- let us, ut;
- let finish = false;
-
- while (!finish) {
- us = this.mul(rem, s);
- q = this.add(q, this.scaleX(us, -2*n));
-
- if ( m > 2*n ) {
- ut = this.mul(rem, t);
- rem = this.scaleX(ut, -2*n);
- m = rem.length-1;
- } else {
- finish = true;
- }
- }
-
- return q;
- }
-
-
- // returns the ith nth-root of one
- oneRoot(n, i) {
- let nbits = log2(n-1)+1;
- let res = this.F.one;
- let r = i;
-
- if(i>=n) {
- throw new Error("Given 'i' should be lower than 'n'");
- }
- else if (1<0) {
- if (r & 1 == 1) {
- res = this.F.mul(res, this.w[nbits]);
- }
- r = r >> 1;
- nbits --;
- }
- return res;
- }
-
- computeVanishingPolinomial(bits, t) {
- const m = 1 << bits;
- return this.F.sub(this.F.pow(t, m), this.F.one);
- }
-
- evaluateLagrangePolynomials(bits, t) {
- const m= 1 << bits;
- const tm = this.F.pow(t, m);
- const u= new Array(m).fill(this.F.zero);
- this._setRoots(bits);
- const omega = this.w[bits];
-
- if (this.F.eq(tm, this.F.one)) {
- for (let i = 0; i < m; i++) {
- if (this.F.eq(this.roots[bits][0],t)) { // i.e., t equals omega^i
- u[i] = this.F.one;
- return u;
- }
- }
- }
-
- const z = this.F.sub(tm, this.F.one);
- // let l = this.F.mul(z, this.F.pow(this.F.twoinv, m));
- let l = this.F.mul(z, this.F.inv(this.F.e(m)));
- for (let i = 0; i < m; i++) {
- u[i] = this.F.mul(l, this.F.inv(this.F.sub(t,this.roots[bits][i])));
- l = this.F.mul(l, omega);
- }
-
- return u;
- }
-
- log2(V) {
- return log2(V);
- }
-}
-
-function log2( V )
-{
- return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
-}
-
-
-function __fft(PF, pall, bits, offset, step) {
-
- const n = 1 << bits;
- if (n==1) {
- return [ pall[offset] ];
- } else if (n==2) {
- return [
- PF.F.add(pall[offset], pall[offset + step]),
- PF.F.sub(pall[offset], pall[offset + step])];
- }
-
- const ndiv2 = n >> 1;
- const p1 = __fft(PF, pall, bits-1, offset, step*2);
- const p2 = __fft(PF, pall, bits-1, offset+step, step*2);
-
- const out = new Array(n);
-
- for (let i=0; i> 1;
- const p1 = __fft2(PF, pall.slice(0, ndiv2), bits-1);
- const p2 = __fft2(PF, pall.slice(ndiv2), bits-1);
-
- const out = new Array(n);
-
- for (let i=0; i>=1;
- }
- return res;
-}
-
-function rev(idx, bits) {
- return (
- _revTable[idx >>> 24] |
- (_revTable[(idx >>> 16) & 0xFF] << 8) |
- (_revTable[(idx >>> 8) & 0xFF] << 16) |
- (_revTable[idx & 0xFF] << 24)
- ) >>> (32-bits);
-}
-
-function __bitReverse(p, bits) {
- for (let k=0; kk) {
- const tmp= p[k];
- p[k] = p[r];
- p[r] = tmp;
- }
- }
-
-}
-
-
diff --git a/src/ratfield.js b/src/ratfield.js
deleted file mode 100644
index 512396c..0000000
--- a/src/ratfield.js
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- Copyright 2018 0kims association.
-
- This file is part of snarkjs.
-
- snarkjs is a free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License as published by the
- Free Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- snarkjs is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- snarkjs. If not, see .
-*/
-
-import * as fUtils from "./futils.js";
-
-export default class RatField {
- constructor(F) {
- this.F = F;
- this.zero = [F.zero, F.one];
- this.one = [F.one, F.one];
- this.two = [F.two, F.one];
- this.twoinv = [F.one, F.two];
- this.q = F.q;
- }
-
- add(a,b) {
- return [
- this.F.add(
- this.F.mul(a[0], b[1]),
- this.F.mul(a[1], b[0])),
- this.F.mul(a[1], b[1])];
- }
-
- double(a) {
- return [this.F.add(a[0], a[0]), a[1]];
- }
-
- sub(a,b) {
- return [
- this.F.sub(
- this.F.mul(a[0], b[1]),
- this.F.mul(a[1], b[0])),
- this.F.mul(a[1], b[1])];
- }
-
- neg(a) {
- return [this.F.neg(a[0]), a[1]];
- }
-
- mul(a,b) {
- return [
- this.F.mul(a[0], b[0]),
- this.F.mul(a[1], b[1]),
- ];
- }
-
- copy(a) {
- return [a[0], a[1]];
- }
-
- div(a, b) {
- return [
- this.F.mul(a[0], b[1]),
- this.F.mul(a[1], b[0]),
- ];
- }
-
- inv(a) {
- return [a[1], a[0]];
- }
-
- square(a) {
- return [
- this.F.square(a[0]),
- this.F.square(a[1])
- ];
- }
-
- mulScalar(base, e) {
- return [this.F.mulScalar(base[0], e) , base[1]];
- }
-
- exp(base, e) {
- return fUtils.exp(this, base, e);
- }
-
- eq(a, b) {
- return this.F.eq(
- this.F.mul(a[0], b[1]),
- this.F.mul(a[1], b[0])
- );
- }
-
- isZero(a) {
- return this.F.isZero(a[0]);
- }
-
- affine(a) {
- return [this.F.div(a[0], a[1]), this.F.one];
- }
-
- toString(a) {
- const ca = this.affine(a);
- return `"0x${ca[0].toString(16)}"`;
- }
-
- random() {
- return [this.F.random(), this.F.one];
- }
-
- fromF(a) {
- return [a, this.F.one];
- }
-
- toF(a) {
- return this.affine(a)[0];
- }
-}
-
diff --git a/src/threadman.js b/src/threadman.js
deleted file mode 100644
index e8ac5bc..0000000
--- a/src/threadman.js
+++ /dev/null
@@ -1,251 +0,0 @@
-/* global window, navigator, Blob, Worker, WebAssembly */
-/*
- Copyright 2019 0KIMS association.
-
- This file is part of wasmsnark (Web Assembly zkSnark Prover).
-
- wasmsnark is a free software: you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- wasmsnark is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with wasmsnark. If not, see .
-*/
-
-// const MEM_SIZE = 1000; // Memory size in 64K Pakes (512Mb)
-const MEM_SIZE = 25; // Memory size in 64K Pakes (1600Kb)
-
-
-import thread from "./threadman_thread.js";
-import os from "os";
-import Worker from "web-worker";
-
-class Deferred {
- constructor() {
- this.promise = new Promise((resolve, reject)=> {
- this.reject = reject;
- this.resolve = resolve;
- });
- }
-}
-
-function sleep(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
-}
-
-function base64ToArrayBuffer(base64) {
- if (process.browser) {
- var binary_string = window.atob(base64);
- var len = binary_string.length;
- var bytes = new Uint8Array(len);
- for (var i = 0; i < len; i++) {
- bytes[i] = binary_string.charCodeAt(i);
- }
- return bytes;
- } else {
- return new Uint8Array(Buffer.from(base64, "base64"));
- }
-}
-
-function stringToBase64(str) {
- if (process.browser) {
- return window.btoa(str);
- } else {
- return Buffer.from(str).toString("base64");
- }
-}
-
-const threadSource = stringToBase64("(" + thread.toString() + ")(self)");
-const workerSource = "data:application/javascript;base64," + threadSource;
-
-
-
-export default async function buildThreadManager(wasm, singleThread) {
- const tm = new ThreadManager();
-
- tm.memory = new WebAssembly.Memory({initial:MEM_SIZE});
- tm.u8 = new Uint8Array(tm.memory.buffer);
- tm.u32 = new Uint32Array(tm.memory.buffer);
-
- const wasmModule = await WebAssembly.compile(base64ToArrayBuffer(wasm.code));
-
- tm.instance = await WebAssembly.instantiate(wasmModule, {
- env: {
- "memory": tm.memory
- }
- });
-
- tm.singleThread = singleThread;
- tm.initalPFree = tm.u32[0]; // Save the Pointer to free space.
- tm.pq = wasm.pq;
- tm.pr = wasm.pr;
- tm.pG1gen = wasm.pG1gen;
- tm.pG1zero = wasm.pG1zero;
- tm.pG2gen = wasm.pG2gen;
- tm.pG2zero = wasm.pG2zero;
- tm.pOneT = wasm.pOneT;
-
- // tm.pTmp0 = tm.alloc(curve.G2.F.n8*3);
- // tm.pTmp1 = tm.alloc(curve.G2.F.n8*3);
-
-
- if (singleThread) {
- tm.code = base64ToArrayBuffer(wasm.code);
- tm.taskManager = thread();
- await tm.taskManager([{
- cmd: "INIT",
- init: MEM_SIZE,
- code: tm.code.slice()
- }]);
- tm.concurrency = 1;
- } else {
- tm.workers = [];
- tm.pendingDeferreds = [];
- tm.working = [];
-
- let concurrency;
-
- if ((typeof(navigator) === "object") && navigator.hardwareConcurrency) {
- concurrency = navigator.hardwareConcurrency;
- } else {
- concurrency = os.cpus().length;
- }
- // Limit to 64 threads for memory reasons.
- if (concurrency>64) concurrency=64;
- tm.concurrency = concurrency;
-
- for (let i = 0; i 0); i++) {
- if (this.working[i] == false) {
- const work = this.actionQueue.shift();
- this.postAction(i, work.data, work.transfers, work.deferred);
- }
- }
- }
-
- queueAction(actionData, transfers) {
- const d = new Deferred();
-
- if (this.singleThread) {
- const res = this.taskManager(actionData);
- d.resolve(res);
- } else {
- this.actionQueue.push({
- data: actionData,
- transfers: transfers,
- deferred: d
- });
- this.processWorks();
- }
- return d.promise;
- }
-
- resetMemory() {
- this.u32[0] = this.initalPFree;
- }
-
- allocBuff(buff) {
- const pointer = this.alloc(buff.byteLength);
- this.setBuff(pointer, buff);
- return pointer;
- }
-
- getBuff(pointer, length) {
- return this.u8.slice(pointer, pointer+ length);
- }
-
- setBuff(pointer, buffer) {
- this.u8.set(new Uint8Array(buffer), pointer);
- }
-
- alloc(length) {
- while (this.u32[0] & 3) this.u32[0]++; // Return always aligned pointers
- const res = this.u32[0];
- this.u32[0] += length;
- return res;
- }
-
- async terminate() {
- for (let i=0; i memory.buffer.byteLength) {
- const currentPages = memory.buffer.byteLength / 0x10000;
- let requiredPages = Math.floor((u32[0] + length) / 0x10000)+1;
- if (requiredPages>MAXMEM) requiredPages=MAXMEM;
- memory.grow(requiredPages-currentPages);
- }
- return res;
- }
-
- function allocBuffer(buffer) {
- const p = alloc(buffer.byteLength);
- setBuffer(p, buffer);
- return p;
- }
-
- function getBuffer(pointer, length) {
- const u8 = new Uint8Array(memory.buffer);
- return new Uint8Array(u8.buffer, u8.byteOffset + pointer, length);
- }
-
- function setBuffer(pointer, buffer) {
- const u8 = new Uint8Array(memory.buffer);
- u8.set(new Uint8Array(buffer), pointer);
- }
-
- function runTask(task) {
- if (task[0].cmd == "INIT") {
- return init(task[0]);
- }
- const ctx = {
- vars: [],
- out: []
- };
- const u32a = new Uint32Array(memory.buffer, 0, 1);
- const oldAlloc = u32a[0];
- for (let i=0; i=0; i--) {
- this.w[i] = this.square(this.w[i+1]);
- }
-
- if (!this.eq(this.w[0], this.one)) {
- throw new Error("Error calculating roots of unity");
- }
-
- this.batchToMontgomery = buildBatchConvert(tm, prefix + "_batchToMontgomery", this.n8, this.n8);
- this.batchFromMontgomery = buildBatchConvert(tm, prefix + "_batchFromMontgomery", this.n8, this.n8);
- }
-
-
- op2(opName, a, b) {
- this.tm.setBuff(this.pOp1, a);
- this.tm.setBuff(this.pOp2, b);
- this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2, this.pOp3);
- return this.tm.getBuff(this.pOp3, this.n8);
- }
-
- op2Bool(opName, a, b) {
- this.tm.setBuff(this.pOp1, a);
- this.tm.setBuff(this.pOp2, b);
- return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2);
- }
-
- op1(opName, a) {
- this.tm.setBuff(this.pOp1, a);
- this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
- return this.tm.getBuff(this.pOp3, this.n8);
- }
-
- op1Bool(opName, a) {
- this.tm.setBuff(this.pOp1, a);
- return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
- }
-
- add(a,b) {
- return this.op2("_add", a, b);
- }
-
-
- eq(a,b) {
- return this.op2Bool("_eq", a, b);
- }
-
- isZero(a) {
- return this.op1Bool("_isZero", a);
- }
-
- sub(a,b) {
- return this.op2("_sub", a, b);
- }
-
- neg(a) {
- return this.op1("_neg", a);
- }
-
- inv(a) {
- return this.op1("_inverse", a);
- }
-
- toMontgomery(a) {
- return this.op1("_toMontgomery", a);
- }
-
- fromMontgomery(a) {
- return this.op1("_fromMontgomery", a);
- }
-
- mul(a,b) {
- return this.op2("_mul", a, b);
- }
-
- div(a, b) {
- this.tm.setBuff(this.pOp1, a);
- this.tm.setBuff(this.pOp2, b);
- this.tm.instance.exports[this.prefix + "_inverse"](this.pOp2, this.pOp2);
- this.tm.instance.exports[this.prefix + "_mul"](this.pOp1, this.pOp2, this.pOp3);
- return this.tm.getBuff(this.pOp3, this.n8);
- }
-
- square(a) {
- return this.op1("_square", a);
- }
-
- isSquare(a) {
- return this.op1Bool("_isSquare", a);
- }
-
- sqrt(a) {
- return this.op1("_sqrt", a);
- }
-
- exp(a, b) {
- if (!(b instanceof Uint8Array)) {
- b = Scalar.toLEBuff(Scalar.e(b));
- }
- this.tm.setBuff(this.pOp1, a);
- this.tm.setBuff(this.pOp2, b);
- this.tm.instance.exports[this.prefix + "_exp"](this.pOp1, this.pOp2, b.byteLength, this.pOp3);
- return this.tm.getBuff(this.pOp3, this.n8);
- }
-
- isNegative(a) {
- return this.op1Bool("_isNegative", a);
- }
-
- e(a, b) {
- if (a instanceof Uint8Array) return a;
- let ra = Scalar.e(a, b);
- if (Scalar.isNegative(ra)) {
- ra = Scalar.neg(ra);
- if (Scalar.gt(ra, this.p)) {
- ra = Scalar.mod(ra, this.p);
- }
- ra = Scalar.sub(this.p, ra);
- } else {
- if (Scalar.gt(ra, this.p)) {
- ra = Scalar.mod(ra, this.p);
- }
- }
- const buff = utils.leInt2Buff(ra, this.n8);
- return this.toMontgomery(buff);
- }
-
- toString(a, radix) {
- const an = this.fromMontgomery(a);
- const s = Scalar.fromRprLE(an, 0);
- return Scalar.toString(s, radix);
- }
-
- fromRng(rng) {
- let v;
- const buff = new Uint8Array(this.n8);
- do {
- v = Scalar.zero;
- for (let i=0; i.
-*/
-
-import chai from "chai";
-
-import * as Scalar from "../src/scalar.js";
-import buildBn128 from "../src/bn128.js";
-import F1Field from "../src/f1field.js";
-
-const assert = chai.assert;
-
-
-describe("F1 testing", () => {
- let bn128;
- before( async() => {
- bn128 = await buildBn128();
- });
- after( async() => {
- bn128.terminate();
- });
-
- it("Should compute euclidean", () => {
- const F = new F1Field(Scalar.fromString("7"));
- const res = F.inv(F.e(4));
-
- assert(F.eq(res, F.e(2)));
- });
-
- it("Should multiply and divide in F1", () => {
- const a = bn128.F1.e("1");
- const b = bn128.F1.e("-1");
- const c = bn128.F1.mul(a,b);
- const d = bn128.F1.div(c,b);
-
- assert(bn128.F1.eq(a, d));
- });
-
- it("Should compute sqrts", () => {
- const F = new F1Field(bn128.r);
- const a = F.e("4");
- let b = F.sqrt(a);
- assert(F.eq(F.e(0), F.sqrt(F.e("0"))));
- assert(F.eq(b, F.e("2")));
- // assert(F.sqrt(F.nqr) === null);
- });
-
- it("Should compute sqrt of 100 random numbers", () => {
- const F = new F1Field(bn128.r);
- for (let j=0;j<100; j++) {
- let a = F.random();
- let s = F.sqrt(a);
- if (s != null) {
- assert(F.eq(F.square(s), a));
- }
- }
- });
-});
-
-describe("Curve G1 Test", () => {
- let bn128;
- before( async() => {
- bn128 = await buildBn128();
- });
- after( async() => {
- bn128.terminate();
- });
-
- it("r*one == 0", () => {
- const res = bn128.G1.timesScalar(bn128.G1.g, bn128.r);
-
- assert(bn128.G1.eq(res, bn128.G1.zero), "G1 does not have range r");
- });
-
- it("Should add match in various in G1", () => {
-
- const r1 = bn128.Fr.e(33);
- const r2 = bn128.Fr.e(44);
-
- const gr1 = bn128.G1.timesFr(bn128.G1.g, r1);
- const gr2 = bn128.G1.timesFr(bn128.G1.g, r2);
-
- const grsum1 = bn128.G1.add(gr1, gr2);
-
- const grsum2 = bn128.G1.timesFr(bn128.G1.g, bn128.Fr.add(r1, r2));
-
- assert(bn128.G1.eq(grsum1, grsum2));
- });
-});
-
-describe("Curve G2 Test", () => {
- let bn128;
- before( async() => {
- bn128 = await buildBn128();
- });
- after( async() => {
- bn128.terminate();
- });
-
- it ("r*one == 0", () => {
- const res = bn128.G2.timesScalar(bn128.G2.g, bn128.r);
-
- assert(bn128.G2.eq(res, bn128.G2.zero), "G2 does not have range r");
- });
-
- it("Should add match in various in G2", () => {
- const r1 = bn128.Fr.e(33);
- const r2 = bn128.Fr.e(44);
-
- const gr1 = bn128.G2.timesFr(bn128.G2.g, r1);
- const gr2 = bn128.G2.timesFr(bn128.G2.g, r2);
-
- const grsum1 = bn128.G2.add(gr1, gr2);
-
- const grsum2 = bn128.G2.timesFr(bn128.G2.g, bn128.Fr.add(r1, r2));
-
- /*
- console.log(G2.toString(grsum1));
- console.log(G2.toString(grsum2));
- */
-
- assert(bn128.G2.eq(grsum1, grsum2));
- });
-});
-
-describe("F6 testing", () => {
- let bn128;
- before( async() => {
- bn128 = await buildBn128();
- });
- after( async() => {
- bn128.terminate();
- });
-
- it("Should multiply and divide in F6", () => {
-
- const a = bn128.F6.fromObject([
- [Scalar.e("1"), Scalar.e("2")],
- [Scalar.e("3"), Scalar.e("4")],
- [Scalar.e("5"), Scalar.e("6")]
- ]);
- const b = bn128.F6.fromObject([
- [Scalar.e("12"), Scalar.e("11")],
- [Scalar.e("10"), Scalar.e("9")],
- [Scalar.e("8"), Scalar.e("7")]
- ]);
- const c = bn128.F6.mul(a,b);
- const d = bn128.F6.div(c,b);
-
- assert(bn128.F6.eq(a, d));
- });
-});
-
-describe("F12 testing", () => {
- let bn128;
- before( async() => {
- bn128 = await buildBn128();
- });
- after( async() => {
- bn128.terminate();
- });
-
- it("Should multiply and divide in F12", () => {
- const a = bn128.Gt.fromObject([
- [
- [Scalar.e("1"), Scalar.e("2")],
- [Scalar.e("3"), Scalar.e("4")],
- [Scalar.e("5"), Scalar.e("6")]
- ],
- [
- [Scalar.e("7"), Scalar.e("8")],
- [Scalar.e("9"), Scalar.e("10")],
- [Scalar.e("11"), Scalar.e("12")]
- ]
- ]);
- const b = bn128.Gt.fromObject([
- [
- [Scalar.e("12"), Scalar.e("11")],
- [Scalar.e("10"), Scalar.e("9")],
- [Scalar.e("8"), Scalar.e("7")]
- ],
- [
- [Scalar.e("6"), Scalar.e("5")],
- [Scalar.e("4"), Scalar.e("3")],
- [Scalar.e("2"), Scalar.e("1")]
- ]
- ]);
- const c = bn128.F12.mul(a,b);
- const d = bn128.F12.div(c,b);
-
- assert(bn128.F12.eq(a, d));
- });
-});
-
-describe("Pairing", () => {
- let bn128;
- before( async() => {
- bn128 = await buildBn128();
- });
- after( async() => {
- bn128.terminate();
- });
-
- /*
- it("Should match pairing", () => {
- for (let i=0; i<1; i++) {
- const bn128 = new BN128();
-
- const g1a = bn128.G1.mulScalar(bn128.G1.g, 25);
- const g2a = bn128.G2.mulScalar(bn128.G2.g, 30);
-
- const g1b = bn128.G1.mulScalar(bn128.G1.g, 30);
- const g2b = bn128.G2.mulScalar(bn128.G2.g, 25);
-
- const pre1a = bn128.prepareG1(g1a);
- const pre2a = bn128.prepareG2(g2a);
- const pre1b = bn128.prepareG1(g1b);
- const pre2b = bn128.prepareG2(g2b);
-
- const r1 = bn128.millerLoop(pre1a, pre2a);
- const r2 = bn128.millerLoop(pre1b, pre2b);
-
- const rbe = bn128.F12.mul(r1, bn128.F12.inverse(r2));
-
- const res = bn128.finalExponentiation(rbe);
-
- assert(bn128.F12.eq(res, bn128.F12.one));
- }
- }).timeout(10000);
- */
- it("Should generate another pairing pairing", () => {
- for (let i=0; i<1; i++) {
- const g1a = bn128.G1.timesScalar(bn128.G1.g, 10);
- const g2a = bn128.G2.timesScalar(bn128.G2.g, 1);
-
- const g1b = bn128.G1.timesScalar(bn128.G1.g, 1);
- const g2b = bn128.G2.timesScalar(bn128.G2.g, 10);
-
- const pre1a = bn128.prepareG1(g1a);
- const pre2a = bn128.prepareG2(g2a);
- const pre1b = bn128.prepareG1(g1b);
- const pre2b = bn128.prepareG2(g2b);
-
- const r1 = bn128.millerLoop(pre1a, pre2a);
- const r2 = bn128.finalExponentiation(r1);
-
- const r3 = bn128.millerLoop(pre1b, pre2b);
-
- const r4 = bn128.finalExponentiation(r3);
-
- /*
- console.log("ML1: " ,bn128.F12.toString(r1));
- console.log("FE1: " ,bn128.F12.toString(r2));
- console.log("ML2: " ,bn128.F12.toString(r3));
- console.log("FE2: " ,bn128.F12.toString(r4));
- */
-
- assert(bn128.F12.eq(r2, r4));
-
-
- /*
- const r2 = bn128.millerLoop(pre1b, pre2b);
-
- const rbe = bn128.F12.mul(r1, bn128.F12.inverse(r2));
-
- const res = bn128.finalExponentiation(rbe);
-
- assert(bn128.F12.eq(res, bn128.F12.one));
- */
- }
- }).timeout(10000);
-});
-
-describe("Compressed Form", () => {
- let bn128;
- before( async() => {
- bn128 = await buildBn128();
- });
- after( async() => {
- bn128.terminate();
- });
-
- it("Should test rpr of G2", () => {
- const P1 = bn128.G2.fromObject([
- [
- Scalar.e("1b2327ce7815d3358fe89fd8e5695305ed23682db29569f549ab8f48cae1f1c4",16),
- Scalar.e("1ed41ca6b3edc06237af648f845c270ff83bcde333f17863c1b71a43b271b46d",16)
- ],
- [
- Scalar.e("122057912ab892abcf2e729f0f342baea3fe1b484840eb97c7d78cd7530f4ab5",16),
- Scalar.e("2cb317fd40d56eeb17b0c1ff9443661a42ec00cea060012873b3f643f1a5bff8",16)
- ],
- [
- Scalar.one,
- Scalar.zero
- ]
- ]);
- const buff = new Uint8Array(64);
- bn128.G2.toRprCompressed(buff, 0, P1);
-
- const P2 = bn128.G2.fromRprCompressed(buff, 0);
-
- /*
- console.log(bn128.G2.toString(P1, 16));
- console.log(bn128.G2.toString(P2, 16));
- */
-
- assert(bn128.G2.eq(P1,P2));
- }).timeout(10000);
-});
diff --git a/test/bn128.js b/test/bn128.js
deleted file mode 100644
index 79d0a74..0000000
--- a/test/bn128.js
+++ /dev/null
@@ -1,181 +0,0 @@
-import assert from "assert";
-import buildBn128 from "../src/bn128.js";
-import {log2} from "../src/utils.js";
-import BigBuffer from "../src/bigbuffer.js";
-
-describe("bn128", async function () {
- this.timeout(10000000);
-
- const logger = {
- error: (msg) => { console.log("ERROR: "+msg); },
- warning: (msg) => { console.log("WARNING: "+msg); },
- info: (msg) => { console.log("INFO: "+msg); },
- debug: (msg) => { console.log("DEBUG: "+msg); },
- };
-
- let bn128;
- before( async() => {
- bn128 = await buildBn128();
- });
- after( async() => {
- bn128.terminate();
- });
-
- it("It shoud do an inverse FFT in G1", async () => {
- const Fr = bn128.Fr;
- const G1 = bn128.G1;
-
- const a = [];
- for (let i=0; i<8; i++) a[i] = Fr.e(i+1);
-
- const aG_expected = [];
- for (let i=0; i<8; i++) aG_expected[i] = G1.timesFr(G1.g, a[i]);
-
- const A = await bn128.Fr.fft(a);
-
-
- const AG = [];
- for (let i=0; i<8; i++) AG[i] = G1.timesFr(G1.g, A[i]);
-
- const aG_calculated = await G1.ifft(AG, "jacobian", "jacobian");
-
- for (let i=0; i<8; i++) {
- assert(G1.eq(aG_calculated[i], aG_expected[i]));
- }
- });
-
-
- it("It shoud do a big FFT/IFFT in Fr", async () => {
- const Fr = bn128.Fr;
-
- const N = 1<<10;
-
- const a = new BigBuffer(N*bn128.Fr.n8);
- for (let i=0; i {
- const Fr = bn128.Fr;
- const N = 8192*16;
-
- const a = [];
- for (let i=0; i {
- const Fr = bn128.Fr;
- const N = 16;
-
- const oldS = Fr.s;
- Fr.s = log2(N)-1; // Force ext
-
- const a = [];
- for (let i=0; i {
- const Fr = bn128.Fr;
- const G1 = bn128.G1;
- const N = 512;
-
- const a = [];
- for (let i=0; i {
- const Fr = bn128.Fr;
- const G1 = bn128.G1;
- const N = 1<<13;
-
- const oldS = Fr.s;
- Fr.s = log2(N)-1;
-
- const a = [];
- for (let i=0; i {
- const Fr = bn128.Fr;
- const G1 = bn128.G1;
- const N = 1 << 10;
-
- const scalars = new BigBuffer(N*bn128.Fr.n8);
- const bases = new BigBuffer(N*G1.F.n8*2);
- let acc = Fr.zero;
- for (let i=0; i.
-*/
-
-import chai from "chai";
-
-import * as Scalar from "../src/scalar.js";
-import PolField from "../src/polfield.js";
-import ZqField from "../src/f1field.js";
-
-const assert = chai.assert;
-
-const r = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
-
-describe("Polynomial field", () => {
- it("Should compute a multiplication", () => {
- const PF = new PolField(new ZqField(r));
-
- const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3)];
- const b = [PF.F.e(1), PF.F.e(2), PF.F.e(3)];
- const res = PF.mul(a,b);
-
- assert(PF.eq(res, [PF.F.e(1), PF.F.e(4), PF.F.e(10), PF.F.e(12), PF.F.e(9)]));
- });
- it("Should compute a multiplication 2", () => {
- const PF = new PolField(new ZqField(r));
-
- const a = [PF.F.e(5), PF.F.e(1)];
- const b = [PF.F.e(-5), PF.F.e(1)];
- const res = PF.mul(a,b);
-
- assert(PF.eq(res, [PF.F.e(-25), PF.F.e(0), PF.F.e(1)]));
- });
- it("Should compute an addition", () => {
- const PF = new PolField(new ZqField(r));
-
- const a = [PF.F.e(5), PF.F.e(1)];
- const b = [PF.F.e(-5), PF.F.e(1)];
- const res = PF.add(a,b);
-
- assert(PF.eq(res, [PF.F.e(0), PF.F.e(2)]));
- });
- it("Should compute a substraction", () => {
- const PF = new PolField(new ZqField(r));
-
- const a = [PF.F.e(5), PF.F.e(3), PF.F.e(4)];
- const b = [PF.F.e(5), PF.F.e(1)];
- const res = PF.sub(a,b);
-
- assert(PF.eq(res, [PF.F.e(0), PF.F.e(2), PF.F.e(4)]));
- });
- it("Should compute reciprocal", () => {
- const PF = new PolField(new ZqField(r));
-
- const a = PF.normalize([PF.F.e(4), PF.F.e(1), PF.F.e(-3), PF.F.e(-1), PF.F.e(2),PF.F.e(1), PF.F.e(-1), PF.F.e(1)]);
- const res = PF._reciprocal(a, 3, 0);
-
- assert(PF.eq(res, PF.normalize([PF.F.e(12), PF.F.e(15), PF.F.e(3), PF.F.e(-4), PF.F.e(-3), PF.F.e(0), PF.F.e(1), PF.F.e(1)])));
- });
- it("Should div2", () => {
- const PF = new PolField(new ZqField(r));
-
- // x^6
- const a = [PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(0),PF.F.e(0), PF.F.e(1)];
- // x^5
- const b = [PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(0), PF.F.e(1)];
-
- const res = PF._div2(6, b);
- assert(PF.eq(res, [PF.F.e(0), PF.F.e(1)]));
-
- const res2 = PF.div(a,b);
- assert(PF.eq(res2, [PF.F.e(0), PF.F.e(1)]));
- });
- it("Should div", () => {
- const PF = new PolField(new ZqField(r));
-
- const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3), PF.F.e(4), PF.F.e(5),PF.F.e(6), PF.F.e(7)];
- const b = [PF.F.e(8), PF.F.e(9), PF.F.e(10), PF.F.e(11), PF.F.e(12), PF.F.e(13)];
-
- const c = PF.mul(a,b);
- const d = PF.div(c,b);
-
- assert(PF.eq(a, d));
- });
- it("Should div big/small", () => {
- const PF = new PolField(new ZqField(r));
-
- const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3), PF.F.e(4), PF.F.e(5),PF.F.e(6), PF.F.e(7)];
- const b = [PF.F.e(8), PF.F.e(9)];
-
- const c = PF.mul(a,b);
- const d = PF.div(c,b);
-
- assert(PF.eq(a, d));
- });
- it("Should div random big", () => {
- const PF = new PolField(new ZqField(r));
-
- let a = [];
- let b = [];
- for (let i=0; i<1000; i++) a.push(PF.F.e(Math.floor(Math.random()*100000) -500000));
- for (let i=0; i<900; i++) b.push(PF.F.e(Math.floor(Math.random()*100000) -500000));
-
- a = PF.normalize(a);
- b = PF.normalize(a);
-
- const c = PF.mul(a,b);
-
- const d = PF.div(c,b);
-
- assert(PF.eq(a, d));
- }).timeout(10000);
- it("Should evaluate and zero", () => {
- const PF = new PolField(new ZqField(r));
- const p = [PF.F.neg(PF.F.e(2)), PF.F.e(1)];
- const v = PF.eval(p, PF.F.e(2));
- assert(PF.F.eq(v, PF.F.e(0)));
- });
- it("Should evaluate bigger number", () => {
- const PF = new PolField(new ZqField(r));
- const p = [PF.F.e(1), PF.F.e(2), PF.F.e(3)];
- const v = PF.eval(p, PF.F.e(2));
- assert(PF.F.eq(v, PF.F.e(17)));
- });
- it("Should create lagrange polynomial minmal", () => {
- const PF = new PolField(new ZqField(r));
-
- const points=[];
- points.push([PF.F.e(1), PF.F.e(1)]);
- points.push([PF.F.e(2), PF.F.e(2)]);
- points.push([PF.F.e(3), PF.F.e(5)]);
-
- const p=PF.lagrange(points);
-
- for (let i=0; i {
- const PF = new PolField(new ZqField(r));
-
- const points=[];
- points.push([PF.F.e(1), PF.F.e(2)]);
- points.push([PF.F.e(2), PF.F.e(-2)]);
- points.push([PF.F.e(3), PF.F.e(0)]);
- points.push([PF.F.e(4), PF.F.e(453345)]);
-
- const p=PF.lagrange(points);
-
- for (let i=0; i {
- const PF = new PolField(new ZqField(r));
- const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3), PF.F.e(4), PF.F.e(5),PF.F.e(6), PF.F.e(7)];
-
- const b = PF.mul(a, [PF.F.e(-7), PF.F.e(1)]);
- const c = PF.ruffini(b, PF.F.e(7));
-
- assert(PF.eq(a, c));
- });
- it("Should test roots", () => {
- const PF = new PolField(new ZqField(r));
- let rt;
-
-
- rt = PF.oneRoot(256, 16);
- for (let i=0; i<8; i++) {
- rt = PF.F.mul(rt, rt);
- }
- assert(PF.F.eq(rt, PF.F.one));
-
- rt = PF.oneRoot(256, 15);
- for (let i=0; i<8; i++) {
- rt = PF.F.mul(rt, rt);
- }
- assert(PF.F.eq(rt, PF.F.one));
-
- rt = PF.oneRoot(8, 3);
- for (let i=0; i<3; i++) {
- rt = PF.F.mul(rt, rt);
- }
- assert(PF.F.eq(rt, PF.F.one));
-
- rt = PF.oneRoot(8, 0);
- assert(PF.F.eq(rt, PF.F.one));
-
- });
- it("Should create a polynomial with values at roots with fft", () => {
- const PF = new PolField(new ZqField(r));
- const a = [PF.F.e(1), PF.F.e(2), PF.F.e(3), PF.F.e(4), PF.F.e(5),PF.F.e(6), PF.F.e(7)];
-
- const p = PF.ifft(a);
-
- for (let i=0; i.
-*/
-
-import chai from "chai";
-
-import * as Scalar from "../src/scalar.js";
-import ZqField from "../src/f1field.js";
-import RatField from "../src/ratfield.js";
-
-const q = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
-const Z = new ZqField(q);
-const R = new RatField(Z);
-
-const assert = chai.assert;
-
-function r(a,b) {
- return [Z.e(a), Z.e(b)];
-}
-
-
-describe("Rational zq Field", () => {
- it("Should compare correctly", () => {
- assert( R.eq(r(3,5), r(6,10)));
- assert(!R.eq(r(3,5), r(6,11)));
- });
- it("Should add correctly", () => {
- const a = r(7,4);
- const b = r(5,12);
-
- assert(R.eq( R.add(a,b), r(13, 6)));
- });
- it("Should substract", () => {
- const a = r(7,4);
- const b = r(5,12);
-
- assert(R.eq( R.sub(a,b), r(4, 3)));
- });
- it("Should multiply", () => {
- const a = r(7,4);
- const b = r(5,12);
-
- assert(R.eq( R.mul(a,b), r(35, 48)));
- });
- it("Should div", () => {
- const a = r(7,4);
- const b = r(5,12);
-
- assert(R.eq( R.div(a,b), r(7*12, 5*4)));
- });
- it("Should square", () => {
- const a = r(7,4);
-
- assert(R.eq( R.square(a), r(49, 16)));
- });
- it("Should affine", () => {
- const a = r(12,4);
- const aa = R.affine(a);
- assert(Z.eq( aa[0], Z.e(3)));
- assert(Z.eq( aa[1], Z.one));
- });
- it("Should convert from Z to R", () => {
- const vz = Z.e(34);
- const vr = R.fromF(vz);
-
- assert(R.eq( vr, r(34,1)));
- });
- it("Should convert from R to Z", () => {
- const vr = r(32, 2);
- const vz = R.toF(vr);
-
- assert(Z.eq( vz, Z.e(16)));
- });
-});
diff --git a/test/sqrt.js b/test/sqrt.js
deleted file mode 100644
index 7cb25fc..0000000
--- a/test/sqrt.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- Copyright 2018 0kims association.
-
- This file is part of zksnark JavaScript library.
-
- zksnark JavaScript library is a free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License as published by the
- Free Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- zksnark JavaScript library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
-
- You should have received a copy of the GNU General Public License along with
- zksnark JavaScript library. If not, see .
-*/
-
-import chai from "chai";
-
-import * as Scalar from "../src/scalar.js";
-import buildBn128 from "../src/bn128.js";
-import F1Field from "../src/f1field.js";
-
-const assert = chai.assert;
-
-
-describe("Sqrt testing", () => {
- let bn128;
- before( async() => {
- bn128 = await buildBn128();
- });
- after( async() => {
- bn128.terminate();
- });
-
-/*
- it("Should compute sqrts", () => {
- const F = new F1Field(bn128.r);
- const a = F.e(2);
- const b = F.sqrt_v(a);
- console.log(F.toString(b));
- });
-*/
- it("Should compute basic sqrts", () => {
- const F = new F1Field(bn128.r);
- assert(F.eq(F.e(0), F.sqrt(F.e("0"))));
- const a = F.e("9");
- let b = F.sqrt(a);
- assert(F.eq(b, F.e("3")));
- assert(F.sqrt(F.sqrt_z) === null);
- });
- it("Should compute sqrt p%4 = 1", () => {
- const F = new F1Field(bn128.r);
- const e = Scalar.div(Scalar.pow(F.p, F.m), 2);
- for (let i=0; i<100; i++) {
- const x2 = F.random();
- const x = F.sqrt(x2);
- if (x==null) {
- assert(F.eq( F.pow(x2, e), F.negone));
- } else {
- assert(F.eq(F.square(x), x2));
- }
- }
- });
- it("Should compute sqrt p%4 = 3", () => {
- const F = new F1Field(bn128.q);
- const e = Scalar.div(Scalar.pow(F.p, F.m), 2);
- for (let i=0; i<100; i++) {
- const x2 = F.random();
- const x = F.sqrt(x2);
- if (x==null) {
- assert(F.eq( F.pow(x2, e), F.negone));
- } else {
- assert(F.eq(F.square(x), x2));
- }
- }
- });
- it("Should compute sqrt m=2 p%4 = 3", () => {
- const F = bn128.F2;
- const e = Scalar.div(Scalar.exp(F.F.p, F.m), 2);
- for (let i=0; i<100; i++) {
- const x2 = F.random();
- if (!F.isSquare(x2)) {
- assert(F.eq( F.exp(x2, e), F.negone));
- } else {
- const x = F.sqrt(x2);
- assert(F.eq(F.square(x), x2));
- }
- }
- });
-
-});
-