This commit is contained in:
Srinath Setty 2021-04-22 11:41:46 -07:00
Родитель f465aed924
Коммит a05d0f42f3
8 изменённых файлов: 312 добавлений и 184 удалений

Просмотреть файл

@ -17,7 +17,7 @@ rand = "0.7.3"
digest = "0.8.1"
sha3 = "0.8.2"
byteorder = "1.3.4"
rayon = { version = "1.3.0", optional = true }
rayon = { version = "1.3.0"}
serde = { version = "1.0.106", features = ["derive"] }
bincode = "1.2.1"
subtle = { version = "^2.2.3", default-features = false }
@ -52,5 +52,4 @@ name = "nizk"
harness = false
[features]
multicore = ["rayon"]
profile = []

Просмотреть файл

@ -11,7 +11,6 @@ use core::ops::Index;
use merlin::Transcript;
use serde::{Deserialize, Serialize};
#[cfg(feature = "multicore")]
use rayon::prelude::*;
#[derive(Debug)]
@ -66,6 +65,9 @@ impl EqPolynomial {
pub fn evals(&self) -> Vec<Scalar> {
let ell = self.r.len();
let mut evals: Vec<Scalar> = vec![Scalar::zero(); ell.pow2()];
/*let ell = self.r.len();
let mut evals: Vec<Scalar> = vec![Scalar::one(); ell.pow2()];
let mut size = 1;
@ -80,6 +82,24 @@ impl EqPolynomial {
}
}
evals
*/
// in each iteration, we double the size of chis
let mut size = 1;
evals[0] = Scalar::one();
for r in self.r.iter().rev() {
let (evals_left, evals_right) = evals.split_at_mut(size);
let (evals_right, _) = evals_right.split_at_mut(size);
let iter = evals_left.par_iter_mut().zip(evals_right.par_iter_mut());
// copy each element from the prior iteration twice
iter.for_each(|(x, y)| {
*y = *x * r;
*x -= &*y;
});
size *= 2;
}
evals
}
pub fn compute_factored_lens(ell: usize) -> (usize, usize) {
@ -142,7 +162,6 @@ impl DensePolynomial {
)
}
#[cfg(feature = "multicore")]
fn commit_inner(&self, blinds: &Vec<Scalar>, gens: &MultiCommitGens) -> PolyCommitment {
let L_size = blinds.len();
let R_size = self.Z.len() / L_size;
@ -158,21 +177,6 @@ impl DensePolynomial {
PolyCommitment { C }
}
#[cfg(not(feature = "multicore"))]
fn commit_inner(&self, blinds: &[Scalar], gens: &MultiCommitGens) -> PolyCommitment {
let L_size = blinds.len();
let R_size = self.Z.len() / L_size;
assert_eq!(L_size * R_size, self.Z.len());
let C = (0..L_size)
.map(|i| {
self.Z[R_size * i..R_size * (i + 1)]
.commit(&blinds[i], gens)
.compress()
})
.collect();
PolyCommitment { C }
}
pub fn commit(
&self,
gens: &PolyCommitmentGens,
@ -211,9 +215,18 @@ impl DensePolynomial {
pub fn bound_poly_var_top(&mut self, r: &Scalar) {
let n = self.len() / 2;
for i in 0..n {
self.Z[i] = self.Z[i] + r * (self.Z[i + n] - self.Z[i]);
}
// The following code is a parallel version of this code snippet
// for i in 0..n {
// self.Z[i] = self.Z[i] + r * (self.Z[i + n] - self.Z[i]);
// }
let (left, right) = self.Z.split_at_mut(n);
let (right, _) = right.split_at(n);
let iter = left.par_iter_mut().zip(right.par_iter());
iter.for_each(|(a, b)| {
*a += r * (b - *a);
});
self.num_vars -= 1;
self.len = n;
}

Просмотреть файл

@ -10,12 +10,10 @@ extern crate curve25519_dalek;
extern crate digest;
extern crate merlin;
extern crate rand;
extern crate rayon;
extern crate sha3;
extern crate test;
#[cfg(feature = "multicore")]
extern crate rayon;
mod commitments;
mod dense_mlpoly;
mod errors;

Просмотреть файл

@ -10,6 +10,7 @@ use super::super::scalar::Scalar;
use super::super::transcript::ProofTranscript;
use core::iter;
use merlin::Transcript;
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
@ -67,8 +68,6 @@ impl BulletReductionProof {
assert_eq!(G_factors.len(), n);
assert_eq!(blinds_vec.len(), 2 * lg_n);
//transcript.innerproduct_domain_sep(n as u64);
let mut L_vec = Vec::with_capacity(lg_n);
let mut R_vec = Vec::with_capacity(lg_n);
let mut blinds_iter = blinds_vec.iter();
@ -107,11 +106,31 @@ impl BulletReductionProof {
let u = transcript.challenge_scalar(b"u");
let u_inv = u.invert().unwrap();
let a_L_vec = (0..n)
.into_par_iter()
.map(|i| a_L[i] * u + u_inv * a_R[i])
.collect::<Vec<Scalar>>();
let b_L_vec = (0..n)
.into_par_iter()
.map(|i| b_L[i] * u_inv + u * b_R[i])
.collect::<Vec<Scalar>>();
let G_L_vec = (0..n)
.into_par_iter()
.map(|i| GroupElement::vartime_multiscalar_mul(&[u_inv, u], &[G_L[i], G_R[i]]))
.collect::<Vec<GroupElement>>();
for i in 0..n {
a_L[i] = a_L[i] * u + u_inv * a_R[i];
b_L[i] = b_L[i] * u_inv + u * b_R[i];
G_L[i] = GroupElement::vartime_multiscalar_mul(&[u_inv, u], &[G_L[i], G_R[i]]);
a_L[i] = a_L_vec[i];
b_L[i] = b_L_vec[i];
G_L[i] = G_L_vec[i];
}
//for i in 0..n {
//a_L[i] = a_L[i] * u + u_inv * a_R[i];
//b_L[i] = b_L[i] * u_inv + u * b_R[i];
//G_L[i] = GroupElement::vartime_multiscalar_mul(&[u_inv, u], &[G_L[i], G_R[i]]);
//}
blind_fin = blind_fin + blind_L * u * u + blind_R * u_inv * u_inv;

Просмотреть файл

@ -9,7 +9,8 @@ use super::sparse_mlpoly::{
};
use super::timer::Timer;
use merlin::Transcript;
use rand::rngs::OsRng;
use rand::thread_rng;
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Debug)]
@ -144,8 +145,6 @@ impl R1CSInstance {
Timer::print(&format!("number_of_variables {}", num_vars));
Timer::print(&format!("number_of_inputs {}", num_inputs));
let mut csprng: OsRng = OsRng;
// assert num_cons and num_vars are power of 2
assert_eq!(num_cons.log2().pow2(), num_cons);
assert_eq!(num_vars.log2().pow2(), num_vars);
@ -159,37 +158,54 @@ impl R1CSInstance {
// produce a random satisfying assignment
let Z = {
let mut Z: Vec<Scalar> = (0..size_z)
.map(|_i| Scalar::random(&mut csprng))
.collect::<Vec<Scalar>>();
.into_par_iter()
.map(|_| Scalar::random(&mut thread_rng()))
.collect();
Z[num_vars] = Scalar::one(); // set the constant term to 1
Z
};
// three sparse matrices
let mut A: Vec<SparseMatEntry> = Vec::new();
let mut B: Vec<SparseMatEntry> = Vec::new();
let mut C: Vec<SparseMatEntry> = Vec::new();
let one = Scalar::one();
for i in 0..num_cons {
let A_idx = i % size_z;
let B_idx = (i + 2) % size_z;
A.push(SparseMatEntry::new(i, A_idx, one));
B.push(SparseMatEntry::new(i, B_idx, one));
let AB_val = Z[A_idx] * Z[B_idx];
let A: Vec<SparseMatEntry> = {
(0..num_cons)
.into_par_iter()
.map(|i| {
let A_idx = i % size_z;
SparseMatEntry::new(i, A_idx, one)
})
.collect()
};
let C_idx = (i + 3) % size_z;
let C_val = Z[C_idx];
let B: Vec<SparseMatEntry> = {
(0..num_cons)
.into_par_iter()
.map(|i| {
let B_idx = (i + 2) % size_z;
SparseMatEntry::new(i, B_idx, one)
})
.collect()
};
if C_val == Scalar::zero() {
C.push(SparseMatEntry::new(i, num_vars, AB_val));
} else {
C.push(SparseMatEntry::new(
i,
C_idx,
AB_val * C_val.invert().unwrap(),
));
}
}
let C: Vec<SparseMatEntry> = {
(0..num_cons)
.into_par_iter()
.map(|i| {
let A_idx = i % size_z;
let B_idx = (i + 2) % size_z;
let AB_val = Z[A_idx] * Z[B_idx];
let C_idx = (i + 3) % size_z;
let C_val = Z[C_idx];
if C_val == Scalar::zero() {
SparseMatEntry::new(i, num_vars, AB_val)
} else {
SparseMatEntry::new(i, C_idx, AB_val * C_val.invert().unwrap())
}
})
.collect()
};
Timer::print(&format!("number_non-zero_entries_A {}", A.len()));
Timer::print(&format!("number_non-zero_entries_B {}", B.len()));
@ -259,11 +275,18 @@ impl R1CSInstance {
assert_eq!(num_rows, self.num_cons);
assert_eq!(z.len(), num_cols);
assert!(num_cols > self.num_vars);
(
DensePolynomial::new(self.A.multiply_vec(num_rows, num_cols, z)),
DensePolynomial::new(self.B.multiply_vec(num_rows, num_cols, z)),
DensePolynomial::new(self.C.multiply_vec(num_rows, num_cols, z)),
)
let (A, (B, C)) = rayon::join(
|| DensePolynomial::new(self.A.multiply_vec(num_rows, num_cols, z)),
|| {
rayon::join(
|| DensePolynomial::new(self.B.multiply_vec(num_rows, num_cols, z)),
|| DensePolynomial::new(self.C.multiply_vec(num_rows, num_cols, z)),
)
},
);
(A, B, C)
}
pub fn compute_eval_table_sparse(
@ -275,9 +298,15 @@ impl R1CSInstance {
assert_eq!(num_rows, self.num_cons);
assert!(num_cols > self.num_vars);
let evals_A = self.A.compute_eval_table_sparse(&evals, num_rows, num_cols);
let evals_B = self.B.compute_eval_table_sparse(&evals, num_rows, num_cols);
let evals_C = self.C.compute_eval_table_sparse(&evals, num_rows, num_cols);
let (evals_A, (evals_B, evals_C)) = rayon::join(
|| self.A.compute_eval_table_sparse(evals, num_rows, num_cols),
|| {
rayon::join(
|| self.B.compute_eval_table_sparse(evals, num_rows, num_cols),
|| self.C.compute_eval_table_sparse(evals, num_rows, num_cols),
)
},
);
(evals_A, evals_B, evals_C)
}

Просмотреть файл

@ -16,6 +16,7 @@ use super::timer::Timer;
use super::transcript::{AppendToTranscript, ProofTranscript};
use core::iter;
use merlin::Transcript;
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
@ -274,6 +275,7 @@ impl R1CSProof {
assert_eq!(evals_A.len(), evals_B.len());
assert_eq!(evals_A.len(), evals_C.len());
(0..evals_A.len())
.into_par_iter()
.map(|i| r_A * evals_A[i] + r_B * evals_B[i] + r_C * evals_C[i])
.collect::<Vec<Scalar>>()
};

Просмотреть файл

@ -14,6 +14,7 @@ use super::timer::Timer;
use super::transcript::{AppendToTranscript, ProofTranscript};
use core::cmp::Ordering;
use merlin::Transcript;
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Debug)]
@ -423,6 +424,7 @@ impl SparseMatPolynomial {
assert_eq!(self.num_vars_y.pow2(), eval_table_ry.len());
(0..self.M.len())
.into_par_iter()
.map(|i| {
let row = self.M[i].row;
let col = self.M[i].col;

Просмотреть файл

@ -12,6 +12,7 @@ use super::unipoly::{CompressedUniPoly, UniPoly};
use core::iter;
use itertools::izip;
use merlin::Transcript;
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
@ -188,42 +189,49 @@ impl SumcheckInstanceProof {
transcript: &mut Transcript,
) -> (Self, Vec<Scalar>, Vec<Scalar>)
where
F: Fn(&Scalar, &Scalar, &Scalar) -> Scalar,
F: Fn(&Scalar, &Scalar, &Scalar) -> Scalar + Sync,
{
let mut e = *claim;
let mut r: Vec<Scalar> = Vec::new();
let mut cubic_polys: Vec<CompressedUniPoly> = Vec::new();
for _j in 0..num_rounds {
let mut eval_point_0 = Scalar::zero();
let mut eval_point_2 = Scalar::zero();
let mut eval_point_3 = Scalar::zero();
let len = poly_A.len() / 2;
for i in 0..len {
// eval 0: bound_func is A(low)
eval_point_0 += comb_func(&poly_A[i], &poly_B[i], &poly_C[i]);
// eval 2: bound_func is -A(low) + 2*A(high)
let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i];
eval_point_2 += comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
);
let (eval_point_0, eval_point_2, eval_point_3) = {
// make an iterator returning contributions to the three evaluations
let eval_iter = (0..len).into_par_iter().map(|i| {
// eval 0: bound_func is A(low)
let eval_point_0 = comb_func(&poly_A[i], &poly_B[i], &poly_C[i]);
// eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2)
let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i];
// eval 2: bound_func is -A(low) + 2*A(high)
let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i];
let eval_point_2 = comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
);
eval_point_3 += comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
);
}
// eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2)
let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i];
let eval_point_3 = comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
);
(eval_point_0, eval_point_2, eval_point_3)
});
// accumulate contributions using the iter
eval_iter.reduce(
|| (Scalar::zero(), Scalar::zero(), Scalar::zero()),
|a, b| (a.0 + b.0, a.1 + b.1, a.2 + b.2),
)
};
let evals = vec![eval_point_0, e - eval_point_0, eval_point_2, eval_point_3];
let poly = UniPoly::from_evals(&evals);
@ -234,10 +242,18 @@ impl SumcheckInstanceProof {
//derive the verifier's challenge for the next round
let r_j = transcript.challenge_scalar(b"challenge_nextround");
r.push(r_j);
// bound all tables to the verifier's challenege
poly_A.bound_poly_var_top(&r_j);
poly_B.bound_poly_var_top(&r_j);
poly_C.bound_poly_var_top(&r_j);
rayon::join(
|| poly_A.bound_poly_var_top(&r_j),
|| {
rayon::join(
|| poly_B.bound_poly_var_top(&r_j),
|| poly_C.bound_poly_var_top(&r_j),
)
},
);
e = poly.evaluate(&r_j);
cubic_polys.push(poly.compress());
}
@ -272,12 +288,11 @@ impl SumcheckInstanceProof {
(Vec<Scalar>, Vec<Scalar>, Vec<Scalar>),
)
where
F: Fn(&Scalar, &Scalar, &Scalar) -> Scalar,
F: Fn(&Scalar, &Scalar, &Scalar) -> Scalar + Sync,
{
let (poly_A_vec_par, poly_B_vec_par, poly_C_par) = poly_vec_par;
let (poly_A_vec_seq, poly_B_vec_seq, poly_C_vec_seq) = poly_vec_seq;
//let (poly_A_vec_seq, poly_B_vec_seq, poly_C_vec_seq) = poly_vec_seq;
let mut e = *claim;
let mut r: Vec<Scalar> = Vec::new();
let mut cubic_polys: Vec<CompressedUniPoly> = Vec::new();
@ -286,20 +301,18 @@ impl SumcheckInstanceProof {
let mut evals: Vec<(Scalar, Scalar, Scalar)> = Vec::new();
for (poly_A, poly_B) in poly_A_vec_par.iter().zip(poly_B_vec_par.iter()) {
let mut eval_point_0 = Scalar::zero();
let mut eval_point_2 = Scalar::zero();
let mut eval_point_3 = Scalar::zero();
let len = poly_A.len() / 2;
for i in 0..len {
// make an iterator returning the contributions to the evaluations
let eval_iter = (0..len).into_par_iter().map(|i| {
// eval 0: bound_func is A(low)
eval_point_0 += comb_func(&poly_A[i], &poly_B[i], &poly_C_par[i]);
let eval_point_0 = comb_func(&poly_A[i], &poly_B[i], &poly_C_par[i]);
// eval 2: bound_func is -A(low) + 2*A(high)
let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C_par[len + i] + poly_C_par[len + i] - poly_C_par[i];
eval_point_2 += comb_func(
let eval_point_2 = comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
@ -310,12 +323,19 @@ impl SumcheckInstanceProof {
let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C_bound_point + poly_C_par[len + i] - poly_C_par[i];
eval_point_3 += comb_func(
let eval_point_3 = comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
);
}
(eval_point_0, eval_point_2, eval_point_3)
});
// Sum the iterator to get the evaluations
let (eval_point_0, eval_point_2, eval_point_3) = eval_iter.reduce(
|| (Scalar::zero(), Scalar::zero(), Scalar::zero()),
|a, b| (a.0 + b.0, a.1 + b.1, a.2 + b.2),
);
evals.push((eval_point_0, eval_point_2, eval_point_3));
}
@ -325,32 +345,43 @@ impl SumcheckInstanceProof {
poly_B_vec_seq.iter(),
poly_C_vec_seq.iter()
) {
let mut eval_point_0 = Scalar::zero();
let mut eval_point_2 = Scalar::zero();
let mut eval_point_3 = Scalar::zero();
let len = poly_A.len() / 2;
for i in 0..len {
// eval 0: bound_func is A(low)
eval_point_0 += comb_func(&poly_A[i], &poly_B[i], &poly_C[i]);
// eval 2: bound_func is -A(low) + 2*A(high)
let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i];
eval_point_2 += comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
);
// eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2)
let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i];
eval_point_3 += comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
);
}
let (eval_point_0, eval_point_2, eval_point_3) = {
// create an iterator to get contributions to each of the evaluation points
let eval_iter = (0..len).into_par_iter().map(|i| {
// eval 0: bound_func is A(low)
let eval_point_0 = comb_func(&poly_A[i], &poly_B[i], &poly_C[i]);
// eval 2: bound_func is -A(low) + 2*A(high)
let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i];
let eval_point_2 = comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
);
// eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2)
let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i];
let eval_point_3 = comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
);
(eval_point_0, eval_point_2, eval_point_3)
});
// Sum the iterator to get the evaluations
eval_iter.reduce(
|| (Scalar::zero(), Scalar::zero(), Scalar::zero()),
|a, b| (a.0 + b.0, a.1 + b.1, a.2 + b.2),
)
};
evals.push((eval_point_0, eval_point_2, eval_point_3));
}
@ -375,8 +406,10 @@ impl SumcheckInstanceProof {
// bound all tables to the verifier's challenege
for (poly_A, poly_B) in poly_A_vec_par.iter_mut().zip(poly_B_vec_par.iter_mut()) {
poly_A.bound_poly_var_top(&r_j);
poly_B.bound_poly_var_top(&r_j);
rayon::join(
|| poly_A.bound_poly_var_top(&r_j),
|| poly_B.bound_poly_var_top(&r_j),
);
}
poly_C_par.bound_poly_var_top(&r_j);
@ -385,9 +418,15 @@ impl SumcheckInstanceProof {
poly_B_vec_seq.iter_mut(),
poly_C_vec_seq.iter_mut()
) {
poly_A.bound_poly_var_top(&r_j);
poly_B.bound_poly_var_top(&r_j);
poly_C.bound_poly_var_top(&r_j);
rayon::join(
|| poly_A.bound_poly_var_top(&r_j),
|| {
rayon::join(
|| poly_B.bound_poly_var_top(&r_j),
|| poly_C.bound_poly_var_top(&r_j),
)
},
);
}
e = poly.evaluate(&r_j);
@ -436,7 +475,7 @@ impl ZKSumcheckInstanceProof {
random_tape: &mut RandomTape,
) -> (Self, Vec<Scalar>, Vec<Scalar>, Scalar)
where
F: Fn(&Scalar, &Scalar) -> Scalar,
F: Fn(&Scalar, &Scalar) -> Scalar + Sync,
{
let (blinds_poly, blinds_evals) = (
random_tape.random_vector(b"blinds_poly", num_rounds),
@ -452,19 +491,27 @@ impl ZKSumcheckInstanceProof {
for j in 0..num_rounds {
let (poly, comm_poly) = {
let mut eval_point_0 = Scalar::zero();
let mut eval_point_2 = Scalar::zero();
let len = poly_A.len() / 2;
for i in 0..len {
// eval 0: bound_func is A(low)
eval_point_0 += comb_func(&poly_A[i], &poly_B[i]);
let (eval_point_0, eval_point_2) = {
// make an iterator returning contributions to the three evaluations
let eval_iter = (0..len).into_par_iter().map(|i| {
// eval 0: bound_func is A(low)
let eval_point_0 = comb_func(&poly_A[i], &poly_B[i]);
// eval 2: bound_func is -A(low) + 2*A(high)
let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i];
eval_point_2 += comb_func(&poly_A_bound_point, &poly_B_bound_point);
}
// eval 2: bound_func is -A(low) + 2*A(high)
let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i];
let eval_point_2 = comb_func(&poly_A_bound_point, &poly_B_bound_point);
(eval_point_0, eval_point_2)
});
// accumulate contributions using the iter
eval_iter.reduce(
|| (Scalar::zero(), Scalar::zero()),
|a, b| (a.0 + b.0, a.1 + b.1),
)
};
let evals = vec![eval_point_0, claim_per_round - eval_point_0, eval_point_2];
let poly = UniPoly::from_evals(&evals);
@ -480,8 +527,10 @@ impl ZKSumcheckInstanceProof {
let r_j = transcript.challenge_scalar(b"challenge_nextround");
// bound all tables to the verifier's challenege
poly_A.bound_poly_var_top(&r_j);
poly_B.bound_poly_var_top(&r_j);
rayon::join(
|| poly_A.bound_poly_var_top(&r_j),
|| poly_B.bound_poly_var_top(&r_j),
);
// produce a proof of sum-check and of evaluation
let (proof, claim_next_round, comm_claim_next_round) = {
@ -598,7 +647,7 @@ impl ZKSumcheckInstanceProof {
random_tape: &mut RandomTape,
) -> (Self, Vec<Scalar>, Vec<Scalar>, Scalar)
where
F: Fn(&Scalar, &Scalar, &Scalar, &Scalar) -> Scalar,
F: Fn(&Scalar, &Scalar, &Scalar, &Scalar) -> Scalar + Sync,
{
let (blinds_poly, blinds_evals) = (
random_tape.random_vector(b"blinds_poly", num_rounds),
@ -615,39 +664,46 @@ impl ZKSumcheckInstanceProof {
for j in 0..num_rounds {
let (poly, comm_poly) = {
let mut eval_point_0 = Scalar::zero();
let mut eval_point_2 = Scalar::zero();
let mut eval_point_3 = Scalar::zero();
let len = poly_A.len() / 2;
for i in 0..len {
// eval 0: bound_func is A(low)
eval_point_0 += comb_func(&poly_A[i], &poly_B[i], &poly_C[i], &poly_D[i]);
let (eval_point_0, eval_point_2, eval_point_3) = {
// make an iterator returning contributions to the three evaluations
let eval_iter = (0..len).into_par_iter().map(|i| {
// eval 0: bound_func is A(low)
let eval_point_0 = comb_func(&poly_A[i], &poly_B[i], &poly_C[i], &poly_D[i]);
// eval 2: bound_func is -A(low) + 2*A(high)
let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i];
let poly_D_bound_point = poly_D[len + i] + poly_D[len + i] - poly_D[i];
eval_point_2 += comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
&poly_D_bound_point,
);
// eval 2: bound_func is -A(low) + 2*A(high)
let poly_A_bound_point = poly_A[len + i] + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B[len + i] + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C[len + i] + poly_C[len + i] - poly_C[i];
let poly_D_bound_point = poly_D[len + i] + poly_D[len + i] - poly_D[i];
let eval_point_2 = comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
&poly_D_bound_point,
);
// eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2)
let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i];
let poly_D_bound_point = poly_D_bound_point + poly_D[len + i] - poly_D[i];
eval_point_3 += comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
&poly_D_bound_point,
);
}
// eval 3: bound_func is -2A(low) + 3A(high); computed incrementally with bound_func applied to eval(2)
let poly_A_bound_point = poly_A_bound_point + poly_A[len + i] - poly_A[i];
let poly_B_bound_point = poly_B_bound_point + poly_B[len + i] - poly_B[i];
let poly_C_bound_point = poly_C_bound_point + poly_C[len + i] - poly_C[i];
let poly_D_bound_point = poly_D_bound_point + poly_D[len + i] - poly_D[i];
let eval_point_3 = comb_func(
&poly_A_bound_point,
&poly_B_bound_point,
&poly_C_bound_point,
&poly_D_bound_point,
);
(eval_point_0, eval_point_2, eval_point_3)
});
// accumulate contributions using the iter
eval_iter.reduce(
|| (Scalar::zero(), Scalar::zero(), Scalar::zero()),
|a, b| (a.0 + b.0, a.1 + b.1, a.2 + b.2),
)
};
let evals = vec![
eval_point_0,
@ -668,10 +724,20 @@ impl ZKSumcheckInstanceProof {
let r_j = transcript.challenge_scalar(b"challenge_nextround");
// bound all tables to the verifier's challenege
poly_A.bound_poly_var_top(&r_j);
poly_B.bound_poly_var_top(&r_j);
poly_C.bound_poly_var_top(&r_j);
poly_D.bound_poly_var_top(&r_j);
rayon::join(
|| poly_A.bound_poly_var_top(&r_j),
|| {
rayon::join(
|| poly_B.bound_poly_var_top(&r_j),
|| {
rayon::join(
|| poly_C.bound_poly_var_top(&r_j),
|| poly_D.bound_poly_var_top(&r_j),
)
},
)
},
);
// produce a proof of sum-check and of evaluation
let (proof, claim_next_round, comm_claim_next_round) = {