@@ -22,6 +22,16 @@ template <class Curve> class GeminiTest : public CommitmentTest<Curve> {
2222 using CK = CommitmentKey<Curve>;
2323 using VK = VerifierCommitmentKey<Curve>;
2424
25+ // is_big_ck is set to true in the high degree attack test. It uses a larger SRS size (big_ck_size=2^14) and allows
26+ // the prover
27+ // to commit to high degree polynomials (big_n=2^12).
28+ bool is_big_ck = false ;
29+ static constexpr size_t big_n = 1UL << 12 ;
30+ static constexpr size_t small_log_n = 3 ;
31+ static constexpr size_t big_ck_size = 1 << 14 ;
32+ inline static CK big_ck = create_commitment_key<CK>(big_ck_size);
33+ bool is_reject_case = false ;
34+
2535 static CK ck;
2636 static VK vk;
2737
@@ -34,21 +44,25 @@ template <class Curve> class GeminiTest : public CommitmentTest<Curve> {
3444 void execute_gemini_and_verify_claims (std::vector<Fr>& multilinear_evaluation_point,
3545 MockClaimGenerator<Curve> mock_claims)
3646 {
47+ const size_t poly_size = is_big_ck ? big_n : n;
48+ const CK& comkey = is_big_ck ? big_ck : ck;
49+ const size_t multilinear_challenge_size = is_big_ck ? small_log_n : log_n;
50+
3751 auto prover_transcript = NativeTranscript::prover_init_empty ();
3852
3953 // Compute:
4054 // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
4155 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
4256 auto prover_output = GeminiProver::prove (
43- this -> n , mock_claims.polynomial_batcher , multilinear_evaluation_point, ck , prover_transcript);
57+ poly_size , mock_claims.polynomial_batcher , multilinear_evaluation_point, comkey , prover_transcript);
4458
4559 // The prover output needs to be completed by adding the "positive" Fold claims, i.e. evaluations of Fold^(i) at
4660 // r^{2^i} for i=1, ..., d-1. Although here we are copying polynomials, it is not the case when GeminiProver is
4761 // combined with ShplonkProver.
4862 std::vector<ProverOpeningClaim<Curve>> prover_claims_with_pos_evals;
4963 // `prover_output` consists of d+1 opening claims, we add another d-1 claims for each positive evaluation
5064 // Fold^i(r^{2^i}) for i = 1, ..., d-1
51- const size_t total_num_claims = 2 * log_n ;
65+ const size_t total_num_claims = 2 * multilinear_challenge_size ;
5266 prover_claims_with_pos_evals.reserve (total_num_claims);
5367
5468 for (auto & claim : prover_output) {
@@ -81,9 +95,20 @@ template <class Curve> class GeminiTest : public CommitmentTest<Curve> {
8195 multilinear_evaluation_point, mock_claims.claim_batcher , verifier_transcript);
8296
8397 // Check equality of the opening pairs computed by prover and verifier
84- for (auto [prover_claim, verifier_claim] : zip_view (prover_claims_with_pos_evals, verifier_claims)) {
85- this ->verify_opening_claim (verifier_claim, prover_claim.polynomial , ck);
86- ASSERT_EQ (prover_claim.opening_pair , verifier_claim.opening_pair );
98+ if (this ->is_reject_case ) {
99+ bool mismatch = false ;
100+ for (auto [prover_claim, verifier_claim] : zip_view (prover_claims_with_pos_evals, verifier_claims)) {
101+ if (prover_claim.opening_pair != verifier_claim.opening_pair ) {
102+ mismatch = true ;
103+ break ;
104+ }
105+ }
106+ EXPECT_TRUE (mismatch) << " Expected a mismatch in opening pairs, but all matched." ;
107+ } else {
108+ for (auto [prover_claim, verifier_claim] : zip_view (prover_claims_with_pos_evals, verifier_claims)) {
109+ this ->verify_opening_claim (verifier_claim, prover_claim.polynomial , comkey);
110+ ASSERT_EQ (prover_claim.opening_pair , verifier_claim.opening_pair );
111+ }
87112 }
88113 }
89114
@@ -335,5 +360,62 @@ TYPED_TEST(GeminiTest, SoundnessRegression)
335360 }
336361}
337362
363+ // The prover commits to a higher degree polynomial than what is expected. The test considers the case where
364+ // this polynomial folds down to a constant (equal to the claimed evaluation) after the expected number of rounds
365+ // (due to the choice of the evaluation point). In this case, the verifier accepts.
366+ TYPED_TEST (GeminiTest, HighDegreeAttackAccept)
367+ {
368+ using Fr = typename TypeParam::ScalarField;
369+
370+ this ->is_big_ck = true ;
371+
372+ // Sample public opening point (u_0, u_1, u_2)
373+ auto u = this ->random_evaluation_point (this ->small_log_n );
374+
375+ // Choose a claimed eval at `u`
376+ Fr claimed_multilinear_eval = Fr::random_element ();
377+
378+ // poly is of high degrees, as the SRS allows for it
379+ Polynomial<Fr> poly (this ->big_n );
380+
381+ // Define poly to be of a specific form such that after small_log_n folds with u, it becomes a constant equal to
382+ // claimed_multilinear_eval.
383+ const Fr tail = ((Fr (1 ) - u[0 ]) * (Fr (1 ) - u[1 ])).invert ();
384+ poly.at (4 ) = claimed_multilinear_eval * tail / u[2 ];
385+ poly.at (4088 ) = tail;
386+ poly.at (4092 ) = -tail * (Fr (1 ) - u[2 ]) / u[2 ];
387+
388+ MockClaimGenerator<TypeParam> mock_claims (
389+ this ->big_n , std::vector{ std::move (poly) }, std::vector<Fr>{ claimed_multilinear_eval }, this ->big_ck );
390+
391+ this ->execute_gemini_and_verify_claims (u, mock_claims);
392+ }
393+
394+ // The prover commits to a higher degree polynomial than what is expected. The test considers the case where
395+ // this polynomial does not fold down to a constant after the expected number of rounds. In this case, the verifier
396+ // rejects with high probabililty.
397+ TYPED_TEST (GeminiTest, HighDegreeAttackReject)
398+ {
399+ using Fr = typename TypeParam::ScalarField;
400+ using Polynomial = bb::Polynomial<Fr>;
401+
402+ this ->is_big_ck = true ;
403+ this ->is_reject_case = true ;
404+
405+ // poly of high degree, as SRS allows for it
406+ Polynomial poly = Polynomial::random (this ->big_n );
407+
408+ // Sample public opening point (u_0, u_1, u_2)
409+ auto u = this ->random_evaluation_point (this ->small_log_n );
410+
411+ // Choose a claimed eval at `u`
412+ Fr claimed_multilinear_eval = Fr::random_element ();
413+
414+ MockClaimGenerator<TypeParam> mock_claims (
415+ this ->big_n , std::vector{ std::move (poly) }, std::vector<Fr>{ claimed_multilinear_eval }, this ->big_ck );
416+
417+ this ->execute_gemini_and_verify_claims (u, mock_claims);
418+ }
419+
338420template <class Curve > typename GeminiTest<Curve>::CK GeminiTest<Curve>::ck;
339421template <class Curve > typename GeminiTest<Curve>::VK GeminiTest<Curve>::vk;
0 commit comments