From 80884d9fa815de3873b25ceb348cd1cd78a720dd Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Fri, 6 Oct 2023 17:32:44 +0200 Subject: [PATCH 1/3] Add Browser ES module build --- build/browser.esm.js | 18210 +++++++++++++++++++++++++++++++++ build/main.cjs | 110 +- package-lock.json | 948 +- package.json | 21 +- rollup.browser.esm.config.js | 39 + src/threadman.js | 10 +- 6 files changed, 19206 insertions(+), 132 deletions(-) create mode 100644 build/browser.esm.js create mode 100644 rollup.browser.esm.config.js diff --git a/build/browser.esm.js b/build/browser.esm.js new file mode 100644 index 0000000..d164540 --- /dev/null +++ b/build/browser.esm.js @@ -0,0 +1,18210 @@ +/* global BigInt */ +const hexLen = [ 0, 1, 2, 2, 3, 3, 3, 3, 4 ,4 ,4 ,4 ,4 ,4 ,4 ,4]; + +function fromString(s, radix) { + if ((!radix)||(radix==10)) { + return BigInt(s); + } else if (radix==16) { + if (s.slice(0,2) == "0x") { + return BigInt(s); + } else { + return BigInt("0x"+s); + } + } +} + +const e = fromString; + +function fromArray(a, radix) { + let acc =BigInt(0); + radix = BigInt(radix); + for (let i=0; i> BigInt(n); +} + +const shl = shiftLeft; +const shr = shiftRight; + +function isOdd$5(a) { + return (BigInt(a) & BigInt(1)) == BigInt(1); +} + + +function naf(n) { + let E = BigInt(n); + const res = []; + while (E) { + if (E & BigInt(1)) { + const z = 2 - Number(E % BigInt(4)); + res.push( z ); + E = E - BigInt(z); + } else { + res.push( 0 ); + } + E = E >> BigInt(1); + } + return res; +} + + +function bits(n) { + let E = BigInt(n); + const res = []; + while (E) { + if (E & BigInt(1)) { + res.push(1); + } else { + res.push( 0 ); + } + E = E >> BigInt(1); + } + return res; +} + +function toNumber$1(s) { + if (s>BigInt(Number.MAX_SAFE_INTEGER )) { + throw new Error("Number too big"); + } + return Number(s); +} + +function toArray(s, radix) { + const res = []; + let rem = BigInt(s); + radix = BigInt(radix); + while (rem) { + res.unshift( Number(rem % radix)); + rem = rem / radix; + } + return res; +} + + +function add(a, b) { + return BigInt(a) + BigInt(b); +} + +function sub(a, b) { + return BigInt(a) - BigInt(b); +} + +function neg(a) { + return -BigInt(a); +} + +function mul(a, b) { + return BigInt(a) * BigInt(b); +} + +function square$2(a) { + return BigInt(a) * BigInt(a); +} + +function pow(a, b) { + return BigInt(a) ** BigInt(b); +} + +function exp$1(a, b) { + return BigInt(a) ** BigInt(b); +} + +function abs$1(a) { + return BigInt(a) >= 0 ? BigInt(a) : -BigInt(a); +} + +function div(a, b) { + return BigInt(a) / BigInt(b); +} + +function mod(a, b) { + return BigInt(a) % BigInt(b); +} + +function eq(a, b) { + return BigInt(a) == BigInt(b); +} + +function neq(a, b) { + return BigInt(a) != BigInt(b); +} + +function lt(a, b) { + return BigInt(a) < BigInt(b); +} + +function gt(a, b) { + return BigInt(a) > BigInt(b); +} + +function leq(a, b) { + return BigInt(a) <= BigInt(b); +} + +function geq(a, b) { + return BigInt(a) >= BigInt(b); +} + +function band(a, b) { + return BigInt(a) & BigInt(b); +} + +function bor(a, b) { + return BigInt(a) | BigInt(b); +} + +function bxor(a, b) { + return BigInt(a) ^ BigInt(b); +} + +function land(a, b) { + return BigInt(a) && BigInt(b); +} + +function lor(a, b) { + return BigInt(a) || BigInt(b); +} + +function lnot(a) { + return !BigInt(a); +} + +// Returns a buffer with Little Endian Representation +function toRprLE(buff, o, e, n8) { + const s = "0000000" + e.toString(16); + const v = new Uint32Array(buff.buffer, buff.byteOffset + o, n8/4); + const l = (((s.length-7)*4 - 1) >> 5)+1; // Number of 32bit words; + for (let i=0; i> 5)+1; // Number of 32bit words; + for (let i=0; i a[a.length-i-1] = ch.toString(16).padStart(8,"0") ); + return fromString(a.join(""), 16); +} + +// Pases a buffer with Big Endian Representation +function fromRprBE(buff, o, n8) { + n8 = n8 || buff.byteLength; + o = o || 0; + const v = new DataView(buff.buffer, buff.byteOffset + o, n8); + const a = new Array(n8/4); + 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 ]. + */ + +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$2(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$2(_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$2(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$2(V); + } +} + +function log2$2( 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$1(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$1(PF, pall, bits-1, offset, step*2); + const p2 = __fft$1(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$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; + } + } + +} + +/* + 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$1(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"); + } + + for (let i=n.length-2; 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); + } + } + + return res; +} + + +/* +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); + } + + return res; +}; +*/ + + +function exp(F, base, e) { + + if (isZero$1(e)) return F.one; + + const n = bits(e); + + if (n.length==0) return F.one; + + let res = base; + + for (let i=n.length-2; i>=0; i--) { + + res = F.square(res); + + if (n[i]) { + res = F.mul(res, base); + } + } + + return 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); + } + } 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 { + alg8_complex(F); + } + + } +} + + +function alg5_tonelliShanks(F) { + F.sqrt_q = pow(F.p, F.m); + + F.sqrt_s = 0; + F.sqrt_t = sub(F.sqrt_q, 1); + + while (!isOdd$5(F.sqrt_t)) { + F.sqrt_s = F.sqrt_s + 1; + F.sqrt_t = div(F.sqrt_t, 2); + } + + let c0 = F.one; + + 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) ); + } + + F.sqrt_tm1d2 = div(sub(F.sqrt_t, 1),2); + + 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; + + 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++; + } + + 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; + + st[c] = (st[c] + st[d]) >>> 0; + st[b] = (st[b] ^ st[c]) >>> 0; + st[b] = ((st[b] << 12) | ((st[b]>>>20) & 0xFFF)) >>> 0; + + st[a] = (st[a] + st[b]) >>> 0; + st[d] = (st[d] ^ st[a]) >>> 0; + st[d] = ((st[d] << 8) | ((st[d]>>>24) & 0xFF)) >>> 0; + + st[c] = (st[c] + st[d]) >>> 0; + st[b] = (st[b] ^ st[c]) >>> 0; + st[b] = ((st[b] << 7) | ((st[b]>>>25) & 0x7F)) >>> 0; +} + +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); + + quarterRound(st, 0, 5,10,15); + quarterRound(st, 1, 6,11,12); + quarterRound(st, 2, 7, 8,13); + quarterRound(st, 3, 4, 9,14); +} + +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); + } + + nextU32() { + if (this.idx == 16) this.update(); + return this.buff[this.idx++]; + } + + nextU64() { + return add(mul(this.nextU32(), 0x100000000), this.nextU32()); + } + + nextBool() { + return (this.nextU32() & 1) == 1; + } + + 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; + } +} + +function getRandomBytes(n) { + let array = new Uint8Array(n); + { // Browser + if (typeof globalThis.crypto !== "undefined") { // Supported + globalThis.crypto.getRandomValues(array); + } else { // fallback + for (let i=0; i>>0; + } + } + } + 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]); + } + return seed; +} + +let threadRng = null; + +function getThreadRng() { + if (threadRng) return threadRng; + threadRng = new ChaCha(getRandomSeed()); + return threadRng; +} + +/* + 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 ]. + */ + +class FFT { + constructor (G, F, opMulGF) { + this.F = F; + this.G = G; + this.opMulGF = opMulGF; + + let rem = F.sqrt_t || F.t; + let s = F.sqrt_s || F.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.one; + this.bitLength = bitLength$6(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; + } + + this.nqr_to_t = this.pow(this.nqr, this.t); + + buildSqrt(this); + + this.FFT = new FFT(this, this, this.mul.bind(this)); + + this.fft = this.FFT.fft.bind(this.FFT); + this.ifft = this.FFT.ifft.bind(this.FFT); + this.w = this.FFT.w; + this.wi = this.FFT.wi; + + this.shift = this.square(this.nqr); + this.k = this.exp(this.nqr, 2**this.s); + } + + 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; + } + + } + + add(a, b) { + const res = a + b; + return res >= this.p ? res-this.p : res; + } + + sub(a, b) { + return (a >= b) ? a-b : this.p-b+a; + } + + neg(a) { + return a ? this.p-a : a; + } + + mul(a, b) { + return (a*b)%this.p; + } + + mulScalar(base, s) { + return (base * this.e(s)) % this.p; + } + + square(a) { + return (a*a) % this.p; + } + + eq(a, b) { + return a==b; + } + + 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= 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)&&(base == 10)) { + 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; + } + + fft(a) { + return this.FFT.fft(a); + } + + ifft(a) { + return this.FFT.ifft(a); + } + + // Returns a buffer with Little Endian Representation + toRprLE(buff, o, e) { + toRprLE(buff, o, e, this.n64*8); + } + + // Returns a buffer with Big Endian Representation + toRprBE(buff, o, e) { + toRprBE(buff, o, e, this.n64*8); + } + + // Returns a buffer with Big Endian Montgomery Representation + toRprBEM(buff, o, e) { + return this.toRprBE(buff, o, this.mul(this.R, e)); + } + + toRprLEM(buff, o, e) { + return this.toRprLE(buff, o, this.mul(this.R, e)); + } + + + // Pases a buffer with Little Endian Representation + fromRprLE(buff, o) { + return fromRprLE(buff, o, this.n8); + } + + // Pases a buffer with Big Endian Representation + fromRprBE(buff, o) { + return fromRprBE(buff, o, this.n8); + } + + fromRprLEM(buff, o) { + return this.mul(this.fromRprLE(buff, o), this.Ri); + } + + fromRprBEM(buff, o) { + return this.mul(this.fromRprBE(buff, o), this.Ri); + } + + toObject(a) { + return 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 . +*/ + + +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]; + } + + toObject(a) { + return 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 . +*/ + + +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]; + } + + toObject(a) { + return 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 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; + } + } + + +} + +function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; +} + +var utils$6 = {}; + +/* + 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 . +*/ + +utils$6.bigInt2BytesLE = function bigInt2BytesLE(_a, len) { + const b = Array(len); + let v = BigInt(_a); + for (let i=0; i> 8n; + } + return b; +}; + +utils$6.bigInt2U32LE = function bigInt2BytesLE(_a, len) { + const b = Array(len); + let v = BigInt(_a); + for (let i=0; i> 32n; + } + return b; +}; + +utils$6.isOcamNum = function(a) { + if (!Array.isArray(a)) return false; + if (a.length != 3) return false; + if (typeof a[0] !== "number") return false; + if (typeof a[1] !== "number") return false; + if (!Array.isArray(a[2])) return false; + return true; +}; + +/* + 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 . +*/ + +var build_int = function buildInt(module, n64, _prefix) { + + const prefix = _prefix || "int"; + if (module.modules[prefix]) return prefix; // already builded + module.modules[prefix] = {}; + + const n32 = n64*2; + const n8 = n64*8; + + function buildCopy() { + const f = module.addFunction(prefix+"_copy"); + f.addParam("px", "i32"); + f.addParam("pr", "i32"); + + const c = f.getCodeBuilder(); + + for (let i=0; i>1) )&&(i>1, k>>1) + ) + ) + ); + + f.addCode( + c.setLocal(c1, + c.i64_add( + c.getLocal(c1), + c.i64_shr_u( + c.getLocal(c0), + c.i64_const(32) + ) + ) + ) + ); + } + + // Add the old carry + + if (k>0) { + f.addCode( + c.setLocal(c0, + c.i64_add( + c.i64_and( + c.getLocal(c0), + c.i64_const(0xFFFFFFFF) + ), + c.i64_and( + c.getLocal(c0_old), + c.i64_const(0xFFFFFFFF) + ), + ) + ) + ); + + f.addCode( + c.setLocal(c1, + c.i64_add( + c.i64_add( + c.getLocal(c1), + c.i64_shr_u( + c.getLocal(c0), + c.i64_const(32) + ) + ), + c.getLocal(c1_old) + ) + ) + ); + } + + f.addCode( + c.i64_store32( + c.getLocal("r"), + k*4, + c.getLocal(c0) + ) + ); + + f.addCode( + c.setLocal( + c0_old, + c.getLocal(c1) + ), + c.setLocal( + c1_old, + c.i64_shr_u( + c.getLocal(c0_old), + c.i64_const(32) + ) + ) + ); + + } + f.addCode( + c.i64_store32( + c.getLocal("r"), + n32*4*2-4, + c.getLocal(c0_old) + ) + ); + + } + + + function buildSquareOld() { + const f = module.addFunction(prefix+"_squareOld"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode(c.call(prefix + "_mul", c.getLocal("x"), c.getLocal("x"), c.getLocal("r"))); + } + + function _buildMul1() { + const f = module.addFunction(prefix+"__mul1"); + f.addParam("px", "i32"); + f.addParam("y", "i64"); + f.addParam("pr", "i32"); + f.addLocal("c", "i64"); + + const c = f.getCodeBuilder(); + + f.addCode(c.setLocal( + "c", + c.i64_mul( + c.i64_load32_u(c.getLocal("px"), 0, 0), + c.getLocal("y") + ) + )); + + f.addCode(c.i64_store32( + c.getLocal("pr"), + 0, + 0, + c.getLocal("c"), + )); + + for (let i=1; i3)&&(Y[eY]==0) ey--; + f.addCode(c.block(c.loop( + c.br_if( + 1, + c.i32_or( + c.i32_load8_u( + c.i32_add(Y , c.getLocal("eY")), + 0, + 0 + ), + c.i32_eq( + c.getLocal("eY"), + c.i32_const(3) + ) + ) + ), + c.setLocal("eY", c.i32_sub(c.getLocal("eY"), c.i32_const(1))), + c.br(0) + ))); + + f.addCode( + c.setLocal( + "sy", + c.i64_add( + c.i64_load32_u( + c.i32_sub( + c.i32_add( Y, c.getLocal("eY")), + c.i32_const(3) + ), + 0, + 0 + ), + c.i64_const(1) + ) + ) + ); + + // Force a divide by 0 if quotien is 0 + f.addCode( + c.if( + c.i64_eq( + c.getLocal("sy"), + c.i64_const(1) + ), + c.drop(c.i64_div_u(c.i64_const(0), c.i64_const(0))) + ) + ); + + f.addCode(c.block(c.loop( + + // while (eX>7)&&(Y[eX]==0) ex--; + c.block(c.loop( + c.br_if( + 1, + c.i32_or( + c.i32_load8_u( + c.i32_add(R , c.getLocal("eX")), + 0, + 0 + ), + c.i32_eq( + c.getLocal("eX"), + c.i32_const(7) + ) + ) + ), + c.setLocal("eX", c.i32_sub(c.getLocal("eX"), c.i32_const(1))), + c.br(0) + )), + + c.setLocal( + "sx", + c.i64_load( + c.i32_sub( + c.i32_add( R, c.getLocal("eX")), + c.i32_const(7) + ), + 0, + 0 + ) + ), + + c.setLocal( + "sx", + c.i64_div_u( + c.getLocal("sx"), + c.getLocal("sy") + ) + ), + c.setLocal( + "ec", + c.i32_sub( + c.i32_sub( + c.getLocal("eX"), + c.getLocal("eY") + ), + c.i32_const(4) + ) + ), + + // While greater than 32 bits or ec is neg, shr and inc exp + c.block(c.loop( + c.br_if( + 1, + c.i32_and( + c.i64_eqz( + c.i64_and( + c.getLocal("sx"), + c.i64_const("0xFFFFFFFF00000000") + ) + ), + c.i32_ge_s( + c.getLocal("ec"), + c.i32_const(0) + ) + ) + ), + + c.setLocal( + "sx", + c.i64_shr_u( + c.getLocal("sx"), + c.i64_const(8) + ) + ), + + c.setLocal( + "ec", + c.i32_add( + c.getLocal("ec"), + c.i32_const(1) + ) + ), + c.br(0) + )), + + c.if( + c.i64_eqz(c.getLocal("sx")), + [ + ...c.br_if( + 2, + c.i32_eqz(c.call(prefix + "_gte", R, Y)) + ), + ...c.setLocal("sx", c.i64_const(1)), + ...c.setLocal("ec", c.i32_const(0)) + ] + ), + + c.call(prefix + "__mul1", Y, c.getLocal("sx"), R2), + c.drop(c.call( + prefix + "_sub", + R, + c.i32_sub(R2, c.getLocal("ec")), + R + )), + c.call( + prefix + "__add1", + c.i32_add(C, c.getLocal("ec")), + c.getLocal("sx") + ), + c.br(0) + ))); + } + + function buildInverseMod() { + + const f = module.addFunction(prefix+"_inverseMod"); + f.addParam("px", "i32"); + f.addParam("pm", "i32"); + f.addParam("pr", "i32"); + f.addLocal("t", "i32"); + f.addLocal("newt", "i32"); + f.addLocal("r", "i32"); + f.addLocal("qq", "i32"); + f.addLocal("qr", "i32"); + f.addLocal("newr", "i32"); + f.addLocal("swp", "i32"); + f.addLocal("x", "i32"); + f.addLocal("signt", "i32"); + f.addLocal("signnewt", "i32"); + f.addLocal("signx", "i32"); + + const c = f.getCodeBuilder(); + + const aux1 = c.i32_const(module.alloc(n8)); + const aux2 = c.i32_const(module.alloc(n8)); + const aux3 = c.i32_const(module.alloc(n8)); + const aux4 = c.i32_const(module.alloc(n8)); + const aux5 = c.i32_const(module.alloc(n8)); + const aux6 = c.i32_const(module.alloc(n8)); + const mulBuff = c.i32_const(module.alloc(n8*2)); + const aux7 = c.i32_const(module.alloc(n8)); + + f.addCode( + c.setLocal("t", aux1), + c.call(prefix + "_zero", aux1), + c.setLocal("signt", c.i32_const(0)), + ); + + f.addCode( + c.setLocal("r", aux2), + c.call(prefix + "_copy", c.getLocal("pm"), aux2) + ); + + f.addCode( + c.setLocal("newt", aux3), + c.call(prefix + "_one", aux3), + c.setLocal("signnewt", c.i32_const(0)), + ); + + f.addCode( + c.setLocal("newr", aux4), + c.call(prefix + "_copy", c.getLocal("px"), aux4) + ); + + + + + f.addCode(c.setLocal("qq", aux5)); + f.addCode(c.setLocal("qr", aux6)); + f.addCode(c.setLocal("x", aux7)); + + f.addCode(c.block(c.loop( + c.br_if( + 1, + c.call(prefix + "_isZero", c.getLocal("newr") ) + ), + c.call(prefix + "_div", c.getLocal("r"), c.getLocal("newr"), c.getLocal("qq"), c.getLocal("qr")), + + c.call(prefix + "_mul", c.getLocal("qq"), c.getLocal("newt"), mulBuff), + + c.if( + c.getLocal("signt"), + c.if( + c.getLocal("signnewt"), + c.if ( + c.call(prefix + "_gte", mulBuff, c.getLocal("t")), + [ + ...c.drop(c.call(prefix + "_sub", mulBuff, c.getLocal("t"), c.getLocal("x"))), + ...c.setLocal("signx", c.i32_const(0)) + ], + [ + ...c.drop(c.call(prefix + "_sub", c.getLocal("t"), mulBuff, c.getLocal("x"))), + ...c.setLocal("signx", c.i32_const(1)) + ], + ), + [ + ...c.drop(c.call(prefix + "_add", mulBuff, c.getLocal("t"), c.getLocal("x"))), + ...c.setLocal("signx", c.i32_const(1)) + ] + ), + c.if( + c.getLocal("signnewt"), + [ + ...c.drop(c.call(prefix + "_add", mulBuff, c.getLocal("t"), c.getLocal("x"))), + ...c.setLocal("signx", c.i32_const(0)) + ], + c.if ( + c.call(prefix + "_gte", c.getLocal("t"), mulBuff), + [ + ...c.drop(c.call(prefix + "_sub", c.getLocal("t"), mulBuff, c.getLocal("x"))), + ...c.setLocal("signx", c.i32_const(0)) + ], + [ + ...c.drop(c.call(prefix + "_sub", mulBuff, c.getLocal("t"), c.getLocal("x"))), + ...c.setLocal("signx", c.i32_const(1)) + ] + ) + ) + ), + + c.setLocal("swp", c.getLocal("t")), + c.setLocal("t", c.getLocal("newt")), + c.setLocal("newt", c.getLocal("x")), + c.setLocal("x", c.getLocal("swp")), + + c.setLocal("signt", c.getLocal("signnewt")), + c.setLocal("signnewt", c.getLocal("signx")), + + c.setLocal("swp", c.getLocal("r")), + c.setLocal("r", c.getLocal("newr")), + c.setLocal("newr", c.getLocal("qr")), + c.setLocal("qr", c.getLocal("swp")), + + c.br(0) + ))); + + f.addCode(c.if( + c.getLocal("signt"), + c.drop(c.call(prefix + "_sub", c.getLocal("pm"), c.getLocal("t"), c.getLocal("pr"))), + c.call(prefix + "_copy", c.getLocal("t"), c.getLocal("pr")) + )); + } + + + buildCopy(); + buildZero(); + buildIsZero(); + buildOne(); + buildEq(); + buildGte(); + buildAdd(); + buildSub(); + buildMul(); + buildSquare(); + buildSquareOld(); + buildDiv(); + buildInverseMod(); + module.exportFunction(prefix+"_copy"); + module.exportFunction(prefix+"_zero"); + module.exportFunction(prefix+"_one"); + module.exportFunction(prefix+"_isZero"); + module.exportFunction(prefix+"_eq"); + module.exportFunction(prefix+"_gte"); + module.exportFunction(prefix+"_add"); + module.exportFunction(prefix+"_sub"); + module.exportFunction(prefix+"_mul"); + module.exportFunction(prefix+"_square"); + module.exportFunction(prefix+"_squareOld"); + module.exportFunction(prefix+"_div"); + module.exportFunction(prefix+"_inverseMod"); + + return prefix; +}; + +/* + 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 . +*/ + +var build_timesscalar = function buildTimesScalar(module, fnName, elementLen, opAB, opAA, opCopy, opInit) { + + const f = module.addFunction(fnName); + f.addParam("base", "i32"); + f.addParam("scalar", "i32"); + f.addParam("scalarLength", "i32"); + f.addParam("r", "i32"); + f.addLocal("i", "i32"); + f.addLocal("b", "i32"); + + const c = f.getCodeBuilder(); + + const aux = c.i32_const(module.alloc(elementLen)); + + f.addCode( + c.if( + c.i32_eqz(c.getLocal("scalarLength")), + [ + ...c.call(opInit, c.getLocal("r")), + ...c.ret([]) + ] + ) + ); + f.addCode(c.call(opCopy, c.getLocal("base"), aux)); + f.addCode(c.call(opInit, c.getLocal("r"))); + f.addCode(c.setLocal("i", c.getLocal("scalarLength"))); + f.addCode(c.block(c.loop( + c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), + + c.setLocal( + "b", + c.i32_load8_u( + c.i32_add( + c.getLocal("scalar"), + c.getLocal("i") + ) + ) + ), + ...innerLoop(), + c.br_if(1, c.i32_eqz ( c.getLocal("i") )), + c.br(0) + ))); + + + function innerLoop() { + const code = []; + for (let i=0; i<8; i++) { + code.push( + ...c.call(opAA, c.getLocal("r"), c.getLocal("r")), + ...c.if( + c.i32_ge_u( c.getLocal("b"), c.i32_const(0x80 >> i)), + [ + ...c.setLocal( + "b", + c.i32_sub( + c.getLocal("b"), + c.i32_const(0x80 >> i) + ) + ), + ...c.call(opAB, c.getLocal("r"),aux, c.getLocal("r")) + ] + ) + ); + } + return code; + } + +}; + +var build_batchinverse = buildBatchInverse$3; + +function buildBatchInverse$3(module, prefix) { + + + const n8 = module.modules[prefix].n64*8; + + const f = module.addFunction(prefix+"_batchInverse"); + f.addParam("pIn", "i32"); + f.addParam("inStep", "i32"); + f.addParam("n", "i32"); + f.addParam("pOut", "i32"); + f.addParam("outStep", "i32"); + f.addLocal("itAux", "i32"); + f.addLocal("itIn", "i32"); + f.addLocal("itOut","i32"); + f.addLocal("i","i32"); + + const c = f.getCodeBuilder(); + + const AUX = c.i32_const(module.alloc(n8)); + + + // Alloc Working space for accumulated umltiplications + f.addCode( + c.setLocal("itAux", c.i32_load( c.i32_const(0) )), + c.i32_store( + c.i32_const(0), + c.i32_add( + c.getLocal("itAux"), + c.i32_mul( + c.i32_add( + c.getLocal("n"), + c.i32_const(1) + ), + c.i32_const(n8) + ) + ) + ) + ); + + f.addCode( + + // aux[0] = a; + c.call(prefix+"_one", c.getLocal("itAux")), + // for (i=0;i b ? 1 : -1; +} + +function square$1(n) { + return n * n; +} + +function isOdd$4(n) { + return n % 2n !== 0n; +} + +function isEven(n) { + return n % 2n === 0n; +} + +function isNegative$3(n) { + return n < 0n; +} + +function isPositive(n) { + return n > 0n; +} + +function bitLength$5(n) { + if (isNegative$3(n)) { + return n.toString(2).length - 1; // discard the - sign + } else { + return n.toString(2).length; + } +} + +function abs(n) { + return n < 0n ? -n : n; +} + +function isUnit(n) { + return abs(n) === 1n; +} + +function modInv$3(a, n) { + var t = 0n, newT = 1n, r = n, newR = abs(a), q, lastT, lastR; + while (newR !== 0n) { + q = r / newR; + lastT = t; + lastR = r; + t = newT; + r = newR; + newT = lastT - (q * newT); + newR = lastR - (q * newR); + } + if (!isUnit(r)) throw new Error(a.toString() + " and " + n.toString() + " are not co-prime"); + if (compare(t, 0n) === -1) { + t = t + n; + } + if (isNegative$3(a)) { + return -t; + } + return t; +} + +function modPow$2(n, exp, mod) { + if (mod === 0n) throw new Error("Cannot take modPow with modulus 0"); + var r = 1n, + base = n % mod; + if (isNegative$3(exp)) { + exp = exp * -1n; + base = modInv$3(base, mod); + } + while (isPositive(exp)) { + if (base === 0n) return 0n; + if (isOdd$4(exp)) r = r * base % mod; + exp = exp / 2n; + base = square$1(base) % mod; + } + return r; +} + +function compareAbs(a, b) { + a = a >= 0n ? a : -a; + b = b >= 0n ? b : -b; + return a === b ? 0 : a > b ? 1 : -1; +} + +function isDivisibleBy(a, n) { + if (n === 0n) return false; + if (isUnit(n)) return true; + if (compareAbs(n, 2n) === 0) return isEven(a); + return a % n === 0n; +} + +function isBasicPrime(v) { + var n = abs(v); + if (isUnit(n)) return false; + if (n === 2n || n === 3n || n === 5n) return true; + if (isEven(n) || isDivisibleBy(n, 3n) || isDivisibleBy(n, 5n)) return false; + if (n < 49n) return true; + // we don't know if it's prime: let the other functions figure it out +} + +function prev(n) { + return n - 1n; +} + +function millerRabinTest(n, a) { + var nPrev = prev(n), + b = nPrev, + r = 0, + d, i, x; + while (isEven(b)) b = b / 2n, r++; + next: for (i = 0; i < a.length; i++) { + if (n < a[i]) continue; + x = modPow$2(BigInt(a[i]), b, n); + if (isUnit(x) || x === nPrev) continue; + for (d = r - 1; d != 0; d--) { + x = square$1(x) % n; + if (isUnit(x)) return false; + if (x === nPrev) continue next; + } + return false; + } + return true; +} + +function isPrime$1(p) { + var isPrime = isBasicPrime(p); + if (isPrime !== undefined) return isPrime; + var n = abs(p); + var bits = bitLength$5(n); + if (bits <= 64) + return millerRabinTest(n, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]); + var logN = Math.log(2) * Number(bits); + var t = Math.ceil(logN); + for (var a = [], i = 0; i < t; i++) { + a.push(BigInt(i + 2)); + } + return millerRabinTest(n, a); +} + +bigint.bitLength = bitLength$5; +bigint.isOdd = isOdd$4; +bigint.isNegative = isNegative$3; +bigint.abs = abs; +bigint.isUnit = isUnit; +bigint.compare = compare; +bigint.modInv = modInv$3; +bigint.modPow = modPow$2; +bigint.isPrime = isPrime$1; +bigint.square = square$1; + +/* + 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 buildInt = build_int; +const utils$5 = utils$6; +const buildExp$2 = build_timesscalar; +const buildBatchInverse$2 = build_batchinverse; +const buildBatchConvertion$1 = build_batchconvertion; +const buildBatchOp = build_batchop; +const { bitLength: bitLength$4, modInv: modInv$2, modPow: modPow$1, isPrime, isOdd: isOdd$3, square } = bigint; + +var build_f1m = function buildF1m(module, _q, _prefix, _intPrefix) { + const q = BigInt(_q); + const n64 = Math.floor((bitLength$4(q - 1n) - 1)/64) +1; + const n32 = n64*2; + const n8 = n64*8; + + const prefix = _prefix || "f1m"; + if (module.modules[prefix]) return prefix; // already builded + + const intPrefix = buildInt(module, n64, _intPrefix); + const pq = module.alloc(n8, utils$5.bigInt2BytesLE(q, n8)); + + const pR2 = module.alloc(utils$5.bigInt2BytesLE(square(1n << BigInt(n64*64)) % q, n8)); + const pOne = module.alloc(utils$5.bigInt2BytesLE((1n << BigInt(n64*64)) % q, n8)); + const pZero = module.alloc(utils$5.bigInt2BytesLE(0n, n8)); + const _minusOne = q - 1n; + const _e = _minusOne >> 1n; // e = (p-1)/2 + const pe = module.alloc(n8, utils$5.bigInt2BytesLE(_e, n8)); + + const _ePlusOne = _e + 1n; // e = (p-1)/2 + const pePlusOne = module.alloc(n8, utils$5.bigInt2BytesLE(_ePlusOne, n8)); + + module.modules[prefix] = { + pq: pq, + pR2: pR2, + n64: n64, + q: q, + pOne: pOne, + pZero: pZero, + pePlusOne: pePlusOne + }; + + function buildOne() { + const f = module.addFunction(prefix+"_one"); + f.addParam("pr", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode(c.call(intPrefix + "_copy", c.i32_const(pOne), c.getLocal("pr"))); + } + + function buildAdd() { + const f = module.addFunction(prefix+"_add"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.if( + c.call(intPrefix+"_add", c.getLocal("x"), c.getLocal("y"), c.getLocal("r")), + c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), + c.if( + c.call(intPrefix+"_gte", c.getLocal("r"), c.i32_const(pq) ), + c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), + ) + ) + ); + } + + function buildSub() { + const f = module.addFunction(prefix+"_sub"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.if( + c.call(intPrefix+"_sub", c.getLocal("x"), c.getLocal("y"), c.getLocal("r")), + c.drop(c.call(intPrefix+"_add", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))) + ) + ); + } + + function buildNeg() { + const f = module.addFunction(prefix+"_neg"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.call(prefix + "_sub", c.i32_const(pZero), c.getLocal("x"), c.getLocal("r")) + ); + } + + + function buildIsNegative() { + const f = module.addFunction(prefix+"_isNegative"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const AUX = c.i32_const(module.alloc(n8)); + + f.addCode( + c.call(prefix + "_fromMontgomery", c.getLocal("x"), AUX), + c.call(intPrefix + "_gte", AUX, c.i32_const(pePlusOne) ) + ); + } + + function buildSign() { + const f = module.addFunction(prefix+"_sign"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const AUX = c.i32_const(module.alloc(n8)); + + f.addCode( + c.if ( + c.call(intPrefix + "_isZero", c.getLocal("x")), + c.ret(c.i32_const(0)) + ), + c.call(prefix + "_fromMontgomery", c.getLocal("x"), AUX), + c.if( + c.call(intPrefix + "_gte", AUX, c.i32_const(pePlusOne)), + c.ret(c.i32_const(-1)) + ), + c.ret(c.i32_const(1)) + ); + } + + + function buildMReduct() { + const carries = module.alloc(n32*n32*8); + + const f = module.addFunction(prefix+"_mReduct"); + f.addParam("t", "i32"); + f.addParam("r", "i32"); + f.addLocal("np32", "i64"); + f.addLocal("c", "i64"); + f.addLocal("m", "i64"); + + const c = f.getCodeBuilder(); + + const np32 = Number(0x100000000n - modInv$2(q, 0x100000000n)); + + f.addCode(c.setLocal("np32", c.i64_const(np32))); + + for (let i=0; i=n32) { + f.addCode( + c.i64_store32( + c.getLocal("r"), + (k-n32)*4, + c.getLocal(c0) + ) + ); + } + [c0, c1] = [c1, c0]; + f.addCode( + c.setLocal(c1, + c.i64_shr_u( + c.getLocal(c0), + c.i64_const(32) + ) + ) + ); + } + f.addCode( + c.i64_store32( + c.getLocal("r"), + n32*4-4, + c.getLocal(c0) + ) + ); + + f.addCode( + c.if( + c.i32_wrap_i64(c.getLocal(c1)), + c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), + c.if( + c.call(intPrefix+"_gte", c.getLocal("r"), c.i32_const(pq) ), + c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), + ) + ) + ); + } + + + function buildSquare() { + + const f = module.addFunction(prefix+"_square"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + f.addLocal("c0", "i64"); + f.addLocal("c1", "i64"); + f.addLocal("c0_old", "i64"); + f.addLocal("c1_old", "i64"); + f.addLocal("np32", "i64"); + + + for (let i=0;i>1) )&&(i>1, k>>1) + ) + ) + ); + + f.addCode( + c.setLocal(c1, + c.i64_add( + c.getLocal(c1), + c.i64_shr_u( + c.getLocal(c0), + c.i64_const(32) + ) + ) + ) + ); + } + + // Add the old carry + + if (k>0) { + f.addCode( + c.setLocal(c0, + c.i64_add( + c.i64_and( + c.getLocal(c0), + c.i64_const(0xFFFFFFFF) + ), + c.i64_and( + c.getLocal(c0_old), + c.i64_const(0xFFFFFFFF) + ), + ) + ) + ); + + f.addCode( + c.setLocal(c1, + c.i64_add( + c.i64_add( + c.getLocal(c1), + c.i64_shr_u( + c.getLocal(c0), + c.i64_const(32) + ) + ), + c.getLocal(c1_old) + ) + ) + ); + } + + + for (let i=Math.max(1, k-n32+1); (i<=k)&&(i=n32) { + f.addCode( + c.i64_store32( + c.getLocal("r"), + (k-n32)*4, + c.getLocal(c0) + ) + ); + } + f.addCode( + c.setLocal( + c0_old, + c.getLocal(c1) + ), + c.setLocal( + c1_old, + c.i64_shr_u( + c.getLocal(c0_old), + c.i64_const(32) + ) + ) + ); + } + f.addCode( + c.i64_store32( + c.getLocal("r"), + n32*4-4, + c.getLocal(c0_old) + ) + ); + + f.addCode( + c.if( + c.i32_wrap_i64(c.getLocal(c1_old)), + c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), + c.if( + c.call(intPrefix+"_gte", c.getLocal("r"), c.i32_const(pq) ), + c.drop(c.call(intPrefix+"_sub", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))), + ) + ) + ); + } + + + function buildSquareOld() { + const f = module.addFunction(prefix+"_squareOld"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode(c.call(prefix + "_mul", c.getLocal("x"), c.getLocal("x"), c.getLocal("r"))); + } + + function buildToMontgomery() { + const f = module.addFunction(prefix+"_toMontgomery"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + f.addCode(c.call(prefix+"_mul", c.getLocal("x"), c.i32_const(pR2), c.getLocal("r"))); + } + + function buildFromMontgomery() { + + const pAux2 = module.alloc(n8*2); + + const f = module.addFunction(prefix+"_fromMontgomery"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + f.addCode(c.call(intPrefix + "_copy", c.getLocal("x"), c.i32_const(pAux2) )); + f.addCode(c.call(intPrefix + "_zero", c.i32_const(pAux2 + n8) )); + f.addCode(c.call(prefix+"_mReduct", c.i32_const(pAux2), c.getLocal("r"))); + } + + function buildInverse() { + + const f = module.addFunction(prefix+ "_inverse"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + f.addCode(c.call(prefix + "_fromMontgomery", c.getLocal("x"), c.getLocal("r"))); + f.addCode(c.call(intPrefix + "_inverseMod", c.getLocal("r"), c.i32_const(pq), c.getLocal("r"))); + f.addCode(c.call(prefix + "_toMontgomery", c.getLocal("r"), c.getLocal("r"))); + } + + // Calculate various valuse needed for sqrt + + + let _nqr = 2n; + if (isPrime(q)) { + while (modPow$1(_nqr, _e, q) !== _minusOne) _nqr = _nqr + 1n; + } + + let s2 = 0; + let _t = _minusOne; + + while ((!isOdd$3(_t))&&(_t !== 0n)) { + s2++; + _t = _t >> 1n; + } + const pt = module.alloc(n8, utils$5.bigInt2BytesLE(_t, n8)); + + const _nqrToT = modPow$1(_nqr, _t, q); + const pNqrToT = module.alloc(utils$5.bigInt2BytesLE((_nqrToT << BigInt(n64*64)) % q, n8)); + + const _tPlusOneOver2 = (_t + 1n) >> 1n; + const ptPlusOneOver2 = module.alloc(n8, utils$5.bigInt2BytesLE(_tPlusOneOver2, n8)); + + function buildSqrt() { + + const f = module.addFunction(prefix+ "_sqrt"); + f.addParam("n", "i32"); + f.addParam("r", "i32"); + f.addLocal("m", "i32"); + f.addLocal("i", "i32"); + f.addLocal("j", "i32"); + + const c = f.getCodeBuilder(); + + const ONE = c.i32_const(pOne); + const C = c.i32_const(module.alloc(n8)); + const T = c.i32_const(module.alloc(n8)); + const R = c.i32_const(module.alloc(n8)); + const SQ = c.i32_const(module.alloc(n8)); + const B = c.i32_const(module.alloc(n8)); + + f.addCode( + + // If (n==0) return 0 + c.if( + c.call(prefix + "_isZero", c.getLocal("n")), + c.ret( + c.call(prefix + "_zero", c.getLocal("r")) + ) + ), + + c.setLocal("m", c.i32_const(s2)), + c.call(prefix + "_copy", c.i32_const(pNqrToT), C), + c.call(prefix + "_exp", c.getLocal("n"), c.i32_const(pt), c.i32_const(n8), T), + c.call(prefix + "_exp", c.getLocal("n"), c.i32_const(ptPlusOneOver2), c.i32_const(n8), R), + + c.block(c.loop( + c.br_if(1, c.call(prefix + "_eq", T, ONE)), + + c.call(prefix + "_square", T, SQ), + c.setLocal("i", c.i32_const(1)), + c.block(c.loop( + c.br_if(1, c.call(prefix + "_eq", SQ, ONE)), + c.call(prefix + "_square", SQ, SQ), + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )), + + c.call(prefix + "_copy", C, B), + c.setLocal("j", c.i32_sub(c.i32_sub( c.getLocal("m"), c.getLocal("i")), c.i32_const(1)) ), + c.block(c.loop( + c.br_if(1, c.i32_eqz(c.getLocal("j"))), + c.call(prefix + "_square", B, B), + c.setLocal("j", c.i32_sub(c.getLocal("j"), c.i32_const(1))), + c.br(0) + )), + + c.setLocal("m", c.getLocal("i")), + c.call(prefix + "_square", B, C), + c.call(prefix + "_mul", T, C, T), + c.call(prefix + "_mul", R, B, R), + + c.br(0) + )), + + c.if( + c.call(prefix + "_isNegative", R), + c.call(prefix + "_neg", R, c.getLocal("r")), + c.call(prefix + "_copy", R, c.getLocal("r")), + ) + ); + } + + function buildIsSquare() { + const f = module.addFunction(prefix+"_isSquare"); + f.addParam("n", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const ONE = c.i32_const(pOne); + const AUX = c.i32_const(module.alloc(n8)); + + f.addCode( + c.if( + c.call(prefix + "_isZero", c.getLocal("n")), + c.ret(c.i32_const(1)) + ), + c.call(prefix + "_exp", c.getLocal("n"), c.i32_const(pe), c.i32_const(n8), AUX), + c.call(prefix + "_eq", AUX, ONE) + ); + } + + + function buildLoad() { + const f = module.addFunction(prefix+"_load"); + f.addParam("scalar", "i32"); + f.addParam("scalarLen", "i32"); + f.addParam("r", "i32"); + f.addLocal("p", "i32"); + f.addLocal("l", "i32"); + f.addLocal("i", "i32"); + f.addLocal("j", "i32"); + const c = f.getCodeBuilder(); + + const R = c.i32_const(module.alloc(n8)); + const pAux = module.alloc(n8); + const AUX = c.i32_const(pAux); + + f.addCode( + c.call(intPrefix + "_zero", c.getLocal("r")), + c.setLocal("i", c.i32_const(n8)), + c.setLocal("p", c.getLocal("scalar")), + c.block(c.loop( + c.br_if(1, c.i32_gt_u(c.getLocal("i"), c.getLocal("scalarLen"))), + + c.if( + c.i32_eq(c.getLocal("i"), c.i32_const(n8)), + c.call(prefix + "_one", R), + c.call(prefix + "_mul", R, c.i32_const(pR2), R) + ), + c.call(prefix + "_mul", c.getLocal("p"), R, AUX), + c.call(prefix + "_add", c.getLocal("r"), AUX, c.getLocal("r")), + + c.setLocal("p", c.i32_add(c.getLocal("p"), c.i32_const(n8))), + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(n8))), + c.br(0) + )), + + c.setLocal("l", c.i32_rem_u( c.getLocal("scalarLen"), c.i32_const(n8))), + c.if(c.i32_eqz(c.getLocal("l")), c.ret([])), + c.call(intPrefix + "_zero", AUX), + c.setLocal("j", c.i32_const(0)), + c.block(c.loop( + c.br_if(1, c.i32_eq(c.getLocal("j"), c.getLocal("l"))), + + c.i32_store8( + c.getLocal("j"), + pAux, + c.i32_load8_u(c.getLocal("p")), + ), + c.setLocal("p", c.i32_add(c.getLocal("p"), c.i32_const(1))), + c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), + c.br(0) + )), + + c.if( + c.i32_eq(c.getLocal("i"), c.i32_const(n8)), + c.call(prefix + "_one", R), + c.call(prefix + "_mul", R, c.i32_const(pR2), R) + ), + c.call(prefix + "_mul", AUX, R, AUX), + c.call(prefix + "_add", c.getLocal("r"), AUX, c.getLocal("r")), + ); + } + + function buildTimesScalar() { + const f = module.addFunction(prefix+"_timesScalar"); + f.addParam("x", "i32"); + f.addParam("scalar", "i32"); + f.addParam("scalarLen", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const AUX = c.i32_const(module.alloc(n8)); + + f.addCode( + c.call(prefix + "_load", c.getLocal("scalar"), c.getLocal("scalarLen"), AUX), + c.call(prefix + "_toMontgomery", AUX, AUX), + c.call(prefix + "_mul", c.getLocal("x"), AUX, c.getLocal("r")), + ); + } + + function buildIsOne() { + const f = module.addFunction(prefix+"_isOne"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + f.addCode( + c.ret(c.call(intPrefix + "_eq", c.getLocal("x"), c.i32_const(pOne))) + ); + } + + + module.exportFunction(intPrefix + "_copy", prefix+"_copy"); + module.exportFunction(intPrefix + "_zero", prefix+"_zero"); + module.exportFunction(intPrefix + "_isZero", prefix+"_isZero"); + module.exportFunction(intPrefix + "_eq", prefix+"_eq"); + + buildIsOne(); + buildAdd(); + buildSub(); + buildNeg(); + buildMReduct(); + buildMul(); + buildSquare(); + buildSquareOld(); + buildToMontgomery(); + buildFromMontgomery(); + buildIsNegative(); + buildSign(); + buildInverse(); + buildOne(); + buildLoad(); + buildTimesScalar(); + buildBatchInverse$2(module, prefix); + buildBatchConvertion$1(module, prefix + "_batchToMontgomery", prefix + "_toMontgomery", n8, n8); + buildBatchConvertion$1(module, prefix + "_batchFromMontgomery", prefix + "_fromMontgomery", n8, n8); + buildBatchConvertion$1(module, prefix + "_batchNeg", prefix + "_neg", n8, n8); + buildBatchOp(module, prefix + "_batchAdd", prefix + "_add", n8, n8); + buildBatchOp(module, prefix + "_batchSub", prefix + "_sub", n8, n8); + buildBatchOp(module, prefix + "_batchMul", prefix + "_mul", n8, n8); + + module.exportFunction(prefix + "_add"); + module.exportFunction(prefix + "_sub"); + module.exportFunction(prefix + "_neg"); + module.exportFunction(prefix + "_isNegative"); + module.exportFunction(prefix + "_isOne"); + module.exportFunction(prefix + "_sign"); + module.exportFunction(prefix + "_mReduct"); + module.exportFunction(prefix + "_mul"); + module.exportFunction(prefix + "_square"); + module.exportFunction(prefix + "_squareOld"); + module.exportFunction(prefix + "_fromMontgomery"); + module.exportFunction(prefix + "_toMontgomery"); + module.exportFunction(prefix + "_inverse"); + module.exportFunction(prefix + "_one"); + module.exportFunction(prefix + "_load"); + module.exportFunction(prefix + "_timesScalar"); + buildExp$2( + module, + prefix + "_exp", + n8, + prefix + "_mul", + prefix + "_square", + intPrefix + "_copy", + prefix + "_one", + ); + module.exportFunction(prefix + "_exp"); + module.exportFunction(prefix + "_batchInverse"); + if (isPrime(q)) { + buildSqrt(); + buildIsSquare(); + module.exportFunction(prefix + "_sqrt"); + module.exportFunction(prefix + "_isSquare"); + } + module.exportFunction(prefix + "_batchToMontgomery"); + module.exportFunction(prefix + "_batchFromMontgomery"); + // console.log(module.functionIdxByName); + + return prefix; +}; + +/* + 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 buildF1m$2 =build_f1m; +const { bitLength: bitLength$3 } = bigint; + +var build_f1 = function buildF1(module, _q, _prefix, _f1mPrefix, _intPrefix) { + + const q = BigInt(_q); + const n64 = Math.floor((bitLength$3(q - 1n) - 1)/64) +1; + const n8 = n64*8; + + const prefix = _prefix || "f1"; + if (module.modules[prefix]) return prefix; // already builded + module.modules[prefix] = { + n64: n64 + }; + + const intPrefix = _intPrefix || "int"; + const f1mPrefix = buildF1m$2(module, q, _f1mPrefix, intPrefix); + + + const pR2 = module.modules[f1mPrefix].pR2; + const pq = module.modules[f1mPrefix].pq; + const pePlusOne = module.modules[f1mPrefix].pePlusOne; + + function buildMul() { + const pAux1 = module.alloc(n8); + + const f = module.addFunction(prefix+ "_mul"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + f.addCode(c.call(f1mPrefix + "_mul", c.getLocal("x"), c.getLocal("y"), c.i32_const(pAux1))); + f.addCode(c.call(f1mPrefix + "_mul", c.i32_const(pAux1), c.i32_const(pR2), c.getLocal("r"))); + } + + function buildSquare() { + const f = module.addFunction(prefix+"_square"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode(c.call(prefix + "_mul", c.getLocal("x"), c.getLocal("x"), c.getLocal("r"))); + } + + + function buildInverse() { + + const f = module.addFunction(prefix+ "_inverse"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + f.addCode(c.call(intPrefix + "_inverseMod", c.getLocal("x"), c.i32_const(pq), c.getLocal("r"))); + } + + function buildIsNegative() { + const f = module.addFunction(prefix+"_isNegative"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.call(intPrefix + "_gte", c.getLocal("x"), c.i32_const(pePlusOne) ) + ); + } + + + buildMul(); + buildSquare(); + buildInverse(); + buildIsNegative(); + module.exportFunction(f1mPrefix + "_add", prefix + "_add"); + module.exportFunction(f1mPrefix + "_sub", prefix + "_sub"); + module.exportFunction(f1mPrefix + "_neg", prefix + "_neg"); + module.exportFunction(prefix + "_mul"); + module.exportFunction(prefix + "_square"); + module.exportFunction(prefix + "_inverse"); + module.exportFunction(prefix + "_isNegative"); + module.exportFunction(f1mPrefix + "_copy", prefix+"_copy"); + module.exportFunction(f1mPrefix + "_zero", prefix+"_zero"); + module.exportFunction(f1mPrefix + "_one", prefix+"_one"); + module.exportFunction(f1mPrefix + "_isZero", prefix+"_isZero"); + module.exportFunction(f1mPrefix + "_eq", prefix+"_eq"); + + return prefix; +}; + +/* + 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 buildExp$1 = build_timesscalar; +const buildBatchInverse$1 = build_batchinverse; +const utils$4 = utils$6; + +var build_f2m = function buildF2m(module, mulNonResidueFn, prefix, f1mPrefix) { + + if (module.modules[prefix]) return prefix; // already builded + + const f1n8 = module.modules[f1mPrefix].n64*8; + const q = module.modules[f1mPrefix].q; + + module.modules[prefix] = { + n64: module.modules[f1mPrefix].n64*2 + }; + + function buildAdd() { + const f = module.addFunction(prefix+"_add"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const y0 = c.getLocal("y"); + const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_add", x0, y0, r0), + c.call(f1mPrefix+"_add", x1, y1, r1), + ); + } + + function buildTimesScalar() { + const f = module.addFunction(prefix+"_timesScalar"); + f.addParam("x", "i32"); + f.addParam("scalar", "i32"); + f.addParam("scalarLen", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_timesScalar", x0, c.getLocal("scalar"), c.getLocal("scalarLen"), r0), + c.call(f1mPrefix+"_timesScalar", x1, c.getLocal("scalar"), c.getLocal("scalarLen"), r1), + ); + } + + function buildSub() { + const f = module.addFunction(prefix+"_sub"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const y0 = c.getLocal("y"); + const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_sub", x0, y0, r0), + c.call(f1mPrefix+"_sub", x1, y1, r1), + ); + } + + function buildNeg() { + const f = module.addFunction(prefix+"_neg"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_neg", x0, r0), + c.call(f1mPrefix+"_neg", x1, r1), + ); + } + + function buildConjugate() { + const f = module.addFunction(prefix+"_conjugate"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_copy", x0, r0), + c.call(f1mPrefix+"_neg", x1, r1), + ); + } + + + function buildIsNegative() { + const f = module.addFunction(prefix+"_isNegative"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + + f.addCode( + c.if( + c.call(f1mPrefix+"_isZero", x1), + c.ret(c.call(f1mPrefix+"_isNegative", x0)) + ), + c.ret(c.call(f1mPrefix+"_isNegative", x1)) + ); + } + + function buildMul() { + const f = module.addFunction(prefix+"_mul"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const y0 = c.getLocal("y"); + const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + const A = c.i32_const(module.alloc(f1n8)); + const B = c.i32_const(module.alloc(f1n8)); + const C = c.i32_const(module.alloc(f1n8)); + const D = c.i32_const(module.alloc(f1n8)); + + + f.addCode( + c.call(f1mPrefix + "_mul", x0, y0, A), // A = x0*y0 + c.call(f1mPrefix + "_mul", x1, y1, B), // B = x1*y1 + + c.call(f1mPrefix + "_add", x0, x1, C), // C = x0 + x1 + c.call(f1mPrefix + "_add", y0, y1, D), // D = y0 + y1 + c.call(f1mPrefix + "_mul", C, D, C), // C = (x0 + x1)*(y0 + y1) = x0*y0+x0*y1+x1*y0+x1*y1 + + // c.call(f1mPrefix + "_mul", B, c.i32_const(pNonResidue), r0), // r0 = nr*(x1*y1) + c.call(mulNonResidueFn, B, r0), // r0 = nr*(x1*y1) + c.call(f1mPrefix + "_add", A, r0, r0), // r0 = x0*y0 + nr*(x1*y1) + c.call(f1mPrefix + "_add", A, B, r1), // r1 = x0*y0+x1*y1 + c.call(f1mPrefix + "_sub", C, r1, r1) // r1 = x0*y0+x0*y1+x1*y0+x1*y1 - x0*y0+x1*y1 = x0*y1+x1*y0 + ); + + } + + function buildMul1() { + const f = module.addFunction(prefix+"_mul1"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const y = c.getLocal("y"); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + + f.addCode( + c.call(f1mPrefix + "_mul", x0, y, r0), // A = x0*y + c.call(f1mPrefix + "_mul", x1, y, r1), // B = x1*y + ); + } + + function buildSquare() { + const f = module.addFunction(prefix+"_square"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + const AB = c.i32_const(module.alloc(f1n8)); + const APB = c.i32_const(module.alloc(f1n8)); + const APNB = c.i32_const(module.alloc(f1n8)); + const ABPNAB = c.i32_const(module.alloc(f1n8)); + + + f.addCode( + // AB = x0*y1 + c.call(f1mPrefix + "_mul", x0, x1, AB), + + // APB = x0+y1 + c.call(f1mPrefix + "_add", x0, x1, APB), + + // APBN0 = x0 + nr*x1 + c.call(mulNonResidueFn, x1, APNB), + c.call(f1mPrefix + "_add", x0, APNB, APNB), + + // ABPNAB = ab + nr*ab + c.call(mulNonResidueFn, AB, ABPNAB), + c.call(f1mPrefix + "_add", ABPNAB, AB, ABPNAB), + + // r0 = APB * APNB - ABPNAB + c.call(f1mPrefix + "_mul", APB, APNB, r0), + c.call(f1mPrefix + "_sub", r0, ABPNAB, r0), + + // r1 = AB + AB + c.call(f1mPrefix + "_add", AB, AB, r1), + ); + + } + + + function buildToMontgomery() { + const f = module.addFunction(prefix+"_toMontgomery"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_toMontgomery", x0, r0), + c.call(f1mPrefix+"_toMontgomery", x1, r1) + ); + } + + function buildFromMontgomery() { + const f = module.addFunction(prefix+"_fromMontgomery"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_fromMontgomery", x0, r0), + c.call(f1mPrefix+"_fromMontgomery", x1, r1) + ); + } + + function buildCopy() { + const f = module.addFunction(prefix+"_copy"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_copy", x0, r0), + c.call(f1mPrefix+"_copy", x1, r1) + ); + } + + function buildZero() { + const f = module.addFunction(prefix+"_zero"); + f.addParam("x", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_zero", x0), + c.call(f1mPrefix+"_zero", x1) + ); + } + + function buildOne() { + const f = module.addFunction(prefix+"_one"); + f.addParam("x", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_one", x0), + c.call(f1mPrefix+"_zero", x1) + ); + } + + function buildEq() { + const f = module.addFunction(prefix+"_eq"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const y0 = c.getLocal("y"); + const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); + + f.addCode( + c.i32_and( + c.call(f1mPrefix+"_eq", x0, y0), + c.call(f1mPrefix+"_eq", x1, y1) + ) + ); + } + + function buildIsZero() { + const f = module.addFunction(prefix+"_isZero"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + + f.addCode( + c.i32_and( + c.call(f1mPrefix+"_isZero", x0), + c.call(f1mPrefix+"_isZero", x1) + ) + ); + } + + function buildInverse() { + const f = module.addFunction(prefix+"_inverse"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + + const t0 = c.i32_const(module.alloc(f1n8)); + const t1 = c.i32_const(module.alloc(f1n8)); + const t2 = c.i32_const(module.alloc(f1n8)); + const t3 = c.i32_const(module.alloc(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_square", x0, t0), + c.call(f1mPrefix+"_square", x1, t1), + // c.call(f1mPrefix+"_mul", t1, c.i32_const(pNonResidue), t2), + c.call(mulNonResidueFn, t1, t2), + + c.call(f1mPrefix+"_sub", t0, t2, t2), + c.call(f1mPrefix+"_inverse", t2, t3), + + c.call(f1mPrefix+"_mul", x0, t3, r0), + c.call(f1mPrefix+"_mul", x1, t3, r1), + c.call(f1mPrefix+"_neg", r1, r1), + ); + } + + + function buildSign() { + const f = module.addFunction(prefix+"_sign"); + f.addParam("x", "i32"); + f.addLocal("s", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + + f.addCode( + c.setLocal("s" , c.call( f1mPrefix + "_sign", x1)), + c.if( + c.getLocal("s"), + c.ret(c.getLocal("s")) + ), + c.ret(c.call( f1mPrefix + "_sign", x0)) + ); + } + + function buildIsOne() { + const f = module.addFunction(prefix+"_isOne"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + + f.addCode( + c.ret(c.i32_and( + c.call(f1mPrefix + "_isOne", x0), + c.call(f1mPrefix + "_isZero", x1), + )) + ); + } + + + // Check here: https://eprint.iacr.org/2012/685.pdf + // Alg 9adj + function buildSqrt() { + + const f = module.addFunction(prefix+"_sqrt"); + f.addParam("a", "i32"); + f.addParam("pr", "i32"); + + const c = f.getCodeBuilder(); + + // BigInt can't take `undefined` so we use `|| 0` + const e34 = c.i32_const(module.alloc(utils$4.bigInt2BytesLE((BigInt(q || 0) - 3n) / 4n, f1n8 ))); + // BigInt can't take `undefined` so we use `|| 0` + const e12 = c.i32_const(module.alloc(utils$4.bigInt2BytesLE((BigInt(q || 0) - 1n) / 2n, f1n8 ))); + + const a = c.getLocal("a"); + const a1 = c.i32_const(module.alloc(f1n8*2)); + const alpha = c.i32_const(module.alloc(f1n8*2)); + const a0 = c.i32_const(module.alloc(f1n8*2)); + const pn1 = module.alloc(f1n8*2); + const n1 = c.i32_const(pn1); + const n1a = c.i32_const(pn1); + const n1b = c.i32_const(pn1+f1n8); + const x0 = c.i32_const(module.alloc(f1n8*2)); + const b = c.i32_const(module.alloc(f1n8*2)); + + f.addCode( + + c.call(prefix + "_one", n1), + c.call(prefix + "_neg", n1, n1), + + // const a1 = F.pow(a, F.sqrt_e34); + c.call(prefix + "_exp", a, e34, c.i32_const(f1n8), a1), + + // const a1 = F.pow(a, F.sqrt_e34); + c.call(prefix + "_square", a1, alpha), + c.call(prefix + "_mul", a, alpha, alpha), + + // const a0 = F.mul(F.frobenius(1, alfa), alfa); + c.call(prefix + "_conjugate", alpha, a0), + c.call(prefix + "_mul", a0, alpha, a0), + + // if (F.eq(a0, F.negone)) return null; + c.if(c.call(prefix + "_eq",a0,n1), c.unreachable() ), + + // const x0 = F.mul(a1, a); + c.call(prefix + "_mul", a1, a, x0), + + // if (F.eq(alfa, F.negone)) { + c.if( + c.call(prefix + "_eq", alpha, n1), + [ + // x = F.mul(x0, [F.F.zero, F.F.one]); + ...c.call(f1mPrefix + "_zero", n1a), + ...c.call(f1mPrefix + "_one", n1b), + ...c.call(prefix + "_mul", n1, x0, c.getLocal("pr")), + ], + [ + // const b = F.pow(F.add(F.one, alfa), F.sqrt_e12); + ...c.call(prefix + "_one", b), + ...c.call(prefix + "_add", b, alpha, b), + ...c.call(prefix + "_exp", b, e12, c.i32_const(f1n8), b), + + // x = F.mul(b, x0); + ...c.call(prefix + "_mul", b, x0, c.getLocal("pr")), + ] + ) + ); + + } + + + function buildIsSquare() { + + const f = module.addFunction(prefix+"_isSquare"); + f.addParam("a", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + // BigInt can't take `undefined` so we use `|| 0` + const e34 = c.i32_const(module.alloc(utils$4.bigInt2BytesLE((BigInt(q || 0) - 3n) / 4n, f1n8 ))); + + const a = c.getLocal("a"); + const a1 = c.i32_const(module.alloc(f1n8*2)); + const alpha = c.i32_const(module.alloc(f1n8*2)); + const a0 = c.i32_const(module.alloc(f1n8*2)); + const pn1 = module.alloc(f1n8*2); + const n1 = c.i32_const(pn1); + + f.addCode( + + c.call(prefix + "_one", n1), + c.call(prefix + "_neg", n1, n1), + + // const a1 = F.pow(a, F.sqrt_e34); + c.call(prefix + "_exp", a, e34, c.i32_const(f1n8), a1), + + // const a1 = F.pow(a, F.sqrt_e34); + c.call(prefix + "_square", a1, alpha), + c.call(prefix + "_mul", a, alpha, alpha), + + // const a0 = F.mul(F.frobenius(1, alfa), alfa); + c.call(prefix + "_conjugate", alpha, a0), + c.call(prefix + "_mul", a0, alpha, a0), + + // if (F.eq(a0, F.negone)) return null; + c.if( + c.call( + prefix + "_eq", + a0, + n1 + ), + c.ret(c.i32_const(0)) + ), + c.ret(c.i32_const(1)) + ); + + } + + + buildIsZero(); + buildIsOne(); + buildZero(); + buildOne(); + buildCopy(); + buildMul(); + buildMul1(); + buildSquare(); + buildAdd(); + buildSub(); + buildNeg(); + buildConjugate(); + buildToMontgomery(); + buildFromMontgomery(); + buildEq(); + buildInverse(); + buildTimesScalar(); + buildSign(); + buildIsNegative(); + + module.exportFunction(prefix + "_isZero"); + module.exportFunction(prefix + "_isOne"); + module.exportFunction(prefix + "_zero"); + module.exportFunction(prefix + "_one"); + module.exportFunction(prefix + "_copy"); + module.exportFunction(prefix + "_mul"); + module.exportFunction(prefix + "_mul1"); + module.exportFunction(prefix + "_square"); + module.exportFunction(prefix + "_add"); + module.exportFunction(prefix + "_sub"); + module.exportFunction(prefix + "_neg"); + module.exportFunction(prefix + "_sign"); + module.exportFunction(prefix + "_conjugate"); + module.exportFunction(prefix + "_fromMontgomery"); + module.exportFunction(prefix + "_toMontgomery"); + module.exportFunction(prefix + "_eq"); + module.exportFunction(prefix + "_inverse"); + buildBatchInverse$1(module, prefix); + buildExp$1( + module, + prefix + "_exp", + f1n8*2, + prefix + "_mul", + prefix + "_square", + prefix + "_copy", + prefix + "_one", + ); + buildSqrt(); + buildIsSquare(); + + module.exportFunction(prefix + "_exp"); + module.exportFunction(prefix + "_timesScalar"); + module.exportFunction(prefix + "_batchInverse"); + module.exportFunction(prefix + "_sqrt"); + module.exportFunction(prefix + "_isSquare"); + module.exportFunction(prefix + "_isNegative"); + + + return prefix; +}; + +/* + 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 buildExp = build_timesscalar; +const buildBatchInverse = build_batchinverse; + +var build_f3m = function buildF3m(module, mulNonResidueFn, prefix, f1mPrefix) { + + if (module.modules[prefix]) return prefix; // already builded + + const f1n8 = module.modules[f1mPrefix].n64*8; + module.modules[prefix] = { + n64: module.modules[f1mPrefix].n64*3 + }; + + function buildAdd() { + const f = module.addFunction(prefix+"_add"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const y0 = c.getLocal("y"); + const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); + const y2 = c.i32_add(c.getLocal("y"), c.i32_const(2*f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); + + f.addCode( + c.call(f1mPrefix+"_add", x0, y0, r0), + c.call(f1mPrefix+"_add", x1, y1, r1), + c.call(f1mPrefix+"_add", x2, y2, r2), + ); + } + + function buildTimesScalar() { + const f = module.addFunction(prefix+"_timesScalar"); + f.addParam("x", "i32"); + f.addParam("scalar", "i32"); + f.addParam("scalarLen", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); + + f.addCode( + c.call(f1mPrefix+"_timesScalar", x0, c.getLocal("scalar"), c.getLocal("scalarLen"), r0), + c.call(f1mPrefix+"_timesScalar", x1, c.getLocal("scalar"), c.getLocal("scalarLen"), r1), + c.call(f1mPrefix+"_timesScalar", x2, c.getLocal("scalar"), c.getLocal("scalarLen"), r2), + ); + } + + + function buildSub() { + const f = module.addFunction(prefix+"_sub"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const y0 = c.getLocal("y"); + const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); + const y2 = c.i32_add(c.getLocal("y"), c.i32_const(2*f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); + + f.addCode( + c.call(f1mPrefix+"_sub", x0, y0, r0), + c.call(f1mPrefix+"_sub", x1, y1, r1), + c.call(f1mPrefix+"_sub", x2, y2, r2), + ); + } + + function buildNeg() { + const f = module.addFunction(prefix+"_neg"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); + + f.addCode( + c.call(f1mPrefix+"_neg", x0, r0), + c.call(f1mPrefix+"_neg", x1, r1), + c.call(f1mPrefix+"_neg", x2, r2), + ); + } + + function buildIsNegative() { + const f = module.addFunction(prefix+"_isNegative"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + + f.addCode( + c.if( + c.call(f1mPrefix+"_isZero", x2), + c.if( + c.call(f1mPrefix+"_isZero", x1), + c.ret(c.call(f1mPrefix+"_isNegative", x0)), + c.ret(c.call(f1mPrefix+"_isNegative", x1)) + ) + ), + c.ret(c.call(f1mPrefix+"_isNegative", x2)) + ); + } + + + function buildMul() { + const f = module.addFunction(prefix+"_mul"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.addParam("r", "i32"); + + const cd = f.getCodeBuilder(); + + const a = cd.getLocal("x"); + const b = cd.i32_add(cd.getLocal("x"), cd.i32_const(f1n8)); + const c = cd.i32_add(cd.getLocal("x"), cd.i32_const(2*f1n8)); + const A = cd.getLocal("y"); + const B = cd.i32_add(cd.getLocal("y"), cd.i32_const(f1n8)); + const C = cd.i32_add(cd.getLocal("y"), cd.i32_const(2*f1n8)); + const r0 = cd.getLocal("r"); + const r1 = cd.i32_add(cd.getLocal("r"), cd.i32_const(f1n8)); + const r2 = cd.i32_add(cd.getLocal("r"), cd.i32_const(2*f1n8)); + + const aA = cd.i32_const(module.alloc(f1n8)); + const bB = cd.i32_const(module.alloc(f1n8)); + const cC = cd.i32_const(module.alloc(f1n8)); + const a_b = cd.i32_const(module.alloc(f1n8)); + const A_B = cd.i32_const(module.alloc(f1n8)); + const a_c = cd.i32_const(module.alloc(f1n8)); + const A_C = cd.i32_const(module.alloc(f1n8)); + const b_c = cd.i32_const(module.alloc(f1n8)); + const B_C = cd.i32_const(module.alloc(f1n8)); + const aA_bB = cd.i32_const(module.alloc(f1n8)); + const aA_cC = cd.i32_const(module.alloc(f1n8)); + const bB_cC = cd.i32_const(module.alloc(f1n8)); + const AUX = cd.i32_const(module.alloc(f1n8)); + + + f.addCode( + cd.call(f1mPrefix + "_mul", a, A, aA), + cd.call(f1mPrefix + "_mul", b, B, bB), + cd.call(f1mPrefix + "_mul", c, C, cC), + + cd.call(f1mPrefix + "_add", a, b, a_b), + cd.call(f1mPrefix + "_add", A, B, A_B), + cd.call(f1mPrefix + "_add", a, c, a_c), + cd.call(f1mPrefix + "_add", A, C, A_C), + cd.call(f1mPrefix + "_add", b, c, b_c), + cd.call(f1mPrefix + "_add", B, C, B_C), + + cd.call(f1mPrefix + "_add", aA, bB, aA_bB), + cd.call(f1mPrefix + "_add", aA, cC, aA_cC), + cd.call(f1mPrefix + "_add", bB, cC, bB_cC), + + cd.call(f1mPrefix + "_mul", b_c, B_C, r0), + cd.call(f1mPrefix + "_sub", r0, bB_cC, r0), + cd.call(mulNonResidueFn, r0, r0), + cd.call(f1mPrefix + "_add", aA, r0, r0), + + cd.call(f1mPrefix + "_mul", a_b, A_B, r1), + cd.call(f1mPrefix + "_sub", r1, aA_bB, r1), + cd.call(mulNonResidueFn, cC, AUX), + cd.call(f1mPrefix + "_add", r1, AUX, r1), + + cd.call(f1mPrefix + "_mul", a_c, A_C, r2), + cd.call(f1mPrefix + "_sub", r2, aA_cC, r2), + cd.call(f1mPrefix + "_add", r2, bB, r2), + ); + + } + + function buildSquare() { + const f = module.addFunction(prefix+"_square"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const A = c.getLocal("x"); + const B = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const C = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); + + const s0 = c.i32_const(module.alloc(f1n8)); + const ab = c.i32_const(module.alloc(f1n8)); + const s1 = c.i32_const(module.alloc(f1n8)); + const s2 = c.i32_const(module.alloc(f1n8)); + const bc = c.i32_const(module.alloc(f1n8)); + const s3 = c.i32_const(module.alloc(f1n8)); + const s4 = c.i32_const(module.alloc(f1n8)); + + + f.addCode( + + c.call(f1mPrefix + "_square", A, s0), + c.call(f1mPrefix + "_mul", A, B, ab), + c.call(f1mPrefix + "_add", ab, ab, s1), + + c.call(f1mPrefix + "_sub", A, B, s2), + c.call(f1mPrefix + "_add", s2, C, s2), + c.call(f1mPrefix + "_square", s2, s2), + + c.call(f1mPrefix + "_mul", B, C, bc), + c.call(f1mPrefix + "_add", bc, bc, s3), + + c.call(f1mPrefix + "_square", C, s4), + + c.call(mulNonResidueFn, s3, r0), + c.call(f1mPrefix + "_add", s0, r0, r0), + + c.call(mulNonResidueFn, s4, r1), + c.call(f1mPrefix + "_add", s1, r1, r1), + + c.call(f1mPrefix + "_add", s0, s4, r2), + c.call(f1mPrefix + "_sub", s3, r2, r2), + c.call(f1mPrefix + "_add", s2, r2, r2), + c.call(f1mPrefix + "_add", s1, r2, r2), + ); + + } + + + function buildToMontgomery() { + const f = module.addFunction(prefix+"_toMontgomery"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); + + f.addCode( + c.call(f1mPrefix+"_toMontgomery", x0, r0), + c.call(f1mPrefix+"_toMontgomery", x1, r1), + c.call(f1mPrefix+"_toMontgomery", x2, r2) + ); + } + + function buildFromMontgomery() { + const f = module.addFunction(prefix+"_fromMontgomery"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); + + f.addCode( + c.call(f1mPrefix+"_fromMontgomery", x0, r0), + c.call(f1mPrefix+"_fromMontgomery", x1, r1), + c.call(f1mPrefix+"_fromMontgomery", x2, r2) + ); + } + + function buildCopy() { + const f = module.addFunction(prefix+"_copy"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); + + f.addCode( + c.call(f1mPrefix+"_copy", x0, r0), + c.call(f1mPrefix+"_copy", x1, r1), + c.call(f1mPrefix+"_copy", x2, r2), + ); + } + + function buildZero() { + const f = module.addFunction(prefix+"_zero"); + f.addParam("x", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + + f.addCode( + c.call(f1mPrefix+"_zero", x0), + c.call(f1mPrefix+"_zero", x1), + c.call(f1mPrefix+"_zero", x2), + ); + } + + function buildOne() { + const f = module.addFunction(prefix+"_one"); + f.addParam("x", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + + f.addCode( + c.call(f1mPrefix+"_one", x0), + c.call(f1mPrefix+"_zero", x1), + c.call(f1mPrefix+"_zero", x2), + ); + } + + function buildEq() { + const f = module.addFunction(prefix+"_eq"); + f.addParam("x", "i32"); + f.addParam("y", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const y0 = c.getLocal("y"); + const y1 = c.i32_add(c.getLocal("y"), c.i32_const(f1n8)); + const y2 = c.i32_add(c.getLocal("y"), c.i32_const(2*f1n8)); + + f.addCode( + c.i32_and( + c.i32_and( + c.call(f1mPrefix+"_eq", x0, y0), + c.call(f1mPrefix+"_eq", x1, y1), + ), + c.call(f1mPrefix+"_eq", x2, y2) + ) + ); + } + + function buildIsZero() { + const f = module.addFunction(prefix+"_isZero"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + + f.addCode( + c.i32_and( + c.i32_and( + c.call(f1mPrefix+"_isZero", x0), + c.call(f1mPrefix+"_isZero", x1) + ), + c.call(f1mPrefix+"_isZero", x2) + ) + ); + } + + function buildInverse() { + const f = module.addFunction(prefix+"_inverse"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + const r0 = c.getLocal("r"); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(f1n8)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(2*f1n8)); + + const t0 = c.i32_const(module.alloc(f1n8)); + const t1 = c.i32_const(module.alloc(f1n8)); + const t2 = c.i32_const(module.alloc(f1n8)); + const t3 = c.i32_const(module.alloc(f1n8)); + const t4 = c.i32_const(module.alloc(f1n8)); + const t5 = c.i32_const(module.alloc(f1n8)); + const c0 = c.i32_const(module.alloc(f1n8)); + const c1 = c.i32_const(module.alloc(f1n8)); + const c2 = c.i32_const(module.alloc(f1n8)); + const t6 = c.i32_const(module.alloc(f1n8)); + const AUX = c.i32_const(module.alloc(f1n8)); + + f.addCode( + c.call(f1mPrefix+"_square", x0, t0), + c.call(f1mPrefix+"_square", x1, t1), + c.call(f1mPrefix+"_square", x2, t2), + c.call(f1mPrefix+"_mul", x0, x1, t3), + c.call(f1mPrefix+"_mul", x0, x2, t4), + c.call(f1mPrefix+"_mul", x1, x2, t5), + + c.call(mulNonResidueFn, t5, c0), + c.call(f1mPrefix+"_sub", t0, c0, c0), + + c.call(mulNonResidueFn, t2, c1), + c.call(f1mPrefix+"_sub", c1, t3, c1), + + c.call(f1mPrefix+"_sub", t1, t4, c2), + + c.call(f1mPrefix+"_mul", x2, c1, t6), + c.call(f1mPrefix+"_mul", x1, c2, AUX), + c.call(f1mPrefix+"_add", t6, AUX, t6), + c.call(mulNonResidueFn, t6, t6), + c.call(f1mPrefix+"_mul", x0, c0, AUX), + c.call(f1mPrefix+"_add", AUX, t6, t6), + + c.call(f1mPrefix+"_inverse", t6, t6), + + c.call(f1mPrefix+"_mul", t6, c0, r0), + c.call(f1mPrefix+"_mul", t6, c1, r1), + c.call(f1mPrefix+"_mul", t6, c2, r2) + ); + } + + + function buildSign() { + const f = module.addFunction(prefix+"_sign"); + f.addParam("x", "i32"); + f.addLocal("s", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(2*f1n8)); + + f.addCode( + c.setLocal("s" , c.call( f1mPrefix + "_sign", x2)), + c.if( + c.getLocal("s"), + c.ret(c.getLocal("s")) + ), + c.setLocal("s" , c.call( f1mPrefix + "_sign", x1)), + c.if( + c.getLocal("s"), + c.ret(c.getLocal("s")) + ), + c.ret(c.call( f1mPrefix + "_sign", x0)) + ); + } + + function buildIsOne() { + const f = module.addFunction(prefix+"_isOne"); + f.addParam("x", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(f1n8*2)); + + f.addCode( + c.ret( + c.i32_and( + c.i32_and( + c.call(f1mPrefix + "_isOne", x0), + c.call(f1mPrefix + "_isZero", x1) + ), + c.call(f1mPrefix + "_isZero", x2) + ) + ) + ); + } + + buildIsZero(); + buildIsOne(); + buildZero(); + buildOne(); + buildCopy(); + buildMul(); + buildSquare(); + buildAdd(); + buildSub(); + buildNeg(); + buildSign(); + buildToMontgomery(); + buildFromMontgomery(); + buildEq(); + buildInverse(); + buildTimesScalar(); + buildIsNegative(); + + module.exportFunction(prefix + "_isZero"); + module.exportFunction(prefix + "_isOne"); + module.exportFunction(prefix + "_zero"); + module.exportFunction(prefix + "_one"); + module.exportFunction(prefix + "_copy"); + module.exportFunction(prefix + "_mul"); + module.exportFunction(prefix + "_square"); + module.exportFunction(prefix + "_add"); + module.exportFunction(prefix + "_sub"); + module.exportFunction(prefix + "_neg"); + module.exportFunction(prefix + "_sign"); + module.exportFunction(prefix + "_fromMontgomery"); + module.exportFunction(prefix + "_toMontgomery"); + module.exportFunction(prefix + "_eq"); + module.exportFunction(prefix + "_inverse"); + buildBatchInverse(module, prefix); + buildExp( + module, + prefix + "_exp", + f1n8*3, + prefix + "_mul", + prefix + "_square", + prefix + "_copy", + prefix + "_one" + ); + module.exportFunction(prefix + "_exp"); + module.exportFunction(prefix + "_timesScalar"); + module.exportFunction(prefix + "_batchInverse"); + module.exportFunction(prefix + "_isNegative"); + + return prefix; +}; + +/* + 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 . +*/ + +var build_timesscalarnaf = function buildTimesScalarNAF(module, fnName, elementLen, opAB, opAA, opAmB, opCopy, opInit) { + + const f = module.addFunction(fnName); + f.addParam("base", "i32"); + f.addParam("scalar", "i32"); + f.addParam("scalarLength", "i32"); + f.addParam("r", "i32"); + f.addLocal("old0", "i32"); + f.addLocal("nbits", "i32"); + f.addLocal("i", "i32"); + f.addLocal("last", "i32"); + f.addLocal("cur", "i32"); + f.addLocal("carry", "i32"); + f.addLocal("p", "i32"); + + const c = f.getCodeBuilder(); + + const aux = c.i32_const(module.alloc(elementLen)); + + function getBit(IDX) { + return c.i32_and( + c.i32_shr_u( + c.i32_load( + c.i32_add( + c.getLocal("scalar"), + c.i32_and( + c.i32_shr_u( + IDX, + c.i32_const(3) + ), + c.i32_const(0xFFFFFFFC) + ) + ) + ), + c.i32_and( + IDX, + c.i32_const(0x1F) + ) + ), + c.i32_const(1) + ); + } + + function pushBit(b) { + return [ + ...c.i32_store8( + c.getLocal("p"), + c.i32_const(b) + ), + ...c.setLocal( + "p", + c.i32_add( + c.getLocal("p"), + c.i32_const(1) + ) + ) + ]; + } + + f.addCode( + c.if( + c.i32_eqz(c.getLocal("scalarLength")), + [ + ...c.call(opInit, c.getLocal("r")), + ...c.ret([]) + ] + ), + c.setLocal("nbits", c.i32_shl(c.getLocal("scalarLength"), c.i32_const(3))), + c.setLocal("old0", c.i32_load(c.i32_const(0))), + c.setLocal("p", c.getLocal("old0")), + c.i32_store( + c.i32_const(0), + c.i32_and( + c.i32_add( + c.i32_add( + c.getLocal("old0"), + c.i32_const(32) + ), + c.getLocal("nbits") + ), + c.i32_const(0xFFFFFFF8) + ) + ), + c.setLocal("i", c.i32_const(1)), + + c.setLocal("last",getBit(c.i32_const(0))), + c.setLocal("carry",c.i32_const(0)), + + c.block(c.loop( + c.br_if(1, c.i32_eq( c.getLocal("i"), c.getLocal("nbits"))), + + c.setLocal("cur", getBit(c.getLocal("i"))), + c.if( c.getLocal("last"), + c.if( c.getLocal("cur"), + c.if(c.getLocal("carry"), + [ + ...c.setLocal("last", c.i32_const(0)), + ...c.setLocal("carry", c.i32_const(1)), + ...pushBit(1) + ] + , + [ + ...c.setLocal("last", c.i32_const(0)), + ...c.setLocal("carry", c.i32_const(1)), + ...pushBit(255) + ], + ), + c.if(c.getLocal("carry"), + [ + ...c.setLocal("last", c.i32_const(0)), + ...c.setLocal("carry", c.i32_const(1)), + ...pushBit(255) + ] + , + [ + ...c.setLocal("last", c.i32_const(0)), + ...c.setLocal("carry", c.i32_const(0)), + ...pushBit(1) + ], + ), + ), + c.if( c.getLocal("cur"), + c.if(c.getLocal("carry"), + [ + ...c.setLocal("last", c.i32_const(0)), + ...c.setLocal("carry", c.i32_const(1)), + ...pushBit(0) + ] + , + [ + ...c.setLocal("last", c.i32_const(1)), + ...c.setLocal("carry", c.i32_const(0)), + ...pushBit(0) + ], + ), + c.if(c.getLocal("carry"), + [ + ...c.setLocal("last", c.i32_const(1)), + ...c.setLocal("carry", c.i32_const(0)), + ...pushBit(0) + ] + , + [ + ...c.setLocal("last", c.i32_const(0)), + ...c.setLocal("carry", c.i32_const(0)), + ...pushBit(0) + ], + ), + ) + ), + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )), + + c.if( c.getLocal("last"), + c.if(c.getLocal("carry"), + [ + ...pushBit(255), + ...pushBit(0), + ...pushBit(1) + ] + , + [ + ...pushBit(1) + ], + ), + c.if(c.getLocal("carry"), + [ + ...pushBit(0), + ...pushBit(1) + ] + ), + ), + + c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))), + + // p already points to the last bit + + c.call(opCopy, c.getLocal("base"), aux), + + c.call(opInit, c.getLocal("r")), + + c.block(c.loop( + + + c.call(opAA, c.getLocal("r"), c.getLocal("r")), + + + c.setLocal("cur", + c.i32_load8_u( + c.getLocal("p") + ) + ), + + c.if( + c.getLocal("cur"), + c.if( + c.i32_eq(c.getLocal("cur"), c.i32_const(1)), + c.call(opAB, c.getLocal("r"), aux, c.getLocal("r")), + c.call(opAmB, c.getLocal("r"), aux, c.getLocal("r")), + ) + ), + + c.br_if(1, c.i32_eq( c.getLocal("old0"), c.getLocal("p"))), + c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))), + c.br(0) + + )), + + c.i32_store( c.i32_const(0), c.getLocal("old0")) + + ); + +}; + +/* + 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 . +*/ + +var build_multiexp = function buildMultiexp(module, prefix, fnName, opAdd, n8b) { + + const n64g = module.modules[prefix].n64; + const n8g = n64g*8; + + function buildGetChunk() { + const f = module.addFunction(fnName + "_getChunk"); + f.addParam("pScalar", "i32"); + f.addParam("scalarSize", "i32"); // Number of bytes of the scalar + f.addParam("startBit", "i32"); // Bit to start extract + f.addParam("chunkSize", "i32"); // Chunk size in bits + f.addLocal("bitsToEnd", "i32"); + f.addLocal("mask", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.setLocal("bitsToEnd", + c.i32_sub( + c.i32_mul( + c.getLocal("scalarSize"), + c.i32_const(8) + ), + c.getLocal("startBit") + ) + ), + c.if( + c.i32_gt_s( + c.getLocal("chunkSize"), + c.getLocal("bitsToEnd") + ), + c.setLocal( + "mask", + c.i32_sub( + c.i32_shl( + c.i32_const(1), + c.getLocal("bitsToEnd") + ), + c.i32_const(1) + ) + ), + c.setLocal( + "mask", + c.i32_sub( + c.i32_shl( + c.i32_const(1), + c.getLocal("chunkSize") + ), + c.i32_const(1) + ) + ) + ), + c.i32_and( + c.i32_shr_u( + c.i32_load( + c.i32_add( + c.getLocal("pScalar"), + c.i32_shr_u( + c.getLocal("startBit"), + c.i32_const(3) + ) + ), + 0, // offset + 0 // align to byte. + ), + c.i32_and( + c.getLocal("startBit"), + c.i32_const(0x7) + ) + ), + c.getLocal("mask") + ) + ); + } + + function buildMutiexpChunk() { + const f = module.addFunction(fnName + "_chunk"); + f.addParam("pBases", "i32"); + f.addParam("pScalars", "i32"); + f.addParam("scalarSize", "i32"); // Number of points + f.addParam("n", "i32"); // Number of points + f.addParam("startBit", "i32"); // bit where it starts the chunk + f.addParam("chunkSize", "i32"); // bit where it starts the chunk + f.addParam("pr", "i32"); + f.addLocal("nChunks", "i32"); + f.addLocal("itScalar", "i32"); + f.addLocal("endScalar", "i32"); + f.addLocal("itBase", "i32"); + f.addLocal("i", "i32"); + f.addLocal("j", "i32"); + f.addLocal("nTable", "i32"); + f.addLocal("pTable", "i32"); + f.addLocal("idx", "i32"); + f.addLocal("pIdxTable", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.if( + c.i32_eqz(c.getLocal("n")), + [ + ...c.call(prefix + "_zero", c.getLocal("pr")), + ...c.ret([]) + ] + ), + + // Allocate memory + + c.setLocal( + "nTable", + c.i32_shl( + c.i32_const(1), + c.getLocal("chunkSize") + ) + ), + c.setLocal("pTable", c.i32_load( c.i32_const(0) )), + c.i32_store( + c.i32_const(0), + c.i32_add( + c.getLocal("pTable"), + c.i32_mul( + c.getLocal("nTable"), + c.i32_const(n8g) + ) + ) + ), + + // Reset Table + c.setLocal("j", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("j"), + c.getLocal("nTable") + ) + ), + + c.call( + prefix + "_zero", + c.i32_add( + c.getLocal("pTable"), + c.i32_mul( + c.getLocal("j"), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), + c.br(0) + )), + + // Distribute elements + c.setLocal("itBase", c.getLocal("pBases")), + c.setLocal("itScalar", c.getLocal("pScalars")), + c.setLocal("endScalar", + c.i32_add( + c.getLocal("pScalars"), + c.i32_mul( + c.getLocal("n"), + c.getLocal("scalarSize") + ) + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("itScalar"), + c.getLocal("endScalar") + ) + ), + + c.setLocal( + "idx", + c.call(fnName + "_getChunk", + c.getLocal("itScalar"), + c.getLocal("scalarSize"), + c.getLocal("startBit"), + c.getLocal("chunkSize") + ) + ), + + c.if( + c.getLocal("idx"), + [ + ...c.setLocal( + "pIdxTable", + c.i32_add( + c.getLocal("pTable"), + c.i32_mul( + c.i32_sub( + c.getLocal("idx"), + c.i32_const(1) + ), + c.i32_const(n8g) + ) + ) + ), + ...c.call( + opAdd, + c.getLocal("pIdxTable"), + c.getLocal("itBase"), + c.getLocal("pIdxTable"), + ) + ] + ), + + c.setLocal("itScalar", c.i32_add(c.getLocal("itScalar"), c.getLocal("scalarSize"))), + c.setLocal("itBase", c.i32_add(c.getLocal("itBase"), c.i32_const(n8b))), + c.br(0) + )), + + c.call(fnName + "_reduceTable", c.getLocal("pTable"), c.getLocal("chunkSize")), + c.call( + prefix + "_copy", + c.getLocal("pTable"), + c.getLocal("pr") + ), + + + c.i32_store( + c.i32_const(0), + c.getLocal("pTable") + ) + + ); + } + + function buildMultiexp() { + const f = module.addFunction(fnName); + f.addParam("pBases", "i32"); + f.addParam("pScalars", "i32"); + f.addParam("scalarSize", "i32"); // Number of points + f.addParam("n", "i32"); // Number of points + f.addParam("pr", "i32"); + f.addLocal("chunkSize", "i32"); + f.addLocal("nChunks", "i32"); + f.addLocal("itScalar", "i32"); + f.addLocal("endScalar", "i32"); + f.addLocal("itBase", "i32"); + f.addLocal("itBit", "i32"); + f.addLocal("i", "i32"); + f.addLocal("j", "i32"); + f.addLocal("nTable", "i32"); + f.addLocal("pTable", "i32"); + f.addLocal("idx", "i32"); + f.addLocal("pIdxTable", "i32"); + + const c = f.getCodeBuilder(); + + const aux = c.i32_const(module.alloc(n8g)); + + const pTSizes = module.alloc([ + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 16, 16, 15, 14, 13, 13, + 12, 11, 10, 9, 8, 7, 7, 6, + 5 , 4, 3, 2, 1, 1, 1, 1 + ]); + + f.addCode( + c.call(prefix + "_zero", c.getLocal("pr")), + c.if( + c.i32_eqz(c.getLocal("n")), + c.ret([]) + ), + c.setLocal("chunkSize", c.i32_load8_u( c.i32_clz(c.getLocal("n")), pTSizes )), + c.setLocal( + "nChunks", + c.i32_add( + c.i32_div_u( + c.i32_sub( + c.i32_shl( + c.getLocal("scalarSize"), + c.i32_const(3) + ), + c.i32_const(1) + ), + c.getLocal("chunkSize") + ), + c.i32_const(1) + ) + ), + + + // Allocate memory + + c.setLocal( + "itBit", + c.i32_mul( + c.i32_sub( + c.getLocal("nChunks"), + c.i32_const(1) + ), + c.getLocal("chunkSize") + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_lt_s( + c.getLocal("itBit"), + c.i32_const(0) + ) + ), + + // Double nChunk times + c.if( + c.i32_eqz(c.call(prefix + "_isZero", c.getLocal("pr"))), + [ + ...c.setLocal("j", c.i32_const(0)), + ...c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("j"), + c.getLocal("chunkSize") + ) + ), + + c.call(prefix + "_double", c.getLocal("pr"), c.getLocal("pr")), + + c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), + c.br(0) + )) + ] + ), + + c.call( + fnName + "_chunk", + c.getLocal("pBases"), + c.getLocal("pScalars"), + c.getLocal("scalarSize"), + c.getLocal("n"), + c.getLocal("itBit"), + c.getLocal("chunkSize"), + aux + ), + + c.call( + prefix + "_add", + c.getLocal("pr"), + aux, + c.getLocal("pr") + ), + c.setLocal("itBit", c.i32_sub(c.getLocal("itBit"), c.getLocal("chunkSize"))), + c.br(0) + )) + ); + } + + function buildReduceTable() { + const f = module.addFunction(fnName + "_reduceTable"); + f.addParam("pTable", "i32"); + f.addParam("p", "i32"); // Number of bits of the table + f.addLocal("half", "i32"); + f.addLocal("it1", "i32"); + f.addLocal("it2", "i32"); + f.addLocal("pAcc", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.if( + c.i32_eq(c.getLocal("p"), c.i32_const(1)), + c.ret([]) + ), + c.setLocal( + "half", + c.i32_shl( + c.i32_const(1), + c.i32_sub( + c.getLocal("p"), + c.i32_const(1) + ) + ) + ), + + c.setLocal("it1", c.getLocal("pTable")), + c.setLocal( + "it2", + c.i32_add( + c.getLocal("pTable"), + c.i32_mul( + c.getLocal("half"), + c.i32_const(n8g) + ) + ) + ), + c.setLocal("pAcc", + c.i32_sub( + c.getLocal("it2"), + c.i32_const(n8g) + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("it1"), + c.getLocal("pAcc") + ) + ), + c.call( + prefix + "_add", + c.getLocal("it1"), + c.getLocal("it2"), + c.getLocal("it1") + ), + c.call( + prefix + "_add", + c.getLocal("pAcc"), + c.getLocal("it2"), + c.getLocal("pAcc") + ), + c.setLocal("it1", c.i32_add(c.getLocal("it1"), c.i32_const(n8g))), + c.setLocal("it2", c.i32_add(c.getLocal("it2"), c.i32_const(n8g))), + c.br(0) + )), + + c.call( + fnName + "_reduceTable", + c.getLocal("pTable"), + c.i32_sub( + c.getLocal("p"), + c.i32_const(1) + ) + ), + + c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))), + c.block(c.loop( + c.br_if(1, c.i32_eqz(c.getLocal("p"))), + c.call(prefix + "_double", c.getLocal("pAcc"), c.getLocal("pAcc")), + c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))), + c.br(0) + )), + + c.call(prefix + "_add", c.getLocal("pTable"), c.getLocal("pAcc"), c.getLocal("pTable")) + ); + } + + buildGetChunk(); + buildReduceTable(); + buildMutiexpChunk(); + buildMultiexp(); + + module.exportFunction(fnName); + module.exportFunction(fnName +"_chunk"); + + +}; + +/* + 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 buildTimesScalarNAF = build_timesscalarnaf; +//const buildTimesScalar = require("./build_timesscalar"); +const buildBatchConvertion = build_batchconvertion; +const buildMultiexp$1 = build_multiexp; + +var build_curve_jacobian_a0 = function buildCurve(module, prefix, prefixField, pB) { + + + const n64 = module.modules[prefixField].n64; + const n8 = n64*8; + + if (module.modules[prefix]) return prefix; // already builded + module.modules[prefix] = { + n64: n64*3 + }; + + function buildIsZero() { + const f = module.addFunction(prefix + "_isZero"); + f.addParam("p1", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + f.addCode(c.call( + prefixField + "_isZero", + c.i32_add( + c.getLocal("p1"), + c.i32_const(n8*2) + ) + )); + } + function buildIsZeroAffine() { + const f = module.addFunction(prefix + "_isZeroAffine"); + f.addParam("p1", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.i32_and( + c.call( + prefixField + "_isZero", + c.getLocal("p1") + ), + c.call( + prefixField + "_isZero", + c.i32_add( + c.getLocal("p1"), + c.i32_const(n8) + ) + ) + ) + ); + } + + function buildCopy() { + const f = module.addFunction(prefix + "_copy"); + f.addParam("ps", "i32"); + f.addParam("pd", "i32"); + + const c = f.getCodeBuilder(); + + for (let i=0; i. +*/ + +const { isOdd: isOdd$2, modInv: modInv$1, modPow } = bigint; +const utils$3 = utils$6; + +var build_fft = function buildFFT(module, prefix, gPrefix, fPrefix, opGtimesF) { + + const n64f = module.modules[fPrefix].n64; + const n8f = n64f*8; + + const n64g = module.modules[gPrefix].n64; + const n8g = n64g*8; + + const q = module.modules[fPrefix].q; + + let rem = q - 1n; + let maxBits = 0; + while (!isOdd$2(rem)) { + maxBits ++; + rem = rem >> 1n; + } + + let nr = 2n; + + while ( modPow(nr, q >> 1n, q) === 1n ) nr = nr + 1n; + + // console.log(nr); + + const w = new Array(maxBits+1); + w[maxBits] = modPow(nr, rem, q); + + let n=maxBits-1; + while (n>=0) { + w[n] = modPow(w[n+1], 2n, q); + n--; + } + + const bytes = []; + const R = (1n << BigInt(n8f*8)) % q; + + for (let i=0; i> i); + } + } + return r; + } + + const rtable = Array(256); + for (let i=0; i<256; i++) { + rtable[i] = rev(i); + } + + const REVTABLE = module.alloc(rtable); + + + function buildLog2() { + const f = module.addFunction(prefix+"__log2"); + f.addParam("n", "i32"); + f.setReturnType("i32"); + f.addLocal("bits", "i32"); + f.addLocal("aux", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.setLocal( + "aux", + c.i32_shr_u( + c.getLocal("n"), + c.i32_const(1) + ) + ) + ); + f.addCode(c.setLocal("bits", c.i32_const(0))); + + f.addCode(c.block(c.loop( + c.br_if( + 1, + c.i32_eqz(c.getLocal("aux")) + ), + + c.setLocal( + "aux", + c.i32_shr_u( + c.getLocal("aux"), + c.i32_const(1) + ) + ), + + c.setLocal( + "bits", + c.i32_add( + c.getLocal("bits"), + c.i32_const(1) + ) + ), + + c.br(0) + ))); + + f.addCode(c.if( + c.i32_ne( + c.getLocal("n"), + c.i32_shl( + c.i32_const(1), + c.getLocal("bits") + ) + ), + c.unreachable() + )); + + f.addCode(c.if( + c.i32_gt_u( + c.getLocal("bits"), + c.i32_const(maxBits) + ), + c.unreachable() + )); + + f.addCode(c.getLocal("bits")); + } + + function buildFFT() { + const f = module.addFunction(prefix+"_fft"); + f.addParam("px", "i32"); + f.addParam("n", "i32"); + + f.addLocal("bits", "i32"); + + const c = f.getCodeBuilder(); + + const One = c.i32_const(module.alloc(n8f)); + + f.addCode( + c.setLocal( + "bits", + c.call( + prefix + "__log2", + c.getLocal("n") + ) + ), + c.call(fPrefix + "_one", One), + c.call( + prefix+"_rawfft", + c.getLocal("px"), + c.getLocal("bits"), + c.i32_const(0), + One + ) + ); + + } + + function buildIFFT() { + const f = module.addFunction(prefix+"_ifft"); + f.addParam("px", "i32"); + f.addParam("n", "i32"); + f.addLocal("bits", "i32"); + f.addLocal("pInv2", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.setLocal( + "bits", + c.call( + prefix + "__log2", + c.getLocal("n") + ) + ), + c.setLocal( + "pInv2", + c.i32_add( + c.i32_const(INV2), + c.i32_mul( + c.getLocal("bits"), + c.i32_const(n8f) + ) + ) + ), + + c.call( + prefix+"_rawfft", + c.getLocal("px"), + c.getLocal("bits"), + c.i32_const(1), + c.getLocal("pInv2") + ), + ); + } + + function buildRawFFT() { + const f = module.addFunction(prefix+"_rawfft"); + f.addParam("px", "i32"); + f.addParam("bits", "i32"); // 2 power + f.addParam("reverse", "i32"); + f.addParam("mulFactor", "i32"); + + f.addLocal("s", "i32"); + f.addLocal("k", "i32"); + f.addLocal("j", "i32"); + f.addLocal("m", "i32"); + f.addLocal("mdiv2", "i32"); + f.addLocal("n", "i32"); + f.addLocal("pwm", "i32"); + f.addLocal("idx1", "i32"); + f.addLocal("idx2", "i32"); + + const c = f.getCodeBuilder(); + + const W = c.i32_const(module.alloc(n8f)); + const T = c.i32_const(module.alloc(n8g)); + const U = c.i32_const(module.alloc(n8g)); + + f.addCode( + c.call(prefix + "__reversePermutation", c.getLocal("px"), c.getLocal("bits")), + c.setLocal("n", c.i32_shl(c.i32_const(1), c.getLocal("bits"))), + c.setLocal("s", c.i32_const(1)), + c.block(c.loop( + c.br_if( + 1, + c.i32_gt_u( + c.getLocal("s"), + c.getLocal("bits") + ) + ), + c.setLocal("m", c.i32_shl(c.i32_const(1), c.getLocal("s"))), + c.setLocal("pwm", + c.i32_add( + c.i32_const(ROOTs), + c.i32_mul( + c.getLocal("s"), + c.i32_const(n8f) + ) + ) + ), + c.setLocal("k", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_ge_u( + c.getLocal("k"), + c.getLocal("n") + ) + ), + + c.call(fPrefix + "_one", W), + + c.setLocal("mdiv2", c.i32_shr_u(c.getLocal("m"), c.i32_const(1)) ), + c.setLocal("j", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_ge_u( + c.getLocal("j"), + c.getLocal("mdiv2") + ) + ), + + c.setLocal( + "idx1", + c.i32_add( + c.getLocal("px"), + c.i32_mul( + c.i32_add( + c.getLocal("k"), + c.getLocal("j") + ), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal( + "idx2", + c.i32_add( + c.getLocal("idx1"), + c.i32_mul( + c.getLocal("mdiv2"), + c.i32_const(n8g) + ) + ) + ), + + c.call( + opGtimesF, + c.getLocal("idx2"), + W, + T + ), + + c.call( + gPrefix + "_copy", + c.getLocal("idx1"), + U + ), + + c.call( + gPrefix + "_add", + U, + T, + c.getLocal("idx1"), + ), + + c.call( + gPrefix + "_sub", + U, + T, + c.getLocal("idx2"), + ), + + c.call( + fPrefix + "_mul", + W, + c.getLocal("pwm"), + W, + ), + + c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), + c.br(0) + )), + + c.setLocal("k", c.i32_add(c.getLocal("k"), c.getLocal("m"))), + c.br(0) + )), + + c.setLocal("s", c.i32_add(c.getLocal("s"), c.i32_const(1))), + c.br(0) + )), + c.call( + prefix + "__fftFinal", + c.getLocal("px"), + c.getLocal("bits"), + c.getLocal("reverse"), + c.getLocal("mulFactor") + ) + ); + } + + + function buildFinalInverse() { + const f = module.addFunction(prefix+"__fftFinal"); + f.addParam("px", "i32"); + f.addParam("bits", "i32"); + f.addParam("reverse", "i32"); + f.addParam("mulFactor", "i32"); + f.addLocal("n", "i32"); + f.addLocal("ndiv2", "i32"); + f.addLocal("pInv2", "i32"); + f.addLocal("i", "i32"); + f.addLocal("mask", "i32"); + f.addLocal("idx1", "i32"); + f.addLocal("idx2", "i32"); + + const c = f.getCodeBuilder(); + + const T = c.i32_const(module.alloc(n8g)); + + f.addCode( + c.if( + c.i32_and( + c.i32_eqz(c.getLocal("reverse")), + c.call(fPrefix + "_isOne", c.getLocal("mulFactor")) + ), + c.ret([]) + ), + c.setLocal("n", c.i32_shl( c.i32_const(1), c.getLocal("bits"))), + + c.setLocal("mask", c.i32_sub( c.getLocal("n") , c.i32_const(1))), + c.setLocal("i", c.i32_const(1)), + c.setLocal( + "ndiv2", + c.i32_shr_u( + c.getLocal("n"), + c.i32_const(1) + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_ge_u( + c.getLocal("i"), + c.getLocal("ndiv2") + ) + ), + + c.setLocal("idx1", + c.i32_add( + c.getLocal("px"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal("idx2", + c.i32_add( + c.getLocal("px"), + c.i32_mul( + c.i32_sub( + c.getLocal("n"), + c.getLocal("i") + ), + c.i32_const(n8g) + ) + ) + ), + + c.if( + c.getLocal("reverse"), + c.if( + c.call(fPrefix + "_isOne", c.getLocal("mulFactor")), + [ + ...c.call(gPrefix + "_copy", c.getLocal("idx1"), T), + ...c.call(gPrefix + "_copy", c.getLocal("idx2") , c.getLocal("idx1") ), + ...c.call(gPrefix + "_copy", T , c.getLocal("idx2")), + ], + [ + ...c.call(gPrefix + "_copy", c.getLocal("idx1"), T), + ...c.call(opGtimesF , c.getLocal("idx2") , c.getLocal("mulFactor"), c.getLocal("idx1") ), + ...c.call(opGtimesF , T , c.getLocal("mulFactor"), c.getLocal("idx2")), + ] + ), + c.if( + c.call(fPrefix + "_isOne", c.getLocal("mulFactor")), + [ + // Do nothing (It should not be here) + ], + [ + ...c.call(opGtimesF , c.getLocal("idx1") , c.getLocal("mulFactor"), c.getLocal("idx1") ), + ...c.call(opGtimesF , c.getLocal("idx2") , c.getLocal("mulFactor"), c.getLocal("idx2")), + ] + ) + ), + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + + c.br(0) + )), + + c.if( + c.call(fPrefix + "_isOne", c.getLocal("mulFactor")), + [ + // Do nothing (It should not be here) + ], + [ + ...c.call(opGtimesF, c.getLocal("px") , c.getLocal("mulFactor"), c.getLocal("px")), + ...c.setLocal("idx2", + c.i32_add( + c.getLocal("px"), + c.i32_mul( + c.getLocal("ndiv2"), + c.i32_const(n8g) + ) + ) + ), + ...c.call(opGtimesF, c.getLocal("idx2"),c.getLocal("mulFactor"), c.getLocal("idx2")) + ] + ) + ); + } + + function buildReversePermutation() { + const f = module.addFunction(prefix+"__reversePermutation"); + f.addParam("px", "i32"); + f.addParam("bits", "i32"); + f.addLocal("n", "i32"); + f.addLocal("i", "i32"); + f.addLocal("ri", "i32"); + f.addLocal("idx1", "i32"); + f.addLocal("idx2", "i32"); + + const c = f.getCodeBuilder(); + + const T = c.i32_const(module.alloc(n8g)); + + f.addCode( + c.setLocal("n", c.i32_shl( c.i32_const(1), c.getLocal("bits"))), + c.setLocal("i", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("i"), + c.getLocal("n") + ) + ), + + c.setLocal("idx1", + c.i32_add( + c.getLocal("px"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal("ri", c.call(prefix + "__rev", c.getLocal("i"), c.getLocal("bits"))), + + c.setLocal("idx2", + c.i32_add( + c.getLocal("px"), + c.i32_mul( + c.getLocal("ri"), + c.i32_const(n8g) + ) + ) + ), + + c.if( + c.i32_lt_u( + c.getLocal("i"), + c.getLocal("ri") + ), + [ + ...c.call(gPrefix + "_copy", c.getLocal("idx1"), T), + ...c.call(gPrefix + "_copy", c.getLocal("idx2") , c.getLocal("idx1")), + ...c.call(gPrefix + "_copy", T , c.getLocal("idx2")) + ] + ), + + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + + c.br(0) + )) + ); + } + + function buildRev() { + const f = module.addFunction(prefix+"__rev"); + f.addParam("x", "i32"); + f.addParam("bits", "i32"); + f.setReturnType("i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.i32_rotl( + c.i32_add( + c.i32_add( + c.i32_shl( + c.i32_load8_u( + c.i32_and( + c.getLocal("x"), + c.i32_const(0xFF) + ), + REVTABLE, + 0 + ), + c.i32_const(24) + ), + c.i32_shl( + c.i32_load8_u( + c.i32_and( + c.i32_shr_u( + c.getLocal("x"), + c.i32_const(8) + ), + c.i32_const(0xFF) + ), + REVTABLE, + 0 + ), + c.i32_const(16) + ), + ), + c.i32_add( + c.i32_shl( + c.i32_load8_u( + c.i32_and( + c.i32_shr_u( + c.getLocal("x"), + c.i32_const(16) + ), + c.i32_const(0xFF) + ), + REVTABLE, + 0 + ), + c.i32_const(8) + ), + c.i32_load8_u( + c.i32_and( + c.i32_shr_u( + c.getLocal("x"), + c.i32_const(24) + ), + c.i32_const(0xFF) + ), + REVTABLE, + 0 + ), + ) + ), + c.getLocal("bits") + ) + ); + } + + + function buildFFTJoin() { + const f = module.addFunction(prefix+"_fftJoin"); + f.addParam("pBuff1", "i32"); + f.addParam("pBuff2", "i32"); + f.addParam("n", "i32"); + f.addParam("first", "i32"); + f.addParam("inc", "i32"); + f.addLocal("idx1", "i32"); + f.addLocal("idx2", "i32"); + f.addLocal("i", "i32"); + + const c = f.getCodeBuilder(); + + const W = c.i32_const(module.alloc(n8f)); + const T = c.i32_const(module.alloc(n8g)); + const U = c.i32_const(module.alloc(n8g)); + + f.addCode( + c.call( fPrefix + "_copy", c.getLocal("first"), W), + c.setLocal("i", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("i"), + c.getLocal("n") + ) + ), + + c.setLocal( + "idx1", + c.i32_add( + c.getLocal("pBuff1"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal( + "idx2", + c.i32_add( + c.getLocal("pBuff2"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.call( + opGtimesF, + c.getLocal("idx2"), + W, + T + ), + + c.call( + gPrefix + "_copy", + c.getLocal("idx1"), + U + ), + + c.call( + gPrefix + "_add", + U, + T, + c.getLocal("idx1"), + ), + + c.call( + gPrefix + "_sub", + U, + T, + c.getLocal("idx2"), + ), + + c.call( + fPrefix + "_mul", + W, + c.getLocal("inc"), + W, + ), + + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + } + + + function buildFFTJoinExt() { + const f = module.addFunction(prefix+"_fftJoinExt"); + f.addParam("pBuff1", "i32"); + f.addParam("pBuff2", "i32"); + f.addParam("n", "i32"); + f.addParam("first", "i32"); + f.addParam("inc", "i32"); + f.addParam("totalBits", "i32"); + f.addLocal("idx1", "i32"); + f.addLocal("idx2", "i32"); + f.addLocal("i", "i32"); + f.addLocal("pShiftToM", "i32"); + + const c = f.getCodeBuilder(); + + const W = c.i32_const(module.alloc(n8f)); + const U = c.i32_const(module.alloc(n8g)); + + f.addCode( + + c.setLocal("pShiftToM", + c.i32_add( + c.i32_const(SHIFT_TO_M), + c.i32_mul( + c.getLocal("totalBits"), + c.i32_const(n8f) + ) + ) + ), + + + c.call( fPrefix + "_copy", c.getLocal("first"), W), + c.setLocal("i", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("i"), + c.getLocal("n") + ) + ), + + c.setLocal( + "idx1", + c.i32_add( + c.getLocal("pBuff1"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal( + "idx2", + c.i32_add( + c.getLocal("pBuff2"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.call( + gPrefix + "_add", + c.getLocal("idx1"), + c.getLocal("idx2"), + U + ), + + c.call( + opGtimesF, + c.getLocal("idx2"), + c.getLocal("pShiftToM"), + c.getLocal("idx2") + ), + + c.call( + gPrefix + "_add", + c.getLocal("idx1"), + c.getLocal("idx2"), + c.getLocal("idx2") + ), + + c.call( + opGtimesF, + c.getLocal("idx2"), + W, + c.getLocal("idx2"), + ), + + c.call( + gPrefix + "_copy", + U, + c.getLocal("idx1") + ), + + c.call( + fPrefix + "_mul", + W, + c.getLocal("inc"), + W + ), + + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + } + + function buildFFTJoinExtInv() { + const f = module.addFunction(prefix+"_fftJoinExtInv"); + f.addParam("pBuff1", "i32"); + f.addParam("pBuff2", "i32"); + f.addParam("n", "i32"); + f.addParam("first", "i32"); + f.addParam("inc", "i32"); + f.addParam("totalBits", "i32"); + f.addLocal("idx1", "i32"); + f.addLocal("idx2", "i32"); + f.addLocal("i", "i32"); + f.addLocal("pShiftToM", "i32"); + f.addLocal("pSConst", "i32"); + + const c = f.getCodeBuilder(); + + const W = c.i32_const(module.alloc(n8f)); + const U = c.i32_const(module.alloc(n8g)); + + f.addCode( + + c.setLocal("pShiftToM", + c.i32_add( + c.i32_const(SHIFT_TO_M), + c.i32_mul( + c.getLocal("totalBits"), + c.i32_const(n8f) + ) + ) + ), + c.setLocal("pSConst", + c.i32_add( + c.i32_const(SCONST), + c.i32_mul( + c.getLocal("totalBits"), + c.i32_const(n8f) + ) + ) + ), + + + c.call( fPrefix + "_copy", c.getLocal("first"), W), + c.setLocal("i", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("i"), + c.getLocal("n") + ) + ), + + c.setLocal( + "idx1", + c.i32_add( + c.getLocal("pBuff1"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal( + "idx2", + c.i32_add( + c.getLocal("pBuff2"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.call( + opGtimesF, + c.getLocal("idx2"), + W, + U + ), + + c.call( + gPrefix + "_sub", + c.getLocal("idx1"), + U, + c.getLocal("idx2"), + ), + + c.call( + opGtimesF, + c.getLocal("idx2"), + c.getLocal("pSConst"), + c.getLocal("idx2") + ), + + c.call( + opGtimesF, + c.getLocal("idx1"), + c.getLocal("pShiftToM"), + c.getLocal("idx1") + ), + + c.call( + gPrefix + "_sub", + U, + c.getLocal("idx1"), + c.getLocal("idx1") + ), + + c.call( + opGtimesF, + c.getLocal("idx1"), + c.getLocal("pSConst"), + c.getLocal("idx1") + ), + + c.call( + fPrefix + "_mul", + W, + c.getLocal("inc"), + W + ), + + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + } + + + + function buildPrepareLagrangeEvaluation() { + const f = module.addFunction(prefix+"_prepareLagrangeEvaluation"); + f.addParam("pBuff1", "i32"); + f.addParam("pBuff2", "i32"); + f.addParam("n", "i32"); + f.addParam("first", "i32"); + f.addParam("inc", "i32"); + f.addParam("totalBits", "i32"); + f.addLocal("idx1", "i32"); + f.addLocal("idx2", "i32"); + f.addLocal("i", "i32"); + f.addLocal("pShiftToM", "i32"); + f.addLocal("pSConst", "i32"); + + const c = f.getCodeBuilder(); + + const W = c.i32_const(module.alloc(n8f)); + const U = c.i32_const(module.alloc(n8g)); + + f.addCode( + + c.setLocal("pShiftToM", + c.i32_add( + c.i32_const(SHIFT_TO_M), + c.i32_mul( + c.getLocal("totalBits"), + c.i32_const(n8f) + ) + ) + ), + c.setLocal("pSConst", + c.i32_add( + c.i32_const(SCONST), + c.i32_mul( + c.getLocal("totalBits"), + c.i32_const(n8f) + ) + ) + ), + + + c.call( fPrefix + "_copy", c.getLocal("first"), W), + c.setLocal("i", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("i"), + c.getLocal("n") + ) + ), + + c.setLocal( + "idx1", + c.i32_add( + c.getLocal("pBuff1"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal( + "idx2", + c.i32_add( + c.getLocal("pBuff2"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + + c.call( + opGtimesF, + c.getLocal("idx1"), + c.getLocal("pShiftToM"), + U + ), + + c.call( + gPrefix + "_sub", + c.getLocal("idx2"), + U, + U + ), + + c.call( + gPrefix + "_sub", + c.getLocal("idx1"), + c.getLocal("idx2"), + c.getLocal("idx2"), + ), + + c.call( + opGtimesF, + U, + c.getLocal("pSConst"), + c.getLocal("idx1"), + ), + + c.call( + opGtimesF, + c.getLocal("idx2"), + W, + c.getLocal("idx2"), + ), + + c.call( + fPrefix + "_mul", + W, + c.getLocal("inc"), + W + ), + + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + } + + function buildFFTMix() { + const f = module.addFunction(prefix+"_fftMix"); + f.addParam("pBuff", "i32"); + f.addParam("n", "i32"); + f.addParam("exp", "i32"); + f.addLocal("nGroups", "i32"); + f.addLocal("nPerGroup", "i32"); + f.addLocal("nPerGroupDiv2", "i32"); + f.addLocal("pairOffset", "i32"); + f.addLocal("idx1", "i32"); + f.addLocal("idx2", "i32"); + f.addLocal("i", "i32"); + f.addLocal("j", "i32"); + f.addLocal("pwm", "i32"); + + const c = f.getCodeBuilder(); + + const W = c.i32_const(module.alloc(n8f)); + const T = c.i32_const(module.alloc(n8g)); + const U = c.i32_const(module.alloc(n8g)); + + f.addCode( + c.setLocal("nPerGroup", c.i32_shl(c.i32_const(1), c.getLocal("exp"))), + c.setLocal("nPerGroupDiv2", c.i32_shr_u(c.getLocal("nPerGroup"), c.i32_const(1))), + c.setLocal("nGroups", c.i32_shr_u(c.getLocal("n"), c.getLocal("exp"))), + c.setLocal("pairOffset", c.i32_mul(c.getLocal("nPerGroupDiv2"), c.i32_const(n8g))), + c.setLocal("pwm", + c.i32_add( + c.i32_const(ROOTs), + c.i32_mul( + c.getLocal("exp"), + c.i32_const(n8f) + ) + ) + ), + c.setLocal("i", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("i"), + c.getLocal("nGroups") + ) + ), + c.call( fPrefix + "_one", W), + c.setLocal("j", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("j"), + c.getLocal("nPerGroupDiv2") + ) + ), + + c.setLocal( + "idx1", + c.i32_add( + c.getLocal("pBuff"), + c.i32_mul( + c.i32_add( + c.i32_mul( + c.getLocal("i"), + c.getLocal("nPerGroup") + ), + c.getLocal("j") + ), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal( + "idx2", + c.i32_add( + c.getLocal("idx1"), + c.getLocal("pairOffset") + ) + ), + + c.call( + opGtimesF, + c.getLocal("idx2"), + W, + T + ), + + c.call( + gPrefix + "_copy", + c.getLocal("idx1"), + U + ), + + c.call( + gPrefix + "_add", + U, + T, + c.getLocal("idx1"), + ), + + c.call( + gPrefix + "_sub", + U, + T, + c.getLocal("idx2"), + ), + + c.call( + fPrefix + "_mul", + W, + c.getLocal("pwm"), + W, + ), + c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), + c.br(0) + )), + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + } + + + // Reverse all and multiply by factor + function buildFFTFinal() { + const f = module.addFunction(prefix+"_fftFinal"); + f.addParam("pBuff", "i32"); + f.addParam("n", "i32"); + f.addParam("factor", "i32"); + f.addLocal("idx1", "i32"); + f.addLocal("idx2", "i32"); + f.addLocal("i", "i32"); + f.addLocal("ndiv2", "i32"); + + const c = f.getCodeBuilder(); + + const T = c.i32_const(module.alloc(n8g)); + + f.addCode( + c.setLocal("ndiv2", c.i32_shr_u(c.getLocal("n"), c.i32_const(1))), + c.if( + c.i32_and( + c.getLocal("n"), + c.i32_const(1) + ), + c.call( + opGtimesF, + c.i32_add( + c.getLocal("pBuff"), + c.i32_mul( + c.getLocal("ndiv2"), + c.i32_const(n8g) + ) + ), + c.getLocal("factor"), + c.i32_add( + c.getLocal("pBuff"), + c.i32_mul( + c.getLocal("ndiv2"), + c.i32_const(n8g) + ) + ), + ), + ), + c.setLocal("i", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_ge_u( + c.getLocal("i"), + c.getLocal("ndiv2") + ) + ), + + c.setLocal( + "idx1", + c.i32_add( + c.getLocal("pBuff"), + c.i32_mul( + c.getLocal("i"), + c.i32_const(n8g) + ) + ) + ), + + c.setLocal( + "idx2", + c.i32_add( + c.getLocal("pBuff"), + c.i32_mul( + c.i32_sub( + c.i32_sub( + c.getLocal("n"), + c.i32_const(1) + ), + c.getLocal("i") + ), + c.i32_const(n8g) + ) + ) + ), + + c.call( + opGtimesF, + c.getLocal("idx2"), + c.getLocal("factor"), + T + ), + + c.call( + opGtimesF, + c.getLocal("idx1"), + c.getLocal("factor"), + c.getLocal("idx2"), + ), + + c.call( + gPrefix + "_copy", + T, + c.getLocal("idx1"), + ), + + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + } + + buildRev(); + buildReversePermutation(); + buildFinalInverse(); + buildRawFFT(); + buildLog2(); + buildFFT(); + buildIFFT(); + buildFFTJoin(); + buildFFTJoinExt(); + buildFFTJoinExtInv(); + buildFFTMix(); + buildFFTFinal(); + buildPrepareLagrangeEvaluation(); + + module.exportFunction(prefix+"_fft"); + module.exportFunction(prefix+"_ifft"); + module.exportFunction(prefix+"_rawfft"); + module.exportFunction(prefix+"_fftJoin"); + module.exportFunction(prefix+"_fftJoinExt"); + module.exportFunction(prefix+"_fftJoinExtInv"); + module.exportFunction(prefix+"_fftMix"); + module.exportFunction(prefix+"_fftFinal"); + module.exportFunction(prefix+"_prepareLagrangeEvaluation"); + +}; + +/* + 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 . +*/ + +var build_pol = function buildPol(module, prefix, prefixField) { + + const n64 = module.modules[prefixField].n64; + const n8 = n64*8; + + + function buildZero() { + const f = module.addFunction(prefix+"_zero"); + f.addParam("px", "i32"); + f.addParam("n", "i32"); + f.addLocal("lastp", "i32"); + f.addLocal("p", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.setLocal("p", c.getLocal("px")), + c.setLocal( + "lastp", + c.i32_add( + c.getLocal("px"), + c.i32_mul( + c.getLocal("n"), + c.i32_const(n8) + ) + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("p"), + c.getLocal("lastp") + ) + ), + c.call(prefixField + "_zero", c.getLocal("p")), + c.setLocal("p", c.i32_add(c.getLocal("p"), c.i32_const(n8))), + c.br(0) + )) + ); + } + + function buildConstructLC() { + const f = module.addFunction(prefix+"_constructLC"); + f.addParam("ppolynomials", "i32"); + f.addParam("psignals", "i32"); + f.addParam("nSignals", "i32"); + f.addParam("pres", "i32"); + f.addLocal("i", "i32"); + f.addLocal("j", "i32"); + f.addLocal("pp", "i32"); + f.addLocal("ps", "i32"); + f.addLocal("pd", "i32"); + f.addLocal("ncoefs", "i32"); + + const c = f.getCodeBuilder(); + + const aux = c.i32_const(module.alloc(n8)); + + f.addCode( + c.setLocal("i", c.i32_const(0)), + c.setLocal("pp", c.getLocal("ppolynomials")), + c.setLocal("ps", c.getLocal("psignals")), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("i"), + c.getLocal("nSignals") + ) + ), + + c.setLocal("ncoefs", c.i32_load(c.getLocal("pp"))), + c.setLocal("pp", c.i32_add(c.getLocal("pp"), c.i32_const(4))), + + c.setLocal("j", c.i32_const(0)), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("j"), + c.getLocal("ncoefs") + ) + ), + + c.setLocal( + "pd", + c.i32_add( + c.getLocal("pres"), + c.i32_mul( + c.i32_load(c.getLocal("pp")), + c.i32_const(n8) + ) + ) + ), + + c.setLocal("pp", c.i32_add(c.getLocal("pp"), c.i32_const(4))), + + + c.call( + prefixField + "_mul", + c.getLocal("ps"), + c.getLocal("pp"), + aux + ), + + c.call( + prefixField + "_add", + aux, + c.getLocal("pd"), + c.getLocal("pd") + ), + + c.setLocal("pp", c.i32_add(c.getLocal("pp"), c.i32_const(n8))), + c.setLocal("j", c.i32_add(c.getLocal("j"), c.i32_const(1))), + c.br(0) + )), + + c.setLocal("ps", c.i32_add(c.getLocal("ps"), c.i32_const(n8))), + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + + } + + buildZero(); + buildConstructLC(); + + + module.exportFunction(prefix + "_zero"); + module.exportFunction(prefix + "_constructLC"); + + return prefix; + + + + +}; + +var build_qap = function buildQAP(module, prefix, prefixField) { + + const n64 = module.modules[prefixField].n64; + const n8 = n64*8; + + + function buildBuildABC() { + const f = module.addFunction(prefix+"_buildABC"); + f.addParam("pCoefs", "i32"); + f.addParam("nCoefs", "i32"); + f.addParam("pWitness", "i32"); + f.addParam("pA", "i32"); + f.addParam("pB", "i32"); + f.addParam("pC", "i32"); + f.addParam("offsetOut", "i32"); + f.addParam("nOut", "i32"); + f.addParam("offsetWitness", "i32"); + f.addParam("nWitness", "i32"); + f.addLocal("it", "i32"); + f.addLocal("ita", "i32"); + f.addLocal("itb", "i32"); + f.addLocal("last", "i32"); + f.addLocal("m", "i32"); + f.addLocal("c", "i32"); + f.addLocal("s", "i32"); + f.addLocal("pOut", "i32"); + + const c = f.getCodeBuilder(); + + const aux = c.i32_const(module.alloc(n8)); + + f.addCode( + + // Set output a and b to 0 + c.setLocal("ita", c.getLocal("pA")), + c.setLocal("itb", c.getLocal("pB")), + c.setLocal( + "last", + c.i32_add( + c.getLocal("pA"), + c.i32_mul( + c.getLocal("nOut"), + c.i32_const(n8) + ) + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("ita"), + c.getLocal("last") + ) + ), + c.call(prefixField + "_zero", c.getLocal("ita")), + c.call(prefixField + "_zero", c.getLocal("itb")), + c.setLocal("ita", c.i32_add(c.getLocal("ita"), c.i32_const(n8))), + c.setLocal("itb", c.i32_add(c.getLocal("itb"), c.i32_const(n8))), + c.br(0) + )), + + + c.setLocal("it", c.getLocal("pCoefs")), + c.setLocal( + "last", + c.i32_add( + c.getLocal("pCoefs"), + c.i32_mul( + c.getLocal("nCoefs"), + c.i32_const(n8+12) + ) + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("it"), + c.getLocal("last") + ) + ), + c.setLocal( + "s", + c.i32_load(c.getLocal("it"), 8) + ), + c.if( + c.i32_or( + c.i32_lt_u( + c.getLocal("s"), + c.getLocal("offsetWitness"), + ), + c.i32_ge_u( + c.getLocal("s"), + c.i32_add( + c.getLocal("offsetWitness"), + c.getLocal("nWitness"), + ) + ) + ), + [ + ...c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8+12))), + ...c.br(1) + ] + ), + + c.setLocal( + "m", + c.i32_load(c.getLocal("it")) + ), + c.if( + c.i32_eq(c.getLocal("m"), c.i32_const(0)), + c.setLocal("pOut", c.getLocal("pA")), + c.if( + c.i32_eq(c.getLocal("m"), c.i32_const(1)), + c.setLocal("pOut", c.getLocal("pB")), + [ + ...c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8+12))), + ...c.br(1) + ] + ) + ), + c.setLocal( + "c", + c.i32_load(c.getLocal("it"), 4) + ), + c.if( + c.i32_or( + c.i32_lt_u( + c.getLocal("c"), + c.getLocal("offsetOut"), + ), + c.i32_ge_u( + c.getLocal("c"), + c.i32_add( + c.getLocal("offsetOut"), + c.getLocal("nOut"), + ) + ) + ), + [ + ...c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8+12))), + ...c.br(1) + ] + ), + c.setLocal( + "pOut", + c.i32_add( + c.getLocal("pOut"), + c.i32_mul( + c.i32_sub( + c.getLocal("c"), + c.getLocal("offsetOut") + ), + c.i32_const(n8) + ) + ) + ), + c.call( + prefixField + "_mul", + c.i32_add( + c.getLocal("pWitness"), + c.i32_mul( + c.i32_sub(c.getLocal("s"), c.getLocal("offsetWitness")), + c.i32_const(n8) + ) + ), + c.i32_add( c.getLocal("it"), c.i32_const(12)), + aux + ), + c.call( + prefixField + "_add", + c.getLocal("pOut"), + aux, + c.getLocal("pOut"), + ), + c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8+12))), + c.br(0) + )), + + c.setLocal("ita", c.getLocal("pA")), + c.setLocal("itb", c.getLocal("pB")), + c.setLocal("it", c.getLocal("pC")), + c.setLocal( + "last", + c.i32_add( + c.getLocal("pA"), + c.i32_mul( + c.getLocal("nOut"), + c.i32_const(n8) + ) + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("ita"), + c.getLocal("last") + ) + ), + c.call( + prefixField + "_mul", + c.getLocal("ita"), + c.getLocal("itb"), + c.getLocal("it") + ), + c.setLocal("ita", c.i32_add(c.getLocal("ita"), c.i32_const(n8))), + c.setLocal("itb", c.i32_add(c.getLocal("itb"), c.i32_const(n8))), + c.setLocal("it", c.i32_add(c.getLocal("it"), c.i32_const(n8))), + c.br(0) + )), + + ); + } + + function buildJoinABC() { + const f = module.addFunction(prefix+"_joinABC"); + f.addParam("pA", "i32"); + f.addParam("pB", "i32"); + f.addParam("pC", "i32"); + f.addParam("n", "i32"); + f.addParam("pP", "i32"); + f.addLocal("ita", "i32"); + f.addLocal("itb", "i32"); + f.addLocal("itc", "i32"); + f.addLocal("itp", "i32"); + f.addLocal("last", "i32"); + + const c = f.getCodeBuilder(); + + const aux = c.i32_const(module.alloc(n8)); + + f.addCode( + c.setLocal("ita", c.getLocal("pA")), + c.setLocal("itb", c.getLocal("pB")), + c.setLocal("itc", c.getLocal("pC")), + c.setLocal("itp", c.getLocal("pP")), + c.setLocal( + "last", + c.i32_add( + c.getLocal("pA"), + c.i32_mul( + c.getLocal("n"), + c.i32_const(n8) + ) + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("ita"), + c.getLocal("last") + ) + ), + c.call( + prefixField + "_mul", + c.getLocal("ita"), + c.getLocal("itb"), + aux + ), + c.call( + prefixField + "_sub", + aux, + c.getLocal("itc"), + c.getLocal("itp"), + ), + c.setLocal("ita", c.i32_add(c.getLocal("ita"), c.i32_const(n8))), + c.setLocal("itb", c.i32_add(c.getLocal("itb"), c.i32_const(n8))), + c.setLocal("itc", c.i32_add(c.getLocal("itc"), c.i32_const(n8))), + c.setLocal("itp", c.i32_add(c.getLocal("itp"), c.i32_const(n8))), + c.br(0) + )) + ); + } + + function buildBatchAdd() { + const f = module.addFunction(prefix+"_batchAdd"); + f.addParam("pa", "i32"); + f.addParam("pb", "i32"); + f.addParam("n", "i32"); + f.addParam("pr", "i32"); + f.addLocal("ita", "i32"); + f.addLocal("itb", "i32"); + f.addLocal("itr", "i32"); + f.addLocal("last", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.setLocal("ita", c.getLocal("pa")), + c.setLocal("itb", c.getLocal("pb")), + c.setLocal("itr", c.getLocal("pr")), + c.setLocal( + "last", + c.i32_add( + c.getLocal("pa"), + c.i32_mul( + c.getLocal("n"), + c.i32_const(n8) + ) + ) + ), + c.block(c.loop( + c.br_if( + 1, + c.i32_eq( + c.getLocal("ita"), + c.getLocal("last") + ) + ), + c.call( + prefixField + "_add", + c.getLocal("ita"), + c.getLocal("itb"), + c.getLocal("itr"), + ), + c.setLocal("ita", c.i32_add(c.getLocal("ita"), c.i32_const(n8))), + c.setLocal("itb", c.i32_add(c.getLocal("itb"), c.i32_const(n8))), + c.setLocal("itr", c.i32_add(c.getLocal("itr"), c.i32_const(n8))), + c.br(0) + )) + ); + } + + buildBuildABC(); + buildJoinABC(); + buildBatchAdd(); + + module.exportFunction(prefix + "_buildABC"); + module.exportFunction(prefix + "_joinABC"); + module.exportFunction(prefix + "_batchAdd"); + + return prefix; + +}; + +/* + 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 . +*/ + +var build_applykey = function buildApplyKey(module, fnName, gPrefix, frPrefix, sizeGIn, sizeGOut, sizeF, opGtimesF) { + + const f = module.addFunction(fnName); + f.addParam("pIn", "i32"); + f.addParam("n", "i32"); + f.addParam("pFirst", "i32"); + f.addParam("pInc", "i32"); + f.addParam("pOut", "i32"); + f.addLocal("pOldFree", "i32"); + f.addLocal("i", "i32"); + f.addLocal("pFrom", "i32"); + f.addLocal("pTo", "i32"); + + const c = f.getCodeBuilder(); + + const t = c.i32_const(module.alloc(sizeF)); + + f.addCode( + c.setLocal("pFrom", c.getLocal("pIn")), + c.setLocal("pTo", c.getLocal("pOut")), + ); + + // t = first + f.addCode( + c.call( + frPrefix + "_copy", + c.getLocal("pFirst"), + t + ) + ); + f.addCode( + c.setLocal("i", c.i32_const(0)), + c.block(c.loop( + c.br_if(1, c.i32_eq ( c.getLocal("i"), c.getLocal("n") )), + + c.call( + opGtimesF, + c.getLocal("pFrom"), + t, + c.getLocal("pTo") + ), + c.setLocal("pFrom", c.i32_add(c.getLocal("pFrom"), c.i32_const(sizeGIn))), + c.setLocal("pTo", c.i32_add(c.getLocal("pTo"), c.i32_const(sizeGOut))), + + // t = t* inc + c.call( + frPrefix + "_mul", + t, + c.getLocal("pInc"), + t + ), + c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + + module.exportFunction(fnName); + +}; + +const utils$2 = utils$6; + +const buildF1m$1 =build_f1m; +const buildF1$1 =build_f1; +const buildF2m$1 =build_f2m; +const buildF3m$1 =build_f3m; +const buildCurve$1 =build_curve_jacobian_a0; +const buildFFT$2 = build_fft; +const buildPol$1 = build_pol; +const buildQAP$1 = build_qap; +const buildApplyKey$1 = build_applykey; +const { bitLength: bitLength$2, modInv, isOdd: isOdd$1, isNegative: isNegative$2 } = bigint; + +var build_bn128 = function buildBN128(module, _prefix) { + + const prefix = _prefix || "bn128"; + + if (module.modules[prefix]) return prefix; // already builded + + const q = 21888242871839275222246405745257275088696311157297823662689037894645226208583n; + const r = 21888242871839275222246405745257275088548364400416034343698204186575808495617n; + + + const n64 = Math.floor((bitLength$2(q - 1n) - 1)/64) +1; + const n8 = n64*8; + const frsize = n8; + const f1size = n8; + const f2size = f1size * 2; + const ftsize = f1size * 12; + + const pr = module.alloc(utils$2.bigInt2BytesLE( r, frsize )); + + const f1mPrefix = buildF1m$1(module, q, "f1m"); + buildF1$1(module, r, "fr", "frm"); + + const pG1b = module.alloc(utils$2.bigInt2BytesLE( toMontgomery(3n), f1size )); + const g1mPrefix = buildCurve$1(module, "g1m", "f1m", pG1b); + + buildFFT$2(module, "frm", "frm", "frm", "frm_mul"); + + buildPol$1(module, "pol", "frm"); + buildQAP$1(module, "qap", "frm"); + + const f2mPrefix = buildF2m$1(module, "f1m_neg", "f2m", "f1m"); + const pG2b = module.alloc([ + ...utils$2.bigInt2BytesLE( toMontgomery(19485874751759354771024239261021720505790618469301721065564631296452457478373n), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(266929791119991161246907387137283842545076965332900288569378510910307636690n), f1size ) + ]); + const g2mPrefix = buildCurve$1(module, "g2m", "f2m", pG2b); + + + function buildGTimesFr(fnName, opMul) { + const f = module.addFunction(fnName); + f.addParam("pG", "i32"); + f.addParam("pFr", "i32"); + f.addParam("pr", "i32"); + + const c = f.getCodeBuilder(); + + const AUX = c.i32_const(module.alloc(n8)); + + f.addCode( + c.call("frm_fromMontgomery", c.getLocal("pFr"), AUX), + c.call( + opMul, + c.getLocal("pG"), + AUX, + c.i32_const(n8), + c.getLocal("pr") + ) + ); + + module.exportFunction(fnName); + } + buildGTimesFr("g1m_timesFr", "g1m_timesScalar"); + buildFFT$2(module, "g1m", "g1m", "frm", "g1m_timesFr"); + + buildGTimesFr("g2m_timesFr", "g2m_timesScalar"); + buildFFT$2(module, "g2m", "g2m", "frm", "g2m_timesFr"); + + buildGTimesFr("g1m_timesFrAffine", "g1m_timesScalarAffine"); + buildGTimesFr("g2m_timesFrAffine", "g2m_timesScalarAffine"); + + buildApplyKey$1(module, "frm_batchApplyKey", "fmr", "frm", n8, n8, n8, "frm_mul"); + buildApplyKey$1(module, "g1m_batchApplyKey", "g1m", "frm", n8*3, n8*3, n8, "g1m_timesFr"); + buildApplyKey$1(module, "g1m_batchApplyKeyMixed", "g1m", "frm", n8*2, n8*3, n8, "g1m_timesFrAffine"); + buildApplyKey$1(module, "g2m_batchApplyKey", "g2m", "frm", n8*2*3, n8*3*2, n8, "g2m_timesFr"); + buildApplyKey$1(module, "g2m_batchApplyKeyMixed", "g2m", "frm", n8*2*2, n8*3*2, n8, "g2m_timesFrAffine"); + + function toMontgomery(a) { + return BigInt(a) * ( 1n << BigInt(f1size*8)) % q; + } + + const G1gen = [ + 1n, + 2n, + 1n + ]; + + const pG1gen = module.alloc( + [ + ...utils$2.bigInt2BytesLE( toMontgomery(G1gen[0]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G1gen[1]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G1gen[2]), f1size ), + ] + ); + + const G1zero = [ + 0n, + 1n, + 0n + ]; + + const pG1zero = module.alloc( + [ + ...utils$2.bigInt2BytesLE( toMontgomery(G1zero[0]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G1zero[1]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G1zero[2]), f1size ) + ] + ); + + const G2gen = [ + [ + 10857046999023057135944570762232829481370756359578518086990519993285655852781n, + 11559732032986387107991004021392285783925812861821192530917403151452391805634n, + ],[ + 8495653923123431417604973247489272438418190587263600148770280649306958101930n, + 4082367875863433681332203403145435568316851327593401208105741076214120093531n, + ],[ + 1n, + 0n, + ] + ]; + + const pG2gen = module.alloc( + [ + ...utils$2.bigInt2BytesLE( toMontgomery(G2gen[0][0]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2gen[0][1]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2gen[1][0]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2gen[1][1]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2gen[2][0]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2gen[2][1]), f1size ), + ] + ); + + const G2zero = [ + [ + 0n, + 0n, + ],[ + 1n, + 0n, + ],[ + 0n, + 0n, + ] + ]; + + const pG2zero = module.alloc( + [ + ...utils$2.bigInt2BytesLE( toMontgomery(G2zero[0][0]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2zero[0][1]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2zero[1][0]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2zero[1][1]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2zero[2][0]), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(G2zero[2][1]), f1size ), + ] + ); + + const pOneT = module.alloc([ + ...utils$2.bigInt2BytesLE( toMontgomery(1), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(0), f1size ), + ]); + + const pNonResidueF6 = module.alloc([ + ...utils$2.bigInt2BytesLE( toMontgomery(9), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(1), f1size ), + ]); + + const pTwoInv = module.alloc([ + ...utils$2.bigInt2BytesLE( toMontgomery( modInv(2n, q)), f1size ), + ...utils$2.bigInt2BytesLE( 0n, f1size ) + ]); + + const pAltBn128Twist = pNonResidueF6; + + const pTwistCoefB = module.alloc([ + ...utils$2.bigInt2BytesLE( toMontgomery(19485874751759354771024239261021720505790618469301721065564631296452457478373n), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery(266929791119991161246907387137283842545076965332900288569378510910307636690n), f1size ), + ]); + + function build_mulNR6() { + const f = module.addFunction(prefix + "_mulNR6"); + f.addParam("x", "i32"); + f.addParam("pr", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.call( + f2mPrefix + "_mul", + c.i32_const(pNonResidueF6), + c.getLocal("x"), + c.getLocal("pr") + ) + ); + } + build_mulNR6(); + + const f6mPrefix = buildF3m$1(module, prefix+"_mulNR6", "f6m", "f2m"); + + function build_mulNR12() { + const f = module.addFunction(prefix + "_mulNR12"); + f.addParam("x", "i32"); + f.addParam("pr", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.call( + f2mPrefix + "_mul", + c.i32_const(pNonResidueF6), + c.i32_add(c.getLocal("x"), c.i32_const(n8*4)), + c.getLocal("pr") + ), + c.call( + f2mPrefix + "_copy", + c.getLocal("x"), + c.i32_add(c.getLocal("pr"), c.i32_const(n8*2)), + ), + c.call( + f2mPrefix + "_copy", + c.i32_add(c.getLocal("x"), c.i32_const(n8*2)), + c.i32_add(c.getLocal("pr"), c.i32_const(n8*4)), + ) + ); + } + build_mulNR12(); + + const ftmPrefix = buildF2m$1(module, prefix+"_mulNR12", "ftm", f6mPrefix); + + + const ateLoopCount = 29793968203157093288n; + const ateLoopBitBytes = bits(ateLoopCount); + const pAteLoopBitBytes = module.alloc(ateLoopBitBytes); + + const ateCoefSize = 3 * f2size; + const ateNDblCoefs = ateLoopBitBytes.length-1; + const ateNAddCoefs = ateLoopBitBytes.reduce((acc, b) => acc + ( b!=0 ? 1 : 0) ,0); + const ateNCoefs = ateNAddCoefs + ateNDblCoefs + 1; + const prePSize = 3*2*n8; + const preQSize = 3*n8*2 + ateNCoefs*ateCoefSize; + + + module.modules[prefix] = { + n64: n64, + pG1gen: pG1gen, + pG1zero: pG1zero, + pG1b: pG1b, + pG2gen: pG2gen, + pG2zero: pG2zero, + pG2b: pG2b, + pq: module.modules["f1m"].pq, + pr: pr, + pOneT: pOneT, + prePSize: prePSize, + preQSize: preQSize, + r: r.toString(), + q: q.toString() + }; + + // console.log("PrePSize: " +prePSize); + // console.log("PreQSize: " +preQSize); + + const finalExpZ = 4965661367192848881n; + + function naf(n) { + let E = n; + const res = []; + while (E > 0n) { + if (isOdd$1(E)) { + const z = 2 - Number(E % 4n); + res.push( z ); + E = E - BigInt(z); + } else { + res.push( 0 ); + } + E = E >> 1n; + } + return res; + } + + function bits(n) { + let E = n; + const res = []; + while (E > 0n) { + if (isOdd$1(E)) { + res.push( 1 ); + } else { + res.push( 0 ); + } + E = E >> 1n; + } + return res; + } + + function buildPrepareG1() { + const f = module.addFunction(prefix+ "_prepareG1"); + f.addParam("pP", "i32"); + f.addParam("ppreP", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.call(g1mPrefix + "_normalize", c.getLocal("pP"), c.getLocal("ppreP")), // TODO Remove if already in affine + ); + } + + function buildPrepAddStep() { + const f = module.addFunction(prefix+ "_prepAddStep"); + f.addParam("pQ", "i32"); + f.addParam("pR", "i32"); + f.addParam("pCoef", "i32"); + + const c = f.getCodeBuilder(); + + const X2 = c.getLocal("pQ"); + const Y2 = c.i32_add(c.getLocal("pQ"), c.i32_const(f2size)); + + const X1 = c.getLocal("pR"); + const Y1 = c.i32_add(c.getLocal("pR"), c.i32_const(f2size)); + const Z1 = c.i32_add(c.getLocal("pR"), c.i32_const(2*f2size)); + + const ELL_0 = c.getLocal("pCoef"); + const ELL_VW = c.i32_add(c.getLocal("pCoef"), c.i32_const(f2size)); + const ELL_VV = c.i32_add(c.getLocal("pCoef"), c.i32_const(2*f2size)); + + const D = ELL_VW; + const E = c.i32_const(module.alloc(f2size)); + const F = c.i32_const(module.alloc(f2size)); + const G = c.i32_const(module.alloc(f2size)); + const H = c.i32_const(module.alloc(f2size)); + const I = c.i32_const(module.alloc(f2size)); + const J = c.i32_const(module.alloc(f2size)); + const AUX = c.i32_const(module.alloc(f2size)); + + f.addCode( + // D = X1 - X2*Z1 + c.call(f2mPrefix + "_mul", X2, Z1, D), + c.call(f2mPrefix + "_sub", X1, D, D), + + // E = Y1 - Y2*Z1 + c.call(f2mPrefix + "_mul", Y2, Z1, E), + c.call(f2mPrefix + "_sub", Y1, E, E), + + // F = D^2 + c.call(f2mPrefix + "_square", D, F), + + // G = E^2 + c.call(f2mPrefix + "_square", E, G), + + // H = D*F + c.call(f2mPrefix + "_mul", D, F, H), + + // I = X1 * F + c.call(f2mPrefix + "_mul", X1, F, I), + + // J = H + Z1*G - (I+I) + c.call(f2mPrefix + "_add", I, I, AUX), + c.call(f2mPrefix + "_mul", Z1, G, J), + c.call(f2mPrefix + "_add", H, J, J), + c.call(f2mPrefix + "_sub", J, AUX, J), + + + // X3 (X1) = D*J + c.call(f2mPrefix + "_mul", D, J, X1), + + // Y3 (Y1) = E*(I-J)-(H*Y1) + c.call(f2mPrefix + "_mul", H, Y1, Y1), + c.call(f2mPrefix + "_sub", I, J, AUX), + c.call(f2mPrefix + "_mul", E, AUX, AUX), + c.call(f2mPrefix + "_sub", AUX, Y1, Y1), + + // Z3 (Z1) = Z1*H + c.call(f2mPrefix + "_mul", Z1, H, Z1), + + // ell_0 = xi * (E * X2 - D * Y2) + c.call(f2mPrefix + "_mul", D, Y2, AUX), + c.call(f2mPrefix + "_mul", E, X2, ELL_0), + c.call(f2mPrefix + "_sub", ELL_0, AUX, ELL_0), + c.call(f2mPrefix + "_mul", ELL_0, c.i32_const(pAltBn128Twist), ELL_0), + + + // ell_VV = - E (later: * xP) + c.call(f2mPrefix + "_neg", E, ELL_VV), + + // ell_VW = D (later: * yP ) + // Already assigned + + ); + } + + + + function buildPrepDoubleStep() { + const f = module.addFunction(prefix+ "_prepDblStep"); + f.addParam("pR", "i32"); + f.addParam("pCoef", "i32"); + + const c = f.getCodeBuilder(); + + const X1 = c.getLocal("pR"); + const Y1 = c.i32_add(c.getLocal("pR"), c.i32_const(f2size)); + const Z1 = c.i32_add(c.getLocal("pR"), c.i32_const(2*f2size)); + + const ELL_0 = c.getLocal("pCoef"); + const ELL_VW = c.i32_add(c.getLocal("pCoef"), c.i32_const(f2size)); + const ELL_VV = c.i32_add(c.getLocal("pCoef"), c.i32_const(2*f2size)); + + const A = c.i32_const(module.alloc(f2size)); + const B = c.i32_const(module.alloc(f2size)); + const C = c.i32_const(module.alloc(f2size)); + const D = c.i32_const(module.alloc(f2size)); + const E = c.i32_const(module.alloc(f2size)); + const F = c.i32_const(module.alloc(f2size)); + const G = c.i32_const(module.alloc(f2size)); + const H = c.i32_const(module.alloc(f2size)); + const I = c.i32_const(module.alloc(f2size)); + const J = c.i32_const(module.alloc(f2size)); + const E2 = c.i32_const(module.alloc(f2size)); + const AUX = c.i32_const(module.alloc(f2size)); + + f.addCode( + + // A = X1 * Y1 / 2 + c.call(f2mPrefix + "_mul", Y1, c.i32_const(pTwoInv), A), + c.call(f2mPrefix + "_mul", X1, A, A), + + // B = Y1^2 + c.call(f2mPrefix + "_square", Y1, B), + + // C = Z1^2 + c.call(f2mPrefix + "_square", Z1, C), + + // D = 3 * C + c.call(f2mPrefix + "_add", C, C, D), + c.call(f2mPrefix + "_add", D, C, D), + + // E = twist_b * D + c.call(f2mPrefix + "_mul", c.i32_const(pTwistCoefB), D, E), + + // F = 3 * E + c.call(f2mPrefix + "_add", E, E, F), + c.call(f2mPrefix + "_add", E, F, F), + + // G = (B+F)/2 + c.call(f2mPrefix + "_add", B, F, G), + c.call(f2mPrefix + "_mul", G, c.i32_const(pTwoInv), G), + + // H = (Y1+Z1)^2-(B+C) + c.call(f2mPrefix + "_add", B, C, AUX), + c.call(f2mPrefix + "_add", Y1, Z1, H), + c.call(f2mPrefix + "_square", H, H), + c.call(f2mPrefix + "_sub", H, AUX, H), + + // I = E-B + c.call(f2mPrefix + "_sub", E, B, I), + + // J = X1^2 + c.call(f2mPrefix + "_square", X1, J), + + // E_squared = E^2 + c.call(f2mPrefix + "_square", E, E2), + + // X3 (X1) = A * (B-F) + c.call(f2mPrefix + "_sub", B, F, AUX), + c.call(f2mPrefix + "_mul", A, AUX, X1), + + // Y3 (Y1) = G^2 - 3*E^2 + c.call(f2mPrefix + "_add", E2, E2, AUX), + c.call(f2mPrefix + "_add", E2, AUX, AUX), + c.call(f2mPrefix + "_square", G, Y1), + c.call(f2mPrefix + "_sub", Y1, AUX, Y1), + + // Z3 (Z1) = B * H + c.call(f2mPrefix + "_mul", B, H, Z1), + + // ell_0 = xi * I + c.call(f2mPrefix + "_mul", c.i32_const(pAltBn128Twist), I, ELL_0), + + // ell_VW = - H (later: * yP) + c.call(f2mPrefix + "_neg", H, ELL_VW), + + // ell_VV = 3*J (later: * xP) + c.call(f2mPrefix + "_add", J, J, ELL_VV), + c.call(f2mPrefix + "_add", J, ELL_VV, ELL_VV), + + ); + } + + function buildMulByQ() { + const f = module.addFunction(prefix + "_mulByQ"); + f.addParam("p1", "i32"); + f.addParam("pr", "i32"); + + const c = f.getCodeBuilder(); + + const x = c.getLocal("p1"); + const y = c.i32_add(c.getLocal("p1"), c.i32_const(f2size)); + const z = c.i32_add(c.getLocal("p1"), c.i32_const(f2size*2)); + const x3 = c.getLocal("pr"); + const y3 = c.i32_add(c.getLocal("pr"), c.i32_const(f2size)); + const z3 = c.i32_add(c.getLocal("pr"), c.i32_const(f2size*2)); + + const MulByQX = c.i32_const(module.alloc([ + ...utils$2.bigInt2BytesLE( toMontgomery("21575463638280843010398324269430826099269044274347216827212613867836435027261"), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery("10307601595873709700152284273816112264069230130616436755625194854815875713954"), f1size ), + ])); + + const MulByQY = c.i32_const(module.alloc([ + ...utils$2.bigInt2BytesLE( toMontgomery("2821565182194536844548159561693502659359617185244120367078079554186484126554"), f1size ), + ...utils$2.bigInt2BytesLE( toMontgomery("3505843767911556378687030309984248845540243509899259641013678093033130930403"), f1size ), + ])); + + f.addCode( + // The frobeniusMap(1) in this field, is the conjugate + c.call(f2mPrefix + "_conjugate", x, x3), + c.call(f2mPrefix + "_mul", MulByQX, x3, x3), + c.call(f2mPrefix + "_conjugate", y, y3), + c.call(f2mPrefix + "_mul", MulByQY, y3, y3), + c.call(f2mPrefix + "_conjugate", z, z3), + ); + } + + + function buildPrepareG2() { + buildMulByQ(); + const f = module.addFunction(prefix+ "_prepareG2"); + f.addParam("pQ", "i32"); + f.addParam("ppreQ", "i32"); + f.addLocal("pCoef", "i32"); + f.addLocal("i", "i32"); + + const c = f.getCodeBuilder(); + + const QX = c.getLocal("pQ"); + + const pR = module.alloc(f2size*3); + const R = c.i32_const(pR); + const RX = c.i32_const(pR); + const RY = c.i32_const(pR+f2size); + const RZ = c.i32_const(pR+2*f2size); + + const cQX = c.i32_add( c.getLocal("ppreQ"), c.i32_const(0)); + const cQY = c.i32_add( c.getLocal("ppreQ"), c.i32_const(f2size)); + + const pQ1 = module.alloc(f2size*3); + const Q1 = c.i32_const(pQ1); + + const pQ2 = module.alloc(f2size*3); + const Q2 = c.i32_const(pQ2); + const Q2Y = c.i32_const(pQ2 + f2size); + + f.addCode( + c.call(g2mPrefix + "_normalize", QX, cQX), // TODO Remove if already in affine + c.call(f2mPrefix + "_copy", cQX, RX), + c.call(f2mPrefix + "_copy", cQY, RY), + c.call(f2mPrefix + "_one", RZ), + ); + + f.addCode( + c.setLocal("pCoef", c.i32_add( c.getLocal("ppreQ"), c.i32_const(f2size*3))), + c.setLocal("i", c.i32_const(ateLoopBitBytes.length-2)), + c.block(c.loop( + + c.call(prefix + "_prepDblStep", R, c.getLocal("pCoef")), + c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + + c.if( + c.i32_load8_s(c.getLocal("i"), pAteLoopBitBytes), + [ + ...c.call(prefix + "_prepAddStep", cQX, R, c.getLocal("pCoef")), + ...c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + ] + ), + c.br_if(1, c.i32_eqz ( c.getLocal("i") )), + c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + + f.addCode( + c.call(prefix + "_mulByQ", cQX, Q1), + c.call(prefix + "_mulByQ", Q1, Q2) + ); + + f.addCode( + c.call(f2mPrefix + "_neg", Q2Y, Q2Y), + + c.call(prefix + "_prepAddStep", Q1, R, c.getLocal("pCoef")), + c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + + c.call(prefix + "_prepAddStep", Q2, R, c.getLocal("pCoef")), + c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + ); + } + + function buildMulBy024Old() { + const f = module.addFunction(prefix+ "__mulBy024Old"); + f.addParam("pEll0", "i32"); + f.addParam("pEllVW", "i32"); + f.addParam("pEllVV", "i32"); + f.addParam("pR", "i32"); // Result in F12 + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("pEll0"); + const x2 = c.getLocal("pEllVV"); + const x4 = c.getLocal("pEllVW"); + + const z0 = c.getLocal("pR"); + + const pAUX12 = module.alloc(ftsize); + const AUX12 = c.i32_const(pAUX12); + const AUX12_0 = c.i32_const(pAUX12); + const AUX12_2 = c.i32_const(pAUX12+f2size); + const AUX12_4 = c.i32_const(pAUX12+f2size*2); + const AUX12_6 = c.i32_const(pAUX12+f2size*3); + const AUX12_8 = c.i32_const(pAUX12+f2size*4); + const AUX12_10 = c.i32_const(pAUX12+f2size*5); + + f.addCode( + + c.call(f2mPrefix + "_copy", x0, AUX12_0), + c.call(f2mPrefix + "_zero", AUX12_2), + c.call(f2mPrefix + "_copy", x2, AUX12_4), + c.call(f2mPrefix + "_zero", AUX12_6), + c.call(f2mPrefix + "_copy", x4, AUX12_8), + c.call(f2mPrefix + "_zero", AUX12_10), + c.call(ftmPrefix + "_mul", AUX12, z0, z0), + ); + } + + function buildMulBy024() { + const f = module.addFunction(prefix+ "__mulBy024"); + f.addParam("pEll0", "i32"); + f.addParam("pEllVW", "i32"); + f.addParam("pEllVV", "i32"); + f.addParam("pR", "i32"); // Result in F12 + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("pEll0"); + const x2 = c.getLocal("pEllVV"); + const x4 = c.getLocal("pEllVW"); + + const z0 = c.getLocal("pR"); + const z1 = c.i32_add(c.getLocal("pR"), c.i32_const(2*n8)); + const z2 = c.i32_add(c.getLocal("pR"), c.i32_const(4*n8)); + const z3 = c.i32_add(c.getLocal("pR"), c.i32_const(6*n8)); + const z4 = c.i32_add(c.getLocal("pR"), c.i32_const(8*n8)); + const z5 = c.i32_add(c.getLocal("pR"), c.i32_const(10*n8)); + + const t0 = c.i32_const(module.alloc(f2size)); + const t1 = c.i32_const(module.alloc(f2size)); + const t2 = c.i32_const(module.alloc(f2size)); + const s0 = c.i32_const(module.alloc(f2size)); + const T3 = c.i32_const(module.alloc(f2size)); + const T4 = c.i32_const(module.alloc(f2size)); + const D0 = c.i32_const(module.alloc(f2size)); + const D2 = c.i32_const(module.alloc(f2size)); + const D4 = c.i32_const(module.alloc(f2size)); + const S1 = c.i32_const(module.alloc(f2size)); + const AUX = c.i32_const(module.alloc(f2size)); + + f.addCode( + + // D0 = z0 * x0; + c.call(f2mPrefix + "_mul", z0, x0, D0), + // D2 = z2 * x2; + c.call(f2mPrefix + "_mul", z2, x2, D2), + // D4 = z4 * x4; + c.call(f2mPrefix + "_mul", z4, x4, D4), + // t2 = z0 + z4; + c.call(f2mPrefix + "_add", z0, z4, t2), + // t1 = z0 + z2; + c.call(f2mPrefix + "_add", z0, z2, t1), + // s0 = z1 + z3 + z5; + c.call(f2mPrefix + "_add", z1, z3, s0), + c.call(f2mPrefix + "_add", s0, z5, s0), + + + // For z.a_.a_ = z0. + // S1 = z1 * x2; + c.call(f2mPrefix + "_mul", z1, x2, S1), + // T3 = S1 + D4; + c.call(f2mPrefix + "_add", S1, D4, T3), + // T4 = my_Fp6::non_residue * T3 + D0; + c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), T3, T4), + c.call(f2mPrefix + "_add", T4, D0, z0), + // z0 = T4; + + // For z.a_.b_ = z1 + // T3 = z5 * x4; + c.call(f2mPrefix + "_mul", z5, x4, T3), + // S1 = S1 + T3; + c.call(f2mPrefix + "_add", S1, T3, S1), + // T3 = T3 + D2; + c.call(f2mPrefix + "_add", T3, D2, T3), + // T4 = my_Fp6::non_residue * T3; + c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), T3, T4), + // T3 = z1 * x0; + c.call(f2mPrefix + "_mul", z1, x0, T3), + // S1 = S1 + T3; + c.call(f2mPrefix + "_add", S1, T3, S1), + // T4 = T4 + T3; + c.call(f2mPrefix + "_add", T4, T3, z1), + // z1 = T4; + + + + // For z.a_.c_ = z2 + // t0 = x0 + x2; + c.call(f2mPrefix + "_add", x0, x2, t0), + // T3 = t1 * t0 - D0 - D2; + c.call(f2mPrefix + "_mul", t1, t0, T3), + c.call(f2mPrefix + "_add", D0, D2, AUX), + c.call(f2mPrefix + "_sub", T3, AUX, T3), + // T4 = z3 * x4; + c.call(f2mPrefix + "_mul", z3, x4, T4), + // S1 = S1 + T4; + c.call(f2mPrefix + "_add", S1, T4, S1), + + + // For z.b_.a_ = z3 (z3 needs z2) + // t0 = z2 + z4; + c.call(f2mPrefix + "_add", z2, z4, t0), + // T3 = T3 + T4; + // z2 = T3; + c.call(f2mPrefix + "_add", T3, T4, z2), + // t1 = x2 + x4; + c.call(f2mPrefix + "_add", x2, x4, t1), + // T3 = t0 * t1 - D2 - D4; + c.call(f2mPrefix + "_mul", t1, t0, T3), + c.call(f2mPrefix + "_add", D2, D4, AUX), + c.call(f2mPrefix + "_sub", T3, AUX, T3), + // T4 = my_Fp6::non_residue * T3; + c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), T3, T4), + // T3 = z3 * x0; + c.call(f2mPrefix + "_mul", z3, x0, T3), + // S1 = S1 + T3; + c.call(f2mPrefix + "_add", S1, T3, S1), + // T4 = T4 + T3; + c.call(f2mPrefix + "_add", T4, T3, z3), + // z3 = T4; + + // For z.b_.b_ = z4 + // T3 = z5 * x2; + c.call(f2mPrefix + "_mul", z5, x2, T3), + // S1 = S1 + T3; + c.call(f2mPrefix + "_add", S1, T3, S1), + // T4 = my_Fp6::non_residue * T3; + c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), T3, T4), + // t0 = x0 + x4; + c.call(f2mPrefix + "_add", x0, x4, t0), + // T3 = t2 * t0 - D0 - D4; + c.call(f2mPrefix + "_mul", t2, t0, T3), + c.call(f2mPrefix + "_add", D0, D4, AUX), + c.call(f2mPrefix + "_sub", T3, AUX, T3), + // T4 = T4 + T3; + c.call(f2mPrefix + "_add", T4, T3, z4), + // z4 = T4; + + // For z.b_.c_ = z5. + // t0 = x0 + x2 + x4; + c.call(f2mPrefix + "_add", x0, x2, t0), + c.call(f2mPrefix + "_add", t0, x4, t0), + // T3 = s0 * t0 - S1; + c.call(f2mPrefix + "_mul", s0, t0, T3), + c.call(f2mPrefix + "_sub", T3, S1, z5), + // z5 = T3; + + ); + } + + + function buildMillerLoop() { + const f = module.addFunction(prefix+ "_millerLoop"); + f.addParam("ppreP", "i32"); + f.addParam("ppreQ", "i32"); + f.addParam("r", "i32"); + f.addLocal("pCoef", "i32"); + f.addLocal("i", "i32"); + + const c = f.getCodeBuilder(); + + const preP_PX = c.getLocal("ppreP"); + const preP_PY = c.i32_add(c.getLocal("ppreP"), c.i32_const(f1size)); + + const ELL_0 = c.getLocal("pCoef"); + const ELL_VW = c.i32_add(c.getLocal("pCoef"), c.i32_const(f2size)); + const ELL_VV = c.i32_add(c.getLocal("pCoef"), c.i32_const(2*f2size)); + + + const pVW = module.alloc(f2size); + const VW = c.i32_const(pVW); + const pVV = module.alloc(f2size); + const VV = c.i32_const(pVV); + + const F = c.getLocal("r"); + + + f.addCode( + c.call(ftmPrefix + "_one", F), + + c.setLocal("pCoef", c.i32_add( c.getLocal("ppreQ"), c.i32_const(f2size*3))), + + c.setLocal("i", c.i32_const(ateLoopBitBytes.length-2)), + c.block(c.loop( + + + c.call(ftmPrefix + "_square", F, F), + + c.call(f2mPrefix + "_mul1", ELL_VW,preP_PY, VW), + c.call(f2mPrefix + "_mul1", ELL_VV, preP_PX, VV), + c.call(prefix + "__mulBy024", ELL_0, VW, VV, F), + c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + + c.if( + c.i32_load8_s(c.getLocal("i"), pAteLoopBitBytes), + [ + ...c.call(f2mPrefix + "_mul1", ELL_VW, preP_PY, VW), + ...c.call(f2mPrefix + "_mul1", ELL_VV, preP_PX, VV), + + ...c.call(prefix + "__mulBy024", ELL_0, VW, VV, F), + ...c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + + ] + ), + c.br_if(1, c.i32_eqz ( c.getLocal("i") )), + c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + + ); + + f.addCode( + c.call(f2mPrefix + "_mul1", ELL_VW, preP_PY, VW), + c.call(f2mPrefix + "_mul1", ELL_VV, preP_PX, VV), + c.call(prefix + "__mulBy024", ELL_0, VW, VV, F), + c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + + c.call(f2mPrefix + "_mul1", ELL_VW, preP_PY, VW), + c.call(f2mPrefix + "_mul1", ELL_VV, preP_PX, VV), + c.call(prefix + "__mulBy024", ELL_0, VW, VV, F), + c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + + ); + + } + + + function buildFrobeniusMap(n) { + const F12 = [ + [ + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + ], + [ + [1n, 0n], + [8376118865763821496583973867626364092589906065868298776909617916018768340080n, 16469823323077808223889137241176536799009286646108169935659301613961712198316n], + [21888242871839275220042445260109153167277707414472061641714758635765020556617n, 0n], + [11697423496358154304825782922584725312912383441159505038794027105778954184319n, 303847389135065887422783454877609941456349188919719272345083954437860409601n], + [21888242871839275220042445260109153167277707414472061641714758635765020556616n, 0n], + [3321304630594332808241809054958361220322477375291206261884409189760185844239n, 5722266937896532885780051958958348231143373700109372999374820235121374419868n], + [21888242871839275222246405745257275088696311157297823662689037894645226208582n, 0n], + [13512124006075453725662431877630910996106405091429524885779419978626457868503n, 5418419548761466998357268504080738289687024511189653727029736280683514010267n], + [2203960485148121921418603742825762020974279258880205651966n, 0n], + [10190819375481120917420622822672549775783927716138318623895010788866272024264n, 21584395482704209334823622290379665147239961968378104390343953940207365798982n], + [2203960485148121921418603742825762020974279258880205651967n, 0n], + [18566938241244942414004596690298913868373833782006617400804628704885040364344n, 16165975933942742336466353786298926857552937457188450663314217659523851788715n], + ] + ]; + + const F6 = [ + [ + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + ], + [ + [1n, 0n], + [21575463638280843010398324269430826099269044274347216827212613867836435027261n, 10307601595873709700152284273816112264069230130616436755625194854815875713954n], + [21888242871839275220042445260109153167277707414472061641714758635765020556616n, 0n], + [3772000881919853776433695186713858239009073593817195771773381919316419345261n, 2236595495967245188281701248203181795121068902605861227855261137820944008926n], + [2203960485148121921418603742825762020974279258880205651966n, 0n], + [18429021223477853657660792034369865839114504446431234726392080002137598044644n, 9344045779998320333812420223237981029506012124075525679208581902008406485703n], + ], + [ + [1n, 0n], + [2581911344467009335267311115468803099551665605076196740867805258568234346338n, 19937756971775647987995932169929341994314640652964949448313374472400716661030n], + [2203960485148121921418603742825762020974279258880205651966n, 0n], + [5324479202449903542726783395506214481928257762400643279780343368557297135718n, 16208900380737693084919495127334387981393726419856888799917914180988844123039n], + [21888242871839275220042445260109153167277707414472061641714758635765020556616n, 0n], + [13981852324922362344252311234282257507216387789820983642040889267519694726527n, 7629828391165209371577384193250820201684255241773809077146787135900891633097n], + ] + ]; + + const f = module.addFunction(prefix+ "__frobeniusMap"+n); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + for (let i=0; i<6; i++) { + const X = (i==0) ? c.getLocal("x") : c.i32_add(c.getLocal("x"), c.i32_const(i*f2size)); + const Xc0 = X; + const Xc1 = c.i32_add(c.getLocal("x"), c.i32_const(i*f2size + f1size)); + const R = (i==0) ? c.getLocal("r") : c.i32_add(c.getLocal("r"), c.i32_const(i*f2size)); + const Rc0 = R; + const Rc1 = c.i32_add(c.getLocal("r"), c.i32_const(i*f2size + f1size)); + const coef = mul2(F12[Math.floor(i/3)][n%12] , F6[i%3][n%6]); + const pCoef = module.alloc([ + ...utils$2.bigInt2BytesLE(toMontgomery(coef[0]), 32), + ...utils$2.bigInt2BytesLE(toMontgomery(coef[1]), 32), + ]); + if (n%2 == 1) { + f.addCode( + c.call(f1mPrefix + "_copy", Xc0, Rc0), + c.call(f1mPrefix + "_neg", Xc1, Rc1), + c.call(f2mPrefix + "_mul", R, c.i32_const(pCoef), R), + ); + } else { + f.addCode(c.call(f2mPrefix + "_mul", X, c.i32_const(pCoef), R)); + } + } + + function mul2(a, b) { + const ac0 = BigInt(a[0]); + const ac1 = BigInt(a[1]); + const bc0 = BigInt(b[0]); + const bc1 = BigInt(b[1]); + const res = [ + (ac0 * bc0 - ( ac1 * bc1) ) % q, + (ac0 * bc1 + ( ac1 * bc0) ) % q, + ]; + if (isNegative$2(res[0])) res[0] = res[0] + q; + return res; + } + + } + + + + function buildFinalExponentiationFirstChunk() { + + const f = module.addFunction(prefix+ "__finalExponentiationFirstChunk"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const elt = c.getLocal("x"); + const eltC0 = elt; + const eltC1 = c.i32_add(elt, c.i32_const(n8*6)); + const r = c.getLocal("r"); + const pA = module.alloc(ftsize); + const A = c.i32_const(pA); + const Ac0 = A; + const Ac1 = c.i32_const(pA + n8*6); + const B = c.i32_const(module.alloc(ftsize)); + const C = c.i32_const(module.alloc(ftsize)); + const D = c.i32_const(module.alloc(ftsize)); + + f.addCode( + // const alt_bn128_Fq12 A = alt_bn128_Fq12(elt.c0,-elt.c1); + c.call(f6mPrefix + "_copy", eltC0, Ac0), + c.call(f6mPrefix + "_neg", eltC1, Ac1), + + // const alt_bn128_Fq12 B = elt.inverse(); + c.call(ftmPrefix + "_inverse", elt, B), + + // const alt_bn128_Fq12 C = A * B; + c.call(ftmPrefix + "_mul", A, B, C), + // const alt_bn128_Fq12 D = C.Frobenius_map(2); + c.call(prefix + "__frobeniusMap2", C, D), + // const alt_bn128_Fq12 result = D * C; + c.call(ftmPrefix + "_mul", C, D, r), + ); + } + + function buildCyclotomicSquare() { + const f = module.addFunction(prefix+ "__cyclotomicSquare"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x4 = c.i32_add(c.getLocal("x"), c.i32_const(f2size)); + const x3 = c.i32_add(c.getLocal("x"), c.i32_const(2*f2size)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(3*f2size)); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(4*f2size)); + const x5 = c.i32_add(c.getLocal("x"), c.i32_const(5*f2size)); + + const r0 = c.getLocal("r"); + const r4 = c.i32_add(c.getLocal("r"), c.i32_const(f2size)); + const r3 = c.i32_add(c.getLocal("r"), c.i32_const(2*f2size)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(3*f2size)); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(4*f2size)); + const r5 = c.i32_add(c.getLocal("r"), c.i32_const(5*f2size)); + + const t0 = c.i32_const(module.alloc(f2size)); + const t1 = c.i32_const(module.alloc(f2size)); + const t2 = c.i32_const(module.alloc(f2size)); + const t3 = c.i32_const(module.alloc(f2size)); + const t4 = c.i32_const(module.alloc(f2size)); + const t5 = c.i32_const(module.alloc(f2size)); + const tmp = c.i32_const(module.alloc(f2size)); + const AUX = c.i32_const(module.alloc(f2size)); + + + f.addCode( + // // t0 + t1*y = (z0 + z1*y)^2 = a^2 + // tmp = z0 * z1; + // t0 = (z0 + z1) * (z0 + my_Fp6::non_residue * z1) - tmp - my_Fp6::non_residue * tmp; + // t1 = tmp + tmp; + c.call(f2mPrefix + "_mul", x0, x1, tmp), + c.call(f2mPrefix + "_mul", x1, c.i32_const(pNonResidueF6), t0), + c.call(f2mPrefix + "_add", x0, t0, t0), + c.call(f2mPrefix + "_add", x0, x1, AUX), + c.call(f2mPrefix + "_mul", AUX, t0, t0), + c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), tmp, AUX), + c.call(f2mPrefix + "_add", tmp, AUX, AUX), + c.call(f2mPrefix + "_sub", t0, AUX, t0), + c.call(f2mPrefix + "_add", tmp, tmp, t1), + + // // t2 + t3*y = (z2 + z3*y)^2 = b^2 + // tmp = z2 * z3; + // t2 = (z2 + z3) * (z2 + my_Fp6::non_residue * z3) - tmp - my_Fp6::non_residue * tmp; + // t3 = tmp + tmp; + c.call(f2mPrefix + "_mul", x2, x3, tmp), + c.call(f2mPrefix + "_mul", x3, c.i32_const(pNonResidueF6), t2), + c.call(f2mPrefix + "_add", x2, t2, t2), + c.call(f2mPrefix + "_add", x2, x3, AUX), + c.call(f2mPrefix + "_mul", AUX, t2, t2), + c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), tmp, AUX), + c.call(f2mPrefix + "_add", tmp, AUX, AUX), + c.call(f2mPrefix + "_sub", t2, AUX, t2), + c.call(f2mPrefix + "_add", tmp, tmp, t3), + + // // t4 + t5*y = (z4 + z5*y)^2 = c^2 + // tmp = z4 * z5; + // t4 = (z4 + z5) * (z4 + my_Fp6::non_residue * z5) - tmp - my_Fp6::non_residue * tmp; + // t5 = tmp + tmp; + c.call(f2mPrefix + "_mul", x4, x5, tmp), + c.call(f2mPrefix + "_mul", x5, c.i32_const(pNonResidueF6), t4), + c.call(f2mPrefix + "_add", x4, t4, t4), + c.call(f2mPrefix + "_add", x4, x5, AUX), + c.call(f2mPrefix + "_mul", AUX, t4, t4), + c.call(f2mPrefix + "_mul", c.i32_const(pNonResidueF6), tmp, AUX), + c.call(f2mPrefix + "_add", tmp, AUX, AUX), + c.call(f2mPrefix + "_sub", t4, AUX, t4), + c.call(f2mPrefix + "_add", tmp, tmp, t5), + + // For A + // z0 = 3 * t0 - 2 * z0 + c.call(f2mPrefix + "_sub", t0, x0, r0), + c.call(f2mPrefix + "_add", r0, r0, r0), + c.call(f2mPrefix + "_add", t0, r0, r0), + // z1 = 3 * t1 + 2 * z1 + c.call(f2mPrefix + "_add", t1, x1, r1), + c.call(f2mPrefix + "_add", r1, r1, r1), + c.call(f2mPrefix + "_add", t1, r1, r1), + + // For B + // z2 = 3 * (xi * t5) + 2 * z2 + c.call(f2mPrefix + "_mul", t5, c.i32_const(pAltBn128Twist), AUX), + c.call(f2mPrefix + "_add", AUX, x2, r2), + c.call(f2mPrefix + "_add", r2, r2, r2), + c.call(f2mPrefix + "_add", AUX, r2, r2), + // z3 = 3 * t4 - 2 * z3 + c.call(f2mPrefix + "_sub", t4, x3, r3), + c.call(f2mPrefix + "_add", r3, r3, r3), + c.call(f2mPrefix + "_add", t4, r3, r3), + + // For C + // z4 = 3 * t2 - 2 * z4 + c.call(f2mPrefix + "_sub", t2, x4, r4), + c.call(f2mPrefix + "_add", r4, r4, r4), + c.call(f2mPrefix + "_add", t2, r4, r4), + // z5 = 3 * t3 + 2 * z5 + c.call(f2mPrefix + "_add", t3, x5, r5), + c.call(f2mPrefix + "_add", r5, r5, r5), + c.call(f2mPrefix + "_add", t3, r5, r5), + + ); + } + + + function buildCyclotomicExp(exponent, fnName) { + const exponentNafBytes = naf(exponent).map( (b) => (b==-1 ? 0xFF: b) ); + const pExponentNafBytes = module.alloc(exponentNafBytes); + + const f = module.addFunction(prefix+ "__cyclotomicExp_"+fnName); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + f.addLocal("bit", "i32"); + f.addLocal("i", "i32"); + + const c = f.getCodeBuilder(); + + const x = c.getLocal("x"); + + const res = c.getLocal("r"); + + const inverse = c.i32_const(module.alloc(ftsize)); + + + f.addCode( + c.call(ftmPrefix + "_conjugate", x, inverse), + c.call(ftmPrefix + "_one", res), + + c.if( + c.teeLocal("bit", c.i32_load8_s(c.i32_const(exponentNafBytes.length-1), pExponentNafBytes)), + c.if( + c.i32_eq( + c.getLocal("bit"), + c.i32_const(1) + ), + c.call(ftmPrefix + "_mul", res, x, res), + c.call(ftmPrefix + "_mul", res, inverse, res), + ) + ), + + c.setLocal("i", c.i32_const(exponentNafBytes.length-2)), + c.block(c.loop( + c.call(prefix + "__cyclotomicSquare", res, res), + c.if( + c.teeLocal("bit", c.i32_load8_s(c.getLocal("i"), pExponentNafBytes)), + c.if( + c.i32_eq( + c.getLocal("bit"), + c.i32_const(1) + ), + c.call(ftmPrefix + "_mul", res, x, res), + c.call(ftmPrefix + "_mul", res, inverse, res), + ) + ), + c.br_if(1, c.i32_eqz ( c.getLocal("i") )), + c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + } + + + + function buildFinalExponentiationLastChunk() { + buildCyclotomicSquare(); + buildCyclotomicExp(finalExpZ, "w0"); + + const f = module.addFunction(prefix+ "__finalExponentiationLastChunk"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const elt = c.getLocal("x"); + const result = c.getLocal("r"); + const A = c.i32_const(module.alloc(ftsize)); + const B = c.i32_const(module.alloc(ftsize)); + const C = c.i32_const(module.alloc(ftsize)); + const D = c.i32_const(module.alloc(ftsize)); + const E = c.i32_const(module.alloc(ftsize)); + const F = c.i32_const(module.alloc(ftsize)); + const G = c.i32_const(module.alloc(ftsize)); + const H = c.i32_const(module.alloc(ftsize)); + const I = c.i32_const(module.alloc(ftsize)); + const J = c.i32_const(module.alloc(ftsize)); + const K = c.i32_const(module.alloc(ftsize)); + const L = c.i32_const(module.alloc(ftsize)); + const M = c.i32_const(module.alloc(ftsize)); + const N = c.i32_const(module.alloc(ftsize)); + const O = c.i32_const(module.alloc(ftsize)); + const P = c.i32_const(module.alloc(ftsize)); + const Q = c.i32_const(module.alloc(ftsize)); + const R = c.i32_const(module.alloc(ftsize)); + const S = c.i32_const(module.alloc(ftsize)); + const T = c.i32_const(module.alloc(ftsize)); + const U = c.i32_const(module.alloc(ftsize)); + + f.addCode( + + + // A = exp_by_neg_z(elt) // = elt^(-z) + c.call(prefix + "__cyclotomicExp_w0", elt, A), + c.call(ftmPrefix + "_conjugate", A, A), + // B = A^2 // = elt^(-2*z) + c.call(prefix + "__cyclotomicSquare", A, B), + // C = B^2 // = elt^(-4*z) + c.call(prefix + "__cyclotomicSquare", B, C), + // D = C * B // = elt^(-6*z) + c.call(ftmPrefix + "_mul", C, B, D), + // E = exp_by_neg_z(D) // = elt^(6*z^2) + c.call(prefix + "__cyclotomicExp_w0", D, E), + c.call(ftmPrefix + "_conjugate", E, E), + // F = E^2 // = elt^(12*z^2) + c.call(prefix + "__cyclotomicSquare", E, F), + // G = epx_by_neg_z(F) // = elt^(-12*z^3) + c.call(prefix + "__cyclotomicExp_w0", F, G), + c.call(ftmPrefix + "_conjugate", G, G), + // H = conj(D) // = elt^(6*z) + c.call(ftmPrefix + "_conjugate", D, H), + // I = conj(G) // = elt^(12*z^3) + c.call(ftmPrefix + "_conjugate", G, I), + // J = I * E // = elt^(12*z^3 + 6*z^2) + c.call(ftmPrefix + "_mul", I, E, J), + // K = J * H // = elt^(12*z^3 + 6*z^2 + 6*z) + c.call(ftmPrefix + "_mul", J, H, K), + // L = K * B // = elt^(12*z^3 + 6*z^2 + 4*z) + c.call(ftmPrefix + "_mul", K, B, L), + // M = K * E // = elt^(12*z^3 + 12*z^2 + 6*z) + c.call(ftmPrefix + "_mul", K, E, M), + + // N = M * elt // = elt^(12*z^3 + 12*z^2 + 6*z + 1) + c.call(ftmPrefix + "_mul", M, elt, N), + + // O = L.Frobenius_map(1) // = elt^(q*(12*z^3 + 6*z^2 + 4*z)) + c.call(prefix + "__frobeniusMap1", L, O), + // P = O * N // = elt^(q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1)) + c.call(ftmPrefix + "_mul", O, N, P), + // Q = K.Frobenius_map(2) // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z)) + c.call(prefix + "__frobeniusMap2", K, Q), + // R = Q * P // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1)) + c.call(ftmPrefix + "_mul", Q, P, R), + // S = conj(elt) // = elt^(-1) + c.call(ftmPrefix + "_conjugate", elt, S), + // T = S * L // = elt^(12*z^3 + 6*z^2 + 4*z - 1) + c.call(ftmPrefix + "_mul", S, L, T), + // U = T.Frobenius_map(3) // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1)) + c.call(prefix + "__frobeniusMap3", T, U), + // V = U * R // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1) + q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1)) + c.call(ftmPrefix + "_mul", U, R, result), + // result = V + ); + } + + + function buildFinalExponentiation() { + buildFinalExponentiationFirstChunk(); + buildFinalExponentiationLastChunk(); + const f = module.addFunction(prefix+ "_finalExponentiation"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const elt = c.getLocal("x"); + const result = c.getLocal("r"); + const eltToFirstChunk = c.i32_const(module.alloc(ftsize)); + + f.addCode( + c.call(prefix + "__finalExponentiationFirstChunk", elt, eltToFirstChunk ), + c.call(prefix + "__finalExponentiationLastChunk", eltToFirstChunk, result ) + ); + } + + + function buildFinalExponentiationOld() { + const f = module.addFunction(prefix+ "_finalExponentiationOld"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const exponent = 552484233613224096312617126783173147097382103762957654188882734314196910839907541213974502761540629817009608548654680343627701153829446747810907373256841551006201639677726139946029199968412598804882391702273019083653272047566316584365559776493027495458238373902875937659943504873220554161550525926302303331747463515644711876653177129578303191095900909191624817826566688241804408081892785725967931714097716709526092261278071952560171111444072049229123565057483750161460024353346284167282452756217662335528813519139808291170539072125381230815729071544861602750936964829313608137325426383735122175229541155376346436093930287402089517426973178917569713384748081827255472576937471496195752727188261435633271238710131736096299798168852925540549342330775279877006784354801422249722573783561685179618816480037695005515426162362431072245638324744480n; + + const pExponent = module.alloc(utils$2.bigInt2BytesLE( exponent, 352 )); + + const c = f.getCodeBuilder(); + + f.addCode( + c.call(ftmPrefix + "_exp", c.getLocal("x"), c.i32_const(pExponent), c.i32_const(352), c.getLocal("r")), + ); + } + + + + + const pPreP = module.alloc(prePSize); + const pPreQ = module.alloc(preQSize); + + function buildPairingEquation(nPairings) { + + const f = module.addFunction(prefix+ "_pairingEq"+nPairings); + for (let i=0; i acc + ( b!=0 ? 1 : 0) ,0); + const ateNCoefs = ateNAddCoefs + ateNDblCoefs + 1; + const prePSize = 3*2*n8q; + const preQSize = 3*n8q*2 + ateNCoefs*ateCoefSize; + const finalExpIsNegative = true; + + const finalExpZ = 15132376222941642752n; + + + module.modules[prefix] = { + n64q: n64q, + n64r: n64r, + n8q: n8q, + n8r: n8r, + pG1gen: pG1gen, + pG1zero: pG1zero, + pG1b: pG1b, + pG2gen: pG2gen, + pG2zero: pG2zero, + pG2b: pG2b, + pq: module.modules["f1m"].pq, + pr: pr, + pOneT: pOneT, + r: r, + q: q, + prePSize: prePSize, + preQSize: preQSize + }; + + + function naf(n) { + let E = n; + const res = []; + while (E > 0n) { + if (isOdd(E)) { + const z = 2 - Number(E % 4n); + res.push( z ); + E = E - BigInt(z); + } else { + res.push( 0 ); + } + E = E >> 1n; + } + return res; + } + + function bits(n) { + let E = n; + const res = []; + while (E > 0n) { + if (isOdd(E)) { + res.push( 1 ); + } else { + res.push( 0 ); + } + E = E >> 1n; + } + return res; + } + + function buildPrepareG1() { + const f = module.addFunction(prefix+ "_prepareG1"); + f.addParam("pP", "i32"); + f.addParam("ppreP", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode( + c.call(g1mPrefix + "_normalize", c.getLocal("pP"), c.getLocal("ppreP")), // TODO Remove if already in affine + ); + } + + + + function buildPrepDoubleStep() { + const f = module.addFunction(prefix+ "_prepDblStep"); + f.addParam("R", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const Rx = c.getLocal("R"); + const Ry = c.i32_add(c.getLocal("R"), c.i32_const(2*n8q)); + const Rz = c.i32_add(c.getLocal("R"), c.i32_const(4*n8q)); + + const t0 = c.getLocal("r"); + const t3 = c.i32_add(c.getLocal("r"), c.i32_const(2*n8q)); + const t6 = c.i32_add(c.getLocal("r"), c.i32_const(4*n8q)); + + + const zsquared = c.i32_const(module.alloc(f2size)); + const t1 = c.i32_const(module.alloc(f2size)); + const t2 = c.i32_const(module.alloc(f2size)); + const t4 = c.i32_const(module.alloc(f2size)); + const t5 = c.i32_const(module.alloc(f2size)); + + f.addCode( + + // tmp0 = r.x.square(); + c.call(f2mPrefix + "_square", Rx, t0), + + // tmp1 = r.y.square(); + c.call(f2mPrefix + "_square", Ry, t1), + + // tmp2 = tmp1.square(); + c.call(f2mPrefix + "_square", t1, t2), + + // tmp3 = (tmp1 + r.x).square() - tmp0 - tmp2; + c.call(f2mPrefix + "_add", t1, Rx, t3), + c.call(f2mPrefix + "_square", t3, t3), + c.call(f2mPrefix + "_sub", t3, t0, t3), + c.call(f2mPrefix + "_sub", t3, t2, t3), + + // tmp3 = tmp3 + tmp3; + c.call(f2mPrefix + "_add", t3, t3, t3), + + // tmp4 = tmp0 + tmp0 + tmp0; + c.call(f2mPrefix + "_add", t0, t0, t4), + c.call(f2mPrefix + "_add", t4, t0, t4), + + // tmp6 = r.x + tmp4; + c.call(f2mPrefix + "_add", Rx, t4, t6), + + // tmp5 = tmp4.square(); + c.call(f2mPrefix + "_square", t4, t5), + + // zsquared = r.z.square(); + c.call(f2mPrefix + "_square", Rz, zsquared), + + // r.x = tmp5 - tmp3 - tmp3; + c.call(f2mPrefix + "_sub", t5, t3, Rx), + c.call(f2mPrefix + "_sub", Rx, t3, Rx), + + // r.z = (r.z + r.y).square() - tmp1 - zsquared; + c.call(f2mPrefix + "_add", Rz, Ry, Rz), + c.call(f2mPrefix + "_square", Rz, Rz), + c.call(f2mPrefix + "_sub", Rz, t1, Rz), + c.call(f2mPrefix + "_sub", Rz, zsquared, Rz), + + // r.y = (tmp3 - r.x) * tmp4; + c.call(f2mPrefix + "_sub", t3, Rx, Ry), + c.call(f2mPrefix + "_mul", Ry, t4, Ry), + + // tmp2 = tmp2 + tmp2; + c.call(f2mPrefix + "_add", t2, t2, t2), + + // tmp2 = tmp2 + tmp2; + c.call(f2mPrefix + "_add", t2, t2, t2), + + // tmp2 = tmp2 + tmp2; + c.call(f2mPrefix + "_add", t2, t2, t2), + + // r.y -= tmp2; + c.call(f2mPrefix + "_sub", Ry, t2, Ry), + + // tmp3 = tmp4 * zsquared; + c.call(f2mPrefix + "_mul", t4, zsquared, t3), + + // tmp3 = tmp3 + tmp3; + c.call(f2mPrefix + "_add", t3, t3, t3), + + // tmp3 = -tmp3; + c.call(f2mPrefix + "_neg", t3, t3), + + // tmp6 = tmp6.square() - tmp0 - tmp5; + c.call(f2mPrefix + "_square", t6, t6), + c.call(f2mPrefix + "_sub", t6, t0, t6), + c.call(f2mPrefix + "_sub", t6, t5, t6), + + // tmp1 = tmp1 + tmp1; + c.call(f2mPrefix + "_add", t1, t1, t1), + + // tmp1 = tmp1 + tmp1; + c.call(f2mPrefix + "_add", t1, t1, t1), + + // tmp6 = tmp6 - tmp1; + c.call(f2mPrefix + "_sub", t6, t1, t6), + + // tmp0 = r.z * zsquared; + c.call(f2mPrefix + "_mul", Rz, zsquared, t0), + + // tmp0 = tmp0 + tmp0; + c.call(f2mPrefix + "_add", t0, t0, t0), + + ); + } + + function buildPrepAddStep() { + const f = module.addFunction(prefix+ "_prepAddStep"); + f.addParam("R", "i32"); + f.addParam("Q", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const Rx = c.getLocal("R"); + const Ry = c.i32_add(c.getLocal("R"), c.i32_const(2*n8q)); + const Rz = c.i32_add(c.getLocal("R"), c.i32_const(4*n8q)); + + const Qx = c.getLocal("Q"); + const Qy = c.i32_add(c.getLocal("Q"), c.i32_const(2*n8q)); + + const t10 = c.getLocal("r"); + const t1 = c.i32_add(c.getLocal("r"), c.i32_const(2*n8q)); + const t9 = c.i32_add(c.getLocal("r"), c.i32_const(4*n8q)); + + const zsquared = c.i32_const(module.alloc(f2size)); + const ysquared = c.i32_const(module.alloc(f2size)); + const ztsquared = c.i32_const(module.alloc(f2size)); + const t0 = c.i32_const(module.alloc(f2size)); + const t2 = c.i32_const(module.alloc(f2size)); + const t3 = c.i32_const(module.alloc(f2size)); + const t4 = c.i32_const(module.alloc(f2size)); + const t5 = c.i32_const(module.alloc(f2size)); + const t6 = c.i32_const(module.alloc(f2size)); + const t7 = c.i32_const(module.alloc(f2size)); + const t8 = c.i32_const(module.alloc(f2size)); + + f.addCode( + + // zsquared = r.z.square(); + c.call(f2mPrefix + "_square", Rz, zsquared), + + // ysquared = q.y.square(); + c.call(f2mPrefix + "_square", Qy, ysquared), + + // t0 = zsquared * q.x; + c.call(f2mPrefix + "_mul", zsquared, Qx, t0), + + // t1 = ((q.y + r.z).square() - ysquared - zsquared) * zsquared; + c.call(f2mPrefix + "_add", Qy, Rz, t1), + c.call(f2mPrefix + "_square", t1, t1), + c.call(f2mPrefix + "_sub", t1, ysquared, t1), + c.call(f2mPrefix + "_sub", t1, zsquared, t1), + c.call(f2mPrefix + "_mul", t1, zsquared, t1), + + // t2 = t0 - r.x; + c.call(f2mPrefix + "_sub", t0, Rx, t2), + + // t3 = t2.square(); + c.call(f2mPrefix + "_square", t2, t3), + + // t4 = t3 + t3; + c.call(f2mPrefix + "_add", t3, t3, t4), + + // t4 = t4 + t4; + c.call(f2mPrefix + "_add", t4, t4, t4), + + // t5 = t4 * t2; + c.call(f2mPrefix + "_mul", t4, t2, t5), + + // t6 = t1 - r.y - r.y; + c.call(f2mPrefix + "_sub", t1, Ry, t6), + c.call(f2mPrefix + "_sub", t6, Ry, t6), + + // t9 = t6 * q.x; + c.call(f2mPrefix + "_mul", t6, Qx, t9), + + // t7 = t4 * r.x; + c.call(f2mPrefix + "_mul", t4, Rx, t7), + + // r.x = t6.square() - t5 - t7 - t7; + c.call(f2mPrefix + "_square", t6, Rx), + c.call(f2mPrefix + "_sub", Rx, t5, Rx), + c.call(f2mPrefix + "_sub", Rx, t7, Rx), + c.call(f2mPrefix + "_sub", Rx, t7, Rx), + + // r.z = (r.z + t2).square() - zsquared - t3; + c.call(f2mPrefix + "_add", Rz, t2, Rz), + c.call(f2mPrefix + "_square", Rz, Rz), + c.call(f2mPrefix + "_sub", Rz, zsquared, Rz), + c.call(f2mPrefix + "_sub", Rz, t3, Rz), + + // t10 = q.y + r.z; + c.call(f2mPrefix + "_add", Qy, Rz, t10), + + // t8 = (t7 - r.x) * t6; + c.call(f2mPrefix + "_sub", t7, Rx, t8), + c.call(f2mPrefix + "_mul", t8, t6, t8), + + // t0 = r.y * t5; + c.call(f2mPrefix + "_mul", Ry, t5, t0), + + // t0 = t0 + t0; + c.call(f2mPrefix + "_add", t0, t0, t0), + + // r.y = t8 - t0; + c.call(f2mPrefix + "_sub", t8, t0, Ry), + + // t10 = t10.square() - ysquared; + c.call(f2mPrefix + "_square", t10, t10), + c.call(f2mPrefix + "_sub", t10, ysquared, t10), + + // ztsquared = r.z.square(); + c.call(f2mPrefix + "_square", Rz, ztsquared), + + // t10 = t10 - ztsquared; + c.call(f2mPrefix + "_sub", t10, ztsquared, t10), + + // t9 = t9 + t9 - t10; + c.call(f2mPrefix + "_add", t9, t9, t9), + c.call(f2mPrefix + "_sub", t9, t10, t9), + + // t10 = r.z + r.z; + c.call(f2mPrefix + "_add", Rz, Rz, t10), + + // t6 = -t6; + c.call(f2mPrefix + "_neg", t6, t6), + + // t1 = t6 + t6; + c.call(f2mPrefix + "_add", t6, t6, t1), + ); + } + + + function buildPrepareG2() { + const f = module.addFunction(prefix+ "_prepareG2"); + f.addParam("pQ", "i32"); + f.addParam("ppreQ", "i32"); + f.addLocal("pCoef", "i32"); + f.addLocal("i", "i32"); + + const c = f.getCodeBuilder(); + + + const Q = c.getLocal("pQ"); + + const pR = module.alloc(f2size*3); + const R = c.i32_const(pR); + + const base = c.getLocal("ppreQ"); + + f.addCode( + c.call(g2mPrefix + "_normalize", Q, base), + c.if( + c.call(g2mPrefix + "_isZero", base), + c.ret([]) + ), + c.call(g2mPrefix + "_copy", base, R), + c.setLocal("pCoef", c.i32_add(c.getLocal("ppreQ"), c.i32_const(f2size*3))), + ); + + f.addCode( + c.setLocal("i", c.i32_const(ateLoopBitBytes.length-2)), + c.block(c.loop( + + c.call(prefix + "_prepDblStep", R, c.getLocal("pCoef")), + c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + + c.if( + c.i32_load8_s(c.getLocal("i"), pAteLoopBitBytes), + [ + ...c.call(prefix + "_prepAddStep", R, base, c.getLocal("pCoef")), + ...c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + ] + ), + c.br_if(1, c.i32_eqz ( c.getLocal("i") )), + c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + } + + + function buildF6Mul1() { + const f = module.addFunction(f6mPrefix+ "_mul1"); + f.addParam("pA", "i32"); // F6 + f.addParam("pC1", "i32"); // F2 + f.addParam("pR", "i32"); // F6 + + const c = f.getCodeBuilder(); + + const A_c0 = c.getLocal("pA"); + const A_c1 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*2)); + const A_c2 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*4)); + + const c1 = c.getLocal("pC1"); + + const t1 = c.getLocal("pR"); + const t2 = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*2)); + const b_b = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*4)); + + const Ac0_Ac1 = c.i32_const(module.alloc(f1size*2)); + const Ac1_Ac2 = c.i32_const(module.alloc(f1size*2)); + + f.addCode( + + c.call(f2mPrefix + "_add", A_c0, A_c1, Ac0_Ac1), + c.call(f2mPrefix + "_add", A_c1, A_c2, Ac1_Ac2), + + // let b_b = self.c1 * c1; + c.call(f2mPrefix + "_mul", A_c1, c1, b_b), + + // let t1 = (self.c1 + self.c2) * c1 - b_b; + c.call(f2mPrefix + "_mul", Ac1_Ac2, c1, t1), + c.call(f2mPrefix + "_sub", t1, b_b, t1), + + // let t1 = t1.mul_by_nonresidue(); + c.call(f2mPrefix + "_mulNR", t1, t1), + + // let t2 = (self.c0 + self.c1) * c1 - b_b; + c.call(f2mPrefix + "_mul", Ac0_Ac1, c1, t2), + c.call(f2mPrefix + "_sub", t2, b_b, t2), + ); + } + buildF6Mul1(); + + function buildF6Mul01() { + const f = module.addFunction(f6mPrefix+ "_mul01"); + f.addParam("pA", "i32"); // F6 + f.addParam("pC0", "i32"); // F2 + f.addParam("pC1", "i32"); // F2 + f.addParam("pR", "i32"); // F6 + + const c = f.getCodeBuilder(); + + const A_c0 = c.getLocal("pA"); + const A_c1 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*2)); + const A_c2 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*4)); + + const c0 = c.getLocal("pC0"); + const c1 = c.getLocal("pC1"); + + const t1 = c.getLocal("pR"); + const t2 = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*2)); + const t3 = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*4)); + + const a_a = c.i32_const(module.alloc(f1size*2)); + const b_b = c.i32_const(module.alloc(f1size*2)); + const Ac0_Ac1 = c.i32_const(module.alloc(f1size*2)); + const Ac0_Ac2 = c.i32_const(module.alloc(f1size*2)); + + f.addCode( + // let a_a = self.c0 * c0; + c.call(f2mPrefix + "_mul", A_c0, c0, a_a), + + // let b_b = self.c1 * c1; + c.call(f2mPrefix + "_mul", A_c1, c1, b_b), + + + c.call(f2mPrefix + "_add", A_c0, A_c1, Ac0_Ac1), + c.call(f2mPrefix + "_add", A_c0, A_c2, Ac0_Ac2), + + // let t1 = (self.c1 + self.c2) * c1 - b_b; + c.call(f2mPrefix + "_add", A_c1, A_c2, t1), + c.call(f2mPrefix + "_mul", t1, c1, t1), + c.call(f2mPrefix + "_sub", t1, b_b, t1), + + // let t1 = t1.mul_by_nonresidue() + a_a; + c.call(f2mPrefix + "_mulNR", t1, t1), + c.call(f2mPrefix + "_add", t1, a_a, t1), + + // let t2 = (c0 + c1) * (self.c0 + self.c1) - a_a - b_b; + c.call(f2mPrefix + "_add", c0, c1, t2), + c.call(f2mPrefix + "_mul", t2, Ac0_Ac1, t2), + c.call(f2mPrefix + "_sub", t2, a_a, t2), + c.call(f2mPrefix + "_sub", t2, b_b, t2), + + // let t3 = (self.c0 + self.c2) * c0 - a_a + b_b; + c.call(f2mPrefix + "_mul", Ac0_Ac2, c0, t3), + c.call(f2mPrefix + "_sub", t3, a_a, t3), + c.call(f2mPrefix + "_add", t3, b_b, t3), + + + ); + } + buildF6Mul01(); + + + function buildF12Mul014() { + + const f = module.addFunction(ftmPrefix+ "_mul014"); + f.addParam("pA", "i32"); // F12 + f.addParam("pC0", "i32"); // F2 + f.addParam("pC1", "i32"); // F2 + f.addParam("pC4", "i32"); // F2 + f.addParam("pR", "i32"); // F12 + + const c = f.getCodeBuilder(); + + + const A_c0 = c.getLocal("pA"); + const A_c1 = c.i32_add(c.getLocal("pA"), c.i32_const(f1size*6)); + + const c0 = c.getLocal("pC0"); + const c1 = c.getLocal("pC1"); + const c4 = c.getLocal("pC4"); + + const aa = c.i32_const(module.alloc(f1size*6)); + const bb = c.i32_const(module.alloc(f1size*6)); + const o = c.i32_const(module.alloc(f1size*2)); + + const R_c0 = c.getLocal("pR"); + const R_c1 = c.i32_add(c.getLocal("pR"), c.i32_const(f1size*6)); + + f.addCode( + // let aa = self.c0.mul_by_01(c0, c1); + c.call(f6mPrefix + "_mul01", A_c0, c0, c1, aa), + + // let bb = self.c1.mul_by_1(c4); + c.call(f6mPrefix + "_mul1", A_c1, c4, bb), + + // let o = c1 + c4; + c.call(f2mPrefix + "_add", c1, c4, o), + + // let c1 = self.c1 + self.c0; + c.call(f6mPrefix + "_add", A_c1, A_c0, R_c1), + + // let c1 = c1.mul_by_01(c0, &o); + c.call(f6mPrefix + "_mul01", R_c1, c0, o, R_c1), + + // let c1 = c1 - aa - bb; + c.call(f6mPrefix + "_sub", R_c1, aa, R_c1), + c.call(f6mPrefix + "_sub", R_c1, bb, R_c1), + + // let c0 = bb; + c.call(f6mPrefix + "_copy", bb, R_c0), + + // let c0 = c0.mul_by_nonresidue(); + c.call(f6mPrefix + "_mulNR", R_c0, R_c0), + + // let c0 = c0 + aa; + c.call(f6mPrefix + "_add", R_c0, aa, R_c0), + ); + } + buildF12Mul014(); + + + function buildELL() { + const f = module.addFunction(prefix+ "_ell"); + f.addParam("pP", "i32"); + f.addParam("pCoefs", "i32"); + f.addParam("pF", "i32"); + + const c = f.getCodeBuilder(); + + const Px = c.getLocal("pP"); + const Py = c.i32_add(c.getLocal("pP"), c.i32_const(n8q)); + + const F = c.getLocal("pF"); + + const coef0_0 = c.getLocal("pCoefs"); + const coef0_1 = c.i32_add(c.getLocal("pCoefs"), c.i32_const(f1size)); + const coef1_0 = c.i32_add(c.getLocal("pCoefs"), c.i32_const(f1size*2)); + const coef1_1 = c.i32_add(c.getLocal("pCoefs"), c.i32_const(f1size*3)); + const coef2 = c.i32_add(c.getLocal("pCoefs"), c.i32_const(f1size*4)); + + const pc0 = module.alloc(f1size*2); + const c0 = c.i32_const(pc0); + const c0_c0 = c.i32_const(pc0); + const c0_c1 = c.i32_const(pc0+f1size); + + const pc1 = module.alloc(f1size*2); + const c1 = c.i32_const(pc1); + const c1_c0 = c.i32_const(pc1); + const c1_c1 = c.i32_const(pc1+f1size); + f.addCode( + // let mut c0 = coeffs.0; + // let mut c1 = coeffs.1; + // + // c0.c0 *= p.y; + // c0.c1 *= p.y; + // + // c1.c0 *= p.x; + // c1.c1 *= p.x; + // + // f.mul_by_014(&coeffs.2, &c1, &c0) + + c.call(f1mPrefix + "_mul", coef0_0, Py, c0_c0), + c.call(f1mPrefix + "_mul", coef0_1, Py, c0_c1), + c.call(f1mPrefix + "_mul", coef1_0, Px, c1_c0), + c.call(f1mPrefix + "_mul", coef1_1, Px, c1_c1), + + c.call(ftmPrefix + "_mul014", F, coef2, c1, c0, F), + + ); + + } + buildELL(); + + function buildMillerLoop() { + const f = module.addFunction(prefix+ "_millerLoop"); + f.addParam("ppreP", "i32"); + f.addParam("ppreQ", "i32"); + f.addParam("r", "i32"); + f.addLocal("pCoef", "i32"); + f.addLocal("i", "i32"); + + const c = f.getCodeBuilder(); + + const preP = c.getLocal("ppreP"); + + const coefs = c.getLocal("pCoef"); + + const F = c.getLocal("r"); + + + f.addCode( + c.call(ftmPrefix + "_one", F), + + c.if( + c.call(g1mPrefix + "_isZero", preP), + c.ret([]) + ), + c.if( + c.call(g1mPrefix + "_isZero", c.getLocal("ppreQ")), + c.ret([]) + ), + c.setLocal("pCoef", c.i32_add( c.getLocal("ppreQ"), c.i32_const(f2size*3))), + + c.setLocal("i", c.i32_const(ateLoopBitBytes.length-2)), + c.block(c.loop( + + + c.call(prefix + "_ell", preP, coefs, F), + c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + + c.if( + c.i32_load8_s(c.getLocal("i"), pAteLoopBitBytes), + [ + ...c.call(prefix + "_ell", preP, coefs, F), + ...c.setLocal("pCoef", c.i32_add(c.getLocal("pCoef"), c.i32_const(ateCoefSize))), + ] + ), + c.call(ftmPrefix + "_square", F, F), + + c.br_if(1, c.i32_eq ( c.getLocal("i"), c.i32_const(1) )), + c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )), + c.call(prefix + "_ell", preP, coefs, F), + + ); + + + { + f.addCode( + c.call(ftmPrefix + "_conjugate", F, F), + ); + } + } + + + function buildFrobeniusMap(n) { + const F12 = [ + [ + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + ], + [ + [1n, 0n], + [3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n, 151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n], + [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n, 0n], + [2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n, 1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n], + [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n, 0n], + [3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n, 877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n], + [4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n, 0n], + [151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027n, 3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760n], + [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n, 0n], + [1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257n, 2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530n], + [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n, 0n], + [877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230n, 3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557n], + ] + ]; + + const F6 = [ + [ + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + [1n, 0n], + ], + [ + [1n, 0n], + [0n, 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n], + [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n, 0n], + [0n, 1n], + [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n, 0n], + [0n, 793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n], + ], + [ + [1n, 0n], + [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437n, 0n], + [4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436n, 0n], + [4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786n, 0n], + [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350n, 0n], + [793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351n, 0n], + ] + ]; + + const f = module.addFunction(ftmPrefix + "_frobeniusMap"+n); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + for (let i=0; i<6; i++) { + const X = (i==0) ? c.getLocal("x") : c.i32_add(c.getLocal("x"), c.i32_const(i*f2size)); + const Xc0 = X; + const Xc1 = c.i32_add(c.getLocal("x"), c.i32_const(i*f2size + f1size)); + const R = (i==0) ? c.getLocal("r") : c.i32_add(c.getLocal("r"), c.i32_const(i*f2size)); + const Rc0 = R; + const Rc1 = c.i32_add(c.getLocal("r"), c.i32_const(i*f2size + f1size)); + const coef = mul2(F12[Math.floor(i/3)][n%12] , F6[i%3][n%6]); + const pCoef = module.alloc([ + ...utils$1.bigInt2BytesLE(toMontgomery(coef[0]), n8q), + ...utils$1.bigInt2BytesLE(toMontgomery(coef[1]), n8q), + ]); + if (n%2 == 1) { + f.addCode( + c.call(f1mPrefix + "_copy", Xc0, Rc0), + c.call(f1mPrefix + "_neg", Xc1, Rc1), + c.call(f2mPrefix + "_mul", R, c.i32_const(pCoef), R), + ); + } else { + f.addCode(c.call(f2mPrefix + "_mul", X, c.i32_const(pCoef), R)); + } + } + + function mul2(a, b) { + const ac0 = a[0]; + const ac1 = a[1]; + const bc0 = b[0]; + const bc1 = b[1]; + const res = [ + (ac0 * bc0 - (ac1 * bc1)) % q, + (ac0 * bc1 + (ac1 * bc0)) % q, + ]; + if (isNegative$1(res[0])) res[0] = res[0] + q; + return res; + } + + } + + + function buildCyclotomicSquare() { + const f = module.addFunction(prefix+ "__cyclotomicSquare"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const x0 = c.getLocal("x"); + const x4 = c.i32_add(c.getLocal("x"), c.i32_const(f2size)); + const x3 = c.i32_add(c.getLocal("x"), c.i32_const(2*f2size)); + const x2 = c.i32_add(c.getLocal("x"), c.i32_const(3*f2size)); + const x1 = c.i32_add(c.getLocal("x"), c.i32_const(4*f2size)); + const x5 = c.i32_add(c.getLocal("x"), c.i32_const(5*f2size)); + + const r0 = c.getLocal("r"); + const r4 = c.i32_add(c.getLocal("r"), c.i32_const(f2size)); + const r3 = c.i32_add(c.getLocal("r"), c.i32_const(2*f2size)); + const r2 = c.i32_add(c.getLocal("r"), c.i32_const(3*f2size)); + const r1 = c.i32_add(c.getLocal("r"), c.i32_const(4*f2size)); + const r5 = c.i32_add(c.getLocal("r"), c.i32_const(5*f2size)); + + const t0 = c.i32_const(module.alloc(f2size)); + const t1 = c.i32_const(module.alloc(f2size)); + const t2 = c.i32_const(module.alloc(f2size)); + const t3 = c.i32_const(module.alloc(f2size)); + const t4 = c.i32_const(module.alloc(f2size)); + const t5 = c.i32_const(module.alloc(f2size)); + const tmp = c.i32_const(module.alloc(f2size)); + const AUX = c.i32_const(module.alloc(f2size)); + + + f.addCode( + // // t0 + t1*y = (z0 + z1*y)^2 = a^2 + // tmp = z0 * z1; + // t0 = (z0 + z1) * (z0 + my_Fp6::non_residue * z1) - tmp - my_Fp6::non_residue * tmp; + // t1 = tmp + tmp; + c.call(f2mPrefix + "_mul", x0, x1, tmp), + c.call(f2mPrefix + "_mulNR", x1, t0), + c.call(f2mPrefix + "_add", x0, t0, t0), + c.call(f2mPrefix + "_add", x0, x1, AUX), + c.call(f2mPrefix + "_mul", AUX, t0, t0), + c.call(f2mPrefix + "_mulNR", tmp, AUX), + c.call(f2mPrefix + "_add", tmp, AUX, AUX), + c.call(f2mPrefix + "_sub", t0, AUX, t0), + c.call(f2mPrefix + "_add", tmp, tmp, t1), + + // // t2 + t3*y = (z2 + z3*y)^2 = b^2 + // tmp = z2 * z3; + // t2 = (z2 + z3) * (z2 + my_Fp6::non_residue * z3) - tmp - my_Fp6::non_residue * tmp; + // t3 = tmp + tmp; + c.call(f2mPrefix + "_mul", x2, x3, tmp), + c.call(f2mPrefix + "_mulNR", x3, t2), + c.call(f2mPrefix + "_add", x2, t2, t2), + c.call(f2mPrefix + "_add", x2, x3, AUX), + c.call(f2mPrefix + "_mul", AUX, t2, t2), + c.call(f2mPrefix + "_mulNR", tmp, AUX), + c.call(f2mPrefix + "_add", tmp, AUX, AUX), + c.call(f2mPrefix + "_sub", t2, AUX, t2), + c.call(f2mPrefix + "_add", tmp, tmp, t3), + + // // t4 + t5*y = (z4 + z5*y)^2 = c^2 + // tmp = z4 * z5; + // t4 = (z4 + z5) * (z4 + my_Fp6::non_residue * z5) - tmp - my_Fp6::non_residue * tmp; + // t5 = tmp + tmp; + c.call(f2mPrefix + "_mul", x4, x5, tmp), + c.call(f2mPrefix + "_mulNR", x5, t4), + c.call(f2mPrefix + "_add", x4, t4, t4), + c.call(f2mPrefix + "_add", x4, x5, AUX), + c.call(f2mPrefix + "_mul", AUX, t4, t4), + c.call(f2mPrefix + "_mulNR", tmp, AUX), + c.call(f2mPrefix + "_add", tmp, AUX, AUX), + c.call(f2mPrefix + "_sub", t4, AUX, t4), + c.call(f2mPrefix + "_add", tmp, tmp, t5), + + // For A + // z0 = 3 * t0 - 2 * z0 + c.call(f2mPrefix + "_sub", t0, x0, r0), + c.call(f2mPrefix + "_add", r0, r0, r0), + c.call(f2mPrefix + "_add", t0, r0, r0), + // z1 = 3 * t1 + 2 * z1 + c.call(f2mPrefix + "_add", t1, x1, r1), + c.call(f2mPrefix + "_add", r1, r1, r1), + c.call(f2mPrefix + "_add", t1, r1, r1), + + // For B + // z2 = 3 * (xi * t5) + 2 * z2 + c.call(f2mPrefix + "_mul", t5, c.i32_const(pBls12381Twist), AUX), + c.call(f2mPrefix + "_add", AUX, x2, r2), + c.call(f2mPrefix + "_add", r2, r2, r2), + c.call(f2mPrefix + "_add", AUX, r2, r2), + // z3 = 3 * t4 - 2 * z3 + c.call(f2mPrefix + "_sub", t4, x3, r3), + c.call(f2mPrefix + "_add", r3, r3, r3), + c.call(f2mPrefix + "_add", t4, r3, r3), + + // For C + // z4 = 3 * t2 - 2 * z4 + c.call(f2mPrefix + "_sub", t2, x4, r4), + c.call(f2mPrefix + "_add", r4, r4, r4), + c.call(f2mPrefix + "_add", t2, r4, r4), + // z5 = 3 * t3 + 2 * z5 + c.call(f2mPrefix + "_add", t3, x5, r5), + c.call(f2mPrefix + "_add", r5, r5, r5), + c.call(f2mPrefix + "_add", t3, r5, r5), + + ); + } + + + function buildCyclotomicExp(exponent, isExpNegative, fnName) { + const exponentNafBytes = naf(exponent).map( (b) => (b==-1 ? 0xFF: b) ); + const pExponentNafBytes = module.alloc(exponentNafBytes); + // const pExponent = module.alloc(utils.bigInt2BytesLE(exponent, n8)); + + const f = module.addFunction(prefix+ "__cyclotomicExp_"+fnName); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + f.addLocal("bit", "i32"); + f.addLocal("i", "i32"); + + const c = f.getCodeBuilder(); + + const x = c.getLocal("x"); + + const res = c.getLocal("r"); + + const inverse = c.i32_const(module.alloc(ftsize)); + + + f.addCode( + c.call(ftmPrefix + "_conjugate", x, inverse), + c.call(ftmPrefix + "_one", res), + + c.if( + c.teeLocal("bit", c.i32_load8_s(c.i32_const(exponentNafBytes.length-1), pExponentNafBytes)), + c.if( + c.i32_eq( + c.getLocal("bit"), + c.i32_const(1) + ), + c.call(ftmPrefix + "_mul", res, x, res), + c.call(ftmPrefix + "_mul", res, inverse, res), + ) + ), + + c.setLocal("i", c.i32_const(exponentNafBytes.length-2)), + c.block(c.loop( + c.call(prefix + "__cyclotomicSquare", res, res), + c.if( + c.teeLocal("bit", c.i32_load8_s(c.getLocal("i"), pExponentNafBytes)), + c.if( + c.i32_eq( + c.getLocal("bit"), + c.i32_const(1) + ), + c.call(ftmPrefix + "_mul", res, x, res), + c.call(ftmPrefix + "_mul", res, inverse, res), + ) + ), + c.br_if(1, c.i32_eqz ( c.getLocal("i") )), + c.setLocal("i", c.i32_sub(c.getLocal("i"), c.i32_const(1))), + c.br(0) + )) + ); + + if (isExpNegative) { + f.addCode( + c.call(ftmPrefix + "_conjugate", res, res), + ); + } + + } + + function buildFinalExponentiation() { + buildCyclotomicSquare(); + buildCyclotomicExp(finalExpZ, finalExpIsNegative, "w0"); + + const f = module.addFunction(prefix+ "_finalExponentiation"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const c = f.getCodeBuilder(); + + const elt = c.getLocal("x"); + const res = c.getLocal("r"); + const t0 = c.i32_const(module.alloc(ftsize)); + const t1 = c.i32_const(module.alloc(ftsize)); + const t2 = c.i32_const(module.alloc(ftsize)); + const t3 = c.i32_const(module.alloc(ftsize)); + const t4 = c.i32_const(module.alloc(ftsize)); + const t5 = c.i32_const(module.alloc(ftsize)); + const t6 = c.i32_const(module.alloc(ftsize)); + + f.addCode( + + // let mut t0 = f.frobenius_map(6) + c.call(ftmPrefix + "_frobeniusMap6", elt, t0), + + // let t1 = f.invert() + c.call(ftmPrefix + "_inverse", elt, t1), + + // let mut t2 = t0 * t1; + c.call(ftmPrefix + "_mul", t0, t1, t2), + + // t1 = t2.clone(); + c.call(ftmPrefix + "_copy", t2, t1), + + // t2 = t2.frobenius_map().frobenius_map(); + c.call(ftmPrefix + "_frobeniusMap2", t2, t2), + + // t2 *= t1; + c.call(ftmPrefix + "_mul", t2, t1, t2), + + + // t1 = cyclotomic_square(t2).conjugate(); + c.call(prefix + "__cyclotomicSquare", t2, t1), + c.call(ftmPrefix + "_conjugate", t1, t1), + + // let mut t3 = cycolotomic_exp(t2); + c.call(prefix + "__cyclotomicExp_w0", t2, t3), + + // let mut t4 = cyclotomic_square(t3); + c.call(prefix + "__cyclotomicSquare", t3, t4), + + // let mut t5 = t1 * t3; + c.call(ftmPrefix + "_mul", t1, t3, t5), + + // t1 = cycolotomic_exp(t5); + c.call(prefix + "__cyclotomicExp_w0", t5, t1), + + // t0 = cycolotomic_exp(t1); + c.call(prefix + "__cyclotomicExp_w0", t1, t0), + + // let mut t6 = cycolotomic_exp(t0); + c.call(prefix + "__cyclotomicExp_w0", t0, t6), + + // t6 *= t4; + c.call(ftmPrefix + "_mul", t6, t4, t6), + + // t4 = cycolotomic_exp(t6); + c.call(prefix + "__cyclotomicExp_w0", t6, t4), + + // t5 = t5.conjugate(); + c.call(ftmPrefix + "_conjugate", t5, t5), + + // t4 *= t5 * t2; + c.call(ftmPrefix + "_mul", t4, t5, t4), + c.call(ftmPrefix + "_mul", t4, t2, t4), + + // t5 = t2.conjugate(); + c.call(ftmPrefix + "_conjugate", t2, t5), + + // t1 *= t2; + c.call(ftmPrefix + "_mul", t1, t2, t1), + + // t1 = t1.frobenius_map().frobenius_map().frobenius_map(); + c.call(ftmPrefix + "_frobeniusMap3", t1, t1), + + // t6 *= t5; + c.call(ftmPrefix + "_mul", t6, t5, t6), + + // t6 = t6.frobenius_map(); + c.call(ftmPrefix + "_frobeniusMap1", t6, t6), + + // t3 *= t0; + c.call(ftmPrefix + "_mul", t3, t0, t3), + + // t3 = t3.frobenius_map().frobenius_map(); + c.call(ftmPrefix + "_frobeniusMap2", t3, t3), + + // t3 *= t1; + c.call(ftmPrefix + "_mul", t3, t1, t3), + + // t3 *= t6; + c.call(ftmPrefix + "_mul", t3, t6, t3), + + // f = t3 * t4; + c.call(ftmPrefix + "_mul", t3, t4, res), + + ); + } + + + function buildFinalExponentiationOld() { + const f = module.addFunction(prefix+ "_finalExponentiationOld"); + f.addParam("x", "i32"); + f.addParam("r", "i32"); + + const exponent = 322277361516934140462891564586510139908379969514828494218366688025288661041104682794998680497580008899973249814104447692778988208376779573819485263026159588510513834876303014016798809919343532899164848730280942609956670917565618115867287399623286813270357901731510188149934363360381614501334086825442271920079363289954510565375378443704372994881406797882676971082200626541916413184642520269678897559532260949334760604962086348898118982248842634379637598665468817769075878555493752214492790122785850202957575200176084204422751485957336465472324810982833638490904279282696134323072515220044451592646885410572234451732790590013479358343841220074174848221722017083597872017638514103174122784843925578370430843522959600095676285723737049438346544753168912974976791528535276317256904336520179281145394686565050419250614107803233314658825463117900250701199181529205942363159325765991819433914303908860460720581408201373164047773794825411011922305820065611121544561808414055302212057471395719432072209245600258134364584636810093520285711072578721435517884103526483832733289802426157301542744476740008494780363354305116978805620671467071400711358839553375340724899735460480144599782014906586543813292157922220645089192130209334926661588737007768565838519456601560804957985667880395221049249803753582637708560n; + + const pExponent = module.alloc(utils$1.bigInt2BytesLE( exponent, 544 )); + + const c = f.getCodeBuilder(); + + f.addCode( + c.call(ftmPrefix + "_exp", c.getLocal("x"), c.i32_const(pExponent), c.i32_const(544), c.getLocal("r")), + ); + } + + + const pPreP = module.alloc(prePSize); + const pPreQ = module.alloc(preQSize); + + function buildPairingEquation(nPairings) { + + const f = module.addFunction(prefix+ "_pairingEq"+nPairings); + for (let i=0; i. +*/ + +// module.exports.bn128_wasm = require("./build/bn128_wasm.js"); +// module.exports.bls12381_wasm = require("./build/bls12381_wasm.js"); +// module.exports.mnt6753_wasm = require("./build/mnt6753_wasm.js"); + +var buildBn128$1 = build_bn128; +var buildBls12381$1 = build_bls12381; + +/* global BigInt */ + +function stringifyBigInts(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); + } else if (typeof o == "object") { + const res = {}; + const keys = Object.keys(o); + keys.forEach((k) => { + res[k] = stringifyBigInts(o[k]); + }); + return res; + } else { + return o; + } +} + +function unstringifyBigInts(o) { + if (typeof o == "string" && /^[0-9]+$/.test(o)) { + return BigInt(o); + } else if (typeof o == "string" && /^0x[0-9a-fA-F]+$/.test(o)) { + return BigInt(o); + } else if (Array.isArray(o)) { + return o.map(unstringifyBigInts); + } else if (typeof o == "object") { + if (o === null) return null; + const res = {}; + const keys = Object.keys(o); + keys.forEach((k) => { + res[k] = unstringifyBigInts(o[k]); + }); + return res; + } else { + return o; + } +} + +function beBuff2int(buff) { + let res = BigInt(0); + 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(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 & 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; +} + +function leBuff2int(buff) { + let res = BigInt(0); + let i = 0; + const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength); + while (i < buff.length) { + if (i + 4 <= buff.length) { + res += BigInt(buffV.getUint32(i, true)) << BigInt(i * 8); + i += 4; + } else if (i + 2 <= buff.length) { + res += BigInt(buffV.getUint16(i, true)) << BigInt(i * 8); + i += 2; + } else { + res += BigInt(buffV.getUint8(i, true)) << BigInt(i * 8); + i += 1; + } + } + return res; +} + +function leInt2Buff(n, len) { + let r = n; + if (typeof len === "undefined") { + len = Math.floor((bitLength$6(n) - 1) / 8) + 1; + if (len == 0) len = 1; + } + const buff = new Uint8Array(len); + const buffV = new DataView(buff.buffer); + let o = 0; + while (o < len) { + if (o + 4 <= len) { + buffV.setUint32(o, Number(r & BigInt(0xffffffff)), true); + o += 4; + r = r >> BigInt(32); + } else if (o + 2 <= len) { + buffV.setUint16(o, Number(r & BigInt(0xffff)), true); + o += 2; + r = r >> BigInt(16); + } else { + buffV.setUint8(o, Number(r & BigInt(0xff)), true); + o += 1; + r = r >> BigInt(8); + } + } + if (r) { + throw new Error("Number does not fit in this length"); + } + return buff; +} + +function stringifyFElements(F, o) { + if (typeof o == "bigint" || o.eq !== undefined) { + return o.toString(10); + } else if (o instanceof Uint8Array) { + return F.toString(F.e(o)); + } else if (Array.isArray(o)) { + return o.map(stringifyFElements.bind(this, F)); + } else if (typeof o == "object") { + const res = {}; + const keys = Object.keys(o); + keys.forEach((k) => { + res[k] = stringifyFElements(F, o[k]); + }); + return res; + } else { + return o; + } +} + +function unstringifyFElements(F, o) { + if (typeof o == "string" && /^[0-9]+$/.test(o)) { + return F.e(o); + } else if (typeof o == "string" && /^0x[0-9a-fA-F]+$/.test(o)) { + return F.e(o); + } else if (Array.isArray(o)) { + return o.map(unstringifyFElements.bind(this, F)); + } else if (typeof o == "object") { + if (o === null) return null; + const res = {}; + const keys = Object.keys(o); + keys.forEach((k) => { + res[k] = unstringifyFElements(F, o[k]); + }); + return res; + } else { + return o; + } +} + +const _revTable = []; +for (let i = 0; i < 256; i++) { + _revTable[i] = _revSlow(i, 8); +} + +function _revSlow(idx, bits) { + let res = 0; + let a = idx; + for (let i = 0; i < bits; i++) { + res <<= 1; + res = res | (a & 1); + a >>= 1; + } + return res; +} + +function bitReverse(idx, bits) { + return ( + (_revTable[idx >>> 24] | + (_revTable[(idx >>> 16) & 0xff] << 8) | + (_revTable[(idx >>> 8) & 0xff] << 16) | + (_revTable[idx & 0xff] << 24)) >>> + (32 - bits) + ); +} + +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 buffReverseBits(buff, eSize) { + const n = buff.byteLength / eSize; + const bits = log2(n); + if (n != 1 << bits) { + throw new Error("Invalid number of pointers"); + } + for (let i = 0; i < n; i++) { + const r = bitReverse(i, bits); + if (i > r) { + 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); + } + } +} + +function array2buffer(arr, sG) { + const buff = new Uint8Array(sG * arr.length); + + for (let i = 0; i < arr.length; i++) { + buff.set(arr[i], i * sG); + } + + return buff; +} + +function buffer2array(buff, sG) { + const n = buff.byteLength / sG; + const arr = new Array(n); + for (let i = 0; i < n; i++) { + arr[i] = buff.slice(i * sG, i * sG + sG); + } + return arr; +} + +var _utils = /*#__PURE__*/Object.freeze({ + __proto__: null, + array2buffer: array2buffer, + beBuff2int: beBuff2int, + beInt2Buff: beInt2Buff, + bitReverse: bitReverse, + buffReverseBits: buffReverseBits, + buffer2array: buffer2array, + leBuff2int: leBuff2int, + leInt2Buff: leInt2Buff, + log2: log2, + stringifyBigInts: stringifyBigInts, + stringifyFElements: stringifyFElements, + unstringifyBigInts: unstringifyBigInts, + unstringifyFElements: unstringifyFElements +}); + +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) { + if ((buff instanceof BigBuffer)&&(buff.buffers.length==1)) { + return this.buffers[firstPage].set(buff.buffers[0], offset % PAGE_SIZE); + } else { + 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$4(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 stringToBase64(str) { + { + return globalThis.btoa(str); + } +} + +const threadSource = stringToBase64("(" + "function thread(self) {\n const MAXMEM = 32767;\n let instance;\n let memory;\n\n if (self) {\n self.onmessage = function(e) {\n let data;\n if (e.data) {\n data = e.data;\n } else {\n data = e;\n }\n\n if (data[0].cmd == \"INIT\") {\n init(data[0]).then(function() {\n self.postMessage(data.result);\n });\n } else if (data[0].cmd == \"TERMINATE\") {\n self.close();\n } else {\n const res = runTask(data);\n self.postMessage(res);\n }\n };\n }\n\n async function init(data) {\n const code = new Uint8Array(data.code);\n const wasmModule = await WebAssembly.compile(code);\n memory = new WebAssembly.Memory({initial:data.init, maximum: MAXMEM});\n\n instance = await WebAssembly.instantiate(wasmModule, {\n env: {\n \"memory\": memory\n }\n });\n }\n\n\n\n function alloc(length) {\n const u32 = new Uint32Array(memory.buffer, 0, 1);\n while (u32[0] & 3) u32[0]++; // Return always aligned pointers\n const res = u32[0];\n u32[0] += length;\n if (u32[0] + length > memory.buffer.byteLength) {\n const currentPages = memory.buffer.byteLength / 0x10000;\n let requiredPages = Math.floor((u32[0] + length) / 0x10000)+1;\n if (requiredPages>MAXMEM) requiredPages=MAXMEM;\n memory.grow(requiredPages-currentPages);\n }\n return res;\n }\n\n function allocBuffer(buffer) {\n const p = alloc(buffer.byteLength);\n setBuffer(p, buffer);\n return p;\n }\n\n function getBuffer(pointer, length) {\n const u8 = new Uint8Array(memory.buffer);\n return new Uint8Array(u8.buffer, u8.byteOffset + pointer, length);\n }\n\n function setBuffer(pointer, buffer) {\n const u8 = new Uint8Array(memory.buffer);\n u8.set(new Uint8Array(buffer), pointer);\n }\n\n function runTask(task) {\n if (task[0].cmd == \"INIT\") {\n return init(task[0]);\n }\n const ctx = {\n vars: [],\n out: []\n };\n const u32a = new Uint32Array(memory.buffer, 0, 1);\n const oldAlloc = u32a[0];\n for (let i=0; i64) 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]); + } + + 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); + }; +} + +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 = array2buffer(buff, sIn); + returnArray = true; + } else { + buff = buff.slice(0, buff.byteLength); + } + + 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 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 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; + }; +} + +async function buildEngine(params) { + + const tm = await buildThreadManager(params.wasm, params.singleThread); + + + const curve = {}; + + curve.q = e(params.wasm.q.toString()); + curve.r = e(params.wasm.r.toString()); + 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. +*/ + +function toNumber(n) { + return BigInt(n); +} + +function isNegative(n) { + return n < 0n; +} + +function isZero(n) { + return n === 0n; +} + +function bitLength(n) { + if (isNegative(n)) { + return n.toString(2).length - 1; // discard the - sign + } else { + return n.toString(2).length; + } +} + +function u32(n) { + const b = []; + const v = toNumber(n); + b.push(Number(v & 0xFFn)); + b.push(Number(v >> 8n & 0xFFn)); + b.push(Number(v >> 16n & 0xFFn)); + b.push(Number(v >> 24n & 0xFFn)); + return b; +} + +function toUTF8Array(str) { + var utf8 = []; + for (var i=0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) utf8.push(charcode); + else if (charcode < 0x800) { + utf8.push(0xc0 | (charcode >> 6), + 0x80 | (charcode & 0x3f)); + } + else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | (charcode >> 12), + 0x80 | ((charcode>>6) & 0x3f), + 0x80 | (charcode & 0x3f)); + } + // surrogate pair + else { + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 0x10000 + (((charcode & 0x3ff)<<10) + | (str.charCodeAt(i) & 0x3ff)); + utf8.push(0xf0 | (charcode >>18), + 0x80 | ((charcode>>12) & 0x3f), + 0x80 | ((charcode>>6) & 0x3f), + 0x80 | (charcode & 0x3f)); + } + } + return utf8; +} + +function string(str) { + const bytes = toUTF8Array(str); + return [ ...varuint32(bytes.length), ...bytes ]; +} + +function varuint(n) { + const code = []; + let v = toNumber(n); + if (isNegative(v)) throw new Error("Number cannot be negative"); + while (!isZero(v)) { + code.push(Number(v & 0x7Fn)); + v = v >> 7n; + } + if (code.length==0) code.push(0); + for (let i=0; i 0xFFFFFFFFn) throw new Error("Number too big"); + if (v > 0x7FFFFFFFn) v = v - 0x100000000n; + // bigInt("-80000000", 16) as base10 + if (v < -2147483648n) throw new Error("Number too small"); + return varint(v); +} + +function varint64(n) { + let v = toNumber(n); + if (v > 0xFFFFFFFFFFFFFFFFn) throw new Error("Number too big"); + if (v > 0x7FFFFFFFFFFFFFFFn) v = v - 0x10000000000000000n; + // bigInt("-8000000000000000", 16) as base10 + if (v < -9223372036854775808n) throw new Error("Number too small"); + return varint(v); +} + +function varuint32(n) { + let v = toNumber(n); + if (v > 0xFFFFFFFFn) throw new Error("Number too big"); + return varuint(v); +} + +function toHexString(byteArray) { + return Array.from(byteArray, function(byte) { + return ("0" + (byte & 0xFF).toString(16)).slice(-2); + }).join(""); +} + +/* + Copyright 2019 0KIMS association. + + This file is part of wasmbuilder + + wasmbuilder 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. + + wasmbuilder 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 wasmbuilder. If not, see . +*/ + + +class CodeBuilder { + constructor(func) { + this.func = func; + this.functionName = func.functionName; + this.module = func.module; + } + + setLocal(localName, valCode) { + const idx = this.func.localIdxByName[localName]; + if (idx === undefined) + throw new Error(`Local Variable not defined: Function: ${this.functionName} local: ${localName} `); + return [...valCode, 0x21, ...varuint32( idx )]; + } + + teeLocal(localName, valCode) { + const idx = this.func.localIdxByName[localName]; + if (idx === undefined) + throw new Error(`Local Variable not defined: Function: ${this.functionName} local: ${localName} `); + return [...valCode, 0x22, ...varuint32( idx )]; + } + + getLocal(localName) { + const idx = this.func.localIdxByName[localName]; + if (idx === undefined) + throw new Error(`Local Variable not defined: Function: ${this.functionName} local: ${localName} `); + return [0x20, ...varuint32( idx )]; + } + + i64_load8_s(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 0 : _align; // 8 bits alignment by default + return [...idxCode, 0x30, align, ...varuint32(offset)]; + } + + i64_load8_u(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 0 : _align; // 8 bits alignment by default + return [...idxCode, 0x31, align, ...varuint32(offset)]; + } + + i64_load16_s(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 1 : _align; // 16 bits alignment by default + return [...idxCode, 0x32, align, ...varuint32(offset)]; + } + + i64_load16_u(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 1 : _align; // 16 bits alignment by default + return [...idxCode, 0x33, align, ...varuint32(offset)]; + } + + i64_load32_s(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 2 : _align; // 32 bits alignment by default + return [...idxCode, 0x34, align, ...varuint32(offset)]; + } + + i64_load32_u(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 2 : _align; // 32 bits alignment by default + return [...idxCode, 0x35, align, ...varuint32(offset)]; + } + + i64_load(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 3 : _align; // 64 bits alignment by default + return [...idxCode, 0x29, align, ...varuint32(offset)]; + } + + + i64_store(idxCode, _offset, _align, _codeVal) { + let offset, align, codeVal; + if (Array.isArray(_offset)) { + offset = 0; + align = 3; + codeVal = _offset; + } else if (Array.isArray(_align)) { + offset = _offset; + align = 3; + codeVal = _align; + } else if (Array.isArray(_codeVal)) { + offset = _offset; + align = _align; + codeVal = _codeVal; + } + return [...idxCode, ...codeVal, 0x37, align, ...varuint32(offset)]; + } + + i64_store32(idxCode, _offset, _align, _codeVal) { + let offset, align, codeVal; + if (Array.isArray(_offset)) { + offset = 0; + align = 2; + codeVal = _offset; + } else if (Array.isArray(_align)) { + offset = _offset; + align = 2; + codeVal = _align; + } else if (Array.isArray(_codeVal)) { + offset = _offset; + align = _align; + codeVal = _codeVal; + } + return [...idxCode, ...codeVal, 0x3e, align, ...varuint32(offset)]; + } + + + i64_store16(idxCode, _offset, _align, _codeVal) { + let offset, align, codeVal; + if (Array.isArray(_offset)) { + offset = 0; + align = 1; + codeVal = _offset; + } else if (Array.isArray(_align)) { + offset = _offset; + align = 1; + codeVal = _align; + } else if (Array.isArray(_codeVal)) { + offset = _offset; + align = _align; + codeVal = _codeVal; + } + return [...idxCode, ...codeVal, 0x3d, align, ...varuint32(offset)]; + } + + + i64_store8(idxCode, _offset, _align, _codeVal) { + let offset, align, codeVal; + if (Array.isArray(_offset)) { + offset = 0; + align = 0; + codeVal = _offset; + } else if (Array.isArray(_align)) { + offset = _offset; + align = 0; + codeVal = _align; + } else if (Array.isArray(_codeVal)) { + offset = _offset; + align = _align; + codeVal = _codeVal; + } + return [...idxCode, ...codeVal, 0x3c, align, ...varuint32(offset)]; + } + + i32_load8_s(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 0 : _align; // 32 bits alignment by default + return [...idxCode, 0x2c, align, ...varuint32(offset)]; + } + + i32_load8_u(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 0 : _align; // 32 bits alignment by default + return [...idxCode, 0x2d, align, ...varuint32(offset)]; + } + + i32_load16_s(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 1 : _align; // 32 bits alignment by default + return [...idxCode, 0x2e, align, ...varuint32(offset)]; + } + + i32_load16_u(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 1 : _align; // 32 bits alignment by default + return [...idxCode, 0x2f, align, ...varuint32(offset)]; + } + + i32_load(idxCode, _offset, _align) { + const offset = _offset || 0; + const align = (_align === undefined) ? 2 : _align; // 32 bits alignment by default + return [...idxCode, 0x28, align, ...varuint32(offset)]; + } + + i32_store(idxCode, _offset, _align, _codeVal) { + let offset, align, codeVal; + if (Array.isArray(_offset)) { + offset = 0; + align = 2; + codeVal = _offset; + } else if (Array.isArray(_align)) { + offset = _offset; + align = 2; + codeVal = _align; + } else if (Array.isArray(_codeVal)) { + offset = _offset; + align = _align; + codeVal = _codeVal; + } + return [...idxCode, ...codeVal, 0x36, align, ...varuint32(offset)]; + } + + + i32_store16(idxCode, _offset, _align, _codeVal) { + let offset, align, codeVal; + if (Array.isArray(_offset)) { + offset = 0; + align = 1; + codeVal = _offset; + } else if (Array.isArray(_align)) { + offset = _offset; + align = 1; + codeVal = _align; + } else if (Array.isArray(_codeVal)) { + offset = _offset; + align = _align; + codeVal = _codeVal; + } + return [...idxCode, ...codeVal, 0x3b, align, ...varuint32(offset)]; + } + + i32_store8(idxCode, _offset, _align, _codeVal) { + let offset, align, codeVal; + if (Array.isArray(_offset)) { + offset = 0; + align = 0; + codeVal = _offset; + } else if (Array.isArray(_align)) { + offset = _offset; + align = 0; + codeVal = _align; + } else if (Array.isArray(_codeVal)) { + offset = _offset; + align = _align; + codeVal = _codeVal; + } + return [...idxCode, ...codeVal, 0x3a, align, ...varuint32(offset)]; + } + + call(fnName, ...args) { + const idx = this.module.functionIdxByName[fnName]; + if (idx === undefined) + throw new Error(`Function not defined: Function: ${fnName}`); + return [...[].concat(...args), 0x10, ...varuint32(idx)]; + } + + call_indirect(fnIdx, ...args) { + return [...[].concat(...args), ...fnIdx, 0x11, 0, 0]; + } + + if(condCode, thenCode, elseCode) { + if (elseCode) { + return [...condCode, 0x04, 0x40, ...thenCode, 0x05, ...elseCode, 0x0b]; + } else { + return [...condCode, 0x04, 0x40, ...thenCode, 0x0b]; + } + } + + block(bCode) { return [0x02, 0x40, ...bCode, 0x0b]; } + loop(...args) { + return [0x03, 0x40, ...[].concat(...[...args]), 0x0b]; + } + br_if(relPath, condCode) { return [...condCode, 0x0d, ...varuint32(relPath)]; } + br(relPath) { return [0x0c, ...varuint32(relPath)]; } + ret(rCode) { return [...rCode, 0x0f]; } + drop(dCode) { return [...dCode, 0x1a]; } + + i64_const(num) { return [0x42, ...varint64(num)]; } + i32_const(num) { return [0x41, ...varint32(num)]; } + + + i64_eqz(opcode) { return [...opcode, 0x50]; } + i64_eq(op1code, op2code) { return [...op1code, ...op2code, 0x51]; } + i64_ne(op1code, op2code) { return [...op1code, ...op2code, 0x52]; } + i64_lt_s(op1code, op2code) { return [...op1code, ...op2code, 0x53]; } + i64_lt_u(op1code, op2code) { return [...op1code, ...op2code, 0x54]; } + i64_gt_s(op1code, op2code) { return [...op1code, ...op2code, 0x55]; } + i64_gt_u(op1code, op2code) { return [...op1code, ...op2code, 0x56]; } + i64_le_s(op1code, op2code) { return [...op1code, ...op2code, 0x57]; } + i64_le_u(op1code, op2code) { return [...op1code, ...op2code, 0x58]; } + i64_ge_s(op1code, op2code) { return [...op1code, ...op2code, 0x59]; } + i64_ge_u(op1code, op2code) { return [...op1code, ...op2code, 0x5a]; } + i64_add(op1code, op2code) { return [...op1code, ...op2code, 0x7c]; } + i64_sub(op1code, op2code) { return [...op1code, ...op2code, 0x7d]; } + i64_mul(op1code, op2code) { return [...op1code, ...op2code, 0x7e]; } + i64_div_s(op1code, op2code) { return [...op1code, ...op2code, 0x7f]; } + i64_div_u(op1code, op2code) { return [...op1code, ...op2code, 0x80]; } + i64_rem_s(op1code, op2code) { return [...op1code, ...op2code, 0x81]; } + i64_rem_u(op1code, op2code) { return [...op1code, ...op2code, 0x82]; } + i64_and(op1code, op2code) { return [...op1code, ...op2code, 0x83]; } + i64_or(op1code, op2code) { return [...op1code, ...op2code, 0x84]; } + i64_xor(op1code, op2code) { return [...op1code, ...op2code, 0x85]; } + i64_shl(op1code, op2code) { return [...op1code, ...op2code, 0x86]; } + i64_shr_s(op1code, op2code) { return [...op1code, ...op2code, 0x87]; } + i64_shr_u(op1code, op2code) { return [...op1code, ...op2code, 0x88]; } + i64_extend_i32_s(op1code) { return [...op1code, 0xac]; } + i64_extend_i32_u(op1code) { return [...op1code, 0xad]; } + i64_clz(op1code) { return [...op1code, 0x79]; } + i64_ctz(op1code) { return [...op1code, 0x7a]; } + + i32_eqz(op1code) { return [...op1code, 0x45]; } + i32_eq(op1code, op2code) { return [...op1code, ...op2code, 0x46]; } + i32_ne(op1code, op2code) { return [...op1code, ...op2code, 0x47]; } + i32_lt_s(op1code, op2code) { return [...op1code, ...op2code, 0x48]; } + i32_lt_u(op1code, op2code) { return [...op1code, ...op2code, 0x49]; } + i32_gt_s(op1code, op2code) { return [...op1code, ...op2code, 0x4a]; } + i32_gt_u(op1code, op2code) { return [...op1code, ...op2code, 0x4b]; } + i32_le_s(op1code, op2code) { return [...op1code, ...op2code, 0x4c]; } + i32_le_u(op1code, op2code) { return [...op1code, ...op2code, 0x4d]; } + i32_ge_s(op1code, op2code) { return [...op1code, ...op2code, 0x4e]; } + i32_ge_u(op1code, op2code) { return [...op1code, ...op2code, 0x4f]; } + i32_add(op1code, op2code) { return [...op1code, ...op2code, 0x6a]; } + i32_sub(op1code, op2code) { return [...op1code, ...op2code, 0x6b]; } + i32_mul(op1code, op2code) { return [...op1code, ...op2code, 0x6c]; } + i32_div_s(op1code, op2code) { return [...op1code, ...op2code, 0x6d]; } + i32_div_u(op1code, op2code) { return [...op1code, ...op2code, 0x6e]; } + i32_rem_s(op1code, op2code) { return [...op1code, ...op2code, 0x6f]; } + i32_rem_u(op1code, op2code) { return [...op1code, ...op2code, 0x70]; } + i32_and(op1code, op2code) { return [...op1code, ...op2code, 0x71]; } + i32_or(op1code, op2code) { return [...op1code, ...op2code, 0x72]; } + i32_xor(op1code, op2code) { return [...op1code, ...op2code, 0x73]; } + i32_shl(op1code, op2code) { return [...op1code, ...op2code, 0x74]; } + i32_shr_s(op1code, op2code) { return [...op1code, ...op2code, 0x75]; } + i32_shr_u(op1code, op2code) { return [...op1code, ...op2code, 0x76]; } + i32_rotl(op1code, op2code) { return [...op1code, ...op2code, 0x77]; } + i32_rotr(op1code, op2code) { return [...op1code, ...op2code, 0x78]; } + i32_wrap_i64(op1code) { return [...op1code, 0xa7]; } + i32_clz(op1code) { return [...op1code, 0x67]; } + i32_ctz(op1code) { return [...op1code, 0x68]; } + + unreachable() { return [ 0x0 ]; } + + current_memory() { return [ 0x3f, 0]; } + + comment() { return []; } +} + +/* + Copyright 2019 0KIMS association. + + This file is part of wasmbuilder + + wasmbuilder 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. + + wasmbuilder 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 wasmbuilder. If not, see . +*/ + + +const typeCodes = { + "i32": 0x7f, + "i64": 0x7e, + "f32": 0x7d, + "f64": 0x7c, + "anyfunc": 0x70, + "func": 0x60, + "emptyblock": 0x40 +}; + + +class FunctionBuilder { + + constructor (module, fnName, fnType, moduleName, fieldName) { + if (fnType == "import") { + this.fnType = "import"; + this.moduleName = moduleName; + this.fieldName = fieldName; + } else if (fnType == "internal") { + this.fnType = "internal"; + } else { + throw new Error("Invalid function fnType: " + fnType); + } + this.module = module; + this.fnName = fnName; + this.params = []; + this.locals = []; + this.localIdxByName = {}; + this.code = []; + this.returnType = null; + this.nextLocal =0; + } + + addParam(paramName, paramType) { + if (this.localIdxByName[paramName]) + throw new Error(`param already exists. Function: ${this.fnName}, Param: ${paramName} `); + const idx = this.nextLocal++; + this.localIdxByName[paramName] = idx; + this.params.push({ + type: paramType + }); + } + + addLocal(localName, localType, _length) { + const length = _length || 1; + if (this.localIdxByName[localName]) + throw new Error(`local already exists. Function: ${this.fnName}, Param: ${localName} `); + const idx = this.nextLocal++; + this.localIdxByName[localName] = idx; + this.locals.push({ + type: localType, + length: length + }); + } + + setReturnType(returnType) { + if (this.returnType) + throw new Error(`returnType already defined. Function: ${this.fnName}`); + this.returnType = returnType; + } + + getSignature() { + const params = [...varuint32(this.params.length), ...this.params.map((p) => typeCodes[p.type])]; + const returns = this.returnType ? [0x01, typeCodes[this.returnType]] : [0]; + return [0x60, ...params, ...returns]; + } + + getBody() { + const locals = this.locals.map((l) => [ + ...varuint32(l.length), + typeCodes[l.type] + ]); + + const body = [ + ...varuint32(this.locals.length), + ...[].concat(...locals), + ...this.code, + 0x0b + ]; + return [ + ...varuint32(body.length), + ...body + ]; + } + + addCode(...code) { + this.code.push(...[].concat(...[...code])); + } + + getCodeBuilder() { + return new CodeBuilder(this); + } +} + +/* + Copyright 2019 0KIMS association. + + This file is part of wasmbuilder + + wasmbuilder 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. + + wasmbuilder 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 wasmbuilder. If not, see . +*/ + + +class ModuleBuilder { + + constructor() { + this.functions = []; + this.functionIdxByName = {}; + this.nImportFunctions = 0; + this.nInternalFunctions =0; + this.memory = { + pagesSize: 1, + moduleName: "env", + fieldName: "memory" + }; + this.free = 8; + this.datas = []; + this.modules = {}; + this.exports = []; + this.functionsTable = []; + } + + build() { + this._setSignatures(); + return new Uint8Array([ + ...u32(0x6d736100), + ...u32(1), + ...this._buildType(), + ...this._buildImport(), + ...this._buildFunctionDeclarations(), + ...this._buildFunctionsTable(), + ...this._buildExports(), + ...this._buildElements(), + ...this._buildCode(), + ...this._buildData() + ]); + } + + addFunction(fnName) { + if (typeof(this.functionIdxByName[fnName]) !== "undefined") + throw new Error(`Function already defined: ${fnName}`); + + const idx = this.functions.length; + this.functionIdxByName[fnName] = idx; + + this.functions.push(new FunctionBuilder(this, fnName, "internal")); + + this.nInternalFunctions++; + return this.functions[idx]; + } + + addIimportFunction(fnName, moduleName, _fieldName) { + if (typeof(this.functionIdxByName[fnName]) !== "undefined") + throw new Error(`Function already defined: ${fnName}`); + + if ( (this.functions.length>0) + &&(this.functions[this.functions.length-1].type == "internal")) + throw new Error(`Import functions must be declared before internal: ${fnName}`); + + let fieldName = _fieldName || fnName; + + const idx = this.functions.length; + this.functionIdxByName[fnName] = idx; + + this.functions.push(new FunctionBuilder(this, fnName, "import", moduleName, fieldName)); + + this.nImportFunctions ++; + return this.functions[idx]; + } + + setMemory(pagesSize, moduleName, fieldName) { + this.memory = { + pagesSize: pagesSize, + moduleName: moduleName || "env", + fieldName: fieldName || "memory" + }; + } + + exportFunction(fnName, _exportName) { + const exportName = _exportName || fnName; + if (typeof(this.functionIdxByName[fnName]) === "undefined") + throw new Error(`Function not defined: ${fnName}`); + const idx = this.functionIdxByName[fnName]; + if (exportName != fnName) { + this.functionIdxByName[exportName] = idx; + } + this.exports.push({ + exportName: exportName, + idx: idx + }); + } + + addFunctionToTable(fnName) { + const idx = this.functionIdxByName[fnName]; + this.functionsTable.push(idx); + } + + addData(offset, bytes) { + this.datas.push({ + offset: offset, + bytes: bytes + }); + } + + alloc(a, b) { + let size; + let bytes; + if ((Array.isArray(a) || ArrayBuffer.isView(a)) && (typeof(b) === "undefined")) { + size = a.length; + bytes = a; + } else { + size = a; + bytes = b; + } + size = (((size-1)>>3) +1)<<3; // Align to 64 bits. + const p = this.free; + this.free += size; + if (bytes) { + this.addData(p, bytes); + } + return p; + } + + allocString(s) { + const encoder = new globalThis.TextEncoder(); + const uint8array = encoder.encode(s); + return this.alloc([...uint8array, 0]); + } + + _setSignatures() { + this.signatures = []; + const signatureIdxByName = {}; + if (this.functionsTable.length>0) { + const signature = this.functions[this.functionsTable[0]].getSignature(); + const signatureName = "s_"+toHexString(signature); + signatureIdxByName[signatureName] = 0; + this.signatures.push(signature); + } + for (let i=0; i= 0) { + curve = await buildBn128(singleThread, plugins); + } else if (["BLS12381"].indexOf(normName) >= 0) { + curve = await buildBls12381(singleThread, plugins); + } else { + throw new Error(`Curve not supported: ${name}`); + } + return curve; + + function normalizeName(n) { + return n.toUpperCase().match(/[A-Za-z0-9]+/g).join(""); + } + +} + +const Scalar=_Scalar; +const utils = _utils; + +export { BigBuffer, ChaCha, EC, ZqField as F1Field, F2Field, F3Field, PolField, Scalar, ZqField, buildBls12381, buildBn128, getCurveFromName, getCurveFromQ, getCurveFromR, utils }; diff --git a/build/main.cjs b/build/main.cjs index a9b5c5b..7deea6a 100644 --- a/build/main.cjs +++ b/build/main.cjs @@ -1,19 +1,11 @@ 'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); - var crypto = require('crypto'); var wasmcurves = require('wasmcurves'); var os = require('os'); var Worker = require('web-worker'); var wasmbuilder = require('wasmbuilder'); -function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - -var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto); -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]; @@ -263,51 +255,51 @@ const one = e(1); var _Scalar = /*#__PURE__*/Object.freeze({ __proto__: null, - fromString: fromString, + abs: abs, + add: add, + band: band, + bitLength: bitLength, + bits: bits, + bor: bor, + bxor: bxor, + div: div, e: e, + eq: eq, + exp: exp$1, fromArray: fromArray, - bitLength: bitLength, + fromRprBE: fromRprBE, + fromRprLE: fromRprLE, + fromString: fromString, + geq: geq, + gt: gt, isNegative: isNegative, + isOdd: isOdd, isZero: isZero, + land: land, + leq: leq, + lnot: lnot, + lor: lor, + lt: lt, + mod: mod, + mul: mul, + naf: naf, + neg: neg, + neq: neq, + one: one, + pow: pow, shiftLeft: shiftLeft, shiftRight: shiftRight, shl: shl, shr: shr, - isOdd: isOdd, - naf: naf, - bits: bits, - toNumber: toNumber, - toArray: toArray, - add: add, - sub: sub, - neg: neg, - mul: mul, square: square, - pow: pow, - exp: exp$1, - abs: abs, - div: div, - mod: mod, - eq: eq, - neq: neq, - lt: lt, - gt: gt, - leq: leq, - geq: geq, - band: band, - bor: bor, - bxor: bxor, - land: land, - lor: lor, - lnot: lnot, - toRprLE: toRprLE, + sub: sub, + toArray: toArray, + toLEBuff: toLEBuff, + toNumber: toNumber, toRprBE: toRprBE, - fromRprLE: fromRprLE, - fromRprBE: fromRprBE, + toRprLE: toRprLE, toString: toString, - toLEBuff: toLEBuff, - zero: zero, - one: one + zero: zero }); /* @@ -947,6 +939,7 @@ function __bitReverse(p, bits) { */ + function mulScalar(F, base, e) { let res; @@ -1288,7 +1281,7 @@ function getRandomBytes(n) { } } else { // NodeJS - crypto__default["default"].randomFillSync(array); + crypto.randomFillSync(array); } return array; } @@ -1840,6 +1833,7 @@ class ZqField { snarkjs. If not, see . */ + class F2Field { constructor(F, nonResidue) { this.type="F2"; @@ -2077,6 +2071,7 @@ class F2Field { snarkjs. If not, see . */ + class F3Field { constructor(F, nonResidue) { this.type="F3"; @@ -2361,6 +2356,7 @@ class F3Field { */ + function isGreatest(F, a) { if (Array.isArray(a)) { for (let i=a.length-1; i>=0; i--) { @@ -3023,19 +3019,19 @@ function buffer2array(buff, sG) { var _utils = /*#__PURE__*/Object.freeze({ __proto__: null, - stringifyBigInts: stringifyBigInts, - unstringifyBigInts: unstringifyBigInts, + array2buffer: array2buffer, beBuff2int: beBuff2int, beInt2Buff: beInt2Buff, + bitReverse: bitReverse, + buffReverseBits: buffReverseBits, + buffer2array: buffer2array, leBuff2int: leBuff2int, leInt2Buff: leInt2Buff, - stringifyFElements: stringifyFElements, - unstringifyFElements: unstringifyFElements, - bitReverse: bitReverse, log2: log2, - buffReverseBits: buffReverseBits, - array2buffer: array2buffer, - buffer2array: buffer2array + stringifyBigInts: stringifyBigInts, + stringifyFElements: stringifyFElements, + unstringifyBigInts: unstringifyBigInts, + unstringifyFElements: unstringifyFElements }); const PAGE_SIZE = 1<<30; @@ -4373,7 +4369,6 @@ function thread(self) { return runTask; } -/* global navigator, WebAssembly */ /* Copyright 2019 0KIMS association. @@ -4465,12 +4460,13 @@ async function buildThreadManager(wasm, singleThread) { tm.pendingDeferreds = []; tm.working = []; - let concurrency; - - if ((typeof(navigator) === "object") && navigator.hardwareConcurrency) { + let concurrency = 2; + if (process.browser) { + if (typeof navigator === "object" && navigator.hardwareConcurrency) { concurrency = navigator.hardwareConcurrency; + } } else { - concurrency = os__default["default"].cpus().length; + concurrency = os.cpus().length; } if(concurrency == 0){ @@ -4483,7 +4479,7 @@ async function buildThreadManager(wasm, singleThread) { for (let i = 0; i=16.0.0" @@ -119,6 +123,64 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -154,6 +216,218 @@ "node": ">= 8" } }, + "node_modules/@rollup/plugin-commonjs": { + "version": "25.0.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.4.tgz", + "integrity": "sha512-L92Vz9WUZXDnlQQl3EwbypJR4+DM2EbsO+/KOcEkP4Mc6Ct453EeDB2uH9lgRwj4w5yflgNpq9pHOiY8aoUXBQ==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.27.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@rollup/plugin-commonjs/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz", + "integrity": "sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.1", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-replace": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.3.tgz", + "integrity": "sha512-je7fu05B800IrMlWjb2wzJcdXzHYW46iTipfChnBDbIbDXhASZs27W1B58T2Yf45jZtJUONegpbce+9Ut2Ti/Q==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "magic-string": "^0.27.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-replace/node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.3.tgz", + "integrity": "sha512-EF0oejTMtkyhrkwCdg0HJ0IpkcaVg1MMSf2olHb2Jp+1mnLM04OhjpJWGma4HobiDTF0WCyViWuvadyE9ch2XA==", + "dev": true, + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.x || ^3.x" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-terser/node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.4.tgz", + "integrity": "sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", + "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==", + "dev": true + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -321,6 +595,24 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -479,6 +771,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -546,6 +850,15 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -694,9 +1007,9 @@ } }, "node_modules/esquery": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", - "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -754,9 +1067,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -812,22 +1125,23 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.7", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" } }, "node_modules/flatted": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", - "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/fs.realpath": { @@ -850,6 +1164,12 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -901,9 +1221,9 @@ } }, "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -921,6 +1241,18 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -967,7 +1299,7 @@ "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { "node": ">=0.8.19" @@ -1001,6 +1333,33 @@ "node": ">=8" } }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1022,6 +1381,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -1049,6 +1414,15 @@ "node": ">=8" } }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -1064,7 +1438,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "node_modules/js-yaml": { @@ -1079,6 +1453,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1088,9 +1468,18 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -1271,7 +1660,7 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "node_modules/normalize-path": { @@ -1378,6 +1767,12 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -1467,6 +1862,23 @@ "node": ">=0.10.0" } }, + "node_modules/resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -1502,15 +1914,16 @@ } }, "node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.18.0", + "npm": ">=8.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2" @@ -1589,6 +2002,31 @@ "node": ">=8" } }, + "node_modules/smob": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz", + "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1625,10 +2063,40 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/terser": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", + "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "node_modules/to-regex-range": { @@ -1865,18 +2333,18 @@ "dev": true }, "@eslint-community/eslint-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", - "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "requires": { "eslint-visitor-keys": "^3.3.0" } }, "@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", + "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", "dev": true }, "@eslint/eslintrc": { @@ -1925,6 +2393,55 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1951,6 +2468,156 @@ "fastq": "^1.6.0" } }, + "@rollup/plugin-commonjs": { + "version": "25.0.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.4.tgz", + "integrity": "sha512-L92Vz9WUZXDnlQQl3EwbypJR4+DM2EbsO+/KOcEkP4Mc6Ct453EeDB2uH9lgRwj4w5yflgNpq9pHOiY8aoUXBQ==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.27.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.13" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@rollup/plugin-node-resolve": { + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz", + "integrity": "sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.1", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + } + }, + "@rollup/plugin-replace": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.3.tgz", + "integrity": "sha512-je7fu05B800IrMlWjb2wzJcdXzHYW46iTipfChnBDbIbDXhASZs27W1B58T2Yf45jZtJUONegpbce+9Ut2Ti/Q==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1", + "magic-string": "^0.27.0" + }, + "dependencies": { + "magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.13" + } + } + } + }, + "@rollup/plugin-terser": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.3.tgz", + "integrity": "sha512-EF0oejTMtkyhrkwCdg0HJ0IpkcaVg1MMSf2olHb2Jp+1mnLM04OhjpJWGma4HobiDTF0WCyViWuvadyE9ch2XA==", + "dev": true, + "requires": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "dependencies": { + "serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + } + } + }, + "@rollup/pluginutils": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.4.tgz", + "integrity": "sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "dependencies": { + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + } + } + }, + "@types/estree": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", + "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==", + "dev": true + }, + "@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true + }, "acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -2082,6 +2749,18 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2200,6 +2879,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2247,6 +2938,12 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, "diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -2353,9 +3050,9 @@ } }, "esquery": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", - "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -2401,9 +3098,9 @@ "dev": true }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -2444,19 +3141,20 @@ "dev": true }, "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", "dev": true, "requires": { - "flatted": "^3.1.0", + "flatted": "^3.2.7", + "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, "flatted": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", - "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "fs.realpath": { @@ -2472,6 +3170,12 @@ "dev": true, "optional": true }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2508,9 +3212,9 @@ } }, "globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -2522,6 +3226,15 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2553,7 +3266,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "inflight": { @@ -2581,6 +3294,24 @@ "binary-extensions": "^2.0.0" } }, + "is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "requires": { + "builtin-modules": "^3.3.0" + } + }, + "is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2596,6 +3327,12 @@ "is-extglob": "^2.1.1" } }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2614,6 +3351,15 @@ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, + "is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "requires": { + "@types/estree": "*" + } + }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -2623,7 +3369,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "js-yaml": { @@ -2635,6 +3381,12 @@ "argparse": "^2.0.1" } }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2644,9 +3396,18 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2785,7 +3546,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "normalize-path": { @@ -2862,6 +3623,12 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -2916,6 +3683,17 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2938,9 +3716,9 @@ } }, "rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -2985,6 +3763,28 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "smob": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz", + "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3009,10 +3809,28 @@ "has-flag": "^4.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "terser": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", + "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "to-regex-range": { diff --git a/package.json b/package.json index e2d6ce1..3ee5364 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,24 @@ { "name": "ffjavascript", "type": "module", - "version": "0.2.60", + "version": "0.2.61", "description": "Finite Field Library in Javascript", "main": "./build/main.cjs", "module": "./main.js", "exports": { - "import": "./main.js", - "require": "./build/main.cjs" + ".": { + "node": { + "import": "./main.js", + "require": "./build/main.cjs" + }, + "browser": "./build/browser.esm.js" + } }, "scripts": { "test": "mocha", - "build": "rollup -c rollup.cjs.config.js" + "build:node": "rollup -c rollup.cjs.config.js", + "build:browser": "rollup -c rollup.browser.esm.config.js", + "build": "npm run build:node && npm run build:browser" }, "repository": { "type": "git", @@ -37,10 +44,14 @@ "web-worker": "^1.2.0" }, "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.4", + "@rollup/plugin-node-resolve": "^15.2.1", + "@rollup/plugin-replace": "^5.0.3", + "@rollup/plugin-terser": "^0.4.3", "blake2b": "^2.1.3", "chai": "^4.2.0", "eslint": "^8.0.1", "mocha": "^10.0.0", - "rollup": "^2.38.5" + "rollup": "^3.29.4" } } diff --git a/rollup.browser.esm.config.js b/rollup.browser.esm.config.js new file mode 100644 index 0000000..85e27ca --- /dev/null +++ b/rollup.browser.esm.config.js @@ -0,0 +1,39 @@ +import commonJS from "@rollup/plugin-commonjs"; +import replace from "@rollup/plugin-replace"; +import terser from "@rollup/plugin-terser"; +import { nodeResolve } from "@rollup/plugin-node-resolve"; +import thread from "./src/threadman_thread.js"; + +export default [ + { + input: "main.js", + output: [ + { + format: "es", + file: "build/browser.esm.js", + }, + ], + plugins: [ + replace({ + preventAssignment: true, + changed: "replaced", + delimiters: ["", ""], + "process.browser": true, + /* + Because of some frontend frameworks uses monkey patching to track UI changes or other purposes (including Angular, AngularJS, Ember.js, JQuery...), it's important to make sure that the thread function is not modified by the framework and passing in the web worker as it is. + */ + "thread.toString()": JSON.stringify(thread.toString()), + }), + commonJS(), + nodeResolve({ + browser: true, + }), + // minify the output + terser(), + ], + treeshake: { + // remove unused imports from the build + preset: "smallest", + }, + }, +]; diff --git a/src/threadman.js b/src/threadman.js index 61310a9..3870ff2 100644 --- a/src/threadman.js +++ b/src/threadman.js @@ -1,4 +1,3 @@ -/* global navigator, WebAssembly */ /* Copyright 2019 0KIMS association. @@ -95,12 +94,13 @@ export default async function buildThreadManager(wasm, singleThread) { tm.pendingDeferreds = []; tm.working = []; - let concurrency; - - if ((typeof(navigator) === "object") && navigator.hardwareConcurrency) { + let concurrency = 2; + if (process.browser) { + if (typeof navigator === "object" && navigator.hardwareConcurrency) { concurrency = navigator.hardwareConcurrency; + } } else { - concurrency = os.cpus().length; + concurrency = os.cpus().length; } if(concurrency == 0){ From 8a8d2aea23c90888bf429e014957e6ab85bb1b7a Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Fri, 6 Oct 2023 18:09:52 +0200 Subject: [PATCH 2/3] Remove Terser plugin --- package-lock.json | 250 ----------------------------------- package.json | 1 - rollup.browser.esm.config.js | 55 ++++---- 3 files changed, 26 insertions(+), 280 deletions(-) diff --git a/package-lock.json b/package-lock.json index afc18aa..349d9f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "@rollup/plugin-commonjs": "^25.0.4", "@rollup/plugin-node-resolve": "^15.2.1", "@rollup/plugin-replace": "^5.0.3", - "@rollup/plugin-terser": "^0.4.3", "blake2b": "^2.1.3", "chai": "^4.2.0", "eslint": "^8.0.1", @@ -123,64 +122,12 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -357,37 +304,6 @@ "node": ">=12" } }, - "node_modules/@rollup/plugin-terser": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.3.tgz", - "integrity": "sha512-EF0oejTMtkyhrkwCdg0HJ0IpkcaVg1MMSf2olHb2Jp+1mnLM04OhjpJWGma4HobiDTF0WCyViWuvadyE9ch2XA==", - "dev": true, - "dependencies": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.x || ^3.x" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-terser/node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/@rollup/pluginutils": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.4.tgz", @@ -595,12 +511,6 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, "node_modules/builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", @@ -771,12 +681,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -2002,31 +1906,6 @@ "node": ">=8" } }, - "node_modules/smob": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz", - "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -2075,24 +1954,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", - "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -2393,55 +2254,12 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, "@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, - "@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2565,28 +2383,6 @@ } } }, - "@rollup/plugin-terser": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.3.tgz", - "integrity": "sha512-EF0oejTMtkyhrkwCdg0HJ0IpkcaVg1MMSf2olHb2Jp+1mnLM04OhjpJWGma4HobiDTF0WCyViWuvadyE9ch2XA==", - "dev": true, - "requires": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, - "dependencies": { - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, "@rollup/pluginutils": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.4.tgz", @@ -2749,12 +2545,6 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, "builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", @@ -2879,12 +2669,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -3763,28 +3547,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "smob": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz", - "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3815,18 +3577,6 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, - "terser": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", - "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", diff --git a/package.json b/package.json index 3ee5364..895a544 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "@rollup/plugin-commonjs": "^25.0.4", "@rollup/plugin-node-resolve": "^15.2.1", "@rollup/plugin-replace": "^5.0.3", - "@rollup/plugin-terser": "^0.4.3", "blake2b": "^2.1.3", "chai": "^4.2.0", "eslint": "^8.0.1", diff --git a/rollup.browser.esm.config.js b/rollup.browser.esm.config.js index 85e27ca..213ce0e 100644 --- a/rollup.browser.esm.config.js +++ b/rollup.browser.esm.config.js @@ -1,39 +1,36 @@ import commonJS from "@rollup/plugin-commonjs"; import replace from "@rollup/plugin-replace"; -import terser from "@rollup/plugin-terser"; import { nodeResolve } from "@rollup/plugin-node-resolve"; import thread from "./src/threadman_thread.js"; export default [ - { - input: "main.js", - output: [ - { - format: "es", - file: "build/browser.esm.js", - }, - ], - plugins: [ - replace({ - preventAssignment: true, - changed: "replaced", - delimiters: ["", ""], - "process.browser": true, - /* + { + input: "main.js", + output: [ + { + format: "es", + file: "build/browser.esm.js", + }, + ], + plugins: [ + replace({ + preventAssignment: true, + changed: "replaced", + delimiters: ["", ""], + "process.browser": true, + /* Because of some frontend frameworks uses monkey patching to track UI changes or other purposes (including Angular, AngularJS, Ember.js, JQuery...), it's important to make sure that the thread function is not modified by the framework and passing in the web worker as it is. */ - "thread.toString()": JSON.stringify(thread.toString()), - }), - commonJS(), - nodeResolve({ - browser: true, - }), - // minify the output - terser(), - ], - treeshake: { - // remove unused imports from the build - preset: "smallest", + "thread.toString()": JSON.stringify(thread.toString()), + }), + commonJS(), + nodeResolve({ + browser: true, + }), + ], + treeshake: { + // remove unused imports from the build + preset: "smallest", + }, }, - }, ]; From 51e091d26eb4e38bf3c60134dd783e5509dfa7e3 Mon Sep 17 00:00:00 2001 From: Dimasik Kolezhniuk Date: Tue, 10 Oct 2023 16:20:20 +0200 Subject: [PATCH 3/3] Add explanation to browser.esm build --- rollup.browser.esm.config.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rollup.browser.esm.config.js b/rollup.browser.esm.config.js index 213ce0e..74db36c 100644 --- a/rollup.browser.esm.config.js +++ b/rollup.browser.esm.config.js @@ -17,9 +17,13 @@ export default [ preventAssignment: true, changed: "replaced", delimiters: ["", ""], + /* + * The following variable replaces to true in the build in the similar way as snarkjs does. + * https://github.com/iden3/snarkjs/blob/ef9042451f98f254b520b8ce9b9544a849e90a5d/config/rollup.iife.config.js + */ "process.browser": true, /* - Because of some frontend frameworks uses monkey patching to track UI changes or other purposes (including Angular, AngularJS, Ember.js, JQuery...), it's important to make sure that the thread function is not modified by the framework and passing in the web worker as it is. + Because of some frontend frameworks uses monkey patching to track UI changes or other purposes (including Angular, AngularJS, Ember.js, JQuery...), it's important to make sure that the thread function is not modified by the framework and passing in the web worker as it is. */ "thread.toString()": JSON.stringify(thread.toString()), }),