[Feature] Add snarkVerify and snarkVerifyBatch for standalone SNARK proof verification#1216
[Feature] Add snarkVerify and snarkVerifyBatch for standalone SNARK proof verification#1216
Conversation
4e09a02 to
08e3c46
Compare
|
@cursor review |
There was a problem hiding this comment.
Pull request overview
This PR adds standalone SNARK proof verification to the SDK, exposing snarkVerify and snarkVerifyBatch functions for client-side verification of Varuna proofs that may not be from on-chain programs.
Changes:
- New
ProofWASM type with serialization/deserialization support - New
snarkVerifyandsnarkVerifyBatchWASM-bound functions inexecution.rs, with convenience wrappers onProgramManager - Updated
create-leo-apptemplates with working examples of proof verification
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
wasm/src/types/native/mod.rs |
Adds ProofNative type alias for the native Proof<CurrentNetwork> |
wasm/src/programs/proof.rs |
New Proof WASM type with fromBytes, fromString, toBytes, toString methods |
wasm/src/programs/mod.rs |
Registers the new proof module |
wasm/src/programs/execution.rs |
Adds snarkVerify, snarkVerifyBatch, and parse_field_inputs functions |
wasm/Cargo.toml |
Adds snarkvm-synthesizer-snark dev-dependency with test-helpers feature |
sdk/src/wasm.ts |
Re-exports Proof, snarkVerify, snarkVerifyBatch |
sdk/src/browser.ts |
Re-exports Proof, snarkVerify, snarkVerifyBatch |
sdk/src/program-manager.ts |
Adds verifyProof and verifyBatchProof convenience methods |
sdk/tests/program-manager.test.ts |
Adds tests for Proof type and SNARK verification functions |
sdk/tests/data/snark-verify.ts |
New test fixture file with sample verifying key, proof, and inputs |
create-leo-app/template-react-ts/src/workers/worker.ts |
Adds verifyProof worker method using sample fixtures |
create-leo-app/template-react-ts/src/App.tsx |
Adds UI button to trigger verifyProof in the React template |
create-leo-app/template-node-ts/src/index.ts |
Adds snarkProofVerification demo function to the Node template |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| verifyProof(verifyingKey: VerifyingKey, inputs: string[], proof: Proof): boolean { | ||
| try { | ||
| return snarkVerify(verifyingKey, inputs, proof); | ||
| } catch (e) { | ||
| console.warn(`Proof verification failed: ${e}`); | ||
| return false; | ||
| } | ||
| } |
There was a problem hiding this comment.
verifyProof silently swallows all exceptions and returns false, including errors caused by invalid inputs (e.g. malformed field strings, wrong number of inputs). This makes it impossible for callers to distinguish a legitimate "proof is invalid" result from an error in their own inputs. Consider either re-throwing non-verification errors (e.g. parse errors) or at minimum documenting clearly that any exception results in a false return. The same issue applies to verifyBatchProof.
There was a problem hiding this comment.
Removed the try/catch. Input errors (e.g. malformed field strings) now propagate to the caller instead of being silently returned as false. Invalid proofs still return false since VerifyingKey::verify returns a bool, not a Result
iamalwaysuncomfortable
left a comment
There was a problem hiding this comment.
This is great! A couple of nits + a few main change requests:
- On the JS side, users should be able to specify either
- The field representation of the inputs (as this is what leo/aleo functions take to do snark.verify) for people who know how to handle this.
- However we should also be able accept the string serialization representation of the inputs (i.e. ["1u32", "2u32"]) and perform the conversion on behalf of the user for users who don't know how to handle it.
- We likely don't need the proof object exported.
- The create-leo-app example should allow people to paste in their own proofs and inputs.
Thanks for putting this together, I'd say this is almost over the line.
| // Demonstrate standalone SNARK proof verification. This verifies a proof from a circuit that is | ||
| // not necessarily an Aleo program execution. Useful for verifying proofs received from external | ||
| // sources (e.g. another party proved a computation and you want to verify it). | ||
| function snarkProofVerification() { |
There was a problem hiding this comment.
Can we make a version of this for the react example that allows people to put their own proof and verifying key in?
There was a problem hiding this comment.
Great idea! Updated the React template to accept user provided verifying key, proof, and public inputs via text fields. Pre-filled with sample fixtures so it works out of the box.
| } | ||
|
|
||
| /** | ||
| * Verify a SNARK proof against a verifying key and public inputs. |
There was a problem hiding this comment.
| * Verify a SNARK proof against a verifying key and public inputs. | |
| * Verify an Aleo zkSnark proof against a verifying key and public inputs. |
| pub fn snark_verify_batch(verifying_keys: Array, inputs: Array, proof: &Proof) -> Result<bool, String> { | ||
| if verifying_keys.length() != inputs.length() { | ||
| return Err(format!( | ||
| "Mismatch: {} verifying keys but {} input groups provided", |
There was a problem hiding this comment.
| "Mismatch: {} verifying keys but {} input groups provided", | |
| "Mismatch: {} verifying keys but {} input groups provided. # of input groups must match # of verifying keys.", |
| * It directly invokes the Varuna proof verification from snarkVM. | ||
| * | ||
| * @param {VerifyingKey} verifyingKey The verifying key for the circuit | ||
| * @param {string[]} inputs Array of field element strings representing public inputs (e.g. ["1field", "2field"]) |
There was a problem hiding this comment.
So although we DO want to support fields, we also want to support passing the string representations of the types here in the SDK instead of the field representations, then internally we can call toFields() on the inputs.
So this means the string representation of normal aleo types like:
- ["1u32", "2u32"]
- ["{ is_open: true, commision: 20u8}"]
We can then parse to see if they're correct aleo types and call to_fields() internally. Users should have the option to pass both the Field representation of the inputs AND the serialized aleo type representations. We can do this via a parameter object.
There was a problem hiding this comment.
We can then parse to see if they're correct aleo types and call to_fields() internally. Users should have the option to pass both the Field representation of the inputs AND the serialized aleo type representations. We can do this via a parameter object.
Technically we could do it in this JS side because we have the toFields() tooling to do it here.
| * const proof = Proof.fromString("proof1..."); | ||
| * const isValid = programManager.verifyProof(verifyingKey, ["1field", "2field"], proof); | ||
| */ | ||
| verifyProof(verifyingKey: VerifyingKey, inputs: string[], proof: Proof): boolean { |
There was a problem hiding this comment.
We want to move to object parameters in general in new JS methods, so here we'd do this.
| verifyProof(verifyingKey: VerifyingKey, inputs: string[], proof: Proof): boolean { | |
| verifyProof(VerificationOptions): boolean { |
| * Each verifying key is paired with one or more sets of public inputs (instances). | ||
| * | ||
| * @param {string[]} verifyingKeys Array of verifying key strings, one per circuit | ||
| * @param {string[][][]} inputs 3D array of field element strings [circuit_idx][instance_idx][field_idx] |
There was a problem hiding this comment.
Same comment here, we want users to be able to put it in the plaintext string representation of the inputs.
| /// @param {Proof} proof The batch proof to verify | ||
| /// @returns {boolean} True if the batch proof is valid, false otherwise | ||
| #[wasm_bindgen(js_name = "snarkVerifyBatch")] | ||
| pub fn snark_verify_batch(verifying_keys: Array, inputs: Array, proof: &Proof) -> Result<bool, String> { |
There was a problem hiding this comment.
We might consider giving the user the option to give either field inputs OR the string serialization.
There was a problem hiding this comment.
Handled at the SDK layer. ProgramManager.verifyProof() and verifyBatchProof() will now both run inputsToFields() which accepts either raw field strings or Aleo type strings (e.g. "1u32", "true", structs) and automatically converts them to fields via Plaintext.toFields(). The wasm functions are kept as thin wrappers over the snarkVM native API, while ProgramManager provides the user-friendly interface.
| * | ||
| * @param {VerifyingKey} verifyingKey The verifying key for the circuit | ||
| * @param {string[]} inputs Array of field element strings representing public inputs (e.g. ["1field", "2field"]) | ||
| * @param {Proof} proof The proof to verify |
There was a problem hiding this comment.
This should likely just be the proof string and not the wasm object.
| * @param {Proof} proof The proof to verify | |
| * @param {string} proof The proof to verify |
There was a problem hiding this comment.
Good call! Updated to accept proof and verifyingKey as plain strings. The methods now handle Proof.fromString() / VerifyingKey.fromString() conversion internally so users don't need to import or construct wasm objects.
| /// SNARK proof for verification of program execution | ||
| #[wasm_bindgen] | ||
| #[derive(Clone, Debug)] | ||
| pub struct Proof(ProofNative); |
There was a problem hiding this comment.
I don't think we need to export this object as it doesn't add much. The main reason for exporting an object to wasm is when it provides computations done in Rust that would be hard/error-prone/hard-to-maintain if re-implemented in JS/TS. In methods that use proofs we can just construct the Rust object via the string representation.
There was a problem hiding this comment.
Agreed! Updated to accept proof: string (and verifyingKey: string). The ProgramManager methods handle Proof.fromString() / VerifyingKey.fromString() internally, so users never need to import or construct the Proof wasm object.
08d0221 to
938dbc1
Compare
938dbc1 to
cb9d1cb
Compare
cb9d1cb to
166742d
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
166742d to
369140c
Compare
0f51672 to
ad9220e
Compare
369140c to
576d07e
Compare
e56f119 to
a2d2ad7
Compare
576d07e to
db6261e
Compare
…namic-dispatch branch
* Add WASM support for dynamic dispatch variant types (DynamicRecord, DynamicFuture, RecordWithDynamicID, ExternalRecordWithDynamicID) * fmt * fix(wasm): normalize dynamic dispatch type strings to match snarkVM serialization and add missing doc comments * add JS/TS fixture tests for dynamic dispatch variant types (record_dynamic, record_with_dynamic_id, external_record_with_dynamic_id)
…ture to match snarkVM (#1210)
* Handle Consensus V14 in deployments * Remove redundant .map_err in latest_stateroot call * Update getOrInitConsensusVersionTestHeights tests and doc comments to handle all currently active test version heights * Deallocate deployment cost tuple
* Add stringToField utility function for converting program and function names to fields for dynamic dispatch * Add exports of the stringToField utility in the js SDK
* Add the dynamic record type * Add JS side tests for the DynamicRecord type * Check visibility on record conversion roundtrip --------- Signed-off-by: Mike Turner <mike@provable.com>
* Handle Consensus V14 in deployments (#1230) * Handle Consensus V14 in deployments * Remove redundant .map_err in latest_stateroot call * Update getOrInitConsensusVersionTestHeights tests and doc comments to handle all currently active test version heights * Deallocate deployment cost tuple * Updates to make AMM tests works * Also handle upgrade * Address feedback * Cleanup * Cargo fmt lints * Revert .gitignore changes unrelated to this PR * Change core rev to the testnet 4.6.0 candidate * Bump version update to v0.9.18 * Remove unecessary dependencies in the workspace root --------- Co-authored-by: Mike Turner <mike@provable.com>
c0ac20e to
a095833
Compare
…NARK proof verification Add support for verifying SNARK proofs from programs not deployed on chain, wrapping snarkVM's VerifyingKey::verify and VerifyingKey::verify_batch APIs.
db6261e to
e0cae55
Compare
e0cae55 to
8e9354b
Compare
8e9354b to
18eb4aa
Compare
…inputsToFields from Plaintext to Value
18eb4aa to
8672101
Compare
6c5a46a to
486b002
Compare
b1382e8 to
3c76a12
Compare
|
This feature has been merged via #1263 therefore closing this! |
Motivation
The
snark.verifyopcode is being added tosnarkVMalongsidedynamic dispatch, enabling Leo programs to verify SNARK proofs from programs that are not deployed on-chain. This PR exposes the same capability to the SDK, allowing client-side proof verification viasnarkVerifyandsnarkVerifyBatch. These functions take a verifying key, public inputs, and a proof, and return whether the proof is valid, matching the opcode's interface for JS/TS consumers.Test Plan
Prooftype roundtrip (string and bytes), nativeVerifyingKey::verifywith valid/invalid inputs, proof fixture roundtripProof.fromString/toBytesroundtrip,snarkVerifywith valid inputs returns true,snarkVerifywith wrong inputs returns false,snarkVerifyBatchwith valid batch returns true,snarkVerifyBatchwith mismatched key/input counts throwstemplate-node-ts,template-react-ts) updated with working examplesNote
Medium Risk
Introduces new WASM-exposed SNARK verification primitives and new
ProgramManagerverification entrypoints; while mostly additive, it touches cryptographic verification surfaces and input parsing/field conversion paths.Overview
Adds standalone SNARK proof verification support to the SDK by exposing WASM functions
snarkVerify/snarkVerifyBatchplus a newProoftype, and re-exporting them through the browser SDK surface.Extends
ProgramManagerwithverifyProofandverifyBatchProof(and exportedVerificationOptionstypes), including automatic conversion of Aleo-typed public inputs to field elements viaPlaintext.toFields().Updates create-leo-app Node/React templates to demonstrate proof verification (including a React UI + worker method), and adds SDK/wasm tests and fixtures to validate valid/invalid and batch verification behavior.
Written by Cursor Bugbot for commit 369140c. This will update automatically on new commits. Configure here.