UNPKG

@nori-zk/proof-conversion

Version:

Verifying zkVM proofs inside o1js circuits, to generate Mina compatible proof

163 lines 7.23 kB
import { resolve } from 'path'; import { computeAuxWitness } from '../../../pairing-utils/index.js'; import { makeAlphaBeta } from '../../../pairing-utils/index.js'; import { createDirectories, createDirectory, } from '../../../utils/cache.js'; import { getRandomString } from '../../../utils/random.js'; import { range } from '../../../utils/range.js'; import rootDir from '../../../utils/root_dir.js'; import { readFileSync, rmSync, writeFileSync } from 'fs'; import { Groth16Verifier } from '../../../groth/verifier.js'; import { Proof } from '../../../groth/proof.js'; const proofVkCacheStructure = { proofs: range(5).map((i) => `layer${i}`), vks: range(5).map((i) => `layer${i}`), }; const nodeCacheStructure = range(4).map((i) => `node${i}`); export class Groth16ComputationalPlan { constructor() { this.name = 'Groth16Converter'; this.stages = [ { // Create the cache and working directories // Create the proofs and vks directories // Create the node directories name: 'CreateFileSystemCache', type: 'main-thread', execute: (state) => { createDirectory(state.cacheDir); createDirectory(state.workingDir); createDirectories(state.workingDir, proofVkCacheStructure); createDirectories(state.workingDir, nodeCacheStructure); }, }, { name: 'makeAlphaBeta', type: 'main-thread', execute: (state) => { const raw_vk = state.input.raw_vk; const input = { alpha: { x: raw_vk.alpha.x, y: raw_vk.alpha.y, }, beta: { x_c0: raw_vk.beta.x_c0, x_c1: raw_vk.beta.x_c1, y_c0: raw_vk.beta.y_c0, y_c1: raw_vk.beta.y_c1, }, }; const risc0_vk = makeAlphaBeta(raw_vk, input); writeFileSync(resolve(state.workingDir, 'risc_zero_vk.json'), JSON.stringify(risc0_vk)); writeFileSync(resolve(state.workingDir, 'risc_zero_proof.json'), JSON.stringify(state.input.risc0_proof)); state.vkPath = resolve(state.workingDir, 'risc_zero_vk.json'); state.proofPath = resolve(state.workingDir, 'risc_zero_proof.json'); }, }, { name: 'GenerateWitness', type: 'main-thread', execute: (state) => { // args = [vk_path, proof_path, mlo_write_path] const vk_path = state.vkPath; const proof_path = state.proofPath; const groth16 = new Groth16Verifier(vk_path); const proof = Proof.parse(groth16.vk, proof_path); const mlo = groth16.multiMillerLoop(proof).toJSON(); const witness = computeAuxWitness(JSON.parse(mlo)); state.witnessPath = resolve(state.workingDir, 'aux_wtns.json'); // Write the mlo and witness to the cache dir writeFileSync(resolve(state.workingDir, 'mlo.json'), mlo); writeFileSync(state.witnessPath, JSON.stringify(witness)); return; }, }, { name: 'CompileRecursion', type: 'serial-cmd', processCmd: (state) => { return { cmd: 'node', args: [ '--max-old-space-size=6000', resolve(rootDir, 'build', 'src', 'compile_recursion_vks.js'), state.workingDir, state.cacheDir, ], capture: true, printableArgs: [0, 1, 2], }; }, }, { name: 'ComputeZKP', type: 'parallel-cmd', processCmds: (state) => { process.env.GROTH16_VK_PATH = state.vkPath; return range(16).map((i) => { return { cmd: 'node', args: [ '--max-old-space-size=6000', resolve(rootDir, 'build', 'src', 'groth', 'recursion', 'prove_zkps.js'), `zkp${i}`, state.proofPath, state.witnessPath, state.workingDir, state.cacheDir, ], capture: true, printableArgs: [0, 1, 2], }; }); }, numaOptimized: true, }, ...range(1, 5).map((i) => { const stage = { name: `CompressLayer${i}`, type: 'parallel-cmd', processCmds: (state) => { const upperLimit = Math.pow(2, 4 - i) - 1; return range(upperLimit + 1).map((ZKP_J) => { return { cmd: 'node', args: [ '--max-old-space-size=6000', resolve(rootDir, 'build', 'src', 'node_resolver.js'), '16', `${i}`, `${ZKP_J}`, state.workingDir, state.cacheDir, ], capture: true, printableArgs: [0, 1, 2, 3, 4], }; }); }, numaOptimized: true, }; return stage; }), ]; } async init(state, input) { state.input = input; state.workingDirName = getRandomString(20); const pwd = process.cwd(); state.workingDir = resolve(pwd, '.conversion-cache', state.workingDirName); state.cacheDir = resolve(pwd, '.conversion-cache', 'groth16_cache'); } async then(state) { const output = { vkData: JSON.parse(readFileSync(resolve(state.workingDir, 'vks', 'nodeVk.json'), 'utf8')), proofData: JSON.parse(readFileSync(resolve(state.workingDir, 'proofs', 'layer4', 'p0.json'), 'utf8')), }; return output; } async finally(state) { rmSync(state.workingDir, { recursive: true, force: true }); } } //# sourceMappingURL=index.js.map