o1-labs/o1js

Add ZkProgram.Optimistic to allow for deferred recursive proof calculations

dfstio opened this issue · 2 comments

When calculating recursive proofs, there is a significant probability that the user's transactions are malformed or contain the data that will cause asserts in ZkProgram to throw. Therefore, in the case of calculating recursive proof for 100 txs, which is expensive, it makes sense first to check all txs to make sure that the proof can be created.

Now, it is possible to do this in two ways:

  1. Add TypeScript code that repeats the logic of ZkProgram and checks the txs. This method is error-prone, but it can give a 90% probability of checks being correct.
  2. Define Struct, which contains all the logic, and in the ZkProgram, just call Struct functions. All txs can be checked by calling Struct's functions. There is a 99% probability of checks being correct, but it is still not 100%

The better way would be to define the new ZkProgram.Optimistic that just calculates the state without long proof calculations:

    class MyOptimisticZkProgram extends ZkProgram.Optimistic(MyZkProgram) {}
    try { 
      for( let i=0; i<100; i++) {
        // only do state calculations and check assertions, do not produce proofs
        await MyOptimisticZkProgram.check(txs[i]);
      }
      // All txs are valid, now produce proofs
      for( let i=0; i<100; i++) {
        proofs.push(await MyZkProgram.check(txs[i]));
      }
    } catch (e) {
      console.error(`Txs are invalid`, e);
    }

The second use case is quickly producing the final state of the ZkProgram to get it signed by the user. This decreases the user's wait time and guarantees that we can later produce valid proof of the signed state.

ZkProgram.Optimistic has nothing to do with "proofs off" debugging and is intended for use in production environments with proofs on.

@dfstio are you aware of program.rawMethods which contains the raw program methods that you could run on your inputs directly?

@dfstio are you aware of program.rawMethods which contains the raw program methods that you could run on your inputs directly?

Thank you! This way, it works:
await MyZkProgram.rawMethods.check(txs[i]);