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