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