use groth16_solana::groth16::Groth16Verifyingkey;
use sha2::{Digest, Sha256};
#[cfg(test)]
mod test;
mod utils;
use utils::*;
pub const GROTH16_VK_5_0_0_BYTES: &[u8] = include_bytes!("../vk/v5.0.0/groth16_vk.bin");
pub const GROTH16_VK_4_0_0_RC3_BYTES: &[u8] = include_bytes!("../vk/v4.0.0-rc.3/groth16_vk.bin");
pub const GROTH16_VK_3_0_0_BYTES: &[u8] = include_bytes!("../vk/v3.0.0/groth16_vk.bin");
pub const GROTH16_VK_3_0_0_RC4_BYTES: &[u8] = include_bytes!("../vk/v3.0.0rc4/groth16_vk.bin");
pub const GROTH16_VK_2_0_0_BYTES: &[u8] = include_bytes!("../vk/v2.0.0/groth16_vk.bin");
pub fn verify_proof_raw(proof: &[u8], public_inputs: &[u8], vk: &[u8]) -> Result<(), Error> {
let proof = load_proof_from_bytes(proof)?;
let vk = load_groth16_verifying_key_from_bytes(vk)?;
let public_inputs = load_public_inputs_from_bytes(public_inputs)?;
let vk = Groth16Verifyingkey {
nr_pubinputs: vk.nr_pubinputs as usize,
vk_alpha_g1: vk.vk_alpha_g1,
vk_beta_g2: vk.vk_beta_g2,
vk_gamme_g2: vk.vk_gamma_g2,
vk_delta_g2: vk.vk_delta_g2,
vk_ic: vk.vk_ic.as_slice(),
};
let mut verifier = groth16_solana::groth16::Groth16Verifier::new(
&proof.pi_a,
&proof.pi_b,
&proof.pi_c,
&public_inputs.inputs,
&vk,
)
.map_err(|_| Error::VerificationError)?;
verifier.verify().map_err(|_| Error::VerificationError)
}
#[inline]
pub fn verify_proof(
proof: &[u8],
sp1_public_inputs: &[u8],
sp1_vkey_hash: &str,
groth16_vk: &[u8],
) -> Result<(), Error> {
let groth16_vk_hash: [u8; 4] = Sha256::digest(groth16_vk)[..4].try_into().unwrap();
if groth16_vk_hash != proof[..4] {
return Err(Error::Groth16VkeyHashMismatch);
}
let sp1_vkey_hash = decode_sp1_vkey_hash(sp1_vkey_hash)?;
verify_proof_raw(
&proof[4..],
&groth16_public_values(&sp1_vkey_hash, sp1_public_inputs),
groth16_vk,
)
}