sp1_verifier/groth16/mod.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
mod converter;
pub mod error;
mod verify;
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};
/// A verifier for Groth16 zero-knowledge proofs.
#[derive(Debug)]
pub struct Groth16Verifier;
impl Groth16Verifier {
/// Verifies a Groth16 proof.
///
/// # Arguments
///
/// * `proof` - The proof bytes.
/// * `public_inputs` - The SP1 public inputs.
/// * `sp1_vkey_hash` - The SP1 vkey hash.
/// This is generated in the following manner:
///
/// ```ignore
/// use sp1_sdk::ProverClient;
/// let client = ProverClient::new();
/// let (pk, vk) = client.setup(ELF);
/// let sp1_vkey_hash = vk.bytes32();
/// ```
/// * `groth16_vk` - The Groth16 verifying key bytes.
/// Usually this will be the [`static@crate::GROTH16_VK_BYTES`] constant, which is the Groth16
/// verifying key for the current SP1 version.
///
/// # Returns
///
/// A success [`Result`] if verification succeeds, or a [`Groth16Error`] if verification fails.
pub fn verify(
proof: &[u8],
sp1_public_inputs: &[u8],
sp1_vkey_hash: &str,
groth16_vk: &[u8],
) -> Result<(), Groth16Error> {
// Hash the vk and get the first 4 bytes.
let groth16_vk_hash: [u8; 4] = Sha256::digest(groth16_vk)[..4]
.try_into()
.map_err(|_| Groth16Error::GeneralError(Error::InvalidData))?;
// Check to make sure that this proof was generated by the groth16 proving key corresponding to
// the given groth16_vk.
//
// SP1 prepends the raw Groth16 proof with the first 4 bytes of the groth16 vkey to
// facilitate this check.
if groth16_vk_hash != proof[..4] {
return Err(Groth16Error::Groth16VkeyHashMismatch);
}
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)?;
verify_groth16_raw(&groth16_vk, &proof, &public_inputs)
}
}