testudo/src/r1csproof.rs
src/r1csproof.rsRaw
1use super::commitments::{Commitments, MultiCommitGens};
2use super::dense_mlpoly::{
3 DensePolynomial, EqPolynomial, PolyCommitment, PolyCommitmentGens, PolyEvalProof,
4};
5use super::errors::ProofVerifyError;
6use super::group::{CompressedGroup, GroupElement, VartimeMultiscalarMul};
7use super::math::Math;
8use super::nizk::{EqualityProof, KnowledgeProof, ProductProof};
9use super::r1csinstance::{R1CSInstance, R1CSInstanceEvals};
10use super::scalar::Scalar;
11use super::sparse_mlpoly::{SparsePolyEntry, SparsePolynomial};
12use super::sumcheck::ZKSumcheckInstanceProof;
13use super::timer::Timer;
14use super::transcript::{AppendToTranscript, ProofTranscript};
15use merlin::Transcript;
16use serde::{Deserialize, Serialize};
17use std::iter;
18
19#[cfg(test)]
20use super::sparse_mlpoly::{SparseMatEntry, SparseMatPolynomial};
21
22#[derive(Serialize, Deserialize, Debug)]
23pub struct R1CSProof {
24 comm_vars: PolyCommitment,
25 sc_proof_phase1: ZKSumcheckInstanceProof,
26 claims_phase2: (
27 CompressedGroup,
28 CompressedGroup,
29 CompressedGroup,
30 CompressedGroup,
31 ),
32 pok_claims_phase2: (KnowledgeProof, ProductProof),
33 proof_eq_sc_phase1: EqualityProof,
34 sc_proof_phase2: ZKSumcheckInstanceProof,
35 comm_vars_at_ry: CompressedGroup,
36 proof_eval_vars_at_ry: PolyEvalProof,
37 proof_eq_sc_phase2: EqualityProof,
38}
39
40pub struct R1CSSumcheckGens {
41 gens_1: MultiCommitGens,
42 gens_3: MultiCommitGens,
43 gens_4: MultiCommitGens,
44}
45
46// TODO: fix passing gens_1_ref
47impl R1CSSumcheckGens {
48 pub fn new(label: &'static [u8], gens_1_ref: &MultiCommitGens) -> Self {
49 let gens_1 = gens_1_ref.clone();
50 let gens_3 = MultiCommitGens::new(3, label);
51 let gens_4 = MultiCommitGens::new(4, label);
52
53 R1CSSumcheckGens {
54 gens_1,
55 gens_3,
56 gens_4,
57 }
58 }
59}
60
61pub struct R1CSGens {
62 gens_sc: R1CSSumcheckGens,
63 gens_pc: PolyCommitmentGens,
64}
65
66impl R1CSGens {
67 pub fn new(_num_cons: usize, num_vars: usize, label: &'static [u8]) -> Self {
68 let num_poly_vars = num_vars.log2();
69 let gens_pc = PolyCommitmentGens::new(num_poly_vars, label);
70 let gens_sc = R1CSSumcheckGens::new(label, &gens_pc.gens.gens_1);
71 R1CSGens { gens_sc, gens_pc }
72 }
73}
74
75impl R1CSProof {
76 fn prove_phase_one(
77 num_rounds: usize,
78 evals_tau: &mut DensePolynomial,
79 evals_Az: &mut DensePolynomial,
80 evals_Bz: &mut DensePolynomial,
81 evals_Cz: &mut DensePolynomial,
82 gens: &R1CSSumcheckGens,
83 transcript: &mut Transcript,
84 random_tape: &mut Transcript,
85 ) -> (ZKSumcheckInstanceProof, Vec<Scalar>, Vec<Scalar>, Scalar) {
86 let comb_func = |poly_A_comp: &Scalar,
87 poly_B_comp: &Scalar,
88 poly_C_comp: &Scalar,
89 poly_D_comp: &Scalar|
90 -> Scalar { poly_A_comp * (poly_B_comp * poly_C_comp - poly_D_comp) };
91
92 let (sc_proof_phase_one, r, claims, blind_claim_postsc) =
93 ZKSumcheckInstanceProof::prove_cubic_with_additive_term(
94 &Scalar::zero(), // claim is zero
95 &Scalar::zero(), // blind for claim is also zero
96 num_rounds,
97 evals_tau,
98 evals_Az,
99 evals_Bz,
100 evals_Cz,
101 comb_func,
102 &gens.gens_1,
103 &gens.gens_4,
104 transcript,
105 random_tape,
106 );
107
108 (sc_proof_phase_one, r, claims, blind_claim_postsc)
109 }
110
111 fn prove_phase_two(
112 num_rounds: usize,
113 claim: &Scalar,
114 blind_claim: &Scalar,
115 evals_z: &mut DensePolynomial,
116 evals_ABC: &mut DensePolynomial,
117 gens: &R1CSSumcheckGens,
118 transcript: &mut Transcript,
119 random_tape: &mut Transcript,
120 ) -> (ZKSumcheckInstanceProof, Vec<Scalar>, Vec<Scalar>, Scalar) {
121 let comb_func =
122 |poly_A_comp: &Scalar, poly_B_comp: &Scalar| -> Scalar { poly_A_comp * poly_B_comp };
123 let (sc_proof_phase_two, r, claims, blind_claim_postsc) = ZKSumcheckInstanceProof::prove_quad(
124 claim,
125 blind_claim,
126 num_rounds,
127 evals_z,
128 evals_ABC,
129 comb_func,
130 &gens.gens_1,
131 &gens.gens_3,
132 transcript,
133 random_tape,
134 );
135
136 (sc_proof_phase_two, r, claims, blind_claim_postsc)
137 }
138
139 fn protocol_name() -> &'static [u8] {
140 b"R1CS proof"
141 }
142
143 pub fn prove(
144 inst: &R1CSInstance,
145 vars: Vec<Scalar>,
146 input: &Vec<Scalar>,
147 gens: &R1CSGens,
148 transcript: &mut Transcript,
149 random_tape: &mut Transcript,
150 ) -> (R1CSProof, Vec<Scalar>, Vec<Scalar>) {
151 let timer_prove = Timer::new("R1CSProof::prove");
152 transcript.append_protocol_name(R1CSProof::protocol_name());
153
154 // we currently require the number of |inputs| + 1 to be at most number of vars
155 assert!(input.len() + 1 <= vars.len());
156
157 let timer_commit = Timer::new("polycommit");
158 let (poly_vars, comm_vars, blinds_vars) = {
159 // create a multilinear polynomial using the supplied assignment for variables
160 let poly_vars = DensePolynomial::new(vars.clone());
161
162 // produce a commitment to the satisfying assignment
163 let (comm_vars, blinds_vars) = poly_vars.commit(true, &gens.gens_pc, Some(random_tape));
164
165 // add the commitment to the prover's transcript
166 comm_vars.append_to_transcript(b"poly_commitment", transcript);
167 (poly_vars, comm_vars, blinds_vars)
168 };
169 timer_commit.stop();
170
171 let timer_sc_proof_phase1 = Timer::new("prove_sc_phase_one");
172
173 // append input to variables to create a single vector z
174 let z = {
175 let num_inputs = input.len();
176 let num_vars = vars.len();
177 let mut z = vars;
178 z.extend(&vec![Scalar::one()]); // add constant term in z
179 z.extend(input);
180 z.extend(&vec![Scalar::zero(); num_vars - num_inputs - 1]); // we will pad with zeros
181 z
182 };
183
184 // derive the verifier's challenge tau
185 let (num_rounds_x, num_rounds_y) = (inst.get_num_cons().log2(), z.len().log2());
186 let tau = transcript.challenge_vector(b"challenge_tau", num_rounds_x);
187 // compute the initial evaluation table for R(\tau, x)
188 let mut poly_tau = DensePolynomial::new(EqPolynomial::new(tau.clone()).evals());
189 let (mut poly_Az, mut poly_Bz, mut poly_Cz) =
190 inst.multiply_vec(inst.get_num_cons(), z.len(), &z);
191
192 let (sc_proof_phase1, rx, _claims_phase1, blind_claim_postsc1) = R1CSProof::prove_phase_one(
193 num_rounds_x,
194 &mut poly_tau,
195 &mut poly_Az,
196 &mut poly_Bz,
197 &mut poly_Cz,
198 &gens.gens_sc,
199 transcript,
200 random_tape,
201 );
202 assert_eq!(poly_tau.len(), 1);
203 assert_eq!(poly_Az.len(), 1);
204 assert_eq!(poly_Bz.len(), 1);
205 assert_eq!(poly_Cz.len(), 1);
206 timer_sc_proof_phase1.stop();
207
208 let (tau_claim, Az_claim, Bz_claim, Cz_claim) =
209 (&poly_tau[0], &poly_Az[0], &poly_Bz[0], &poly_Cz[0]);
210 let (Az_blind, Bz_blind, Cz_blind, prod_Az_Bz_blind) = (
211 random_tape.challenge_scalar(b"Az_blind"),
212 random_tape.challenge_scalar(b"Bz_blind"),
213 random_tape.challenge_scalar(b"Cz_blind"),
214 random_tape.challenge_scalar(b"prod_Az_Bz_blind"),
215 );
216
217 let (pok_Cz_claim, comm_Cz_claim) = {
218 KnowledgeProof::prove(
219 &gens.gens_sc.gens_1,
220 transcript,
221 random_tape,
222 &Cz_claim,
223 &Cz_blind,
224 )
225 };
226
227 let (proof_prod, comm_Az_claim, comm_Bz_claim, comm_prod_Az_Bz_claims) = {
228 let prod = Az_claim * Bz_claim;
229 ProductProof::prove(
230 &gens.gens_sc.gens_1,
231 transcript,
232 random_tape,
233 &Az_claim,
234 &Az_blind,
235 &Bz_claim,
236 &Bz_blind,
237 &prod,
238 &prod_Az_Bz_blind,
239 )
240 };
241
242 comm_Az_claim.append_to_transcript(b"comm_Az_claim", transcript);
243 comm_Bz_claim.append_to_transcript(b"comm_Bz_claim", transcript);
244 comm_Cz_claim.append_to_transcript(b"comm_Cz_claim", transcript);
245 comm_prod_Az_Bz_claims.append_to_transcript(b"comm_prod_Az_Bz_claims", transcript);
246
247 // prove the final step of sum-check #1
248 let taus_bound_rx = tau_claim;
249 let blind_expected_claim_postsc1 = taus_bound_rx * (&prod_Az_Bz_blind - &Cz_blind);
250 let claim_post_phase1 = (Az_claim * Bz_claim - Cz_claim) * taus_bound_rx;
251 let (proof_eq_sc_phase1, _C1, _C2) = EqualityProof::prove(
252 &gens.gens_sc.gens_1,
253 transcript,
254 random_tape,
255 &claim_post_phase1,
256 &blind_expected_claim_postsc1,
257 &claim_post_phase1,
258 &blind_claim_postsc1,
259 );
260
261 let timer_sc_proof_phase2 = Timer::new("prove_sc_phase_two");
262 // combine the three claims into a single claim
263 let r_A = transcript.challenge_scalar(b"challenege_Az");
264 let r_B = transcript.challenge_scalar(b"challenege_Bz");
265 let r_C = transcript.challenge_scalar(b"challenege_Cz");
266 let claim_phase2 = &r_A * Az_claim + &r_B * Bz_claim + &r_C * Cz_claim;
267 let blind_claim_phase2 = &r_A * Az_blind + &r_B * Bz_blind + &r_C * Cz_blind;
268
269 let evals_ABC = {
270 // compute the initial evaluation table for R(\tau, x)
271 let evals_rx = EqPolynomial::new(rx.clone()).evals();
272 let (evals_A, evals_B, evals_C) =
273 inst.compute_eval_table_sparse(inst.get_num_cons(), z.len(), &evals_rx);
274
275 assert_eq!(evals_A.len(), evals_B.len());
276 assert_eq!(evals_A.len(), evals_C.len());
277 (0..evals_A.len())
278 .map(|i| &r_A * &evals_A[i] + &r_B * &evals_B[i] + &r_C * &evals_C[i])
279 .collect::<Vec<Scalar>>()
280 };
281
282 // another instance of the sum-check protocol
283 let (sc_proof_phase2, ry, claims_phase2, blind_claim_postsc2) = R1CSProof::prove_phase_two(
284 num_rounds_y,
285 &claim_phase2,
286 &blind_claim_phase2,
287 &mut DensePolynomial::new(z),
288 &mut DensePolynomial::new(evals_ABC),
289 &gens.gens_sc,
290 transcript,
291 random_tape,
292 );
293 timer_sc_proof_phase2.stop();
294
295 let timer_polyeval = Timer::new("polyeval");
296 let eval_vars_at_ry = poly_vars.evaluate(&ry[1..].to_vec());
297 let blind_eval = random_tape.challenge_scalar(b"blind_eval");
298 let (proof_eval_vars_at_ry, comm_vars_at_ry) = PolyEvalProof::prove(
299 &poly_vars,
300 Some(&blinds_vars),
301 &ry[1..].to_vec(),
302 &eval_vars_at_ry,
303 Some(&blind_eval),
304 &gens.gens_pc,
305 transcript,
306 random_tape,
307 );
308 timer_polyeval.stop();
309
310 // prove the final step of sum-check #2
311 let blind_eval_Z_at_ry = (Scalar::one() - &ry[0]) * blind_eval;
312 let blind_expected_claim_postsc2 = &claims_phase2[1] * &blind_eval_Z_at_ry;
313 let claim_post_phase2 = &claims_phase2[0] * &claims_phase2[1];
314 let (proof_eq_sc_phase2, _C1, _C2) = EqualityProof::prove(
315 &gens.gens_pc.gens.gens_1,
316 transcript,
317 random_tape,
318 &claim_post_phase2,
319 &blind_expected_claim_postsc2,
320 &claim_post_phase2,
321 &blind_claim_postsc2,
322 );
323
324 timer_prove.stop();
325
326 (
327 R1CSProof {
328 comm_vars,
329 sc_proof_phase1,
330 claims_phase2: (
331 comm_Az_claim,
332 comm_Bz_claim,
333 comm_Cz_claim,
334 comm_prod_Az_Bz_claims,
335 ),
336 pok_claims_phase2: (pok_Cz_claim, proof_prod),
337 proof_eq_sc_phase1,
338 sc_proof_phase2,
339 comm_vars_at_ry,
340 proof_eval_vars_at_ry,
341 proof_eq_sc_phase2,
342 },
343 rx,
344 ry,
345 )
346 }
347
348 pub fn verify(
349 &self,
350 num_vars: usize,
351 num_cons: usize,
352 input: &Vec<Scalar>,
353 evals: &R1CSInstanceEvals,
354 transcript: &mut Transcript,
355 gens: &R1CSGens,
356 ) -> Result<(Vec<Scalar>, Vec<Scalar>), ProofVerifyError> {
357 transcript.append_protocol_name(R1CSProof::protocol_name());
358
359 let n = num_vars;
360 // add the commitment to the verifier's transcript
361 self
362 .comm_vars
363 .append_to_transcript(b"poly_commitment", transcript);
364
365 let (num_rounds_x, num_rounds_y) = (num_cons.log2(), (2 * num_vars).log2());
366
367 // derive the verifier's challenge tau
368 let tau = transcript.challenge_vector(b"challenge_tau", num_rounds_x);
369
370 // verify the first sum-check instance
371 let claim_phase1 = Scalar::zero()
372 .commit(&Scalar::zero(), &gens.gens_sc.gens_1)
373 .compress();
374 let (comm_claim_post_phase1, rx) = self
375 .sc_proof_phase1
376 .verify(
377 &claim_phase1,
378 num_rounds_x,
379 3,
380 &gens.gens_sc.gens_1,
381 &gens.gens_sc.gens_4,
382 transcript,
383 )
384 .unwrap();
385
386 // perform the intermediate sum-check test with claimed Az, Bz, and Cz
387 let (comm_Az_claim, comm_Bz_claim, comm_Cz_claim, comm_prod_Az_Bz_claims) = &self.claims_phase2;
388 let (pok_Cz_claim, proof_prod) = &self.pok_claims_phase2;
389
390 assert!(pok_Cz_claim
391 .verify(&gens.gens_sc.gens_1, transcript, &comm_Cz_claim)
392 .is_ok());
393 assert!(proof_prod
394 .verify(
395 &gens.gens_sc.gens_1,
396 transcript,
397 &comm_Az_claim,
398 &comm_Bz_claim,
399 &comm_prod_Az_Bz_claims
400 )
401 .is_ok());
402
403 comm_Az_claim.append_to_transcript(b"comm_Az_claim", transcript);
404 comm_Bz_claim.append_to_transcript(b"comm_Bz_claim", transcript);
405 comm_Cz_claim.append_to_transcript(b"comm_Cz_claim", transcript);
406 comm_prod_Az_Bz_claims.append_to_transcript(b"comm_prod_Az_Bz_claims", transcript);
407
408 let taus_bound_rx: Scalar = (0..rx.len())
409 .map(|i| &rx[i] * &tau[i] + (&Scalar::one() - &rx[i]) * (&Scalar::one() - &tau[i]))
410 .product();
411 let expected_claim_post_phase1 = (&taus_bound_rx
412 * (comm_prod_Az_Bz_claims.decompress().unwrap() - comm_Cz_claim.decompress().unwrap()))
413 .compress();
414
415 // verify proof that expected_claim_post_phase1 == claim_post_phase1
416 assert!(self
417 .proof_eq_sc_phase1
418 .verify(
419 &gens.gens_sc.gens_1,
420 transcript,
421 &expected_claim_post_phase1,
422 &comm_claim_post_phase1,
423 )
424 .is_ok());
425
426 // derive three public challenges and then derive a joint claim
427 let r_A = transcript.challenge_scalar(b"challenege_Az");
428 let r_B = transcript.challenge_scalar(b"challenege_Bz");
429 let r_C = transcript.challenge_scalar(b"challenege_Cz");
430
431 // r_A * comm_Az_claim + r_B * comm_Bz_claim + r_C * comm_Cz_claim;
432 let comm_claim_phase2 = GroupElement::vartime_multiscalar_mul(
433 iter::once(&r_A)
434 .chain(iter::once(&r_B))
435 .chain(iter::once(&r_C)),
436 iter::once(&comm_Az_claim)
437 .chain(iter::once(&comm_Bz_claim))
438 .chain(iter::once(&comm_Cz_claim))
439 .map(|pt| pt.decompress().unwrap())
440 .collect::<Vec<GroupElement>>(),
441 )
442 .compress();
443
444 // verify the joint claim with a sum-check protocol
445 let (comm_claim_post_phase2, ry) = self
446 .sc_proof_phase2
447 .verify(
448 &comm_claim_phase2,
449 num_rounds_y,
450 2,
451 &gens.gens_sc.gens_1,
452 &gens.gens_sc.gens_3,
453 transcript,
454 )
455 .unwrap();
456
457 // verify Z(ry) proof against the initial commitment
458 assert!(self
459 .proof_eval_vars_at_ry
460 .verify(
461 &gens.gens_pc,
462 transcript,
463 &ry[1..].to_vec(),
464 &self.comm_vars_at_ry,
465 &self.comm_vars
466 )
467 .is_ok());
468
469 let poly_input_eval = {
470 // constant term
471 let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, Scalar::one())];
472 //remaining inputs
473 input_as_sparse_poly_entries.extend(
474 (0..input.len())
475 .map(|i| SparsePolyEntry::new(i + 1, input[i]))
476 .collect::<Vec<SparsePolyEntry>>(),
477 );
478 SparsePolynomial::new(n.log2(), input_as_sparse_poly_entries).evaluate(&ry[1..].to_vec())
479 };
480
481 // compute commitment to eval_Z_at_ry = (Scalar::one() - ry[0]) * self.eval_vars_at_ry + ry[0] * poly_input_eval
482 let comm_eval_Z_at_ry = GroupElement::vartime_multiscalar_mul(
483 iter::once(Scalar::one() - &ry[0]).chain(iter::once(ry[0])),
484 iter::once(&self.comm_vars_at_ry.decompress().unwrap()).chain(iter::once(
485 &poly_input_eval.commit(&Scalar::zero(), &gens.gens_pc.gens.gens_1),
486 )),
487 );
488
489 // perform the final check in the second sum-check protocol
490 let (eval_A_r, eval_B_r, eval_C_r) = evals.get_evaluations();
491 let expected_claim_post_phase2 =
492 (&(&r_A * &eval_A_r + &r_B * &eval_B_r + &r_C * &eval_C_r) * comm_eval_Z_at_ry).compress();
493 // verify proof that expected_claim_post_phase1 == claim_post_phase1
494 assert!(self
495 .proof_eq_sc_phase2
496 .verify(
497 &gens.gens_sc.gens_1,
498 transcript,
499 &expected_claim_post_phase2,
500 &comm_claim_post_phase2,
501 )
502 .is_ok());
503
504 Ok((rx, ry))
505 }
506}
507
508#[cfg(test)]
509mod tests {
510 use super::*;
511 use rand::rngs::OsRng;
512
513 fn produce_tiny_r1cs() -> (R1CSInstance, Vec<Scalar>, Vec<Scalar>) {
514 // three constraints over five variables Z1, Z2, Z3, Z4, and Z5
515 // rounded to the nearest power of two
516 let num_cons = 128;
517 let num_vars = 256;
518 let num_inputs = 2;
519
520 // encode the above constraints into three matrices
521 let mut A: Vec<SparseMatEntry> = Vec::new();
522 let mut B: Vec<SparseMatEntry> = Vec::new();
523 let mut C: Vec<SparseMatEntry> = Vec::new();
524
525 let one = Scalar::one();
526 // constraint 0 entries
527 // (Z1 + Z2) * I0 - Z3 = 0;
528 A.push(SparseMatEntry::new(0, 0, one));
529 A.push(SparseMatEntry::new(0, 1, one));
530 B.push(SparseMatEntry::new(0, num_vars + 1, one));
531 C.push(SparseMatEntry::new(0, 2, one));
532
533 // constraint 1 entries
534 // (Z1 + I1) * (Z3) - Z4 = 0
535 A.push(SparseMatEntry::new(1, 0, one));
536 A.push(SparseMatEntry::new(1, num_vars + 2, one));
537 B.push(SparseMatEntry::new(1, 2, one));
538 C.push(SparseMatEntry::new(1, 3, one));
539 // constraint 3 entries
540 // Z5 * 1 - 0 = 0
541 A.push(SparseMatEntry::new(2, 4, one));
542 B.push(SparseMatEntry::new(2, num_vars, one));
543
544 let num_vars_x = num_cons.log2();
545 let num_vars_y = (2 * num_vars).log2();
546
547 let poly_A = SparseMatPolynomial::new(num_vars_x, num_vars_y, A);
548 let poly_B = SparseMatPolynomial::new(num_vars_x, num_vars_y, B);
549 let poly_C = SparseMatPolynomial::new(num_vars_x, num_vars_y, C);
550
551 let inst = R1CSInstance::new(num_cons, num_vars, num_inputs, poly_A, poly_B, poly_C);
552
553 // compute a satisfying assignment
554 let mut csprng: OsRng = OsRng;
555 let i0 = Scalar::random(&mut csprng);
556 let i1 = Scalar::random(&mut csprng);
557 let z1 = Scalar::random(&mut csprng);
558 let z2 = Scalar::random(&mut csprng);
559 let z3 = (z1 + z2) * i0; // constraint 1: (Z1 + Z2) * I0 - Z3 = 0;
560 let z4 = (z1 + i1) * z3; // constraint 2: (Z1 + I1) * (Z3) - Z4 = 0
561 let z5 = Scalar::zero(); //constraint 3
562
563 let mut vars = vec![Scalar::zero(); num_vars];
564 vars[0] = z1;
565 vars[1] = z2;
566 vars[2] = z3;
567 vars[3] = z4;
568 vars[4] = z5;
569
570 let mut input = vec![Scalar::zero(); num_inputs];
571 input[0] = i0;
572 input[1] = i1;
573
574 (inst, vars, input)
575 }
576
577 #[test]
578 fn test_tiny_r1cs() {
579 let (inst, vars, input) = tests::produce_tiny_r1cs();
580 let is_sat = inst.is_sat(&vars, &input);
581 assert_eq!(is_sat, true);
582 }
583
584 #[test]
585 fn test_synthetic_r1cs() {
586 let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(1024, 1024, 10);
587 let is_sat = inst.is_sat(&vars, &input);
588 assert_eq!(is_sat, true);
589 }
590
591 #[test]
592 pub fn check_r1cs_proof() {
593 let num_vars = 1024;
594 let num_cons = num_vars;
595 let num_inputs = 10;
596 let (inst, vars, input) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
597
598 let gens = R1CSGens::new(num_cons, num_vars, b"test-m");
599
600 let mut random_tape = {
601 let mut csprng: OsRng = OsRng;
602 let mut tape = Transcript::new(b"proof");
603 tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
604 tape
605 };
606 let mut prover_transcript = Transcript::new(b"example");
607 let (proof, rx, ry) = R1CSProof::prove(
608 &inst,
609 vars,
610 &input,
611 &gens,
612 &mut prover_transcript,
613 &mut random_tape,
614 );
615
616 let eval_table_rx = EqPolynomial::new(rx).evals();
617 let eval_table_ry = EqPolynomial::new(ry).evals();
618 let inst_evals = inst.evaluate_with_tables(&eval_table_rx, &eval_table_ry);
619
620 let mut verifier_transcript = Transcript::new(b"example");
621 assert!(proof
622 .verify(
623 inst.get_num_vars(),
624 inst.get_num_cons(),
625 &input,
626 &inst_evals,
627 &mut verifier_transcript,
628 &gens,
629 )
630 .is_ok());
631 }
632}