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