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