UNPKG

@nori-zk/proof-conversion

Version:

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

102 lines 5.14 kB
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