use crate::curves::{create_adapter, CurveAdapter};
use crate::error::{Error, Result};
use crate::model::{Groth16VerificationKey, Groth16VerifierInputs};
use crate::parser::arkworks;
use std::path::Path;
pub fn load_arkworks_inputs(
vk_path: &Path,
proof_path: Option<&Path>,
public_path: Option<&Path>,
curve_hint: Option<&str>,
) -> Result<Groth16VerifierInputs> {
arkworks::load_arkworks_inputs(vk_path, proof_path, public_path, curve_hint)
}
pub fn load_arkworks_bundle(
path: &Path,
curve_hint: Option<&str>,
) -> Result<Groth16VerifierInputs> {
arkworks::load_arkworks_bundle(path, curve_hint)
}
pub fn load_arkworks_inputs_auto(
vk_path: &Path,
proof_path: Option<&Path>,
public_path: Option<&Path>,
) -> Result<Groth16VerifierInputs> {
infer_arkworks_curve("arkworks inputs", |curve| {
arkworks::load_arkworks_inputs(vk_path, proof_path, public_path, Some(curve))
})
}
fn infer_arkworks_curve(
label: &str,
mut load: impl FnMut(&str) -> Result<Groth16VerifierInputs>,
) -> Result<Groth16VerifierInputs> {
let mut matches = Vec::new();
let mut errors = Vec::new();
for curve in ["bn254", "bls12381"] {
match load(curve).and_then(validate_candidate) {
Ok(inputs) => {
if !matches
.iter()
.any(|existing: &Groth16VerifierInputs| existing.curve == inputs.curve)
{
matches.push(inputs);
}
}
Err(err) => errors.push(format!("{curve}: {err}")),
}
}
match matches.len() {
1 => Ok(matches.remove(0)),
0 => Err(Error::MissingInput(format!(
"could not auto-detect {label} curve: {}",
errors.join("; ")
))),
_ => Err(Error::CurveMismatch(format!(
"{label} are valid for more than one supported curve"
))),
}
}
fn validate_candidate(inputs: Groth16VerifierInputs) -> Result<Groth16VerifierInputs> {
let adapter = create_adapter(inputs.curve.canonical_name())?;
if inputs.has_test_vectors() {
match adapter.local_verify(&inputs) {
Ok(true) => Ok(inputs),
Ok(false) => Err(Error::LocalProofVerificationFailed(
"local verification returned false".to_string(),
)),
Err(err) => Err(err),
}
} else {
serialize_verifying_key(adapter.as_ref(), &inputs.verifying_key)?;
Ok(inputs)
}
}
fn serialize_verifying_key(adapter: &dyn CurveAdapter, vk: &Groth16VerificationKey) -> Result<()> {
adapter.serialize_g1_vk(&vk.vk_alpha_1)?;
adapter.serialize_g2_vk(&vk.vk_beta_2)?;
adapter.serialize_g2_vk(&vk.vk_gamma_2)?;
adapter.serialize_g2_vk(&vk.vk_delta_2)?;
for point in &vk.ic {
adapter.serialize_g1_vk(point)?;
}
Ok(())
}