circomkit
Version:
A Circom testing & development environment
256 lines (242 loc) • 12 kB
JavaScript
;
var require$$0 = require('commander');
var index = require('./index-BtEai0uC.cjs');
var fs = require('fs');
var child_process = require('child_process');
require('snarkjs');
require('circom_tester');
require('fs/promises');
require('crypto');
require('loglevel');
require('https');
require('node:assert');
require('node:path');
require('node:fs');
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var extraTypings = {exports: {}};
(function (module, exports) {
const commander = require$$0;
exports = module.exports = {};
// Return a different global program than commander,
// and don't also return it as default export.
exports.program = new commander.Command();
/**
* Expose classes. The FooT versions are just types, so return Commander original implementations!
*/
exports.Argument = commander.Argument;
exports.Command = commander.Command;
exports.CommanderError = commander.CommanderError;
exports.Help = commander.Help;
exports.InvalidArgumentError = commander.InvalidArgumentError;
exports.InvalidOptionArgumentError = commander.InvalidArgumentError; // Deprecated
exports.Option = commander.Option;
// In Commander, the create routines end up being aliases for the matching
// methods on the global program due to the (deprecated) legacy default export.
// Here we roll our own, the way Commander might in future.
exports.createCommand = (name) => new commander.Command(name);
exports.createOption = (flags, description) =>
new commander.Option(flags, description);
exports.createArgument = (name, description) =>
new commander.Argument(name, description);
} (extraTypings, extraTypings.exports));
var extraTypingsExports = extraTypings.exports;
var extraTypingsCommander = /*@__PURE__*/getDefaultExportFromCjs(extraTypingsExports);
// wrapper to provide named exports for ESM.
const {
program,
createCommand,
createArgument,
createOption,
CommanderError,
InvalidArgumentError,
InvalidOptionArgumentError, // deprecated old name
Command,
Argument,
Option,
Help,
} = extraTypingsCommander;
var __async$1 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
function teardown() {
return __async$1(this, null, function* () {
if (globalThis.curve_bn128) yield globalThis.curve_bn128.terminate();
});
}
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
const CONFIG_PATH = "./circomkit.json";
function cli(args) {
const circomkit = new index.Circomkit(fs.existsSync(CONFIG_PATH) ? JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8")) : {});
const circuit = new Command("compile").description("compile the circuit").argument("[pattern]", 'Circuit name or pattern (defaults to ".*" for all circuits)').action((pattern) => __async(this, null, function* () {
const circuits = circomkit.readCircuits();
const circuitNames = Object.keys(circuits);
if (!pattern) pattern = ".*";
const regex = new RegExp(`^${pattern}$`);
const matchingCircuits = circuitNames.filter((name) => regex.test(name));
if (matchingCircuits.length === 0) {
circomkit.log.info("No circuits found matching pattern:", pattern);
return;
}
for (const circuitName of matchingCircuits) {
circomkit.log.info(`Compiling ${circuitName}...`);
const path = yield circomkit.compile(circuitName);
circomkit.log.info(`Built at: ${path}`);
}
}));
const instantiate = new Command("instantiate").description("create the main component").argument("<circuit>", "Circuit name").action((circuit2) => __async(this, null, function* () {
const path = circomkit.instantiate(circuit2);
circomkit.log.info("Created at:", path);
}));
const info = new Command("info").description("print circuit information").argument("<circuit>", "Circuit name").action((circuit2) => __async(this, null, function* () {
const info2 = yield circomkit.info(circuit2);
console.log(`Prime Field: ${info2.primeName}`);
console.log(`Number of Wires: ${info2.wires}`);
console.log(`Number of Constraints: ${info2.constraints}`);
console.log(`Number of Private Inputs: ${info2.privateInputs}`);
console.log(`Number of Public Inputs: ${info2.publicInputs}`);
console.log(`Number of Public Outputs: ${info2.publicOutputs}`);
console.log(`Number of Labels: ${info2.labels}`);
}));
const clear = new Command("clear").description("clear circuit build artifacts").argument("<circuit>", "Circuit name").action((circuit2) => __async(this, null, function* () {
yield circomkit.clear(circuit2);
circomkit.log.info("Cleaned.");
}));
const init = new Command("init").description("initialize a new Circomkit project").argument("[dir]", "Directory").action((dir) => __async(this, null, function* () {
const cmd = `git clone https://github.com/erhant/circomkit-examples.git ${dir != null ? dir : "."}`;
circomkit.log.info(cmd);
const result = yield new Promise(
(resolve, reject) => child_process.exec(cmd, (error, stdout, stderr) => error ? reject(error) : resolve({ stdout, stderr }))
);
circomkit.log.info(result.stdout);
if (result.stderr) {
circomkit.log.info(result.stderr);
}
circomkit.log.info("Circomkit project initialized! \u2728");
}));
const json = new Command("json").description("export JSON files").addCommand(
new Command("r1cs").description("export r1cs").argument("<circuit>", "Circuit name").option("-p, --print", "Print JSON without saving it").action((circuit2, options) => __async(this, null, function* () {
const { json: json2, path } = yield circomkit.json("r1cs", circuit2);
if (options.print) {
console.log(index.prettyStringify(json2));
} else {
fs.writeFileSync(path, index.prettyStringify(json2));
circomkit.log.info("Exported R1CS at: " + path);
}
}))
).addCommand(
new Command("zkey").description("export prover key").argument("<circuit>", "Circuit name").option("-p, --print", "Print JSON without saving it").action((circuit2, options) => __async(this, null, function* () {
const { json: json2, path } = yield circomkit.json("zkey", circuit2);
if (options.print) {
console.log(index.prettyStringify(json2));
} else {
fs.writeFileSync(path, index.prettyStringify(json2));
circomkit.log.info("Exported prover key at: " + path);
}
}))
).addCommand(
new Command("wtns").description("export witness").argument("<circuit>", "Circuit name").argument("<input>", "Input name").option("-p, --print", "Print JSON without saving it").action((circuit2, input, options) => __async(this, null, function* () {
const { json: json2, path } = yield circomkit.json("wtns", circuit2, input);
if (options.print) {
console.log(index.prettyStringify(json2));
} else {
fs.writeFileSync(path, index.prettyStringify(json2));
circomkit.log.info("Exported witness at: " + path);
}
}))
);
const contract = new Command("contract").description("export Solidity verifier contract").argument("<circuit>", "Circuit name").action((circuit2) => __async(this, null, function* () {
const path = yield circomkit.contract(circuit2);
circomkit.log.info("Created at: " + path);
}));
const calldata = new Command("calldata").description("export calldata for a verifier contract").argument("<circuit>", "Circuit name").argument("<input>", "Input name").action((circuit2, input) => __async(this, null, function* () {
const calldata2 = yield circomkit.calldata(circuit2, input);
circomkit.log.info(calldata2);
}));
const vkey = new Command("vkey").description("extract verification key").argument("<circuit>", "Circuit name").argument("[pkeyPath]", "Prover key path").action((circuit2, pkeyPath) => __async(this, null, function* () {
const path = yield circomkit.vkey(circuit2, pkeyPath);
circomkit.log.info("Created at: " + path);
}));
const prove = new Command("prove").description("generate zk-proof").argument("<circuit>", "Circuit name").argument("<input>", "Input name").action((circuit2, input) => __async(this, null, function* () {
const path = yield circomkit.prove(circuit2, input);
circomkit.log.info("Generated at: " + path);
}));
const verify = new Command("verify").description("verify zk-proof").argument("<circuit>", "Circuit name").argument("<input>", "Input name").action((circuit2, input) => __async(this, null, function* () {
const ok = yield circomkit.verify(circuit2, input);
if (ok) {
circomkit.log.info("Verification successful.");
} else {
circomkit.log.info("Verification failed!");
}
}));
const witness = new Command("witness").description("compute witness").argument("<circuit>", "Circuit name").argument("<input>", "Input name").action((circuit2, input) => __async(this, null, function* () {
const path = yield circomkit.witness(circuit2, input);
circomkit.log.info("Witness created: " + path);
}));
const setup = new Command("setup").description("commence circuit-specific setup").argument("<circuit>", "Circuit name").argument("[ptauPath]", "Path to PTAU").action((circuit2, ptauPath) => __async(this, null, function* () {
const { proverKeyPath, verifierKeyPath } = yield circomkit.setup(circuit2, ptauPath);
circomkit.log.info("Prover key created: " + proverKeyPath);
circomkit.log.info("Verifier key created: " + verifierKeyPath);
}));
const ptau = new Command("ptau").description("download PTAU file").argument("<circuit>", "Circuit name").action((circuit2) => __async(this, null, function* () {
const path = yield circomkit.ptau(circuit2);
circomkit.log.info("PTAU ready at: " + path);
}));
const list = new Command("list").description("list circuits & instances").action(() => __async(this, null, function* () {
const templates = fs.readdirSync(circomkit.config.dirCircuits).filter((path) => path.endsWith(".circom")).map((path) => path.slice(0, -".circom".length));
circomkit.log.info(
`Template Files (${circomkit.config.dirCircuits}):
` + templates.map((c, i) => ` ${i + 1}. ${c}`).join("\n")
);
const circuits = circomkit.readCircuits();
circomkit.log.info(
`
Circuit Names (${circomkit.config.circuits}):
` + Object.keys(circuits).map((c, i) => ` ${i + 1}. ${c}`).join("\n")
);
}));
const config = new Command("config").description("print configuration").action(() => {
circomkit.log.info(circomkit.config);
});
new Command().name("circomkit").description("Circom testing & development toolkit").addCommand(init).addCommand(config).addCommand(list).addCommand(json).addCommand(circuit).addCommand(instantiate).addCommand(info).addCommand(clear).addCommand(contract).addCommand(vkey).addCommand(ptau).addCommand(setup).addCommand(prove).addCommand(witness).addCommand(verify).addCommand(calldata).hook("postAction", () => __async(this, null, function* () {
return yield teardown();
})).parse(args);
}
cli(process.argv);