Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 132 additions & 15 deletions src/ipa/no_zk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<RistrettoPoint> = self.L_vec.iter().map(|L| L.decompress().unwrap()).collect();
let Rs: Vec<RistrettoPoint> = 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<RistrettoPoint> = self.L_vec.iter().map(|L| L.decompress().unwrap()).collect();
let Rs: Vec<RistrettoPoint> = self.R_vec.iter().map(|R| R.decompress().unwrap()).collect();
Expand All @@ -133,20 +176,22 @@ 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<Scalar> = Vec::new();
let mut h_i: Vec<Scalar> = Vec::new();
let mut g_i: Vec<Scalar> = Vec::with_capacity(n);
let mut h_i: Vec<Scalar> = Vec::with_capacity(n);
for x in 0..n {
let mut i: usize = 1;
let mut j: usize = 0;
let mut g = self.a;
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;
Expand All @@ -156,13 +201,13 @@ impl NoZK {
}

// {l_j},{r_j}
let mut l_j: Vec<Scalar> = Vec::new();
let mut r_j: Vec<Scalar> = Vec::new();
let mut l_j: Vec<Scalar> = Vec::with_capacity(n);
let mut r_j: Vec<Scalar> = 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];
}
Expand All @@ -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()
}
}
Expand Down Expand Up @@ -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<Scalar> = (0..n).map(|_| Scalar::random(&mut rng)).collect();
let b: Vec<Scalar> = (0..n).map(|_| Scalar::random(&mut rng)).collect();

let t = inner_product(&a, &b);

let G: Vec<RistrettoPoint> = (0..n).map(|_| RistrettoPoint::random(&mut rng)).collect();
let H: Vec<RistrettoPoint> = (0..n).map(|_| RistrettoPoint::random(&mut rng)).collect();
let Q = RistrettoPoint::hash_from_bytes::<Sha3_512>(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<Scalar> = (0..n).map(|_| Scalar::random(&mut rng)).collect();
let b: Vec<Scalar> = (0..n).map(|_| Scalar::random(&mut rng)).collect();

let t = inner_product(&a, &b);

let G: Vec<RistrettoPoint> = (0..n).map(|_| RistrettoPoint::random(&mut rng)).collect();
let H: Vec<RistrettoPoint> = (0..n).map(|_| RistrettoPoint::random(&mut rng)).collect();
let Q = RistrettoPoint::hash_from_bytes::<Sha3_512>(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));
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![feature(test)]

mod copy;
mod ipa;
mod lmpa;
Expand Down