snarkjs
Version:
zkSNARKs implementation in JavaScript
1,779 lines (1,463 loc) • 6.91 MB
JavaScript
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