testudo/src/nizk.rs
src/nizk.rsRaw
1use super::bullet::BulletReductionProof;
2use super::commitments::{Commitments, MultiCommitGens};
3use super::errors::ProofVerifyError;
4use super::group::CompressedGroup;
5use super::math::Math;
6use super::scalar::Scalar;
7use super::transcript::{AppendToTranscript, ProofTranscript};
8use merlin::Transcript;
9use serde::{Deserialize, Serialize};
10
11#[derive(Serialize, Deserialize, Debug)]
12pub struct KnowledgeProof {
13 alpha: CompressedGroup,
14 z1: Scalar,
15 z2: Scalar,
16}
17
18impl KnowledgeProof {
19 fn protocol_name() -> &'static [u8] {
20 b"knowledge proof"
21 }
22
23 pub fn prove(
24 gens_n: &MultiCommitGens,
25 transcript: &mut Transcript,
26 random_tape: &mut Transcript,
27 x: &Scalar,
28 r: &Scalar,
29 ) -> (KnowledgeProof, CompressedGroup) {
30 transcript.append_protocol_name(KnowledgeProof::protocol_name());
31
32 // produce two random Scalars
33 let t1 = random_tape.challenge_scalar(b"t1");
34 let t2 = random_tape.challenge_scalar(b"t2");
35
36 let C = x.commit(&r, gens_n).compress();
37 C.append_to_transcript(b"C", transcript);
38
39 let alpha = t1.commit(&t2, gens_n).compress();
40 alpha.append_to_transcript(b"alpha", transcript);
41
42 let c = transcript.challenge_scalar(b"c");
43
44 let z1 = x * &c + &t1;
45 let z2 = r * &c + &t2;
46
47 (KnowledgeProof { alpha, z1, z2 }, C)
48 }
49
50 pub fn verify(
51 &self,
52 gens_n: &MultiCommitGens,
53 transcript: &mut Transcript,
54 C: &CompressedGroup,
55 ) -> Result<(), ProofVerifyError> {
56 transcript.append_protocol_name(KnowledgeProof::protocol_name());
57 C.append_to_transcript(b"C", transcript);
58 self.alpha.append_to_transcript(b"alpha", transcript);
59
60 let c = transcript.challenge_scalar(b"c");
61
62 let lhs = self.z1.commit(&self.z2, gens_n).compress();
63 let rhs = (&c * C.decompress().expect("Could not decompress C")
64 + self
65 .alpha
66 .decompress()
67 .expect("Could not decompress self.alpha"))
68 .compress();
69
70 if lhs == rhs {
71 Ok(())
72 } else {
73 Err(ProofVerifyError)
74 }
75 }
76}
77
78#[derive(Serialize, Deserialize, Debug)]
79pub struct EqualityProof {
80 alpha: CompressedGroup,
81 z: Scalar,
82}
83
84impl EqualityProof {
85 fn protocol_name() -> &'static [u8] {
86 b"equality proof"
87 }
88
89 pub fn prove(
90 gens_n: &MultiCommitGens,
91 transcript: &mut Transcript,
92 random_tape: &mut Transcript,
93 v1: &Scalar,
94 s1: &Scalar,
95 v2: &Scalar,
96 s2: &Scalar,
97 ) -> (EqualityProof, CompressedGroup, CompressedGroup) {
98 transcript.append_protocol_name(EqualityProof::protocol_name());
99
100 // produce a random Scalar
101 let r = random_tape.challenge_scalar(b"r");
102
103 let C1 = v1.commit(&s1, gens_n).compress();
104 C1.append_to_transcript(b"C1", transcript);
105
106 let C2 = v2.commit(&s2, gens_n).compress();
107 C2.append_to_transcript(b"C2", transcript);
108
109 let alpha = (&r * gens_n.h).compress();
110 alpha.append_to_transcript(b"alpha", transcript);
111
112 let c = transcript.challenge_scalar(b"c");
113
114 let z = &c * (s1 - s2) + &r;
115
116 (EqualityProof { alpha, z }, C1, C2)
117 }
118
119 pub fn verify(
120 &self,
121 gens_n: &MultiCommitGens,
122 transcript: &mut Transcript,
123 C1: &CompressedGroup,
124 C2: &CompressedGroup,
125 ) -> Result<(), ProofVerifyError> {
126 transcript.append_protocol_name(EqualityProof::protocol_name());
127 C1.append_to_transcript(b"C1", transcript);
128 C2.append_to_transcript(b"C2", transcript);
129 self.alpha.append_to_transcript(b"alpha", transcript);
130
131 let c = transcript.challenge_scalar(b"c");
132 let rhs = {
133 let C = &C1.decompress().unwrap() - &C2.decompress().unwrap();
134 (&c * C + &self.alpha.decompress().unwrap()).compress()
135 };
136
137 let lhs = (&self.z * gens_n.h).compress();
138
139 if lhs == rhs {
140 Ok(())
141 } else {
142 Err(ProofVerifyError)
143 }
144 }
145}
146
147#[derive(Serialize, Deserialize, Debug)]
148pub struct ProductProof {
149 alpha: CompressedGroup,
150 beta: CompressedGroup,
151 delta: CompressedGroup,
152 z: [Scalar; 5],
153}
154
155impl ProductProof {
156 fn protocol_name() -> &'static [u8] {
157 b"product proof"
158 }
159
160 pub fn prove(
161 gens_n: &MultiCommitGens,
162 transcript: &mut Transcript,
163 random_tape: &mut Transcript,
164 x: &Scalar,
165 rX: &Scalar,
166 y: &Scalar,
167 rY: &Scalar,
168 z: &Scalar,
169 rZ: &Scalar,
170 ) -> (
171 ProductProof,
172 CompressedGroup,
173 CompressedGroup,
174 CompressedGroup,
175 ) {
176 transcript.append_protocol_name(ProductProof::protocol_name());
177
178 // produce five random Scalar
179 let b1 = random_tape.challenge_scalar(b"b1");
180 let b2 = random_tape.challenge_scalar(b"b2");
181 let b3 = random_tape.challenge_scalar(b"b3");
182 let b4 = random_tape.challenge_scalar(b"b4");
183 let b5 = random_tape.challenge_scalar(b"b5");
184
185 let X = x.commit(&rX, gens_n).compress();
186 X.append_to_transcript(b"X", transcript);
187
188 let Y = y.commit(&rY, gens_n).compress();
189 Y.append_to_transcript(b"Y", transcript);
190
191 let Z = z.commit(&rZ, gens_n).compress();
192 Z.append_to_transcript(b"Z", transcript);
193
194 let alpha = b1.commit(&b2, gens_n).compress();
195 alpha.append_to_transcript(b"alpha", transcript);
196
197 let beta = b3.commit(&b4, gens_n).compress();
198 beta.append_to_transcript(b"beta", transcript);
199
200 let delta = {
201 let gens_X = &MultiCommitGens {
202 n: 1,
203 G: vec![X.decompress().unwrap()],
204 h: gens_n.h,
205 };
206 b3.commit(&b5, gens_X).compress()
207 };
208 delta.append_to_transcript(b"delta", transcript);
209
210 let c = transcript.challenge_scalar(b"c");
211
212 let z1 = &b1 + &c * x;
213 let z2 = &b2 + &c * rX;
214 let z3 = &b3 + &c * y;
215 let z4 = &b4 + &c * rY;
216 let z5 = &b5 + &c * (rZ - rX * y);
217 let z = [z1, z2, z3, z4, z5];
218
219 (
220 ProductProof {
221 alpha,
222 beta,
223 delta,
224 z,
225 },
226 X,
227 Y,
228 Z,
229 )
230 }
231
232 fn check_equality(
233 P: &CompressedGroup,
234 X: &CompressedGroup,
235 c: &Scalar,
236 gens_n: &MultiCommitGens,
237 z1: &Scalar,
238 z2: &Scalar,
239 ) -> bool {
240 let lhs = (P.decompress().unwrap() + c * X.decompress().unwrap()).compress();
241 let rhs = z1.commit(&z2, gens_n).compress();
242
243 if lhs == rhs {
244 true
245 } else {
246 false
247 }
248 }
249
250 pub fn verify(
251 &self,
252 gens_n: &MultiCommitGens,
253 transcript: &mut Transcript,
254 X: &CompressedGroup,
255 Y: &CompressedGroup,
256 Z: &CompressedGroup,
257 ) -> Result<(), ProofVerifyError> {
258 transcript.append_protocol_name(ProductProof::protocol_name());
259
260 X.append_to_transcript(b"X", transcript);
261 Y.append_to_transcript(b"Y", transcript);
262 Z.append_to_transcript(b"Z", transcript);
263 self.alpha.append_to_transcript(b"alpha", transcript);
264 self.beta.append_to_transcript(b"beta", transcript);
265 self.delta.append_to_transcript(b"delta", transcript);
266
267 let z1 = self.z[0];
268 let z2 = self.z[1];
269 let z3 = self.z[2];
270 let z4 = self.z[3];
271 let z5 = self.z[4];
272
273 let c = transcript.challenge_scalar(b"c");
274
275 if ProductProof::check_equality(&self.alpha, &X, &c, &gens_n, &z1, &z2)
276 && ProductProof::check_equality(&self.beta, &Y, &c, &gens_n, &z3, &z4)
277 && ProductProof::check_equality(
278 &self.delta,
279 &Z,
280 &c,
281 &MultiCommitGens {
282 n: 1,
283 G: vec![X.decompress().unwrap()],
284 h: gens_n.h,
285 },
286 &z3,
287 &z5,
288 )
289 {
290 Ok(())
291 } else {
292 Err(ProofVerifyError)
293 }
294 }
295}
296
297#[derive(Debug, Serialize, Deserialize)]
298pub struct DotProductProof {
299 delta: CompressedGroup,
300 beta: CompressedGroup,
301 z: Vec<Scalar>,
302 z_delta: Scalar,
303 z_beta: Scalar,
304}
305
306impl DotProductProof {
307 fn protocol_name() -> &'static [u8] {
308 b"dot product proof"
309 }
310
311 pub fn compute_dotproduct(a: &Vec<Scalar>, b: &Vec<Scalar>) -> Scalar {
312 assert_eq!(a.len(), b.len());
313 (0..a.len()).map(|i| &a[i] * &b[i]).sum()
314 }
315
316 pub fn prove(
317 gens_1: &MultiCommitGens,
318 gens_n: &MultiCommitGens,
319 transcript: &mut Transcript,
320 random_tape: &mut Transcript,
321 x: &Vec<Scalar>,
322 r_x: &Scalar,
323 a: &Vec<Scalar>,
324 y: &Scalar,
325 r_y: &Scalar,
326 ) -> (DotProductProof, CompressedGroup, CompressedGroup) {
327 transcript.append_protocol_name(DotProductProof::protocol_name());
328
329 let n = x.len();
330 assert_eq!(x.len(), a.len());
331 assert_eq!(gens_n.n, a.len());
332 assert_eq!(gens_1.n, 1);
333
334 // produce randomness for the proofs
335 let d = random_tape.challenge_vector(b"d", n);
336 let r_delta = random_tape.challenge_scalar(b"r_delta");
337 let r_beta = random_tape.challenge_scalar(b"r_beta");
338
339 let Cx = x.commit(&r_x, gens_n).compress();
340 Cx.append_to_transcript(b"Cx", transcript);
341
342 let Cy = y.commit(&r_y, gens_1).compress();
343 Cy.append_to_transcript(b"Cy", transcript);
344
345 let delta = d.commit(&r_delta, gens_n).compress();
346 delta.append_to_transcript(b"delta", transcript);
347
348 let dotproduct_a_d = DotProductProof::compute_dotproduct(&a, &d);
349
350 let beta = dotproduct_a_d.commit(&r_beta, gens_1).compress();
351 beta.append_to_transcript(b"beta", transcript);
352
353 let c = transcript.challenge_scalar(b"c");
354
355 let z = (0..d.len())
356 .map(|i| c * x[i] + d[i])
357 .collect::<Vec<Scalar>>();
358
359 let z_delta = c * r_x + r_delta;
360 let z_beta = c * r_y + r_beta;
361
362 (
363 DotProductProof {
364 delta,
365 beta,
366 z,
367 z_delta,
368 z_beta,
369 },
370 Cx,
371 Cy,
372 )
373 }
374
375 pub fn verify(
376 &self,
377 gens_1: &MultiCommitGens,
378 gens_n: &MultiCommitGens,
379 transcript: &mut Transcript,
380 a: &Vec<Scalar>,
381 Cx: &CompressedGroup,
382 Cy: &CompressedGroup,
383 ) -> Result<(), ProofVerifyError> {
384 assert_eq!(gens_n.n, a.len());
385 assert_eq!(gens_1.n, 1);
386
387 transcript.append_protocol_name(DotProductProof::protocol_name());
388 Cx.append_to_transcript(b"Cx", transcript);
389 Cy.append_to_transcript(b"Cy", transcript);
390 self.delta.append_to_transcript(b"delta", transcript);
391 self.beta.append_to_transcript(b"beta", transcript);
392
393 let c = transcript.challenge_scalar(b"c");
394
395 let mut result = &c * Cx.decompress().unwrap() + self.delta.decompress().unwrap()
396 == self.z.commit(&self.z_delta, gens_n);
397
398 let dotproduct_z_a = DotProductProof::compute_dotproduct(&self.z, &a);
399 result &= &c * Cy.decompress().unwrap() + self.beta.decompress().unwrap()
400 == dotproduct_z_a.commit(&self.z_beta, gens_1);
401
402 if result {
403 Ok(())
404 } else {
405 Err(ProofVerifyError)
406 }
407 }
408}
409
410pub struct DotProductProofGens {
411 n: usize,
412 pub gens_n: MultiCommitGens,
413 pub gens_1: MultiCommitGens,
414}
415
416impl DotProductProofGens {
417 pub fn new(n: usize, label: &[u8]) -> Self {
418 let (gens_n, gens_1) = MultiCommitGens::new(n + 1, label).split_at_mut(n);
419 DotProductProofGens { n, gens_n, gens_1 }
420 }
421}
422
423#[derive(Debug, Serialize, Deserialize)]
424pub struct DotProductProofLog {
425 bullet_reduction_proof: BulletReductionProof,
426 delta: CompressedGroup,
427 beta: CompressedGroup,
428 z1: Scalar,
429 z2: Scalar,
430}
431
432impl DotProductProofLog {
433 fn protocol_name() -> &'static [u8] {
434 b"dot product proof (log)"
435 }
436
437 pub fn compute_dotproduct(a: &Vec<Scalar>, b: &Vec<Scalar>) -> Scalar {
438 assert_eq!(a.len(), b.len());
439 (0..a.len()).map(|i| &a[i] * &b[i]).sum()
440 }
441
442 pub fn prove(
443 gens: &DotProductProofGens,
444 transcript: &mut Transcript,
445 random_tape: &mut Transcript,
446 x: &Vec<Scalar>,
447 r_x: &Scalar,
448 a: &Vec<Scalar>,
449 y: &Scalar,
450 r_y: &Scalar,
451 ) -> (DotProductProofLog, CompressedGroup, CompressedGroup) {
452 transcript.append_protocol_name(DotProductProofLog::protocol_name());
453
454 let n = x.len();
455 assert_eq!(x.len(), a.len());
456 assert_eq!(gens.n, n);
457
458 // produce randomness for generating a proof
459 let d = random_tape.challenge_scalar(b"d");
460 let r_delta = random_tape.challenge_scalar(b"r_delta");
461 let r_beta = random_tape.challenge_scalar(b"r_delta");
462 let blinds_vec = {
463 let v1 = random_tape.challenge_vector(b"blinds_vec_1", 2 * n.log2());
464 let v2 = random_tape.challenge_vector(b"blinds_vec_2", 2 * n.log2());
465 (0..v1.len())
466 .map(|i| (v1[i], v2[i]))
467 .collect::<Vec<(Scalar, Scalar)>>()
468 };
469
470 let Cx = x.commit(&r_x, &gens.gens_n).compress();
471 Cx.append_to_transcript(b"Cx", transcript);
472
473 let Cy = y.commit(&r_y, &gens.gens_1).compress();
474 Cy.append_to_transcript(b"Cy", transcript);
475
476 let r_Gamma = r_x + r_y;
477 let (bullet_reduction_proof, _Gamma_hat, x_hat, a_hat, g_hat, rhat_Gamma) =
478 BulletReductionProof::prove(
479 transcript,
480 &gens.gens_1.G[0],
481 &gens.gens_n.G,
482 &gens.gens_n.h,
483 x,
484 a,
485 &r_Gamma,
486 &blinds_vec,
487 );
488 let y_hat = x_hat * a_hat;
489
490 let delta = {
491 let gens_hat = MultiCommitGens {
492 n: 1,
493 G: vec![g_hat],
494 h: gens.gens_1.h,
495 };
496 d.commit(&r_delta, &gens_hat).compress()
497 };
498 delta.append_to_transcript(b"delta", transcript);
499
500 let beta = d.commit(&r_beta, &gens.gens_1).compress();
501 beta.append_to_transcript(b"beta", transcript);
502
503 let c = transcript.challenge_scalar(b"c");
504
505 let z1 = d + c * y_hat;
506 let z2 = a_hat * (c * rhat_Gamma + r_beta) + r_delta;
507
508 (
509 DotProductProofLog {
510 bullet_reduction_proof,
511 delta,
512 beta,
513 z1,
514 z2,
515 },
516 Cx,
517 Cy,
518 )
519 }
520
521 pub fn verify(
522 &self,
523 n: usize,
524 gens: &DotProductProofGens,
525 transcript: &mut Transcript,
526 a: &Vec<Scalar>,
527 Cx: &CompressedGroup,
528 Cy: &CompressedGroup,
529 ) -> Result<(), ProofVerifyError> {
530 assert_eq!(gens.n, n);
531 assert_eq!(a.len(), n);
532
533 transcript.append_protocol_name(DotProductProofLog::protocol_name());
534 Cx.append_to_transcript(b"Cx", transcript);
535 Cy.append_to_transcript(b"Cy", transcript);
536
537 let Gamma = Cx.decompress().unwrap() + Cy.decompress().unwrap();
538
539 let (g_hat, Gamma_hat, a_hat) = self
540 .bullet_reduction_proof
541 .verify(n, a, transcript, &Gamma, &gens.gens_n.G)
542 .unwrap();
543
544 self.delta.append_to_transcript(b"delta", transcript);
545 self.beta.append_to_transcript(b"beta", transcript);
546
547 let c = transcript.challenge_scalar(b"c");
548
549 let c_s = &c;
550 let beta_s = self.beta.decompress().unwrap();
551 let a_hat_s = &a_hat;
552 let delta_s = self.delta.decompress().unwrap();
553 let z1_s = &self.z1;
554 let z2_s = &self.z2;
555
556 let lhs = ((Gamma_hat * c_s + beta_s) * a_hat_s + delta_s).compress();
557 let rhs = ((g_hat + &gens.gens_1.G[0] * a_hat_s) * z1_s + gens.gens_1.h * z2_s).compress();
558
559 assert_eq!(lhs, rhs);
560
561 if lhs == rhs {
562 Ok(())
563 } else {
564 Err(ProofVerifyError)
565 }
566 }
567}
568
569#[cfg(test)]
570mod tests {
571 use super::*;
572 use rand::rngs::OsRng;
573 #[test]
574 fn check_knowledgeproof() {
575 let mut csprng: OsRng = OsRng;
576
577 let gens_1 = MultiCommitGens::new(1, b"test-knowledgeproof");
578
579 let x = Scalar::random(&mut csprng);
580 let r = Scalar::random(&mut csprng);
581
582 let mut random_tape = {
583 let mut csprng: OsRng = OsRng;
584 let mut tape = Transcript::new(b"proof");
585 tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
586 tape
587 };
588 let mut prover_transcript = Transcript::new(b"example");
589 let (proof, committed_value) =
590 KnowledgeProof::prove(&gens_1, &mut prover_transcript, &mut random_tape, &x, &r);
591
592 let mut verifier_transcript = Transcript::new(b"example");
593 assert!(proof
594 .verify(&gens_1, &mut verifier_transcript, &committed_value)
595 .is_ok());
596 }
597
598 #[test]
599 fn check_equalityproof() {
600 let mut csprng: OsRng = OsRng;
601
602 let gens_1 = MultiCommitGens::new(1, b"test-equalityproof");
603 let v1 = Scalar::random(&mut csprng);
604 let v2 = v1;
605 let s1 = Scalar::random(&mut csprng);
606 let s2 = Scalar::random(&mut csprng);
607
608 let mut random_tape = {
609 let mut csprng: OsRng = OsRng;
610 let mut tape = Transcript::new(b"proof");
611 tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
612 tape
613 };
614 let mut prover_transcript = Transcript::new(b"example");
615 let (proof, C1, C2) = EqualityProof::prove(
616 &gens_1,
617 &mut prover_transcript,
618 &mut random_tape,
619 &v1,
620 &s1,
621 &v2,
622 &s2,
623 );
624
625 let mut verifier_transcript = Transcript::new(b"example");
626 assert!(proof
627 .verify(&gens_1, &mut verifier_transcript, &C1, &C2)
628 .is_ok());
629 }
630
631 #[test]
632 fn check_productproof() {
633 let mut csprng: OsRng = OsRng;
634
635 let gens_1 = MultiCommitGens::new(1, b"test-productproof");
636 let x = Scalar::random(&mut csprng);
637 let rX = Scalar::random(&mut csprng);
638 let y = Scalar::random(&mut csprng);
639 let rY = Scalar::random(&mut csprng);
640 let z = x * y;
641 let rZ = Scalar::random(&mut csprng);
642
643 let mut random_tape = {
644 let mut csprng: OsRng = OsRng;
645 let mut tape = Transcript::new(b"proof");
646 tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
647 tape
648 };
649 let mut prover_transcript = Transcript::new(b"example");
650 let (proof, X, Y, Z) = ProductProof::prove(
651 &gens_1,
652 &mut prover_transcript,
653 &mut random_tape,
654 &x,
655 &rX,
656 &y,
657 &rY,
658 &z,
659 &rZ,
660 );
661
662 let mut verifier_transcript = Transcript::new(b"example");
663 assert!(proof
664 .verify(&gens_1, &mut verifier_transcript, &X, &Y, &Z)
665 .is_ok());
666 }
667
668 #[test]
669 fn check_dotproductproof() {
670 let mut csprng: OsRng = OsRng;
671
672 let n = 1024;
673
674 let gens_1 = MultiCommitGens::new(1, b"test-two");
675 let gens_1024 = MultiCommitGens::new(n, b"test-1024");
676
677 let mut x: Vec<Scalar> = Vec::new();
678 let mut a: Vec<Scalar> = Vec::new();
679 for _ in 0..n {
680 x.push(Scalar::random(&mut csprng));
681 a.push(Scalar::random(&mut csprng));
682 }
683 let y = DotProductProofLog::compute_dotproduct(&x, &a);
684 let r_x = Scalar::random(&mut csprng);
685 let r_y = Scalar::random(&mut csprng);
686
687 let mut random_tape = {
688 let mut csprng: OsRng = OsRng;
689 let mut tape = Transcript::new(b"proof");
690 tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
691 tape
692 };
693 let mut prover_transcript = Transcript::new(b"example");
694 let (proof, Cx, Cy) = DotProductProof::prove(
695 &gens_1,
696 &gens_1024,
697 &mut prover_transcript,
698 &mut random_tape,
699 &x,
700 &r_x,
701 &a,
702 &y,
703 &r_y,
704 );
705
706 let mut verifier_transcript = Transcript::new(b"example");
707 assert!(proof
708 .verify(&gens_1, &gens_1024, &mut verifier_transcript, &a, &Cx, &Cy)
709 .is_ok());
710 }
711
712 #[test]
713 fn check_dotproductproof_log() {
714 let mut csprng: OsRng = OsRng;
715
716 let n = 1024;
717
718 let gens = DotProductProofGens::new(n, b"test-1024");
719
720 let x: Vec<Scalar> = (0..n).map(|_i| Scalar::random(&mut csprng)).collect();
721 let a: Vec<Scalar> = (0..n).map(|_i| Scalar::random(&mut csprng)).collect();
722 let y = DotProductProof::compute_dotproduct(&x, &a);
723
724 let r_x = Scalar::random(&mut csprng);
725 let r_y = Scalar::random(&mut csprng);
726
727 let mut random_tape = {
728 let mut csprng: OsRng = OsRng;
729 let mut tape = Transcript::new(b"proof");
730 tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
731 tape
732 };
733 let mut prover_transcript = Transcript::new(b"example");
734 let (proof, Cx, Cy) = DotProductProofLog::prove(
735 &gens,
736 &mut prover_transcript,
737 &mut random_tape,
738 &x,
739 &r_x,
740 &a,
741 &y,
742 &r_y,
743 );
744
745 let mut verifier_transcript = Transcript::new(b"example");
746 assert!(proof
747 .verify(n, &gens, &mut verifier_transcript, &a, &Cx, &Cy)
748 .is_ok());
749 }
750}