sp1_verifier/plonk/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 68 69 70 71 72 73 74 75 76
pub(crate) const GAMMA: &str = "gamma";
pub(crate) const BETA: &str = "beta";
pub(crate) const ALPHA: &str = "alpha";
pub(crate) const ZETA: &str = "zeta";
pub(crate) const U: &str = "u";
mod converter;
mod hash_to_field;
mod kzg;
mod proof;
mod transcript;
mod verify;
pub(crate) mod error;
pub(crate) use converter::{load_plonk_proof_from_bytes, load_plonk_verifying_key_from_bytes};
pub(crate) use proof::PlonkProof;
pub(crate) use verify::verify_plonk_raw;
use error::PlonkError;
use sha2::{Digest, Sha256};
use crate::{bn254_public_values, decode_sp1_vkey_hash, error::Error};
/// A verifier for Plonk zero-knowledge proofs.
#[derive(Debug)]
pub struct PlonkVerifier;
impl PlonkVerifier {
/// # 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();
/// ```
/// * `plonk_vk` - The Plonk verifying key bytes.
/// Usually this will be the [`static@crate::PLONK_VK_BYTES`] constant.
///
/// # Returns
///
/// A success [`Result`] if verification succeeds, or a [`PlonkError`] if verification fails.
pub fn verify(
proof: &[u8],
sp1_public_inputs: &[u8],
sp1_vkey_hash: &str,
plonk_vk: &[u8],
) -> Result<(), PlonkError> {
// Hash the vk and get the first 4 bytes.
let plonk_vk_hash: [u8; 4] = Sha256::digest(plonk_vk)[..4]
.try_into()
.map_err(|_| PlonkError::GeneralError(Error::InvalidData))?;
// Check to make sure that this proof was generated by the plonk proving key corresponding to
// the given plonk vk.
//
// SP1 prepends the raw Plonk proof with the first 4 bytes of the plonk vkey to
// facilitate this check.
if plonk_vk_hash != proof[..4] {
return Err(PlonkError::PlonkVkeyHashMismatch);
}
let sp1_vkey_hash = decode_sp1_vkey_hash(sp1_vkey_hash)?;
let public_inputs = bn254_public_values(&sp1_vkey_hash, sp1_public_inputs);
let plonk_vk = load_plonk_verifying_key_from_bytes(plonk_vk)?;
let proof = load_plonk_proof_from_bytes(&proof[4..], plonk_vk.qcp.len())?;
verify_plonk_raw(&plonk_vk, &proof, &public_inputs)
}
}