circom-compat/src/zkey.rs
src/zkey.rsRaw
1//! ZKey Parsing
2//!
3//! Each ZKey file is broken into sections:
4//! Header(1)
5//! Prover Type 1 Groth
6//! HeaderGroth(2)
7//! n8q
8//! q
9//! n8r
10//! r
11//! NVars
12//! NPub
13//! DomainSize (multiple of 2
14//! alpha1
15//! beta1
16//! delta1
17//! beta2
18//! gamma2
19//! delta2
20//! IC(3)
21//! Coefs(4)
22//! PointsA(5)
23//! PointsB1(6)
24//! PointsB2(7)
25//! PointsC(8)
26//! PointsH(9)
27//! Contributions(10)
28use ark_ff::{BigInteger256, FromBytes};
29use ark_serialize::{CanonicalDeserialize, SerializationError};
30use ark_std::log2;
31use byteorder::{LittleEndian, ReadBytesExt};
32
33use std::{
34 collections::HashMap,
35 io::{Read, Result as IoResult, Seek, SeekFrom},
36};
37
38use ark_bn254::{Bn254, Fq, Fq2, G1Affine, G2Affine};
39use ark_groth16::{ProvingKey, VerifyingKey};
40use num_traits::Zero;
41
42#[derive(Clone, Debug)]
43struct Section {
44 position: u64,
45 size: usize,
46}
47
48/// Reads a SnarkJS ZKey file into an Arkworks ProvingKey.
49pub fn read_zkey<R: Read + Seek>(reader: &mut R) -> IoResult<ProvingKey<Bn254>> {
50 let mut binfile = BinFile::new(reader)?;
51 binfile.proving_key()
52}
53
54#[derive(Debug)]
55struct BinFile<'a, R> {
56 ftype: String,
57 version: u32,
58 sections: HashMap<u32, Vec<Section>>,
59 reader: &'a mut R,
60}
61
62impl<'a, R: Read + Seek> BinFile<'a, R> {
63 fn new(reader: &'a mut R) -> IoResult<Self> {
64 let mut magic = [0u8; 4];
65 reader.read_exact(&mut magic)?;
66
67 let version = reader.read_u32::<LittleEndian>()?;
68
69 let num_sections = reader.read_u32::<LittleEndian>()?;
70
71 let mut sections = HashMap::new();
72 for _ in 0..num_sections {
73 let section_id = reader.read_u32::<LittleEndian>()?;
74 let section_length = reader.read_u64::<LittleEndian>()?;
75
76 let section = sections.entry(section_id).or_insert_with(Vec::new);
77 section.push(Section {
78 position: reader.stream_position()?,
79 size: section_length as usize,
80 });
81
82 reader.seek(SeekFrom::Current(section_length as i64))?;
83 }
84
85 Ok(Self {
86 ftype: std::str::from_utf8(&magic[..]).unwrap().to_string(),
87 version,
88 sections,
89 reader,
90 })
91 }
92
93 fn proving_key(&mut self) -> IoResult<ProvingKey<Bn254>> {
94 let header = self.groth_header()?;
95 let ic = self.ic(header.n_public)?;
96
97 let a_query = self.a_query(header.n_vars)?;
98 let b_g1_query = self.b_g1_query(header.n_vars)?;
99 let b_g2_query = self.b_g2_query(header.n_vars)?;
100 let l_query = self.l_query(header.n_vars - header.n_public - 1)?;
101 let h_query = self.h_query(header.domain_size as usize)?;
102
103 let vk = VerifyingKey::<Bn254> {
104 alpha_g1: header.verifying_key.alpha_g1,
105 beta_g2: header.verifying_key.beta_g2,
106 gamma_g2: header.verifying_key.gamma_g2,
107 delta_g2: header.verifying_key.delta_g2,
108 gamma_abc_g1: ic,
109 };
110
111 let pk = ProvingKey::<Bn254> {
112 vk,
113 beta_g1: header.verifying_key.beta_g1,
114 delta_g1: header.verifying_key.delta_g1,
115 a_query,
116 b_g1_query,
117 b_g2_query,
118 h_query,
119 l_query,
120 };
121
122 Ok(pk)
123 }
124
125 fn get_section(&self, id: u32) -> Section {
126 self.sections.get(&id).unwrap()[0].clone()
127 }
128
129 fn groth_header(&mut self) -> IoResult<HeaderGroth> {
130 let section = self.get_section(2);
131 let header = HeaderGroth::new(&mut self.reader, §ion)?;
132 Ok(header)
133 }
134
135 fn ic(&mut self, n_public: usize) -> IoResult<Vec<G1Affine>> {
136 // the range is non-inclusive so we do +1 to get all inputs
137 self.g1_section(n_public + 1, 3)
138 }
139
140 // Section 4 is the coefficients, we ignore it
141
142 fn a_query(&mut self, n_vars: usize) -> IoResult<Vec<G1Affine>> {
143 self.g1_section(n_vars, 5)
144 }
145
146 fn b_g1_query(&mut self, n_vars: usize) -> IoResult<Vec<G1Affine>> {
147 self.g1_section(n_vars, 6)
148 }
149
150 fn b_g2_query(&mut self, n_vars: usize) -> IoResult<Vec<G2Affine>> {
151 self.g2_section(n_vars, 7)
152 }
153
154 fn l_query(&mut self, n_vars: usize) -> IoResult<Vec<G1Affine>> {
155 self.g1_section(n_vars, 8)
156 }
157
158 fn h_query(&mut self, n_vars: usize) -> IoResult<Vec<G1Affine>> {
159 self.g1_section(n_vars, 9)
160 }
161
162 fn g1_section(&mut self, num: usize, section_id: usize) -> IoResult<Vec<G1Affine>> {
163 let section = self.get_section(section_id as u32);
164 self.reader.seek(SeekFrom::Start(section.position))?;
165 deserialize_g1_vec(self.reader, num as u32)
166 }
167
168 fn g2_section(&mut self, num: usize, section_id: usize) -> IoResult<Vec<G2Affine>> {
169 let section = self.get_section(section_id as u32);
170 self.reader.seek(SeekFrom::Start(section.position))?;
171 deserialize_g2_vec(self.reader, num as u32)
172 }
173}
174
175#[derive(Default, Clone, Debug, CanonicalDeserialize)]
176pub struct ZVerifyingKey {
177 alpha_g1: G1Affine,
178 beta_g1: G1Affine,
179 beta_g2: G2Affine,
180 gamma_g2: G2Affine,
181 delta_g1: G1Affine,
182 delta_g2: G2Affine,
183}
184
185impl ZVerifyingKey {
186 fn new<R: Read>(reader: &mut R) -> IoResult<Self> {
187 let alpha_g1 = deserialize_g1(reader)?;
188 let beta_g1 = deserialize_g1(reader)?;
189 let beta_g2 = deserialize_g2(reader)?;
190 let gamma_g2 = deserialize_g2(reader)?;
191 let delta_g1 = deserialize_g1(reader)?;
192 let delta_g2 = deserialize_g2(reader)?;
193
194 Ok(Self {
195 alpha_g1,
196 beta_g1,
197 beta_g2,
198 gamma_g2,
199 delta_g1,
200 delta_g2,
201 })
202 }
203}
204
205#[derive(Clone, Debug)]
206struct HeaderGroth {
207 n8q: u32,
208 q: BigInteger256,
209
210 n8r: u32,
211 r: BigInteger256,
212
213 n_vars: usize,
214 n_public: usize,
215
216 domain_size: u32,
217 power: u32,
218
219 verifying_key: ZVerifyingKey,
220}
221
222impl HeaderGroth {
223 fn new<R: Read + Seek>(reader: &mut R, section: &Section) -> IoResult<Self> {
224 reader.seek(SeekFrom::Start(section.position))?;
225 Self::read(reader)
226 }
227
228 fn read<R: Read>(mut reader: &mut R) -> IoResult<Self> {
229 // TODO: Impl From<u32> in Arkworks
230 let n8q: u32 = FromBytes::read(&mut reader)?;
231 // group order r of Bn254
232 let q = BigInteger256::read(&mut reader)?;
233
234 let n8r: u32 = FromBytes::read(&mut reader)?;
235 // Prime field modulus
236 let r = BigInteger256::read(&mut reader)?;
237
238 let n_vars = u32::read(&mut reader)? as usize;
239 let n_public = u32::read(&mut reader)? as usize;
240
241 let domain_size: u32 = FromBytes::read(&mut reader)?;
242 let power = log2(domain_size as usize);
243
244 let verifying_key = ZVerifyingKey::new(&mut reader)?;
245
246 Ok(Self {
247 n8q,
248 q,
249 n8r,
250 r,
251 n_vars,
252 n_public,
253 domain_size,
254 power,
255 verifying_key,
256 })
257 }
258}
259
260// skips the multiplication by R because Circom points are already in Montgomery form
261fn deserialize_field<R: Read>(reader: &mut R) -> IoResult<Fq> {
262 let bigint = BigInteger256::read(reader)?;
263 // if you use ark_ff::PrimeField::from_repr it multiplies by R
264 Ok(Fq::new(bigint))
265}
266
267pub fn deserialize_field2<R: Read>(reader: &mut R) -> IoResult<Fq2> {
268 let c0 = deserialize_field(reader)?;
269 let c1 = deserialize_field(reader)?;
270 Ok(Fq2::new(c0, c1))
271}
272
273fn deserialize_g1<R: Read>(reader: &mut R) -> IoResult<G1Affine> {
274 let x = deserialize_field(reader)?;
275 let y = deserialize_field(reader)?;
276 let infinity = x.is_zero() && y.is_zero();
277 Ok(G1Affine::new(x, y, infinity))
278}
279
280fn deserialize_g2<R: Read>(reader: &mut R) -> IoResult<G2Affine> {
281 let f1 = deserialize_field2(reader)?;
282 let f2 = deserialize_field2(reader)?;
283 let infinity = f1.is_zero() && f2.is_zero();
284 Ok(G2Affine::new(f1, f2, infinity))
285}
286
287fn deserialize_g1_vec<R: Read>(reader: &mut R, n_vars: u32) -> IoResult<Vec<G1Affine>> {
288 (0..n_vars).map(|_| deserialize_g1(reader)).collect()
289}
290
291fn deserialize_g2_vec<R: Read>(reader: &mut R, n_vars: u32) -> IoResult<Vec<G2Affine>> {
292 (0..n_vars).map(|_| deserialize_g2(reader)).collect()
293}
294
295#[cfg(test)]
296mod tests {
297 use super::*;
298 use ark_bn254::{G1Projective, G2Projective};
299 use num_bigint::BigUint;
300 use serde_json::Value;
301 use std::fs::File;
302
303 use crate::{circom::CircomReduction, CircomBuilder, CircomConfig};
304 use ark_groth16::{
305 create_random_proof_with_reduction as prove, prepare_verifying_key, verify_proof,
306 };
307 use ark_std::rand::thread_rng;
308 use num_traits::{One, Zero};
309 use std::str::FromStr;
310
311 use std::convert::TryFrom;
312
313 fn fq_from_str(s: &str) -> Fq {
314 BigInteger256::try_from(BigUint::from_str(s).unwrap())
315 .unwrap()
316 .into()
317 }
318
319 // Circom snarkjs code:
320 // console.log(curve.G1.F.one)
321 fn fq_buf() -> Vec<u8> {
322 vec![
323 157, 13, 143, 197, 141, 67, 93, 211, 61, 11, 199, 245, 40, 235, 120, 10, 44, 70, 121,
324 120, 111, 163, 110, 102, 47, 223, 7, 154, 193, 119, 10, 14,
325 ]
326 }
327
328 // Circom snarkjs code:
329 // const buff = new Uint8Array(curve.G1.F.n8*2);
330 // curve.G1.toRprLEM(buff, 0, curve.G1.one);
331 // console.dir( buff, { 'maxArrayLength': null })
332 fn g1_buf() -> Vec<u8> {
333 vec![
334 157, 13, 143, 197, 141, 67, 93, 211, 61, 11, 199, 245, 40, 235, 120, 10, 44, 70, 121,
335 120, 111, 163, 110, 102, 47, 223, 7, 154, 193, 119, 10, 14, 58, 27, 30, 139, 27, 135,
336 186, 166, 123, 22, 142, 235, 81, 214, 241, 20, 88, 140, 242, 240, 222, 70, 221, 204,
337 94, 190, 15, 52, 131, 239, 20, 28,
338 ]
339 }
340
341 // Circom snarkjs code:
342 // const buff = new Uint8Array(curve.G2.F.n8*2);
343 // curve.G2.toRprLEM(buff, 0, curve.G2.one);
344 // console.dir( buff, { 'maxArrayLength': null })
345 fn g2_buf() -> Vec<u8> {
346 vec![
347 38, 32, 188, 2, 209, 181, 131, 142, 114, 1, 123, 73, 53, 25, 235, 220, 223, 26, 129,
348 151, 71, 38, 184, 251, 59, 80, 150, 175, 65, 56, 87, 25, 64, 97, 76, 168, 125, 115,
349 180, 175, 196, 216, 2, 88, 90, 221, 67, 96, 134, 47, 160, 82, 252, 80, 233, 9, 107,
350 123, 234, 58, 131, 240, 254, 20, 246, 233, 107, 136, 157, 250, 157, 97, 120, 155, 158,
351 245, 151, 210, 127, 254, 254, 125, 27, 35, 98, 26, 158, 255, 6, 66, 158, 174, 235, 126,
352 253, 40, 238, 86, 24, 199, 86, 91, 9, 100, 187, 60, 125, 50, 34, 249, 87, 220, 118, 16,
353 53, 51, 190, 53, 249, 85, 130, 100, 253, 147, 230, 160, 164, 13,
354 ]
355 }
356
357 // Circom logs in Projective coordinates: console.log(curve.G1.one)
358 fn g1_one() -> G1Affine {
359 let x = Fq::one();
360 let y = Fq::one() + Fq::one();
361 let z = Fq::one();
362 G1Affine::from(G1Projective::new(x, y, z))
363 }
364
365 // Circom logs in Projective coordinates: console.log(curve.G2.one)
366 fn g2_one() -> G2Affine {
367 let x = Fq2::new(
368 fq_from_str(
369 "10857046999023057135944570762232829481370756359578518086990519993285655852781",
370 ),
371 fq_from_str(
372 "11559732032986387107991004021392285783925812861821192530917403151452391805634",
373 ),
374 );
375
376 let y = Fq2::new(
377 fq_from_str(
378 "8495653923123431417604973247489272438418190587263600148770280649306958101930",
379 ),
380 fq_from_str(
381 "4082367875863433681332203403145435568316851327593401208105741076214120093531",
382 ),
383 );
384 let z = Fq2::new(Fq::one(), Fq::zero());
385 G2Affine::from(G2Projective::new(x, y, z))
386 }
387
388 #[test]
389 fn can_deser_fq() {
390 let buf = fq_buf();
391 let fq = deserialize_field(&mut &buf[..]).unwrap();
392 assert_eq!(fq, Fq::one());
393 }
394
395 #[test]
396 fn can_deser_g1() {
397 let buf = g1_buf();
398 assert_eq!(buf.len(), 64);
399 let g1 = deserialize_g1(&mut &buf[..]).unwrap();
400 let expected = g1_one();
401 assert_eq!(g1, expected);
402 }
403
404 #[test]
405 fn can_deser_g1_vec() {
406 let n_vars = 10;
407 let buf = vec![g1_buf(); n_vars]
408 .iter()
409 .cloned()
410 .flatten()
411 .collect::<Vec<_>>();
412 let expected = vec![g1_one(); n_vars];
413
414 let de = deserialize_g1_vec(&mut &buf[..], n_vars as u32).unwrap();
415 assert_eq!(expected, de);
416 }
417
418 #[test]
419 fn can_deser_g2() {
420 let buf = g2_buf();
421 assert_eq!(buf.len(), 128);
422 let g2 = deserialize_g2(&mut &buf[..]).unwrap();
423
424 let expected = g2_one();
425 assert_eq!(g2, expected);
426 }
427
428 #[test]
429 fn can_deser_g2_vec() {
430 let n_vars = 10;
431 let buf = vec![g2_buf(); n_vars]
432 .iter()
433 .cloned()
434 .flatten()
435 .collect::<Vec<_>>();
436 let expected = vec![g2_one(); n_vars];
437
438 let de = deserialize_g2_vec(&mut &buf[..], n_vars as u32).unwrap();
439 assert_eq!(expected, de);
440 }
441
442 #[test]
443 fn header() {
444 // `circom --r1cs` using the below file:
445 //
446 // template Multiplier() {
447 // signal private input a;
448 // signal private input b;
449 // signal output c;
450 //
451 // c <== a*b;
452 // }
453 //
454 // component main = Multiplier();
455 //
456 // Then:
457 // `snarkjs zkey new circuit.r1cs powersOfTau28_hez_final_10.ptau test.zkey`
458 let path = "./test-vectors/test.zkey";
459 let mut file = File::open(path).unwrap();
460 let mut binfile = BinFile::new(&mut file).unwrap();
461 let header = binfile.groth_header().unwrap();
462 assert_eq!(header.n_vars, 4);
463 assert_eq!(header.n_public, 1);
464 assert_eq!(header.domain_size, 4);
465 assert_eq!(header.power, 2);
466 }
467
468 #[test]
469 fn deser_key() {
470 let path = "./test-vectors/test.zkey";
471 let mut file = File::open(path).unwrap();
472 let params = read_zkey(&mut file).unwrap();
473
474 // Check IC
475 let expected = vec![
476 deserialize_g1(
477 &mut &[
478 11, 205, 205, 176, 2, 105, 129, 243, 153, 58, 137, 89, 61, 95, 99, 161, 133,
479 201, 153, 192, 119, 19, 113, 136, 43, 105, 47, 206, 166, 55, 81, 22, 154, 77,
480 58, 119, 28, 230, 160, 206, 134, 98, 4, 115, 112, 184, 46, 117, 61, 180, 103,
481 138, 141, 202, 110, 252, 199, 252, 141, 211, 5, 46, 244, 10,
482 ][..],
483 )
484 .unwrap(),
485 deserialize_g1(
486 &mut &[
487 118, 135, 198, 156, 63, 190, 210, 98, 194, 59, 169, 168, 204, 168, 76, 208,
488 109, 170, 24, 193, 57, 31, 184, 88, 234, 218, 118, 58, 107, 129, 90, 36, 230,
489 98, 62, 243, 3, 55, 68, 227, 117, 64, 188, 81, 81, 247, 161, 68, 68, 210, 142,
490 191, 174, 43, 110, 194, 253, 128, 217, 4, 54, 196, 111, 43,
491 ][..],
492 )
493 .unwrap(),
494 ];
495 assert_eq!(expected, params.vk.gamma_abc_g1);
496
497 // Check A Query
498 let expected = vec![
499 deserialize_g1(
500 &mut &[
501 240, 165, 110, 187, 72, 39, 218, 59, 128, 85, 50, 174, 229, 1, 86, 58, 125,
502 244, 145, 205, 248, 253, 120, 2, 165, 140, 154, 55, 220, 253, 14, 19, 212, 106,
503 59, 19, 125, 198, 202, 4, 59, 74, 14, 62, 20, 248, 219, 47, 234, 205, 54, 183,
504 33, 119, 165, 84, 46, 75, 39, 17, 229, 42, 192, 2,
505 ][..],
506 )
507 .unwrap(),
508 deserialize_g1(
509 &mut &[
510 93, 53, 177, 82, 50, 5, 123, 116, 91, 35, 14, 196, 43, 180, 54, 15, 88, 144,
511 197, 105, 57, 167, 54, 5, 188, 109, 17, 89, 9, 223, 80, 1, 39, 193, 211, 168,
512 203, 119, 169, 105, 17, 156, 53, 106, 11, 102, 44, 92, 123, 220, 158, 240, 97,
513 253, 30, 121, 4, 236, 171, 23, 100, 34, 133, 11,
514 ][..],
515 )
516 .unwrap(),
517 deserialize_g1(
518 &mut &[
519 177, 47, 21, 237, 244, 73, 76, 98, 80, 10, 10, 142, 80, 145, 40, 254, 100, 214,
520 103, 33, 38, 84, 238, 248, 252, 181, 75, 32, 109, 16, 93, 23, 135, 157, 206,
521 122, 107, 105, 202, 164, 197, 124, 242, 100, 70, 108, 9, 180, 224, 102, 250,
522 149, 130, 14, 133, 185, 132, 189, 193, 230, 180, 143, 156, 30,
523 ][..],
524 )
525 .unwrap(),
526 deserialize_g1(
527 &mut &[
528 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
529 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
530 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
531 ][..],
532 )
533 .unwrap(),
534 ];
535 assert_eq!(expected, params.a_query);
536
537 // B G1 Query
538 let expected = vec![
539 deserialize_g1(
540 &mut &[
541 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
542 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
543 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
544 ][..],
545 )
546 .unwrap(),
547 deserialize_g1(
548 &mut &[
549 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
550 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
551 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
552 ][..],
553 )
554 .unwrap(),
555 deserialize_g1(
556 &mut &[
557 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
558 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
559 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
560 ][..],
561 )
562 .unwrap(),
563 deserialize_g1(
564 &mut &[
565 177, 47, 21, 237, 244, 73, 76, 98, 80, 10, 10, 142, 80, 145, 40, 254, 100, 214,
566 103, 33, 38, 84, 238, 248, 252, 181, 75, 32, 109, 16, 93, 23, 192, 95, 174, 93,
567 171, 34, 86, 151, 199, 77, 127, 3, 75, 254, 119, 227, 124, 241, 134, 235, 51,
568 55, 203, 254, 164, 226, 111, 250, 189, 190, 199, 17,
569 ][..],
570 )
571 .unwrap(),
572 ];
573 assert_eq!(expected, params.b_g1_query);
574
575 // B G2 Query
576 let expected = vec![
577 deserialize_g2(
578 &mut &[
579 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
580 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
581 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
582 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
583 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
584 ][..],
585 )
586 .unwrap(),
587 deserialize_g2(
588 &mut &[
589 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
590 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
591 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
592 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
593 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
594 ][..],
595 )
596 .unwrap(),
597 deserialize_g2(
598 &mut &[
599 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
600 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
601 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
602 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
603 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
604 ][..],
605 )
606 .unwrap(),
607 deserialize_g2(
608 &mut &[
609 240, 25, 157, 232, 164, 49, 152, 204, 244, 190, 178, 178, 29, 133, 205, 175,
610 172, 28, 12, 123, 139, 202, 196, 13, 67, 165, 204, 42, 74, 40, 6, 36, 112, 104,
611 61, 67, 107, 112, 72, 41, 213, 210, 249, 75, 89, 144, 144, 34, 177, 228, 18,
612 70, 80, 195, 124, 82, 40, 122, 91, 21, 198, 100, 154, 1, 16, 235, 41, 4, 176,
613 106, 9, 113, 141, 251, 100, 233, 188, 128, 194, 173, 0, 100, 206, 110, 53, 223,
614 163, 47, 166, 235, 25, 12, 151, 238, 45, 0, 78, 210, 56, 53, 57, 212, 67, 189,
615 253, 132, 62, 62, 116, 20, 235, 15, 245, 113, 30, 182, 33, 127, 203, 231, 124,
616 149, 74, 223, 39, 190, 217, 41,
617 ][..],
618 )
619 .unwrap(),
620 ];
621 assert_eq!(expected, params.b_g2_query);
622
623 // Check L Query
624 let expected = vec![
625 deserialize_g1(
626 &mut &[
627 146, 142, 29, 235, 9, 162, 84, 255, 6, 119, 86, 214, 154, 18, 12, 190, 202, 19,
628 168, 45, 29, 76, 174, 130, 6, 59, 146, 15, 229, 82, 81, 40, 50, 25, 124, 247,
629 129, 12, 147, 35, 108, 119, 178, 116, 238, 145, 33, 184, 74, 201, 128, 41, 151,
630 6, 60, 84, 156, 225, 200, 14, 240, 171, 128, 20,
631 ][..],
632 )
633 .unwrap(),
634 deserialize_g1(
635 &mut &[
636 26, 32, 112, 226, 161, 84, 188, 236, 141, 226, 119, 169, 235, 218, 253, 176,
637 157, 184, 108, 243, 73, 122, 239, 217, 39, 190, 239, 105, 147, 190, 80, 47,
638 211, 68, 155, 212, 139, 173, 229, 160, 123, 117, 243, 110, 162, 188, 217, 206,
639 102, 19, 36, 189, 87, 183, 113, 8, 164, 133, 43, 142, 138, 109, 66, 33,
640 ][..],
641 )
642 .unwrap(),
643 ];
644 assert_eq!(expected, params.l_query);
645
646 // Check H Query
647 let expected = vec![
648 deserialize_g1(
649 &mut &[
650 21, 76, 104, 34, 28, 236, 135, 204, 218, 16, 160, 115, 185, 44, 19, 62, 43, 24,
651 57, 99, 207, 105, 10, 139, 195, 60, 17, 57, 85, 244, 167, 10, 166, 166, 165,
652 55, 38, 75, 116, 116, 182, 87, 217, 112, 28, 237, 239, 123, 231, 180, 122, 109,
653 77, 116, 88, 67, 102, 48, 80, 214, 137, 47, 94, 30,
654 ][..],
655 )
656 .unwrap(),
657 deserialize_g1(
658 &mut &[
659 144, 175, 205, 119, 119, 192, 11, 10, 148, 224, 87, 161, 157, 231, 101, 208,
660 55, 15, 13, 16, 24, 59, 9, 22, 63, 215, 255, 30, 77, 188, 71, 37, 84, 227, 59,
661 29, 159, 116, 101, 93, 212, 220, 159, 141, 204, 107, 131, 87, 174, 149, 175,
662 72, 199, 109, 64, 109, 180, 150, 160, 249, 246, 33, 212, 29,
663 ][..],
664 )
665 .unwrap(),
666 deserialize_g1(
667 &mut &[
668 129, 169, 52, 179, 66, 88, 123, 199, 222, 69, 24, 17, 219, 235, 118, 195, 156,
669 210, 14, 21, 76, 155, 178, 210, 223, 4, 233, 5, 8, 18, 156, 24, 82, 68, 183,
670 186, 7, 126, 2, 201, 207, 207, 74, 45, 44, 199, 16, 165, 25, 65, 157, 199, 90,
671 159, 12, 150, 250, 17, 177, 193, 244, 93, 230, 41,
672 ][..],
673 )
674 .unwrap(),
675 deserialize_g1(
676 &mut &[
677 207, 61, 229, 214, 21, 61, 103, 165, 93, 145, 54, 138, 143, 214, 5, 83, 183,
678 22, 174, 87, 108, 59, 99, 96, 19, 20, 25, 139, 114, 238, 198, 40, 182, 88, 1,
679 255, 206, 132, 156, 165, 178, 171, 0, 226, 179, 30, 192, 4, 79, 198, 69, 43,
680 145, 133, 116, 86, 36, 144, 190, 119, 79, 241, 76, 16,
681 ][..],
682 )
683 .unwrap(),
684 ];
685 assert_eq!(expected, params.h_query);
686 }
687
688 #[test]
689 fn deser_vk() {
690 let path = "./test-vectors/test.zkey";
691 let mut file = File::open(path).unwrap();
692 let params = read_zkey(&mut file).unwrap();
693
694 let json = std::fs::read_to_string("./test-vectors/verification_key.json").unwrap();
695 let json: Value = serde_json::from_str(&json).unwrap();
696
697 assert_eq!(json_to_g1(&json, "vk_alpha_1"), params.vk.alpha_g1);
698 assert_eq!(json_to_g2(&json, "vk_beta_2"), params.vk.beta_g2);
699 assert_eq!(json_to_g2(&json, "vk_gamma_2"), params.vk.gamma_g2);
700 assert_eq!(json_to_g2(&json, "vk_delta_2"), params.vk.delta_g2);
701 assert_eq!(json_to_g1_vec(&json, "IC"), params.vk.gamma_abc_g1);
702 }
703
704 fn json_to_g1(json: &Value, key: &str) -> G1Affine {
705 let els: Vec<String> = json
706 .get(key)
707 .unwrap()
708 .as_array()
709 .unwrap()
710 .iter()
711 .map(|i| i.as_str().unwrap().to_string())
712 .collect();
713 G1Affine::from(G1Projective::new(
714 fq_from_str(&els[0]),
715 fq_from_str(&els[1]),
716 fq_from_str(&els[2]),
717 ))
718 }
719
720 fn json_to_g1_vec(json: &Value, key: &str) -> Vec<G1Affine> {
721 let els: Vec<Vec<String>> = json
722 .get(key)
723 .unwrap()
724 .as_array()
725 .unwrap()
726 .iter()
727 .map(|i| {
728 i.as_array()
729 .unwrap()
730 .iter()
731 .map(|x| x.as_str().unwrap().to_string())
732 .collect::<Vec<String>>()
733 })
734 .collect();
735
736 els.iter()
737 .map(|coords| {
738 G1Affine::from(G1Projective::new(
739 fq_from_str(&coords[0]),
740 fq_from_str(&coords[1]),
741 fq_from_str(&coords[2]),
742 ))
743 })
744 .collect()
745 }
746
747 fn json_to_g2(json: &Value, key: &str) -> G2Affine {
748 let els: Vec<Vec<String>> = json
749 .get(key)
750 .unwrap()
751 .as_array()
752 .unwrap()
753 .iter()
754 .map(|i| {
755 i.as_array()
756 .unwrap()
757 .iter()
758 .map(|x| x.as_str().unwrap().to_string())
759 .collect::<Vec<String>>()
760 })
761 .collect();
762
763 let x = Fq2::new(fq_from_str(&els[0][0]), fq_from_str(&els[0][1]));
764 let y = Fq2::new(fq_from_str(&els[1][0]), fq_from_str(&els[1][1]));
765 let z = Fq2::new(fq_from_str(&els[2][0]), fq_from_str(&els[2][1]));
766 G2Affine::from(G2Projective::new(x, y, z))
767 }
768
769 #[test]
770 fn verify_proof_with_zkey() {
771 let path = "./test-vectors/test.zkey";
772 let mut file = File::open(path).unwrap();
773 let params = read_zkey(&mut file).unwrap(); // binfile.proving_key().unwrap();
774
775 let cfg = CircomConfig::<Bn254>::new(
776 "./test-vectors/mycircuit.wasm",
777 "./test-vectors/mycircuit.r1cs",
778 )
779 .unwrap();
780 let mut builder = CircomBuilder::new(cfg);
781 builder.push_input("a", 3);
782 builder.push_input("b", 11);
783
784 let circom = builder.build().unwrap();
785
786 let inputs = circom.get_public_inputs().unwrap();
787
788 let mut rng = thread_rng();
789 let proof = prove::<_, _, _, CircomReduction>(circom, ¶ms, &mut rng).unwrap();
790
791 let pvk = prepare_verifying_key(¶ms.vk);
792
793 let verified = verify_proof(&pvk, &proof, &inputs).unwrap();
794
795 assert!(verified);
796 }
797}