o1js
Version:
TypeScript framework for zk-SNARKs and zkApps
93 lines (74 loc) • 2.21 kB
text/typescript
import { Field, ZkProgram, assert, Provable, Proof, Experimental } from 'o1js';
import { tic, toc } from '../examples/utils/tic-toc.js';
let log: string[] = [];
function pushLog(s: string) {
Provable.asProver(() => {
console.log(s);
log.push(s);
});
}
let mergeProgram = ZkProgram({
name: 'recursive-2',
publicOutput: Field,
methods: {
baseCase: {
privateInputs: [Field],
async method(x: Field) {
pushLog('baseCase');
x = x.add(7);
return { publicOutput: x };
},
},
mergeOne: {
privateInputs: [],
async method() {
pushLog('mergeOne');
let z = Provable.witness(Field, () => 0);
let x: Field = await mergeProgramRecursive.baseCase(z);
return { publicOutput: x.add(1) };
},
},
mergeTwo: {
privateInputs: [],
async method() {
pushLog('mergeTwo');
let z = Provable.witness(Field, () => 0);
let x: Field = await mergeProgramRecursive.baseCase(z);
let y: Field = await mergeProgramRecursive.mergeOne();
return { publicOutput: x.add(y) };
},
},
},
});
let mergeProgramRecursive = Experimental.Recursive(mergeProgram);
let Wrapper = ZkProgram({
name: 'wraps-recursive-2',
methods: {
wrap: {
privateInputs: [mergeProgram.Proof],
async method(proof: Proof<undefined, Field>) {
proof.verify();
let x = proof.publicOutput;
x.assertLessThan(30);
},
},
},
});
tic('compiling');
await mergeProgram.compile();
await Wrapper.compile();
toc();
tic('executing 4 proofs');
let { proof } = await mergeProgram.mergeTwo();
toc();
assert(await mergeProgram.verify(proof), 'Proof is not valid');
proof.publicOutput.assertEquals(15);
assert(log.length === 4, 'log.length === 4');
assert(log[0] === 'mergeTwo', 'log[0] === "mergeTwo"');
assert(log[1] === 'baseCase', 'log[1] === "baseCase"');
assert(log[2] === 'mergeOne', 'log[2] === "mergeOne"');
assert(log[3] === 'baseCase', 'log[3] === "baseCase"');
tic('execute wrapper proof');
let { proof: wrapperProof } = await Wrapper.wrap(proof);
toc();
assert(await Wrapper.verify(wrapperProof), 'Wrapper proof is not valid');