diff --git a/package-lock.json b/package-lock.json index 9a176f6..163b35d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@solarity/zkit", - "version": "0.2.3", + "version": "0.2.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@solarity/zkit", - "version": "0.2.3", + "version": "0.2.4", "license": "MIT", "dependencies": { "ejs": "3.1.10", diff --git a/package.json b/package.json index 9ed24f2..b247fa7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@solarity/zkit", - "version": "0.2.3", + "version": "0.2.4", "license": "MIT", "author": "Distributed Lab", "readme": "README.md", diff --git a/src/core/CircuitZKit.ts b/src/core/CircuitZKit.ts index a8736d6..f85bce5 100644 --- a/src/core/CircuitZKit.ts +++ b/src/core/CircuitZKit.ts @@ -1,5 +1,6 @@ import ejs from "ejs"; import fs from "fs"; +import * as os from "os"; import path from "path"; import * as snarkjs from "snarkjs"; @@ -7,7 +8,7 @@ import { ArtifactsFileType, Calldata, CircuitZKitConfig, - Inputs, + Signals, ProofStruct, VerifierTemplateType, } from "../types/circuit-zkit"; @@ -54,16 +55,37 @@ export class CircuitZKit { fs.writeFileSync(verifierFilePath, verifierCode, "utf-8"); } + /** + * Calculates a witness for the given inputs. + * + * @param {Signals} inputs - The inputs for the circuit. + * @returns {Promise} The generated witness. + */ + public async calculateWitness(inputs: Signals): Promise { + const tmpDir = path.join(os.tmpdir(), ".zkit"); + + if (!fs.existsSync(tmpDir)) { + fs.mkdirSync(tmpDir, { recursive: true }); + } + + const wtnsFile = path.join(tmpDir, `${this.getCircuitName()}.wtns`); + const wasmFile = this.mustGetArtifactsFilePath("wasm"); + + await snarkjs.wtns.calculate(inputs, wasmFile, wtnsFile); + + return (await snarkjs.wtns.exportJson(wtnsFile)) as bigint[]; + } + /** * Generates a proof for the given inputs. * * @dev The `inputs` should be in the same order as the circuit expects them. * - * @param {Inputs} inputs - The inputs for the circuit. + * @param {Signals} inputs - The inputs for the circuit. * @returns {Promise} The generated proof. * @todo Add support for other proving systems. */ - public async generateProof(inputs: Inputs): Promise { + public async generateProof(inputs: Signals): Promise { const zKeyFile = this.mustGetArtifactsFilePath("zkey"); const wasmFile = this.mustGetArtifactsFilePath("wasm"); diff --git a/src/types/circuit-zkit.ts b/src/types/circuit-zkit.ts index 882e6e6..c99a629 100644 --- a/src/types/circuit-zkit.ts +++ b/src/types/circuit-zkit.ts @@ -22,11 +22,10 @@ export type ProofStruct = { publicSignals: PublicSignals; }; -export type NumberLike = number | bigint | string; +export type NumberLike = number | bigint | `${number}`; export type ArrayLike = NumberLike[] | ArrayLike[]; -export type InputLike = NumberLike | ArrayLike; - -export type Inputs = Record; +export type Signal = NumberLike | ArrayLike; +export type Signals = Record; export type ArtifactsFileType = "r1cs" | "zkey" | "vkey" | "sym" | "json" | "wasm"; export type VerifierTemplateType = "groth16"; diff --git a/test/CircuitZKit.test.ts b/test/CircuitZKit.test.ts index 6c60b38..70dfa6d 100644 --- a/test/CircuitZKit.test.ts +++ b/test/CircuitZKit.test.ts @@ -1,6 +1,7 @@ import ejs from "ejs"; -import path from "path"; import fs from "fs"; +import * as os from "os"; +import path from "path"; import { expect } from "chai"; import { useFixtureProject } from "./helpers"; @@ -177,6 +178,32 @@ describe("CircuitZKit", () => { }); }); + describe("calculateWitness", () => { + useFixtureProject("simple-circuits"); + + it("should correctly create witness", async () => { + const circuitName = "Multiplier"; + const circuitArtifactsPath = getArtifactsFullPath(`${circuitName}.circom`); + + const multiplierCircuit: CircuitZKit = new CircuitZKit({ + circuitName, + circuitArtifactsPath, + verifierDirPath: getVerifiersDirFullPath(), + }); + + const b = 10, + a = 20; + + const tmpDir = path.join(os.tmpdir(), ".zkit"); + + fs.rmSync(tmpDir, { force: true, recursive: true }); + + expect(await multiplierCircuit.calculateWitness({ a, b })).to.deep.eq([1n, 200n, 20n, 10n]); + expect(await multiplierCircuit.calculateWitness({ a, b })).to.deep.eq([1n, 200n, 20n, 10n]); + expect(await multiplierCircuit.calculateWitness({ a, b: 30 })).to.deep.eq([1n, 600n, 20n, 30n]); + }); + }); + describe("generateProof/verifyProof", () => { useFixtureProject("simple-circuits");