UNPKG

snarkjs

Version:

zkSNARKs implementation in JavaScript

1,779 lines (1,463 loc) 6.91 MB
var snarkjs = (function (exports) { 'use strict'; /* global BigInt */ const hexLen$1 = [ 0, 1, 2, 2, 3, 3, 3, 3, 4 ,4 ,4 ,4 ,4 ,4 ,4 ,4]; function fromString$1(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$1 = fromString$1; function fromArray(a, radix) { let acc =BigInt(0); radix = BigInt(radix); for (let i=0; i<a.length; i++) { acc = acc*radix + BigInt(a[i]); } return acc; } function bitLength$6$1(a) { const aS =a.toString(16); return (aS.length-1)*4 +hexLen$1[parseInt(aS[0], 16)]; } function isNegative$4$1(a) { return BigInt(a) < BigInt(0); } function isZero$1$1(a) { return !a; } function shiftLeft$1(a, n) { return BigInt(a) << BigInt(n); } function shiftRight$1(a, n) { return BigInt(a) >> BigInt(n); } const shl = shiftLeft$1; const shr = shiftRight$1; function isOdd$5$1(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$1(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$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$1(a, b) { return BigInt(a) + BigInt(b); } function sub$1(a, b) { return BigInt(a) - BigInt(b); } function neg$1(a) { return -BigInt(a); } function mul$1(a, b) { return BigInt(a) * BigInt(b); } function square$2(a) { return BigInt(a) * BigInt(a); } function pow$1(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$1(a, b) { return BigInt(a) / BigInt(b); } function mod$1(a, b) { return BigInt(a) % BigInt(b); } function eq$1(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$1(a, b) { return BigInt(a) > BigInt(b); } function leq(a, b) { return BigInt(a) <= BigInt(b); } function geq$1(a, b) { return BigInt(a) >= BigInt(b); } function band$1(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$1(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<l; i++) v[i] = parseInt(s.substring(s.length-8*i-8, s.length-8*i), 16); for (let i=l; i<v.length; i++) v[i] = 0; for (let i=v.length*4; i<n8; i++) buff[i] = toNumber$1$1(band$1(shiftRight$1(e, i*8), 0xFF)); } // Returns a buffer with Big Endian Representation function toRprBE$1(buff, o, e, n8) { const s = "0000000" + e.toString(16); const v = new DataView(buff.buffer, buff.byteOffset + o, n8); const l = (((s.length-7)*4 - 1) >> 5)+1; // Number of 32bit words; for (let i=0; i<l; i++) v.setUint32(n8-i*4 -4, parseInt(s.substring(s.length-8*i-8, s.length-8*i), 16), false); for (let i=0; i<n8/4-l; i++) v[i] = 0; } // Pases a buffer with Little Endian Representation function fromRprLE$1(buff, o, n8) { n8 = n8 || buff.byteLength; o = o || 0; const v = new Uint32Array(buff.buffer, buff.byteOffset + o, n8/4); const a = new Array(n8/4); v.forEach( (ch,i) => a[a.length-i-1] = ch.toString(16).padStart(8,"0") ); return fromString$1(a.join(""), 16); } // Pases a buffer with Big Endian Representation function fromRprBE$1(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<n8/4; i++) { a[i] = v.getUint32(i*4, false).toString(16).padStart(8, "0"); } return fromString$1(a.join(""), 16); } function toString$6(a, radix) { return a.toString(radix); } function toLEBuff$1(a) { const buff = new Uint8Array(Math.floor((bitLength$6$1(a) - 1) / 8) +1); toRprLE$1(buff, 0, a, buff.byteLength); return buff; } const zero$1 = e$1(0); const one$1 = e$1(1); var _Scalar = /*#__PURE__*/Object.freeze({ __proto__: null, abs: abs$1, add: add$1, band: band$1, bitLength: bitLength$6$1, bits: bits$1, bor: bor, bxor: bxor, div: div$1, e: e$1, eq: eq$1, exp: exp$1, fromArray: fromArray, fromRprBE: fromRprBE$1, fromRprLE: fromRprLE$1, fromString: fromString$1, geq: geq$1, gt: gt$1, isNegative: isNegative$4$1, isOdd: isOdd$5$1, isZero: isZero$1$1, land: land, leq: leq, lnot: lnot, lor: lor, lt: lt, mod: mod$1, mul: mul$1, naf: naf, neg: neg$1, neq: neq, one: one$1, pow: pow$1, shiftLeft: shiftLeft$1, shiftRight: shiftRight$1, shl: shl, shr: shr, square: square$2, sub: sub$1, toArray: toArray, toLEBuff: toLEBuff$1, toNumber: toNumber$1$1, toRprBE: toRprBE$1, toRprLE: toRprLE$1, toString: toString$6, zero: zero$1 }); /* 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$2(F, base, e) { if (isZero$1$1(e)) return F.one; const n = bits$1(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$1 (F) { if ((F.m % 2) == 1) { if (eq$1(mod$1(F.p, 4), 1 )) { if (eq$1(mod$1(F.p, 8), 1 )) { if (eq$1(mod$1(F.p, 16), 1 )) { // alg7_muller(F); alg5_tonelliShanks$1(F); } else if (eq$1(mod$1(F.p, 16), 9 )) { alg4_kong$1(F); } else { throw new Error("Field withot sqrt"); } } else if (eq$1(mod$1(F.p, 8), 5 )) { alg3_atkin$1(F); } else { throw new Error("Field withot sqrt"); } } else if (eq$1(mod$1(F.p, 4), 3 )) { alg2_shanks$1(F); } } else { const pm2mod4 = mod$1(pow$1(F.p, F.m/2), 4); if (pm2mod4 == 1) { alg10_adj$1(F); } else if (pm2mod4 == 3) { alg9_adj$1(F); } else { alg8_complex$1(F); } } } function alg5_tonelliShanks$1(F) { F.sqrt_q = pow$1(F.p, F.m); F.sqrt_s = 0; F.sqrt_t = sub$1(F.sqrt_q, 1); while (!isOdd$5$1(F.sqrt_t)) { F.sqrt_s = F.sqrt_s + 1; F.sqrt_t = div$1(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$1(sub$1(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<v-k-1; i++) { w = F.square(w); } z = F.square(w); b = F.mul(b, z); x = F.mul(x, w); v = k; } return F.geq(x, F.zero) ? x : F.neg(x); }; } function alg4_kong$1(F) { F.sqrt = function() { throw new Error("Sqrt alg 4 not implemented"); }; } function alg3_atkin$1(F) { F.sqrt = function() { throw new Error("Sqrt alg 3 not implemented"); }; } function alg2_shanks$1(F) { F.sqrt_q = pow$1(F.p, F.m); F.sqrt_e1 = div$1( sub$1(F.sqrt_q, 3) , 4); F.sqrt = function(a) { if (this.isZero(a)) return this.zero; // Test that have solution const a1 = this.pow(a, this.sqrt_e1); const a0 = this.mul(this.square(a1), a); if ( this.eq(a0, this.negone) ) return null; const x = this.mul(a1, a); return F.geq(x, F.zero) ? x : F.neg(x); }; } function alg10_adj$1(F) { F.sqrt = function() { throw new Error("Sqrt alg 10 not implemented"); }; } function alg9_adj$1(F) { F.sqrt_q = pow$1(F.p, F.m/2); F.sqrt_e34 = div$1( sub$1(F.sqrt_q, 3) , 4); F.sqrt_e12 = div$1( sub$1(F.sqrt_q, 1) , 2); F.frobenius = function(n, x) { if ((n%2) == 1) { return F.conjugate(x); } else { return x; } }; F.sqrt = function(a) { const F = this; const a1 = F.pow(a, F.sqrt_e34); const alfa = F.mul(F.square(a1), a); const a0 = F.mul(F.frobenius(1, alfa), alfa); if (F.eq(a0, F.negone)) return null; const x0 = F.mul(a1, a); let x; if (F.eq(alfa, F.negone)) { x = F.mul(x0, [F.F.zero, F.F.one]); } else { const b = F.pow(F.add(F.one, alfa), F.sqrt_e12); x = F.mul(b, x0); } return F.geq(x, F.zero) ? x : F.neg(x); }; } function alg8_complex$1(F) { F.sqrt = function() { throw new Error("Sqrt alg 8 not implemented"); }; } function quarterRound$1(st, a, b, c, d) { st[a] = (st[a] + st[b]) >>> 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$1(st) { quarterRound$1(st, 0, 4, 8,12); quarterRound$1(st, 1, 5, 9,13); quarterRound$1(st, 2, 6,10,14); quarterRound$1(st, 3, 7,11,15); quarterRound$1(st, 0, 5,10,15); quarterRound$1(st, 1, 6,11,12); quarterRound$1(st, 2, 7, 8,13); quarterRound$1(st, 3, 4, 9,14); } class ChaCha$1 { 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$1(mul$1(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$1(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$2(n) { let array = new Uint8Array(n); { // Browser if (typeof globalThis.crypto !== "undefined") { // Supported globalThis.crypto.getRandomValues(array); } else { // fallback for (let i=0; i<n; i++) { array[i] = (Math.random()*4294967296)>>>0; } } } return array; } function getRandomSeed$1() { const arr = getRandomBytes$2(32); const arrV = new Uint32Array(arr.buffer); const seed = []; for (let i=0; i<8; i++) { seed.push(arrV[i]); } return seed; } let threadRng$1 = null; function getThreadRng$1() { if (threadRng$1) return threadRng$1; threadRng$1 = new ChaCha$1(getRandomSeed$1()); return threadRng$1; } /* 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 <https://www.gnu.org/licenses/>. */ /* 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$1 { 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<n; j++) { rootsi[j] = r; r = this.F.mul(r, this.w[i]); } this.roots.push(rootsi); } */ this._setRoots(Math.min(s, 15)); } _setRoots(n) { 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<nroots; j++) { rootsi[j] = r; r = this.F.mul(r, this.w[i]); } this.roots[i] = rootsi; } } fft(p) { if (p.length <= 1) return p; const bits = log2$1$1(p.length-1)+1; this._setRoots(bits); const m = 1 << bits; if (p.length != m) { throw new Error("Size must be multiple of 2"); } const res = __fft$1(this, p, bits, 0, 1); return res; } ifft(p) { if (p.length <= 1) return p; const bits = log2$1$1(p.length-1)+1; this._setRoots(bits); const m = 1 << bits; if (p.length != m) { throw new Error("Size must be multiple of 2"); } const res = __fft$1(this, p, bits, 0, 1); const twoinvm = this.F.inv( this.F.mulScalar(this.F.one, m) ); const resn = new Array(m); for (let i=0; i<m; i++) { resn[i] = this.opMulGF(res[(m-i)%m], twoinvm); } return resn; } } function log2$1$1( V ) { return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) ); } function __fft$1(PF, pall, bits, offset, step) { const n = 1 << bits; if (n==1) { return [ pall[offset] ]; } else if (n==2) { return [ PF.G.add(pall[offset], pall[offset + step]), PF.G.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<ndiv2; i++) { out[i] = PF.G.add(p1[i], PF.opMulGF(p2[i], PF.roots[bits][i])); out[i+ndiv2] = PF.G.sub(p1[i], PF.opMulGF(p2[i], PF.roots[bits][i])); } return out; } /* global BigInt */ class ZqField$1 { constructor(p) { this.type="F1"; this.one = BigInt(1); this.zero = BigInt(0); this.p = BigInt(p); this.m = 1; this.negone = this.p-this.one; this.two = BigInt(2); this.half = this.p >> this.one; this.bitLength = bitLength$6$1(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$1(this); this.FFT = new FFT$1(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.zero) t += this.p; return t; } mod(a, b) { return a % b; } pow(b, e) { return exp$2(this, b, e); } exp(b, e) { return exp$2(this, b, e); } band(a, b) { const res = ((a & b) & this.mask); return res >= this.p ? res-this.p : res; } bor(a, b) { const res = ((a | b) & this.mask); return res >= this.p ? res-this.p : res; } bxor(a, b) { const res = ((a ^ b) & this.mask); return res >= this.p ? res-this.p : res; } bnot(a) { const res = a ^ this.mask; return res >= this.p ? res-this.p : res; } shl(a, b) { if (Number(b) < this.bitLength) { const res = (a << b) & this.mask; return res >= this.p ? res-this.p : res; } else { const nb = this.p - b; if (Number(nb) < this.bitLength) { return a >> nb; } else { return this.zero; } } } shr(a, b) { if (Number(b) < this.bitLength) { return a >> b; } else { const nb = this.p - b; if (Number(nb) < this.bitLength) { const res = (a << nb) & this.mask; return res >= this.p ? res-this.p : res; } else { return 0; } } } land(a, b) { return (a && b) ? this.one : this.zero; } lor(a, b) { return (a || b) ? this.one : this.zero; } lnot(a) { return (a) ? this.zero : this.one; } sqrt_old(n) { if (n == this.zero) return this.zero; // Test that have solution const res = this.pow(n, this.negone >> this.one); if ( res != this.one ) return null; let m = this.s; let c = this.nqr_to_t; let t = this.pow(n, this.t); let r = this.pow(n, this.add(this.t, this.one) >> this.one ); while ( t != this.one ) { let sq = this.square(t); let i = 1; while (sq != this.one ) { i++; sq = this.square(sq); } // b = c ^ m-i-1 let b = c; for (let j=0; j< m-i-1; j ++) b = this.square(b); m = i; c = this.square(b); t = this.mul(t, c); r = this.mul(r, b); } if (r > (this.p >> this.one)) { r = this.neg(r); } return r; } normalize(a, b) { a = BigInt(a,b); if (a < 0) { let na = -a; if (na >= this.p) na = na % this.p; return this.p - na; } else { return (a>= this.p) ? a%this.p : a; } } random() { const nBytes = (this.bitLength*2 / 8); let res =this.zero; for (let i=0; i<nBytes; i++) { res = (res << BigInt(8)) + BigInt(getRandomBytes$2(1)[0]); } return res % this.p; } toString(a, base) { base = base || 10; let vs; if ((a > 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.n64; i++) { v += rng.nextU64() << BigInt(64 *i); } v &= this.mask; } while (v >= 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$1(buff, o, e, this.n64*8); } // Returns a buffer with Big Endian Representation toRprBE(buff, o, e) { toRprBE$1(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$1(buff, o, this.n8); } // Pases a buffer with Big Endian Representation fromRprBE(buff, o) { return fromRprBE$1(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; } } var utils$6$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 <https://www.gnu.org/licenses/>. */ utils$6$1.bigInt2BytesLE = function bigInt2BytesLE(_a, len) { const b = Array(len); let v = BigInt(_a); for (let i=0; i<len; i++) { b[i] = Number(v & 0xFFn); v = v >> 8n; } return b; }; utils$6$1.bigInt2U32LE = function bigInt2BytesLE(_a, len) { const b = Array(len); let v = BigInt(_a); for (let i=0; i<len; i++) { b[i] = Number(v & 0xFFFFFFFFn); v = v >> 32n; } return b; }; utils$6$1.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 <https://www.gnu.org/licenses/>. */ var build_int$1 = 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<n64; i++) { f.addCode( c.i64_store( c.getLocal("pr"), i*8, c.i64_load( c.getLocal("px"), i*8 ) ) ); } } function buildZero() { const f = module.addFunction(prefix+"_zero"); f.addParam("pr", "i32"); const c = f.getCodeBuilder(); for (let i=0; i<n64; i++) { f.addCode( c.i64_store( c.getLocal("pr"), i*8, c.i64_const(0) ) ); } } function buildOne() { const f = module.addFunction(prefix+"_one"); f.addParam("pr", "i32"); const c = f.getCodeBuilder(); f.addCode( c.i64_store( c.getLocal("pr"), 0, c.i64_const(1) ) ); for (let i=1; i<n64; i++) { f.addCode( c.i64_store( c.getLocal("pr"), i*8, c.i64_const(0) ) ); } } function buildIsZero() { const f = module.addFunction(prefix+"_isZero"); f.addParam("px", "i32"); f.setReturnType("i32"); const c = f.getCodeBuilder(); function getCompCode(n) { if (n==0) { return c.ret(c.i64_eqz( c.i64_load(c.getLocal("px")) )); } return c.if( c.i64_eqz( c.i64_load(c.getLocal("px"), n*8 ) ), getCompCode(n-1), c.ret(c.i32_const(0)) ); } f.addCode(getCompCode(n64-1)); f.addCode(c.ret(c.i32_const(0))); } function buildEq() { const f = module.addFunction(prefix+"_eq"); f.addParam("px", "i32"); f.addParam("py", "i32"); f.setReturnType("i32"); const c = f.getCodeBuilder(); function getCompCode(n) { if (n==0) { return c.ret(c.i64_eq( c.i64_load(c.getLocal("px")), c.i64_load(c.getLocal("py")) )); } return c.if( c.i64_eq( c.i64_load(c.getLocal("px"), n*8 ), c.i64_load(c.getLocal("py"), n*8 ) ), getCompCode(n-1), c.ret(c.i32_const(0)) ); } f.addCode(getCompCode(n64-1)); f.addCode(c.ret(c.i32_const(0))); } function buildGte() { const f = module.addFunction(prefix+"_gte"); f.addParam("px", "i32"); f.addParam("py", "i32"); f.setReturnType("i32"); const c = f.getCodeBuilder(); function getCompCode(n) { if (n==0) { return c.ret(c.i64_ge_u( c.i64_load(c.getLocal("px")), c.i64_load(c.getLocal("py")) )); } return c.if( c.i64_lt_u( c.i64_load(c.getLocal("px"), n*8 ), c.i64_load(c.getLocal("py"), n*8 ) ), c.ret(c.i32_const(0)), c.if( c.i64_gt_u( c.i64_load(c.getLocal("px"), n*8 ), c.i64_load(c.getLocal("py"), n*8 ) ), c.ret(c.i32_const(1)), getCompCode(n-1) ) ); } f.addCode(getCompCode(n64-1)); f.addCode(c.ret(c.i32_const(0))); } function buildAdd() { const f = module.addFunction(prefix+"_add"); f.addParam("x", "i32"); f.addParam("y", "i32"); f.addParam("r", "i32"); f.setReturnType("i32"); f.addLocal("c", "i64"); const c = f.getCodeBuilder(); f.addCode(c.setLocal( "c", c.i64_add( c.i64_load32_u(c.getLocal("x")), c.i64_load32_u(c.getLocal("y")) ) )); f.addCode(c.i64_store32( c.getLocal("r"), c.getLocal("c"), )); for (let i=1; i<n32; i++) { f.addCode(c.setLocal( "c", c.i64_add( c.i64_add( c.i64_load32_u(c.getLocal("x"), 4*i), c.i64_load32_u(c.getLocal("y"), 4*i) ), c.i64_shr_u (c.getLocal("c"), c.i64_const(32)) ) )); f.addCode(c.i64_store32( c.getLocal("r"), i*4, c.getLocal("c") )); } f.addCode(c.i32_wrap_i64(c.i64_shr_u (c.getLocal("c"), c.i64_const(32)))); } function buildSub() { const f = module.addFunction(prefix+"_sub"); f.addParam("x", "i32"); f.addParam("y", "i32"); f.addParam("r", "i32"); f.setReturnType("i32"); f.addLocal("c", "i64"); const c = f.getCodeBuilder(); f.addCode(c.setLocal( "c", c.i64_sub( c.i64_load32_u(c.getLocal("x")), c.i64_load32_u(c.getLocal("y")) ) )); f.addCode(c.i64_store32( c.getLocal("r"), c.i64_and( c.getLocal("c"), c.i64_const("0xFFFFFFFF") ) )); for (let i=1; i<n32; i++) { f.addCode(c.setLocal( "c", c.i64_add( c.i64_sub( c.i64_load32_u(c.getLocal("x"), 4*i), c.i64_load32_u(c.getLocal("y"), 4*i) ), c.i64_shr_s (c.getLocal("c"), c.i64_const(32)) ) )); f.addCode(c.i64_store32( c.getLocal("r"), i*4, c.i64_and( c.getLocal("c"), c.i64_const("0xFFFFFFFF")) )); } f.addCode(c.i32_wrap_i64 ( c.i64_shr_s (c.getLocal("c"), c.i64_const(32)))); } function buildMul() { const f = module.addFunction(prefix+"_mul"); f.addParam("x", "i32"); f.addParam("y", "i32"); f.addParam("r", "i32"); f.addLocal("c0", "i64"); f.addLocal("c1", "i64"); for (let i=0;i<n32; i++) { f.addLocal("x"+i, "i64"); f.addLocal("y"+i, "i64"); } const c = f.getCodeBuilder(); const loadX = []; const loadY = []; function mulij(i, j) { let X,Y; if (!loadX[i]) { X = c.teeLocal("x"+i, c.i64_load32_u( c.getLocal("x"), i*4)); loadX[i] = true; } else { X = c.getLocal("x"+i); } if (!loadY[j]) { Y = c.teeLocal("y"+j, c.i64_load32_u( c.getLocal("y"), j*4)); loadY[j] = true; } else { Y = c.getLocal("y"+j); } return c.i64_mul( X, Y ); } let c0 = "c0"; let c1 = "c1"; for (let k=0; k<n32*2-1; k++) { for (let i=Math.max(0, k-n32+1); (i<=k)&&(i<n32); i++) { const j= k-i; f.addCode( c.setLocal(c0, c.i64_add( c.i64_and( c.getLocal(c0), c.i64_const(0xFFFFFFFF) ), mulij(i,j) ) ) ); f.addCode( c.setLocal(c1, c.i64_add( c.getLocal(c1), c.i64_shr_u( c.getLocal(c0), c.i64_const(32) ) ) ) ); } f.addCode( c.i64_store32( c.getLocal("r"), k*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*2-4, c.getLocal(c0) ) ); } 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"); for (let i=0;i<n32; i++) { f.addLocal("x"+i, "i64"); } const c = f.getCodeBuilder(); const loadX = []; function mulij(i, j) { let X,Y; if (!loadX[i]) { X = c.teeLocal("x"+i, c.i64_load32_u( c.getLocal("x"), i*4)); loadX[i] = true; } else { X = c.getLocal("x"+i); } if (!loadX[j]) { Y = c.teeLocal("x"+j, c.i64_load32_u( c.getLocal("x"), j*4)); loadX[j] = true; } else { Y = c.getLocal("x"+j); } return c.i64_mul( X, Y ); } let c0 = "c0"; let c1 = "c1"; let c0_old = "c0_old"; let c1_old = "c1_old"; for (let k=0; k<n32*2-1; k++) { f.addCode( c.setLocal(c0, c.i64_const(0)), c.setLocal(c1, c.i64_const(0)), ); for (let i=Math.max(0, k-n32+1); (i<((k+1)>>1) )&&(i<n32); i++) { const j= k-i; f.addCode( c.setLocal(c0, c.i64_add( c.i64_and( c.getLocal(c0), c.i64_const(0xFFFFFFFF) ), mulij(i,j) ) ) ); f.addCode( c.setLocal(c1, c.i64_add( c.getLocal(c1), c.i64_shr_u( c.getLocal(c0), c.i64_const(32) ) ) ) ); } // Multiply by 2 f.addCode( c.setLocal(c0, c.i64_shl( c.i64_and( c.getLocal(c0), c.i64_const(0xFFFFFFFF) ), c.i64_const(1) ) ) ); f.addCode( c.setLocal(c1, c.i64_add( c.i64_shl( c.getLocal(c1), c.i64_const(1) ), c.i64_shr_u( c.getLocal(c0), c.i64_const(32) ) ) ) ); if (k%2 == 0) { f.addCode( c.setLocal(c0, c.i64_add( c.i64_and( c.getLocal(c0), c.i64_const(0xFFFFFFFF) ), mulij(k>>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+"__mu