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