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