-
Notifications
You must be signed in to change notification settings - Fork 370
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
feat(verifier): verify_bytes api GRO-304 #1784
Changes from 3 commits
dd36a6c
63ff7a4
98ad2df
c873148
e8d2a97
78b4418
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,45 @@ Here, the proof, public inputs, and vkey hash are read from stdin. See the follo | |
|
||
> Note that the SP1 SDK itself is *not* `no_std` compatible. | ||
|
||
### Advanced: `verify_bytes` | ||
|
||
`sp1-verifier` also exposes [`Groth16Verifier::verify_bytes`](https://docs.rs/sp1-verifier/latest/sp1_verifier/struct.Groth16Verifier.html#method.verify_bytes) and [`PlonkVerifier::verify_bytes`](https://docs.rs/sp1-verifier/latest/sp1_verifier/struct.PlonkVerifier.html#method.verify_bytes), | ||
which verifies any Groth16 or Plonk proof from gnark. This is especially useful for verifying custom Groth16 and Plonk proofs | ||
efficiently in the SP1 ZKVM. | ||
|
||
The following snippet demonstrates how you might serialize a gnark proof in a way that `sp1-verifier` can use. | ||
|
||
```go | ||
// Write the verifier key. | ||
vkFile, err := os.Create("vk.bin") | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer vkFile.Close() | ||
|
||
// Here, `vk` is a `groth16_bn254.VerifyingKey` or `plonk_bn254.VerifyingKey`. | ||
_, err = vk.WriteTo(vkFile) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Write the proof. | ||
proofFile, err := os.Create("proof.bin") | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer proofFile.Close() | ||
|
||
// Here, `proof` is a `groth16_bn254.Proof` or `plonk_bn254.Proof`. | ||
_, err = proof.WriteTo(proofFile) | ||
if err != nil { | ||
panic(err) | ||
} | ||
``` | ||
|
||
Public values are serialized as big-endian `Fr` values. The default gnark serialization will work | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Capitalize Gnark |
||
out of the box. | ||
|
||
## Wasm Verification | ||
|
||
The [`example-sp1-wasm-verifier`](https://github.com/succinctlabs/example-sp1-wasm-verifier) demonstrates how to | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,19 +2,22 @@ mod converter; | |
pub mod error; | ||
mod verify; | ||
|
||
use bn::Fr; | ||
pub(crate) use converter::{load_groth16_proof_from_bytes, load_groth16_verifying_key_from_bytes}; | ||
use sha2::{Digest, Sha256}; | ||
pub(crate) use verify::*; | ||
|
||
use error::Groth16Error; | ||
|
||
use crate::{bn254_public_values, decode_sp1_vkey_hash, error::Error}; | ||
use crate::{decode_sp1_vkey_hash, error::Error, hash_public_inputs}; | ||
|
||
use alloc::vec::Vec; | ||
use sha2::{Digest, Sha256}; | ||
|
||
/// A verifier for Groth16 zero-knowledge proofs. | ||
#[derive(Debug)] | ||
pub struct Groth16Verifier; | ||
impl Groth16Verifier { | ||
/// Verifies a Groth16 proof. | ||
/// Verifies a Groth16 proof using SP1 native inputs. | ||
/// | ||
/// # Arguments | ||
/// | ||
|
@@ -57,11 +60,45 @@ impl Groth16Verifier { | |
} | ||
|
||
let sp1_vkey_hash = decode_sp1_vkey_hash(sp1_vkey_hash)?; | ||
let public_inputs = bn254_public_values(&sp1_vkey_hash, sp1_public_inputs); | ||
|
||
let proof = load_groth16_proof_from_bytes(&proof[4..])?; | ||
let groth16_vk = load_groth16_verifying_key_from_bytes(groth16_vk)?; | ||
Self::verify_bytes( | ||
&proof[4..], | ||
&[sp1_vkey_hash, hash_public_inputs(sp1_public_inputs)], | ||
groth16_vk, | ||
) | ||
} | ||
|
||
/// Verifies a Groth16 proof using raw byte inputs. | ||
/// | ||
/// WARNING: if you're verifying an SP1 proof, you should use [`verify`] instead. | ||
/// This is a lower-level verification method that works directly with raw bytes rather than | ||
/// the SP1 SDK's data structures. | ||
/// | ||
/// # Arguments | ||
/// | ||
/// * `proof` - The raw Groth16 proof bytes (without the 4-byte vkey hash prefix) | ||
/// * `public_inputs` - The public inputs to the circuit | ||
/// * `groth16_vk` - The Groth16 verifying key bytes | ||
/// | ||
/// # Returns | ||
/// | ||
/// A [`Result`] containing unit `()` if the proof is valid, | ||
/// or a [`Groth16Error`] if verification fails. | ||
/// | ||
/// # Note | ||
/// | ||
/// This method expects the raw proof bytes without the 4-byte vkey hash prefix that | ||
/// [`verify`] checks. If you have a complete proof with the prefix, use [`verify`] instead. | ||
pub fn verify_bytes( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better name is |
||
proof: &[u8], | ||
public_inputs: &[[u8; 32]], | ||
groth16_vk: &[u8], | ||
) -> Result<(), Groth16Error> { | ||
let proof = load_groth16_proof_from_bytes(proof).unwrap(); | ||
let groth16_vk = load_groth16_verifying_key_from_bytes(groth16_vk).unwrap(); | ||
|
||
verify_groth16_raw(&groth16_vk, &proof, &public_inputs) | ||
let public_inputs = | ||
public_inputs.iter().map(|input| Fr::from_slice(input).unwrap()).collect::<Vec<_>>(); | ||
verify_groth16_algebraic(&groth16_vk, &proof, &public_inputs) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,7 +33,7 @@ pub(crate) struct PlonkVerifyingKey { | |
pub(crate) commitment_constraint_indexes: Vec<usize>, | ||
} | ||
|
||
/// Verifies a PLONK proof | ||
/// Verifies a PLONK proof using algebraic inputs. | ||
/// | ||
/// # Arguments | ||
/// | ||
|
@@ -44,7 +44,7 @@ pub(crate) struct PlonkVerifyingKey { | |
/// # Returns | ||
/// | ||
/// * `Result<bool, PlonkError>` - Returns true if the proof is valid, or an error if verification fails | ||
pub(crate) fn verify_plonk_raw( | ||
pub(crate) fn verify_plonk_algebraic( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add #[must_use] so people don't forget to unwrap There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. must_use is already on by default for
|
||
vk: &PlonkVerifyingKey, | ||
proof: &PlonkProof, | ||
public_inputs: &[Fr], | ||
|
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.
Fix: Capitalize Gnark, and add a link to https://docs.gnark.consensys.io/, or the repo.
zkVM, instead of ZKVM.