Skip to content

Commit c0ee259

Browse files
authored
Small fixes (#147)
* Tighten MC fold guard and verify bounds - Restrict the truncated step fold to zero-rest witnesses; fall back to the full fold otherwise. - Reject degree-0 rounds in sumcheck verify before decompress. - Require an exact row count in Hyrax verify. * Mirror verify-bound fixes in Python reference - Reject degree-0 rounds in sumcheck verify. - Require an exact row count in Hyrax verify.
1 parent 833dfc7 commit c0ee259

5 files changed

Lines changed: 18 additions & 11 deletions

File tree

reference/pyvega/hyrax.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ def pcs_verify(vk, ck_eval, transcript, comm, point, comm_eval, arg):
7676
num_rows = mathutil.div_ceil(n, num_cols)
7777
num_vars_rows = mathutil.log2(num_rows)
7878

79-
if len(comm) < num_rows:
79+
if len(comm) != num_rows:
8080
raise ValueError(
81-
f"Hyrax verify: commitment has {len(comm)} rows, fewer than {num_rows} required"
81+
f"Hyrax verify: commitment has {len(comm)} rows, expected exactly {num_rows}"
8282
)
8383
if len(comm_eval) == 0:
8484
raise ValueError("Hyrax verify: evaluation commitment is empty")

reference/pyvega/sumcheck.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ def sumcheck_verify(compressed_polys, claim, num_rounds, degree_bound, transcrip
2828
raise ValueError(
2929
f"InvalidSumcheckProof: round {i} degree {len(cp)} != {degree_bound}"
3030
)
31+
# decompress reads the first stored coefficient; a degree-0 round has none.
32+
if degree_bound == 0:
33+
raise ValueError("InvalidSumcheckProof: degree_bound must be >= 1")
3134
coeffs = unipoly_decompress(cp, e)
3235
transcript.absorb_unipoly(b"p", cp)
3336
r_i = transcript.squeeze(b"c")

src/provider/pcs/hyrax_pc.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -498,12 +498,12 @@ where
498498

499499
let (num_vars_rows, _num_vars_cols) = (num_rows.log_2(), num_cols.log_2());
500500

501-
// The commitment must have enough rows to open at this point, and the
502-
// evaluation commitment must be non-empty.
503-
if comm.comm.len() < num_rows {
501+
// The commitment must have exactly the number of rows implied by the opening
502+
// point, and the evaluation commitment must be non-empty.
503+
if comm.comm.len() != num_rows {
504504
return Err(VegaError::InvalidCommitmentLength {
505505
reason: format!(
506-
"Hyrax verify: commitment has {} rows, fewer than the {} required",
506+
"Hyrax verify: commitment has {} rows, expected exactly {}",
507507
comm.comm.len(),
508508
num_rows
509509
),

src/sumcheck.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ impl<E: Engine> SumcheckProof<E> {
8888
return Err(VegaError::InvalidSumcheckProof);
8989
}
9090

91+
// decompress reads the first stored coefficient; a degree-0 round has none.
92+
if degree_bound == 0 {
93+
return Err(VegaError::InvalidSumcheckProof);
94+
}
95+
9196
let poly = self.compressed_polys[i].decompress(&e);
9297

9398
// we do not need to check if poly(0) + poly(1) = e, as

src/vega_mc_zkp.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,12 +1204,11 @@ where
12041204
let _ =
12051205
SatisfyingAssignment::<E>::process_round(vc_state, vc_shape, vc_ck, vc, ell_b, transcript)?;
12061206

1207-
// Truncate witness W vectors to skip zero rest portion before folding.
1208-
// The rest portion (indices effective_len..) is all zero for step circuits,
1209-
// so the folded result there is also zero. We resize back after folding.
1210-
// Only apply when shared+precommitted > 0 (otherwise truncation would zero everything).
1207+
// Fast path: when the rest witness is pure padding (num_rest_unpadded == 0) and the
1208+
// shared+precommitted prefix is nonempty, fold only that prefix and rebuild the zero
1209+
// rest rows from the folded blind. Otherwise fold the full witness and commitment.
12111210
let effective_len = S.num_shared + S.num_precommitted;
1212-
let use_truncated_fold = effective_len > 0;
1211+
let use_truncated_fold = effective_len > 0 && S.num_rest_unpadded == 0;
12131212
if use_truncated_fold {
12141213
for w in Ws.iter_mut() {
12151214
w.W.truncate(effective_len);

0 commit comments

Comments
 (0)