snarkjs
Version:
zkSNARKs implementation in JavaScript
1,482 lines (1,188 loc) • 458 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var binFileUtils = require('@iden3/binfileutils');
var ffjavascript = require('ffjavascript');
var Blake2b = require('blake2b-wasm');
var readline = require('readline');
var crypto = require('crypto');
var fastFile = require('fastfile');
var circom_runtime = require('circom_runtime');
var r1csfile = require('r1csfile');
var ejs = require('ejs');
var jsSha3 = require('js-sha3');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var binFileUtils__namespace = /*#__PURE__*/_interopNamespace(binFileUtils);
var Blake2b__default = /*#__PURE__*/_interopDefaultLegacy(Blake2b);
var readline__default = /*#__PURE__*/_interopDefaultLegacy(readline);
var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
var fastFile__namespace = /*#__PURE__*/_interopNamespace(fastFile);
var ejs__default = /*#__PURE__*/_interopDefaultLegacy(ejs);
var jsSha3__default = /*#__PURE__*/_interopDefaultLegacy(jsSha3);
const bls12381r$1 = ffjavascript.Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16);
const bn128r$1 = ffjavascript.Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const bls12381q = ffjavascript.Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16);
const bn128q = ffjavascript.Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583");
async function getCurveFromR(r, options) {
let curve;
// check that options param is defined and that options.singleThread is defined
let singleThread = options && options.singleThread;
if (ffjavascript.Scalar.eq(r, bn128r$1)) {
curve = await ffjavascript.buildBn128(singleThread);
} else if (ffjavascript.Scalar.eq(r, bls12381r$1)) {
curve = await ffjavascript.buildBls12381(singleThread);
} else {
throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(r)}`);
}
return curve;
}
async function getCurveFromQ(q, options) {
let curve;
let singleThread = options && options.singleThread;
if (ffjavascript.Scalar.eq(q, bn128q)) {
curve = await ffjavascript.buildBn128(singleThread);
} else if (ffjavascript.Scalar.eq(q, bls12381q)) {
curve = await ffjavascript.buildBls12381(singleThread);
} else {
throw new Error(`Curve not supported: ${ffjavascript.Scalar.toString(q)}`);
}
return curve;
}
async function getCurveFromName(name, options) {
let curve;
let singleThread = options && options.singleThread;
const normName = normalizeName(name);
if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) {
curve = await ffjavascript.buildBn128(singleThread);
} else if (["BLS12381"].indexOf(normName) >= 0) {
curve = await ffjavascript.buildBls12381(singleThread);
} else {
throw new Error(`Curve not supported: ${name}`);
}
return curve;
function normalizeName(n) {
return n.toUpperCase().match(/[A-Za-z0-9]+/g).join("");
}
}
var curves = /*#__PURE__*/Object.freeze({
__proto__: null,
getCurveFromR: getCurveFromR,
getCurveFromQ: getCurveFromQ,
getCurveFromName: getCurveFromName
});
/*
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/>.
*/
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 formatHash(b, title) {
const a = new DataView(b.buffer, b.byteOffset, b.byteLength);
let S = "";
for (let i=0; i<4; i++) {
if (i>0) S += "\n";
S += "\t\t";
for (let j=0; j<4; j++) {
if (j>0) S += " ";
S += a.getUint32(i*16+j*4).toString(16).padStart(8, "0");
}
}
if (title) S = title + "\n" + S;
return S;
}
function hashIsEqual(h1, h2) {
if (h1.byteLength != h2.byteLength) return false;
var dv1 = new Int8Array(h1);
var dv2 = new Int8Array(h2);
for (var i = 0 ; i != h1.byteLength ; i++)
{
if (dv1[i] != dv2[i]) return false;
}
return true;
}
function cloneHasher(h) {
const ph = h.getPartialHash();
const res = Blake2b__default["default"](64);
res.setPartialHash(ph);
return res;
}
async function sameRatio$2(curve, g1s, g1sx, g2s, g2sx) {
if (curve.G1.isZero(g1s)) return false;
if (curve.G1.isZero(g1sx)) return false;
if (curve.G2.isZero(g2s)) return false;
if (curve.G2.isZero(g2sx)) return false;
// return curve.F12.eq(curve.pairing(g1s, g2sx), curve.pairing(g1sx, g2s));
const res = await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s);
return res;
}
function askEntropy() {
if (process.browser) {
return window.prompt("Enter a random text. (Entropy): ", "");
} else {
const rl = readline__default["default"].createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
rl.question("Enter a random text. (Entropy): ", (input) => resolve(input) );
});
}
}
function getRandomBytes(n) {
let array = new Uint8Array(n);
if (process.browser) { // Supported
globalThis.crypto.getRandomValues(array);
} else { // NodeJS
crypto__default["default"].randomFillSync(array);
}
return array;
}
async function sha256digest(data) {
if (process.browser) { // Supported
const buffer = await globalThis.crypto.subtle.digest("SHA-256", data.buffer);
return new Uint8Array(buffer);
} else { // NodeJS
return crypto__default["default"].createHash("sha256").update(data).digest();
}
}
/**
* @param {Uint8Array} data
* @param {number} offset
*/
function readUInt32BE(data, offset) {
return new DataView(data.buffer).getUint32(offset, false);
}
async function getRandomRng(entropy) {
// Generate a random Rng
while (!entropy) {
entropy = await askEntropy();
}
const hasher = Blake2b__default["default"](64);
hasher.update(getRandomBytes(64));
const enc = new TextEncoder(); // always utf-8
hasher.update(enc.encode(entropy));
const hash = hasher.digest();
const seed = [];
for (let i=0;i<8;i++) {
seed[i] = readUInt32BE(hash, i*4);
}
const rng = new ffjavascript.ChaCha(seed);
return rng;
}
async function rngFromBeaconParams(beaconHash, numIterationsExp) {
let nIterationsInner;
let nIterationsOuter;
if (numIterationsExp<32) {
nIterationsInner = (1 << numIterationsExp) >>> 0;
nIterationsOuter = 1;
} else {
nIterationsInner = 0x100000000;
nIterationsOuter = (1 << (numIterationsExp-32)) >>> 0;
}
let curHash = beaconHash;
for (let i=0; i<nIterationsOuter; i++) {
for (let j=0; j<nIterationsInner; j++) {
curHash = await sha256digest(curHash);
}
}
const curHashV = new DataView(curHash.buffer, curHash.byteOffset, curHash.byteLength);
const seed = [];
for (let i=0; i<8; i++) {
seed[i] = curHashV.getUint32(i*4, false);
}
const rng = new ffjavascript.ChaCha(seed);
return rng;
}
function hex2ByteArray(s) {
if (s instanceof Uint8Array) return s;
if (s.slice(0,2) == "0x") s= s.slice(2);
return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16);
}));
}
function byteArray2hex(byteArray) {
return Array.prototype.map.call(byteArray, function(byte) {
return ("0" + (byte & 0xFF).toString(16)).slice(-2);
}).join("");
}
function stringifyBigIntsWithField(Fr, o) {
if (o instanceof Uint8Array) {
return Fr.toString(o);
} else if (Array.isArray(o)) {
return o.map(stringifyBigIntsWithField.bind(null, Fr));
} else if (typeof o == "object") {
const res = {};
const keys = Object.keys(o);
keys.forEach( (k) => {
res[k] = stringifyBigIntsWithField(Fr, o[k]);
});
return res;
} else if ((typeof(o) == "bigint") || o.eq !== undefined) {
return o.toString(10);
} else {
return o;
}
}
const HEADER_ZKEY_SECTION = 1;
const GROTH16_PROTOCOL_ID = 1;
const PLONK_PROTOCOL_ID = 2;
const FFLONK_PROTOCOL_ID = 10;
/*
Copyright 2022 iden3 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/>.
*/
// FFlonk constants
const FF_T_POL_DEG_MIN = 3;
// ZKEY constants
const ZKEY_FF_NSECTIONS = 17;
const ZKEY_FF_HEADER_SECTION = 2;
const ZKEY_FF_ADDITIONS_SECTION = 3;
const ZKEY_FF_A_MAP_SECTION = 4;
const ZKEY_FF_B_MAP_SECTION = 5;
const ZKEY_FF_C_MAP_SECTION = 6;
const ZKEY_FF_QL_SECTION = 7;
const ZKEY_FF_QR_SECTION = 8;
const ZKEY_FF_QM_SECTION = 9;
const ZKEY_FF_QO_SECTION = 10;
const ZKEY_FF_QC_SECTION = 11;
const ZKEY_FF_SIGMA1_SECTION = 12;
const ZKEY_FF_SIGMA2_SECTION = 13;
const ZKEY_FF_SIGMA3_SECTION = 14;
const ZKEY_FF_LAGRANGE_SECTION = 15;
const ZKEY_FF_PTAU_SECTION = 16;
const ZKEY_FF_C0_SECTION = 17;
/*
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/>.
*/
async function writeHeader(fd, zkey) {
// Write the header
///////////
await binFileUtils__namespace.startWriteSection(fd, 1);
await fd.writeULE32(1); // Groth
await binFileUtils__namespace.endWriteSection(fd);
// Write the Groth header section
///////////
const curve = await getCurveFromQ(zkey.q);
await binFileUtils__namespace.startWriteSection(fd, 2);
const primeQ = curve.q;
const n8q = (Math.floor( (ffjavascript.Scalar.bitLength(primeQ) - 1) / 64) +1)*8;
const primeR = curve.r;
const n8r = (Math.floor( (ffjavascript.Scalar.bitLength(primeR) - 1) / 64) +1)*8;
await fd.writeULE32(n8q);
await binFileUtils__namespace.writeBigInt(fd, primeQ, n8q);
await fd.writeULE32(n8r);
await binFileUtils__namespace.writeBigInt(fd, primeR, n8r);
await fd.writeULE32(zkey.nVars); // Total number of bars
await fd.writeULE32(zkey.nPublic); // Total number of public vars (not including ONE)
await fd.writeULE32(zkey.domainSize); // domainSize
await writeG1(fd, curve, zkey.vk_alpha_1);
await writeG1(fd, curve, zkey.vk_beta_1);
await writeG2(fd, curve, zkey.vk_beta_2);
await writeG2(fd, curve, zkey.vk_gamma_2);
await writeG1(fd, curve, zkey.vk_delta_1);
await writeG2(fd, curve, zkey.vk_delta_2);
await binFileUtils__namespace.endWriteSection(fd);
}
async function writeG1(fd, curve, p) {
const buff = new Uint8Array(curve.G1.F.n8*2);
curve.G1.toRprLEM(buff, 0, p);
await fd.write(buff);
}
async function writeG2(fd, curve, p) {
const buff = new Uint8Array(curve.G2.F.n8*2);
curve.G2.toRprLEM(buff, 0, p);
await fd.write(buff);
}
async function readG1(fd, curve, toObject) {
const buff = await fd.read(curve.G1.F.n8*2);
const res = curve.G1.fromRprLEM(buff, 0);
return toObject ? curve.G1.toObject(res) : res;
}
async function readG2(fd, curve, toObject) {
const buff = await fd.read(curve.G2.F.n8*2);
const res = curve.G2.fromRprLEM(buff, 0);
return toObject ? curve.G2.toObject(res) : res;
}
async function readHeader$1(fd, sections, toObject, options) {
// Read Header
/////////////////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 1);
const protocolId = await fd.readULE32();
await binFileUtils__namespace.endReadSection(fd);
if (protocolId === GROTH16_PROTOCOL_ID) {
return await readHeaderGroth16(fd, sections, toObject, options);
} else if (protocolId === PLONK_PROTOCOL_ID) {
return await readHeaderPlonk(fd, sections, toObject, options);
} else if (protocolId === FFLONK_PROTOCOL_ID) {
return await readHeaderFFlonk(fd, sections, toObject, options);
} else {
throw new Error("Protocol not supported: ");
}
}
async function readHeaderGroth16(fd, sections, toObject, options) {
const zkey = {};
zkey.protocol = "groth16";
// Read Groth Header
/////////////////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 2);
const n8q = await fd.readULE32();
zkey.n8q = n8q;
zkey.q = await binFileUtils__namespace.readBigInt(fd, n8q);
const n8r = await fd.readULE32();
zkey.n8r = n8r;
zkey.r = await binFileUtils__namespace.readBigInt(fd, n8r);
zkey.curve = await getCurveFromQ(zkey.q, options);
zkey.nVars = await fd.readULE32();
zkey.nPublic = await fd.readULE32();
zkey.domainSize = await fd.readULE32();
zkey.power = log2(zkey.domainSize);
zkey.vk_alpha_1 = await readG1(fd, zkey.curve, toObject);
zkey.vk_beta_1 = await readG1(fd, zkey.curve, toObject);
zkey.vk_beta_2 = await readG2(fd, zkey.curve, toObject);
zkey.vk_gamma_2 = await readG2(fd, zkey.curve, toObject);
zkey.vk_delta_1 = await readG1(fd, zkey.curve, toObject);
zkey.vk_delta_2 = await readG2(fd, zkey.curve, toObject);
await binFileUtils__namespace.endReadSection(fd);
return zkey;
}
async function readHeaderPlonk(fd, sections, toObject, options) {
const zkey = {};
zkey.protocol = "plonk";
// Read Plonk Header
/////////////////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 2);
const n8q = await fd.readULE32();
zkey.n8q = n8q;
zkey.q = await binFileUtils__namespace.readBigInt(fd, n8q);
const n8r = await fd.readULE32();
zkey.n8r = n8r;
zkey.r = await binFileUtils__namespace.readBigInt(fd, n8r);
zkey.curve = await getCurveFromQ(zkey.q, options);
zkey.nVars = await fd.readULE32();
zkey.nPublic = await fd.readULE32();
zkey.domainSize = await fd.readULE32();
zkey.power = log2(zkey.domainSize);
zkey.nAdditions = await fd.readULE32();
zkey.nConstraints = await fd.readULE32();
zkey.k1 = await fd.read(n8r);
zkey.k2 = await fd.read(n8r);
zkey.Qm = await readG1(fd, zkey.curve, toObject);
zkey.Ql = await readG1(fd, zkey.curve, toObject);
zkey.Qr = await readG1(fd, zkey.curve, toObject);
zkey.Qo = await readG1(fd, zkey.curve, toObject);
zkey.Qc = await readG1(fd, zkey.curve, toObject);
zkey.S1 = await readG1(fd, zkey.curve, toObject);
zkey.S2 = await readG1(fd, zkey.curve, toObject);
zkey.S3 = await readG1(fd, zkey.curve, toObject);
zkey.X_2 = await readG2(fd, zkey.curve, toObject);
await binFileUtils__namespace.endReadSection(fd);
return zkey;
}
async function readHeaderFFlonk(fd, sections, toObject, options) {
const zkey = {};
zkey.protocol = "fflonk";
zkey.protocolId = FFLONK_PROTOCOL_ID;
await binFileUtils__namespace.startReadUniqueSection(fd, sections, ZKEY_FF_HEADER_SECTION);
const n8q = await fd.readULE32();
zkey.n8q = n8q;
zkey.q = await binFileUtils__namespace.readBigInt(fd, n8q);
zkey.curve = await getCurveFromQ(zkey.q, options);
const n8r = await fd.readULE32();
zkey.n8r = n8r;
zkey.r = await binFileUtils__namespace.readBigInt(fd, n8r);
zkey.nVars = await fd.readULE32();
zkey.nPublic = await fd.readULE32();
zkey.domainSize = await fd.readULE32();
zkey.power = log2(zkey.domainSize);
zkey.nAdditions = await fd.readULE32();
zkey.nConstraints = await fd.readULE32();
zkey.k1 = await fd.read(n8r);
zkey.k2 = await fd.read(n8r);
zkey.w3 = await fd.read(n8r);
zkey.w4 = await fd.read(n8r);
zkey.w8 = await fd.read(n8r);
zkey.wr = await fd.read(n8r);
zkey.X_2 = await readG2(fd, zkey.curve, toObject);
zkey.C0 = await readG1(fd, zkey.curve, toObject);
await binFileUtils__namespace.endReadSection(fd);
return zkey;
}
async function readZKey(fileName, toObject) {
const {fd, sections} = await binFileUtils__namespace.readBinFile(fileName, "zkey", 1);
const zkey = await readHeader$1(fd, sections, toObject);
const Fr = new ffjavascript.F1Field(zkey.r);
const Rr = ffjavascript.Scalar.mod(ffjavascript.Scalar.shl(1, zkey.n8r*8), zkey.r);
const Rri = Fr.inv(Rr);
const Rri2 = Fr.mul(Rri, Rri);
let curve = await getCurveFromQ(zkey.q);
// Read IC Section
///////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 3);
zkey.IC = [];
for (let i=0; i<= zkey.nPublic; i++) {
const P = await readG1(fd, curve, toObject);
zkey.IC.push(P);
}
await binFileUtils__namespace.endReadSection(fd);
// Read Coefs
///////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 4);
const nCCoefs = await fd.readULE32();
zkey.ccoefs = [];
for (let i=0; i<nCCoefs; i++) {
const m = await fd.readULE32();
const c = await fd.readULE32();
const s = await fd.readULE32();
const v = await readFr2();
zkey.ccoefs.push({
matrix: m,
constraint: c,
signal: s,
value: v
});
}
await binFileUtils__namespace.endReadSection(fd);
// Read A points
///////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 5);
zkey.A = [];
for (let i=0; i<zkey.nVars; i++) {
const A = await readG1(fd, curve, toObject);
zkey.A[i] = A;
}
await binFileUtils__namespace.endReadSection(fd);
// Read B1
///////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 6);
zkey.B1 = [];
for (let i=0; i<zkey.nVars; i++) {
const B1 = await readG1(fd, curve, toObject);
zkey.B1[i] = B1;
}
await binFileUtils__namespace.endReadSection(fd);
// Read B2 points
///////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 7);
zkey.B2 = [];
for (let i=0; i<zkey.nVars; i++) {
const B2 = await readG2(fd, curve, toObject);
zkey.B2[i] = B2;
}
await binFileUtils__namespace.endReadSection(fd);
// Read C points
///////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 8);
zkey.C = [];
for (let i=zkey.nPublic+1; i<zkey.nVars; i++) {
const C = await readG1(fd, curve, toObject);
zkey.C[i] = C;
}
await binFileUtils__namespace.endReadSection(fd);
// Read H points
///////////
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 9);
zkey.hExps = [];
for (let i=0; i<zkey.domainSize; i++) {
const H = await readG1(fd, curve, toObject);
zkey.hExps.push(H);
}
await binFileUtils__namespace.endReadSection(fd);
await fd.close();
return zkey;
async function readFr2(/* toObject */) {
const n = await binFileUtils__namespace.readBigInt(fd, zkey.n8r);
return Fr.mul(n, Rri2);
}
}
async function readContribution$1(fd, curve, toObject) {
const c = {delta:{}};
c.deltaAfter = await readG1(fd, curve, toObject);
c.delta.g1_s = await readG1(fd, curve, toObject);
c.delta.g1_sx = await readG1(fd, curve, toObject);
c.delta.g2_spx = await readG2(fd, curve, toObject);
c.transcript = await fd.read(64);
c.type = await fd.readULE32();
const paramLength = await fd.readULE32();
const curPos = fd.pos;
let lastType =0;
while (fd.pos-curPos < paramLength) {
const buffType = await fd.read(1);
if (buffType[0]<= lastType) throw new Error("Parameters in the contribution must be sorted");
lastType = buffType[0];
if (buffType[0]==1) { // Name
const buffLen = await fd.read(1);
const buffStr = await fd.read(buffLen[0]);
c.name = new TextDecoder().decode(buffStr);
} else if (buffType[0]==2) {
const buffExp = await fd.read(1);
c.numIterationsExp = buffExp[0];
} else if (buffType[0]==3) {
const buffLen = await fd.read(1);
c.beaconHash = await fd.read(buffLen[0]);
} else {
throw new Error("Parameter not recognized");
}
}
if (fd.pos != curPos + paramLength) {
throw new Error("Parameters do not match");
}
return c;
}
async function readMPCParams(fd, curve, sections) {
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 10);
const res = { contributions: []};
res.csHash = await fd.read(64);
const n = await fd.readULE32();
for (let i=0; i<n; i++) {
const c = await readContribution$1(fd, curve);
res.contributions.push(c);
}
await binFileUtils__namespace.endReadSection(fd);
return res;
}
async function writeContribution$1(fd, curve, c) {
await writeG1(fd, curve, c.deltaAfter);
await writeG1(fd, curve, c.delta.g1_s);
await writeG1(fd, curve, c.delta.g1_sx);
await writeG2(fd, curve, c.delta.g2_spx);
await fd.write(c.transcript);
await fd.writeULE32(c.type || 0);
const params = [];
if (c.name) {
params.push(1); // Param Name
const nameData = new TextEncoder("utf-8").encode(c.name.substring(0,64));
params.push(nameData.byteLength);
for (let i=0; i<nameData.byteLength; i++) params.push(nameData[i]);
}
if (c.type == 1) {
params.push(2); // Param numIterationsExp
params.push(c.numIterationsExp);
params.push(3); // Beacon Hash
params.push(c.beaconHash.byteLength);
for (let i=0; i<c.beaconHash.byteLength; i++) params.push(c.beaconHash[i]);
}
if (params.length>0) {
const paramsBuff = new Uint8Array(params);
await fd.writeULE32(paramsBuff.byteLength);
await fd.write(paramsBuff);
} else {
await fd.writeULE32(0);
}
}
async function writeMPCParams(fd, curve, mpcParams) {
await binFileUtils__namespace.startWriteSection(fd, 10);
await fd.write(mpcParams.csHash);
await fd.writeULE32(mpcParams.contributions.length);
for (let i=0; i<mpcParams.contributions.length; i++) {
await writeContribution$1(fd, curve,mpcParams.contributions[i]);
}
await binFileUtils__namespace.endWriteSection(fd);
}
function hashG1(hasher, curve, p) {
const buff = new Uint8Array(curve.G1.F.n8*2);
curve.G1.toRprUncompressed(buff, 0, p);
hasher.update(buff);
}
function hashG2(hasher,curve, p) {
const buff = new Uint8Array(curve.G2.F.n8*2);
curve.G2.toRprUncompressed(buff, 0, p);
hasher.update(buff);
}
function hashPubKey(hasher, curve, c) {
hashG1(hasher, curve, c.deltaAfter);
hashG1(hasher, curve, c.delta.g1_s);
hashG1(hasher, curve, c.delta.g1_sx);
hashG2(hasher, curve, c.delta.g2_spx);
hasher.update(c.transcript);
}
/*
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/>.
*/
async function write(fd, witness, prime) {
await binFileUtils__namespace.startWriteSection(fd, 1);
const n8 = (Math.floor( (ffjavascript.Scalar.bitLength(prime) - 1) / 64) +1)*8;
await fd.writeULE32(n8);
await binFileUtils__namespace.writeBigInt(fd, prime, n8);
await fd.writeULE32(witness.length);
await binFileUtils__namespace.endWriteSection(fd);
await binFileUtils__namespace.startWriteSection(fd, 2);
for (let i=0; i<witness.length; i++) {
await binFileUtils__namespace.writeBigInt(fd, witness[i], n8);
}
await binFileUtils__namespace.endWriteSection(fd, 2);
}
async function writeBin(fd, witnessBin, prime) {
await binFileUtils__namespace.startWriteSection(fd, 1);
const n8 = (Math.floor( (ffjavascript.Scalar.bitLength(prime) - 1) / 64) +1)*8;
await fd.writeULE32(n8);
await binFileUtils__namespace.writeBigInt(fd, prime, n8);
if (witnessBin.byteLength % n8 != 0) {
throw new Error("Invalid witness length");
}
await fd.writeULE32(witnessBin.byteLength / n8);
await binFileUtils__namespace.endWriteSection(fd);
await binFileUtils__namespace.startWriteSection(fd, 2);
await fd.write(witnessBin);
await binFileUtils__namespace.endWriteSection(fd);
}
async function readHeader(fd, sections) {
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 1);
const n8 = await fd.readULE32();
const q = await binFileUtils__namespace.readBigInt(fd, n8);
const nWitness = await fd.readULE32();
await binFileUtils__namespace.endReadSection(fd);
return {n8, q, nWitness};
}
async function read(fileName) {
const {fd, sections} = await binFileUtils__namespace.readBinFile(fileName, "wtns", 2);
const {n8, nWitness} = await readHeader(fd, sections);
await binFileUtils__namespace.startReadUniqueSection(fd, sections, 2);
const res = [];
for (let i=0; i<nWitness; i++) {
const v = await binFileUtils__namespace.readBigInt(fd, n8);
res.push(v);
}
await binFileUtils__namespace.endReadSection(fd);
await fd.close();
return res;
}
/*
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/>.
*/
const {stringifyBigInts: stringifyBigInts$4} = ffjavascript.utils;
async function groth16Prove(zkeyFileName, witnessFileName, logger, options) {
const {fd: fdWtns, sections: sectionsWtns} = await binFileUtils__namespace.readBinFile(witnessFileName, "wtns", 2, 1<<25, 1<<23);
const wtns = await readHeader(fdWtns, sectionsWtns);
const {fd: fdZKey, sections: sectionsZKey} = await binFileUtils__namespace.readBinFile(zkeyFileName, "zkey", 2, 1<<25, 1<<23);
const zkey = await readHeader$1(fdZKey, sectionsZKey, undefined, options);
if (zkey.protocol != "groth16") {
throw new Error("zkey file is not groth16");
}
if (!ffjavascript.Scalar.eq(zkey.r, wtns.q)) {
throw new Error("Curve of the witness does not match the curve of the proving key");
}
if (wtns.nWitness != zkey.nVars) {
throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`);
}
const curve = zkey.curve;
const Fr = curve.Fr;
const G1 = curve.G1;
const G2 = curve.G2;
const power = log2(zkey.domainSize);
if (logger) logger.debug("Reading Wtns");
const buffWitness = await binFileUtils__namespace.readSection(fdWtns, sectionsWtns, 2);
if (logger) logger.debug("Reading Coeffs");
const buffCoeffs = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 4);
if (logger) logger.debug("Building ABC");
const [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs, logger);
const inc = power == Fr.s ? curve.Fr.shift : curve.Fr.w[power+1];
const buffA = await Fr.ifft(buffA_T, "", "", logger, "IFFT_A");
const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc);
const buffAodd_T = await Fr.fft(buffAodd, "", "", logger, "FFT_A");
const buffB = await Fr.ifft(buffB_T, "", "", logger, "IFFT_B");
const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc);
const buffBodd_T = await Fr.fft(buffBodd, "", "", logger, "FFT_B");
const buffC = await Fr.ifft(buffC_T, "", "", logger, "IFFT_C");
const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc);
const buffCodd_T = await Fr.fft(buffCodd, "", "", logger, "FFT_C");
if (logger) logger.debug("Join ABC");
const buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T, logger);
let proof = {};
if (logger) logger.debug("Reading A Points");
const buffBasesA = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 5);
proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, logger, "multiexp A");
if (logger) logger.debug("Reading B1 Points");
const buffBasesB1 = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 6);
let pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, logger, "multiexp B1");
if (logger) logger.debug("Reading B2 Points");
const buffBasesB2 = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 7);
proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, logger, "multiexp B2");
if (logger) logger.debug("Reading C Points");
const buffBasesC = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 8);
proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic+1)*curve.Fr.n8), logger, "multiexp C");
if (logger) logger.debug("Reading H Points");
const buffBasesH = await binFileUtils__namespace.readSection(fdZKey, sectionsZKey, 9);
const resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, logger, "multiexp H");
const r = curve.Fr.random();
const s = curve.Fr.random();
proof.pi_a = G1.add( proof.pi_a, zkey.vk_alpha_1 );
proof.pi_a = G1.add( proof.pi_a, G1.timesFr( zkey.vk_delta_1, r ));
proof.pi_b = G2.add( proof.pi_b, zkey.vk_beta_2 );
proof.pi_b = G2.add( proof.pi_b, G2.timesFr( zkey.vk_delta_2, s ));
pib1 = G1.add( pib1, zkey.vk_beta_1 );
pib1 = G1.add( pib1, G1.timesFr( zkey.vk_delta_1, s ));
proof.pi_c = G1.add(proof.pi_c, resH);
proof.pi_c = G1.add( proof.pi_c, G1.timesFr( proof.pi_a, s ));
proof.pi_c = G1.add( proof.pi_c, G1.timesFr( pib1, r ));
proof.pi_c = G1.add( proof.pi_c, G1.timesFr( zkey.vk_delta_1, Fr.neg(Fr.mul(r,s) )));
let publicSignals = [];
for (let i=1; i<= zkey.nPublic; i++) {
const b = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8);
publicSignals.push(ffjavascript.Scalar.fromRprLE(b));
}
proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a));
proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b));
proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c));
proof.protocol = "groth16";
proof.curve = curve.name;
await fdZKey.close();
await fdWtns.close();
proof = stringifyBigInts$4(proof);
publicSignals = stringifyBigInts$4(publicSignals);
return {proof, publicSignals};
}
async function buildABC1(curve, zkey, witness, coeffs, logger) {
const n8 = curve.Fr.n8;
const sCoef = 4*3 + zkey.n8r;
const nCoef = (coeffs.byteLength-4) / sCoef;
const outBuffA = new ffjavascript.BigBuffer(zkey.domainSize * n8);
const outBuffB = new ffjavascript.BigBuffer(zkey.domainSize * n8);
const outBuffC = new ffjavascript.BigBuffer(zkey.domainSize * n8);
const outBuf = [ outBuffA, outBuffB ];
for (let i=0; i<nCoef; i++) {
if ((logger)&&(i%1000000 == 0)) logger.debug(`QAP AB: ${i}/${nCoef}`);
const buffCoef = coeffs.slice(4+i*sCoef, 4+i*sCoef+sCoef);
const buffCoefV = new DataView(buffCoef.buffer);
const m= buffCoefV.getUint32(0, true);
const c= buffCoefV.getUint32(4, true);
const s= buffCoefV.getUint32(8, true);
const coef = buffCoef.slice(12, 12+n8);
outBuf[m].set(
curve.Fr.add(
outBuf[m].slice(c*n8, c*n8+n8),
curve.Fr.mul(coef, witness.slice(s*n8, s*n8+n8))
),
c*n8
);
}
for (let i=0; i<zkey.domainSize; i++) {
if ((logger)&&(i%1000000 == 0)) logger.debug(`QAP C: ${i}/${zkey.domainSize}`);
outBuffC.set(
curve.Fr.mul(
outBuffA.slice(i*n8, i*n8+n8),
outBuffB.slice(i*n8, i*n8+n8),
),
i*n8
);
}
return [outBuffA, outBuffB, outBuffC];
}
/*
async function buildABC(curve, zkey, witness, coeffs, logger) {
const concurrency = curve.tm.concurrency;
const sCoef = 4*3 + zkey.n8r;
let getUint32;
if (coeffs instanceof BigBuffer) {
const coeffsDV = [];
const PAGE_LEN = coeffs.buffers[0].length;
for (let i=0; i< coeffs.buffers.length; i++) {
coeffsDV.push(new DataView(coeffs.buffers[i].buffer));
}
getUint32 = function (pos) {
return coeffsDV[Math.floor(pos/PAGE_LEN)].getUint32(pos % PAGE_LEN, true);
};
} else {
const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength);
getUint32 = function (pos) {
return coeffsDV.getUint32(pos, true);
};
}
const elementsPerChunk = Math.floor(zkey.domainSize/concurrency);
const promises = [];
const cutPoints = [];
for (let i=0; i<concurrency; i++) {
cutPoints.push( getCutPoint( Math.floor(i*elementsPerChunk) ));
}
cutPoints.push(coeffs.byteLength);
const chunkSize = 2**26;
for (let s=0 ; s<zkey.nVars ; s+= chunkSize) {
if (logger) logger.debug(`QAP ${s}: ${s}/${zkey.nVars}`);
const ns= Math.min(zkey.nVars-s, chunkSize );
for (let i=0; i<concurrency; i++) {
let n;
if (i< concurrency-1) {
n = elementsPerChunk;
} else {
n = zkey.domainSize - i*elementsPerChunk;
}
if (n==0) continue;
const task = [];
task.push({cmd: "ALLOCSET", var: 0, buff: coeffs.slice(cutPoints[i], cutPoints[i+1])});
task.push({cmd: "ALLOCSET", var: 1, buff: witness.slice(s*curve.Fr.n8, (s+ns)*curve.Fr.n8)});
task.push({cmd: "ALLOC", var: 2, len: n*curve.Fr.n8});
task.push({cmd: "ALLOC", var: 3, len: n*curve.Fr.n8});
task.push({cmd: "ALLOC", var: 4, len: n*curve.Fr.n8});
task.push({cmd: "CALL", fnName: "qap_buildABC", params:[
{var: 0},
{val: (cutPoints[i+1] - cutPoints[i])/sCoef},
{var: 1},
{var: 2},
{var: 3},
{var: 4},
{val: i*elementsPerChunk},
{val: n},
{val: s},
{val: ns}
]});
task.push({cmd: "GET", out: 0, var: 2, len: n*curve.Fr.n8});
task.push({cmd: "GET", out: 1, var: 3, len: n*curve.Fr.n8});
task.push({cmd: "GET", out: 2, var: 4, len: n*curve.Fr.n8});
promises.push(curve.tm.queueAction(task));
}
}
let result = await Promise.all(promises);
const nGroups = result.length / concurrency;
if (nGroups>1) {
const promises2 = [];
for (let i=0; i<concurrency; i++) {
const task=[];
task.push({cmd: "ALLOC", var: 0, len: result[i][0].byteLength});
task.push({cmd: "ALLOC", var: 1, len: result[i][0].byteLength});
for (let m=0; m<3; m++) {
task.push({cmd: "SET", var: 0, buff: result[i][m]});
for (let s=1; s<nGroups; s++) {
task.push({cmd: "SET", var: 1, buff: result[s*concurrency + i][m]});
task.push({cmd: "CALL", fnName: "qap_batchAdd", params:[
{var: 0},
{var: 1},
{val: result[i][m].length/curve.Fr.n8},
{var: 0}
]});
}
task.push({cmd: "GET", out: m, var: 0, len: result[i][m].length});
}
promises2.push(curve.tm.queueAction(task));
}
result = await Promise.all(promises2);
}
const outBuffA = new BigBuffer(zkey.domainSize * curve.Fr.n8);
const outBuffB = new BigBuffer(zkey.domainSize * curve.Fr.n8);
const outBuffC = new BigBuffer(zkey.domainSize * curve.Fr.n8);
let p=0;
for (let i=0; i<result.length; i++) {
outBuffA.set(result[i][0], p);
outBuffB.set(result[i][1], p);
outBuffC.set(result[i][2], p);
p += result[i][0].byteLength;
}
return [outBuffA, outBuffB, outBuffC];
function getCutPoint(v) {
let m = 0;
let n = getUint32(0);
while (m < n) {
var k = Math.floor((n + m) / 2);
const va = getUint32(4 + k*sCoef + 4);
if (va > v) {
n = k - 1;
} else if (va < v) {
m = k + 1;
} else {
n = k;
}
}
return 4 + m*sCoef;
}
}
*/
async function joinABC(curve, zkey, a, b, c, logger) {
const MAX_CHUNK_SIZE = 1 << 22;
const n8 = curve.Fr.n8;
const nElements = Math.floor(a.byteLength / curve.Fr.n8);
const promises = [];
for (let i=0; i<nElements; i += MAX_CHUNK_SIZE) {
if (logger) logger.debug(`JoinABC: ${i}/${nElements}`);
const n= Math.min(nElements - i, MAX_CHUNK_SIZE);
const task = [];
const aChunk = a.slice(i*n8, (i + n)*n8 );
const bChunk = b.slice(i*n8, (i + n)*n8 );
const cChunk = c.slice(i*n8, (i + n)*n8 );
task.push({cmd: "ALLOCSET", var: 0, buff: aChunk});
task.push({cmd: "ALLOCSET", var: 1, buff: bChunk});
task.push({cmd: "ALLOCSET", var: 2, buff: cChunk});
task.push({cmd: "ALLOC", var: 3, len: n*n8});
task.push({cmd: "CALL", fnName: "qap_joinABC", params:[
{var: 0},
{var: 1},
{var: 2},
{val: n},
{var: 3},
]});
task.push({cmd: "CALL", fnName: "frm_batchFromMontgomery", params:[
{var: 3},
{val: n},
{var: 3}
]});
task.push({cmd: "GET", out: 0, var: 3, len: n*n8});
promises.push(curve.tm.queueAction(task));
}
const result = await Promise.all(promises);
let outBuff;
if (a instanceof ffjavascript.BigBuffer) {
outBuff = new ffjavascript.BigBuffer(a.byteLength);
} else {
outBuff = new Uint8Array(a.byteLength);
}
let p=0;
for (let i=0; i<result.length; i++) {
outBuff.set(result[i][0], p);
p += result[i][0].byteLength;
}
return outBuff;
}
/*
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/>.
*/
const { unstringifyBigInts: unstringifyBigInts$b} = ffjavascript.utils;
async function wtnsCalculate(_input, wasmFileName, wtnsFileName, options) {
const input = unstringifyBigInts$b(_input);
const fdWasm = await fastFile__namespace.readExisting(wasmFileName);
const wasm = await fdWasm.read(fdWasm.totalSize);
await fdWasm.close();
const wc = await circom_runtime.WitnessCalculatorBuilder(wasm, options);
if (wc.circom_version() === 1) {
const w = await wc.calculateBinWitness(input);
const fdWtns = await binFileUtils__namespace.createBinFile(wtnsFileName, "wtns", 2, 2);
await writeBin(fdWtns, w, wc.prime);
await fdWtns.close();
} else {
const fdWtns = await fastFile__namespace.createOverride(wtnsFileName);
const w = await wc.calculateWTNSBin(input);
await fdWtns.write(w);
await fdWtns.close();
}
}
/*
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/>.
*/
const {unstringifyBigInts: unstringifyBigInts$a} = ffjavascript.utils;
async function groth16FullProve(_input, wasmFile, zkeyFileName, logger, wtnsCalcOptions, proverOptions) {
const input = unstringifyBigInts$a(_input);
const wtns= {
type: "mem"
};
await wtnsCalculate(input, wasmFile, wtns, wtnsCalcOptions);
return await groth16Prove(zkeyFileName, wtns, logger, proverOptions);
}
/*
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/>.
*/
const {unstringifyBigInts: unstringifyBigInts$9} = ffjavascript.utils;
async function groth16Verify(_vk_verifier, _publicSignals, _proof, logger) {
/*
let cpub = vk_verifier.IC[0];
for (let s= 0; s< vk_verifier.nPublic; s++) {
cpub = G1.add( cpub, G1.timesScalar( vk_verifier.IC[s+1], publicSignals[s]));
}
*/
const vk_verifier = unstringifyBigInts$9(_vk_verifier);
const proof = unstringifyBigInts$9(_proof);
const publicSignals = unstringifyBigInts$9(_publicSignals);
const curve = await getCurveFromName(vk_verifier.curve);
const IC0 = curve.G1.fromObject(vk_verifier.IC[0]);
const IC = new Uint8Array(curve.G1.F.n8*2 * publicSignals.length);
const w = new Uint8Array(curve.Fr.n8 * publicSignals.length);
if (!publicInputsAreValid$1(curve, publicSignals)) {
if (logger) logger.error("Public inputs are not valid.");
return false;
}
for (let i=0; i<publicSignals.length; i++) {
const buffP = curve.G1.fromObject(vk_verifier.IC[i+1]);
IC.set(buffP, i*curve.G1.F.n8*2);
ffjavascript.Scalar.toRprLE(w, curve.Fr.n8*i, publicSignals[i], curve.Fr.n8);
}
let cpub = await curve.G1.multiExpAffine(IC, w);
cpub = curve.G1.add(cpub, IC0);
const pi_a = curve.G1.fromObject(proof.pi_a);
const pi_b = curve.G2.fromObject(proof.pi_b);
const pi_c = curve.G1.fromObject(proof.pi_c);
if (!isWellConstructed$1(curve, {pi_a, pi_b, pi_c})) {
if(logger) logger.error("Proof commitments are not valid.");
return false;
}
const vk_gamma_2 = curve.G2.fromObject(vk_verifier.vk_gamma_2);
const vk_delta_2 = curve.G2.fromObject(vk_verifier.vk_delta_2);
const vk_alpha_1 = curve.G1.fromObject(vk_verifier.vk_alpha_1);
const vk_beta_2 = curve.G2.fromObject(vk_verifier.vk_beta_2);
const res = await curve.pairingEq(
curve.G1.neg(pi_a) , pi_b,
cpub , vk_gamma_2,
pi_c , vk_delta_2,
vk_alpha_1, vk_beta_2
);
if (! res) {
if (logger) logger.error("Invalid proof");
return false;
}
if (logger) logger.info("OK!");
return true;
}
function isWellConstructed$1(curve, proof) {
const G1 = curve.G1;
const G2 = curve.G2;
return G1.isValid(proof.pi_a)
&& G2.isValid(proof.pi_b)
&& G1.isValid(proof.pi_c);
}
function publicInputsAreValid$1(curve, publicInputs) {
for(let i = 0; i < publicInputs.length; i++) {
if(!ffjavascript.Scalar.lt(publicInputs[i], curve.r)) {
return false;
}
}
return true;
}
/*
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/>.
*/
const { unstringifyBigInts: unstringifyBigInts$8} = ffjavascript.utils;
function p256$2(n) {
let nstr = n.toString(16);
while (nstr.length < 64) nstr = "0"+nstr;
nstr = `"0x${nstr}"`;
return nstr;
}
async function groth16ExportSolidityCallData(_proof, _pub) {
const proof = unstringifyBigInts$8(_proof);
const pub = unstringifyBigInts$8(_pub);
let inputs = "";
for (let i=0; i<pub.length; i++) {
if (inputs != "") inputs = inputs + ",";
inputs = inputs + p256$2(pub[i]);
}
let S;
S=`[${p256$2(proof.pi_a[0])}, ${p256$2(proof.pi_a[1])}],` +
`[[${p256$2(proof.pi_b[0][1])}, ${p256$2(proof.pi_b[0][0])}],[${p256$2(proof.pi_b[1][1])}, ${p256$2(proof.pi_b[1][0])}]],` +
`[${p256$2(proof.pi_c[0])}, ${p256$2(proof.pi_c[1])}],` +
`[${inputs}]`;
return S;
}
/*
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/>.
*/
var groth16 =