Skip to content

Commit

Permalink
feat(generate-witness): generate witness file command
Browse files Browse the repository at this point in the history
n
  • Loading branch information
sleepyqadir committed Sep 22, 2022
1 parent 3eb1681 commit a4c33fb
Show file tree
Hide file tree
Showing 6 changed files with 602 additions and 1 deletion.
205 changes: 205 additions & 0 deletions src/commands/actions/calculateWitness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/* eslint-disable @typescript-eslint/prefer-for-of */
/* eslint-disable @typescript-eslint/no-unused-vars */
import chalk from "chalk";
import ora from "ora";
import { log } from "../../../utils/logger";
import { initFS } from "../../../utils/wasm";
import {
fileExists,
getEmptyDir,
getEmptyDirByPath,
} from "../../../utils/utils";
import { builder } from "../../../utils/witness";
import ufs from "@phated/unionfs";
import path from "path";
import { WrappedSnarkJs } from "../../../utils/snarkjs";

const { utils } = require("ffjavascript");

enum Protocol {
GROTH16 = "groth16",
PLONK = "plonk",
}

interface ICircuits {
name: string;
protocol?: Protocol;
circuit?: string;
zkey?: string;
witness?: string;
}
interface IUserConfig {
solidity?: string;
circom: {
inputBasePath?: string;
outputBasePath?: string;
ptau: string;
circuits: ICircuits[];
};
}

export const generateWitness = async (options: any) => {
console.log("generating witness");
try {
let userConfig: IUserConfig;
let circuits: ICircuits[];
const defaultConfig: IUserConfig = {
solidity: "^0.8.0",
circom: {
inputBasePath: "/circuits",
outputBasePath: "/build",
ptau: "",
circuits: [],
},
};

try {
userConfig = require(`${process.cwd()}/shield.config.js`);
circuits = userConfig.circom.circuits;
if (options.circuit) {
circuits = circuits.filter((circuit) => {
return circuit.name === options.circuit;
});
}

if (!userConfig.circom) {
log(
"unable to locate circom user defined config in file shield.config.js.",
"error"
);
process.exit(1);
} else if (!userConfig.circom.ptau) {
log(
"please define the ptau file name in file shield.config.js.",
"error"
);
process.exit(1);
} else if (!circuits.length) {
log(
"please define the circuit details for compilation of circuits in file shield.config.js.",
"error"
);
process.exit(1);
} else {
for (let i = 0; i < circuits.length; i++) {
if (!circuits[i].name) {
log(
"please define the circuit name for compilation of the circuit in file shield.config.js.",
"error"
);
process.exit(1);
}
if (!circuits[i].protocol) {
circuits[i].protocol = Protocol.GROTH16;
}
if (!circuits[i].zkey) {
circuits[i].zkey = circuits[i].name;
}
if (!circuits[i].circuit) {
circuits[i].circuit = `${circuits[i].name}.circom`;
}
}
}
} catch (e) {
log("unable to locate shield config file.", "error");
process.exit(1);
}

const finalConfig: IUserConfig = {
solidity: userConfig.solidity
? userConfig.solidity
: defaultConfig.solidity,
circom: {
inputBasePath: userConfig.circom.inputBasePath
? userConfig.circom.inputBasePath
: defaultConfig.circom.inputBasePath,
outputBasePath: userConfig.circom.outputBasePath
? userConfig.circom.outputBasePath
: defaultConfig.circom.outputBasePath,
ptau: userConfig.circom.ptau,
circuits,
},
};

const wasmFs = await initFS();

const outputBasePath = `${process.cwd()}${
finalConfig.circom.outputBasePath as string
}`;

for (let i = 0; i < finalConfig.circom.circuits.length; i++) {
const circuitName = finalConfig.circom.circuits[i].name;

const circuitPath = `${process.cwd()}${
finalConfig.circom.inputBasePath as string
}/${finalConfig.circom.circuits[i].circuit as string}`;

const wtnsFilePath = `${process.cwd()}${
finalConfig.circom.inputBasePath as string
}/witness.wtns`;

const wasmPath = `${outputBasePath}/${circuitName}/${circuitName}_js/${circuitName}.wasm`;

const inputFilePath = `${process.cwd()}${
finalConfig.circom.inputBasePath as string
}/${finalConfig.circom.circuits[i].witness as string}`;

console.log({ inputFilePath });

if (await fileExists(inputFilePath)) {
const spinner = ora(
chalk.greenBright(`Compiling ${circuitName}\n`)
).start();

const wasmData = ufs.readFileSync(wasmPath);

let logs;

try {
const witness = await builder(wasmData, {
log(message: any, label: string) {
if (label) {
console.log("labellllllssss =============>", {
label,
message,
});
logs.push(label + ": " + message.toString());
} else {
console.log("labellllllssss =============>", {
label,
message,
});
logs.push(message.toString());
}
},
});

const inputFileData = await wasmFs.readFileSync(
inputFilePath,
"utf8"
);

const input = utils.unstringifyBigInts(JSON.parse(inputFileData));

const wtnsFile = await witness.calculateWTNSBin(input, true);

await WrappedSnarkJs.util.generateWtns(wtnsFilePath, wasmPath, input);

spinner.succeed(
chalk.greenBright(`${circuitName} succesfully compiled.`)
);
} catch (err) {
console.log("error in generate witness", err);
}
} else {
log(
`unable to locate ${finalConfig.circom.circuits[i].witness} at dir ${inputFilePath} user defined config in file shield.config.js.`,
"error"
);
}
}
process.exit(0);
} catch (e: any) {
log(e.message, "error");
}
};
1 change: 1 addition & 0 deletions src/commands/actions/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ export const compile = async (options: any) => {
const circuitPath = `${process.cwd()}${
finalConfig.circom.inputBasePath as string
}/${finalConfig.circom.circuits[i].circuit as string}`;

const ptauPath = `${outputBasePath}/${finalConfig.circom.ptau}`;
const r1csPath = `${outputBasePath}/${circuitName}/${circuitName}.r1cs`;
const zKeyPath = {
Expand Down
7 changes: 7 additions & 0 deletions src/commands/list/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { compile, init } from "../actions";
import { generateWitness } from "../actions/calculateWitness";

interface Icommands {
name: string;
Expand All @@ -19,4 +20,10 @@ export const commands: Icommands[] = [
option: ["-c, --circuit <value>", "specific circuit to compile"],
action: compile,
},
{
name: "calculatewitness",
description: "claculte the witness",
option: ["-c, --circuit <value>", "specific circuit to compile"],
action: generateWitness,
},
];
2 changes: 2 additions & 0 deletions templates/config/shield.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ module.exports = {
circuit: "demo.circom",
// (required) Output path for zkey file, inferred from `name` if unspecified
zkey: "demo.zkey",
// (optional) Input path for input signal data, inferred from `name` if unspecified
witness: "input.json",
},
],
},
Expand Down
36 changes: 35 additions & 1 deletion utils/snarkjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import shelljs from "shelljs";
import fsExtra from "fs-extra";
import { fileExists } from "./utils";
import { log } from "./logger";
const { zKey, plonk } = require("snarkjs");
const { zKey, plonk, wtns } = require("snarkjs");
const { stringifyBigInts } = utils;

export const WrappedSnarkJs = {
Expand Down Expand Up @@ -139,5 +139,39 @@ export const WrappedSnarkJs = {
throw error;
}
},
generateWtns: async (wtnsPath: string, wasmPath: string, input: any) => {
try {
await wtns.calculate(input, wasmPath, wtnsPath, defaultWitnessOption());
const wtnsData = await wtns.exportJson(wtnsPath);
await bfj.write(
wtnsPath.replace(".wtns", ".json"),
stringifyBigInts(wtnsData),
{ space: 1 }
);
if (wtnsData) {
log(
`\n✓ Successfully generated the verification key file\n`,
"success"
);
}
} catch (error) {
log(`${error}`, "error");
throw error;
}
},
},
};

function defaultWitnessOption() {
let logFn = console.log;
let calculateWitnessOptions = {
sanityCheck: true,
logTrigger: logFn,
logOutput: logFn,
logStartComponent: logFn,
logFinishComponent: logFn,
logSetSignal: logFn,
logGetSignal: logFn,
};
return calculateWitnessOptions;
}
Loading

0 comments on commit a4c33fb

Please sign in to comment.