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