use ark_bn254::{Bn254, Fr};
use ark_groth16::VerifyingKey;
use ark_serialize::CanonicalSerialize;
use ethabi::{Token, encode};
use primitive_types::U256;
use crate::groth16::{Groth16Error, Groth16Setup};
fn fr_to_u256(fr: &Fr) -> Result<U256, Groth16Error> {
let mut bytes = Vec::new();
fr.serialize_compressed(&mut bytes)
.map_err(|_| Groth16Error::SerializationError)?;
let mut padded = [0u8; 32];
if bytes.len() <= 32 {
padded[32 - bytes.len()..].copy_from_slice(&bytes);
} else {
return Err(Groth16Error::SerializationError);
}
Ok(U256::from_big_endian(&padded))
}
pub fn proof_to_calldata(
proof: &ark_groth16::Proof<Bn254>,
public_inputs: &[Fr],
) -> Result<Vec<u8>, Groth16Error> {
let proof_bytes = Groth16Setup::<Bn254>::proof_to_evm_format(proof)?;
let inputs: Result<Vec<Token>, _> = public_inputs
.iter()
.map(|x| fr_to_u256(x).map(Token::Uint))
.collect();
let inputs = inputs?;
Ok(encode(&[
Token::Bytes(proof_bytes),
Token::Array(inputs),
]))
}
pub fn generate_verifier_contract(vk: &VerifyingKey<Bn254>) -> Result<String, Groth16Error> {
let template = include_str!("../contracts/verifier_template.sol");
let mut vk_bytes = Vec::new();
vk.serialize_compressed(&mut vk_bytes)
.map_err(|_| Groth16Error::SerializationError)?;
Ok(template.replace(
"{{VERIFYING_KEY}}",
&format!("0x{}", hex::encode(&vk_bytes))
))
}