arnaucube
arnaucube/testudoPublic Self-hosted repository
testudo/src/lib.rs
src/lib.rsRaw
  1#![allow(non_snake_case)]
  2#![feature(test)]
  3#![feature(int_log)]
  4#![doc = include_str!("../README.md")]
  5#![deny(missing_docs)]
  6
  7extern crate byteorder;
  8extern crate core;
  9extern crate digest;
 10extern crate merlin;
 11extern crate sha3;
 12extern crate test;
 13extern crate rand;
 14extern crate lazy_static;
 15extern crate ark_std;
 16
 17#[macro_use]
 18extern crate json;
 19
 20#[cfg(feature = "multicore")]
 21extern crate rayon;
 22
 23mod commitments;
 24mod dense_mlpoly;
 25mod errors;
 26mod group;
 27mod math;
 28mod nizk;
 29mod parameters;
 30mod product_tree;
 31mod r1csinstance;
 32mod r1csproof;
 33mod random;
 34mod scalar;
 35mod sparse_mlpoly;
 36mod sumcheck;
 37mod timer;
 38mod transcript;
 39mod unipoly;
 40
 41
 42use core::{cmp::max};
 43use std::borrow::Borrow;
 44use errors::{ProofVerifyError, R1CSError};
 45use merlin::Transcript;
 46use r1csinstance::{
 47  R1CSCommitment, R1CSCommitmentGens, R1CSDecommitment, R1CSEvalProof, R1CSInstance,
 48};
 49use r1csproof::{R1CSGens, R1CSProof};
 50use random::RandomTape;
 51use scalar::Scalar;
 52use ark_serialize::*;
 53use ark_ff::{PrimeField, Field, BigInteger};
 54use ark_std::{One, Zero, UniformRand};
 55use timer::Timer;
 56use transcript::{AppendToTranscript, ProofTranscript};
 57
 58/// `ComputationCommitment` holds a public preprocessed NP statement (e.g., R1CS)
 59pub struct ComputationCommitment {
 60  comm: R1CSCommitment,
 61}
 62
 63/// `ComputationDecommitment` holds information to decommit `ComputationCommitment`
 64pub struct ComputationDecommitment {
 65  decomm: R1CSDecommitment,
 66}
 67
 68/// `Assignment` holds an assignment of values to either the inputs or variables in an `Instance`
 69#[derive(Clone)]
 70pub struct Assignment {
 71  assignment: Vec<Scalar>,
 72}
 73
 74impl Assignment {
 75  /// Constructs a new `Assignment` from a vector
 76  pub fn new(assignment: &Vec<Vec<u8>>) -> Result<Assignment, R1CSError> {
 77    let bytes_to_scalar = |vec: &Vec<Vec<u8>>| -> Result<Vec<Scalar>, R1CSError> {
 78      let mut vec_scalar: Vec<Scalar> = Vec::new();
 79      for v in vec {
 80        let val = Scalar::from_random_bytes(v.as_slice());
 81        if val.is_some() == true {
 82          vec_scalar.push(val.unwrap());
 83        } else {
 84          return Err(R1CSError::InvalidScalar);
 85        }
 86      }
 87      Ok(vec_scalar)
 88    };
 89
 90    let assignment_scalar = bytes_to_scalar(assignment);
 91
 92    // check for any parsing errors
 93    if assignment_scalar.is_err() {
 94      return Err(R1CSError::InvalidScalar);
 95    }
 96
 97    Ok(Assignment {
 98      assignment: assignment_scalar.unwrap(),
 99    })
100  }
101
102  /// pads Assignment to the specified length
103  fn pad(&self, len: usize) -> VarsAssignment {
104    // check that the new length is higher than current length
105    assert!(len > self.assignment.len());
106
107    let padded_assignment = {
108      let mut padded_assignment = self.assignment.clone();
109      padded_assignment.extend(vec![Scalar::zero(); len - self.assignment.len()]);
110      padded_assignment
111    };
112
113    VarsAssignment {
114      assignment: padded_assignment,
115    }
116  }
117}
118
119/// `VarsAssignment` holds an assignment of values to variables in an `Instance`
120pub type VarsAssignment = Assignment;
121
122/// `VarsAssignment` holds an assignment of values to variables in an `Instance`
123pub type InputsAssignment = Assignment;
124
125/// `Instance` holds the description of R1CS matrices
126#[derive(Debug)]
127pub struct Instance {
128  inst: R1CSInstance,
129}
130
131impl Instance {
132  /// Constructs a new `Instance` and an associated satisfying assignment
133  pub fn new(
134    num_cons: usize,
135    num_vars: usize,
136    num_inputs: usize,
137    A: &[(usize, usize, Vec<u8>)],
138    B: &[(usize, usize, Vec<u8>)],
139    C: &[(usize, usize, Vec<u8>)],
140  ) -> Result<Instance, R1CSError> {
141    let (num_vars_padded, num_cons_padded) = {
142      let num_vars_padded = {
143        let mut num_vars_padded = num_vars;
144
145        // ensure that num_inputs + 1 <= num_vars
146        num_vars_padded = max(num_vars_padded, num_inputs + 1);
147
148        // ensure that num_vars_padded a power of two
149        if num_vars_padded.next_power_of_two() != num_vars_padded {
150          num_vars_padded = num_vars_padded.next_power_of_two();
151        }
152        num_vars_padded
153      };
154
155      let num_cons_padded = {
156        let mut num_cons_padded = num_cons;
157
158        // ensure that num_cons_padded is at least 2
159        if num_cons_padded == 0 || num_cons_padded == 1 {
160          num_cons_padded = 2;
161        }
162
163        // ensure that num_cons_padded is power of 2
164        if num_cons.next_power_of_two() != num_cons {
165          num_cons_padded = num_cons.next_power_of_two();
166        }
167        num_cons_padded
168      };
169
170      (num_vars_padded, num_cons_padded)
171    };
172
173    let bytes_to_scalar =
174      |tups: & [(usize, usize, Vec<u8>)]| -> Result<Vec<(usize, usize, Scalar)>, R1CSError> {
175        let mut mat: Vec<(usize, usize, Scalar)> = Vec::new();
176        for (row, col, val_bytes) in tups {
177          // row must be smaller than num_cons
178          if *row >= num_cons {
179            return Err(R1CSError::InvalidIndex);
180          }
181
182          // col must be smaller than num_vars + 1 + num_inputs
183          if *col >= num_vars + 1 + num_inputs {
184            return Err(R1CSError::InvalidIndex);
185          }
186
187          let val = Scalar::from_random_bytes(&val_bytes.as_slice());
188          if val.is_some() == true {
189            // if col >= num_vars, it means that it is referencing a 1 or input in the satisfying
190            // assignment
191            if *col >= num_vars {
192              mat.push((*row, *col + num_vars_padded - num_vars, val.unwrap()));
193            } else {
194              mat.push((*row, *col, val.unwrap()));
195            }
196          } else {
197            return Err(R1CSError::InvalidScalar);
198          }
199        }
200
201        // pad with additional constraints up until num_cons_padded if the original constraints were 0 or 1
202        // we do not need to pad otherwise because the dummy constraints are implicit in the sum-check protocol
203        if num_cons == 0 || num_cons == 1 {
204          for i in tups.len()..num_cons_padded {
205            mat.push((i, num_vars, Scalar::zero()));
206          }
207        }
208
209        Ok(mat)
210      };
211
212    let A_scalar = bytes_to_scalar(A);
213    if A_scalar.is_err() {
214      return Err(A_scalar.err().unwrap());
215    }
216
217    let B_scalar = bytes_to_scalar(B);
218    if B_scalar.is_err() {
219      return Err(B_scalar.err().unwrap());
220    }
221
222    let C_scalar = bytes_to_scalar(C);
223    if C_scalar.is_err() {
224      return Err(C_scalar.err().unwrap());
225    }
226
227    let inst = R1CSInstance::new(
228      num_cons_padded,
229      num_vars_padded,
230      num_inputs,
231      &A_scalar.unwrap(),
232      &B_scalar.unwrap(),
233      &C_scalar.unwrap(),
234    );
235
236    Ok(Instance { inst })
237  }
238
239  /// Checks if a given R1CSInstance is satisfiable with a given variables and inputs assignments
240  pub fn is_sat(
241    &self,
242    vars: &VarsAssignment,
243    inputs: &InputsAssignment,
244  ) -> Result<bool, R1CSError> {
245    if vars.assignment.len() > self.inst.get_num_vars() {
246      return Err(R1CSError::InvalidNumberOfInputs);
247    }
248
249    if inputs.assignment.len() != self.inst.get_num_inputs() {
250      return Err(R1CSError::InvalidNumberOfInputs);
251    }
252
253    // we might need to pad variables
254    let padded_vars = {
255      let num_padded_vars = self.inst.get_num_vars();
256      let num_vars = vars.assignment.len();
257      if num_padded_vars > num_vars {
258        vars.pad(num_padded_vars)
259      } else {
260        vars.clone()
261      }
262    };
263
264    Ok(
265      self
266        .inst
267        .is_sat(&padded_vars.assignment, &inputs.assignment),
268    )
269  }
270
271  /// Constructs a new synthetic R1CS `Instance` and an associated satisfying assignment
272  pub fn produce_synthetic_r1cs(
273    num_cons: usize,
274    num_vars: usize,
275    num_inputs: usize,
276  ) -> (Instance, VarsAssignment, InputsAssignment) {
277    let (inst, vars, inputs) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
278    (
279      Instance { inst },
280      VarsAssignment { assignment: vars },
281      InputsAssignment { assignment: inputs },
282    )
283  }
284}
285
286/// `SNARKGens` holds public parameters for producing and verifying proofs with the Spartan SNARK
287pub struct SNARKGens {
288  gens_r1cs_sat: R1CSGens,
289  gens_r1cs_eval: R1CSCommitmentGens,
290}
291
292impl SNARKGens {
293  /// Constructs a new `SNARKGens` given the size of the R1CS statement
294  /// `num_nz_entries` specifies the maximum number of non-zero entries in any of the three R1CS matrices
295  pub fn new(num_cons: usize, num_vars: usize, num_inputs: usize, num_nz_entries: usize) -> Self {
296    let num_vars_padded = {
297      let mut num_vars_padded = max(num_vars, num_inputs + 1);
298      if num_vars_padded != num_vars_padded.next_power_of_two() {
299        num_vars_padded = num_vars_padded.next_power_of_two();
300      }
301      num_vars_padded
302    };
303
304    let gens_r1cs_sat = R1CSGens::new(b"gens_r1cs_sat", num_cons, num_vars_padded);
305    let gens_r1cs_eval = R1CSCommitmentGens::new(
306      b"gens_r1cs_eval",
307      num_cons,
308      num_vars_padded,
309      num_inputs,
310      num_nz_entries,
311    );
312    SNARKGens {
313      gens_r1cs_sat,
314      gens_r1cs_eval,
315    }
316  }
317}
318
319/// `SNARK` holds a proof produced by Spartan SNARK
320#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)]
321pub struct SNARK {
322  r1cs_sat_proof: R1CSProof,
323  inst_evals: (Scalar, Scalar, Scalar),
324  r1cs_eval_proof: R1CSEvalProof,
325}
326
327impl SNARK {
328  fn protocol_name() -> &'static [u8] {
329    b"Spartan SNARK proof"
330  }
331
332  /// A public computation to create a commitment to an R1CS instance
333  pub fn encode(
334    inst: &Instance,
335    gens: &SNARKGens,
336  ) -> (ComputationCommitment, ComputationDecommitment) {
337    let timer_encode = Timer::new("SNARK::encode");
338    let (comm, decomm) = inst.inst.commit(&gens.gens_r1cs_eval);
339    timer_encode.stop();
340    (
341      ComputationCommitment { comm },
342      ComputationDecommitment { decomm },
343    )
344  }
345
346  /// A method to produce a SNARK proof of the satisfiability of an R1CS instance
347  pub fn prove(
348    inst: &Instance,
349    comm: &ComputationCommitment,
350    decomm: &ComputationDecommitment,
351    vars: VarsAssignment,
352    inputs: &InputsAssignment,
353    gens: &SNARKGens,
354    transcript: &mut Transcript,
355  ) -> Self {
356    let timer_prove = Timer::new("SNARK::prove");
357
358    // we create a Transcript object seeded with a random Scalar
359    // to aid the prover produce its randomness
360    let mut random_tape = RandomTape::new(b"proof");
361
362    transcript.append_protocol_name(SNARK::protocol_name());
363    comm.comm.append_to_transcript(b"comm", transcript);
364
365    let (r1cs_sat_proof, rx, ry) = {
366      let (proof, rx, ry) = {
367        // we might need to pad variables
368        let padded_vars = {
369          let num_padded_vars = inst.inst.get_num_vars();
370          let num_vars = vars.assignment.len();
371          if num_padded_vars > num_vars {
372            vars.pad(num_padded_vars)
373          } else {
374            vars
375          }
376        };
377
378        R1CSProof::prove(
379          &inst.inst,
380          padded_vars.assignment,
381          &inputs.assignment,
382          &gens.gens_r1cs_sat,
383          transcript,
384          &mut random_tape,
385        )
386      };
387
388      let mut proof_encoded: Vec<u8> = Vec::new();
389      proof.serialize(&mut proof_encoded).unwrap();
390      Timer::print(&format!("len_r1cs_sat_proof {:?}", proof_encoded.len()));
391
392      (proof, rx, ry)
393    };
394
395    // We send evaluations of A, B, C at r = (rx, ry) as claims
396    // to enable the verifier complete the first sum-check
397    let timer_eval = Timer::new("eval_sparse_polys");
398    let inst_evals = {
399      let (Ar, Br, Cr) = inst.inst.evaluate(&rx, &ry);
400      Ar.append_to_transcript(b"Ar_claim", transcript);
401      Br.append_to_transcript(b"Br_claim", transcript);
402      Cr.append_to_transcript(b"Cr_claim", transcript);
403      (Ar, Br, Cr)
404    };
405    timer_eval.stop();
406
407    let r1cs_eval_proof = {
408      let proof = R1CSEvalProof::prove(
409        &decomm.decomm,
410        &rx,
411        &ry,
412        &inst_evals,
413        &gens.gens_r1cs_eval,
414        transcript,
415        &mut random_tape,
416      );
417
418      let mut proof_encoded: Vec<u8> = Vec::new();
419      proof.serialize(&mut proof_encoded).unwrap();
420      Timer::print(&format!("len_r1cs_eval_proof {:?}", proof_encoded.len()));
421      proof
422    };
423
424    timer_prove.stop();
425    SNARK {
426      r1cs_sat_proof,
427      inst_evals,
428      r1cs_eval_proof,
429    }
430  }
431
432  /// A method to verify the SNARK proof of the satisfiability of an R1CS instance
433  pub fn verify(
434    &self,
435    comm: &ComputationCommitment,
436    input: &InputsAssignment,
437    transcript: &mut Transcript,
438    gens: &SNARKGens,
439  ) -> Result<(), ProofVerifyError> {
440    let timer_verify = Timer::new("SNARK::verify");
441    transcript.append_protocol_name(SNARK::protocol_name());
442
443    // append a commitment to the computation to the transcript
444    comm.comm.append_to_transcript(b"comm", transcript);
445
446    let timer_sat_proof = Timer::new("verify_sat_proof");
447    assert_eq!(input.assignment.len(), comm.comm.get_num_inputs());
448    let (rx, ry) = self.r1cs_sat_proof.verify(
449      comm.comm.get_num_vars(),
450      comm.comm.get_num_cons(),
451      &input.assignment,
452      &self.inst_evals,
453      transcript,
454      &gens.gens_r1cs_sat,
455    )?;
456    timer_sat_proof.stop();
457
458    let timer_eval_proof = Timer::new("verify_eval_proof");
459    let (Ar, Br, Cr) = &self.inst_evals;
460    Ar.append_to_transcript(b"Ar_claim", transcript);
461    Br.append_to_transcript(b"Br_claim", transcript);
462    Cr.append_to_transcript(b"Cr_claim", transcript);
463    self.r1cs_eval_proof.verify(
464      &comm.comm,
465      &rx,
466      &ry,
467      &self.inst_evals,
468      &gens.gens_r1cs_eval,
469      transcript,
470    )?;
471    timer_eval_proof.stop();
472    timer_verify.stop();
473    Ok(())
474  }
475}
476
477/// `NIZKGens` holds public parameters for producing and verifying proofs with the Spartan NIZK
478pub struct NIZKGens {
479  gens_r1cs_sat: R1CSGens,
480}
481
482impl NIZKGens {
483  /// Constructs a new `NIZKGens` given the size of the R1CS statement
484  pub fn new(num_cons: usize, num_vars: usize, num_inputs: usize) -> Self {
485    let num_vars_padded = {
486      let mut num_vars_padded = max(num_vars, num_inputs + 1);
487      if num_vars_padded != num_vars_padded.next_power_of_two() {
488        num_vars_padded = num_vars_padded.next_power_of_two();
489      }
490      num_vars_padded
491    };
492
493    let gens_r1cs_sat = R1CSGens::new(b"gens_r1cs_sat", num_cons, num_vars_padded);
494    NIZKGens { gens_r1cs_sat }
495  }
496}
497
498/// `NIZK` holds a proof produced by Spartan NIZK
499#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)]
500pub struct NIZK {
501  r1cs_sat_proof: R1CSProof,
502  r: (Vec<Scalar>, Vec<Scalar>),
503}
504
505impl NIZK {
506  fn protocol_name() -> &'static [u8] {
507    b"Spartan NIZK proof"
508  }
509
510  /// A method to produce a NIZK proof of the satisfiability of an R1CS instance
511  pub fn prove(
512    inst: &Instance,
513    vars: VarsAssignment,
514    input: &InputsAssignment,
515    gens: &NIZKGens,
516    transcript: &mut Transcript,
517  ) -> Self {
518    let timer_prove = Timer::new("NIZK::prove");
519    // we create a Transcript object seeded with a random Scalar
520    // to aid the prover produce its randomness
521    let mut random_tape = RandomTape::new(b"proof");
522
523    transcript.append_protocol_name(NIZK::protocol_name());
524    inst.inst.append_to_transcript(b"inst", transcript);
525
526    let (r1cs_sat_proof, rx, ry) = {
527      // we might need to pad variables
528      let padded_vars = {
529        let num_padded_vars = inst.inst.get_num_vars();
530        let num_vars = vars.assignment.len();
531        if num_padded_vars > num_vars {
532          vars.pad(num_padded_vars)
533        } else {
534          vars
535        }
536      };
537
538      let (proof, rx, ry) = R1CSProof::prove(
539        &inst.inst,
540        padded_vars.assignment,
541        &input.assignment,
542        &gens.gens_r1cs_sat,
543        transcript,
544        &mut random_tape,
545      );
546      let mut proof_encoded = Vec::new();
547      proof.serialize(&mut proof_encoded).unwrap();
548      Timer::print(&format!("len_r1cs_sat_proof {:?}", proof_encoded.len()));
549      (proof, rx, ry)
550    };
551
552    timer_prove.stop();
553    NIZK {
554      r1cs_sat_proof,
555      r: (rx, ry),
556    }
557  }
558
559  /// A method to verify a NIZK proof of the satisfiability of an R1CS instance
560  pub fn verify(
561    &self,
562    inst: &Instance,
563    input: &InputsAssignment,
564    transcript: &mut Transcript,
565    gens: &NIZKGens,
566  ) -> Result<(), ProofVerifyError> {
567    let timer_verify = Timer::new("NIZK::verify");
568
569    transcript.append_protocol_name(NIZK::protocol_name());
570    inst.inst.append_to_transcript(b"inst", transcript);
571
572    // We send evaluations of A, B, C at r = (rx, ry) as claims
573    // to enable the verifier complete the first sum-check
574    let timer_eval = Timer::new("eval_sparse_polys");
575    let (claimed_rx, claimed_ry) = &self.r;
576    let inst_evals = inst.inst.evaluate(claimed_rx, claimed_ry);
577    timer_eval.stop();
578
579    let timer_sat_proof = Timer::new("verify_sat_proof");
580    assert_eq!(input.assignment.len(), inst.inst.get_num_inputs());
581    let (rx, ry) = self.r1cs_sat_proof.verify(
582      inst.inst.get_num_vars(),
583      inst.inst.get_num_cons(),
584      &input.assignment,
585      &inst_evals,
586      transcript,
587      &gens.gens_r1cs_sat,
588    )?;
589
590    // verify if claimed rx and ry are correct
591    assert_eq!(rx, *claimed_rx);
592    assert_eq!(ry, *claimed_ry);
593    timer_sat_proof.stop();
594    timer_verify.stop();
595
596    Ok(())
597  }
598}
599
600#[cfg(test)]
601mod tests {
602  use super::*;
603  use ark_ff::{PrimeField};
604
605  #[test]
606  pub fn check_snark() {
607    let num_vars = 256;
608    let num_cons = num_vars;
609    let num_inputs = 10;
610
611    // produce public generators
612    let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_cons);
613
614    // produce a synthetic R1CSInstance
615    let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
616
617    // create a commitment to R1CSInstance
618    let (comm, decomm) = SNARK::encode(&inst, &gens);
619
620    // produce a proof
621    let mut prover_transcript = Transcript::new(b"example");
622    let proof = SNARK::prove(
623      &inst,
624      &comm,
625      &decomm,
626      vars,
627      &inputs,
628      &gens,
629      &mut prover_transcript,
630    );
631
632    // verify the proof
633    let mut verifier_transcript = Transcript::new(b"example");
634    assert!(proof
635      .verify(&comm, &inputs, &mut verifier_transcript, &gens)
636      .is_ok());
637  }
638
639  #[test]
640  pub fn check_r1cs_invalid_index() {
641    let num_cons = 4;
642    let num_vars = 8;
643    let num_inputs = 1;
644
645    let zero: [u8; 32] = [
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, 0, 0, 0, 0, 0,
647      0,
648    ];
649
650    let A = vec![(0, 0, zero.to_vec())];
651    let B = vec![(100, 1, zero.to_vec())];
652    let C = vec![(1, 1, zero.to_vec())];
653
654    let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C);
655    assert!(inst.is_err());
656    assert_eq!(inst.err(), Some(R1CSError::InvalidIndex));
657  }
658
659  #[test]
660  pub fn check_r1cs_invalid_scalar() {
661    let num_cons = 4;
662    let num_vars = 8;
663    let num_inputs = 1;
664
665    let zero: [u8; 32] = [
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, 0, 0, 0, 0, 0,
667      0,
668    ];
669
670    let larger_than_mod = [
671      3, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8, 216,
672      57, 51, 72, 125, 157, 41, 83, 167, 237, 115,
673    ];
674
675    let A = vec![(0, 0, zero.to_vec())];
676    let B = vec![(1, 1, larger_than_mod.to_vec())];
677    let C = vec![(1, 1, zero.to_vec())];
678
679    let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C);
680    assert!(inst.is_err());
681    assert_eq!(inst.err(), Some(R1CSError::InvalidScalar));
682  }
683
684  #[test]
685  fn test_padded_constraints() {
686    // parameters of the R1CS instance
687    let num_cons = 1;
688    let num_vars = 0;
689    let num_inputs = 3;
690    let num_non_zero_entries = 3;
691
692    // We will encode the above constraints into three matrices, where
693    // the coefficients in the matrix are in the little-endian byte order
694    let mut A: Vec<(usize, usize, Vec<u8>)> = Vec::new();
695    let mut B: Vec<(usize, usize, Vec<u8>)> = Vec::new();
696    let mut C: Vec<(usize, usize, Vec<u8>)> = Vec::new();
697
698    // Create a^2 + b + 13
699    A.push((0, num_vars + 2, (Scalar::one().into_repr().to_bytes_le()))); // 1*a
700    B.push((0, num_vars + 2, Scalar::one().into_repr().to_bytes_le())); // 1*a
701    C.push((0, num_vars + 1, Scalar::one().into_repr().to_bytes_le())); // 1*z
702    C.push((0, num_vars, (-Scalar::from(13u64)).into_repr().to_bytes_le())); // -13*1
703    C.push((0, num_vars + 3, (-Scalar::one()).into_repr().to_bytes_le())); // -1*b
704
705    // Var Assignments (Z_0 = 16 is the only output)
706    let vars = vec![Scalar::zero().into_repr().to_bytes_le(); num_vars];
707
708    // create an InputsAssignment (a = 1, b = 2)
709    let mut inputs = vec![Scalar::zero().into_repr().to_bytes_le(); num_inputs];
710    inputs[0] = Scalar::from(16u64).into_repr().to_bytes_le();
711    inputs[1] = Scalar::from(1u64).into_repr().to_bytes_le();
712    inputs[2] = Scalar::from(2u64).into_repr().to_bytes_le();
713
714    let assignment_inputs = InputsAssignment::new(&inputs).unwrap();
715    let assignment_vars = VarsAssignment::new(&vars).unwrap();
716
717    // Check if instance is satisfiable
718    let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C).unwrap();
719    let res = inst.is_sat(&assignment_vars, &assignment_inputs);
720    assert!(res.unwrap(), "should be satisfied");
721
722    // SNARK public params
723    let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_non_zero_entries);
724
725    // create a commitment to the R1CS instance
726    let (comm, decomm) = SNARK::encode(&inst, &gens);
727
728    // produce a SNARK
729    let mut prover_transcript = Transcript::new(b"snark_example");
730    let proof = SNARK::prove(
731      &inst,
732      &comm,
733      &decomm,
734      assignment_vars.clone(),
735      &assignment_inputs,
736      &gens,
737      &mut prover_transcript,
738    );
739
740    // verify the SNARK
741    let mut verifier_transcript = Transcript::new(b"snark_example");
742    assert!(proof
743      .verify(&comm, &assignment_inputs, &mut verifier_transcript, &gens)
744      .is_ok());
745
746    // NIZK public params
747    let gens = NIZKGens::new(num_cons, num_vars, num_inputs);
748
749    // produce a NIZK
750    let mut prover_transcript = Transcript::new(b"nizk_example");
751    let proof = NIZK::prove(
752      &inst,
753      assignment_vars,
754      &assignment_inputs,
755      &gens,
756      &mut prover_transcript,
757    );
758
759    // verify the NIZK
760    let mut verifier_transcript = Transcript::new(b"nizk_example");
761    assert!(proof
762      .verify(&inst, &assignment_inputs, &mut verifier_transcript, &gens)
763      .is_ok());
764  }
765}