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 self.r1cs_eval_proof.verify(
445 &comm.comm,
446 &rx,
447 &ry,
448 &self.inst_evals,
449 &gens.gens_r1cs_eval,
450 transcript,
451 )?;
452 timer_eval_proof.stop();
453 timer_verify.stop();
454 Ok(())
455 }
456}
457
458/// `NIZKGens` holds public parameters for producing and verifying proofs with the Spartan NIZK
459pub struct NIZKGens {
460 gens_r1cs_sat: R1CSGens,
461}
462
463impl NIZKGens {
464 /// Constructs a new `NIZKGens` given the size of the R1CS statement
465 pub fn new(num_cons: usize, num_vars: usize, num_inputs: usize) -> Self {
466 let num_vars_padded = {
467 let mut num_vars_padded = max(num_vars, num_inputs + 1);
468 if num_vars_padded != num_vars_padded.next_power_of_two() {
469 num_vars_padded = num_vars_padded.next_power_of_two();
470 }
471 num_vars_padded
472 };
473
474 let gens_r1cs_sat = R1CSGens::new(b"gens_r1cs_sat", num_cons, num_vars_padded);
475 NIZKGens { gens_r1cs_sat }
476 }
477}
478
479/// `NIZK` holds a proof produced by Spartan NIZK
480#[derive(Serialize, Deserialize, Debug)]
481pub struct NIZK {
482 r1cs_sat_proof: R1CSProof,
483 r: (Vec<Scalar>, Vec<Scalar>),
484}
485
486impl NIZK {
487 fn protocol_name() -> &'static [u8] {
488 b"Spartan NIZK proof"
489 }
490
491 /// A method to produce a NIZK proof of the satisfiability of an R1CS instance
492 pub fn prove(
493 inst: &Instance,
494 vars: VarsAssignment,
495 input: &InputsAssignment,
496 gens: &NIZKGens,
497 transcript: &mut Transcript,
498 ) -> Self {
499 let timer_prove = Timer::new("NIZK::prove");
500 // we create a Transcript object seeded with a random Scalar
501 // to aid the prover produce its randomness
502 let mut random_tape = RandomTape::new(b"proof");
503 transcript.append_protocol_name(NIZK::protocol_name());
504 let (r1cs_sat_proof, rx, ry) = {
505 // we might need to pad variables
506 let padded_vars = {
507 let num_padded_vars = inst.inst.get_num_vars();
508 let num_vars = vars.assignment.len();
509 if num_padded_vars > num_vars {
510 vars.pad(num_padded_vars)
511 } else {
512 vars
513 }
514 };
515
516 let (proof, rx, ry) = R1CSProof::prove(
517 &inst.inst,
518 padded_vars.assignment,
519 &input.assignment,
520 &gens.gens_r1cs_sat,
521 transcript,
522 &mut random_tape,
523 );
524 let proof_encoded: Vec<u8> = bincode::serialize(&proof).unwrap();
525 Timer::print(&format!("len_r1cs_sat_proof {:?}", proof_encoded.len()));
526 (proof, rx, ry)
527 };
528
529 timer_prove.stop();
530 NIZK {
531 r1cs_sat_proof,
532 r: (rx, ry),
533 }
534 }
535
536 /// A method to verify a NIZK proof of the satisfiability of an R1CS instance
537 pub fn verify(
538 &self,
539 inst: &Instance,
540 input: &InputsAssignment,
541 transcript: &mut Transcript,
542 gens: &NIZKGens,
543 ) -> Result<(), ProofVerifyError> {
544 let timer_verify = Timer::new("NIZK::verify");
545
546 transcript.append_protocol_name(NIZK::protocol_name());
547
548 // We send evaluations of A, B, C at r = (rx, ry) as claims
549 // to enable the verifier complete the first sum-check
550 let timer_eval = Timer::new("eval_sparse_polys");
551 let (claimed_rx, claimed_ry) = &self.r;
552 let inst_evals = inst.inst.evaluate(claimed_rx, claimed_ry);
553 timer_eval.stop();
554
555 let timer_sat_proof = Timer::new("verify_sat_proof");
556 assert_eq!(input.assignment.len(), inst.inst.get_num_inputs());
557 let (rx, ry) = self.r1cs_sat_proof.verify(
558 inst.inst.get_num_vars(),
559 inst.inst.get_num_cons(),
560 &input.assignment,
561 &inst_evals,
562 transcript,
563 &gens.gens_r1cs_sat,
564 )?;
565
566 // verify if claimed rx and ry are correct
567 assert_eq!(rx, *claimed_rx);
568 assert_eq!(ry, *claimed_ry);
569 timer_sat_proof.stop();
570 timer_verify.stop();
571
572 Ok(())
573 }
574}
575
576#[cfg(test)]
577mod tests {
578 use super::*;
579
580 #[test]
581 pub fn check_snark() {
582 let num_vars = 256;
583 let num_cons = num_vars;
584 let num_inputs = 10;
585
586 // produce public generators
587 let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_cons);
588
589 // produce a synthetic R1CSInstance
590 let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
591
592 // create a commitment to R1CSInstance
593 let (comm, decomm) = SNARK::encode(&inst, &gens);
594
595 // produce a proof
596 let mut prover_transcript = Transcript::new(b"example");
597 let proof = SNARK::prove(&inst, &decomm, vars, &inputs, &gens, &mut prover_transcript);
598
599 // verify the proof
600 let mut verifier_transcript = Transcript::new(b"example");
601 assert!(proof
602 .verify(&comm, &inputs, &mut verifier_transcript, &gens)
603 .is_ok());
604 }
605
606 #[test]
607 pub fn check_r1cs_invalid_index() {
608 let num_cons = 4;
609 let num_vars = 8;
610 let num_inputs = 1;
611
612 let zero: [u8; 32] = [
613 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,
614 0,
615 ];
616
617 let A = vec![(0, 0, zero)];
618 let B = vec![(100, 1, zero)];
619 let C = vec![(1, 1, zero)];
620
621 let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C);
622 assert!(inst.is_err());
623 assert_eq!(inst.err(), Some(R1CSError::InvalidIndex));
624 }
625
626 #[test]
627 pub fn check_r1cs_invalid_scalar() {
628 let num_cons = 4;
629 let num_vars = 8;
630 let num_inputs = 1;
631
632 let zero: [u8; 32] = [
633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
634 0,
635 ];
636
637 let larger_than_mod = [
638 3, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8, 216,
639 57, 51, 72, 125, 157, 41, 83, 167, 237, 115,
640 ];
641
642 let A = vec![(0, 0, zero)];
643 let B = vec![(1, 1, larger_than_mod)];
644 let C = vec![(1, 1, zero)];
645
646 let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C);
647 assert!(inst.is_err());
648 assert_eq!(inst.err(), Some(R1CSError::InvalidScalar));
649 }
650
651 #[test]
652 fn test_padded_constraints() {
653 // parameters of the R1CS instance
654 let num_cons = 1;
655 let num_vars = 0;
656 let num_inputs = 3;
657 let num_non_zero_entries = 3;
658
659 // We will encode the above constraints into three matrices, where
660 // the coefficients in the matrix are in the little-endian byte order
661 let mut A: Vec<(usize, usize, [u8; 32])> = Vec::new();
662 let mut B: Vec<(usize, usize, [u8; 32])> = Vec::new();
663 let mut C: Vec<(usize, usize, [u8; 32])> = Vec::new();
664
665 // Create a^2 + b + 13
666 A.push((0, num_vars + 2, Scalar::one().to_bytes())); // 1*a
667 B.push((0, num_vars + 2, Scalar::one().to_bytes())); // 1*a
668 C.push((0, num_vars + 1, Scalar::one().to_bytes())); // 1*z
669 C.push((0, num_vars, (-Scalar::from(13u64)).to_bytes())); // -13*1
670 C.push((0, num_vars + 3, (-Scalar::one()).to_bytes())); // -1*b
671
672 // Var Assignments (Z_0 = 16 is the only output)
673 let vars = vec![Scalar::zero().to_bytes(); num_vars];
674
675 // create an InputsAssignment (a = 1, b = 2)
676 let mut inputs = vec![Scalar::zero().to_bytes(); num_inputs];
677 inputs[0] = Scalar::from(16u64).to_bytes();
678 inputs[1] = Scalar::from(1u64).to_bytes();
679 inputs[2] = Scalar::from(2u64).to_bytes();
680
681 let assignment_inputs = InputsAssignment::new(&inputs).unwrap();
682 let assignment_vars = VarsAssignment::new(&vars).unwrap();
683
684 // Check if instance is satisfiable
685 let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C).unwrap();
686 let res = inst.is_sat(&assignment_vars, &assignment_inputs);
687 assert!(res.unwrap(), "should be satisfied");
688
689 // SNARK public params
690 let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_non_zero_entries);
691
692 // create a commitment to the R1CS instance
693 let (comm, decomm) = SNARK::encode(&inst, &gens);
694
695 // produce a SNARK
696 let mut prover_transcript = Transcript::new(b"snark_example");
697 let proof = SNARK::prove(
698 &inst,
699 &decomm,
700 assignment_vars.clone(),
701 &assignment_inputs,
702 &gens,
703 &mut prover_transcript,
704 );
705
706 // verify the SNARK
707 let mut verifier_transcript = Transcript::new(b"snark_example");
708 assert!(proof
709 .verify(&comm, &assignment_inputs, &mut verifier_transcript, &gens)
710 .is_ok());
711
712 // NIZK public params
713 let gens = NIZKGens::new(num_cons, num_vars, num_inputs);
714
715 // produce a NIZK
716 let mut prover_transcript = Transcript::new(b"nizk_example");
717 let proof = NIZK::prove(
718 &inst,
719 assignment_vars,
720 &assignment_inputs,
721 &gens,
722 &mut prover_transcript,
723 );
724
725 // verify the NIZK
726 let mut verifier_transcript = Transcript::new(b"nizk_example");
727 assert!(proof
728 .verify(&inst, &assignment_inputs, &mut verifier_transcript, &gens)
729 .is_ok());
730 }
731}