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()
486            .cloned()
487            .collect::<Vec<_>>();
488        let expected = vec![g1_one(); n_vars];
489
490        let de = deserialize_g1_vec(&mut &buf[..], n_vars as u32).unwrap();
491        assert_eq!(expected, de);
492    }
493
494    #[test]
495    fn can_deser_g2() {
496        let buf = g2_buf();
497        assert_eq!(buf.len(), 128);
498        let g2 = deserialize_g2(&mut &buf[..]).unwrap();
499
500        let expected = g2_one();
501        assert_eq!(g2, expected);
502    }
503
504    #[test]
505    fn can_deser_g2_vec() {
506        let n_vars = 10;
507        let buf = vec![g2_buf(); n_vars]
508            .iter()
509            .flatten()
510            .cloned()
511            .collect::<Vec<_>>();
512        let expected = vec![g2_one(); n_vars];
513
514        let de = deserialize_g2_vec(&mut &buf[..], n_vars as u32).unwrap();
515        assert_eq!(expected, de);
516    }
517
518    #[test]
519    fn header() {
520        // `circom --r1cs` using the below file:
521        //
522        //  template Multiplier() {
523        //     signal private input a;
524        //     signal private input b;
525        //     signal output c;
526        //
527        //     c <== a*b;
528        // }
529        //
530        // component main = Multiplier();
531        //
532        // Then:
533        // `snarkjs zkey new circuit.r1cs powersOfTau28_hez_final_10.ptau test.zkey`
534        let path = "./test-vectors/test.zkey";
535        let mut file = File::open(path).unwrap();
536        let mut binfile = BinFile::new(&mut file).unwrap();
537        let header = binfile.groth_header().unwrap();
538        assert_eq!(header.n_vars, 4);
539        assert_eq!(header.n_public, 1);
540        assert_eq!(header.domain_size, 4);
541        assert_eq!(header.power, 2);
542    }
543
544    #[test]
545    fn deser_key() {
546        let path = "./test-vectors/test.zkey";
547        let mut file = File::open(path).unwrap();
548        let (params, _matrices) = read_zkey(&mut file).unwrap();
549
550        // Check IC
551        let expected = vec![
552            deserialize_g1(
553                &mut &[
554                    11, 205, 205, 176, 2, 105, 129, 243, 153, 58, 137, 89, 61, 95, 99, 161, 133,
555                    201, 153, 192, 119, 19, 113, 136, 43, 105, 47, 206, 166, 55, 81, 22, 154, 77,
556                    58, 119, 28, 230, 160, 206, 134, 98, 4, 115, 112, 184, 46, 117, 61, 180, 103,
557                    138, 141, 202, 110, 252, 199, 252, 141, 211, 5, 46, 244, 10,
558                ][..],
559            )
560            .unwrap(),
561            deserialize_g1(
562                &mut &[
563                    118, 135, 198, 156, 63, 190, 210, 98, 194, 59, 169, 168, 204, 168, 76, 208,
564                    109, 170, 24, 193, 57, 31, 184, 88, 234, 218, 118, 58, 107, 129, 90, 36, 230,
565                    98, 62, 243, 3, 55, 68, 227, 117, 64, 188, 81, 81, 247, 161, 68, 68, 210, 142,
566                    191, 174, 43, 110, 194, 253, 128, 217, 4, 54, 196, 111, 43,
567                ][..],
568            )
569            .unwrap(),
570        ];
571        assert_eq!(expected, params.vk.gamma_abc_g1);
572
573        // Check A Query
574        let expected = vec![
575            deserialize_g1(
576                &mut &[
577                    240, 165, 110, 187, 72, 39, 218, 59, 128, 85, 50, 174, 229, 1, 86, 58, 125,
578                    244, 145, 205, 248, 253, 120, 2, 165, 140, 154, 55, 220, 253, 14, 19, 212, 106,
579                    59, 19, 125, 198, 202, 4, 59, 74, 14, 62, 20, 248, 219, 47, 234, 205, 54, 183,
580                    33, 119, 165, 84, 46, 75, 39, 17, 229, 42, 192, 2,
581                ][..],
582            )
583            .unwrap(),
584            deserialize_g1(
585                &mut &[
586                    93, 53, 177, 82, 50, 5, 123, 116, 91, 35, 14, 196, 43, 180, 54, 15, 88, 144,
587                    197, 105, 57, 167, 54, 5, 188, 109, 17, 89, 9, 223, 80, 1, 39, 193, 211, 168,
588                    203, 119, 169, 105, 17, 156, 53, 106, 11, 102, 44, 92, 123, 220, 158, 240, 97,
589                    253, 30, 121, 4, 236, 171, 23, 100, 34, 133, 11,
590                ][..],
591            )
592            .unwrap(),
593            deserialize_g1(
594                &mut &[
595                    177, 47, 21, 237, 244, 73, 76, 98, 80, 10, 10, 142, 80, 145, 40, 254, 100, 214,
596                    103, 33, 38, 84, 238, 248, 252, 181, 75, 32, 109, 16, 93, 23, 135, 157, 206,
597                    122, 107, 105, 202, 164, 197, 124, 242, 100, 70, 108, 9, 180, 224, 102, 250,
598                    149, 130, 14, 133, 185, 132, 189, 193, 230, 180, 143, 156, 30,
599                ][..],
600            )
601            .unwrap(),
602            deserialize_g1(
603                &mut &[
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, 0, 0,
606                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
607                ][..],
608            )
609            .unwrap(),
610        ];
611        assert_eq!(expected, params.a_query);
612
613        // B G1 Query
614        let expected = vec![
615            deserialize_g1(
616                &mut &[
617                    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,
618                    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,
619                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
620                ][..],
621            )
622            .unwrap(),
623            deserialize_g1(
624                &mut &[
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, 0, 0,
626                    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,
627                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
628                ][..],
629            )
630            .unwrap(),
631            deserialize_g1(
632                &mut &[
633                    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,
634                    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,
635                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
636                ][..],
637            )
638            .unwrap(),
639            deserialize_g1(
640                &mut &[
641                    177, 47, 21, 237, 244, 73, 76, 98, 80, 10, 10, 142, 80, 145, 40, 254, 100, 214,
642                    103, 33, 38, 84, 238, 248, 252, 181, 75, 32, 109, 16, 93, 23, 192, 95, 174, 93,
643                    171, 34, 86, 151, 199, 77, 127, 3, 75, 254, 119, 227, 124, 241, 134, 235, 51,
644                    55, 203, 254, 164, 226, 111, 250, 189, 190, 199, 17,
645                ][..],
646            )
647            .unwrap(),
648        ];
649        assert_eq!(expected, params.b_g1_query);
650
651        // B G2 Query
652        let expected = vec![
653            deserialize_g2(
654                &mut &[
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, 0, 0,
658                    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,
659                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
660                ][..],
661            )
662            .unwrap(),
663            deserialize_g2(
664                &mut &[
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, 0, 0,
668                    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,
669                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
670                ][..],
671            )
672            .unwrap(),
673            deserialize_g2(
674                &mut &[
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, 0, 0,
678                    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,
679                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
680                ][..],
681            )
682            .unwrap(),
683            deserialize_g2(
684                &mut &[
685                    240, 25, 157, 232, 164, 49, 152, 204, 244, 190, 178, 178, 29, 133, 205, 175,
686                    172, 28, 12, 123, 139, 202, 196, 13, 67, 165, 204, 42, 74, 40, 6, 36, 112, 104,
687                    61, 67, 107, 112, 72, 41, 213, 210, 249, 75, 89, 144, 144, 34, 177, 228, 18,
688                    70, 80, 195, 124, 82, 40, 122, 91, 21, 198, 100, 154, 1, 16, 235, 41, 4, 176,
689                    106, 9, 113, 141, 251, 100, 233, 188, 128, 194, 173, 0, 100, 206, 110, 53, 223,
690                    163, 47, 166, 235, 25, 12, 151, 238, 45, 0, 78, 210, 56, 53, 57, 212, 67, 189,
691                    253, 132, 62, 62, 116, 20, 235, 15, 245, 113, 30, 182, 33, 127, 203, 231, 124,
692                    149, 74, 223, 39, 190, 217, 41,
693                ][..],
694            )
695            .unwrap(),
696        ];
697        assert_eq!(expected, params.b_g2_query);
698
699        // Check L Query
700        let expected = vec![
701            deserialize_g1(
702                &mut &[
703                    146, 142, 29, 235, 9, 162, 84, 255, 6, 119, 86, 214, 154, 18, 12, 190, 202, 19,
704                    168, 45, 29, 76, 174, 130, 6, 59, 146, 15, 229, 82, 81, 40, 50, 25, 124, 247,
705                    129, 12, 147, 35, 108, 119, 178, 116, 238, 145, 33, 184, 74, 201, 128, 41, 151,
706                    6, 60, 84, 156, 225, 200, 14, 240, 171, 128, 20,
707                ][..],
708            )
709            .unwrap(),
710            deserialize_g1(
711                &mut &[
712                    26, 32, 112, 226, 161, 84, 188, 236, 141, 226, 119, 169, 235, 218, 253, 176,
713                    157, 184, 108, 243, 73, 122, 239, 217, 39, 190, 239, 105, 147, 190, 80, 47,
714                    211, 68, 155, 212, 139, 173, 229, 160, 123, 117, 243, 110, 162, 188, 217, 206,
715                    102, 19, 36, 189, 87, 183, 113, 8, 164, 133, 43, 142, 138, 109, 66, 33,
716                ][..],
717            )
718            .unwrap(),
719        ];
720        assert_eq!(expected, params.l_query);
721
722        // Check H Query
723        let expected = vec![
724            deserialize_g1(
725                &mut &[
726                    21, 76, 104, 34, 28, 236, 135, 204, 218, 16, 160, 115, 185, 44, 19, 62, 43, 24,
727                    57, 99, 207, 105, 10, 139, 195, 60, 17, 57, 85, 244, 167, 10, 166, 166, 165,
728                    55, 38, 75, 116, 116, 182, 87, 217, 112, 28, 237, 239, 123, 231, 180, 122, 109,
729                    77, 116, 88, 67, 102, 48, 80, 214, 137, 47, 94, 30,
730                ][..],
731            )
732            .unwrap(),
733            deserialize_g1(
734                &mut &[
735                    144, 175, 205, 119, 119, 192, 11, 10, 148, 224, 87, 161, 157, 231, 101, 208,
736                    55, 15, 13, 16, 24, 59, 9, 22, 63, 215, 255, 30, 77, 188, 71, 37, 84, 227, 59,
737                    29, 159, 116, 101, 93, 212, 220, 159, 141, 204, 107, 131, 87, 174, 149, 175,
738                    72, 199, 109, 64, 109, 180, 150, 160, 249, 246, 33, 212, 29,
739                ][..],
740            )
741            .unwrap(),
742            deserialize_g1(
743                &mut &[
744                    129, 169, 52, 179, 66, 88, 123, 199, 222, 69, 24, 17, 219, 235, 118, 195, 156,
745                    210, 14, 21, 76, 155, 178, 210, 223, 4, 233, 5, 8, 18, 156, 24, 82, 68, 183,
746                    186, 7, 126, 2, 201, 207, 207, 74, 45, 44, 199, 16, 165, 25, 65, 157, 199, 90,
747                    159, 12, 150, 250, 17, 177, 193, 244, 93, 230, 41,
748                ][..],
749            )
750            .unwrap(),
751            deserialize_g1(
752                &mut &[
753                    207, 61, 229, 214, 21, 61, 103, 165, 93, 145, 54, 138, 143, 214, 5, 83, 183,
754                    22, 174, 87, 108, 59, 99, 96, 19, 20, 25, 139, 114, 238, 198, 40, 182, 88, 1,
755                    255, 206, 132, 156, 165, 178, 171, 0, 226, 179, 30, 192, 4, 79, 198, 69, 43,
756                    145, 133, 116, 86, 36, 144, 190, 119, 79, 241, 76, 16,
757                ][..],
758            )
759            .unwrap(),
760        ];
761        assert_eq!(expected, params.h_query);
762    }
763
764    #[test]
765    fn deser_vk() {
766        let path = "./test-vectors/test.zkey";
767        let mut file = File::open(path).unwrap();
768        let (params, _matrices) = read_zkey(&mut file).unwrap();
769
770        let json = std::fs::read_to_string("./test-vectors/verification_key.json").unwrap();
771        let json: Value = serde_json::from_str(&json).unwrap();
772
773        assert_eq!(json_to_g1(&json, "vk_alpha_1"), params.vk.alpha_g1);
774        assert_eq!(json_to_g2(&json, "vk_beta_2"), params.vk.beta_g2);
775        assert_eq!(json_to_g2(&json, "vk_gamma_2"), params.vk.gamma_g2);
776        assert_eq!(json_to_g2(&json, "vk_delta_2"), params.vk.delta_g2);
777        assert_eq!(json_to_g1_vec(&json, "IC"), params.vk.gamma_abc_g1);
778    }
779
780    fn json_to_g1(json: &Value, key: &str) -> G1Affine {
781        let els: Vec<String> = json
782            .get(key)
783            .unwrap()
784            .as_array()
785            .unwrap()
786            .iter()
787            .map(|i| i.as_str().unwrap().to_string())
788            .collect();
789        G1Affine::from(G1Projective::new(
790            fq_from_str(&els[0]),
791            fq_from_str(&els[1]),
792            fq_from_str(&els[2]),
793        ))
794    }
795
796    fn json_to_g1_vec(json: &Value, key: &str) -> Vec<G1Affine> {
797        let els: Vec<Vec<String>> = json
798            .get(key)
799            .unwrap()
800            .as_array()
801            .unwrap()
802            .iter()
803            .map(|i| {
804                i.as_array()
805                    .unwrap()
806                    .iter()
807                    .map(|x| x.as_str().unwrap().to_string())
808                    .collect::<Vec<String>>()
809            })
810            .collect();
811
812        els.iter()
813            .map(|coords| {
814                G1Affine::from(G1Projective::new(
815                    fq_from_str(&coords[0]),
816                    fq_from_str(&coords[1]),
817                    fq_from_str(&coords[2]),
818                ))
819            })
820            .collect()
821    }
822
823    fn json_to_g2(json: &Value, key: &str) -> G2Affine {
824        let els: Vec<Vec<String>> = json
825            .get(key)
826            .unwrap()
827            .as_array()
828            .unwrap()
829            .iter()
830            .map(|i| {
831                i.as_array()
832                    .unwrap()
833                    .iter()
834                    .map(|x| x.as_str().unwrap().to_string())
835                    .collect::<Vec<String>>()
836            })
837            .collect();
838
839        let x = Fq2::new(fq_from_str(&els[0][0]), fq_from_str(&els[0][1]));
840        let y = Fq2::new(fq_from_str(&els[1][0]), fq_from_str(&els[1][1]));
841        let z = Fq2::new(fq_from_str(&els[2][0]), fq_from_str(&els[2][1]));
842        G2Affine::from(G2Projective::new(x, y, z))
843    }
844
845    #[test]
846    fn verify_proof_with_zkey_with_r1cs() {
847        let path = "./test-vectors/test.zkey";
848        let mut file = File::open(path).unwrap();
849        let (params, _matrices) = read_zkey(&mut file).unwrap(); // binfile.proving_key().unwrap();
850
851        let cfg = CircomConfig::<Fr>::new(
852            "./test-vectors/mycircuit.wasm",
853            "./test-vectors/mycircuit.r1cs",
854        )
855        .unwrap();
856        let mut builder = CircomBuilder::new(cfg);
857        builder.push_input("a", 3);
858        builder.push_input("b", 11);
859
860        let circom = builder.build().unwrap();
861
862        let inputs = circom.get_public_inputs().unwrap();
863
864        let mut rng = thread_rng();
865        let proof = Groth16::<Bn254, CircomReduction>::prove(&params, circom, &mut rng).unwrap();
866
867        let pvk = Groth16::<Bn254>::process_vk(&params.vk).unwrap();
868
869        let verified = Groth16::<Bn254>::verify_with_processed_vk(&pvk, &inputs, &proof).unwrap();
870
871        assert!(verified);
872    }
873
874    #[test]
875    fn verify_proof_with_zkey_without_r1cs() {
876        let path = "./test-vectors/test.zkey";
877        let mut file = File::open(path).unwrap();
878        let (params, matrices) = read_zkey(&mut file).unwrap();
879
880        let mut wtns = WitnessCalculator::new("./test-vectors/mycircuit.wasm").unwrap();
881        let mut inputs: HashMap<String, Vec<num_bigint::BigInt>> = HashMap::new();
882        let values = inputs.entry("a".to_string()).or_insert_with(Vec::new);
883        values.push(3.into());
884
885        let values = inputs.entry("b".to_string()).or_insert_with(Vec::new);
886        values.push(11.into());
887
888        let mut rng = thread_rng();
889        use ark_std::UniformRand;
890        let num_inputs = matrices.num_instance_variables;
891        let num_constraints = matrices.num_constraints;
892        let rng = &mut rng;
893
894        let r = ark_bn254::Fr::rand(rng);
895        let s = ark_bn254::Fr::rand(rng);
896
897        let full_assignment = wtns
898            .calculate_witness_element::<Fr, _>(inputs, false)
899            .unwrap();
900        let proof = Groth16::<Bn254, CircomReduction>::create_proof_with_reduction_and_matrices(
901            &params,
902            r,
903            s,
904            &matrices,
905            num_inputs,
906            num_constraints,
907            full_assignment.as_slice(),
908        )
909        .unwrap();
910
911        let pvk = Groth16::<Bn254>::process_vk(&params.vk).unwrap();
912        let inputs = &full_assignment[1..num_inputs];
913        let verified = Groth16::<Bn254>::verify_with_processed_vk(&pvk, inputs, &proof).unwrap();
914
915        assert!(verified);
916    }
917}