From bacf36e447de897d962a4a699fff801f65211800 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 8 Jan 2025 14:33:38 +0000 Subject: [PATCH 1/4] added unit and integration tests --- .../commitment_schemes/pcs_test_flavors.hpp | 25 ++ .../pcs_test_instance_witness_generator.hpp | 64 ++++ .../shplonk/shplemini.test.cpp | 282 ++++++++++++------ .../small_subgroup_ipa/small_subgroup_ipa.hpp | 15 +- .../small_subgroup_ipa.test.cpp | 251 ++++++++++++++++ 5 files changed, 547 insertions(+), 90 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp create mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp create mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp new file mode 100644 index 00000000000..29f6363696c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/transcript/transcript.hpp" +#include "commitment_key.test.hpp" + +namespace bb { +class TestBn254Flavor { + public: + using Curve = curve::BN254; + using CommitmentKey = CommitmentKey; + using Transcript = NativeTranscript; + using FF = typename Curve::ScalarField; + static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; +}; + +class TestGrumpkinFlavor { + public: + using Curve = curve::Grumpkin; + using CommitmentKey = CommitmentKey; + using Transcript = NativeTranscript; + using FF = typename Curve::ScalarField; + static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp new file mode 100644 index 00000000000..91b7084bf64 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/transcript/transcript.hpp" +#include "commitment_key.test.hpp" + +namespace bb { + +template struct PCSInstanceWitnessGenerator { + public: + using CommitmentKey = CommitmentKey; + using Fr = typename Curve::ScalarField; + using Commitment = typename Curve::AffineElement; + using Polynomial = bb::Polynomial; + + std::shared_ptr ck; + std::vector polynomials; + std::vector shiftable_polynomials; + std::vector const_size_mle_opening_point; + std::vector unshifted_commitments; + std::vector shifted_commitments; + std::vector unshifted_evals; + std::vector shifted_evals; + + PCSInstanceWitnessGenerator(const size_t n, + const size_t num_polynomials, + const size_t num_shiftable, + const std::vector& mle_opening_point, + std::shared_ptr& commitment_key) + : ck(commitment_key) // Initialize the commitment key + , polynomials(num_polynomials) + , shiftable_polynomials(num_shiftable) + + { + construct_instance_and_witnesses(n, mle_opening_point); + } + + void construct_instance_and_witnesses(size_t n, const std::vector& mle_opening_point) + { + + const size_t num_unshifted = polynomials.size() - shiftable_polynomials.size(); + + for (size_t idx = 0; idx < num_unshifted; idx++) { + polynomials[idx] = Polynomial::random(n); + unshifted_commitments.push_back(ck->commit(polynomials[idx])); + unshifted_evals.push_back(polynomials[idx].evaluate_mle(mle_opening_point)); + } + + size_t idx = num_unshifted; + for (auto& poly : shiftable_polynomials) { + poly = Polynomial::random(n, /*shiftable*/ 1); + polynomials[idx] = poly; + auto comm = this->ck->commit(poly); + unshifted_commitments.push_back(comm); + shifted_commitments.push_back(comm); + unshifted_evals.push_back(poly.evaluate_mle(mle_opening_point)); + shifted_evals.push_back(poly.evaluate_mle(mle_opening_point, true)); + idx++; + } + } +}; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp index bfb9fd93169..f9d7992e1df 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -7,6 +7,8 @@ #include "../utils/batch_mul_native.hpp" #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/ipa/ipa.hpp" +#include "barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp" +#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp" #include "barretenberg/ecc/curves/bn254/g1.hpp" #include @@ -14,29 +16,29 @@ namespace bb { -template class ShpleminiTest : public CommitmentTest { +template class ShpleminiTest : public CommitmentTest { public: - using Fr = typename Curve::ScalarField; - using Commitment = typename Curve::AffineElement; - using GroupElement = typename Curve::Element; - using Polynomial = bb::Polynomial; + static constexpr size_t n = 32; + static constexpr size_t log_n = 5; + static constexpr size_t num_polynomials = 5; + static constexpr size_t num_shiftable = 2; }; -using CurveTypes = ::testing::Types; +using FlavorTypes = ::testing::Types; -TYPED_TEST_SUITE(ShpleminiTest, CurveTypes); +TYPED_TEST_SUITE(ShpleminiTest, FlavorTypes); // This test checks that batch_multivariate_opening_claims method operates correctly TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) { - using ShpleminiVerifier = ShpleminiVerifier_; - using Fr = typename TypeParam::ScalarField; - using GroupElement = typename TypeParam::Element; - using Commitment = typename TypeParam::AffineElement; - using Polynomial = typename bb::Polynomial; + using Curve = typename TypeParam::Curve; + using ShpleminiVerifier = ShpleminiVerifier_; + using Fr = typename Curve::ScalarField; + using GroupElement = typename Curve::Element; + using Commitment = typename Curve::AffineElement; - const size_t n = 16; - const size_t log_n = 4; + std::shared_ptr ck; + ck = CreateCommitmentKey(); // Generate mock challenges Fr rho = Fr::random_element(); @@ -45,37 +47,40 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) Fr shplonk_eval_challenge = Fr::random_element(); // Generate multilinear polynomials and compute their commitments - auto mle_opening_point = this->random_evaluation_point(log_n); - auto poly1 = Polynomial::random(n); - auto poly2 = Polynomial::random(n, /*shiftable*/ 1); - Polynomial poly3(n); - - Commitment commitment1 = this->commit(poly1); - Commitment commitment2 = this->commit(poly2); - Commitment commitment3 = this->commit(poly3); - EXPECT_TRUE(commitment3.is_point_at_infinity()); - - std::vector unshifted_commitments = { commitment1, commitment2, commitment3 }; - std::vector shifted_commitments = { commitment2, commitment3 }; - - // Evaluate the polynomials at the multivariate challenge, poly3 is not evaluated, because it is 0. - auto eval1 = poly1.evaluate_mle(mle_opening_point); - auto eval2 = poly2.evaluate_mle(mle_opening_point); - Fr eval3{ 0 }; - Fr eval3_shift{ 0 }; - auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); + auto mle_opening_point = this->random_evaluation_point(this->log_n); + + auto pcs_instance_witness = + PCSInstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); // Collect multilinear evaluations - std::vector multilinear_evaluations = { eval1, eval2, eval3, eval2_shift, eval3_shift }; - std::vector rhos = gemini::powers_of_rho(rho, multilinear_evaluations.size()); + std::vector rhos = gemini::powers_of_rho(rho, this->num_polynomials + this->num_shiftable); // Compute batched multivariate evaluation - Fr batched_evaluation = - std::inner_product(multilinear_evaluations.begin(), multilinear_evaluations.end(), rhos.begin(), Fr::zero()); + Fr batched_evaluation = Fr(0); + size_t idx = 0; + for (auto& eval : pcs_instance_witness.unshifted_evals) { + batched_evaluation += eval * rhos[idx]; + idx++; + } + + for (auto& eval : pcs_instance_witness.shifted_evals) { + batched_evaluation += eval * rhos[idx]; + idx++; + } // Compute batched commitments manually - GroupElement batched_commitment_unshifted = commitment1 * rhos[0] + commitment2 * rhos[1] + commitment3 * rhos[2]; - GroupElement batched_commitment_to_be_shifted = commitment2 * rhos[3] + commitment3 * rhos[4]; + idx = 0; + GroupElement batched_commitment_unshifted = GroupElement::zero(); + for (auto& comm : pcs_instance_witness.unshifted_commitments) { + batched_commitment_unshifted += comm * rhos[idx]; + idx++; + } + + GroupElement batched_commitment_to_be_shifted = GroupElement::zero(); + for (auto& comm : pcs_instance_witness.shifted_commitments) { + batched_commitment_to_be_shifted += comm * rhos[idx]; + idx++; + } // Compute expected result manually GroupElement commitment_to_univariate = @@ -100,10 +105,10 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) ((shplonk_eval_challenge - gemini_eval_challenge).invert() - shplonk_batching_challenge * (shplonk_eval_challenge + gemini_eval_challenge).invert()); - ShpleminiVerifier::batch_multivariate_opening_claims(RefVector(unshifted_commitments), - RefVector(shifted_commitments), - RefArray{ eval1, eval2, eval3 }, - RefArray{ eval2_shift, eval3_shift }, + ShpleminiVerifier::batch_multivariate_opening_claims(RefVector(pcs_instance_witness.unshifted_commitments), + RefVector(pcs_instance_witness.shifted_commitments), + RefVector(pcs_instance_witness.unshifted_evals), + RefVector(pcs_instance_witness.shifted_evals), rho, unshifted_scalar, shifted_scalar, @@ -114,22 +119,24 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) // Final pairing check GroupElement shplemini_result = batch_mul_native(commitments, scalars); - EXPECT_EQ(commitments.size(), unshifted_commitments.size() + shifted_commitments.size()); + EXPECT_EQ(commitments.size(), + pcs_instance_witness.unshifted_commitments.size() + pcs_instance_witness.shifted_commitments.size()); EXPECT_EQ(batched_evaluation, verifier_batched_evaluation); EXPECT_EQ(-expected_result, shplemini_result); } TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) { - using GeminiProver = GeminiProver_; - using ShpleminiVerifier = ShpleminiVerifier_; - using ShplonkVerifier = ShplonkVerifier_; - using Fr = typename TypeParam::ScalarField; - using GroupElement = typename TypeParam::Element; - using Commitment = typename TypeParam::AffineElement; + using Curve = TypeParam::Curve; + using GeminiProver = GeminiProver_; + using ShpleminiVerifier = ShpleminiVerifier_; + using ShplonkVerifier = ShplonkVerifier_; + using Fr = typename Curve::ScalarField; + using GroupElement = typename Curve::Element; + using Commitment = typename Curve::AffineElement; using Polynomial = typename bb::Polynomial; - const size_t n = 16; - const size_t log_n = 4; + std::shared_ptr ck; + ck = CreateCommitmentKey(); // Generate mock challenges Fr rho = Fr::random_element(); @@ -137,62 +144,58 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) Fr shplonk_batching_challenge = Fr::random_element(); Fr shplonk_eval_challenge = Fr::random_element(); - // Generate multilinear polynomials and compute their commitments - auto mle_opening_point = this->random_evaluation_point(log_n); - auto poly1 = Polynomial::random(n); - auto poly2 = Polynomial::random(n, /*shiftable*/ 1); - Polynomial poly3 = Polynomial::shiftable(n); - - // Evaluate the polynomials at the multivariate challenge, poly3 is not evaluated, because it is 0. - auto eval1 = poly1.evaluate_mle(mle_opening_point); - auto eval2 = poly2.evaluate_mle(mle_opening_point); - Fr eval3{ 0 }; - Fr eval3_shift{ 0 }; - auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); + std::vector mle_opening_point = this->random_evaluation_point(this->log_n); + + auto pcs_instance_witness = + PCSInstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); // Collect multilinear evaluations - std::vector multilinear_evaluations = { eval1, eval2, eval3, eval2_shift, eval3_shift }; - std::vector rhos = gemini::powers_of_rho(rho, multilinear_evaluations.size()); + std::vector rhos = gemini::powers_of_rho(rho, this->num_polynomials + this->num_shiftable); + + Polynomial batched_unshifted(this->n); + Polynomial batched_to_be_shifted = Polynomial::shiftable(this->n); - Polynomial batched_unshifted(n); - Polynomial batched_to_be_shifted = Polynomial::shiftable(n); - batched_unshifted.add_scaled(poly1, rhos[0]); - batched_unshifted.add_scaled(poly2, rhos[1]); - batched_unshifted.add_scaled(poly3, rhos[2]); - batched_to_be_shifted.add_scaled(poly2, rhos[3]); - batched_to_be_shifted.add_scaled(poly3, rhos[4]); + size_t idx = 0; + for (auto& poly : pcs_instance_witness.polynomials) { + batched_unshifted.add_scaled(poly, rhos[idx]); + idx++; + } + + for (auto& poly : pcs_instance_witness.shiftable_polynomials) { + batched_unshifted.add_scaled(poly, rhos[idx]); + idx++; + } // Compute: // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1 auto fold_polynomials = GeminiProver::compute_fold_polynomials( - log_n, mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); + this->log_n, mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); std::vector prover_commitments; - for (size_t l = 0; l < log_n - 1; ++l) { - auto commitment = this->ck()->commit(fold_polynomials[l + 2]); + for (size_t l = 0; l < this->log_n - 1; ++l) { + auto commitment = ck->commit(fold_polynomials[l + 2]); prover_commitments.emplace_back(commitment); } - const auto opening_claims = - GeminiProver::compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), gemini_eval_challenge); + const auto opening_claims = GeminiProver::compute_fold_polynomial_evaluations( + this->log_n, std::move(fold_polynomials), gemini_eval_challenge); std::vector prover_evaluations; - for (size_t l = 0; l < log_n; ++l) { + for (size_t l = 0; l < this->log_n; ++l) { const auto& evaluation = opening_claims[l + 1].opening_pair.evaluation; prover_evaluations.emplace_back(evaluation); } - std::vector r_squares = gemini::powers_of_evaluation_challenge(gemini_eval_challenge, log_n); + std::vector r_squares = gemini::powers_of_evaluation_challenge(gemini_eval_challenge, this->log_n); GroupElement expected_result = GroupElement::zero(); - std::vector expected_inverse_vanishing_evals(log_n + 1); + std::vector expected_inverse_vanishing_evals(this->log_n + 1); // Compute expected inverses expected_inverse_vanishing_evals[0] = (shplonk_eval_challenge - r_squares[0]).invert(); - expected_inverse_vanishing_evals[1] = (shplonk_eval_challenge + r_squares[0]).invert(); - expected_inverse_vanishing_evals[2] = (shplonk_eval_challenge + r_squares[1]).invert(); - expected_inverse_vanishing_evals[3] = (shplonk_eval_challenge + r_squares[2]).invert(); - expected_inverse_vanishing_evals[4] = (shplonk_eval_challenge + r_squares[3]).invert(); + for (size_t idx = 1; idx < this->log_n + 1; idx++) { + expected_inverse_vanishing_evals[idx] = (shplonk_eval_challenge + r_squares[idx - 1]).invert(); + } Fr current_challenge{ shplonk_batching_challenge * shplonk_batching_challenge }; for (size_t idx = 0; idx < prover_commitments.size(); ++idx) { @@ -202,13 +205,13 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) // Run the ShepliminiVerifier batching method std::vector inverse_vanishing_evals = - ShplonkVerifier::compute_inverted_gemini_denominators(log_n + 1, shplonk_eval_challenge, r_squares); + ShplonkVerifier::compute_inverted_gemini_denominators(this->log_n + 1, shplonk_eval_challenge, r_squares); std::vector commitments; std::vector scalars; Fr expected_constant_term_accumulator{ 0 }; - ShpleminiVerifier::batch_gemini_claims_received_from_prover(log_n, + ShpleminiVerifier::batch_gemini_claims_received_from_prover(this->log_n, prover_commitments, prover_evaluations, inverse_vanishing_evals, @@ -223,4 +226,107 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) EXPECT_EQ(shplemini_result, expected_result); } -} // namespace bb +TYPED_TEST(ShpleminiTest, ShpleminiWithZK) +{ + using ZKData = ZKSumcheckData; + using Curve = TypeParam::Curve; + using ShpleminiProver = ShpleminiProver_; + using ShpleminiVerifier = ShpleminiVerifier_; + using Fr = typename Curve::ScalarField; + // using GroupElement = typename Curve::Element; + using Commitment = typename Curve::AffineElement; + + auto prover_transcript = TypeParam::Transcript::prover_init_empty(); + std::shared_ptr ck; + ck = CreateCommitmentKey(); + + // Generate Libra polynomials, compute masked concatenated Libra polynomial, commit to it + ZKData zk_sumcheck_data(this->log_n, prover_transcript, ck); + + // Generate multilinear challenge of size CONST_PROOF_SIZE_LOG_N + auto const_size_mle_opening_point = this->random_evaluation_point(CONST_PROOF_SIZE_LOG_N); + // Truncate the challenge for evaluations + const std::vector mle_opening_point(const_size_mle_opening_point.begin(), + const_size_mle_opening_point.begin() + this->log_n); + // Generate random prover polynomials, compute their evaluations and commitments + auto pcs_instance_witness = + PCSInstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); + + // Compute the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges + const Fr claimed_inner_product = SmallSubgroupIPATest::compute_claimed_inner_product( + zk_sumcheck_data, const_size_mle_opening_point, this->log_n); + + prover_transcript->template send_to_verifier("Libra:claimed_evaluation", claimed_inner_product); + + // Instantiate SmallSubgroupIPAProver, this prover sends commitments to Big Sum and Quotient polynomials + auto small_subgroup_ipa_prover = SmallSubgroupIPAProver( + zk_sumcheck_data, const_size_mle_opening_point, claimed_inner_product, prover_transcript, ck); + + // Reduce to KZG or IPA based on the curve used in the test Flavor + const auto opening_claim = ShpleminiProver::prove(this->n, + RefVector(pcs_instance_witness.polynomials), + RefVector(pcs_instance_witness.shiftable_polynomials), + const_size_mle_opening_point, + ck, + prover_transcript, + small_subgroup_ipa_prover.get_witness_polynomials()); + + if constexpr (std::is_same_v) { + IPA::compute_opening_proof(this->ck(), opening_claim, prover_transcript); + } else { + KZG::compute_opening_proof(this->ck(), opening_claim, prover_transcript); + } + auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + + // Start populating Verifier's array of Libra commitments + std::array libra_commitments = {}; + libra_commitments[0] = + verifier_transcript->template receive_from_prover("Libra:concatenation_commitment"); + + // Place the Libra total sum to the transcript + const Fr libra_total_sum = verifier_transcript->template receive_from_prover("Libra:Sum"); + const Fr libra_challenge = verifier_transcript->template get_challenge("Libra:Challenge"); + const Fr libra_evaluation = verifier_transcript->template receive_from_prover("Libra:claimed_evaluation"); + + // Transcript consistency checks + EXPECT_EQ(libra_total_sum, zk_sumcheck_data.libra_total_sum); + EXPECT_EQ(libra_challenge, zk_sumcheck_data.libra_challenge); + EXPECT_EQ(libra_evaluation, claimed_inner_product); + + // Finalize the array of Libra/SmallSubgroupIpa commitments + libra_commitments[1] = verifier_transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments[2] = verifier_transcript->template receive_from_prover("Libra:quotient_commitment"); + + // Used to verify the consistency of the evaluations of the concatenated libra polynomial, big sum polynomial, and + // the quotient polynomial computed by SmallSubgroupIPAProver + bool consistency_checked = true; + + // Run Shplemini + const auto batch_opening_claim = + ShpleminiVerifier::compute_batch_opening_claim(this->n, + RefVector(pcs_instance_witness.unshifted_commitments), + RefVector(pcs_instance_witness.shifted_commitments), + RefVector(pcs_instance_witness.unshifted_evals), + RefVector(pcs_instance_witness.shifted_evals), + const_size_mle_opening_point, + this->vk()->get_g1_identity(), + verifier_transcript, + {}, + true, + &consistency_checked, + libra_commitments, + libra_evaluation); + // Verify claim using KZG or IPA + if constexpr (std::is_same_v) { + auto result = + IPA::reduce_verify_batch_opening_claim(batch_opening_claim, this->vk(), verifier_transcript); + EXPECT_EQ(result, true); + } else { + const auto pairing_points = + KZG::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript); + // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2) + EXPECT_EQ(this->vk()->pairing_check(pairing_points[0], pairing_points[1]), true); + } +} + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp index 39f9b27b625..2bdb6093723 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp @@ -204,7 +204,7 @@ template class SmallSubgroupIPAProver { // We concatenate 1 with CONST_PROOF_SIZE_LOG_N Libra Univariates of length LIBRA_UNIVARIATES_LENGTH const size_t poly_to_concatenate_start = 1 + LIBRA_UNIVARIATES_LENGTH * challenge_idx; coeffs_lagrange_basis[poly_to_concatenate_start] = FF(1); - for (size_t idx = poly_to_concatenate_start + 1; idx < poly_to_concatenate_start + LIBRA_UNIVARIATES_LENGTH; + for (size_t idx = 1 + poly_to_concatenate_start; idx < poly_to_concatenate_start + LIBRA_UNIVARIATES_LENGTH; idx++) { // Recursively compute the powers of the challenge coeffs_lagrange_basis[idx] = coeffs_lagrange_basis[idx - 1] * multivariate_challenge[challenge_idx]; @@ -426,6 +426,17 @@ template class SmallSubgroupIPAVerifier { // Compute the evaluation of the vanishing polynomia Z_H(X) at X = gemini_evaluation_challenge const FF vanishing_poly_eval = gemini_evaluation_challenge.pow(SUBGROUP_SIZE) - FF(1); + bool gemini_challenge_in_small_subgroup = false; + if constexpr (Curve::is_stdlib_type) { + gemini_challenge_in_small_subgroup = (vanishing_poly_eval.get_value() == FF(0).get_value()); + } else { + gemini_challenge_in_small_subgroup = (vanishing_poly_eval == FF(0)); + } + + // The probability of this event is negligible but it has to be processed correctly + if (gemini_challenge_in_small_subgroup) { + throw_or_abort("Gemini evaluation challenge is in the SmallSubgroup."); + } // Construct the challenge polynomial from the sumcheck challenge, the verifier has to evaluate it on its own const std::vector challenge_polynomial_lagrange = compute_challenge_polynomial(multilinear_challenge); @@ -542,4 +553,4 @@ template class SmallSubgroupIPAVerifier { return result; } }; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp new file mode 100644 index 00000000000..9e17711d52c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp @@ -0,0 +1,251 @@ +#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" +#include "barretenberg/commitment_schemes/pcs_test_flavors.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" + +#include +#include + +namespace bb { +template class SmallSubgroupIPATest : public ::testing::Test { + public: + using Curve = typename Flavor::Curve; + using CommitmentKey = typename Flavor::CommitmentKey; + using Transcript = typename Flavor::Transcript; + using FF = typename Curve::ScalarField; + + static constexpr size_t log_circuit_size = 7; + + FF evaluation_challenge; + + void SetUp() override { evaluation_challenge = FF::random_element(); } + + /** + * @brief Comput the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges. + * + * @param zk_sumcheck_data Contains Libra constant term and scaled Libra univariates + * @param multivariate_challenge Sumcheck challenge + * @param log_circuit_size + */ + static FF compute_claimed_inner_product(ZKSumcheckData& zk_sumcheck_data, + const std::vector& multivariate_challenge, + const size_t& log_circuit_size) + { + const FF libra_challenge_inv = zk_sumcheck_data.libra_challenge.invert(); + // Compute claimed inner product similarly to the SumcheckProver + FF claimed_inner_product = FF{ 0 }; + size_t idx = 0; + for (const auto& univariate : zk_sumcheck_data.libra_univariates) { + claimed_inner_product += univariate.evaluate(multivariate_challenge[idx]); + idx++; + } + // Libra Univariates are mutiplied by the Libra challenge in setup_auxiliary_data(), needs to be undone + claimed_inner_product *= libra_challenge_inv / FF(1 << (log_circuit_size - 1)); + claimed_inner_product += zk_sumcheck_data.constant_term; + return claimed_inner_product; + } + + static std::vector generate_random_vector(const size_t size) + { + std::vector multivariate_challenge(size); + for (auto& challenge : multivariate_challenge) { + challenge = FF::random_element(); + } + return multivariate_challenge; + } +}; + +// Register the flavors for the test suite +using TestFlavors = ::testing::Types; +TYPED_TEST_SUITE(SmallSubgroupIPATest, TestFlavors); + +// Implement the tests +TYPED_TEST(SmallSubgroupIPATest, ProverComputationsCorrectness) +{ + using ZKData = ZKSumcheckData; + using SmallSubgroupIPA = SmallSubgroupIPAProver; + using FF = typename TypeParam::FF; + static constexpr size_t SUBGROUP_SIZE = TypeParam::SUBGROUP_SIZE; + + std::shared_ptr ck; + + auto prover_transcript = TypeParam::Transcript::prover_init_empty(); + ck = CreateCommitmentKey(); + + ZKData zk_sumcheck_data(this->log_circuit_size, prover_transcript, ck); + std::vector multivariate_challenge = this->generate_random_vector(this->log_circuit_size); + + const FF claimed_inner_product = + this->compute_claimed_inner_product(zk_sumcheck_data, multivariate_challenge, this->log_circuit_size); + + SmallSubgroupIPA small_subgroup_ipa_prover = + SmallSubgroupIPA(zk_sumcheck_data, multivariate_challenge, claimed_inner_product, prover_transcript, ck); + + auto batched_polynomial = small_subgroup_ipa_prover.get_batched_polynomial(); + auto libra_concatenated_polynomial = small_subgroup_ipa_prover.get_witness_polynomials()[0]; + auto batched_quotient = small_subgroup_ipa_prover.get_witness_polynomials()[3]; + auto challenge_polynomial = small_subgroup_ipa_prover.get_challenge_polynomial(); + + // Check that claimed inner product coincides with the inner product of libra_concatenated_polynomial and + // challenge_polynomial. Since libra_concatenated_polynomial is masked, we also check that masking does not affect + // the evaluations over H + FF inner_product = FF(0); + auto domain = zk_sumcheck_data.interpolation_domain; + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + inner_product += + challenge_polynomial.evaluate(domain[idx]) * libra_concatenated_polynomial.evaluate(domain[idx]); + } + EXPECT_TRUE(inner_product == claimed_inner_product); + + // Check that batched polynomial is divisible by Z_H(X) + bool ipa_claim_consistency = true; + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + ipa_claim_consistency = (batched_polynomial.evaluate(zk_sumcheck_data.interpolation_domain[idx]) == FF{ 0 }) && + ipa_claim_consistency; + } + EXPECT_EQ(ipa_claim_consistency, true); + + // Check that Z_H(X) * Q(X) = batched_polynomial + std::vector Z_H(SUBGROUP_SIZE + 1); + Z_H[0] = -FF(1); + Z_H[SUBGROUP_SIZE] = FF(1); + Polynomial product(batched_polynomial.size()); + + for (size_t i = 0; i < Z_H.size(); i++) { + for (size_t j = 0; j < batched_quotient.size(); j++) { + product.at(i + j) += Z_H[i] * batched_quotient.at(j); + } + } + bool quotient_is_correct = true; + for (const auto& [coeff_expected, coeff] : zip_view(product.coeffs(), batched_polynomial.coeffs())) { + quotient_is_correct = (coeff_expected == coeff) && quotient_is_correct; + } + EXPECT_EQ(quotient_is_correct, true); +} + +TYPED_TEST(SmallSubgroupIPATest, VerifierEvaluations) +{ + using FF = typename TypeParam::FF; + using Curve = typename TypeParam::Curve; + using SmallSubgroupIPA = SmallSubgroupIPAVerifier; + + // Extract the constants + static constexpr size_t SUBGROUP_SIZE = TypeParam::SUBGROUP_SIZE; + const FF subgroup_generator_inverse = Curve::subgroup_generator_inverse; + const FF subgroup_generator = subgroup_generator_inverse.invert(); + + // Sample random Lagrange coefficients over H + std::vector challenge_poly_lagrange = this->generate_random_vector(SUBGROUP_SIZE); + + // Evaluate Verifier's polynomials at the challenge + const FF vanishing_poly_eval = this->evaluation_challenge.pow(SUBGROUP_SIZE) - 1; + + // Compute required evaluations using efficient batch evaluation + const auto [challenge_poly_eval, lagrange_first, lagrange_last] = + SmallSubgroupIPA::compute_batched_barycentric_evaluations( + challenge_poly_lagrange, this->evaluation_challenge, subgroup_generator_inverse, vanishing_poly_eval); + + // Compute the evaluations differently, namely, using Lagrange interpolation + std::array interpolation_domain; + interpolation_domain[0] = FF(1); + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + interpolation_domain[idx] = interpolation_domain[idx - 1] * subgroup_generator; + } + Polynomial challenge_poly_monomial = + Polynomial(interpolation_domain, challenge_poly_lagrange, SUBGROUP_SIZE); + + // Evaluate at the challenge + const FF challenge_poly_expected_eval = challenge_poly_monomial.evaluate(this->evaluation_challenge); + + EXPECT_EQ(challenge_poly_eval, challenge_poly_expected_eval); + + // Compute Lagrange polynomials using interpolation + std::vector lagrange_poly(SUBGROUP_SIZE); + lagrange_poly.at(0) = FF(1); + Polynomial lagrange_first_monomial = Polynomial(interpolation_domain, lagrange_poly, SUBGROUP_SIZE); + EXPECT_EQ(lagrange_first, lagrange_first_monomial.evaluate(this->evaluation_challenge)); + + lagrange_poly.at(0) = FF(0); + lagrange_poly.at(SUBGROUP_SIZE - 1) = FF(1); + Polynomial lagrange_last_monomial = Polynomial(interpolation_domain, lagrange_poly, SUBGROUP_SIZE); + EXPECT_EQ(lagrange_last, lagrange_last_monomial.evaluate(this->evaluation_challenge)); +} + +TYPED_TEST(SmallSubgroupIPATest, ProverAndVerifierSimple) +{ + using FF = typename TypeParam::FF; + using Curve = typename TypeParam::Curve; + using Verifier = SmallSubgroupIPAVerifier; + using Prover = SmallSubgroupIPAProver; + using ZKData = ZKSumcheckData; + + auto prover_transcript = TypeParam::Transcript::prover_init_empty(); + std::shared_ptr ck; + ck = CreateCommitmentKey(); + + ZKData zk_sumcheck_data(this->log_circuit_size, prover_transcript, ck); + + std::vector multivariate_challenge = this->generate_random_vector(CONST_PROOF_SIZE_LOG_N); + + const FF claimed_inner_product = + this->compute_claimed_inner_product(zk_sumcheck_data, multivariate_challenge, this->log_circuit_size); + + Prover small_subgroup_ipa_prover = + Prover(zk_sumcheck_data, multivariate_challenge, claimed_inner_product, prover_transcript, ck); + + auto witness_polynomials = small_subgroup_ipa_prover.get_witness_polynomials(); + + std::array libra_evaluations = { + witness_polynomials[0].evaluate(this->evaluation_challenge), + witness_polynomials[1].evaluate(this->evaluation_challenge * Curve::subgroup_generator), + witness_polynomials[2].evaluate(this->evaluation_challenge), + witness_polynomials[3].evaluate(this->evaluation_challenge) + }; + + bool consistency_checked = Verifier::check_evaluations_consistency( + libra_evaluations, this->evaluation_challenge, multivariate_challenge, claimed_inner_product); + + EXPECT_TRUE(consistency_checked); +} + +TYPED_TEST(SmallSubgroupIPATest, ProverAndVerifierSimpleFailure) +{ + using FF = typename TypeParam::FF; + using Curve = typename TypeParam::Curve; + using Verifier = SmallSubgroupIPAVerifier; + using Prover = SmallSubgroupIPAProver; + using ZKData = ZKSumcheckData; + + auto prover_transcript = TypeParam::Transcript::prover_init_empty(); + std::shared_ptr ck; + ck = CreateCommitmentKey(); + + ZKData zk_sumcheck_data(this->log_circuit_size, prover_transcript, ck); + + std::vector multivariate_challenge = this->generate_random_vector(CONST_PROOF_SIZE_LOG_N); + + const FF claimed_inner_product = + this->compute_claimed_inner_product(zk_sumcheck_data, multivariate_challenge, this->log_circuit_size); + + Prover small_subgroup_ipa_prover = + Prover(zk_sumcheck_data, multivariate_challenge, claimed_inner_product, prover_transcript, ck); + + auto witness_polynomials = small_subgroup_ipa_prover.get_witness_polynomials(); + + // Tamper with witness polynomials + witness_polynomials[0].at(0) = FF::random_element(); + + std::array libra_evaluations = { + witness_polynomials[0].evaluate(this->evaluation_challenge), + witness_polynomials[1].evaluate(this->evaluation_challenge * Curve::subgroup_generator), + witness_polynomials[2].evaluate(this->evaluation_challenge), + witness_polynomials[3].evaluate(this->evaluation_challenge) + }; + + bool consistency_checked = Verifier::check_evaluations_consistency( + libra_evaluations, this->evaluation_challenge, multivariate_challenge, claimed_inner_product); + + // Since witness polynomials were modified, the consistency check must fail + EXPECT_FALSE(consistency_checked); +} + +} // namespace bb \ No newline at end of file From dd35c957dc4392a7eba6eeb9b6bdfdda63a61d91 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 8 Jan 2025 16:34:20 +0000 Subject: [PATCH 2/4] gcc build fixed --- .../commitment_schemes/pcs_test_flavors.hpp | 8 ++++++-- .../pcs_test_instance_witness_generator.hpp | 10 ++++++++-- .../small_subgroup_ipa/small_subgroup_ipa.test.cpp | 1 - 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp index 29f6363696c..26da1f7befa 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp @@ -5,10 +5,14 @@ #include "commitment_key.test.hpp" namespace bb { +/** + * @brief Mock Flavors to use ZKSumcheckData and SmallSubgroupIPAProver in the PCS tests. + * + */ class TestBn254Flavor { public: using Curve = curve::BN254; - using CommitmentKey = CommitmentKey; + using CommitmentKey = bb::CommitmentKey; using Transcript = NativeTranscript; using FF = typename Curve::ScalarField; static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; @@ -17,7 +21,7 @@ class TestBn254Flavor { class TestGrumpkinFlavor { public: using Curve = curve::Grumpkin; - using CommitmentKey = CommitmentKey; + using CommitmentKey = bb::CommitmentKey; using Transcript = NativeTranscript; using FF = typename Curve::ScalarField; static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp index 91b7084bf64..2bc8702d34d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp @@ -6,10 +6,14 @@ #include "commitment_key.test.hpp" namespace bb { - +/** + * @brief Constructs random polynomials, computes commitments and corresponding evaluations. + * + * @tparam Curve + */ template struct PCSInstanceWitnessGenerator { public: - using CommitmentKey = CommitmentKey; + using CommitmentKey = bb::CommitmentKey; using Fr = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; using Polynomial = bb::Polynomial; @@ -41,12 +45,14 @@ template struct PCSInstanceWitnessGenerator { const size_t num_unshifted = polynomials.size() - shiftable_polynomials.size(); + // Process polynomials that are not getting shifted for (size_t idx = 0; idx < num_unshifted; idx++) { polynomials[idx] = Polynomial::random(n); unshifted_commitments.push_back(ck->commit(polynomials[idx])); unshifted_evals.push_back(polynomials[idx].evaluate_mle(mle_opening_point)); } + // Process polynomials that are getting shifted size_t idx = num_unshifted; for (auto& poly : shiftable_polynomials) { poly = Polynomial::random(n, /*shiftable*/ 1); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp index 9e17711d52c..5a85943d652 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp @@ -9,7 +9,6 @@ namespace bb { template class SmallSubgroupIPATest : public ::testing::Test { public: using Curve = typename Flavor::Curve; - using CommitmentKey = typename Flavor::CommitmentKey; using Transcript = typename Flavor::Transcript; using FF = typename Curve::ScalarField; From a05ee544470f88d42ca68564ee50d7cee18ff7dd Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 9 Jan 2025 10:29:31 +0000 Subject: [PATCH 3/4] docs + issues --- .../commitment_schemes/gemini/gemini_impl.hpp | 9 ++++++++ .../shplonk/shplemini.test.cpp | 23 ++++++++++++------- .../small_subgroup_ipa/small_subgroup_ipa.hpp | 5 ++-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp index a66387474d1..3828a009b6b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -124,6 +124,15 @@ std::vector::Claim> GeminiProver_::prove( } const Fr r_challenge = transcript->template get_challenge("Gemini:r"); + const bool gemini_challenge_in_small_subgroup = (has_zk) && (r_challenge.pow(Curve::SUBGROUP_SIZE) == Fr(1)); + + // If Gemini evaluation challenge lands in the multiplicative subgroup used by SmallSubgroupIPA protocol, the + // evaluations of prover polynomials at this challenge would leak witness data. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1194). Handle edge cases in PCS + if (gemini_challenge_in_small_subgroup) { + throw_or_abort("Gemini evaluation challenge is in the SmallSubgroup."); + } + std::vector claims = compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), r_challenge, std::move(batched_group)); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp index f9d7992e1df..e4f4c64a67b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -226,6 +226,11 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) EXPECT_EQ(shplemini_result, expected_result); } +/** + * @brief Test Shplemini with ZK data consisting of a hiding polynomial generated by GeminiProver and Libra polynomials + * used to mask Sumcheck Round Univariates. + * + */ TYPED_TEST(ShpleminiTest, ShpleminiWithZK) { using ZKData = ZKSumcheckData; @@ -233,21 +238,21 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK) using ShpleminiProver = ShpleminiProver_; using ShpleminiVerifier = ShpleminiVerifier_; using Fr = typename Curve::ScalarField; - // using GroupElement = typename Curve::Element; using Commitment = typename Curve::AffineElement; + // Initialize transcript and commitment key auto prover_transcript = TypeParam::Transcript::prover_init_empty(); - std::shared_ptr ck; - ck = CreateCommitmentKey(); + std::shared_ptr ck = CreateCommitmentKey(); // Generate Libra polynomials, compute masked concatenated Libra polynomial, commit to it ZKData zk_sumcheck_data(this->log_n, prover_transcript, ck); - // Generate multilinear challenge of size CONST_PROOF_SIZE_LOG_N - auto const_size_mle_opening_point = this->random_evaluation_point(CONST_PROOF_SIZE_LOG_N); - // Truncate the challenge for evaluations + // Generate multivariate challenge of size CONST_PROOF_SIZE_LOG_N + std::vector const_size_mle_opening_point = this->random_evaluation_point(CONST_PROOF_SIZE_LOG_N); + // Truncate the multivariate challenge to evaluate prover polynomials (As in Sumcheck) const std::vector mle_opening_point(const_size_mle_opening_point.begin(), const_size_mle_opening_point.begin() + this->log_n); + // Generate random prover polynomials, compute their evaluations and commitments auto pcs_instance_witness = PCSInstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); @@ -276,6 +281,8 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK) } else { KZG::compute_opening_proof(this->ck(), opening_claim, prover_transcript); } + + // Initialize verifier's transcript auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); // Start populating Verifier's array of Libra commitments @@ -283,12 +290,12 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK) libra_commitments[0] = verifier_transcript->template receive_from_prover("Libra:concatenation_commitment"); - // Place the Libra total sum to the transcript + // Place Libra data to the transcript const Fr libra_total_sum = verifier_transcript->template receive_from_prover("Libra:Sum"); const Fr libra_challenge = verifier_transcript->template get_challenge("Libra:Challenge"); const Fr libra_evaluation = verifier_transcript->template receive_from_prover("Libra:claimed_evaluation"); - // Transcript consistency checks + // Check that transcript is consistent EXPECT_EQ(libra_total_sum, zk_sumcheck_data.libra_total_sum); EXPECT_EQ(libra_challenge, zk_sumcheck_data.libra_challenge); EXPECT_EQ(libra_evaluation, claimed_inner_product); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp index 2bdb6093723..ac8bc0d7b9b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp @@ -204,7 +204,7 @@ template class SmallSubgroupIPAProver { // We concatenate 1 with CONST_PROOF_SIZE_LOG_N Libra Univariates of length LIBRA_UNIVARIATES_LENGTH const size_t poly_to_concatenate_start = 1 + LIBRA_UNIVARIATES_LENGTH * challenge_idx; coeffs_lagrange_basis[poly_to_concatenate_start] = FF(1); - for (size_t idx = 1 + poly_to_concatenate_start; idx < poly_to_concatenate_start + LIBRA_UNIVARIATES_LENGTH; + for (size_t idx = poly_to_concatenate_start + 1; idx < poly_to_concatenate_start + LIBRA_UNIVARIATES_LENGTH; idx++) { // Recursively compute the powers of the challenge coeffs_lagrange_basis[idx] = coeffs_lagrange_basis[idx - 1] * multivariate_challenge[challenge_idx]; @@ -426,13 +426,14 @@ template class SmallSubgroupIPAVerifier { // Compute the evaluation of the vanishing polynomia Z_H(X) at X = gemini_evaluation_challenge const FF vanishing_poly_eval = gemini_evaluation_challenge.pow(SUBGROUP_SIZE) - FF(1); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1194). Handle edge cases in PCS + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1186). Insecure pattern. bool gemini_challenge_in_small_subgroup = false; if constexpr (Curve::is_stdlib_type) { gemini_challenge_in_small_subgroup = (vanishing_poly_eval.get_value() == FF(0).get_value()); } else { gemini_challenge_in_small_subgroup = (vanishing_poly_eval == FF(0)); } - // The probability of this event is negligible but it has to be processed correctly if (gemini_challenge_in_small_subgroup) { throw_or_abort("Gemini evaluation challenge is in the SmallSubgroup."); From c2cf95d2e7740d53ae9518a20e29c64b6e016b24 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 10 Jan 2025 13:34:18 +0000 Subject: [PATCH 4/4] comments resolved --- .../commitment_key.test.hpp | 32 ++++--- .../shplonk/shplemini.test.cpp | 63 +++++++------ .../small_subgroup_ipa/small_subgroup_ipa.hpp | 26 ++++++ .../small_subgroup_ipa.test.cpp | 90 +++++++++---------- .../instance_witness_generator.hpp} | 44 ++++----- .../test_settings.hpp} | 6 +- 6 files changed, 150 insertions(+), 111 deletions(-) rename barretenberg/cpp/src/barretenberg/commitment_schemes/{pcs_test_instance_witness_generator.hpp => utils/instance_witness_generator.hpp} (50%) rename barretenberg/cpp/src/barretenberg/commitment_schemes/{pcs_test_flavors.hpp => utils/test_settings.hpp} (87%) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.test.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.test.hpp index adafef90c7c..de417753927 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.test.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.test.hpp @@ -14,44 +14,54 @@ namespace bb { constexpr size_t COMMITMENT_TEST_NUM_BN254_POINTS = 4096; constexpr size_t COMMITMENT_TEST_NUM_GRUMPKIN_POINTS = 1 << CONST_ECCVM_LOG_N; -template inline std::shared_ptr CreateCommitmentKey(); +template inline std::shared_ptr create_commitment_key(const size_t num_points = 0); -template <> inline std::shared_ptr> CreateCommitmentKey>() +template <> +inline std::shared_ptr> create_commitment_key>( + const size_t num_points) { srs::init_crs_factory(bb::srs::get_ignition_crs_path()); + if (num_points != 0) { + return std::make_shared>(num_points); + }; return std::make_shared>(COMMITMENT_TEST_NUM_BN254_POINTS); } // For IPA -template <> inline std::shared_ptr> CreateCommitmentKey>() +template <> +inline std::shared_ptr> create_commitment_key>( + const size_t num_points) { srs::init_grumpkin_crs_factory(bb::srs::get_grumpkin_crs_path()); + if (num_points != 0) { + return std::make_shared>(num_points); + } return std::make_shared>(COMMITMENT_TEST_NUM_GRUMPKIN_POINTS); } -template inline std::shared_ptr CreateCommitmentKey() +template inline std::shared_ptr create_commitment_key(size_t num_points) // requires std::default_initializable { - return std::make_shared(); + return std::make_shared(num_points); } -template inline std::shared_ptr CreateVerifierCommitmentKey(); +template inline std::shared_ptr create_verifier_commitment_key(); template <> -inline std::shared_ptr> CreateVerifierCommitmentKey< +inline std::shared_ptr> create_verifier_commitment_key< VerifierCommitmentKey>() { return std::make_shared>(); } // For IPA template <> -inline std::shared_ptr> CreateVerifierCommitmentKey< +inline std::shared_ptr> create_verifier_commitment_key< VerifierCommitmentKey>() { auto crs_factory = std::make_shared>( bb::srs::get_grumpkin_crs_path(), COMMITMENT_TEST_NUM_GRUMPKIN_POINTS); return std::make_shared>(COMMITMENT_TEST_NUM_GRUMPKIN_POINTS, crs_factory); } -template inline std::shared_ptr CreateVerifierCommitmentKey() +template inline std::shared_ptr create_verifier_commitment_key() // requires std::default_initializable { return std::make_shared(); @@ -149,10 +159,10 @@ template class CommitmentTest : public ::testing::Test { { // Avoid reallocating static objects if called in subclasses of FooTest. if (commitment_key == nullptr) { - commitment_key = CreateCommitmentKey(); + commitment_key = create_commitment_key(); } if (verification_key == nullptr) { - verification_key = CreateVerifierCommitmentKey(); + verification_key = create_verifier_commitment_key(); } } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp index e4f4c64a67b..2bcc54538b2 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -5,10 +5,10 @@ #include "../kzg/kzg.hpp" #include "../shplonk/shplonk.hpp" #include "../utils/batch_mul_native.hpp" -#include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/ipa/ipa.hpp" -#include "barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp" -#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp" +#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" +#include "barretenberg/commitment_schemes/utils/instance_witness_generator.hpp" +#include "barretenberg/commitment_schemes/utils/test_settings.hpp" #include "barretenberg/ecc/curves/bn254/g1.hpp" #include @@ -24,9 +24,9 @@ template class ShpleminiTest : public CommitmentTest; +using TestSettings = ::testing::Types; -TYPED_TEST_SUITE(ShpleminiTest, FlavorTypes); +TYPED_TEST_SUITE(ShpleminiTest, TestSettings); // This test checks that batch_multivariate_opening_claims method operates correctly TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) @@ -36,9 +36,9 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) using Fr = typename Curve::ScalarField; using GroupElement = typename Curve::Element; using Commitment = typename Curve::AffineElement; + using CK = typename TypeParam::CommitmentKey; - std::shared_ptr ck; - ck = CreateCommitmentKey(); + std::shared_ptr ck = create_commitment_key(this->n); // Generate mock challenges Fr rho = Fr::random_element(); @@ -50,7 +50,7 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) auto mle_opening_point = this->random_evaluation_point(this->log_n); auto pcs_instance_witness = - PCSInstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); + InstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); // Collect multilinear evaluations std::vector rhos = gemini::powers_of_rho(rho, this->num_polynomials + this->num_shiftable); @@ -77,7 +77,7 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) } GroupElement batched_commitment_to_be_shifted = GroupElement::zero(); - for (auto& comm : pcs_instance_witness.shifted_commitments) { + for (auto& comm : pcs_instance_witness.to_be_shifted_commitments) { batched_commitment_to_be_shifted += comm * rhos[idx]; idx++; } @@ -98,15 +98,15 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) std::vector scalars; Fr verifier_batched_evaluation{ 0 }; - Fr unshifted_scalar = (shplonk_eval_challenge - gemini_eval_challenge).invert() + - shplonk_batching_challenge * (shplonk_eval_challenge + gemini_eval_challenge).invert(); + const Fr unshifted_scalar = (shplonk_eval_challenge - gemini_eval_challenge).invert() + + shplonk_batching_challenge * (shplonk_eval_challenge + gemini_eval_challenge).invert(); - Fr shifted_scalar = gemini_eval_challenge.invert() * - ((shplonk_eval_challenge - gemini_eval_challenge).invert() - - shplonk_batching_challenge * (shplonk_eval_challenge + gemini_eval_challenge).invert()); + const Fr shifted_scalar = gemini_eval_challenge.invert() * + ((shplonk_eval_challenge - gemini_eval_challenge).invert() - + shplonk_batching_challenge * (shplonk_eval_challenge + gemini_eval_challenge).invert()); ShpleminiVerifier::batch_multivariate_opening_claims(RefVector(pcs_instance_witness.unshifted_commitments), - RefVector(pcs_instance_witness.shifted_commitments), + RefVector(pcs_instance_witness.to_be_shifted_commitments), RefVector(pcs_instance_witness.unshifted_evals), RefVector(pcs_instance_witness.shifted_evals), rho, @@ -120,7 +120,8 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) GroupElement shplemini_result = batch_mul_native(commitments, scalars); EXPECT_EQ(commitments.size(), - pcs_instance_witness.unshifted_commitments.size() + pcs_instance_witness.shifted_commitments.size()); + pcs_instance_witness.unshifted_commitments.size() + + pcs_instance_witness.to_be_shifted_commitments.size()); EXPECT_EQ(batched_evaluation, verifier_batched_evaluation); EXPECT_EQ(-expected_result, shplemini_result); } @@ -134,9 +135,9 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) using GroupElement = typename Curve::Element; using Commitment = typename Curve::AffineElement; using Polynomial = typename bb::Polynomial; + using CK = typename TypeParam::CommitmentKey; - std::shared_ptr ck; - ck = CreateCommitmentKey(); + std::shared_ptr ck = create_commitment_key(this->n); // Generate mock challenges Fr rho = Fr::random_element(); @@ -147,7 +148,7 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) std::vector mle_opening_point = this->random_evaluation_point(this->log_n); auto pcs_instance_witness = - PCSInstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); + InstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); // Collect multilinear evaluations std::vector rhos = gemini::powers_of_rho(rho, this->num_polynomials + this->num_shiftable); @@ -156,12 +157,12 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) Polynomial batched_to_be_shifted = Polynomial::shiftable(this->n); size_t idx = 0; - for (auto& poly : pcs_instance_witness.polynomials) { + for (auto& poly : pcs_instance_witness.unshifted_polynomials) { batched_unshifted.add_scaled(poly, rhos[idx]); idx++; } - for (auto& poly : pcs_instance_witness.shiftable_polynomials) { + for (auto& poly : pcs_instance_witness.to_be_shifted_polynomials) { batched_unshifted.add_scaled(poly, rhos[idx]); idx++; } @@ -239,10 +240,14 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK) using ShpleminiVerifier = ShpleminiVerifier_; using Fr = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; + using CK = typename TypeParam::CommitmentKey; // Initialize transcript and commitment key auto prover_transcript = TypeParam::Transcript::prover_init_empty(); - std::shared_ptr ck = CreateCommitmentKey(); + + // SmallSubgroupIPAProver requires at least CURVE::SUBGROUP_SIZE + 3 elements in the ck. + static constexpr size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); + std::shared_ptr ck = create_commitment_key(std::max(this->n, 1ULL << (log_subgroup_size + 1))); // Generate Libra polynomials, compute masked concatenated Libra polynomial, commit to it ZKData zk_sumcheck_data(this->log_n, prover_transcript, ck); @@ -255,10 +260,10 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK) // Generate random prover polynomials, compute their evaluations and commitments auto pcs_instance_witness = - PCSInstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); + InstanceWitnessGenerator(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck); // Compute the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges - const Fr claimed_inner_product = SmallSubgroupIPATest::compute_claimed_inner_product( + const Fr claimed_inner_product = SmallSubgroupIPAProver::compute_claimed_inner_product( zk_sumcheck_data, const_size_mle_opening_point, this->log_n); prover_transcript->template send_to_verifier("Libra:claimed_evaluation", claimed_inner_product); @@ -269,14 +274,14 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK) // Reduce to KZG or IPA based on the curve used in the test Flavor const auto opening_claim = ShpleminiProver::prove(this->n, - RefVector(pcs_instance_witness.polynomials), - RefVector(pcs_instance_witness.shiftable_polynomials), + RefVector(pcs_instance_witness.unshifted_polynomials), + RefVector(pcs_instance_witness.to_be_shifted_polynomials), const_size_mle_opening_point, ck, prover_transcript, small_subgroup_ipa_prover.get_witness_polynomials()); - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { IPA::compute_opening_proof(this->ck(), opening_claim, prover_transcript); } else { KZG::compute_opening_proof(this->ck(), opening_claim, prover_transcript); @@ -312,7 +317,7 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK) const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(this->n, RefVector(pcs_instance_witness.unshifted_commitments), - RefVector(pcs_instance_witness.shifted_commitments), + RefVector(pcs_instance_witness.to_be_shifted_commitments), RefVector(pcs_instance_witness.unshifted_evals), RefVector(pcs_instance_witness.shifted_evals), const_size_mle_opening_point, @@ -324,7 +329,7 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK) libra_commitments, libra_evaluation); // Verify claim using KZG or IPA - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { auto result = IPA::reduce_verify_batch_opening_claim(batch_opening_claim, this->vk(), verifier_transcript); EXPECT_EQ(result, true); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp index ac8bc0d7b9b..54af7999a2a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp @@ -374,6 +374,32 @@ template class SmallSubgroupIPAProver { remainder.at(idx - SUBGROUP_SIZE) += remainder.at(idx); } } + + /** + * @brief For test purposes: Compute the sum of the Libra constant term and Libra univariates evaluated at Sumcheck + * challenges. + * + * @param zk_sumcheck_data Contains Libra constant term and scaled Libra univariates + * @param multivariate_challenge Sumcheck challenge + * @param log_circuit_size + */ + static FF compute_claimed_inner_product(ZKSumcheckData& zk_sumcheck_data, + const std::vector& multivariate_challenge, + const size_t& log_circuit_size) + { + const FF libra_challenge_inv = zk_sumcheck_data.libra_challenge.invert(); + // Compute claimed inner product similarly to the SumcheckProver + FF claimed_inner_product = FF{ 0 }; + size_t idx = 0; + for (const auto& univariate : zk_sumcheck_data.libra_univariates) { + claimed_inner_product += univariate.evaluate(multivariate_challenge[idx]); + idx++; + } + // Libra Univariates are mutiplied by the Libra challenge in setup_auxiliary_data(), needs to be undone + claimed_inner_product *= libra_challenge_inv / FF(1 << (log_circuit_size - 1)); + claimed_inner_product += zk_sumcheck_data.constant_term; + return claimed_inner_product; + } }; /** diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp index 5a85943d652..cc445d3a394 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp @@ -1,8 +1,10 @@ #include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" -#include "barretenberg/commitment_schemes/pcs_test_flavors.hpp" +#include "../commitment_key.test.hpp" #include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" +#include "barretenberg/commitment_schemes/utils/test_settings.hpp" #include +#include #include namespace bb { @@ -13,36 +15,12 @@ template class SmallSubgroupIPATest : public ::testing::Test { using FF = typename Curve::ScalarField; static constexpr size_t log_circuit_size = 7; + static constexpr size_t circuit_size = 1ULL << log_circuit_size; FF evaluation_challenge; void SetUp() override { evaluation_challenge = FF::random_element(); } - /** - * @brief Comput the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges. - * - * @param zk_sumcheck_data Contains Libra constant term and scaled Libra univariates - * @param multivariate_challenge Sumcheck challenge - * @param log_circuit_size - */ - static FF compute_claimed_inner_product(ZKSumcheckData& zk_sumcheck_data, - const std::vector& multivariate_challenge, - const size_t& log_circuit_size) - { - const FF libra_challenge_inv = zk_sumcheck_data.libra_challenge.invert(); - // Compute claimed inner product similarly to the SumcheckProver - FF claimed_inner_product = FF{ 0 }; - size_t idx = 0; - for (const auto& univariate : zk_sumcheck_data.libra_univariates) { - claimed_inner_product += univariate.evaluate(multivariate_challenge[idx]); - idx++; - } - // Libra Univariates are mutiplied by the Libra challenge in setup_auxiliary_data(), needs to be undone - claimed_inner_product *= libra_challenge_inv / FF(1 << (log_circuit_size - 1)); - claimed_inner_product += zk_sumcheck_data.constant_term; - return claimed_inner_product; - } - static std::vector generate_random_vector(const size_t size) { std::vector multivariate_challenge(size); @@ -53,11 +31,11 @@ template class SmallSubgroupIPATest : public ::testing::Test { } }; -// Register the flavors for the test suite -using TestFlavors = ::testing::Types; +using TestFlavors = ::testing::Types; TYPED_TEST_SUITE(SmallSubgroupIPATest, TestFlavors); -// Implement the tests +// Check the correctness of the computation of the claimed inner product and various polynomials needed for the +// SmallSubgroupIPA. TYPED_TEST(SmallSubgroupIPATest, ProverComputationsCorrectness) { using ZKData = ZKSumcheckData; @@ -65,30 +43,34 @@ TYPED_TEST(SmallSubgroupIPATest, ProverComputationsCorrectness) using FF = typename TypeParam::FF; static constexpr size_t SUBGROUP_SIZE = TypeParam::SUBGROUP_SIZE; - std::shared_ptr ck; + using CK = typename TypeParam::CommitmentKey; + + // SmallSubgroupIPAProver requires at least CURVE::SUBGROUP_SIZE + 3 elements in the ck. + static constexpr size_t log_subgroup_size = static_cast(numeric::get_msb(SUBGROUP_SIZE)); + std::shared_ptr ck = + create_commitment_key(std::max(this->circuit_size, 1ULL << (log_subgroup_size + 1))); auto prover_transcript = TypeParam::Transcript::prover_init_empty(); - ck = CreateCommitmentKey(); ZKData zk_sumcheck_data(this->log_circuit_size, prover_transcript, ck); std::vector multivariate_challenge = this->generate_random_vector(this->log_circuit_size); - const FF claimed_inner_product = - this->compute_claimed_inner_product(zk_sumcheck_data, multivariate_challenge, this->log_circuit_size); + const FF claimed_inner_product = SmallSubgroupIPA::compute_claimed_inner_product( + zk_sumcheck_data, multivariate_challenge, this->log_circuit_size); SmallSubgroupIPA small_subgroup_ipa_prover = SmallSubgroupIPA(zk_sumcheck_data, multivariate_challenge, claimed_inner_product, prover_transcript, ck); - auto batched_polynomial = small_subgroup_ipa_prover.get_batched_polynomial(); - auto libra_concatenated_polynomial = small_subgroup_ipa_prover.get_witness_polynomials()[0]; - auto batched_quotient = small_subgroup_ipa_prover.get_witness_polynomials()[3]; - auto challenge_polynomial = small_subgroup_ipa_prover.get_challenge_polynomial(); + const Polynomial batched_polynomial = small_subgroup_ipa_prover.get_batched_polynomial(); + const Polynomial libra_concatenated_polynomial = small_subgroup_ipa_prover.get_witness_polynomials()[0]; + const Polynomial batched_quotient = small_subgroup_ipa_prover.get_witness_polynomials()[3]; + const Polynomial challenge_polynomial = small_subgroup_ipa_prover.get_challenge_polynomial(); // Check that claimed inner product coincides with the inner product of libra_concatenated_polynomial and // challenge_polynomial. Since libra_concatenated_polynomial is masked, we also check that masking does not affect // the evaluations over H FF inner_product = FF(0); - auto domain = zk_sumcheck_data.interpolation_domain; + const std::array domain = zk_sumcheck_data.interpolation_domain; for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { inner_product += challenge_polynomial.evaluate(domain[idx]) * libra_concatenated_polynomial.evaluate(domain[idx]); @@ -121,6 +103,9 @@ TYPED_TEST(SmallSubgroupIPATest, ProverComputationsCorrectness) EXPECT_EQ(quotient_is_correct, true); } +// Check the correctness of the evaluations of the challenge_polynomial, Lagrange first, and Lagrange last that the +// verifier has to compute on its own. Compare the values against the evaluations obtaned by applying Lagrange +// interpolation method used by Polynomial class constructor. TYPED_TEST(SmallSubgroupIPATest, VerifierEvaluations) { using FF = typename TypeParam::FF; @@ -169,6 +154,8 @@ TYPED_TEST(SmallSubgroupIPATest, VerifierEvaluations) EXPECT_EQ(lagrange_last, lagrange_last_monomial.evaluate(this->evaluation_challenge)); } +// Simulate the interaction between the prover and the verifier leading to the consistency check performed by the +// verifier. TYPED_TEST(SmallSubgroupIPATest, ProverAndVerifierSimple) { using FF = typename TypeParam::FF; @@ -176,22 +163,27 @@ TYPED_TEST(SmallSubgroupIPATest, ProverAndVerifierSimple) using Verifier = SmallSubgroupIPAVerifier; using Prover = SmallSubgroupIPAProver; using ZKData = ZKSumcheckData; + using CK = typename TypeParam::CommitmentKey; auto prover_transcript = TypeParam::Transcript::prover_init_empty(); - std::shared_ptr ck; - ck = CreateCommitmentKey(); + + // SmallSubgroupIPAProver requires at least CURVE::SUBGROUP_SIZE + 3 elements in the ck. + static constexpr size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); + std::shared_ptr ck = + create_commitment_key(std::max(this->circuit_size, 1ULL << (log_subgroup_size + 1))); ZKData zk_sumcheck_data(this->log_circuit_size, prover_transcript, ck); std::vector multivariate_challenge = this->generate_random_vector(CONST_PROOF_SIZE_LOG_N); const FF claimed_inner_product = - this->compute_claimed_inner_product(zk_sumcheck_data, multivariate_challenge, this->log_circuit_size); + Prover::compute_claimed_inner_product(zk_sumcheck_data, multivariate_challenge, this->log_circuit_size); Prover small_subgroup_ipa_prover = Prover(zk_sumcheck_data, multivariate_challenge, claimed_inner_product, prover_transcript, ck); - auto witness_polynomials = small_subgroup_ipa_prover.get_witness_polynomials(); + const std::array, NUM_LIBRA_EVALUATIONS> witness_polynomials = + small_subgroup_ipa_prover.get_witness_polynomials(); std::array libra_evaluations = { witness_polynomials[0].evaluate(this->evaluation_challenge), @@ -206,6 +198,7 @@ TYPED_TEST(SmallSubgroupIPATest, ProverAndVerifierSimple) EXPECT_TRUE(consistency_checked); } +// Check that consistency check fails when some of the prover's data is corrupted. TYPED_TEST(SmallSubgroupIPATest, ProverAndVerifierSimpleFailure) { using FF = typename TypeParam::FF; @@ -213,22 +206,27 @@ TYPED_TEST(SmallSubgroupIPATest, ProverAndVerifierSimpleFailure) using Verifier = SmallSubgroupIPAVerifier; using Prover = SmallSubgroupIPAProver; using ZKData = ZKSumcheckData; + using CK = typename TypeParam::CommitmentKey; auto prover_transcript = TypeParam::Transcript::prover_init_empty(); - std::shared_ptr ck; - ck = CreateCommitmentKey(); + + // SmallSubgroupIPAProver requires at least CURVE::SUBGROUP_SIZE + 3 elements in the ck. + static constexpr size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); + std::shared_ptr ck = + create_commitment_key(std::max(this->circuit_size, 1ULL << (log_subgroup_size + 1))); ZKData zk_sumcheck_data(this->log_circuit_size, prover_transcript, ck); std::vector multivariate_challenge = this->generate_random_vector(CONST_PROOF_SIZE_LOG_N); const FF claimed_inner_product = - this->compute_claimed_inner_product(zk_sumcheck_data, multivariate_challenge, this->log_circuit_size); + Prover::compute_claimed_inner_product(zk_sumcheck_data, multivariate_challenge, this->log_circuit_size); Prover small_subgroup_ipa_prover = Prover(zk_sumcheck_data, multivariate_challenge, claimed_inner_product, prover_transcript, ck); - auto witness_polynomials = small_subgroup_ipa_prover.get_witness_polynomials(); + std::array, NUM_LIBRA_EVALUATIONS> witness_polynomials = + small_subgroup_ipa_prover.get_witness_polynomials(); // Tamper with witness polynomials witness_polynomials[0].at(0) = FF::random_element(); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/instance_witness_generator.hpp similarity index 50% rename from barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp rename to barretenberg/cpp/src/barretenberg/commitment_schemes/utils/instance_witness_generator.hpp index 2bc8702d34d..f3b99924b9f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_instance_witness_generator.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/instance_witness_generator.hpp @@ -1,9 +1,9 @@ #pragma once +#include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/transcript/transcript.hpp" -#include "commitment_key.test.hpp" namespace bb { /** @@ -11,7 +11,7 @@ namespace bb { * * @tparam Curve */ -template struct PCSInstanceWitnessGenerator { +template struct InstanceWitnessGenerator { public: using CommitmentKey = bb::CommitmentKey; using Fr = typename Curve::ScalarField; @@ -19,22 +19,22 @@ template struct PCSInstanceWitnessGenerator { using Polynomial = bb::Polynomial; std::shared_ptr ck; - std::vector polynomials; - std::vector shiftable_polynomials; + std::vector unshifted_polynomials; + std::vector to_be_shifted_polynomials; std::vector const_size_mle_opening_point; std::vector unshifted_commitments; - std::vector shifted_commitments; + std::vector to_be_shifted_commitments; std::vector unshifted_evals; std::vector shifted_evals; - PCSInstanceWitnessGenerator(const size_t n, - const size_t num_polynomials, - const size_t num_shiftable, - const std::vector& mle_opening_point, - std::shared_ptr& commitment_key) + InstanceWitnessGenerator(const size_t n, + const size_t num_polynomials, + const size_t num_shiftable, + const std::vector& mle_opening_point, + std::shared_ptr& commitment_key) : ck(commitment_key) // Initialize the commitment key - , polynomials(num_polynomials) - , shiftable_polynomials(num_shiftable) + , unshifted_polynomials(num_polynomials) + , to_be_shifted_polynomials(num_shiftable) { construct_instance_and_witnesses(n, mle_opening_point); @@ -43,23 +43,23 @@ template struct PCSInstanceWitnessGenerator { void construct_instance_and_witnesses(size_t n, const std::vector& mle_opening_point) { - const size_t num_unshifted = polynomials.size() - shiftable_polynomials.size(); + const size_t num_unshifted = unshifted_polynomials.size() - to_be_shifted_polynomials.size(); - // Process polynomials that are not getting shifted + // Constructs polynomials that are not shifted for (size_t idx = 0; idx < num_unshifted; idx++) { - polynomials[idx] = Polynomial::random(n); - unshifted_commitments.push_back(ck->commit(polynomials[idx])); - unshifted_evals.push_back(polynomials[idx].evaluate_mle(mle_opening_point)); + unshifted_polynomials[idx] = Polynomial::random(n); + unshifted_commitments.push_back(ck->commit(unshifted_polynomials[idx])); + unshifted_evals.push_back(unshifted_polynomials[idx].evaluate_mle(mle_opening_point)); } - // Process polynomials that are getting shifted + // Constructs polynomials that are being shifted size_t idx = num_unshifted; - for (auto& poly : shiftable_polynomials) { + for (auto& poly : to_be_shifted_polynomials) { poly = Polynomial::random(n, /*shiftable*/ 1); - polynomials[idx] = poly; - auto comm = this->ck->commit(poly); + unshifted_polynomials[idx] = poly; + const Commitment comm = this->ck->commit(poly); unshifted_commitments.push_back(comm); - shifted_commitments.push_back(comm); + to_be_shifted_commitments.push_back(comm); unshifted_evals.push_back(poly.evaluate_mle(mle_opening_point)); shifted_evals.push_back(poly.evaluate_mle(mle_opening_point, true)); idx++; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_settings.hpp similarity index 87% rename from barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp rename to barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_settings.hpp index 26da1f7befa..5023d02a8f7 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/pcs_test_flavors.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_settings.hpp @@ -1,15 +1,15 @@ #pragma once +#include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/transcript/transcript.hpp" -#include "commitment_key.test.hpp" namespace bb { /** * @brief Mock Flavors to use ZKSumcheckData and SmallSubgroupIPAProver in the PCS tests. * */ -class TestBn254Flavor { +class BN254Settings { public: using Curve = curve::BN254; using CommitmentKey = bb::CommitmentKey; @@ -18,7 +18,7 @@ class TestBn254Flavor { static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; }; -class TestGrumpkinFlavor { +class GrumpkinSettings { public: using Curve = curve::Grumpkin; using CommitmentKey = bb::CommitmentKey;