export-aptos-verifier-core 0.1.1

Load Groth16 artifacts from snarkjs JSON or Arkworks bundles and generate Aptos Move verifier packages.
Documentation
use crate::error::{Error, Result};
use crate::snarkjs::{
    validate_curve_match, validate_protocol, validate_public_counts,
    validate_verification_key_geometry, Proof as LegacyProof, SnarkJsG1, SnarkJsG2,
    VerificationKey as LegacyVerificationKey,
};

pub type DecimalValue = String;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CurveKind {
    Bn254,
    Bls12_381,
}

impl CurveKind {
    pub fn from_name(value: &str) -> Result<Self> {
        match normalize_curve_name(value).as_str() {
            "bn128" | "bn254" | "altbn128" => Ok(Self::Bn254),
            "bls12381" => Ok(Self::Bls12_381),
            _ => Err(Error::UnsupportedCurve(format!(
                "unsupported curve: {value}"
            ))),
        }
    }

    pub fn canonical_name(self) -> &'static str {
        match self {
            Self::Bn254 => "bn254",
            Self::Bls12_381 => "bls12381",
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SourceFormat {
    SnarkjsJson,
    ArkworksCompact,
}

#[derive(Debug, Clone)]
pub struct Groth16G1Point {
    pub x: DecimalValue,
    pub y: DecimalValue,
    pub z: DecimalValue,
}

#[derive(Debug, Clone)]
pub struct Groth16G2Point {
    pub x0: DecimalValue,
    pub x1: DecimalValue,
    pub y0: DecimalValue,
    pub y1: DecimalValue,
    pub z0: DecimalValue,
    pub z1: DecimalValue,
}

#[derive(Debug, Clone)]
pub struct Groth16VerificationKey {
    pub n_public: usize,
    pub vk_alpha_1: Groth16G1Point,
    pub vk_beta_2: Groth16G2Point,
    pub vk_gamma_2: Groth16G2Point,
    pub vk_delta_2: Groth16G2Point,
    pub ic: Vec<Groth16G1Point>,
}

#[derive(Debug, Clone)]
pub struct Groth16Proof {
    pub pi_a: Groth16G1Point,
    pub pi_b: Groth16G2Point,
    pub pi_c: Groth16G1Point,
}

#[derive(Debug, Clone)]
pub struct Groth16VerifierInputs {
    pub curve: CurveKind,
    pub protocol: String,
    pub verifying_key: Groth16VerificationKey,
    pub proof: Groth16Proof,
    pub public_inputs: Vec<DecimalValue>,
    pub source_format: SourceFormat,
}

impl Groth16VerifierInputs {
    pub fn from_legacy(
        vk: LegacyVerificationKey,
        proof: LegacyProof,
        public_inputs: Vec<DecimalValue>,
        source_format: SourceFormat,
    ) -> Result<Self> {
        validate_protocol(vk.protocol.as_ref(), proof.protocol.as_ref())?;
        validate_verification_key_geometry(&vk)?;
        validate_public_counts(&vk, &public_inputs)?;

        let curve_name = validate_curve_match(vk.curve.as_ref(), proof.curve.as_ref())?;
        let curve = CurveKind::from_name(&curve_name)?;
        let protocol = vk
            .protocol
            .clone()
            .or_else(|| proof.protocol.clone())
            .unwrap_or_else(|| "groth16".to_string());

        Ok(Self {
            curve,
            protocol,
            verifying_key: Groth16VerificationKey {
                n_public: vk.n_public,
                vk_alpha_1: vk.vk_alpha_1.into(),
                vk_beta_2: vk.vk_beta_2.into(),
                vk_gamma_2: vk.vk_gamma_2.into(),
                vk_delta_2: vk.vk_delta_2.into(),
                ic: vk.ic.into_iter().map(Into::into).collect(),
            },
            proof: Groth16Proof {
                pi_a: proof.pi_a.into(),
                pi_b: proof.pi_b.into(),
                pi_c: proof.pi_c.into(),
            },
            public_inputs,
            source_format,
        })
    }
}

impl From<SnarkJsG1> for Groth16G1Point {
    fn from(value: SnarkJsG1) -> Self {
        Self {
            x: value.x,
            y: value.y,
            z: value.z,
        }
    }
}

impl From<SnarkJsG2> for Groth16G2Point {
    fn from(value: SnarkJsG2) -> Self {
        Self {
            x0: value.x0,
            x1: value.x1,
            y0: value.y0,
            y1: value.y1,
            z0: value.z0,
            z1: value.z1,
        }
    }
}

fn normalize_curve_name(value: &str) -> String {
    value.to_lowercase().replace(['-', '_'], "")
}