-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
process hangs when verifying proof read&deserialized from file #1411
Comments
hi, @mitschabaude, could u please suggest me? thx |
Using compile({ forceRecompile: true }) fixes it |
thx! |
Do I understand this correctly - you have to do Then it's still a bug, we do want this to work from cached verification keys. I'll reopen this to track it if you don't mind |
Yes, it is correct. I've created a small repo with my usual settings that work for me in MinaNFT: @mitschabaude, you can use it for debugging See also |
Running in to the same problem with the dynamic Single-file repro. Will succeed on first run, hang on second run, and can be fixed by changing import { Bool, Cache, verify, ZkProgram } from 'o1js';
// v-- Change to `true` to fix the hang, even though NoopProgram != VerifyMeProgram.
if (false) {
const NoopProgram = ZkProgram({
name: 'NoopProgram',
methods: {
chaff: {
privateInputs: [],
async method(b) {}
}
}
});
await NoopProgram.compile({ cache: Cache.None });
}
const inputs = await (typeof getPreviousProof !== 'undefined' ? getPreviousProof : createProof)();
console.log('verifying...');
console.log('ok?', await verify(inputs.proof, inputs.verificationKey));
async function createProof() {
const VerifyMeProgram = ZkProgram({
name: 'NoopProgram',
methods: {
proof: {
privateInputs: [Bool],
async method(b) {
b.assertTrue();
},
},
},
});
console.log('compiling...');
const { verificationKey } = await VerifyMeProgram.compile();
console.log('proving...');
const proof = (await VerifyMeProgram.proof(Bool(true))).toJSON();
const data = { verificationKey, proof };
const fs = await import('fs/promises');
const url = await import('url');
await fs.appendFile(url.fileURLToPath(import.meta.url), `async function getPreviousProof() { return ${JSON.stringify(data)}; }`);
return data;
} |
Thanks for the great analysis @SpaceManiac Seems that 'verify()' relies on some values computed during compilation, and isn't able to get them from a cache. We need to fix this! |
@Yoga2015 I cloned your repo zkapp-test and upgraded to o1js 1.6.0 and found that both scripts work ➜ zkapp-test git:(main) ✗ npm run step1
> zkapp-test@1.0.0 step1
> tsc -p tsconfig.json --module esnext && cross-env TEST_ON_BERKELEY=true node --experimental-specifier-resolution=node ./dist/src/step1.js
ProverX_VK: 4245952421456887355009860533252876175165009247779780553775848711375535231266
ok: true
proofStr: {"publicInput":[],"publicOutput":["0"],"maxProofsVerified":0,"proof":"KChzdGF0ZW1lbn.....yMUFGMTEzNzUpKSkpKSkp"}
ok2: true ➜ zkapp-test git:(main) ✗ npm run step2
> zkapp-test@1.0.0 step2
> tsc -p tsconfig.json --module esnext && cross-env TEST_ON_BERKELEY=true node --experimental-specifier-resolution=node ./dist/src/step2.js
ProverX_VK: 4245952421456887355009860533252876175165009247779780553775848711375535231266
str2: {"publicInput":[],"publicOutput":["0"],"maxProofsVerified":0,"proof":"KChzdGF0Z....EY4RjUpKSkpKSkp"}
ok2: true |
I still see the hang on o1js 1.6.0. Stack trace for the record:
|
Running Yoga's original example with @SpaceManiac in your snippet |
|
Whatever this bug is, it seems deeply lodged in the Pickles code. Here's what I found... There are 2 cases I looked at (mostly all reproducing what @SpaceManiac has already reported).
The expected behavior is that these cases both work, but in the first case, the verification call hangs forever and never returns a boolean. The second case works as expected. o1jsIn the example, we call the o1js/src/lib/proof-system/zkprogram.ts Line 475 in 0f57e36
In both cases, the proof we pass is in a ocamlEntering the Pickles layer, the call to In each case, we get passed the deserialization step and enter the async code: Pickles.Side_loaded.verify_promise ~typ [ (vk, statement, proof) ]
|> Promise.map ~f:(fun x -> Js.bool (Or_error.is_ok x))
|> Promise_js_helpers.to_js That is as far as I can trace it for now. |
Would this behavior change if you would call |
can't be, |
this is great progress! so it doesn't depend on any circuit-specific artifact
we will probably only resolve this issue by digging into the Ocaml/Rust verification code and finding out what implicit assumptions it makes on objects that exist And we have a list of objects that are likely contenders: every large object (i.e. subject to caching instead of always computing on the fly) that is shared among different circuits/programs. Could be the SRS? |
In my example, if I remove the following files from the cache:
verify() runs successfully. If I keep those files in the cache folder, verify() hangs |
that is when you compile before verifying right? my explanation for that would be that if those are not present, |
Yes, that's right. Removing any other files does not affect the behavior; the process still hangs. |
@mitschabaude it looks like the verification code actually lives in the mina repo. Is that right? For instance, o1js-bindings calls |
yes it lives in the mina repo! no opinion on where to host the issue (it could also be that it's somehow caused by o1js behaviour of caching the SRS, which lives in the bindings repo |
Hey here, is there a workaround for this issue? Hard to tell from the comment thread. Many thanks. |
@andrewferrone, the best workaround at the moment is to compile an empty zk program, then use a cached proof from disk. For instance
|
This is not a realistic workaround if you're trying to ship an NPM package that others use. I don't want to include a disclaimer in my NPM package that if downloading the package breaks your build, you have to compile an empty zk program to fix it. |
Fair enough. We are working on this and prioritizing the fix. The work around should unblock many users, but I agree it’s not a suitable solution for your use case. |
We're not pre-generating the langrange basis that we need before running the verifier. When we find it missing, the rust code panics, and WASM treats the panic as a halt. The main thread hangs waiting for the dead thread. Will post a fix soon. |
@mrmr1993 I'll do my best :) thanks for pitching in! |
Hey @SebastienGllmt, @andrewferrone, @kadirchan and others. We just released o1js version 1.9.0 which should fix this issue! Please re-open this issue if it is still not working for you :) |
Original issue at Discord: https://discord.com/channels/484437221055922177/1204071024191082496
All the code at https://github.com/TokeniZK/zkapp-test/tree/main/src
tried with o1js version: 0.15.2, 0.15.4, & 0.16.0
Reproduce steps:
I have a demo zkProgram(https://github.com/TokeniZK/zkapp-test/blob/main/src/zkprogram.ts),
step1:
npm run step1
(seen at /src/step1.ts) I exec one method & gen proof, then serialize the
proof
into file:proof.json
. and then read&deserialize it from file and verify it and smoothly get the result:True
.However,
step2: (seen at /src/step2.ts)
npm run step2
I start another process to read the proof from the file on step1(
proof.json
), deserialize it and try to verify the proof, But the process keep await atverify(*)
line !!The text was updated successfully, but these errors were encountered: