mirror of
https://github.com/zkemail/zk-email-verify.git
synced 2026-01-09 13:38:03 -05:00
feat: groth16 proof verification in rust with sample proof of twitter test
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "ark-verifier"
|
||||
name = "utils"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
@@ -55,4 +55,4 @@ default = ["wasmer/default", "circom-2", "ethereum"]
|
||||
wasm = ["wasmer/js-default"]
|
||||
bench-complex-all = []
|
||||
circom-2 = []
|
||||
ethereum = ["ethers-core"]
|
||||
ethereum = ["ethers-core"]
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
# rust-verifier
|
||||
@@ -1,4 +1,6 @@
|
||||
{
|
||||
"name": "rust-verifier",
|
||||
"packageManager": "yarn@3.2.3"
|
||||
"name": "utils",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "utilities to generating bindings for various proving contexts"
|
||||
}
|
||||
|
||||
1
packages/rust-verifier/src/lib.rs
Normal file
1
packages/rust-verifier/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod verifier;
|
||||
178
packages/rust-verifier/src/verifier.rs
Normal file
178
packages/rust-verifier/src/verifier.rs
Normal file
@@ -0,0 +1,178 @@
|
||||
use ark_bn254::Bn254;
|
||||
use ark_bn254::Config;
|
||||
use ark_bn254::Fq2;
|
||||
use ark_bn254::FrConfig;
|
||||
use ark_bn254::G1Affine;
|
||||
use ark_bn254::G2Affine;
|
||||
|
||||
use ark_circom::CircomReduction;
|
||||
use ark_ec::bn::Bn;
|
||||
use ark_ff::Fp;
|
||||
use ark_ff::MontBackend;
|
||||
use ark_groth16::Groth16;
|
||||
use ark_groth16::Proof;
|
||||
use ark_groth16::VerifyingKey;
|
||||
use serde::Deserialize;
|
||||
use std::fs;
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub type GrothBn = Groth16<Bn254, CircomReduction>;
|
||||
pub type GrothBnProof = Proof<Bn<Config>>;
|
||||
pub type GrothBnVkey = VerifyingKey<Bn254>;
|
||||
pub type GrothFp = Fp<MontBackend<FrConfig, 4>, 4>;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct SnarkJsProof {
|
||||
pi_a: [String; 3],
|
||||
pi_b: [[String; 2]; 3],
|
||||
pi_c: [String; 3],
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct SnarkJsVkey {
|
||||
vk_alpha_1: [String; 3],
|
||||
vk_beta_2: [[String; 2]; 3],
|
||||
vk_gamma_2: [[String; 2]; 3],
|
||||
vk_delta_2: [[String; 2]; 3],
|
||||
IC: Vec<[String; 3]>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PublicInputs<const N: usize> {
|
||||
inputs: [GrothFp; N],
|
||||
}
|
||||
|
||||
pub trait JsonDecoder {
|
||||
fn from_json(json: &str) -> Self;
|
||||
fn from_json_file(file_path: &str) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let json = fs::read_to_string(file_path).unwrap();
|
||||
Self::from_json(&json)
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonDecoder for GrothBnProof {
|
||||
fn from_json(json: &str) -> Self {
|
||||
let snarkjs_proof: SnarkJsProof = serde_json::from_str(json).unwrap();
|
||||
let a = G1Affine {
|
||||
x: Fp::from_str(snarkjs_proof.pi_a[0].as_str()).unwrap(),
|
||||
y: Fp::from_str(snarkjs_proof.pi_a[1].as_str()).unwrap(),
|
||||
infinity: false,
|
||||
};
|
||||
let b = G2Affine {
|
||||
x: Fq2::new(
|
||||
Fp::from_str(snarkjs_proof.pi_b[0][0].as_str()).unwrap(),
|
||||
Fp::from_str(snarkjs_proof.pi_b[0][1].as_str()).unwrap(),
|
||||
),
|
||||
y: Fq2::new(
|
||||
Fp::from_str(snarkjs_proof.pi_b[1][0].as_str()).unwrap(),
|
||||
Fp::from_str(snarkjs_proof.pi_b[1][1].as_str()).unwrap(),
|
||||
),
|
||||
infinity: false,
|
||||
};
|
||||
let c = G1Affine {
|
||||
x: Fp::from_str(snarkjs_proof.pi_c[0].as_str()).unwrap(),
|
||||
y: Fp::from_str(snarkjs_proof.pi_c[1].as_str()).unwrap(),
|
||||
infinity: false,
|
||||
};
|
||||
Proof { a, b, c }
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonDecoder for GrothBnVkey {
|
||||
fn from_json(json: &str) -> Self {
|
||||
let snarkjs_vkey: SnarkJsVkey = serde_json::from_str(json).unwrap();
|
||||
let vk_alpha_1 = G1Affine {
|
||||
x: Fp::from_str(snarkjs_vkey.vk_alpha_1[0].as_str()).unwrap(),
|
||||
y: Fp::from_str(snarkjs_vkey.vk_alpha_1[1].as_str()).unwrap(),
|
||||
infinity: false,
|
||||
};
|
||||
let vk_beta_2 = G2Affine {
|
||||
x: Fq2::new(
|
||||
Fp::from_str(snarkjs_vkey.vk_beta_2[0][0].as_str()).unwrap(),
|
||||
Fp::from_str(snarkjs_vkey.vk_beta_2[0][1].as_str()).unwrap(),
|
||||
),
|
||||
y: Fq2::new(
|
||||
Fp::from_str(snarkjs_vkey.vk_beta_2[1][0].as_str()).unwrap(),
|
||||
Fp::from_str(snarkjs_vkey.vk_beta_2[1][1].as_str()).unwrap(),
|
||||
),
|
||||
infinity: false,
|
||||
};
|
||||
let vk_gamma_2 = G2Affine {
|
||||
x: Fq2::new(
|
||||
Fp::from_str(snarkjs_vkey.vk_gamma_2[0][0].as_str()).unwrap(),
|
||||
Fp::from_str(snarkjs_vkey.vk_gamma_2[0][1].as_str()).unwrap(),
|
||||
),
|
||||
y: Fq2::new(
|
||||
Fp::from_str(snarkjs_vkey.vk_gamma_2[1][0].as_str()).unwrap(),
|
||||
Fp::from_str(snarkjs_vkey.vk_gamma_2[1][1].as_str()).unwrap(),
|
||||
),
|
||||
infinity: false,
|
||||
};
|
||||
let vk_delta_2 = G2Affine {
|
||||
x: Fq2::new(
|
||||
Fp::from_str(snarkjs_vkey.vk_delta_2[0][0].as_str()).unwrap(),
|
||||
Fp::from_str(snarkjs_vkey.vk_delta_2[0][1].as_str()).unwrap(),
|
||||
),
|
||||
y: Fq2::new(
|
||||
Fp::from_str(snarkjs_vkey.vk_delta_2[1][0].as_str()).unwrap(),
|
||||
Fp::from_str(snarkjs_vkey.vk_delta_2[1][1].as_str()).unwrap(),
|
||||
),
|
||||
infinity: false,
|
||||
};
|
||||
|
||||
let ic = snarkjs_vkey
|
||||
.IC
|
||||
.iter()
|
||||
.map(|ic| G1Affine {
|
||||
x: Fp::from_str(ic[0].as_str()).unwrap(),
|
||||
y: Fp::from_str(ic[1].as_str()).unwrap(),
|
||||
infinity: false,
|
||||
})
|
||||
.collect();
|
||||
|
||||
VerifyingKey {
|
||||
alpha_g1: vk_alpha_1,
|
||||
beta_g2: vk_beta_2,
|
||||
gamma_g2: vk_gamma_2,
|
||||
delta_g2: vk_delta_2,
|
||||
gamma_abc_g1: ic,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> JsonDecoder for PublicInputs<N> {
|
||||
fn from_json(json: &str) -> Self {
|
||||
let inputs: Vec<String> = serde_json::from_str(json).unwrap();
|
||||
let inputs: Vec<GrothFp> = inputs
|
||||
.iter()
|
||||
.map(|input| Fp::from_str(input).unwrap())
|
||||
.collect();
|
||||
Self {
|
||||
inputs: inputs.try_into().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> PublicInputs<N> {
|
||||
pub fn from(inputs: [&str; N]) -> Self {
|
||||
let inputs: Vec<GrothFp> = inputs
|
||||
.iter()
|
||||
.map(|input| Fp::from_str(input).unwrap())
|
||||
.collect();
|
||||
Self {
|
||||
inputs: inputs.try_into().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Deref for PublicInputs<N> {
|
||||
type Target = [GrothFp];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inputs
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"pi_a": [
|
||||
"7322653719534980528477944398011016647254113886264496434209142915373719728330",
|
||||
"7628912536907839379514448322649890607492217442803051947968392007164895386635",
|
||||
"1"
|
||||
],
|
||||
"pi_b": [
|
||||
[
|
||||
"16234593703961390420744598781852865663725256239282005257881003391155979508175",
|
||||
"2634938501612343384443797634806019339499759856521176306545002649451701618890"
|
||||
],
|
||||
[
|
||||
"20230573717932313809779793208166930057423046021163352571847229725759748970685",
|
||||
"3400562595023578951323767846410060663270999913751859309274508041293791416795"
|
||||
],
|
||||
["1", "0"]
|
||||
],
|
||||
"pi_c": [
|
||||
"4754500730009341734285764647492628138720619353305414050344261728054146174269",
|
||||
"15456162944887044317047060179938689904460637264071491912107485866386470848896",
|
||||
"1"
|
||||
],
|
||||
"protocol": "groth16",
|
||||
"curve": "bn128"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
[
|
||||
"1983664618407009423875829639306275185491946247764487749439145140682408188330",
|
||||
"131061634216091175196322682",
|
||||
"663497778919717248086462294001838786758809425003"
|
||||
]
|
||||
95
packages/rust-verifier/tests/data/proof_of_twitter/vkey.json
Normal file
95
packages/rust-verifier/tests/data/proof_of_twitter/vkey.json
Normal file
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"protocol": "groth16",
|
||||
"curve": "bn128",
|
||||
"nPublic": 3,
|
||||
"vk_alpha_1": [
|
||||
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
|
||||
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
|
||||
"1"
|
||||
],
|
||||
"vk_beta_2": [
|
||||
[
|
||||
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
|
||||
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
|
||||
],
|
||||
[
|
||||
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
|
||||
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
|
||||
],
|
||||
["1", "0"]
|
||||
],
|
||||
"vk_gamma_2": [
|
||||
[
|
||||
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
|
||||
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
|
||||
],
|
||||
[
|
||||
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
|
||||
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
|
||||
],
|
||||
["1", "0"]
|
||||
],
|
||||
"vk_delta_2": [
|
||||
[
|
||||
"12766874234600095787343990480146022057791723986357917332831399540581276927233",
|
||||
"3971642277770342590957506265349105456434855661397513517213431669169235844045"
|
||||
],
|
||||
[
|
||||
"17019878480168149557284885665446758390388295710404486629277107858448704695435",
|
||||
"8466466441600144089096780116598234208747001808490439031541612931795850272713"
|
||||
],
|
||||
["1", "0"]
|
||||
],
|
||||
"vk_alphabeta_12": [
|
||||
[
|
||||
[
|
||||
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
|
||||
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
|
||||
],
|
||||
[
|
||||
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
|
||||
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
|
||||
],
|
||||
[
|
||||
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
|
||||
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
|
||||
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
|
||||
],
|
||||
[
|
||||
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
|
||||
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
|
||||
],
|
||||
[
|
||||
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
|
||||
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
|
||||
]
|
||||
]
|
||||
],
|
||||
"IC": [
|
||||
[
|
||||
"13455031991578888733674312423967185601946065645222957382145186994616611244362",
|
||||
"14050030878011228297368009518321338442347619972518515173925378569459442994011",
|
||||
"1"
|
||||
],
|
||||
[
|
||||
"17413305859812487897886068173955193240718176224001852027948255829721305653639",
|
||||
"20501940977432443854287668104189155029974249999233988371475203832572003103923",
|
||||
"1"
|
||||
],
|
||||
[
|
||||
"16478835329297149904466221463850128581969676144765895448709484660840830338291",
|
||||
"18378280162143562209519402347714766029351163075742403485652069083748853436468",
|
||||
"1"
|
||||
],
|
||||
[
|
||||
"9167194412515699354423101347633274318437697317154678611069229798965044490452",
|
||||
"14219742127910100142812096423691693747338448854474336725819074409505103543838",
|
||||
"1"
|
||||
]
|
||||
]
|
||||
}
|
||||
15
packages/rust-verifier/tests/verifier.rs
Normal file
15
packages/rust-verifier/tests/verifier.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ark_crypto_primitives::snark::SNARK;
|
||||
use utils::verifier::{GrothBn, GrothBnProof, GrothBnVkey, JsonDecoder, PublicInputs};
|
||||
|
||||
#[test]
|
||||
fn test_case_1_proof_valid() {
|
||||
let vkey = GrothBnVkey::from_json_file("tests/data/proof_of_twitter/vkey.json");
|
||||
let proof = GrothBnProof::from_json_file("tests/data/proof_of_twitter/proof.json");
|
||||
let public_inputs: PublicInputs<3> =
|
||||
PublicInputs::from_json_file("tests/data/proof_of_twitter/public.json");
|
||||
let verified = GrothBn::verify(&vkey, &public_inputs, &proof).unwrap();
|
||||
assert!(verified);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user