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