Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
shplemini.test.cpp
Go to the documentation of this file.
1
2#include "shplemini.hpp"
3#include "../commitment_key.test.hpp"
4#include "../gemini/gemini.hpp"
5#include "../kzg/kzg.hpp"
6#include "../shplonk/shplonk.hpp"
7#include "../utils/batch_mul_native.hpp"
14
15#include <gtest/gtest.h>
16#include <vector>
17
18namespace bb {
19
20template <class Flavor> class ShpleminiTest : public CommitmentTest<typename Flavor::Curve> {
21 public:
22 // Size of the test polynomials
23 static constexpr size_t log_n = 9;
24 static constexpr size_t n = 1UL << log_n;
25 // Total number of random polynomials in each test
26 static constexpr size_t num_polynomials = 7;
27 // Number of shiftable polynomials
28 static constexpr size_t num_shiftable = 2;
29
30 // The length of the mock sumcheck univariates.
31 static constexpr size_t sumcheck_univariate_length = 24;
32
33 using Fr = typename Flavor::Curve::ScalarField;
34 using GroupElement = typename Flavor::Curve::Element;
35 using Commitment = typename Flavor::Curve::AffineElement;
36 using CK = typename Flavor::CommitmentKey;
38};
39
40using TestSettings = ::testing::Types<BN254Settings, GrumpkinSettings>;
41
43
44// Non-template test fixture for KZG-specific tests
45class ShpleminiKZGTest : public CommitmentTest<curve::BN254> {
46 public:
47 static constexpr size_t log_n = 9;
48 static constexpr size_t n = 1UL << log_n;
49};
50
51// This test checks that batch_multivariate_opening_claims method operates correctly
52TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
53{
54 using Curve = typename TypeParam::Curve;
55 using Fr = typename Curve::ScalarField;
56 using GroupElement = typename Curve::Element;
57 using Commitment = typename Curve::AffineElement;
58 using CK = typename TypeParam::CommitmentKey;
59
60 CK ck = create_commitment_key<CK>(this->n);
61
62 // Generate mock challenges
63 Fr rho = Fr::random_element();
64 Fr gemini_eval_challenge = Fr::random_element();
65 Fr shplonk_batching_challenge = Fr::random_element();
66 Fr shplonk_eval_challenge = Fr::random_element();
67
68 // Generate multilinear polynomials and compute their commitments
69 auto mle_opening_point = this->random_evaluation_point(this->log_n);
70
71 MockClaimGenerator<Curve> mock_claims(this->n,
72 /*num_polynomials*/ this->num_polynomials,
73 /*num_to_be_shifted*/ this->num_shiftable,
74 mle_opening_point,
75 ck);
76
77 // Collect multilinear evaluations
78 std::vector<Fr> rhos = gemini::powers_of_rho(rho, this->num_polynomials + this->num_shiftable);
79
80 // Lambda to compute batched multivariate evaluation
81 auto update_batched_eval = [&](Fr& batched_eval, const std::vector<Fr>& evaluations, Fr& rho_power) {
82 for (auto& eval : evaluations) {
83 batched_eval += eval * rho_power;
84 rho_power *= rho;
85 }
86 };
87
88 Fr rho_power(1);
89 Fr batched_evaluation(0);
90 update_batched_eval(batched_evaluation, mock_claims.unshifted.evals, rho_power);
91 update_batched_eval(batched_evaluation, mock_claims.to_be_shifted.evals, rho_power);
92
93 // Lambda to compute batched commitment
94 auto compute_batched_commitment = [&](const std::vector<Commitment>& commitments, Fr& rho_power) {
95 GroupElement batched = GroupElement::zero();
96 for (auto& comm : commitments) {
97 batched += comm * rho_power;
98 rho_power *= rho;
99 }
100 return batched;
101 };
102
103 // Compute batched commitments manually
104 rho_power = Fr(1);
105 GroupElement batched_commitment_unshifted =
106 compute_batched_commitment(mock_claims.unshifted.commitments, rho_power);
107 GroupElement batched_commitment_to_be_shifted =
108 compute_batched_commitment(mock_claims.to_be_shifted.commitments, rho_power);
109
110 // Compute expected result manually
111 GroupElement to_be_shifted_contribution = batched_commitment_to_be_shifted * gemini_eval_challenge.invert();
112
113 GroupElement commitment_to_univariate_pos = batched_commitment_unshifted + to_be_shifted_contribution;
114
115 GroupElement commitment_to_univariate_neg = batched_commitment_unshifted - to_be_shifted_contribution;
116
117 GroupElement expected_result =
118 commitment_to_univariate_pos * (shplonk_eval_challenge - gemini_eval_challenge).invert() +
119 commitment_to_univariate_neg *
120 (shplonk_batching_challenge * (shplonk_eval_challenge + gemini_eval_challenge).invert());
121
122 // Run the ShepliminiVerifier batching method
123 std::vector<Commitment> commitments;
124 std::vector<Fr> scalars;
125 Fr verifier_batched_evaluation{ 0 };
126
127 Fr inverted_vanishing_eval_pos = (shplonk_eval_challenge - gemini_eval_challenge).invert();
128 Fr inverted_vanishing_eval_neg = (shplonk_eval_challenge + gemini_eval_challenge).invert();
129
130 std::vector<Fr> inverted_vanishing_evals = { inverted_vanishing_eval_pos, inverted_vanishing_eval_neg };
131
133 inverted_vanishing_evals, shplonk_batching_challenge, gemini_eval_challenge);
134
136 commitments, scalars, verifier_batched_evaluation, rho);
137
138 // Final pairing check
139 GroupElement shplemini_result = batch_mul_native<Curve>(commitments, scalars);
140
141 EXPECT_EQ(commitments.size(),
142 mock_claims.unshifted.commitments.size() + mock_claims.to_be_shifted.commitments.size());
143 EXPECT_EQ(batched_evaluation, verifier_batched_evaluation);
144 EXPECT_EQ(-expected_result, shplemini_result);
145}
146TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching)
147{
148 using Curve = TypeParam::Curve;
149 using GeminiProver = GeminiProver_<Curve>;
150 using ShpleminiVerifier = ShpleminiVerifier_<Curve>;
151 using ShplonkVerifier = ShplonkVerifier_<Curve>;
152 using Fr = typename Curve::ScalarField;
153 using GroupElement = typename Curve::Element;
154 using Commitment = typename Curve::AffineElement;
155 using Polynomial = typename bb::Polynomial<Fr>;
156 using CK = typename TypeParam::CommitmentKey;
157
158 CK ck = create_commitment_key<CK>(this->n);
159
160 // Generate mock challenges
161 Fr rho = Fr::random_element();
162 Fr gemini_eval_challenge = Fr::random_element();
163 Fr shplonk_batching_challenge = Fr::random_element();
164
165 std::vector<Fr> shplonk_batching_challenge_powers =
166 compute_shplonk_batching_challenge_powers(shplonk_batching_challenge, this->log_n);
167
168 Fr shplonk_eval_challenge = Fr::random_element();
169
170 std::vector<Fr> mle_opening_point = this->random_evaluation_point(this->log_n);
171
172 MockClaimGenerator<Curve> mock_claims(this->n,
173 /*num_polynomials*/ this->num_polynomials,
174 /*num_to_be_shifted*/ this->num_shiftable,
175 mle_opening_point,
176 ck);
177
178 // Collect multilinear evaluations
179 std::vector<Fr> rhos = gemini::powers_of_rho(rho, this->num_polynomials + this->num_shiftable);
180
181 Polynomial batched = mock_claims.polynomial_batcher.compute_batched(rho);
182
183 // Compute:
184 // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
185 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
186 auto fold_polynomials = GeminiProver::compute_fold_polynomials(this->log_n, mle_opening_point, batched);
187
188 std::vector<Commitment> prover_commitments;
189 for (size_t l = 0; l < this->log_n - 1; ++l) {
190 auto commitment = ck.commit(fold_polynomials[l]);
191 prover_commitments.emplace_back(commitment);
192 }
193
194 auto [A_0_pos, A_0_neg] =
195 mock_claims.polynomial_batcher.compute_partially_evaluated_batch_polynomials(gemini_eval_challenge);
196
197 const auto opening_claims = GeminiProver::construct_univariate_opening_claims(
198 this->log_n, std::move(A_0_pos), std::move(A_0_neg), std::move(fold_polynomials), gemini_eval_challenge);
199
200 std::vector<Fr> prover_evaluations;
201 for (size_t l = 0; l < this->log_n; ++l) {
202 const auto& evaluation = opening_claims[l + 1].opening_pair.evaluation;
203 prover_evaluations.emplace_back(evaluation);
204 }
205
206 std::vector<Fr> r_squares = gemini::powers_of_evaluation_challenge(gemini_eval_challenge, this->log_n);
207
208 GroupElement expected_result = GroupElement::zero();
209 std::vector<Fr> expected_inverse_vanishing_evals;
210 expected_inverse_vanishing_evals.reserve(2 * this->log_n);
211 // Compute expected inverses
212 for (size_t idx = 0; idx < this->log_n; idx++) {
213 expected_inverse_vanishing_evals.emplace_back((shplonk_eval_challenge - r_squares[idx]).invert());
214 expected_inverse_vanishing_evals.emplace_back((shplonk_eval_challenge + r_squares[idx]).invert());
215 }
216
217 Fr current_challenge{ shplonk_batching_challenge * shplonk_batching_challenge };
218 for (size_t idx = 0; idx < prover_commitments.size(); ++idx) {
219 expected_result -= prover_commitments[idx] * current_challenge * expected_inverse_vanishing_evals[2 * idx + 2];
220 current_challenge *= shplonk_batching_challenge;
221 expected_result -= prover_commitments[idx] * current_challenge * expected_inverse_vanishing_evals[2 * idx + 3];
222 current_challenge *= shplonk_batching_challenge;
223 }
224
225 // Run the ShepliminiVerifier batching method
226 std::vector<Fr> inverse_vanishing_evals =
227 ShplonkVerifier::compute_inverted_gemini_denominators(shplonk_eval_challenge, r_squares);
228
229 Fr expected_constant_term_accumulator{ 0 };
230 std::vector<Fr> padding_indicator_array(this->log_n, Fr{ 1 });
231
232 std::vector<Fr> gemini_fold_pos_evaluations =
234 expected_constant_term_accumulator,
235 mle_opening_point,
236 r_squares,
237 prover_evaluations,
238 expected_constant_term_accumulator);
239 std::vector<Commitment> commitments;
240 std::vector<Fr> scalars;
241
242 ShpleminiVerifier::batch_gemini_claims_received_from_prover(padding_indicator_array,
243 prover_commitments,
244 prover_evaluations,
245 gemini_fold_pos_evaluations,
246 inverse_vanishing_evals,
247 shplonk_batching_challenge_powers,
248 commitments,
249 scalars,
250 expected_constant_term_accumulator);
251
252 // Compute the group element using the output of Shplemini method
253 GroupElement shplemini_result = batch_mul_native<Curve>(commitments, scalars);
254
255 EXPECT_EQ(shplemini_result, expected_result);
256}
257
263TYPED_TEST(ShpleminiTest, ShpleminiZKNoSumcheckOpenings)
264{
265 using ZKData = ZKSumcheckData<TypeParam>;
266 using Curve = TypeParam::Curve;
267 using ShpleminiProver = ShpleminiProver_<Curve>;
268 using ShpleminiVerifier = ShpleminiVerifier_<Curve>;
269 using Fr = typename Curve::ScalarField;
270 using Commitment = typename Curve::AffineElement;
271 using CK = typename TypeParam::CommitmentKey;
272
273 // Initialize transcript and commitment key
274 auto prover_transcript = TypeParam::Transcript::prover_init_empty();
275
276 // SmallSubgroupIPAProver requires at least CURVE::SUBGROUP_SIZE + 3 elements in the ck.
277 static constexpr size_t log_subgroup_size = static_cast<size_t>(numeric::get_msb(Curve::SUBGROUP_SIZE));
278 CK ck = create_commitment_key<CK>(std::max<size_t>(this->n, 1ULL << (log_subgroup_size + 1)));
279
280 // Generate Libra polynomials, compute masked concatenated Libra polynomial, commit to it
281 ZKData zk_sumcheck_data(this->log_n, prover_transcript, ck);
282
283 // Generate multivariate challenge
284 std::vector<Fr> mle_opening_point = this->random_evaluation_point(this->log_n);
285
286 // Generate random prover polynomials, compute their evaluations and commitments
287 MockClaimGenerator<Curve> mock_claims(this->n,
288 /*num_polynomials*/ this->num_polynomials,
289 /*num_to_be_shifted*/ this->num_shiftable,
290 mle_opening_point,
291 ck);
292
293 // Compute the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges
295 zk_sumcheck_data, mle_opening_point, this->log_n);
296
297 prover_transcript->send_to_verifier("Libra:claimed_evaluation", claimed_inner_product);
298
299 // Instantiate SmallSubgroupIPAProver, this prover sends commitments to Big Sum and Quotient polynomials
300 SmallSubgroupIPAProver<TypeParam> small_subgroup_ipa_prover(
301 zk_sumcheck_data, mle_opening_point, claimed_inner_product, prover_transcript, ck);
302 small_subgroup_ipa_prover.prove();
303
304 // Reduce to KZG or IPA based on the curve used in the test Flavor
305 const auto opening_claim = ShpleminiProver::prove(this->n,
306 mock_claims.polynomial_batcher,
307 mle_opening_point,
308 ck,
309 prover_transcript,
310 small_subgroup_ipa_prover.get_witness_polynomials());
311
313 TestFixture::IPA::compute_opening_proof(this->ck(), opening_claim, prover_transcript);
314 } else {
315 KZG<Curve>::compute_opening_proof(this->ck(), opening_claim, prover_transcript);
316 }
317
318 // Initialize verifier's transcript
319 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
320
321 // Start populating Verifier's array of Libra commitments
323 libra_commitments[0] =
324 verifier_transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");
325
326 // Place Libra data to the transcript
327 const Fr libra_total_sum = verifier_transcript->template receive_from_prover<Fr>("Libra:Sum");
328 const Fr libra_challenge = verifier_transcript->template get_challenge<Fr>("Libra:Challenge");
329 const Fr libra_evaluation = verifier_transcript->template receive_from_prover<Fr>("Libra:claimed_evaluation");
330
331 // Check that transcript is consistent
332 EXPECT_EQ(libra_total_sum, zk_sumcheck_data.libra_total_sum);
333 EXPECT_EQ(libra_challenge, zk_sumcheck_data.libra_challenge);
334 EXPECT_EQ(libra_evaluation, claimed_inner_product);
335
336 // Finalize the array of Libra/SmallSubgroupIpa commitments
337 libra_commitments[1] = verifier_transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
338 libra_commitments[2] = verifier_transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
339
340 // Used to verify the consistency of the evaluations of the concatenated libra polynomial, big sum polynomial, and
341 // the quotient polynomial computed by SmallSubgroupIPAProver
342 bool consistency_checked = true;
343
344 // Run Shplemini
345 std::vector<Fr> padding_indicator_array(this->log_n, Fr{ 1 });
346
347 auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array,
348 mock_claims.claim_batcher,
349 mle_opening_point,
350 this->vk().get_g1_identity(),
351 verifier_transcript,
352 {},
353 true,
354 &consistency_checked,
355 libra_commitments,
356 libra_evaluation);
357 // Verify claim using KZG or IPA
359 auto result =
360 TestFixture::IPA::reduce_verify_batch_opening_claim(batch_opening_claim, this->vk(), verifier_transcript);
361 EXPECT_EQ(result, true);
362 } else {
363 const auto pairing_points =
364 KZG<Curve>::reduce_verify_batch_opening_claim(std::move(batch_opening_claim), verifier_transcript);
365 // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2)
366 EXPECT_EQ(this->vk().pairing_check(pairing_points[0], pairing_points[1]), true);
367 }
368}
369
376TYPED_TEST(ShpleminiTest, ShpleminiZKWithSumcheckOpenings)
377{
378 using Curve = TypeParam::Curve;
379 using Fr = typename Curve::ScalarField;
380 using Commitment = typename Curve::AffineElement;
381 using CK = typename TypeParam::CommitmentKey;
382
383 using ShpleminiProver = ShpleminiProver_<Curve>;
384 using ShpleminiVerifier = ShpleminiVerifier_<Curve>;
385
386 CK ck = create_commitment_key<CK>(4096);
387
388 // Generate Sumcheck challenge
389 std::vector<Fr> challenge = this->random_evaluation_point(this->log_n);
390
391 auto prover_transcript = TypeParam::Transcript::prover_init_empty();
392
393 // Generate masking polynomials for Sumcheck Round Univariates
394 ZKSumcheckData<TypeParam> zk_sumcheck_data(this->log_n, prover_transcript, ck);
395 // Generate mock witness
396 MockClaimGenerator<Curve> mock_claims(this->n, 1);
397
398 // Generate valid sumcheck polynomials of given length
399 mock_claims.template compute_sumcheck_opening_data<TypeParam>(
400 this->log_n, this->sumcheck_univariate_length, challenge, ck);
401
402 // Compute the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges
403 const Fr claimed_inner_product =
404 SmallSubgroupIPAProver<TypeParam>::compute_claimed_inner_product(zk_sumcheck_data, challenge, this->log_n);
405
406 prover_transcript->send_to_verifier("Libra:claimed_evaluation", claimed_inner_product);
407
408 // Instantiate SmallSubgroupIPAProver, this prover sends commitments to Big Sum and Quotient polynomials
409 SmallSubgroupIPAProver<TypeParam> small_subgroup_ipa_prover(
410 zk_sumcheck_data, challenge, claimed_inner_product, prover_transcript, ck);
411 small_subgroup_ipa_prover.prove();
412
413 // Reduce proving to a single claimed fed to KZG or IPA
414 const auto opening_claim = ShpleminiProver::prove(this->n,
415 mock_claims.polynomial_batcher,
416 challenge,
417 ck,
418 prover_transcript,
419 small_subgroup_ipa_prover.get_witness_polynomials(),
420 mock_claims.round_univariates,
421 mock_claims.sumcheck_evaluations);
422
424 TestFixture::IPA::compute_opening_proof(this->ck(), opening_claim, prover_transcript);
425 } else {
426 KZG<Curve>::compute_opening_proof(this->ck(), opening_claim, prover_transcript);
427 }
428
429 // Initialize verifier's transcript
430 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
431
433 libra_commitments[0] =
434 verifier_transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");
435
436 // Place Libra data to the transcript
437 const Fr libra_total_sum = verifier_transcript->template receive_from_prover<Fr>("Libra:Sum");
438 const Fr libra_challenge = verifier_transcript->template get_challenge<Fr>("Libra:Challenge");
439 const Fr libra_evaluation = verifier_transcript->template receive_from_prover<Fr>("Libra:claimed_evaluation");
440
441 // Check that transcript is consistent
442 EXPECT_EQ(libra_total_sum, zk_sumcheck_data.libra_total_sum);
443 EXPECT_EQ(libra_challenge, zk_sumcheck_data.libra_challenge);
444 EXPECT_EQ(libra_evaluation, claimed_inner_product);
445
446 // Finalize the array of Libra/SmallSubgroupIpa commitments
447 libra_commitments[1] = verifier_transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
448 libra_commitments[2] = verifier_transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
449
450 bool consistency_checked = true;
451
452 // Run Shplemini
453 std::vector<Fr> padding_indicator_array(this->log_n, Fr{ 1 });
454
455 auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(padding_indicator_array,
456 mock_claims.claim_batcher,
457 challenge,
458 this->vk().get_g1_identity(),
459 verifier_transcript,
460 {},
461 true,
462 &consistency_checked,
463 libra_commitments,
464 libra_evaluation,
465 mock_claims.sumcheck_commitments,
466 mock_claims.sumcheck_evaluations);
467 // Verify claim using KZG or IPA
469 auto result =
470 TestFixture::IPA::reduce_verify_batch_opening_claim(batch_opening_claim, this->vk(), verifier_transcript);
471 EXPECT_EQ(result, true);
472 } else {
473 const auto pairing_points =
474 KZG<Curve>::reduce_verify_batch_opening_claim(std::move(batch_opening_claim), verifier_transcript);
475 // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2)
476 EXPECT_EQ(this->vk().pairing_check(pairing_points[0], pairing_points[1]), true);
477 }
478}
479
486TYPED_TEST(ShpleminiTest, HighDegreeAttackAccept)
487{
488 using Curve = typename TypeParam::Curve;
489 using Fr = typename Curve::ScalarField;
490 using CK = typename TypeParam::CommitmentKey;
491 using ShpleminiProver = ShpleminiProver_<Curve>;
492 using ShpleminiVerifier = ShpleminiVerifier_<Curve>;
494
495 // Use the fixture's n (1 << 9 = 512) as the polynomial size
496 // small_log_n = 3 means we fold to a constant after 3 rounds
497 static constexpr size_t small_log_n = 3;
498 CK ck = create_commitment_key<CK>(this->n);
499
500 // Sample public opening point (u_0, u_1, u_2)
501 auto u = this->random_evaluation_point(small_log_n);
502
503 // Choose a claimed eval at `u`
504 Fr claimed_multilinear_eval = Fr::random_element();
505
506 // poly is of high degrees (up to n), as the SRS allows for it
507 Polynomial poly(this->n);
508
509 // Define poly to be of a specific form such that after small_log_n folds with u, it becomes a constant equal to
510 // claimed_multilinear_eval. The non-zero coefficients are at indices that fold correctly.
511 // For n = 512, small_log_n = 3: indices 4, 504, 508 work (instead of 4, 4088, 4092 for n = 4096)
512 const Fr tail = ((Fr(1) - u[0]) * (Fr(1) - u[1])).invert();
513 poly.at(4) = claimed_multilinear_eval * tail / u[2];
514 poly.at(this->n - 8) = tail; // 504 for n=512
515 poly.at(this->n - 4) = -tail * (Fr(1) - u[2]) / u[2]; // 508 for n=512
516
517 MockClaimGenerator<Curve> mock_claims(
518 this->n, std::vector{ std::move(poly) }, std::vector<Fr>{ claimed_multilinear_eval }, ck);
519
520 auto prover_transcript = NativeTranscript::prover_init_empty();
521
522 // Run Shplemini prover
523 const auto opening_claim =
524 ShpleminiProver::prove(this->n, mock_claims.polynomial_batcher, u, ck, prover_transcript);
525
526 // Run KZG/IPA prover
528 TestFixture::IPA::compute_opening_proof(ck, opening_claim, prover_transcript);
529 } else {
530 KZG<Curve>::compute_opening_proof(ck, opening_claim, prover_transcript);
531 }
532
533 // Verifier side
534 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
535
536 std::vector<Fr> padding_indicator_array(small_log_n, Fr{ 1 });
537
538 auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(
539 padding_indicator_array, mock_claims.claim_batcher, u, this->vk().get_g1_identity(), verifier_transcript);
540
541 // Verify claim - should succeed because the polynomial was crafted to fold correctly
543 auto result =
544 TestFixture::IPA::reduce_verify_batch_opening_claim(batch_opening_claim, this->vk(), verifier_transcript);
545 EXPECT_EQ(result, true);
546 } else {
547 const auto pairing_points =
548 KZG<Curve>::reduce_verify_batch_opening_claim(std::move(batch_opening_claim), verifier_transcript);
549 EXPECT_EQ(this->vk().pairing_check(pairing_points[0], pairing_points[1]), true);
550 }
551}
552
558TYPED_TEST(ShpleminiTest, HighDegreeAttackReject)
559{
560 using Curve = typename TypeParam::Curve;
561 using Fr = typename Curve::ScalarField;
562 using CK = typename TypeParam::CommitmentKey;
563 using ShpleminiProver = ShpleminiProver_<Curve>;
564 using ShpleminiVerifier = ShpleminiVerifier_<Curve>;
566
567 // Use a larger SRS size to allow committing to high degree polynomials
568 static constexpr size_t big_n = 1UL << 12;
569 static constexpr size_t small_log_n = 3;
570 static constexpr size_t big_ck_size = 1 << 14;
571 CK ck = create_commitment_key<CK>(big_ck_size);
572
573 // Random high degree polynomial
574 Polynomial poly = Polynomial::random(big_n);
575
576 // Sample public opening point (u_0, u_1, u_2)
577 auto u = this->random_evaluation_point(small_log_n);
578
579 // Choose a random claimed eval at `u` (likely wrong)
580 Fr claimed_multilinear_eval = Fr::random_element();
581
582 MockClaimGenerator<Curve> mock_claims(
583 big_n, std::vector{ std::move(poly) }, std::vector<Fr>{ claimed_multilinear_eval }, ck);
584
585 auto prover_transcript = NativeTranscript::prover_init_empty();
586
587 // Run Shplemini prover
588 const auto opening_claim = ShpleminiProver::prove(big_n, mock_claims.polynomial_batcher, u, ck, prover_transcript);
589
590 // Run KZG/IPA prover
592 TestFixture::IPA::compute_opening_proof(ck, opening_claim, prover_transcript);
593 } else {
594 KZG<Curve>::compute_opening_proof(ck, opening_claim, prover_transcript);
595 }
596
597 // Verifier side
598 auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);
599
600 std::vector<Fr> padding_indicator_array(small_log_n, Fr{ 1 });
601
602 auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(
603 padding_indicator_array, mock_claims.claim_batcher, u, this->vk().get_g1_identity(), verifier_transcript);
604
605 // Verify claim - should fail because the random polynomial doesn't fold correctly
607 // IPA throws an exception on verification failure
608 EXPECT_THROW(
609 TestFixture::IPA::reduce_verify_batch_opening_claim(batch_opening_claim, this->vk(), verifier_transcript),
610 std::runtime_error);
611 } else {
612 const auto pairing_points =
613 KZG<Curve>::reduce_verify_batch_opening_claim(std::move(batch_opening_claim), verifier_transcript);
614 EXPECT_EQ(this->vk().pairing_check(pairing_points[0], pairing_points[1]), false);
615 }
616}
617
618} // namespace bb
static std::shared_ptr< BaseTranscript > prover_init_empty()
For testing: initializes transcript with some arbitrary data so that a challenge can be generated aft...
static std::shared_ptr< BaseTranscript > verifier_init_empty(const std::shared_ptr< BaseTranscript > &transcript)
For testing: initializes transcript based on proof data then receives junk data produced by BaseTrans...
bb::CommitmentKey< Curve > CommitmentKey
Polynomial compute_batched(const Fr &challenge)
Compute batched polynomial A₀ = F + G/X as the linear combination of all polynomials to be opened.
Definition gemini.hpp:173
std::pair< Polynomial, Polynomial > compute_partially_evaluated_batch_polynomials(const Fr &r_challenge)
Compute partially evaluated batched polynomials A₀(X, r) = A₀₊ = F + G/r, A₀(X, -r) = A₀₋ = F - G/r.
Definition gemini.hpp:229
Gemini Verifier utility methods used by ShpleminiVerifier.
Definition gemini.hpp:311
static PairingPointsType reduce_verify_batch_opening_claim(BatchOpeningClaim< Curve > &&batch_opening_claim, const std::shared_ptr< Transcript > &transcript, const size_t expected_final_msm_size=0)
Computes the input points for the pairing check needed to verify a KZG opening claim obtained from a ...
Definition kzg.hpp:131
static void compute_opening_proof(const CK &ck, const ProverOpeningClaim< Curve > &opening_claim, const std::shared_ptr< Transcript > &prover_trancript)
Computes the KZG commitment to an opening proof polynomial at a single evaluation point.
Definition kzg.hpp:43
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
static Polynomial random(size_t size, size_t start_index=0)
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
static constexpr size_t n
static constexpr size_t log_n
static constexpr size_t n
typename Flavor::Curve::ScalarField Fr
static constexpr size_t num_polynomials
typename Flavor::CommitmentKey CK
typename Flavor::Curve::AffineElement Commitment
static constexpr size_t log_n
static constexpr size_t sumcheck_univariate_length
static constexpr size_t num_shiftable
typename Flavor::Curve::Element GroupElement
IPA< typename Flavor::Curve, log_n > IPA
An efficient verifier for the evaluation proofs of multilinear polynomials and their shifts.
Shplonk Verifier.
Definition shplonk.hpp:343
A Curve-agnostic ZK protocol to prove inner products of small vectors.
std::array< bb::Polynomial< FF >, NUM_SMALL_IPA_EVALUATIONS > get_witness_polynomials() const
static FF compute_claimed_inner_product(ZKSumcheckData< Flavor > &zk_sumcheck_data, const std::vector< FF > &multivariate_challenge, const size_t &log_circuit_size)
For test purposes: Compute the sum of the Libra constant term and Libra univariates evaluated at Sumc...
void prove()
Compute the derived witnesses and and commit to them.
typename Group::element Element
Definition grumpkin.hpp:62
static constexpr size_t SUBGROUP_SIZE
Definition grumpkin.hpp:74
typename Group::affine_element AffineElement
Definition grumpkin.hpp:63
bool expected_result
std::vector< Fr > powers_of_evaluation_challenge(const Fr r, const size_t num_squares)
Compute squares of folding challenge r.
Definition gemini.hpp:94
std::vector< Fr > powers_of_rho(const Fr rho, const size_t num_powers)
Compute powers of challenge ρ
Definition gemini.hpp:77
constexpr T get_msb(const T in)
Definition get_msb.hpp:47
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
::testing::Types< BN254Settings, GrumpkinSettings > TestSettings
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
CommitmentKey< Curve > ck
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Curve::ScalarField Fr
void compute_scalars_for_each_batch(std::span< const Fr > inverted_vanishing_evals, const Fr &nu_challenge, const Fr &r_challenge)
Compute scalars used to batch each set of claims, excluding contribution from batching challenge \rho...
void update_batch_mul_inputs_and_batched_evaluation(std::vector< Commitment > &commitments, std::vector< Fr > &scalars, Fr &batched_evaluation, const Fr &rho, Fr shplonk_batching_pos={ 0 }, Fr shplonk_batching_neg={ 0 })
Append the commitments and scalars from each batch of claims to the Shplemini, vectors which subseque...
Constructs random polynomials, computes commitments and corresponding evaluations.
std::vector< bb::Polynomial< Fr > > round_univariates
std::vector< Commitment > sumcheck_commitments
std::vector< std::array< Fr, 3 > > sumcheck_evaluations
This structure is created to contain various polynomials and constants required by ZK Sumcheck.
constexpr field invert() const noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept