7#include <gtest/gtest.h>
35 for (
auto& poly : full_polynomials.get_precomputed()) {
40 for (
auto& poly : full_polynomials.get_witness()) {
45 for (
auto& poly : full_polynomials.get_shifted()) {
51 if (circuit_size > 1) {
52 full_polynomials.w_l.at(1) =
FF(1);
53 full_polynomials.w_r.at(1) =
FF(1);
54 full_polynomials.w_o.at(1) =
FF(2);
55 full_polynomials.q_l.at(1) =
FF(1);
56 full_polynomials.q_r.at(1) =
FF(1);
57 full_polynomials.q_o.at(1) =
FF(-1);
58 full_polynomials.q_arith.at(1) =
FF(1);
62 if (circuit_size > 2) {
63 full_polynomials.w_l.at(2) =
FF(2);
64 full_polynomials.w_r.at(2) =
FF(2);
65 full_polynomials.w_o.at(2) =
FF(4);
66 full_polynomials.q_m.at(2) =
FF(1);
67 full_polynomials.q_o.at(2) =
FF(-1);
68 full_polynomials.q_arith.at(2) =
FF(1);
74 constexpr size_t NUM_DISABLED_ROWS = 3;
75 if (circuit_size > NUM_DISABLED_ROWS) {
76 for (
size_t i = circuit_size - NUM_DISABLED_ROWS; i < circuit_size; ++i) {
88 full_polynomials.set_shifted();
90 return full_polynomials;
93template <
typename Flavor>
class SumcheckTests :
public ::testing::Test {
105 for (
auto& coeff : poly.coeffs()) {
114 for (
auto [full_poly, input_poly] :
zip_view(full_polynomials.get_all(), input_polynomials)) {
115 full_poly = input_poly.share();
117 return full_polynomials;
120 void test_polynomial_normalization()
123 const size_t multivariate_d(3);
124 const size_t multivariate_n(1 << multivariate_d);
129 for (
auto& poly : random_polynomials) {
130 poly = random_poly(multivariate_n);
132 auto full_polynomials = construct_ultra_full_polynomials(random_polynomials);
134 auto transcript = Flavor::Transcript::prover_init_empty();
136 FF alpha = transcript->template get_challenge<FF>(
"Sumcheck:alpha");
138 std::vector<FF> gate_challenges(multivariate_d);
139 for (
size_t idx = 0; idx < multivariate_d; idx++) {
140 gate_challenges[idx] =
141 transcript->template get_challenge<FF>(
"Sumcheck:gate_challenge_" +
std::to_string(idx));
145 multivariate_n, full_polynomials, transcript, alpha, gate_challenges, {}, multivariate_d);
147 auto output = sumcheck.
prove();
149 FF u_0 = output.challenge[0];
150 FF u_1 = output.challenge[1];
151 FF u_2 = output.challenge[2];
165 FF l_0 = (one - u_0) * (one - u_1) * (one - u_2);
166 FF l_1 = (u_0) * (one - u_1) * (one - u_2);
167 FF l_2 = (one - u_0) * (u_1) * (one - u_2);
168 FF l_3 = (u_0) * (u_1) * (one - u_2);
169 FF l_4 = (one - u_0) * (one - u_1) * (u_2);
170 FF l_5 = (u_0) * (one - u_1) * (u_2);
171 FF l_6 = (one - u_0) * (u_1) * (u_2);
172 FF l_7 = (u_0) * (u_1) * (u_2);
174 FF hand_computed_value;
175 for (
auto [full_poly, partial_eval_poly] :
176 zip_view(full_polynomials.get_all(), sumcheck.partially_evaluated_polynomials.get_all())) {
178 hand_computed_value = l_0 * full_poly[0] + l_1 * full_poly[1] + l_2 * full_poly[2] + l_3 * full_poly[3] +
179 l_4 * full_poly[4] + l_5 * full_poly[5] + l_6 * full_poly[6] + l_7 * full_poly[7];
180 EXPECT_EQ(hand_computed_value, partial_eval_poly[0]);
185 std::vector<FF> u_challenge = { u_0, u_1, u_2 };
186 for (
auto [full_poly, claimed_eval] :
187 zip_view(full_polynomials.get_all(), output.claimed_evaluations.get_all())) {
189 auto v_expected = poly.evaluate_mle(u_challenge);
190 EXPECT_EQ(v_expected, claimed_eval);
196 const size_t multivariate_d(2);
197 const size_t multivariate_n(1 << multivariate_d);
202 for (
auto& poly : random_polynomials) {
203 poly = random_poly(multivariate_n);
205 auto full_polynomials = construct_ultra_full_polynomials(random_polynomials);
207 auto transcript = Flavor::Transcript::prover_init_empty();
209 FF alpha = transcript->template get_challenge<FF>(
"Sumcheck:alpha");
211 std::vector<FF> gate_challenges(multivariate_d);
212 for (
size_t idx = 0; idx < gate_challenges.size(); idx++) {
213 gate_challenges[idx] =
214 transcript->template get_challenge<FF>(
"Sumcheck:gate_challenge_" +
std::to_string(idx));
218 multivariate_n, full_polynomials, transcript, alpha, gate_challenges, {}, CONST_PROOF_SIZE_LOG_N);
223 ZKData zk_sumcheck_data = ZKData(multivariate_d, transcript);
224 output = sumcheck.
prove(zk_sumcheck_data);
226 output = sumcheck.
prove();
228 FF u_0 = output.challenge[0];
229 FF u_1 = output.challenge[1];
230 std::vector<FF> expected_values;
231 for (
auto& polynomial_ptr : full_polynomials.get_all()) {
232 auto& polynomial = polynomial_ptr;
234 FF expected_lo = polynomial[0] * (
FF(1) - u_0) + polynomial[1] * u_0;
235 expected_lo *= (
FF(1) - u_1);
236 FF expected_hi = polynomial[2] * (
FF(1) - u_0) + polynomial[3] * u_0;
238 expected_values.emplace_back(expected_lo + expected_hi);
241 for (
auto [eval, expected] :
zip_view(output.claimed_evaluations.get_all(), expected_values)) {
247 void test_prover_verifier_flow()
249 const size_t multivariate_d(3);
250 const size_t multivariate_n(1 << multivariate_d);
252 const size_t virtual_log_n = 6;
254 auto full_polynomials = create_satisfiable_trace<Flavor>(multivariate_n);
258 auto prover_transcript = Flavor::Transcript::prover_init_empty();
259 FF prover_alpha = prover_transcript->template get_challenge<FF>(
"Sumcheck:alpha");
261 std::vector<FF> prover_gate_challenges(virtual_log_n);
262 prover_gate_challenges =
263 prover_transcript->template get_dyadic_powers_of_challenge<FF>(
"Sumcheck:gate_challenge", virtual_log_n);
269 prover_gate_challenges,
275 ZKData zk_sumcheck_data = ZKData(multivariate_d, prover_transcript);
276 output = sumcheck_prover.prove(zk_sumcheck_data);
278 output = sumcheck_prover.prove();
281 auto verifier_transcript = Flavor::Transcript::verifier_init_empty(prover_transcript);
283 FF verifier_alpha = verifier_transcript->template get_challenge<FF>(
"Sumcheck:alpha");
287 std::vector<FF> verifier_gate_challenges(virtual_log_n);
288 verifier_gate_challenges =
289 verifier_transcript->template get_dyadic_powers_of_challenge<FF>(
"Sumcheck:gate_challenge", virtual_log_n);
291 std::vector<FF> padding_indicator_array(virtual_log_n, 1);
293 for (
size_t idx = 0; idx < virtual_log_n; idx++) {
294 padding_indicator_array[idx] = (idx < multivariate_d) ?
FF{ 1 } :
FF{ 0 };
298 auto verifier_output =
299 sumcheck_verifier.verify(relation_parameters, verifier_gate_challenges, padding_indicator_array);
301 auto verified = verifier_output.verified;
303 EXPECT_EQ(verified,
true);
306 void test_failure_prover_verifier_flow()
310 const size_t multivariate_d(3);
311 const size_t multivariate_n(1 << multivariate_d);
314 auto full_polynomials = create_satisfiable_trace<Flavor>(multivariate_n);
320 full_polynomials.w_l.at(1) =
FF(0);
324 auto prover_transcript = Flavor::Transcript::prover_init_empty();
325 FF prover_alpha = prover_transcript->template get_challenge<FF>(
"Sumcheck:alpha");
327 auto prover_gate_challenges =
328 prover_transcript->template get_dyadic_powers_of_challenge<FF>(
"Sumcheck:gate_challenge", multivariate_d);
334 prover_gate_challenges,
341 ZKData zk_sumcheck_data = ZKData(multivariate_d, prover_transcript);
342 output = sumcheck_prover.prove(zk_sumcheck_data);
344 output = sumcheck_prover.prove();
347 auto verifier_transcript = Flavor::Transcript::verifier_init_empty(prover_transcript);
349 FF verifier_alpha = verifier_transcript->template get_challenge<FF>(
"Sumcheck:alpha");
353 std::vector<FF> verifier_gate_challenges(multivariate_d);
354 for (
size_t idx = 0; idx < multivariate_d; idx++) {
355 verifier_gate_challenges[idx] =
356 verifier_transcript->template get_challenge<FF>(
"Sumcheck:gate_challenge_" +
std::to_string(idx));
359 std::vector<FF> padding_indicator_array(multivariate_d);
360 std::ranges::fill(padding_indicator_array,
FF{ 1 });
361 auto verifier_output =
362 sumcheck_verifier.verify(relation_parameters, verifier_gate_challenges, padding_indicator_array);
364 auto verified = verifier_output.verified;
366 EXPECT_EQ(verified,
false);
379TYPED_TEST(SumcheckTests, PolynomialNormalization)
381 if constexpr (!TypeParam::HasZK) {
382 this->test_polynomial_normalization();
384 GTEST_SKIP() <<
"Skipping test for ZK-enabled flavors";
393TYPED_TEST(SumcheckTests, ProverAndVerifierSimple)
395 this->test_prover_verifier_flow();
398TYPED_TEST(SumcheckTests, ProverAndVerifierSimpleFailure)
400 this->test_failure_prover_verifier_flow();
A container for the prover polynomials.
static constexpr bool HasZK
typename Curve::ScalarField FF
static constexpr size_t NUM_ALL_ENTITIES
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
static Polynomial shiftable(size_t virtual_size)
Utility to create a shiftable polynomial of given virtual size.
The implementation of the sumcheck Prover for statements of the form for multilinear polynomials .
SumcheckOutput< Flavor > prove()
Non-ZK version: Compute round univariate, place it in transcript, compute challenge,...
A flexible, minimal test flavor for sumcheck testing.
Implementation of the sumcheck Verifier for statements of the form for multilinear polynomials .
typename ECCVMFlavor::ProverPolynomials ProverPolynomials
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
SumcheckTestFlavor_< curve::BN254, true, true > SumcheckTestFlavorZK
Zero-knowledge variant.
SumcheckTestFlavor_< curve::BN254, false, true > SumcheckTestFlavor
Base test flavor (BN254, non-ZK, short monomials)
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
Container for parameters used by the grand product (permutation, lookup) Honk relations.
Contains the evaluations of multilinear polynomials at the challenge point . These are computed by S...
This structure is created to contain various polynomials and constants required by ZK Sumcheck.
static field random_element(numeric::RNG *engine=nullptr) noexcept
Minimal test flavors for sumcheck testing without UltraFlavor dependencies.