@@ -160,15 +160,23 @@ template <typename Flavor> class SumcheckProverRound {
160160 const size_t edge_idx)
161161 {
162162 for (auto [extended_edge, multivariate] : zip_view (extended_edges.get_all (), multivariates.get_all ())) {
163+ const size_t end = multivariate.end_index ();
163164 if constexpr (Flavor::USE_SHORT_MONOMIALS ) {
164- extended_edge = bb::Univariate<FF , 2 >({ multivariate[edge_idx], multivariate[edge_idx + 1 ] });
165+ // The main loop iterates up to effective_round_size, which rounds max_end_index up to even.
166+ // For odd max_end_index, the second read of the final edge lands at index == end_index, which
167+ // would trip the virtual-zeroes assertion for polynomials with virtual_size == end_index
168+ // (e.g. gemini_masking_poly). Treat reads past end_index as zero directly.
169+ const FF v0 = (edge_idx < end) ? FF (multivariate[edge_idx]) : FF::zero ();
170+ const FF v1 = (edge_idx + 1 < end) ? FF (multivariate[edge_idx + 1 ]) : FF::zero ();
171+ extended_edge = bb::Univariate<FF , 2 >({ v0, v1 });
165172 } else {
166- if (multivariate. end_index () < edge_idx) {
173+ if (end <= edge_idx) {
167174 static const auto zero_univariate = bb::Univariate<FF , MAX_PARTIAL_RELATION_LENGTH >::zero ();
168175 extended_edge = zero_univariate;
169176 } else {
170- extended_edge = bb::Univariate<FF , 2 >({ multivariate[edge_idx], multivariate[edge_idx + 1 ] })
171- .template extend_to <MAX_PARTIAL_RELATION_LENGTH >();
177+ const FF v0 = multivariate[edge_idx];
178+ const FF v1 = (edge_idx + 1 < end) ? FF (multivariate[edge_idx + 1 ]) : FF::zero ();
179+ extended_edge = bb::Univariate<FF , 2 >({ v0, v1 }).template extend_to <MAX_PARTIAL_RELATION_LENGTH >();
172180 }
173181 }
174182 }
0 commit comments