UNPKG

@unirep/circuits

Version:

Client library for circuit related functions which are used in UniRep protocol.

149 lines (148 loc) 6.19 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebProver = void 0; // import { version } from '../package.json' const version = '2.0.0'; // trusted setup version const KEY_URL = `https://keys.unirep.io/${version}/`; /** * The circuits package includes a browser compatible prover. This prover loads the proving keys from a remote URL. * By default this url is https://keys.unirep.io/${version}/. * * The server is expected to serve the `zkey`, `wasm`, and `vkey` files at their respective names in the provided subpath. * e.g. for the above url the signup zkey is at https://keys.unirep.io/${version}/signup.zkey`. * @param serverUrl The server url to the `zkey`, `wasm`, and `vkey` files. * Default: `https://keys.unirep.io/${version}/` * * @note * :::caution * The keys included are not safe for production use. A phase 2 trusted setup needs to be done before use. * ::: * * @example * **Default key server** * ```ts * import { Circuit } from '@unirep/circuits' * import prover from '@unirep/circuits/provers/web' * * await prover.genProofAndPublicSignals(Circuit.signup, { * // circuit inputs * }) * ``` * * **Custom key server** * ```ts * import { Circuit } from '@unirep/circuits' * import { WebProver } from '@unirep/circuits/provers/web' * * // For a local key server * const prover = new WebProver('http://localhost:8000/keys/') * await prover.genProofAndPublicSignals(Circuit.signup, { * // circuit inputs * }) * ``` * */ class WebProver { constructor(serverUrl = KEY_URL) { this.cache = {}; this.url = serverUrl.endsWith('/') ? serverUrl : `${serverUrl}/`; } /** * Get key object from the server. * @param circuitUrl The url to the a `vkey`, a `zkey`s or a `wasm`. * @returns The `vkey`, the `zkey`s or the `wasm` object. */ async getKey(circuitUrl) { if (this.cache[circuitUrl]) return this.cache[circuitUrl]; const res = fetch(circuitUrl).then((r) => r.arrayBuffer()); this.cache[circuitUrl] = res; return res; } /** * Load proving keys for a circuit into memory. Future proofs using these keys will not need to wait for download. * :::tip * Use this function without `await` to start the download in the background. * ::: * @param circuitName Name of the circuit, which can be chosen from `Circuit` * @example * ```ts * await webProver.warmKeys(circuitName: string) * ``` */ async warmKeys(circuitName) { const wasmUrl = new URL(`${circuitName}.wasm`, this.url).toString(); const zkeyUrl = new URL(`${circuitName}.zkey`, this.url).toString(); await Promise.all([this.getKey(wasmUrl), this.getKey(zkeyUrl)]); } /** * The function returns true if the proof of the circuit is valid, false otherwise. * @param circuitName Name of the circuit, which can be chosen from `Circuit` * @param publicSignals The snark public signals that are generated from `genProofAndPublicSignals` * @param proof The snark proof that is generated from `genProofAndPublicSignals` * @returns True if the proof is valid, false otherwise */ async verifyProof(circuitName, publicSignals, proof) { const _snarkjs = Promise.resolve().then(() => __importStar(require('snarkjs'))); const url = new URL(`${circuitName}.vkey.json`, this.url).toString(); const vkeyBuffer = await this.getKey(url); const vkeyString = String.fromCharCode.apply(null, new Uint8Array(vkeyBuffer)); const vkey = JSON.parse(vkeyString); const snarkjs = await _snarkjs; return snarkjs.groth16.verify(vkey, publicSignals, proof); } /** * Generate proof and public signals with `snarkjs.groth16.fullProve` * @param circuitName * @param inputs Name of the circuit, which can be chosen from `Circuit` * @returns Snark proof and public signals */ async genProofAndPublicSignals(circuitName, inputs) { const _snarkjs = Promise.resolve().then(() => __importStar(require('snarkjs'))); const wasmUrl = new URL(`${circuitName}.wasm`, this.url).toString(); const zkeyUrl = new URL(`${circuitName}.zkey`, this.url).toString(); const [wasm, zkey] = await Promise.all([ this.getKey(wasmUrl), this.getKey(zkeyUrl), ]); const snarkjs = await _snarkjs; const { proof, publicSignals } = await snarkjs.groth16.fullProve(inputs, new Uint8Array(wasm), new Uint8Array(zkey)); return { proof, publicSignals }; } /** * Get vkey from a remote URL. * @param circuitName Name of the circuit, which can be chosen from `Circuit` * @returns vkey of the circuit */ async getVKey(circuitName) { const url = new URL(`${circuitName}.vkey.json`, this.url).toString(); const vkeyBuffer = await this.getKey(url); const vkeyString = String.fromCharCode.apply(null, new Uint8Array(vkeyBuffer)); return JSON.parse(vkeyString); } } exports.WebProver = WebProver; exports.default = new WebProver();