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