arnaucube
arnaucube/testudoPublic Self-hosted repository
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
757    assert!(proof
758      .verify(n, &gens, &mut verifier_transcript, &a, &Cx, &Cy)
759      .is_ok());
760  }
761}