-
Notifications
You must be signed in to change notification settings - Fork 135
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
Error feedback on compile-prover discrepancies #1363
Draft
mitschabaude
wants to merge
29
commits into
v1
Choose a base branch
from
feature/debug-missing-witnesses
base: v1
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+760
−179
Draft
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
a79b0c9
start debugging dex example
mitschabaude 01595e1
start adding types for low level snarky intf
mitschabaude b26f2b2
iterate on types
mitschabaude 7444829
iterate on api and fix type error
mitschabaude bb54d4f
runner that can compare circuit constraints against a previous run
mitschabaude 75a48f7
expose more flexible cs processing
mitschabaude cbf40cd
revert returning result
mitschabaude 02fdbc8
don't return result from constraint system
mitschabaude 08f9f72
use runCircuit in analyzeMethods
mitschabaude b3a3479
move zkapp proving logic to separate file
mitschabaude 089e19e
minor
mitschabaude 5121c46
WIP: compare constraints in zkapp proof to the ones created in analyz…
mitschabaude 7b58e97
remove debugging, fix basic constraint data
mitschabaude a2064f6
add memoized witnesses to avoid failing constraints
mitschabaude 923c5ac
hook prover consistency check into prover when detecting a relevant p…
mitschabaude ad20e1c
show traces to constraints in both versions
mitschabaude b615991
seems more correct but I'm not sure
mitschabaude 73b17e0
helper to print account update layout
mitschabaude e3cfaf9
fix the damn bug
mitschabaude 061cad0
[dex] remove obsolete scare comments
mitschabaude 93568b8
minor example tweak
mitschabaude 9127ae6
submodules
mitschabaude e727822
Merge branch 'fix/prover-bug-reloaded' into feature/debug-missing-wit…
mitschabaude f19076a
changelog
mitschabaude bb37bf1
Merge branch 'main' into feature/debug-missing-witnesses
mitschabaude e9979d9
reduce diff to main where changes weren't necessary
mitschabaude 68487d7
add docs and changelog
mitschabaude dff07c4
more cases in which to check inconsistent constraints
mitschabaude e49b788
bindings
mitschabaude File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
move zkapp proving logic to separate file
commit b3a3479726ff34d882e5201a1a7164cbe6d8a4ef
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import { Pickles } from '../../snarky.js'; | ||
import { | ||
AccountUpdate, | ||
Authorization, | ||
FeePayerUnsigned, | ||
LazyProof, | ||
LazySignature, | ||
ZkappCommand, | ||
ZkappProverData, | ||
ZkappPublicInput, | ||
zkAppProver, | ||
} from '../account_update.js'; | ||
import { MlArray } from '../ml/base.js'; | ||
import { MlFieldConstArray } from '../ml/fields.js'; | ||
import { Empty, Proof, dummyBase64Proof } from '../proof_system.js'; | ||
import { memoizationContext } from '../provable.js'; | ||
|
||
export { addMissingProofs }; | ||
|
||
type AccountUpdateProved = AccountUpdate & { | ||
lazyAuthorization?: LazySignature; | ||
}; | ||
|
||
type ZkappCommandProved = { | ||
feePayer: FeePayerUnsigned; | ||
accountUpdates: AccountUpdateProved[]; | ||
memo: string; | ||
}; | ||
|
||
async function addMissingProofs( | ||
zkappCommand: ZkappCommand, | ||
{ proofsEnabled = true } | ||
): Promise<{ | ||
zkappCommand: ZkappCommandProved; | ||
proofs: (Proof<ZkappPublicInput, Empty> | undefined)[]; | ||
}> { | ||
let { feePayer, accountUpdates, memo } = zkappCommand; | ||
// compute proofs serially. in parallel would clash with our global variable | ||
// hacks | ||
let accountUpdatesProved: AccountUpdateProved[] = []; | ||
let proofs: (Proof<ZkappPublicInput, Empty> | undefined)[] = []; | ||
for (let i = 0; i < accountUpdates.length; i++) { | ||
let { accountUpdateProved, proof } = await addProof( | ||
zkappCommand, | ||
i, | ||
proofsEnabled | ||
); | ||
accountUpdatesProved.push(accountUpdateProved); | ||
proofs.push(proof); | ||
} | ||
return { | ||
zkappCommand: { feePayer, accountUpdates: accountUpdatesProved, memo }, | ||
proofs, | ||
}; | ||
} | ||
|
||
async function addProof( | ||
transaction: ZkappCommand, | ||
index: number, | ||
proofsEnabled: boolean | ||
) { | ||
let accountUpdate = transaction.accountUpdates[index]; | ||
accountUpdate = AccountUpdate.clone(accountUpdate); | ||
|
||
if (accountUpdate.lazyAuthorization?.kind !== 'lazy-proof') { | ||
return { | ||
accountUpdateProved: accountUpdate as AccountUpdateProved, | ||
proof: undefined, | ||
}; | ||
} | ||
if (!proofsEnabled) { | ||
Authorization.setProof(accountUpdate, await dummyBase64Proof()); | ||
return { | ||
accountUpdateProved: accountUpdate as AccountUpdateProved, | ||
proof: undefined, | ||
}; | ||
} | ||
|
||
let lazyProof: LazyProof = accountUpdate.lazyAuthorization; | ||
let prover = getZkappProver(lazyProof); | ||
let proverData = { transaction, accountUpdate, index }; | ||
let proof = await createZkappProof(prover, lazyProof, proverData); | ||
|
||
let accountUpdateProved = Authorization.setProof( | ||
accountUpdate, | ||
Pickles.proofToBase64Transaction(proof.proof) | ||
); | ||
return { accountUpdateProved, proof }; | ||
} | ||
|
||
async function createZkappProof( | ||
prover: Pickles.Prover, | ||
{ | ||
methodName, | ||
args, | ||
previousProofs, | ||
ZkappClass, | ||
memoized, | ||
blindingValue, | ||
}: LazyProof, | ||
{ transaction, accountUpdate, index }: ZkappProverData | ||
): Promise<Proof<ZkappPublicInput, Empty>> { | ||
let publicInput = accountUpdate.toPublicInput(); | ||
let publicInputFields = MlFieldConstArray.to( | ||
ZkappPublicInput.toFields(publicInput) | ||
); | ||
|
||
let [, , proof] = await zkAppProver.run( | ||
[accountUpdate.publicKey, accountUpdate.tokenId, ...args], | ||
{ transaction, accountUpdate, index }, | ||
async () => { | ||
let id = memoizationContext.enter({ | ||
memoized, | ||
currentIndex: 0, | ||
blindingValue, | ||
}); | ||
try { | ||
return await prover(publicInputFields, MlArray.to(previousProofs)); | ||
} catch (err) { | ||
console.error(`Error when proving ${ZkappClass.name}.${methodName}()`); | ||
throw err; | ||
} finally { | ||
memoizationContext.leave(id); | ||
} | ||
} | ||
); | ||
|
||
let maxProofsVerified = ZkappClass._maxProofsVerified!; | ||
const Proof = ZkappClass.Proof(); | ||
return new Proof({ | ||
publicInput, | ||
publicOutput: undefined, | ||
proof, | ||
maxProofsVerified, | ||
}); | ||
} | ||
|
||
function getZkappProver({ methodName, ZkappClass }: LazyProof) { | ||
if (ZkappClass._provers === undefined) | ||
throw Error( | ||
`Cannot prove execution of ${methodName}(), no prover found. ` + | ||
`Try calling \`await ${ZkappClass.name}.compile()\` first, this will cache provers in the background.` | ||
); | ||
let provers = ZkappClass._provers; | ||
let methodError = | ||
`Error when computing proofs: Method ${methodName} not found. ` + | ||
`Make sure your environment supports decorators, and annotate with \`@method ${methodName}\`.`; | ||
if (ZkappClass._methods === undefined) throw Error(methodError); | ||
let i = ZkappClass._methods.findIndex((m) => m.methodName === methodName); | ||
if (i === -1) throw Error(methodError); | ||
return provers[i]; | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code in this new file consists of:
account_update.ts
debugInconsistentConstraints()
, which is triggered after encountering certain errors in the zkApp prover. It then runs the newrunCircuit()
twice, once in compile and once in prover mode, to identify any mismatch in the generated constraints. If a mismatch is found, we throw a very helpful error that points to it. Otherwise, we throw the original prover error.