@nori-zk/proof-conversion
Version:
Verifying zkVM proofs inside o1js circuits, to generate Mina compatible proof
102 lines • 5.14 kB
JavaScript
import { ZkProgram, Field, Poseidon, Provable } from 'o1js';
import { Accumulator } from './data.js';
import { Fp12 } from '../../towers/fp12.js';
import { ATE_LOOP_COUNT } from '../../towers/consts.js';
import { ArrayListHasher } from '../../array_list_hasher.js';
import { AffineCache } from '../../lines/precompute.js';
import { VK } from '../vk_from_env.js';
import { G2Line } from '../../lines/index.js';
import { LineParser } from '../../line_parser.js';
const BEGIN = ATE_LOOP_COUNT.length - 6;
const END = ATE_LOOP_COUNT.length;
const delta_lines = LineParser.parse(BEGIN, END, VK.delta_lines);
const gamma_lines = LineParser.parse(BEGIN, END, VK.gamma_lines);
const zkp6 = ZkProgram({
name: 'zkp6',
publicInput: Field,
publicOutput: Field,
methods: {
compute: {
privateInputs: [
Accumulator,
Provable.Array(Field, ATE_LOOP_COUNT.length),
Provable.Array(G2Line, 91),
],
async method(input, acc, lines_hashes, all_b_lines) {
input.assertEquals(Poseidon.hashPacked(Accumulator, acc));
acc.state.g_digest.assertEquals(ArrayListHasher.hash(lines_hashes));
const a_cache = new AffineCache(acc.proof.negA);
const c_cache = new AffineCache(acc.proof.C);
const pi_cache = new AffineCache(acc.proof.PI);
let T = acc.state.T;
const negB = acc.proof.B.neg();
const b_lines = LineParser.parse(BEGIN, END, all_b_lines);
let idx = 0;
let line_cnt = 0;
let g;
for (let i = BEGIN; i < END; i++) {
idx = i - 1;
const b_line = b_lines[line_cnt];
const delta_line = delta_lines[line_cnt];
const gamma_line = gamma_lines[line_cnt];
line_cnt += 1;
b_line.assert_is_tangent(T);
g = b_line.psi(a_cache);
g = g.sparse_mul(delta_line.psi(c_cache));
g = g.sparse_mul(gamma_line.psi(pi_cache));
T = T.double_from_line(b_line.lambda);
if (ATE_LOOP_COUNT[i] == 1 || ATE_LOOP_COUNT[i] == -1) {
const b_line = b_lines[line_cnt];
const delta_line = delta_lines[line_cnt];
const gamma_line = gamma_lines[line_cnt];
line_cnt += 1;
if (ATE_LOOP_COUNT[i] == 1) {
b_line.assert_is_line(T, acc.proof.B);
T = T.add_from_line(b_line.lambda, acc.proof.B);
}
else {
b_line.assert_is_line(T, negB);
T = T.add_from_line(b_line.lambda, negB);
}
g = g.sparse_mul(b_line.psi(a_cache));
g = g.sparse_mul(delta_line.psi(c_cache));
g = g.sparse_mul(gamma_line.psi(pi_cache));
}
lines_hashes[idx] = Poseidon.hashPacked(Fp12, g);
}
// frobenius part:
let frob_line_cnt = 0;
const frob_b_lines = LineParser.frobenius_lines(all_b_lines);
const frob_delta_lines = LineParser.frobenius_lines(VK.delta_lines);
const frob_gamma_lines = LineParser.frobenius_lines(VK.gamma_lines);
let b_line = frob_b_lines[frob_line_cnt];
let delta_line = frob_delta_lines[frob_line_cnt];
let gamma_line = frob_gamma_lines[frob_line_cnt];
frob_line_cnt += 1;
g = b_line.psi(a_cache);
g = g.sparse_mul(delta_line.psi(c_cache));
g = g.sparse_mul(gamma_line.psi(pi_cache));
const piB = acc.proof.B.frobenius();
b_line.assert_is_line(T, piB);
T = T.add_from_line(b_line.lambda, piB);
b_line = frob_b_lines[frob_line_cnt];
delta_line = frob_delta_lines[frob_line_cnt];
gamma_line = frob_gamma_lines[frob_line_cnt];
let pi_2_B = piB.negative_frobenius();
b_line.assert_is_line(T, pi_2_B);
g = g.sparse_mul(b_line.psi(a_cache));
g = g.sparse_mul(delta_line.psi(c_cache));
g = g.sparse_mul(gamma_line.psi(pi_cache));
lines_hashes[ATE_LOOP_COUNT.length - 1] = Poseidon.hashPacked(Fp12, g);
acc.proof.c_inv.mul(acc.proof.c).assert_equals(Fp12.one()); // assert that witnessed inverse is correct
let new_g_digest = ArrayListHasher.hash(lines_hashes);
acc.state.T = T;
acc.state.g_digest = new_g_digest;
return { publicOutput: Poseidon.hashPacked(Accumulator, acc) };
},
},
},
});
const ZKP6Proof = ZkProgram.Proof(zkp6);
export { ZKP6Proof, zkp6 };
//# sourceMappingURL=zkp6.js.map