Skip to content

Commit c5196fc

Browse files
committed
Revert "apply bound witness fix to ppsnark (#182)"
This reverts commit bba15ba.
1 parent 11d271b commit c5196fc

File tree

2 files changed

+92
-115
lines changed

2 files changed

+92
-115
lines changed

src/spartan/batched_ppsnark.rs

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::{
2020
powers,
2121
ppsnark::{
2222
InnerSumcheckInstance, MemorySumcheckInstance, OuterSumcheckInstance,
23-
R1CSShapeSparkCommitment, R1CSShapeSparkRepr, SumcheckEngine, WitnessBoundSumcheck,
23+
R1CSShapeSparkCommitment, R1CSShapeSparkRepr, SumcheckEngine,
2424
},
2525
sumcheck::SumcheckProof,
2626
PolyEvalInstance, PolyEvalWitness,
@@ -89,6 +89,84 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> DigestHelperTrait<E> for VerifierK
8989
}
9090
}
9191

92+
/// The [WitnessBoundSumcheck] ensures that the witness polynomial W defined over n = log(N) variables,
93+
/// is zero outside of the first `num_vars = 2^m` entries.
94+
///
95+
/// # Details
96+
///
97+
/// The `W` polynomial is padded with zeros to size N = 2^n.
98+
/// The `masked_eq` polynomials is defined as with regards to a random challenge `tau` as
99+
/// the eq(tau) polynomial, where the first 2^m evaluations to 0.
100+
///
101+
/// The instance is given by
102+
/// `0 = ∑_{0≤i<2^n} masked_eq[i] * W[i]`.
103+
/// It is equivalent to the expression
104+
/// `0 = ∑_{2^m≤i<2^n} eq[i] * W[i]`
105+
/// Since `eq` is random, the instance is only satisfied if `W[2^{m}..] = 0`.
106+
pub(in crate::spartan) struct WitnessBoundSumcheck<E: Engine> {
107+
poly_W: MultilinearPolynomial<E::Scalar>,
108+
poly_masked_eq: MultilinearPolynomial<E::Scalar>,
109+
}
110+
111+
impl<E: Engine> WitnessBoundSumcheck<E> {
112+
pub fn new(tau: E::Scalar, poly_W_padded: Vec<E::Scalar>, num_vars: usize) -> Self {
113+
let num_vars_log = num_vars.log_2();
114+
// When num_vars = num_rounds, we shouldn't have to prove anything
115+
// but we still want this instance to compute the evaluation of W
116+
let num_rounds = poly_W_padded.len().log_2();
117+
assert!(num_vars_log < num_rounds);
118+
119+
let tau_coords = PowPolynomial::new(&tau, num_rounds).coordinates();
120+
let poly_masked_eq_evals =
121+
MaskedEqPolynomial::new(&EqPolynomial::new(tau_coords), num_vars_log).evals();
122+
123+
Self {
124+
poly_W: MultilinearPolynomial::new(poly_W_padded),
125+
poly_masked_eq: MultilinearPolynomial::new(poly_masked_eq_evals),
126+
}
127+
}
128+
}
129+
impl<E: Engine> SumcheckEngine<E> for WitnessBoundSumcheck<E> {
130+
fn initial_claims(&self) -> Vec<E::Scalar> {
131+
vec![E::Scalar::ZERO]
132+
}
133+
134+
fn degree(&self) -> usize {
135+
3
136+
}
137+
138+
fn size(&self) -> usize {
139+
assert_eq!(self.poly_W.len(), self.poly_masked_eq.len());
140+
self.poly_W.len()
141+
}
142+
143+
fn evaluation_points(&self) -> Vec<Vec<E::Scalar>> {
144+
let comb_func = |poly_A_comp: &E::Scalar,
145+
poly_B_comp: &E::Scalar,
146+
_: &E::Scalar|
147+
-> E::Scalar { *poly_A_comp * *poly_B_comp };
148+
149+
let (eval_point_0, eval_point_2, eval_point_3) = SumcheckProof::<E>::compute_eval_points_cubic(
150+
&self.poly_masked_eq,
151+
&self.poly_W,
152+
&self.poly_W, // unused
153+
&comb_func,
154+
);
155+
156+
vec![vec![eval_point_0, eval_point_2, eval_point_3]]
157+
}
158+
159+
fn bound(&mut self, r: &E::Scalar) {
160+
[&mut self.poly_W, &mut self.poly_masked_eq]
161+
.par_iter_mut()
162+
.for_each(|poly| poly.bind_poly_var_top(r));
163+
}
164+
165+
fn final_claims(&self) -> Vec<Vec<E::Scalar>> {
166+
vec![vec![self.poly_W[0], self.poly_masked_eq[0]]]
167+
}
168+
}
169+
92170
/// A succinct proof of knowledge of a witness to a relaxed R1CS instance
93171
/// The proof is produced using Spartan's combination of the sum-check and
94172
/// the commitment to a vector viewed as a polynomial commitment

src/spartan/ppsnark.rs

Lines changed: 13 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use crate::{
1313
polys::{
1414
eq::EqPolynomial,
1515
identity::IdentityPolynomial,
16-
masked_eq::MaskedEqPolynomial,
1716
multilinear::MultilinearPolynomial,
1817
power::PowPolynomial,
1918
univariate::{CompressedUniPoly, UniPoly},
@@ -257,84 +256,6 @@ pub trait SumcheckEngine<E: Engine>: Send + Sync {
257256
fn final_claims(&self) -> Vec<Vec<E::Scalar>>;
258257
}
259258

260-
/// The [WitnessBoundSumcheck] ensures that the witness polynomial W defined over n = log(N) variables,
261-
/// is zero outside of the first `num_vars = 2^m` entries.
262-
///
263-
/// # Details
264-
///
265-
/// The `W` polynomial is padded with zeros to size N = 2^n.
266-
/// The `masked_eq` polynomials is defined as with regards to a random challenge `tau` as
267-
/// the eq(tau) polynomial, where the first 2^m evaluations to 0.
268-
///
269-
/// The instance is given by
270-
/// `0 = ∑_{0≤i<2^n} masked_eq[i] * W[i]`.
271-
/// It is equivalent to the expression
272-
/// `0 = ∑_{2^m≤i<2^n} eq[i] * W[i]`
273-
/// Since `eq` is random, the instance is only satisfied if `W[2^{m}..] = 0`.
274-
pub(in crate::spartan) struct WitnessBoundSumcheck<E: Engine> {
275-
poly_W: MultilinearPolynomial<E::Scalar>,
276-
poly_masked_eq: MultilinearPolynomial<E::Scalar>,
277-
}
278-
279-
impl<E: Engine> WitnessBoundSumcheck<E> {
280-
pub fn new(tau: E::Scalar, poly_W_padded: Vec<E::Scalar>, num_vars: usize) -> Self {
281-
let num_vars_log = num_vars.log_2();
282-
// When num_vars = num_rounds, we shouldn't have to prove anything
283-
// but we still want this instance to compute the evaluation of W
284-
let num_rounds = poly_W_padded.len().log_2();
285-
assert!(num_vars_log < num_rounds);
286-
287-
let tau_coords = PowPolynomial::new(&tau, num_rounds).coordinates();
288-
let poly_masked_eq_evals =
289-
MaskedEqPolynomial::new(&EqPolynomial::new(tau_coords), num_vars_log).evals();
290-
291-
Self {
292-
poly_W: MultilinearPolynomial::new(poly_W_padded),
293-
poly_masked_eq: MultilinearPolynomial::new(poly_masked_eq_evals),
294-
}
295-
}
296-
}
297-
impl<E: Engine> SumcheckEngine<E> for WitnessBoundSumcheck<E> {
298-
fn initial_claims(&self) -> Vec<E::Scalar> {
299-
vec![E::Scalar::ZERO]
300-
}
301-
302-
fn degree(&self) -> usize {
303-
3
304-
}
305-
306-
fn size(&self) -> usize {
307-
assert_eq!(self.poly_W.len(), self.poly_masked_eq.len());
308-
self.poly_W.len()
309-
}
310-
311-
fn evaluation_points(&self) -> Vec<Vec<E::Scalar>> {
312-
let comb_func = |poly_A_comp: &E::Scalar,
313-
poly_B_comp: &E::Scalar,
314-
_: &E::Scalar|
315-
-> E::Scalar { *poly_A_comp * *poly_B_comp };
316-
317-
let (eval_point_0, eval_point_2, eval_point_3) = SumcheckProof::<E>::compute_eval_points_cubic(
318-
&self.poly_masked_eq,
319-
&self.poly_W,
320-
&self.poly_W, // unused
321-
&comb_func,
322-
);
323-
324-
vec![vec![eval_point_0, eval_point_2, eval_point_3]]
325-
}
326-
327-
fn bound(&mut self, r: &E::Scalar) {
328-
[&mut self.poly_W, &mut self.poly_masked_eq]
329-
.par_iter_mut()
330-
.for_each(|poly| poly.bind_poly_var_top(r));
331-
}
332-
333-
fn final_claims(&self) -> Vec<Vec<E::Scalar>> {
334-
vec![vec![self.poly_W[0], self.poly_masked_eq[0]]]
335-
}
336-
}
337-
338259
pub(in crate::spartan) struct MemorySumcheckInstance<E: Engine> {
339260
// row
340261
w_plus_r_row: MultilinearPolynomial<E::Scalar>,
@@ -951,11 +872,10 @@ pub struct RelaxedR1CSSNARK<E: Engine, EE: EvaluationEngineTrait<E>> {
951872
}
952873

953874
impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARK<E, EE> {
954-
fn prove_helper<T1, T2, T3, T4>(
875+
fn prove_helper<T1, T2, T3>(
955876
mem: &mut T1,
956877
outer: &mut T2,
957878
inner: &mut T3,
958-
witness: &mut T4,
959879
transcript: &mut E::TE,
960880
) -> Result<
961881
(
@@ -964,31 +884,26 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARK<E, EE> {
964884
Vec<Vec<E::Scalar>>,
965885
Vec<Vec<E::Scalar>>,
966886
Vec<Vec<E::Scalar>>,
967-
Vec<Vec<E::Scalar>>,
968887
),
969888
NovaError,
970889
>
971890
where
972891
T1: SumcheckEngine<E>,
973892
T2: SumcheckEngine<E>,
974893
T3: SumcheckEngine<E>,
975-
T4: SumcheckEngine<E>,
976894
{
977895
// sanity checks
978896
assert_eq!(mem.size(), outer.size());
979897
assert_eq!(mem.size(), inner.size());
980-
assert_eq!(mem.size(), witness.size());
981898
assert_eq!(mem.degree(), outer.degree());
982899
assert_eq!(mem.degree(), inner.degree());
983-
assert_eq!(mem.degree(), witness.degree());
984900

985901
// these claims are already added to the transcript, so we do not need to add
986902
let claims = mem
987903
.initial_claims()
988904
.into_iter()
989905
.chain(outer.initial_claims())
990906
.chain(inner.initial_claims())
991-
.chain(witness.initial_claims())
992907
.collect::<Vec<E::Scalar>>();
993908

994909
let s = transcript.squeeze(b"r")?;
@@ -1002,16 +917,15 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARK<E, EE> {
1002917
let mut cubic_polys: Vec<CompressedUniPoly<E::Scalar>> = Vec::new();
1003918
let num_rounds = mem.size().log_2();
1004919
for _ in 0..num_rounds {
1005-
let ((evals_mem, evals_outer), (evals_inner, evals_witness)) = rayon::join(
1006-
|| rayon::join(|| mem.evaluation_points(), || outer.evaluation_points()),
1007-
|| rayon::join(|| inner.evaluation_points(), || witness.evaluation_points()),
920+
let (evals_mem, (evals_outer, evals_inner)) = rayon::join(
921+
|| mem.evaluation_points(),
922+
|| rayon::join(|| outer.evaluation_points(), || inner.evaluation_points()),
1008923
);
1009924

1010925
let evals: Vec<Vec<E::Scalar>> = evals_mem
1011926
.into_iter()
1012927
.chain(evals_outer.into_iter())
1013928
.chain(evals_inner.into_iter())
1014-
.chain(evals_witness.into_iter())
1015929
.collect::<Vec<Vec<E::Scalar>>>();
1016930
assert_eq!(evals.len(), claims.len());
1017931

@@ -1035,8 +949,8 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARK<E, EE> {
1035949
r.push(r_i);
1036950

1037951
let _ = rayon::join(
1038-
|| rayon::join(|| mem.bound(&r_i), || outer.bound(&r_i)),
1039-
|| rayon::join(|| inner.bound(&r_i), || witness.bound(&r_i)),
952+
|| mem.bound(&r_i),
953+
|| rayon::join(|| outer.bound(&r_i), || inner.bound(&r_i)),
1040954
);
1041955

1042956
e = poly.evaluate(&r_i);
@@ -1046,15 +960,13 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARK<E, EE> {
1046960
let mem_claims = mem.final_claims();
1047961
let outer_claims = outer.final_claims();
1048962
let inner_claims = inner.final_claims();
1049-
let witness_claims = witness.final_claims();
1050963

1051964
Ok((
1052965
SumcheckProof::new(cubic_polys),
1053966
r,
1054967
mem_claims,
1055968
outer_claims,
1056969
inner_claims,
1057-
witness_claims,
1058970
))
1059971
}
1060972
}
@@ -1291,13 +1203,10 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARKTrait<E> for Relax
12911203

12921204
let (mut mem_sc_inst, comm_mem_oracles, mem_oracles) = mem_res?;
12931205

1294-
let mut witness_sc_inst = WitnessBoundSumcheck::new(tau, W.clone(), S.num_vars);
1295-
1296-
let (sc, rand_sc, claims_mem, claims_outer, claims_inner, claims_witness) = Self::prove_helper(
1206+
let (sc, rand_sc, claims_mem, claims_outer, claims_inner) = Self::prove_helper(
12971207
&mut mem_sc_inst,
12981208
&mut outer_sc_inst,
12991209
&mut inner_sc_inst,
1300-
&mut witness_sc_inst,
13011210
&mut transcript,
13021211
)?;
13031212

@@ -1315,11 +1224,11 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARKTrait<E> for Relax
13151224
let eval_t_plus_r_inv_col = claims_mem[1][0];
13161225
let eval_w_plus_r_inv_col = claims_mem[1][1];
13171226
let eval_ts_col = claims_mem[1][2];
1318-
let eval_W = claims_witness[0][0];
13191227

13201228
// compute the remaining claims that did not come for free from the sum-check prover
1321-
let (eval_Cz, eval_E, eval_val_A, eval_val_B, eval_val_C, eval_row, eval_col) = {
1229+
let (eval_W, eval_Cz, eval_E, eval_val_A, eval_val_B, eval_val_C, eval_row, eval_col) = {
13221230
let e = [
1231+
&W,
13231232
&Cz,
13241233
&E,
13251234
&pk.S_repr.val_A,
@@ -1331,7 +1240,7 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARKTrait<E> for Relax
13311240
.into_par_iter()
13321241
.map(|p| MultilinearPolynomial::evaluate_with(p, &rand_sc))
13331242
.collect::<Vec<E::Scalar>>();
1334-
(e[0], e[1], e[2], e[3], e[4], e[5], e[6])
1243+
(e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7])
13351244
};
13361245

13371246
// all the evaluations are at rand_sc, we can fold them into one claim
@@ -1516,7 +1425,7 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARKTrait<E> for Relax
15161425

15171426
let rho = transcript.squeeze(b"r")?;
15181427

1519-
let num_claims = 10;
1428+
let num_claims = 9;
15201429
let s = transcript.squeeze(b"r")?;
15211430
let coeffs = powers::<E>(&s, num_claims);
15221431
let claim = (coeffs[7] + coeffs[8]) * claim; // rest are zeros
@@ -1530,12 +1439,7 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARKTrait<E> for Relax
15301439
let poly_eq_coords = PowPolynomial::new(&rho, num_rounds_sc).coordinates();
15311440
EqPolynomial::new(poly_eq_coords).evaluate(&rand_sc)
15321441
};
1533-
let taus_coords = PowPolynomial::new(&tau, num_rounds_sc).coordinates();
1534-
let eq_tau = EqPolynomial::new(taus_coords);
1535-
1536-
let taus_bound_rand_sc = eq_tau.evaluate(&rand_sc);
1537-
let taus_masked_bound_rand_sc =
1538-
MaskedEqPolynomial::new(&eq_tau, vk.num_vars.log_2()).evaluate(&rand_sc);
1442+
let taus_bound_rand_sc = PowPolynomial::new(&tau, num_rounds_sc).evaluate(&rand_sc);
15391443

15401444
let eval_t_plus_r_row = {
15411445
let eval_addr_row = IdentityPolynomial::new(num_rounds_sc).evaluate(&rand_sc);
@@ -1620,12 +1524,7 @@ impl<E: Engine, EE: EvaluationEngineTrait<E>> RelaxedR1CSSNARKTrait<E> for Relax
16201524
* self.eval_L_col
16211525
* (self.eval_val_A + c * self.eval_val_B + c * c * self.eval_val_C);
16221526

1623-
let claim_witness_final_expected = coeffs[9] * taus_masked_bound_rand_sc * self.eval_W;
1624-
1625-
claim_mem_final_expected
1626-
+ claim_outer_final_expected
1627-
+ claim_inner_final_expected
1628-
+ claim_witness_final_expected
1527+
claim_mem_final_expected + claim_outer_final_expected + claim_inner_final_expected
16291528
};
16301529

16311530
if claim_sc_final_expected != claim_sc_final {

0 commit comments

Comments
 (0)