Skip to content

Commit 6ef3448

Browse files
ibmp33eigmax
andauthored
chore: add serialization for groth16 (#138)
* chore: add serialization for groth16 * chore: polish code * chore: add serialization for groth16 * chore: add serialization for groth16 --------- Co-authored-by: eigmax <[email protected]>
1 parent e73e67a commit 6ef3448

File tree

12 files changed

+372
-60
lines changed

12 files changed

+372
-60
lines changed

groth16/src/json_utils.rs

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
use crate::bellman_ce::pairing::{bls12_381::Bls12, bn256::Bn256};
2+
use algebraic::{errors::Result, utils::repr_to_big, PrimeField};
3+
use franklin_crypto::bellman::{
4+
bls12_381::{
5+
Fq2 as Fq2_bls12381, G1Affine as G1Affine_bls12381, G2Affine as G2Affine_bls12381,
6+
},
7+
bn256::{Fq2, G1Affine, G2Affine},
8+
groth16::{Proof, VerifyingKey},
9+
CurveAffine,
10+
};
11+
use num_bigint::BigUint;
12+
use num_traits::Num;
13+
use serde::{Deserialize, Serialize};
14+
use serde_json::to_string;
15+
#[derive(Debug, Serialize, Deserialize)]
16+
pub struct G1 {
17+
pub x: String,
18+
pub y: String,
19+
}
20+
21+
#[derive(Debug, Serialize, Deserialize)]
22+
pub struct G2 {
23+
pub x: [String; 2],
24+
pub y: [String; 2],
25+
}
26+
27+
#[derive(Debug, Serialize, Deserialize)]
28+
pub struct VerifyingKeyFile {
29+
#[serde(rename = "protocol")]
30+
pub protocol: String,
31+
#[serde(rename = "curve")]
32+
pub curve: String,
33+
#[serde(rename = "vk_alpha_1")]
34+
pub alpha_g1: G1,
35+
#[serde(rename = "vk_beta_1")]
36+
pub beta_g1: G1,
37+
#[serde(rename = "vk_beta_2")]
38+
pub beta_g2: G2,
39+
#[serde(rename = "vk_gamma_2")]
40+
pub gamma_g2: G2,
41+
#[serde(rename = "vk_delta_1")]
42+
pub delta_g1: G1,
43+
#[serde(rename = "vk_delta_2")]
44+
pub delta_g2: G2,
45+
#[serde(rename = "IC")]
46+
pub ic: Vec<G1>,
47+
}
48+
49+
#[derive(Debug, Serialize, Deserialize)]
50+
pub struct ProofFile {
51+
#[serde(rename = "pi_a")]
52+
pub a: G1,
53+
#[serde(rename = "pi_b")]
54+
pub b: G2,
55+
#[serde(rename = "pi_c")]
56+
pub c: G1,
57+
#[serde(rename = "protocol")]
58+
pub protocol: String,
59+
#[serde(rename = "curve")]
60+
pub curve: String,
61+
}
62+
63+
pub trait Parser: franklin_crypto::bellman::pairing::Engine {
64+
fn parse_g1(e: &Self::G1Affine, to_hex: bool) -> (String, String);
65+
fn parse_g2(e: &Self::G2Affine, to_hex: bool) -> (String, String, String, String);
66+
fn parse_g1_json(e: &Self::G1Affine, to_hex: bool) -> G1 {
67+
let parsed = Self::parse_g1(e, to_hex);
68+
G1 {
69+
x: parsed.0,
70+
y: parsed.1,
71+
}
72+
}
73+
fn parse_g2_json(e: &Self::G2Affine, to_hex: bool) -> G2 {
74+
let parsed = Self::parse_g2(e, to_hex);
75+
G2 {
76+
x: (parsed.0, parsed.1).into(),
77+
y: (parsed.2, parsed.3).into(),
78+
}
79+
}
80+
fn to_g1(x: &str, y: &str) -> Self::G1Affine;
81+
fn to_g2(x0: &str, x1: &str, y0: &str, y1: &str) -> Self::G2Affine;
82+
}
83+
84+
pub fn render_scalar_to_str<F: PrimeField>(el: &F, to_hex: bool) -> String {
85+
let repr = el.into_repr();
86+
if to_hex {
87+
repr.to_string()
88+
} else {
89+
repr_to_big(repr)
90+
}
91+
}
92+
93+
pub fn render_str_to_scalar<F: PrimeField>(value: &str) -> F {
94+
let value = match value.starts_with("0x") {
95+
true => BigUint::from_str_radix(&value[2..], 16)
96+
.unwrap()
97+
.to_str_radix(10),
98+
_ => value.to_string(),
99+
};
100+
F::from_str(&value).unwrap()
101+
}
102+
103+
pub fn to_public_input<T: PrimeField>(s: &str) -> Vec<T> {
104+
let input: Vec<String> = serde_json::from_str(s).unwrap();
105+
input
106+
.iter()
107+
.map(|hex_str| render_str_to_scalar::<T>(hex_str))
108+
.collect()
109+
}
110+
111+
impl Parser for Bn256 {
112+
fn parse_g1(e: &Self::G1Affine, to_hex: bool) -> (String, String) {
113+
let (x, y) = e.into_xy_unchecked();
114+
(
115+
render_scalar_to_str(&x, to_hex),
116+
render_scalar_to_str(&y, to_hex),
117+
)
118+
}
119+
120+
fn parse_g2(e: &Self::G2Affine, to_hex: bool) -> (String, String, String, String) {
121+
let (x, y) = e.into_xy_unchecked();
122+
(
123+
render_scalar_to_str(&x.c0, to_hex),
124+
render_scalar_to_str(&x.c1, to_hex),
125+
render_scalar_to_str(&y.c0, to_hex),
126+
render_scalar_to_str(&y.c1, to_hex),
127+
)
128+
}
129+
130+
fn to_g1(x: &str, y: &str) -> Self::G1Affine {
131+
G1Affine::from_xy_unchecked(render_str_to_scalar(x), render_str_to_scalar(y))
132+
}
133+
134+
fn to_g2(x0: &str, x1: &str, y0: &str, y1: &str) -> Self::G2Affine {
135+
let x = Fq2 {
136+
c0: render_str_to_scalar(x0),
137+
c1: render_str_to_scalar(x1),
138+
};
139+
let y = Fq2 {
140+
c0: render_str_to_scalar(y0),
141+
c1: render_str_to_scalar(y1),
142+
};
143+
G2Affine::from_xy_unchecked(x, y)
144+
}
145+
}
146+
147+
impl Parser for Bls12 {
148+
fn parse_g1(e: &Self::G1Affine, to_hex: bool) -> (String, String) {
149+
let (x, y) = e.into_xy_unchecked();
150+
(
151+
render_scalar_to_str(&x, to_hex),
152+
render_scalar_to_str(&y, to_hex),
153+
)
154+
}
155+
156+
fn parse_g2(e: &Self::G2Affine, to_hex: bool) -> (String, String, String, String) {
157+
let (x, y) = e.into_xy_unchecked();
158+
(
159+
render_scalar_to_str(&x.c0, to_hex),
160+
render_scalar_to_str(&x.c1, to_hex),
161+
render_scalar_to_str(&y.c0, to_hex),
162+
render_scalar_to_str(&y.c1, to_hex),
163+
)
164+
}
165+
166+
fn to_g1(x: &str, y: &str) -> Self::G1Affine {
167+
G1Affine_bls12381::from_xy_unchecked(render_str_to_scalar(x), render_str_to_scalar(y))
168+
}
169+
170+
fn to_g2(x0: &str, x1: &str, y0: &str, y1: &str) -> Self::G2Affine {
171+
let x = Fq2_bls12381 {
172+
c0: render_str_to_scalar(x0),
173+
c1: render_str_to_scalar(x1),
174+
};
175+
let y = Fq2_bls12381 {
176+
c0: render_str_to_scalar(y0),
177+
c1: render_str_to_scalar(y1),
178+
};
179+
G2Affine_bls12381::from_xy_unchecked(x, y)
180+
}
181+
}
182+
183+
pub fn serialize_vk<P: Parser>(
184+
vk: &VerifyingKey<P>,
185+
curve_type: &str,
186+
to_hex: bool,
187+
) -> Result<String> {
188+
let verifying_key_file = VerifyingKeyFile {
189+
protocol: "groth16".to_string(),
190+
curve: curve_type.to_string(),
191+
alpha_g1: P::parse_g1_json(&vk.alpha_g1, to_hex),
192+
beta_g1: P::parse_g1_json(&vk.beta_g1, to_hex),
193+
beta_g2: P::parse_g2_json(&vk.beta_g2, to_hex),
194+
gamma_g2: P::parse_g2_json(&vk.gamma_g2, to_hex),
195+
delta_g1: P::parse_g1_json(&vk.delta_g1, to_hex),
196+
delta_g2: P::parse_g2_json(&vk.delta_g2, to_hex),
197+
ic: vk
198+
.ic
199+
.iter()
200+
.map(|e| P::parse_g1_json(e, to_hex))
201+
.collect::<Vec<_>>(),
202+
};
203+
204+
Ok(to_string(&verifying_key_file)?)
205+
}
206+
207+
pub fn serialize_proof<P: Parser>(p: &Proof<P>, curve_type: &str, to_hex: bool) -> Result<String> {
208+
let proof_file = ProofFile {
209+
a: P::parse_g1_json(&p.a, to_hex),
210+
b: P::parse_g2_json(&p.b, to_hex),
211+
c: P::parse_g1_json(&p.c, to_hex),
212+
protocol: "groth16".to_string(),
213+
curve: curve_type.to_string(),
214+
};
215+
216+
Ok(to_string(&proof_file)?)
217+
}
218+
219+
pub fn to_verification_key<P: Parser>(s: &str) -> VerifyingKey<P> {
220+
let vk_file: VerifyingKeyFile =
221+
serde_json::from_str(s).expect("Error during deserialization of the JSON data");
222+
223+
let convert_g1 = |point: &G1| P::to_g1(&point.x, &point.y);
224+
let convert_g2 = |point: &G2| P::to_g2(&point.x[0], &point.x[1], &point.y[0], &point.y[1]);
225+
226+
VerifyingKey {
227+
alpha_g1: convert_g1(&vk_file.alpha_g1),
228+
beta_g1: convert_g1(&vk_file.beta_g1),
229+
beta_g2: convert_g2(&vk_file.beta_g2),
230+
gamma_g2: convert_g2(&vk_file.gamma_g2),
231+
delta_g1: convert_g1(&vk_file.delta_g1),
232+
delta_g2: convert_g2(&vk_file.delta_g2),
233+
ic: vk_file.ic.iter().map(convert_g1).collect(),
234+
}
235+
}
236+
237+
pub fn to_proof<P: Parser>(s: &str) -> Proof<P> {
238+
let proof: ProofFile =
239+
serde_json::from_str(s).expect("Error during deserialization of the JSON data");
240+
241+
let convert_g1 = |point: &G1| P::to_g1(&point.x, &point.y);
242+
let convert_g2 = |point: &G2| P::to_g2(&point.x[0], &point.x[1], &point.y[0], &point.y[1]);
243+
244+
Proof {
245+
a: convert_g1(&proof.a),
246+
b: convert_g2(&proof.b),
247+
c: convert_g1(&proof.c),
248+
}
249+
}
250+
251+
#[cfg(test)]
252+
mod tests {
253+
use super::*;
254+
use crate::bellman_ce::groth16::{Proof, VerifyingKey};
255+
use crate::bellman_ce::pairing::{bls12_381::Bls12, bn256::Bn256};
256+
257+
#[test]
258+
fn test_serialize_vk() {
259+
let mut reader = std::io::BufReader::with_capacity(
260+
1 << 24,
261+
std::fs::File::open("./test-vectors/verification_key.bin").unwrap(),
262+
);
263+
let vk_from_bin = VerifyingKey::<Bn256>::read(&mut reader).unwrap();
264+
let result = serialize_vk(&vk_from_bin, "bn128", false).unwrap();
265+
std::fs::write("./test-vectors/verification_key.json", result)
266+
.expect("Unable to write data to file");
267+
268+
let json_data = std::fs::read_to_string("./test-vectors/verification_key.json")
269+
.expect("Unable to read the JSON file");
270+
let verifying_key_from_json = to_verification_key::<Bn256>(&json_data);
271+
assert_eq!(
272+
vk_from_bin.alpha_g1, verifying_key_from_json.alpha_g1,
273+
"VerificationKey are not equal"
274+
);
275+
}
276+
277+
#[test]
278+
fn test_serialize_vk_bls12381() {
279+
let mut reader = std::io::BufReader::with_capacity(
280+
1 << 24,
281+
std::fs::File::open("./test-vectors/verification_key_bls12381.bin").unwrap(),
282+
);
283+
let vk_from_bin = VerifyingKey::<Bls12>::read(&mut reader).unwrap();
284+
let result = serialize_vk(&vk_from_bin, "bls12381", false).unwrap();
285+
std::fs::write("./test-vectors/verification_key_bls12381.json", result)
286+
.expect("Unable to write data to file");
287+
let json_data = std::fs::read_to_string("./test-vectors/verification_key_bls12381.json")
288+
.expect("Unable to read the JSON file");
289+
let verifying_key_from_json = to_verification_key::<Bls12>(&json_data);
290+
assert_eq!(
291+
vk_from_bin.alpha_g1, verifying_key_from_json.alpha_g1,
292+
"VerificationKey are not equal"
293+
);
294+
}
295+
296+
#[test]
297+
fn test_serialize_proof() {
298+
let mut reader = std::io::BufReader::with_capacity(
299+
1 << 24,
300+
std::fs::File::open("./test-vectors/proof.bin").unwrap(),
301+
);
302+
let proof_from_bin = Proof::<Bn256>::read(&mut reader).unwrap();
303+
let result = serialize_proof(&proof_from_bin, "bn128", false).unwrap();
304+
std::fs::write("./test-vectors/proof.json", result).expect("Unable to write data to file");
305+
306+
let json_data = std::fs::read_to_string("./test-vectors/proof.json")
307+
.expect("Unable to read the JSON file");
308+
let proof_from_json = to_proof::<Bn256>(&json_data);
309+
assert_eq!(proof_from_bin.a, proof_from_json.a, "Proofs are not equal");
310+
}
311+
}

groth16/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod groth16;
2+
pub mod json_utils;
23

34
pub use bellman_ce::pairing::ff;
45
pub use ff::*;

groth16/test-vectors/proof.bin

128 Bytes
Binary file not shown.

groth16/test-vectors/proof.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"pi_a":{"x":"10905341685980874274150221450276555823153279022700815280793205712816544225051","y":"10202155762379182936716953236062961626111732205204299178900872478241297946341"},"pi_b":{"x":["1338445498107572340294993867641202566445851700348442510708274879828386296282","715960249206585599344782789507515384598794467188122779860104990233191718584"],"y":["16749821406279319102006597546165006262150274190725700131363414987974746028898","4186519700035121793525434458515698877463328002407700453041197661949232606762"]},"pi_c":{"x":"21017091347701602277900775955620322776855583460036942304761972046181453833874","y":"13183116007711244014066089262312410303264724202350283300596105680198265390734"},"protocol":"groth16","curve":"bn128"}
708 Bytes
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"protocol":"groth16","curve":"bn128","vk_alpha_1":{"x":"5378666516679669030426253968554722017719204687506819500965191266972562704525","y":"11884127121600853383848213410541219000373777032449499459372628160563826160039"},"vk_beta_1":{"x":"11684926244523749803851436242880351598197401371414225641974167140429606592706","y":"16929741286104563251662568285622534504771343461093856493500590131159047726674"},"vk_beta_2":{"x":["3487033620976845212768103502495007972626150366523406838795608631173434737356","5722453597903794095057921124370073800968815052755180529625796448994959984379"],"y":["10903882886964858379024201093448298739802694041860707200919674705989363314697","13121135188883029175353353776774109279263558732251317411918854951587326451735"]},"vk_gamma_2":{"x":["10213376432339522327829270688979960667935166343925601749766190111213394028579","17878044364476259799411369024855905578579397570653322697041079920852293597018"],"y":["20127734937439354211605145692590108235858989985838133242865379337617277275201","16860366311030991434038951462895802172998962572015514313248458815738807835634"]},"vk_delta_1":{"x":"11812580675586360757509872483306998764270512859221872980162793084480574560007","y":"21631419003837427833755878016845991558820802094484003868757988133232300441323"},"vk_delta_2":{"x":["6392557126586047144123406811983722596643451132034573614997156650191062598459","13326523838708768392335568403673707724254513697314159846597127929687821406612"],"y":["17825290610532104898185648118085521929233132742972425269063635507516756760769","6800237991919287561797152453815129982788413863096002348269331496269366578862"]},"IC":[{"x":"929659533577207043539024015274672310073216612286646842606094101149765235360","y":"335827419452857986330203550224315599249726626406860618832604249213328631746"},{"x":"2686363498352366646252820900835025101354155989284038507478384410495100388581","y":"17555345507164622027374051645603070383629353375584143931251068248182858903287"}]}
1.04 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"protocol":"groth16","curve":"bls12381","vk_alpha_1":{"x":"3993993345820571719409140484493424675806554242871959810886408554601873918255137944101466903763679670262494407588537","y":"434040191028241100687156977701140181479584201136732810220853872204863441112594390241186214510334608184265116445585"},"vk_beta_1":{"x":"2658522315457059457702685926363609046135741594849552828870486944934279944961141450275825340584526857894276358305115","y":"2582005838098837795547524323127572178802259771861368949407021843932842062429470660339994124417267958467089029228208"},"vk_beta_2":{"x":["1939783643649439894411954639292380480325083064066514758489839949576264033790832222199855423207096319681311897764661","1706194026621083356193355989930697019816904718521063732670105129169394895826011607869652463796292903452110365836723"],"y":["2882059267594982145074446435968797036465922412810323976718195308381780496019512186549577150692215060085753645010613","136198744093121836373741155654870641457272202521015181684471622593886579271321371534413401906554696076306020983958"]},"vk_gamma_2":{"x":["883915147635496103065751910712693603416723586016635604322525380426346448467883988595045708410728643160808643307430","1403820781454575035887906376249698826847651524198721302059624628291164223855649425766388826978966815093121313704809"],"y":["3002767327899819554500200115686041250208298181561565918092043416357118574931590689217528083797982832546853161584202","2001179570787517787359145767693379279385541335622939643917241121822169717089689603171961190522553496833471813324630"]},"vk_delta_1":{"x":"1659961497396109626535052665703152028851925462843715619157065076818222268573743565376319420514796164275962013421560","y":"852108729501396447916216038007962962005725557350906076014199487385922217793757155770200106463874358957413139350609"},"vk_delta_2":{"x":["534020031473045642447278438034060292849838077327028015479069546006573823597593395712527205544556207541519503017828","2064747110497790950196077674120447901647089566913002796494296878869005423506584862817520132699626632921133930942162"],"y":["2967133054993642220270835199995585185539112985976514656438629952937248710482231341340574558822407593019383656325111","654893707336486517882533615152317327607862814027749808270768166648386292824429047505275119004528430330592501340375"]},"IC":[{"x":"3215149929540148867769058662590920228610393374201602848716041633020131250087002322681572748299373984475422616855135","y":"3287151148859427866027955777219844883556867208103719288841952355852695402988828398896226297623292986657704831321769"},{"x":"3101785521102172703202926785964685464915214511035452729284362122343456680282492999444404249489107531306726342138515","y":"3640628316062820719549136473192443101956906663205310473213544832255230166150243209243419141396800629848515623269532"}]}

starky/src/starkinfo_map.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,6 @@ impl StarkInfo {
194194
self.map_sections.cm3_2ns.push(ppz_2ns);
195195
pil.cm_dims[self.n_cm1 + self.n_cm2 + i] = dim;
196196
self.exp2pol.insert(self.im_exps_list[i], ppz_n);
197-
log::debug!("5 exp2pol {:?}", self.exp2pol)
198197
}
199198

200199
self.q_dim = Self::get_exp_dim(pil, &pil.expressions[self.c_exp]);

test/snark_verifier.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,15 @@ if [ $snark_type = "groth16" ]; then
5353
fi
5454

5555
if [ $first_run = "true" ]; then
56-
$ZKIT groth16_setup -c $CURVE --r1cs $WORK_DIR/$CIRCUIT_NAME.r1cs -p $WORK_DIR/g16.zkey -v $WORK_DIR/verification_key.bin
56+
$ZKIT groth16_setup -c $CURVE --r1cs $WORK_DIR/$CIRCUIT_NAME.r1cs -p $WORK_DIR/g16.zkey -v $WORK_DIR/verification_key.json
5757
fi
5858

5959
echo "2. groth16 fullprove"
60-
$ZKIT groth16_prove -c $CURVE --r1cs $WORK_DIR/$CIRCUIT_NAME.r1cs -w $WORK_DIR/$CIRCUIT_NAME"_js"/$CIRCUIT_NAME.wasm -p $WORK_DIR/g16.zkey -i $SNARK_INPUT --input $WORK_DIR/public_input.bin --proof $WORK_DIR/proof.bin
60+
$ZKIT groth16_prove -c $CURVE --r1cs $WORK_DIR/$CIRCUIT_NAME.r1cs -w $WORK_DIR/$CIRCUIT_NAME"_js"/$CIRCUIT_NAME.wasm -p $WORK_DIR/g16.zkey -i $SNARK_INPUT --public-input $WORK_DIR/public_input.json --proof $WORK_DIR/proof.json
6161

6262
if [ $first_run = "true" ]; then
6363
echo "4. verify groth16 proof"
64-
$ZKIT groth16_verify -c $CURVE -v $WORK_DIR/verification_key.bin --input $WORK_DIR/public_input.bin --proof $WORK_DIR/proof.bin
64+
$ZKIT groth16_verify -c $CURVE -v $WORK_DIR/verification_key.json --public-input $WORK_DIR/public_input.json --proof $WORK_DIR/proof.json
6565

6666
# TODO: add g16 solidity verifier
6767
#if [ $CURVE = "bn128" ]; then

0 commit comments

Comments
 (0)