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