use crate::common::{G1Point, G2Point, TrustedSetup};
use crate::dag::{ExprId, ExpressionDAG};
use crate::errors::ZkError;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProvingKey {
pub a_matrix: Vec<Vec<f64>>, pub b_matrix: Vec<Vec<f64>>, pub c_matrix: Vec<Vec<f64>>,
pub lagrange_a: Vec<f64>,
pub lagrange_b: Vec<f64>,
pub lagrange_c: Vec<f64>,
pub witness_dag: ExpressionDAG,
pub witness_ids: Vec<ExprId>,
pub witness_names: Vec<String>,
pub public_variables: HashSet<String>,
pub trusted_setup: TrustedSetup,
pub num_constraints: usize,
pub num_variables: usize,
pub evaluation_point: f64,
pub env_dict: std::collections::HashMap<String, i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VerificationKey {
pub g1: G1Point,
pub g2: G2Point,
pub h1: G1Point, pub h2: G2Point,
pub num_constraints: usize,
}
impl ProvingKey {
pub fn save_to_file(&self, path: &std::path::Path) -> Result<(), ZkError> {
let encoded = bincode::serialize(self)
.map_err(|e| ZkError::SerializationError(format!("Failed to serialize proving key: {}", e)))?;
std::fs::write(path, encoded)
.map_err(|e| ZkError::IoError(format!("Failed to write proving key file: {}", e)))?;
Ok(())
}
pub fn load_from_file(path: &std::path::Path) -> Result<Self, ZkError> {
let data = std::fs::read(path)
.map_err(|e| ZkError::IoError(format!("Failed to read proving key file: {}", e)))?;
let proving_key = bincode::deserialize(&data)
.map_err(|e| ZkError::SerializationError(format!("Failed to deserialize proving key: {}", e)))?;
Ok(proving_key)
}
}
impl VerificationKey {
pub fn to_rust_code(&self, prefix: Option<&str>) -> String {
let prefix_upper = prefix.map(|p| p.to_uppercase()).unwrap_or_default();
let prefix_lower = prefix.map(|p| p.to_lowercase()).unwrap_or_default();
let prefix_const = if prefix.is_some() {
format!("{}_", prefix_upper)
} else {
String::new()
};
let prefix_fn = if prefix.is_some() {
format!("{}_", prefix_lower)
} else {
String::new()
};
let mut code = String::new();
code.push_str("// Auto-generated proving key for on-chain verification\n");
if let Some(p) = prefix {
code.push_str(&format!("// Prefix: {}\n", p));
}
code.push_str("// Generated from constraint compilation\n");
code.push_str("// DO NOT EDIT MANUALLY\n");
code.push_str("\n");
code.push_str("#![allow(dead_code)]\n");
code.push_str("\n");
code.push_str("use zyga::{G1Point, G2Point};\n");
code.push_str("\n");
code.push_str(&format!("/// Number of constraints in the system\n"));
code.push_str(&format!("pub const {}NUM_CONSTRAINTS: usize = {};\n", prefix_const, self.num_constraints));
code.push_str("\n");
code.push_str(&format!("/// G1 generator point\n"));
code.push_str(&format!("pub const {}G1_GENERATOR: G1Point = G1Point(\n", prefix_const));
code.push_str(&format!(" {:?}\n", self.g1.to_bytes()));
code.push_str(");\n");
code.push_str("\n");
code.push_str(&format!("/// G2 generator point\n"));
code.push_str(&format!("pub const {}G2_GENERATOR: G2Point = G2Point(\n", prefix_const));
code.push_str(&format!(" {:?}\n", self.g2.to_bytes()));
code.push_str(");\n");
code.push_str("\n");
code.push_str(&format!("/// Trusted setup h1 = g1^alpha\n"));
code.push_str(&format!("pub const {}H1: G1Point = G1Point(\n", prefix_const));
code.push_str(&format!(" {:?}\n", self.h1.to_bytes()));
code.push_str(");\n");
code.push_str("\n");
code.push_str(&format!("/// Trusted setup h2 = g2^beta\n"));
code.push_str(&format!("pub const {}H2: G2Point = G2Point(\n", prefix_const));
code.push_str(&format!(" {:?}\n", self.h2.to_bytes()));
code.push_str(");\n");
code.push_str("\n");
code.push_str(&format!("/// Get proving key elements\n"));
code.push_str(&format!("pub fn get_{}proving_key() -> (G1Point, G2Point, G1Point, G2Point, usize) {{\n", prefix_fn));
code.push_str(&format!(" (\n"));
code.push_str(&format!(" {}G1_GENERATOR,\n", prefix_const));
code.push_str(&format!(" {}G2_GENERATOR,\n", prefix_const));
code.push_str(&format!(" {}H1,\n", prefix_const));
code.push_str(&format!(" {}H2,\n", prefix_const));
code.push_str(&format!(" {}NUM_CONSTRAINTS,\n", prefix_const));
code.push_str(&format!(" )\n"));
code.push_str("}\n");
code
}
}