@nori-zk/proof-conversion
Version:
Verifying zkVM proofs inside o1js circuits, to generate Mina compatible proof
100 lines • 3.34 kB
JavaScript
import { G1Affine, G2Affine } from '../ec/index.js';
import fs from 'fs';
import { ATE_LOOP_COUNT, Fp2, FpC, FrC } from '../towers/index.js';
import { Provable, Struct } from 'o1js';
import { G2Line, computeLineCoeffs } from '../lines/index.js';
import { computePI } from './compute_pi.js';
const getNumOfLines = () => {
let cnt = 0;
for (let i = 1; i < ATE_LOOP_COUNT.length; i++) {
cnt += 1;
if (ATE_LOOP_COUNT[i] !== 0)
cnt += 1;
}
// add two more for frobenius
return cnt + 2;
};
// Cache for dynamically created Proof classes
const proofClassCache = new Map();
function createProofClass(inputCount) {
if (inputCount < 0 || inputCount > 6) {
throw new Error(`Unsupported input count: ${inputCount}. Supported range: 0-6`);
}
const cached = proofClassCache.get(inputCount);
if (cached !== undefined) {
return cached;
}
const ProofClass = class extends Struct({
negA: G1Affine,
B: G2Affine,
C: G1Affine,
PI: G1Affine,
b_lines: Provable.Array(G2Line, getNumOfLines()),
pis: Provable.Array(FrC.provable, inputCount),
}) {
static parse(vk, path) {
const json = JSON.parse(fs.readFileSync(path, 'utf-8'));
// Get public inputs (pi1, pi2, etc).
const publicInputs = [];
for (let i = 1; i <= inputCount; i++) {
const key = `pi${i}`;
const val = json[key];
if (val) {
publicInputs.push(FrC.from(val));
}
}
const negA = new G1Affine({
x: FpC.from(json.negA.x),
y: FpC.from(json.negA.y),
});
const C = new G1Affine({
x: FpC.from(json.C.x),
y: FpC.from(json.C.y),
});
const B = new G2Affine({
x: new Fp2({
c0: FpC.from(json.B.x_c0),
c1: FpC.from(json.B.x_c1),
}),
y: new Fp2({
c0: FpC.from(json.B.y_c0),
c1: FpC.from(json.B.y_c1),
}),
});
// FIXME CHECK THIS VS RUST
const piBn = computePI(vk, publicInputs);
const PI = new G1Affine({
x: FpC.from(piBn.x).assertCanonical(),
y: FpC.from(piBn.y).assertCanonical(),
});
return new ProofClass({
negA,
B,
C,
PI,
b_lines: computeLineCoeffs(B),
pis: publicInputs,
});
}
};
proofClassCache.set(inputCount, ProofClass);
return ProofClass;
}
export function detectInputCountFromProof(path) {
const json = JSON.parse(fs.readFileSync(path, 'utf-8'));
let count = 0;
for (let i = 1; i <= 6; i++) {
if (json[`pi${i}`])
count++;
}
return count;
}
export function parseProof(vk, path) {
const inputCount = detectInputCountFromProof(path);
const ProofClass = createProofClass(inputCount);
return ProofClass.parse(vk, path);
}
// Legacy Proof for backward compatibility (fixed 5 inputs)
const Proof = createProofClass(5);
export { Proof };
//# sourceMappingURL=proof.js.map