@nori-zk/proof-conversion
Version:
Verifying zkVM proofs inside o1js circuits, to generate Mina compatible proof
134 lines • 5 kB
JavaScript
import { Command } from 'commander';
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { ComputationalPlanExecutor } from '../compute/executor.js';
import { performSp1ToPlonk } from '../api/sp1/plonk.js';
import { Logger } from '../logging/logger.js';
import { LogPrinter } from '../logging/log_printer.js';
import { performRisc0ToGroth16 } from '../api/sp1/groth16.js';
new LogPrinter('[NoriProofConverter]', [
'log',
'info',
'warn',
'error',
'debug',
'fatal',
'verbose',
]);
const logger = new Logger('CLI');
// Define max processes
const MAX_PROCESSES = parseInt(process.env.MAX_PROCESSES || '1');
const executor = new ComputationalPlanExecutor(MAX_PROCESSES);
// Command map where key is command name, value is async function
const commandMap = {
sp1ToPlonk: (fileData) => performSp1ToPlonk(executor, fileData),
risc0ToGroth16: ({ fileData1, fileData2 }) => performRisc0ToGroth16(executor, fileData1, fileData2),
};
// Get the current file's directory (ESM equivalent of __dirname)
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Resolve package.json dynamically
const packageJsonPath = path.resolve(__dirname, '..', '..', '..', 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
const version = packageJson.version;
// Utility to write output file with json extension
function writeJsonFile(filePath, commandName, resultStr) {
let dir = path.dirname(filePath);
let base = path.basename(filePath);
// Case-insensitive check for .json extension
if (base.toLowerCase().endsWith('.json')) {
base = base.slice(0, -5); // Remove .json extension
}
let newFilePath = path.join(dir, `${base}.${commandName}.json`);
fs.writeFileSync(newFilePath, resultStr);
return newFilePath;
}
const program = new Command();
// Set metadata for the CLI
program
.name(Object.keys(packageJson.bin)[0])
.description(packageJson.description)
.version(packageJson.version);
// Define the main command
program
.argument('<command>', 'command to execute (e.g. sp1ToPlonk)')
.argument('<arg1>', 'first argument')
.argument('[arg2]', 'second optional argument')
.action((commandName, arg1, arg2) => {
logger.log(`Command '${commandName}' received with arg1 '${arg1}', arg2 '${arg2}'`);
const commandFunction = commandMap[commandName];
if (!commandFunction) {
logger.fatal(`Command '${commandName}' not found.`);
logger.fatal(`Available commands: ${Object.keys(commandMap).join(', ')}`);
process.exit(1);
}
let args;
try {
if (commandName === 'risc0ToGroth16') {
args = {
fileData1: JSON.parse(fs.readFileSync(arg1, 'utf8')),
fileData2: JSON.parse(fs.readFileSync(arg2, 'utf8')),
};
}
else {
args = JSON.parse(fs.readFileSync(arg1, 'utf8'));
}
}
catch (err) {
logger.fatal(`Error processing arguments: ${err}`);
process.exit(1);
}
commandFunction(args)
.then((result) => {
const resultStr = JSON.stringify(result, null, 2);
const outputFilePath = writeJsonFile(arg1, commandName, resultStr);
logger.log(`Wrote result of command ${commandName} to disk: ${outputFilePath}`);
})
.catch((err) => {
logger.fatal(`Error executing command: ${err}`);
process.exit(1);
});
});
// Add a basic check for arguments and show help if needed
if (process.argv.length <= 2) {
console.log(program.helpInformation()); // Directly output help without triggering exit
console.log(`Version: ${version}`);
console.log(`Available commands: ${Object.keys(commandMap).join(', ')}`);
process.exit(0);
}
else {
try {
// Configure exit override to handle errors without recursion
program.exitOverride((err) => {
console.log(program.helpInformation()); // Output help text directly
console.log(`Version: ${version}`);
console.log(`Available commands: ${Object.keys(commandMap).join(', ')}`);
logger.fatal(err);
process.exit(1);
});
// Parse the command line arguments
program.parse(process.argv);
}
catch (err) {
console.log(program.helpInformation());
console.log(`Version: ${version}`);
console.log(`Available commands: ${Object.keys(commandMap).join(', ')}`);
logger.fatal(err);
process.exit(1);
}
}
// Handle Ctrl+C (SIGINT)
process.on('SIGINT', async () => {
try {
logger.warn('Process interrupted by user. Cleaning up.');
await executor.terminate();
logger.fatal('Cleanup finished. Exiting now.');
process.exit(0);
}
finally {
logger.fatal('Cleanup failed. Exiting now.');
process.exit(1);
}
});
//# sourceMappingURL=cli.js.map