From 40e4769a78668e2d9421396e9c80e2f133d234ed Mon Sep 17 00:00:00 2001 From: cedoor Date: Wed, 11 Oct 2023 18:55:22 -0700 Subject: [PATCH] refactor(proof): move snarkjs code inside proof pkg --- packages/proof/package.json | 11 +- packages/proof/rollup.browser.config.ts | 20 +- packages/proof/rollup.node.config.ts | 4 +- packages/proof/src/calculateNullifierHash.ts | 2 +- packages/proof/src/generateProof.ts | 5 +- packages/proof/src/groth16/prove.ts | 226 +++++++++++++++++++ packages/proof/src/groth16/utils.ts | 14 ++ packages/proof/src/groth16/verify.ts | 73 ++++++ packages/proof/src/groth16/wtns-calculate.ts | 39 ++++ packages/proof/src/groth16/wtns-utils.ts | 32 +++ packages/proof/src/groth16/zkey-utils.ts | 60 +++++ packages/proof/src/verifyProof.ts | 4 +- packages/proof/tsconfig.json | 3 + yarn.lock | 184 +-------------- 14 files changed, 472 insertions(+), 205 deletions(-) create mode 100644 packages/proof/src/groth16/prove.ts create mode 100644 packages/proof/src/groth16/utils.ts create mode 100644 packages/proof/src/groth16/verify.ts create mode 100644 packages/proof/src/groth16/wtns-calculate.ts create mode 100644 packages/proof/src/groth16/wtns-utils.ts create mode 100644 packages/proof/src/groth16/zkey-utils.ts diff --git a/packages/proof/package.json b/packages/proof/package.json index c93840a01..0555b35f8 100644 --- a/packages/proof/package.json +++ b/packages/proof/package.json @@ -35,18 +35,17 @@ "access": "public" }, "devDependencies": { + "@iden3/binfileutils": "0.0.11", "@rollup/plugin-commonjs": "^24.1.0", "@rollup/plugin-json": "^5.0.1", "@rollup/plugin-node-resolve": "^15.0.2", - "@rollup/plugin-replace": "^5.0.3", "@rollup/plugin-virtual": "^3.0.2", - "ffjavascript": "^0.2.54", + "fastfile": "0.0.20", "poseidon-lite": "^0.2.0", "rimraf": "^5.0.5", "rollup": "^4.0.2", "rollup-plugin-cleanup": "^3.2.1", - "rollup-plugin-typescript2": "^0.31.2", - "snarkjs": "0.7.1" + "rollup-plugin-typescript2": "^0.31.2" }, "peerDependencies": { "@semaphore-protocol/group": "3.12.3", @@ -57,6 +56,8 @@ "@ethersproject/bytes": "^5.7.0", "@ethersproject/keccak256": "^5.7.0", "@ethersproject/strings": "^5.5.0", - "@zk-kit/incremental-merkle-tree": "0.4.3" + "@zk-kit/incremental-merkle-tree": "0.4.3", + "circom_runtime": "0.1.24", + "ffjavascript": "0.2.60" } } diff --git a/packages/proof/rollup.browser.config.ts b/packages/proof/rollup.browser.config.ts index 48d819b2c..acf966f38 100644 --- a/packages/proof/rollup.browser.config.ts +++ b/packages/proof/rollup.browser.config.ts @@ -1,7 +1,6 @@ import commonjs from "@rollup/plugin-commonjs" import json from "@rollup/plugin-json" import { nodeResolve } from "@rollup/plugin-node-resolve" -import replace from "@rollup/plugin-replace" import virtual from "@rollup/plugin-virtual" import * as fs from "fs" import cleanup from "rollup-plugin-cleanup" @@ -47,24 +46,11 @@ export default { }), virtual({ fs: empty, - os: empty, - crypto: empty, - readline: empty, - ejs: empty, - events: empty, - stream: empty, - util: empty, constants }), - nodeResolve({ - browser: true, - preferBuiltins: false, - exportConditions: ["browser", "default", "module", "require"] - }), - commonjs(), - replace({ - preventAssignment: false, - "process.browser": true + nodeResolve(), + commonjs({ + esmExternals: true }), cleanup({ comments: "jsdoc" }), json() diff --git a/packages/proof/rollup.node.config.ts b/packages/proof/rollup.node.config.ts index 1a0f8d988..97c088b75 100644 --- a/packages/proof/rollup.node.config.ts +++ b/packages/proof/rollup.node.config.ts @@ -37,7 +37,9 @@ export default { useTsconfigDeclarationDir: true }), nodeResolve(), - commonjs(), + commonjs({ + esmExternals: true + }), cleanup({ comments: "jsdoc" }), json() ] diff --git a/packages/proof/src/calculateNullifierHash.ts b/packages/proof/src/calculateNullifierHash.ts index a63da439c..8cca53343 100644 --- a/packages/proof/src/calculateNullifierHash.ts +++ b/packages/proof/src/calculateNullifierHash.ts @@ -1,5 +1,5 @@ import { BytesLike, Hexable } from "@ethersproject/bytes" -import { poseidon2 } from "poseidon-lite/poseidon2" +import { poseidon2 } from "poseidon-lite" import hash from "./hash" /** diff --git a/packages/proof/src/generateProof.ts b/packages/proof/src/generateProof.ts index 78f57b9cf..cd372396d 100644 --- a/packages/proof/src/generateProof.ts +++ b/packages/proof/src/generateProof.ts @@ -3,10 +3,11 @@ import { BytesLike, Hexable } from "@ethersproject/bytes" import { Group } from "@semaphore-protocol/group" import type { Identity } from "@semaphore-protocol/identity" import { MerkleProof } from "@zk-kit/incremental-merkle-tree" -import { groth16, NumericString } from "snarkjs" +import type { NumericString } from "snarkjs" import hash from "./hash" import packProof from "./packProof" import { SemaphoreProof, SnarkArtifacts } from "./types" +import groth16Prove from "./groth16/prove" /** * Generates a Semaphore proof. @@ -45,7 +46,7 @@ export default async function generateProof( } } - const { proof, publicSignals } = await groth16.fullProve( + const { proof, publicSignals } = await groth16Prove( { identityTrapdoor: trapdoor, identityNullifier: nullifier, diff --git a/packages/proof/src/groth16/prove.ts b/packages/proof/src/groth16/prove.ts new file mode 100644 index 000000000..34a37aaf5 --- /dev/null +++ b/packages/proof/src/groth16/prove.ts @@ -0,0 +1,226 @@ +/* eslint-disable no-plusplus */ +/* eslint-disable eqeqeq */ +/* eslint-disable @typescript-eslint/naming-convention */ +/* istanbul ignore file */ + +// @ts-ignore +import * as binFileUtils from "@iden3/binfileutils" +import { BigBuffer, Scalar, utils } from "ffjavascript" +import { log2 } from "./utils" +import * as zkeyUtils from "./zkey-utils" +import * as wtnsUtils from "./wtns-utils" +import wtnsCalculate from "./wtns-calculate" + +const { stringifyBigInts, unstringifyBigInts } = utils + +async function buildABC1(curve: any, zkey: any, witness: any, coeffs: any) { + const { n8 } = curve.Fr + const sCoef = 4 * 3 + zkey.n8r + const nCoef = (coeffs.byteLength - 4) / sCoef + + const outBuffA = new BigBuffer(zkey.domainSize * n8) + const outBuffB = new BigBuffer(zkey.domainSize * n8) + const outBuffC = new BigBuffer(zkey.domainSize * n8) + + const outBuf = [outBuffA, outBuffB] + for (let i = 0; i < nCoef; i++) { + 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++) { + 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 joinABC(curve: any, _zkey: any, a: any, b: any, c: any) { + const MAX_CHUNK_SIZE = 1 << 22 + + const { n8 } = curve.Fr + const nElements = Math.floor(a.byteLength / curve.Fr.n8) + + const promises = [] + + for (let i = 0; i < nElements; i += MAX_CHUNK_SIZE) { + 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 BigBuffer) { + // @ts-ignore + outBuff = new 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 +} + +export default async function groth16Prove(_input: any, wasmFile: any, zkeyFileName: any) { + const input = unstringifyBigInts(_input) + + const witnessFileName = { + type: "mem" + } + + await wtnsCalculate(input, wasmFile, witnessFileName) + + const { fd: fdWtns, sections: sectionsWtns } = await binFileUtils.readBinFile( + witnessFileName, + "wtns", + 2, + 1 << 25, + 1 << 23 + ) + + const wtns = await wtnsUtils.readHeader(fdWtns, sectionsWtns) + + const { fd: fdZKey, sections: sectionsZKey } = await binFileUtils.readBinFile( + zkeyFileName, + "zkey", + 2, + 1 << 25, + 1 << 23 + ) + + const zkey = await zkeyUtils.readHeader(fdZKey, sectionsZKey, undefined) + + if (zkey.protocol !== "groth16") { + throw new Error("zkey file is not groth16") + } + + if (!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 + const { Fr } = curve + const { G1 } = curve + const { G2 } = curve + + const power = log2(zkey.domainSize) + + const buffWitness = await binFileUtils.readSection(fdWtns, sectionsWtns, 2) + const buffCoeffs = await binFileUtils.readSection(fdZKey, sectionsZKey, 4) + + const [buffA_T, buffB_T, buffC_T] = await buildABC1(curve, zkey, buffWitness, buffCoeffs) + + const inc = power == Fr.s ? curve.Fr.shift : curve.Fr.w[power + 1] + + const buffA = await Fr.ifft(buffA_T, "", "", undefined, "IFFT_A") + const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), inc) + const buffAodd_T = await Fr.fft(buffAodd, "", "", undefined, "FFT_A") + + const buffB = await Fr.ifft(buffB_T, "", "", undefined, "IFFT_B") + const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), inc) + const buffBodd_T = await Fr.fft(buffBodd, "", "", undefined, "FFT_B") + + const buffC = await Fr.ifft(buffC_T, "", "", undefined, "IFFT_C") + const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), inc) + const buffCodd_T = await Fr.fft(buffCodd, "", "", undefined, "FFT_C") + + const buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T) + + let proof: any = {} + + const buffBasesA = await binFileUtils.readSection(fdZKey, sectionsZKey, 5) + proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness, undefined, "multiexp A") + + const buffBasesB1 = await binFileUtils.readSection(fdZKey, sectionsZKey, 6) + let pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness, undefined, "multiexp B1") + + const buffBasesB2 = await binFileUtils.readSection(fdZKey, sectionsZKey, 7) + proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness, undefined, "multiexp B2") + + const buffBasesC = await binFileUtils.readSection(fdZKey, sectionsZKey, 8) + proof.pi_c = await curve.G1.multiExpAffine( + buffBasesC, + buffWitness.slice((zkey.nPublic + 1) * curve.Fr.n8), + undefined, + "multiexp C" + ) + + const buffBasesH = await binFileUtils.readSection(fdZKey, sectionsZKey, 9) + const resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T, undefined, "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(Scalar.fromRprLE(b, undefined, undefined)) + } + + 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(proof) + publicSignals = stringifyBigInts(publicSignals) + + return { proof, publicSignals } +} diff --git a/packages/proof/src/groth16/utils.ts b/packages/proof/src/groth16/utils.ts new file mode 100644 index 000000000..198edd1d3 --- /dev/null +++ b/packages/proof/src/groth16/utils.ts @@ -0,0 +1,14 @@ +/* eslint-disable import/prefer-default-export */ +/* eslint-disable no-return-assign */ +/* istanbul ignore file */ + +export function log2(V: any) { + 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) | + // @ts-ignore + ((V & 0xaaaaaaaa) !== 0) + ) +} diff --git a/packages/proof/src/groth16/verify.ts b/packages/proof/src/groth16/verify.ts new file mode 100644 index 000000000..e58330d6a --- /dev/null +++ b/packages/proof/src/groth16/verify.ts @@ -0,0 +1,73 @@ +/* eslint-disable no-plusplus */ +/* eslint-disable @typescript-eslint/naming-convention */ +/* istanbul ignore file */ + +import { Scalar, utils, buildBn128 } from "ffjavascript" + +const { unstringifyBigInts } = utils + +function isWellConstructed(curve: any, proof: any) { + const { G1 } = curve + const { G2 } = curve + + return G1.isValid(proof.pi_a) && G2.isValid(proof.pi_b) && G1.isValid(proof.pi_c) +} + +function publicInputsAreValid(curve: any, publicInputs: any) { + for (let i = 0; i < publicInputs.length; i++) { + if (!Scalar.lt(publicInputs[i], curve.r)) { + return false + } + } + return true +} + +export default async function groth16Verify(_vk_verifier: any, _publicSignals: any, _proof: any) { + const vk_verifier = unstringifyBigInts(_vk_verifier) + const proof = unstringifyBigInts(_proof) + const publicSignals = unstringifyBigInts(_publicSignals) + + const curve = await buildBn128(undefined, undefined) + + 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(curve, publicSignals)) { + 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) + 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(curve, { pi_a, pi_b, pi_c })) { + 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) + + return curve.pairingEq( + curve.G1.neg(pi_a), + pi_b, + cpub, + vk_gamma_2, + pi_c, + vk_delta_2, + + vk_alpha_1, + vk_beta_2 + ) +} diff --git a/packages/proof/src/groth16/wtns-calculate.ts b/packages/proof/src/groth16/wtns-calculate.ts new file mode 100644 index 000000000..263f7e91e --- /dev/null +++ b/packages/proof/src/groth16/wtns-calculate.ts @@ -0,0 +1,39 @@ +/* eslint-disable eqeqeq */ +/* istanbul ignore file */ + +// @ts-ignore +import * as binFileUtils from "@iden3/binfileutils" +// @ts-ignore +import { WitnessCalculatorBuilder } from "circom_runtime" +// @ts-ignore +import * as fastFile from "fastfile" +import { utils } from "ffjavascript" +import * as wtnsUtils from "./wtns-utils" + +const { unstringifyBigInts } = utils + +export default async function wtnsCalculate(_input: any, wasmFileName: any, wtnsFileName: any) { + const input = unstringifyBigInts(_input) + + const fdWasm = await fastFile.readExisting(wasmFileName) + const wasm = await fdWasm.read(fdWasm.totalSize) + await fdWasm.close() + + const wc = await WitnessCalculatorBuilder(wasm) + + if (wc.circom_version() == 1) { + const w = await wc.calculateBinWitness(input) + + const fdWtns = await binFileUtils.createBinFile(wtnsFileName, "wtns", 2, 2) + + await wtnsUtils.writeBin(fdWtns, w, wc.prime) + await fdWtns.close() + } else { + const fdWtns = await fastFile.createOverride(wtnsFileName) + + const w = await wc.calculateWTNSBin(input) + + await fdWtns.write(w) + await fdWtns.close() + } +} diff --git a/packages/proof/src/groth16/wtns-utils.ts b/packages/proof/src/groth16/wtns-utils.ts new file mode 100644 index 000000000..cadca43b2 --- /dev/null +++ b/packages/proof/src/groth16/wtns-utils.ts @@ -0,0 +1,32 @@ +/* eslint-disable eqeqeq */ +/* istanbul ignore file */ + +// @ts-ignore +import * as binFileUtils from "@iden3/binfileutils" +import { Scalar } from "ffjavascript" + +export async function writeBin(fd: any, witnessBin: any, prime: any) { + await binFileUtils.startWriteSection(fd, 1) + const n8 = (Math.floor((Scalar.bitLength(prime) - 1) / 64) + 1) * 8 + await fd.writeULE32(n8) + await binFileUtils.writeBigInt(fd, prime, n8) + if (witnessBin.byteLength % n8 != 0) { + throw new Error("Invalid witness length") + } + await fd.writeULE32(witnessBin.byteLength / n8) + await binFileUtils.endWriteSection(fd) + + await binFileUtils.startWriteSection(fd, 2) + await fd.write(witnessBin) + await binFileUtils.endWriteSection(fd) +} + +export async function readHeader(fd: any, sections: any) { + await binFileUtils.startReadUniqueSection(fd, sections, 1) + const n8 = await fd.readULE32() + const q = await binFileUtils.readBigInt(fd, n8) + const nWitness = await fd.readULE32() + await binFileUtils.endReadSection(fd) + + return { n8, q, nWitness } +} diff --git a/packages/proof/src/groth16/zkey-utils.ts b/packages/proof/src/groth16/zkey-utils.ts new file mode 100644 index 000000000..174726fdb --- /dev/null +++ b/packages/proof/src/groth16/zkey-utils.ts @@ -0,0 +1,60 @@ +/* eslint-disable import/prefer-default-export */ +/* istanbul ignore file */ + +// @ts-ignore +import * as binFileUtils from "@iden3/binfileutils" +import { buildBn128 } from "ffjavascript" +import { log2 } from "./utils" + +async function readG1(fd: any, curve: any, toObject: any) { + 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: any, curve: any, toObject: any) { + 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 readHeaderGroth16(fd: any, sections: any, toObject: any) { + const zkey: any = {} + + zkey.protocol = "groth16" + + await binFileUtils.startReadUniqueSection(fd, sections, 2) + const n8q = await fd.readULE32() + zkey.n8q = n8q + zkey.q = await binFileUtils.readBigInt(fd, n8q) + + const n8r = await fd.readULE32() + zkey.n8r = n8r + zkey.r = await binFileUtils.readBigInt(fd, n8r) + zkey.curve = await buildBn128(undefined, undefined) + 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.endReadSection(fd) + + return zkey +} + +export async function readHeader(fd: any, sections: any, toObject: any) { + await binFileUtils.startReadUniqueSection(fd, sections, 1) + const protocolId = await fd.readULE32() + await binFileUtils.endReadSection(fd) + + if (protocolId === 1) { + return readHeaderGroth16(fd, sections, toObject) + } + + throw new Error("Protocol not supported: ") +} diff --git a/packages/proof/src/verifyProof.ts b/packages/proof/src/verifyProof.ts index 6a43cc1e6..77dc784fd 100644 --- a/packages/proof/src/verifyProof.ts +++ b/packages/proof/src/verifyProof.ts @@ -1,8 +1,8 @@ -import { groth16 } from "snarkjs" import hash from "./hash" import { SemaphoreProof } from "./types" import unpackProof from "./unpackProof" import verificationKeys from "./verificationKeys.json" +import groth16Verify from "./groth16/verify" /** * Verifies a Semaphore proof. @@ -24,7 +24,7 @@ export default function verifyProof( IC: verificationKeys.IC[treeDepth - 16] } - return groth16.verify( + return groth16Verify( verificationKey, [merkleTreeRoot, nullifierHash, hash(signal), hash(externalNullifier)], unpackProof(proof) diff --git a/packages/proof/tsconfig.json b/packages/proof/tsconfig.json index dfaf0c1ad..28b175559 100644 --- a/packages/proof/tsconfig.json +++ b/packages/proof/tsconfig.json @@ -1,4 +1,7 @@ { "extends": "../../tsconfig.json", + "compilerOptions": { + "allowJs": true + }, "include": ["src", "rollup.config.ts"] } diff --git a/yarn.lock b/yarn.lock index 865dad819..9505693d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2812,13 +2812,6 @@ __metadata: languageName: node linkType: hard -"@iden3/bigarray@npm:0.0.2": - version: 0.0.2 - resolution: "@iden3/bigarray@npm:0.0.2" - checksum: a58a4aa75284f7c74ef8a43dd0720764e94389ae4314213f18de9d712fbdb170dd0e9b48672ad297b5f15bd1658d3bff33fe1998e189b48cbf501f1fe78f0adc - languageName: node - linkType: hard - "@iden3/binfileutils@npm:0.0.11": version: 0.0.11 resolution: "@iden3/binfileutils@npm:0.0.11" @@ -4234,21 +4227,6 @@ __metadata: languageName: node linkType: hard -"@rollup/plugin-replace@npm:^5.0.3": - version: 5.0.3 - resolution: "@rollup/plugin-replace@npm:5.0.3" - dependencies: - "@rollup/pluginutils": ^5.0.1 - magic-string: ^0.27.0 - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: 6cb1ba5ef9ac713840532ba0d1ddf70274fd10a74ac46d102508fbe1b84eb1a87c34019cff40c1ac96dbf43131e4e5d3a7873683a05299c44c0256d4a6f38a94 - languageName: node - linkType: hard - "@rollup/plugin-typescript@npm:^8.3.0": version: 8.5.0 resolution: "@rollup/plugin-typescript@npm:8.5.0" @@ -4621,19 +4599,20 @@ __metadata: "@ethersproject/bytes": ^5.7.0 "@ethersproject/keccak256": ^5.7.0 "@ethersproject/strings": ^5.5.0 + "@iden3/binfileutils": 0.0.11 "@rollup/plugin-commonjs": ^24.1.0 "@rollup/plugin-json": ^5.0.1 "@rollup/plugin-node-resolve": ^15.0.2 - "@rollup/plugin-replace": ^5.0.3 "@rollup/plugin-virtual": ^3.0.2 "@zk-kit/incremental-merkle-tree": 0.4.3 - ffjavascript: ^0.2.54 + circom_runtime: 0.1.24 + fastfile: 0.0.20 + ffjavascript: 0.2.60 poseidon-lite: ^0.2.0 rimraf: ^5.0.5 rollup: ^4.0.2 rollup-plugin-cleanup: ^3.2.1 rollup-plugin-typescript2: ^0.31.2 - snarkjs: 0.7.1 peerDependencies: "@semaphore-protocol/group": 3.12.3 "@semaphore-protocol/identity": 3.12.3 @@ -6662,19 +6641,6 @@ __metadata: languageName: node linkType: hard -"bfj@npm:^7.0.2": - version: 7.1.0 - resolution: "bfj@npm:7.1.0" - dependencies: - bluebird: ^3.7.2 - check-types: ^11.2.3 - hoopy: ^0.1.4 - jsonpath: ^1.1.1 - tryer: ^1.0.1 - checksum: 36da9ed36c60f377a3f43bb0433092af7dc40442914b8155a1330ae86b1905640baf57e9c195ab83b36d6518b27cf8ed880adff663aa444c193be149e027d722 - languageName: node - linkType: hard - "big.js@npm:^5.2.2": version: 5.2.2 resolution: "big.js@npm:5.2.2" @@ -6783,7 +6749,7 @@ __metadata: languageName: node linkType: hard -"bluebird@npm:^3.5.0, bluebird@npm:^3.7.2": +"bluebird@npm:^3.5.0": version: 3.7.2 resolution: "bluebird@npm:3.7.2" checksum: 869417503c722e7dc54ca46715f70e15f4d9c602a423a02c825570862d12935be59ed9c7ba34a9b31f186c017c23cac6b54e35446f8353059c101da73eac22ef @@ -7582,13 +7548,6 @@ __metadata: languageName: node linkType: hard -"check-types@npm:^11.2.3": - version: 11.2.3 - resolution: "check-types@npm:11.2.3" - checksum: f99ff09ae65e63cfcfa40a1275c0a70d8c43ffbf9ac35095f3bf030cc70361c92e075a9975a1144329e50b4fe4620be6bedb4568c18abc96071a3e23aed3ed8e - languageName: node - linkType: hard - "chokidar@npm:3.3.0": version: 3.3.0 resolution: "chokidar@npm:3.3.0" @@ -9418,25 +9377,6 @@ __metadata: languageName: node linkType: hard -"escodegen@npm:^1.8.1": - version: 1.14.3 - resolution: "escodegen@npm:1.14.3" - dependencies: - esprima: ^4.0.1 - estraverse: ^4.2.0 - esutils: ^2.0.2 - optionator: ^0.8.1 - source-map: ~0.6.1 - dependenciesMeta: - source-map: - optional: true - bin: - escodegen: bin/escodegen.js - esgenerate: bin/esgenerate.js - checksum: 381cdc4767ecdb221206bbbab021b467bbc2a6f5c9a99c9e6353040080bdd3dfe73d7604ad89a47aca6ea7d58bc635f6bd3fbc8da9a1998e9ddfa8372362ccd0 - languageName: node - linkType: hard - "escodegen@npm:^2.0.0": version: 2.0.0 resolution: "escodegen@npm:2.0.0" @@ -9649,16 +9589,6 @@ __metadata: languageName: node linkType: hard -"esprima@npm:1.2.2": - version: 1.2.2 - resolution: "esprima@npm:1.2.2" - bin: - esparse: ./bin/esparse.js - esvalidate: ./bin/esvalidate.js - checksum: 4f10006f0e315f2f7d8cf6630e465f183512f1ab2e862b11785a133ce37ed1696573deefb5256e510eaa4368342b13b393334477f6ccdcdb8f10e782b0f5e6dc - languageName: node - linkType: hard - "esprima@npm:2.7.x, esprima@npm:^2.7.1": version: 2.7.3 resolution: "esprima@npm:2.7.3" @@ -9704,7 +9634,7 @@ __metadata: languageName: node linkType: hard -"estraverse@npm:^4.1.1, estraverse@npm:^4.2.0": +"estraverse@npm:^4.1.1": version: 4.3.0 resolution: "estraverse@npm:4.3.0" checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 @@ -10282,7 +10212,7 @@ __metadata: languageName: node linkType: hard -"ffjavascript@npm:0.2.60, ffjavascript@npm:^0.2.45": +"ffjavascript@npm:0.2.60, ffjavascript@npm:^0.2.45, ffjavascript@npm:^0.2.48": version: 0.2.60 resolution: "ffjavascript@npm:0.2.60" dependencies: @@ -10293,17 +10223,6 @@ __metadata: languageName: node linkType: hard -"ffjavascript@npm:^0.2.48, ffjavascript@npm:^0.2.54": - version: 0.2.57 - resolution: "ffjavascript@npm:0.2.57" - dependencies: - wasmbuilder: 0.0.16 - wasmcurves: 0.2.0 - web-worker: ^1.2.0 - checksum: 8f3e87b3e2739c607dfc2ef8cb36d92202da57b1323987cca09ade378c584a946b9d784607ee5e2193a2de6200afdc254c19f72f79145aa55d9a8688f83f6708 - languageName: node - linkType: hard - "figlet@npm:^1.5.2": version: 1.5.2 resolution: "figlet@npm:1.5.2" @@ -11865,13 +11784,6 @@ __metadata: languageName: node linkType: hard -"hoopy@npm:^0.1.4": - version: 0.1.4 - resolution: "hoopy@npm:0.1.4" - checksum: cfa60c7684c5e1ee4efe26e167bc54b73f839ffb59d1d44a5c4bf891e26b4f5bcc666555219a98fec95508fea4eda3a79540c53c05cc79afc1f66f9a238f4d9e - languageName: node - linkType: hard - "hosted-git-info@npm:^2.1.4": version: 2.8.9 resolution: "hosted-git-info@npm:2.8.9" @@ -13685,17 +13597,6 @@ __metadata: languageName: node linkType: hard -"jsonpath@npm:^1.1.1": - version: 1.1.1 - resolution: "jsonpath@npm:1.1.1" - dependencies: - esprima: 1.2.2 - static-eval: 2.0.2 - underscore: 1.12.1 - checksum: 5480d8e9e424fe2ed4ade6860b6e2cefddb21adb3a99abe0254cd9428e8ef9b0c9fb5729d6a5a514e90df50d645ccea9f3be48d627570e6222dd5dadc28eba7b - languageName: node - linkType: hard - "jsonpointer@npm:^5.0.0": version: 5.0.1 resolution: "jsonpointer@npm:5.0.1" @@ -14067,13 +13968,6 @@ __metadata: languageName: node linkType: hard -"logplease@npm:^1.2.15": - version: 1.2.15 - resolution: "logplease@npm:1.2.15" - checksum: c2ac90a75dfa28234f67c79a112baf3c7d7a3011a6d16b052e299ad2f37430fd17959fa116629e14ef3b56796a2dd7015802d0a835ded107ceacb0ca5a44393f - languageName: node - linkType: hard - "longest@npm:^2.0.1": version: 2.0.1 resolution: "longest@npm:2.0.1" @@ -16731,18 +16625,6 @@ __metadata: languageName: node linkType: hard -"r1csfile@npm:0.0.47": - version: 0.0.47 - resolution: "r1csfile@npm:0.0.47" - dependencies: - "@iden3/bigarray": 0.0.2 - "@iden3/binfileutils": 0.0.11 - fastfile: 0.0.20 - ffjavascript: 0.2.60 - checksum: edeb325b83851a71cbca2e5de56eb622ee5347ecae921b526a5fc484c4825b6b30c73b6fde40e9bc5112b9d21e046af885bf212ed9cee2efbc6de93b8454ec06 - languageName: node - linkType: hard - "randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" @@ -18089,26 +17971,6 @@ __metadata: languageName: node linkType: hard -"snarkjs@npm:0.7.1": - version: 0.7.1 - resolution: "snarkjs@npm:0.7.1" - dependencies: - "@iden3/binfileutils": 0.0.11 - bfj: ^7.0.2 - blake2b-wasm: ^2.4.0 - circom_runtime: 0.1.24 - ejs: ^3.1.6 - fastfile: 0.0.20 - ffjavascript: 0.2.60 - js-sha3: ^0.8.0 - logplease: ^1.2.15 - r1csfile: 0.0.47 - bin: - snarkjs: build/cli.cjs - checksum: a6cf652962d8e53474fad8aecf884ebb11ddca707e237036e268266ca2760687398043bf47e66eb2bc627435e54c795863f4629ddae99311dbec27f3cdc9167f - languageName: node - linkType: hard - "socks-proxy-agent@npm:^7.0.0": version: 7.0.0 resolution: "socks-proxy-agent@npm:7.0.0" @@ -18456,15 +18318,6 @@ __metadata: languageName: node linkType: hard -"static-eval@npm:2.0.2": - version: 2.0.2 - resolution: "static-eval@npm:2.0.2" - dependencies: - escodegen: ^1.8.1 - checksum: 335a923c5ccb29add404ac23d0a55c0da6cee3071f6f67a7053aeac0dedc6dbfc53ac9269e9c25f403f5b7603a291ef47d7114f99bde241184f7aa3f9286dc32 - languageName: node - linkType: hard - "statuses@npm:2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" @@ -19259,13 +19112,6 @@ __metadata: languageName: node linkType: hard -"tryer@npm:^1.0.1": - version: 1.0.1 - resolution: "tryer@npm:1.0.1" - checksum: 1cf14d7f67c79613f054b569bfc9a89c7020d331573a812dfcf7437244e8f8e6eb6893b210cbd9cc217f67c1d72617f89793df231e4fe7d53634ed91cf3a89d1 - languageName: node - linkType: hard - "ts-command-line-args@npm:^2.2.0": version: 2.4.2 resolution: "ts-command-line-args@npm:2.4.2" @@ -19715,13 +19561,6 @@ __metadata: languageName: node linkType: hard -"underscore@npm:1.12.1": - version: 1.12.1 - resolution: "underscore@npm:1.12.1" - checksum: ec327603aa112b99fe9d74cd9bf3b3b7451465a9d2610ceab269a532e3f191650ab017903be34dc86fe406a11d04d8905a3b04dd4c129493e51bee09a3f3074c - languageName: node - linkType: hard - "undici@npm:^5.12.0": version: 5.21.0 resolution: "undici@npm:5.21.0" @@ -20148,15 +19987,6 @@ __metadata: languageName: node linkType: hard -"wasmcurves@npm:0.2.0": - version: 0.2.0 - resolution: "wasmcurves@npm:0.2.0" - dependencies: - wasmbuilder: 0.0.16 - checksum: 0769ca2d0c2f99619436f86dcab16294d94cc0c8a114b0c5e6ed71df49625a6ad35000011fee57471b7647838eeb75f631e74b200996ac2513e8ca0c47e5b8d0 - languageName: node - linkType: hard - "wasmcurves@npm:0.2.2": version: 0.2.2 resolution: "wasmcurves@npm:0.2.2"