From 5da79b2fcff987a45453ff33221f1a64356f4c3c Mon Sep 17 00:00:00 2001 From: Ken Shamir Date: Mon, 14 Oct 2019 21:23:32 +0100 Subject: [PATCH] Added benchmarks --- src/ipa/no_zk.rs | 147 ++++++++++++++++++++++++++++++++++++++++++----- src/lib.rs | 2 + 2 files changed, 134 insertions(+), 15 deletions(-) diff --git a/src/ipa/no_zk.rs b/src/ipa/no_zk.rs index 87855bd..a4688f5 100644 --- a/src/ipa/no_zk.rs +++ b/src/ipa/no_zk.rs @@ -4,7 +4,7 @@ use crate::transcript::TranscriptProtocol; use curve25519_dalek::{ ristretto::{CompressedRistretto, RistrettoPoint}, scalar::Scalar, - traits::{VartimeMultiscalarMul,IsIdentity}, + traits::{IsIdentity, VartimeMultiscalarMul}, }; use merlin::Transcript; use std::iter; @@ -115,13 +115,56 @@ impl NoZK { G_Vec: &[RistrettoPoint], H_Vec: &[RistrettoPoint], Q: &RistrettoPoint, - n: usize, - P: RistrettoPoint, + mut n: usize, + mut P: RistrettoPoint, t: Scalar, ) -> bool { let mut G = G_Vec.to_owned(); let mut H = H_Vec.to_owned(); + let Ls: Vec = self.L_vec.iter().map(|L| L.decompress().unwrap()).collect(); + let Rs: Vec = self.R_vec.iter().map(|R| R.decompress().unwrap()).collect(); + assert_eq!(n, 1 << Ls.len()); + + transcript.append_u64(b"n", n as u64); + + let alpha = transcript.challenge_scalar(b"alpha"); + let Q = alpha.invert() * Q; + + P = P - (alpha - Scalar::one()) * t * Q; + + let challenges = generate_challenges(self, transcript); + + for ((L, R), challenge) in Ls.iter().zip(Rs.iter()).zip(challenges.iter()) { + let challenge_sq = challenge * challenge; + P = challenge_sq * L + challenge * P + R; + } + + for challenge in challenges.iter() { + n = n / 2; + + let (G_L, G_R) = G.split_at_mut(n); + let (H_L, H_R) = H.split_at_mut(n); + + G = vector_vector_add(G_L, &mut vector_scalar_mul(G_R, challenge)); + H = vector_vector_add(&mut vector_scalar_mul(H_L, challenge), H_R); + } + + let exp_P = G[0] * self.a + H[0] * self.b + (self.a * self.b) * Q; + + exp_P == P + } + pub fn verify_multiexp( + &self, + transcript: &mut Transcript, + G_Vec: &[RistrettoPoint], + H_Vec: &[RistrettoPoint], + Q: &RistrettoPoint, + n: usize, + P: RistrettoPoint, + t: Scalar, + ) -> bool { + // decode L,R let Ls: Vec = self.L_vec.iter().map(|L| L.decompress().unwrap()).collect(); let Rs: Vec = self.R_vec.iter().map(|R| R.decompress().unwrap()).collect(); @@ -133,9 +176,11 @@ impl NoZK { let alpha = transcript.challenge_scalar(b"alpha"); let challenges = generate_challenges(self, transcript); + let logn = challenges.len(); + // {g_i},{h_i} - let mut g_i: Vec = Vec::new(); - let mut h_i: Vec = Vec::new(); + let mut g_i: Vec = Vec::with_capacity(n); + let mut h_i: Vec = Vec::with_capacity(n); for x in 0..n { let mut i: usize = 1; let mut j: usize = 0; @@ -143,10 +188,10 @@ impl NoZK { let mut h = self.b; while i < n { if i & x != 0 { - g *= challenges[challenges.len()-j-1]; + g *= challenges[logn-j-1]; } else { - h *= challenges[challenges.len()-j-1]; + h *= challenges[logn-j-1]; } i <<= 1; j += 1; @@ -156,13 +201,13 @@ impl NoZK { } // {l_j},{r_j} - let mut l_j: Vec = Vec::new(); - let mut r_j: Vec = Vec::new(); + let mut l_j: Vec = Vec::with_capacity(n); + let mut r_j: Vec = Vec::with_capacity(n); let mut p = Scalar::one(); - for i in 0..challenges.len() { + for i in 0..logn { let mut l = -challenges[i]*challenges[i]; let mut r = -Scalar::one(); - for j in (i+1)..challenges.len() { + for j in (i+1)..logn { l *= challenges[j]; r *= challenges[j]; } @@ -173,12 +218,13 @@ impl NoZK { // return value goes here let q = alpha.invert()*((alpha - Scalar::one())*t*p + self.a*self.b); - p = -p; + + let R = RistrettoPoint::vartime_multiscalar_mul( - g_i.iter().chain(h_i.iter()).chain(l_j.iter()).chain(r_j.iter()).chain(iter::once(&q)).chain(iter::once(&p)), - G.iter().chain( H.iter()).chain( Ls.iter()).chain( Rs.iter()).chain(iter::once( Q)).chain(iter::once(&P)) + g_i.iter().chain(h_i.iter()).chain(l_j.iter()).chain(r_j.iter()).chain(iter::once(&q)).chain(iter::once(&-p)), + G_Vec.iter().chain( H_Vec.iter()).chain( Ls.iter()).chain( Rs.iter()).chain(iter::once( Q)).chain(iter::once(&P)) ); - + R.is_identity() } } @@ -243,4 +289,75 @@ mod tests { assert!(proof.verify(&mut verifier_transcript, &G, &H, &Q, n, P, t)); } + + extern crate test; + use super::*; + use test::Bencher; + + #[bench] + fn bench_verify_multiexp(bnch: &mut Bencher) { + let n = 256; + + let mut rng = rand::thread_rng(); + + let a: Vec = (0..n).map(|_| Scalar::random(&mut rng)).collect(); + let b: Vec = (0..n).map(|_| Scalar::random(&mut rng)).collect(); + + let t = inner_product(&a, &b); + + let G: Vec = (0..n).map(|_| RistrettoPoint::random(&mut rng)).collect(); + let H: Vec = (0..n).map(|_| RistrettoPoint::random(&mut rng)).collect(); + let Q = RistrettoPoint::hash_from_bytes::(b"test point"); + + let mut prover_transcript = Transcript::new(b"ip_no_zk"); + + let P = RistrettoPoint::vartime_multiscalar_mul( + a.iter().chain(b.iter()).chain(iter::once(&t)), + G.iter().chain(H.iter()).chain(iter::once(&Q)), + ); + + // We add the compressed point to the transcript, because we need some non-trivial input to generate alpha + // If this is not done, then the prover always will be able to predict what the first challenge will be + prover_transcript.append_message(b"P", P.compress().as_bytes()); + + let proof = create(&mut prover_transcript, G.clone(), H.clone(), &Q, a, b); + + let mut verifier_transcript = Transcript::new(b"ip_no_zk"); + verifier_transcript.append_message(b"P", P.compress().as_bytes()); + + bnch.iter(|| proof.verify_multiexp(&mut verifier_transcript, &G, &H, &Q, n, P, t)); + } + #[bench] + fn bench_verify(bnch: &mut Bencher) { + let n = 256; + + let mut rng = rand::thread_rng(); + + let a: Vec = (0..n).map(|_| Scalar::random(&mut rng)).collect(); + let b: Vec = (0..n).map(|_| Scalar::random(&mut rng)).collect(); + + let t = inner_product(&a, &b); + + let G: Vec = (0..n).map(|_| RistrettoPoint::random(&mut rng)).collect(); + let H: Vec = (0..n).map(|_| RistrettoPoint::random(&mut rng)).collect(); + let Q = RistrettoPoint::hash_from_bytes::(b"test point"); + + let mut prover_transcript = Transcript::new(b"ip_no_zk"); + + let P = RistrettoPoint::vartime_multiscalar_mul( + a.iter().chain(b.iter()).chain(iter::once(&t)), + G.iter().chain(H.iter()).chain(iter::once(&Q)), + ); + + // We add the compressed point to the transcript, because we need some non-trivial input to generate alpha + // If this is not done, then the prover always will be able to predict what the first challenge will be + prover_transcript.append_message(b"P", P.compress().as_bytes()); + + let proof = create(&mut prover_transcript, G.clone(), H.clone(), &Q, a, b); + + let mut verifier_transcript = Transcript::new(b"ip_no_zk"); + verifier_transcript.append_message(b"P", P.compress().as_bytes()); + + bnch.iter(|| proof.verify(&mut verifier_transcript, &G, &H, &Q, n, P, t)); + } } diff --git a/src/lib.rs b/src/lib.rs index 0713bb9..21b7812 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(test)] + mod copy; mod ipa; mod lmpa;