From cee04ed75d1c7057f7935dbfdebba58b5401ebe2 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 4 Dec 2024 12:37:19 +0000 Subject: [PATCH 01/30] first steps --- .../commitment_schemes/ipa/ipa.test.cpp | 77 +++++++++++++++++++ .../commitment_schemes/kzg/kzg.test.cpp | 50 ++++++++++++ .../sumcheck/zk_sumcheck_data.hpp | 32 +++++++- 3 files changed, 157 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index 0abcb594b50..feb4973ed01 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -23,6 +23,83 @@ class IPATest : public CommitmentTest { TEST_F(IPATest, CommitOnManyZeroCoeffPolyWorks) { + + constexpr std::array factors_of_p_minus_1 = { { 2, + 9, // 3^2 + 13, + 29, + 67, + 229, + 311, + // 983, + 11003, + 405928799, + 11465965001 } }; + Fr num_random = Fr::random_element(); + Fr prod{ 1 }; + info(num_random); + for (size_t idx = 0; idx < 10; idx++) { + num_random = num_random.pow(factors_of_p_minus_1[idx]); + prod *= Fr{ factors_of_p_minus_1[idx] }; + } + auto gen = Fr{ 1 }; + + uint32_t limb_0 = 39; + uint32_t limb_1 = 1977533650; + uint32_t limb_2 = 4249115906; + uint32_t limb_3 = 2737479925; + uint32_t limb_4 = 2607196689; + + uint64_t two_to_16 = 1 << 16; + + auto prod_chunk = Fr{ 1 }; + if (num_random != Fr{ 1 }) { + info("generator", num_random); + Fr first_chunk = num_random.pow(limb_4); + + Fr second_chunk = num_random.pow(two_to_16); + second_chunk = second_chunk.pow(two_to_16); + second_chunk = second_chunk.pow(limb_3); + + Fr third_chunk = num_random.pow(two_to_16); + third_chunk = third_chunk.pow(two_to_16); + third_chunk = third_chunk.pow(two_to_16); + third_chunk = third_chunk.pow(two_to_16); + third_chunk = third_chunk.pow(limb_2); + + Fr fourth_chunk = num_random.pow(two_to_16); + fourth_chunk = fourth_chunk.pow(two_to_16); + fourth_chunk = fourth_chunk.pow(two_to_16); + fourth_chunk = fourth_chunk.pow(two_to_16); + fourth_chunk = fourth_chunk.pow(two_to_16); + fourth_chunk = fourth_chunk.pow(two_to_16); + fourth_chunk = fourth_chunk.pow(limb_1); + + Fr fifth_chunk = num_random.pow(two_to_16); + fifth_chunk = fifth_chunk.pow(two_to_16); + fifth_chunk = fifth_chunk.pow(two_to_16); + fifth_chunk = fifth_chunk.pow(two_to_16); + fifth_chunk = fifth_chunk.pow(two_to_16); + fifth_chunk = fifth_chunk.pow(two_to_16); + fifth_chunk = fifth_chunk.pow(two_to_16); + fifth_chunk = fifth_chunk.pow(two_to_16); + fifth_chunk = fifth_chunk.pow(limb_0); + + gen = first_chunk * second_chunk * third_chunk * fourth_chunk * fifth_chunk; + } + info("minus 1 ", Fr(-1)); + + // info(Fr{ 1 } + prod * Fr{ 29 * 13 }); + + if ((gen.pow(983) == Fr{ 1 }) && (gen.pow(982) != Fr{ 1 })) { + info("gen?", gen); + // for (size_t idx = 0; idx < 450; idx++) { + // info(gen.pow(idx)); + // } + } + + Fr root_of_unity = Fr::get_root_of_unity(2); + info("root of unity", root_of_unity); constexpr size_t n = 4; Polynomial p(n); for (size_t i = 0; i < n - 1; i++) { diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index a50c0a8919a..c4ba7152767 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -53,6 +53,56 @@ TYPED_TEST(KZGTest, SingleInLagrangeBasis) using KZG = KZG; using Fr = typename TypeParam::ScalarField; + std::array factors_of_p_minus_1 = { 1 << 28, 9, 983, 237073, 11003, 405928799, 1670836401704629 }; + + Fr num_random = Fr::random_element(); + Fr prod{ 1 }; + info(num_random); + for (size_t idx = 0; idx < 7; idx++) { + num_random = num_random.pow(factors_of_p_minus_1[idx]); + prod *= Fr{ factors_of_p_minus_1[idx] }; + } + auto gen = Fr{ 1 }; + uint32_t first_limb = 749095036; + uint32_t second_limb = 4241987048; + uint32_t fourth_limb = 1922377697; + + uint64_t two_to_16 = 1 << 16; + + auto prod_chunk = Fr{ 1 }; + if (num_random != Fr{ 1 }) { + info("generator", num_random); + Fr first_chunk = num_random.pow(fourth_limb); + Fr second_chunk = num_random.pow(two_to_16); + second_chunk = second_chunk.pow(two_to_16); + second_chunk = second_chunk.pow(second_limb); + + Fr third_chunk = num_random.pow(two_to_16); + third_chunk = third_chunk.pow(two_to_16); + third_chunk = third_chunk.pow(two_to_16); + third_chunk = third_chunk.pow(two_to_16); + third_chunk = third_chunk.pow(first_limb); + prod *= Fr(1 << 64) * Fr(first_limb) + Fr(1 << 32) * Fr(second_limb) + Fr(fourth_limb); + gen = first_chunk * second_chunk * third_chunk; + } + info("minus 1 ", Fr(-1)); + + // info(Fr{ 1 } + prod * Fr{ 29 * 13 }); + + if ((gen.pow(377) == Fr{ 1 }) && (gen.pow(376) != Fr{ 1 })) { + info("gen?", gen); + info("gen to 13*29? ", gen.pow(13 * 29)); + info("gen to 13? ", gen.pow(13)); + info("gen to 29? ", gen.pow(29)); + } + + // for (size_t idx = 0; idx < 7; idx++) { + // info("gen pow ", factors_of_p_minus_1[idx], " ", gen.pow(factors_of_p_minus_1[idx])); + // } + + // for (size_t idx = 0; idx < 1000; idx++) { + // info(idx, " ", gen.pow(idx)); + // } // create a random univariate (coefficients are in Lagrange basis) auto witness = bb::Univariate::get_random(); // define the interpolation domain diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index efe7f8d84be..673a355ddb9 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -20,6 +20,12 @@ template struct ZKSumcheckData { */ static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::MAX_PARTIAL_RELATION_LENGTH; + static constexpr FF grumpkin_subgroup_generator = + FF(uint256_t("00820eccfa880378746c1f015854b884a8ffa551ab51bf15cea2cecc5d3a8850")); + + static constexpr FF bn_254_subgroup_generator = + FF(uint256_t("0e4061303ba140794a3a2d8659909fd6ffb3dfdc290e4d9ca93bccd950f16404")); + /** * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials * \f$P_1,\ldots, P_N\f$ incremented by 1, i.e. it is equal \ref MAX_PARTIAL_RELATION_LENGTH @@ -33,7 +39,7 @@ template struct ZKSumcheckData { using LibraUnivariates = std::vector>; // Container for the evaluations of Libra Univariates that have to be proven. using ClaimedLibraEvaluations = std::vector; - + FF free_term{ 0 }; LibraUnivariates libra_univariates; LibraUnivariates libra_univariates_monomial; FF libra_scaling_factor{ 1 }; @@ -48,11 +54,33 @@ template struct ZKSumcheckData { ZKSumcheckData(const size_t multivariate_d, std::shared_ptr transcript, std::shared_ptr commitment_key = nullptr) - : libra_univariates(generate_libra_univariates(multivariate_d)) // Created in Lagrange basis for Sumcheck + : free_term(FF::random_element()) + , libra_univariates(generate_libra_univariates(multivariate_d)) // Created in Lagrange basis for Sumcheck , libra_univariates_monomial(transform_to_monomial(libra_univariates)) // Required for commiting and by Shplonk { + std::array coeffs_lagrange_subgroup; + coeffs_lagrange_subgroup[0] = free_term; + info(libra_univariates_monomial.size()); + for (size_t poly_idx = 0; poly_idx < libra_univariates_monomial.size(); poly_idx++) { + for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { + size_t idx_to_populate = 1 + poly_idx * LIBRA_UNIVARIATES_LENGTH + idx; + info(idx_to_populate); + coeffs_lagrange_subgroup[idx_to_populate] = libra_univariates_monomial[poly_idx].value_at(idx); + } + } + // 377--> Flavor::SubgroupSize + + // create evaluation domain using the generator + std::array subgroup_interpolation_domain; + for (size_t idx = 0; idx < 377; idx++) { + subgroup_interpolation_domain[idx] = bn_254_subgroup_generator.pow(idx); + } + + Polynomial polynomial_to_commit( + std::span(subgroup_interpolation_domain), std::span(coeffs_lagrange_subgroup), 377); + // If proving_key is provided, commit to libra_univariates if (commitment_key != nullptr) { size_t idx = 0; From b859440697409339079a7f9b8a76719da9bbc1e5 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 5 Dec 2024 12:07:04 +0000 Subject: [PATCH 02/30] wip: computing the batched big sum claim poly --- .../commitment_schemes/shplonk/shplemini.hpp | 18 +++--- .../src/barretenberg/sumcheck/sumcheck.hpp | 26 ++++----- .../barretenberg/sumcheck/sumcheck_output.hpp | 2 +- .../sumcheck/zk_sumcheck_data.hpp | 21 +++---- .../ultra_honk/decider_prover.cpp | 56 ++++++++++++++++++- .../ultra_honk/decider_verifier.cpp | 19 ++++--- 6 files changed, 98 insertions(+), 44 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 1f594bbd3eb..e70c853e4f3 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -29,12 +29,12 @@ template class ShpleminiProver_ { const std::shared_ptr>& commitment_key, const std::shared_ptr& transcript, const std::vector>& libra_univariates = {}, - const std::vector& libra_evaluations = {}, + const FF& libra_evaluation = {}, RefSpan concatenated_polynomials = {}, const std::vector>& groups_to_be_concatenated = {}) { // While Shplemini is not templated on Flavor, we derive ZK flag this way - const bool has_zk = !libra_evaluations.empty(); + const bool has_zk = !(libra_evaluation == FF{ 0 }); std::vector opening_claims = GeminiProver::prove(circuit_size, f_polynomials, g_polynomials, @@ -47,7 +47,7 @@ template class ShpleminiProver_ { // Create opening claims for Libra masking univariates std::vector libra_opening_claims; size_t idx = 0; - for (auto [libra_univariate, libra_evaluation] : zip_view(libra_univariates, libra_evaluations)) { + for (auto libra_univariate : libra_univariates) { OpeningClaim new_claim; new_claim.polynomial = Polynomial(libra_univariate); new_claim.opening_pair.challenge = multilinear_challenge[idx]; @@ -135,7 +135,7 @@ template class ShpleminiVerifier_ { const std::shared_ptr& transcript, const RepeatedCommitmentsData& repeated_commitments = {}, RefSpan libra_univariate_commitments = {}, - const std::vector& libra_univariate_evaluations = {}, + const Fr& libra_univariate_evaluation = Fr{ 0 }, const std::vector>& concatenation_group_commitments = {}, RefSpan concatenated_evaluations = {}) @@ -152,7 +152,7 @@ template class ShpleminiVerifier_ { Fr batched_evaluation = Fr{ 0 }; // While Shplemini is not templated on Flavor, we derive ZK flag this way - const bool has_zk = !libra_univariate_evaluations.empty(); + const bool has_zk = !(libra_univariate_evaluation == Fr{ 0 }); Commitment hiding_polynomial_commitment; if (has_zk) { hiding_polynomial_commitment = @@ -298,7 +298,7 @@ template class ShpleminiVerifier_ { add_zk_data(commitments, scalars, libra_univariate_commitments, - libra_univariate_evaluations, + libra_univariate_evaluation, multivariate_challenge, shplonk_batching_challenge, shplonk_evaluation_challenge); @@ -597,7 +597,7 @@ template class ShpleminiVerifier_ { static void add_zk_data(std::vector& commitments, std::vector& scalars, RefSpan libra_univariate_commitments, - const std::vector& libra_univariate_evaluations, + const Fr& libra_univariate_evaluation, const std::vector& multivariate_challenge, const Fr& shplonk_batching_challenge, const Fr& shplonk_evaluation_challenge) @@ -628,8 +628,8 @@ template class ShpleminiVerifier_ { } // add Libra commitments to the vector of commitments; compute corresponding scalars and the correction to // the constant term - for (const auto [libra_univariate_commitment, denominator, libra_univariate_evaluation] : - zip_view(libra_univariate_commitments, denominators, libra_univariate_evaluations)) { + for (const auto [libra_univariate_commitment, denominator] : + zip_view(libra_univariate_commitments, denominators)) { commitments.push_back(std::move(libra_univariate_commitment)); Fr scaling_factor = denominator * shplonk_challenge_power; scalars.push_back((-scaling_factor)); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 887730da472..fd0d574a5e8 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -258,12 +258,14 @@ template class SumcheckProver { } // The evaluations of Libra uninvariates at \f$ g_0(u_0), \ldots, g_{d-1} (u_{d-1}) \f$ are added to the // transcript. + FF libra_evaluation{ 0 }; + if constexpr (Flavor::HasZK) { - for (size_t idx = 0; idx < multivariate_d; idx++) { - const FF& libra_evaluation = zk_sumcheck_data.libra_evaluations[idx]; - std::string libra_evaluation_label = "Libra:evaluation_" + std::to_string(idx); - transcript->send_to_verifier(libra_evaluation_label, libra_evaluation); + for (auto& libra_eval : zk_sumcheck_data.libra_evaluations) { + libra_evaluation += libra_eval; } + std::string libra_evaluation_label = "Libra:final_evaluation"; + transcript->send_to_verifier(libra_evaluation_label, libra_evaluation); }; // Claimed evaluations of Prover polynomials are extracted and added to the transcript. When Flavor has ZK, the @@ -275,9 +277,7 @@ template class SumcheckProver { if constexpr (!Flavor::HasZK) { return SumcheckOutput{ multivariate_challenge, multivariate_evaluations }; } else { - return SumcheckOutput{ multivariate_challenge, - multivariate_evaluations, - zk_sumcheck_data.libra_evaluations }; + return SumcheckOutput{ multivariate_challenge, multivariate_evaluations, libra_evaluation }; } vinfo("finished sumcheck"); }; @@ -573,14 +573,12 @@ template class SumcheckVerifier { } } // Extract claimed evaluations of Libra univariates and compute their sum multiplied by the Libra challenge - ClaimedLibraEvaluations libra_evaluations(multivariate_d); + FF libra_evaluation{ 0 }; FF full_libra_purported_value = FF(0); if constexpr (Flavor::HasZK) { - for (size_t idx = 0; idx < multivariate_d; idx++) { - libra_evaluations[idx] = - transcript->template receive_from_prover("Libra:evaluation_" + std::to_string(idx)); - full_libra_purported_value += libra_evaluations[idx]; - }; + libra_evaluation = transcript->template receive_from_prover("Libra:final_evaluation"); + full_libra_purported_value += libra_evaluation; + info("sumcheck verifier ", full_libra_purported_value); full_libra_purported_value *= libra_challenge; }; // Final round @@ -606,7 +604,7 @@ template class SumcheckVerifier { if constexpr (!Flavor::HasZK) { return SumcheckOutput{ multivariate_challenge, purported_evaluations, verified }; } else { - return SumcheckOutput{ multivariate_challenge, purported_evaluations, libra_evaluations, verified }; + return SumcheckOutput{ multivariate_challenge, purported_evaluations, libra_evaluation, verified }; } }; }; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp index a18353446a2..3cafcb9b595 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp @@ -36,7 +36,7 @@ template struct SumcheckOutput claimed_libra_evaluations; + FF claimed_libra_evaluation; // Whether or not the evaluations of multilinear polynomials \f$ P_1, \ldots, P_N \f$ and final Sumcheck evaluation // have been confirmed std::optional verified = false; // Optional b/c this struct is shared by the Prover/Verifier diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 673a355ddb9..219fc7b8d7a 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -40,6 +40,9 @@ template struct ZKSumcheckData { // Container for the evaluations of Libra Univariates that have to be proven. using ClaimedLibraEvaluations = std::vector; FF free_term{ 0 }; + std::array interpolation_domain; + Polynomial polynomial_lagrange_form; + Polynomial concatenated; LibraUnivariates libra_univariates; LibraUnivariates libra_univariates_monomial; FF libra_scaling_factor{ 1 }; @@ -54,7 +57,7 @@ template struct ZKSumcheckData { ZKSumcheckData(const size_t multivariate_d, std::shared_ptr transcript, std::shared_ptr commitment_key = nullptr) - : free_term(FF::random_element()) + : free_term(FF(0)) , libra_univariates(generate_libra_univariates(multivariate_d)) // Created in Lagrange basis for Sumcheck , libra_univariates_monomial(transform_to_monomial(libra_univariates)) // Required for commiting and by Shplonk @@ -73,23 +76,21 @@ template struct ZKSumcheckData { // 377--> Flavor::SubgroupSize // create evaluation domain using the generator - std::array subgroup_interpolation_domain; for (size_t idx = 0; idx < 377; idx++) { - subgroup_interpolation_domain[idx] = bn_254_subgroup_generator.pow(idx); + interpolation_domain[idx] = bn_254_subgroup_generator.pow(idx); } + polynomial_lagrange_form = Polynomial(coeffs_lagrange_subgroup); Polynomial polynomial_to_commit( - std::span(subgroup_interpolation_domain), std::span(coeffs_lagrange_subgroup), 377); + std::span(interpolation_domain), std::span(coeffs_lagrange_subgroup), 377); // If proving_key is provided, commit to libra_univariates if (commitment_key != nullptr) { - size_t idx = 0; - for (auto& libra_univariate_monomial : libra_univariates_monomial) { - auto libra_commitment = commitment_key->commit(Polynomial(libra_univariate_monomial)); - transcript->template send_to_verifier("Libra:commitment_" + std::to_string(idx), libra_commitment); - idx++; - } + + auto libra_commitment = commitment_key->commit(polynomial_to_commit); + transcript->template send_to_verifier("Libra:commitment", libra_commitment); } + concatenated = polynomial_to_commit; // Compute the total sum of the Libra polynomials libra_scaling_factor = FF(1); FF libra_total_sum = compute_libra_total_sum(libra_univariates, libra_scaling_factor); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 2a27bd4b2f0..5f405bdee7c 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -64,6 +64,7 @@ template void DeciderProver_::execute_pcs_rounds( OpeningClaim prover_opening_claim; if constexpr (!Flavor::HasZK) { + prover_opening_claim = ShpleminiProver_::prove(proving_key->proving_key.circuit_size, proving_key->proving_key.polynomials.get_unshifted(), proving_key->proving_key.polynomials.get_to_be_shifted(), @@ -71,6 +72,59 @@ template void DeciderProver_::execute_pcs_rounds( ck, transcript); } else { + + size_t log_circuit_size = proving_key->proving_key.log_circuit_size; + Polynomial big_sum_polynomial(377); + Polynomial challenge_polynomial(377); + const size_t big_sum_size = 377; + // compute challenge polynomial F with coeffs (1, u_1, u_1^2,...., u_{d-1}^12) + for (size_t poly_idx = 0; poly_idx < log_circuit_size; poly_idx++) { + + for (size_t idx = 0; idx < Flavor::BATCHED_RELATION_PARTIAL_LENGTH; idx++) { + size_t current_idx = 1 + poly_idx * Flavor::BATCHED_RELATION_PARTIAL_LENGTH + idx; + info(current_idx); + challenge_polynomial.at(current_idx) = sumcheck_output.challenge[poly_idx].pow(idx); + } + } + // compute big sum polynomial, commit to it + big_sum_polynomial.at(0) = FF(0); + for (size_t idx = 1; idx < big_sum_size; idx++) { + size_t prev_idx = idx - 1; + big_sum_polynomial.at(idx) = + big_sum_polynomial.at(prev_idx) + + zk_sumcheck_data.polynomial_lagrange_form.at(prev_idx) * challenge_polynomial.at(prev_idx); + // info(big_sum_polynomial.at(idx)); + } + + Commitment big_sum_commitment = ck->commit(big_sum_polynomial); + transcript->template send_to_verifier("Libra:big_sum_commitment", big_sum_commitment); + + // compute the quotient polynomial C(x)/Z_H(X) + // C(x) = L_g(X) A(X) + (X-g) (A(gx) - (A(x) - F(x) G(x))) + L_{1}(x)(A(x) - s) + // A = big_sum polynomial, in Lagrange basis + // F = challenge polynomial, in Lagrange basis + // G = libra in Lagrange basis, i.e. polynomial_lagrange_form + + Polynomial batched_polynomial_lagrange(big_sum_size); + batched_polynomial_lagrange.at(0) = big_sum_polynomial.at(0); + batched_polynomial_lagrange.at(big_sum_size - 2) = big_sum_polynomial.at(big_sum_size - 2); + std::vector x_minus_g_coeffs(big_sum_size); + auto generator = zk_sumcheck_data.interpolation_domain[0]; + info(generator.pow(377)); + for (auto generator_power : zk_sumcheck_data.interpolation_domain) { + x_minus_g_coeffs.push_back(generator_power - generator); + } + + Polynomial x_minus_g = Polynomial(x_minus_g_coeffs); + info(x_minus_g.at(0)); + for (size_t idx = 1; idx < big_sum_size - 1; idx++) { + batched_polynomial_lagrange.at(idx) *= x_minus_g.at(idx); + batched_polynomial_lagrange.at(idx) *= + (big_sum_polynomial.at(idx + 1) - big_sum_polynomial.at(idx) - + challenge_polynomial.at(idx) * zk_sumcheck_data.polynomial_lagrange_form.at(idx)); + info(batched_polynomial_lagrange.at(idx)); + } + prover_opening_claim = ShpleminiProver_::prove(proving_key->proving_key.circuit_size, proving_key->proving_key.polynomials.get_unshifted(), proving_key->proving_key.polynomials.get_to_be_shifted(), @@ -78,7 +132,7 @@ template void DeciderProver_::execute_pcs_rounds( ck, transcript, zk_sumcheck_data.libra_univariates_monomial, - sumcheck_output.claimed_libra_evaluations); + sumcheck_output.claimed_libra_evaluation); } vinfo("executed multivariate-to-univariate reduction"); PCS::compute_opening_proof(ck, prover_opening_claim, transcript); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 22e93f76360..881c73f3d08 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -48,20 +48,21 @@ template bool DeciderVerifier_::verify() // For MegaZKFlavor: receive commitments to Libra masking polynomials std::vector libra_commitments = {}; if constexpr (Flavor::HasZK) { - for (size_t idx = 0; idx < static_cast(accumulator->verification_key->log_circuit_size); idx++) { - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:commitment_" + std::to_string(idx)); - libra_commitments.push_back(libra_commitment); - }; - } + Commitment libra_commitment = transcript->template receive_from_prover("Libra:commitment"); + libra_commitments.push_back(libra_commitment); + } SumcheckOutput sumcheck_output = sumcheck.verify(accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges); // For MegaZKFlavor: the sumcheck output contains claimed evaluations of the Libra polynomials - std::vector libra_evaluations = {}; + FF libra_evaluation{ 0 }; if constexpr (Flavor::HasZK) { - libra_evaluations = std::move(sumcheck_output.claimed_libra_evaluations); + libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); + Commitment libra_big_sum_commitment = + transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments.push_back(libra_big_sum_commitment); + info("big sum received"); } // If Sumcheck did not verify, return false @@ -81,7 +82,7 @@ template bool DeciderVerifier_::verify() transcript, Flavor::REPEATED_COMMITMENTS, RefVector(libra_commitments), - libra_evaluations); + libra_evaluation); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); bool verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); return sumcheck_output.verified.value() && verified; From ff70d41f76c20b9c0c1026af6797923f6a6d9c05 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Mon, 9 Dec 2024 09:43:19 +0000 Subject: [PATCH 03/30] wip wip assessing approaches --- .../commitment_schemes/ipa/ipa.test.cpp | 30 ++- .../commitment_schemes/kzg/kzg.test.cpp | 6 +- .../shplonk/shplemini.test.cpp | 216 +++++++++--------- .../src/barretenberg/eccvm/eccvm_prover.cpp | 2 +- .../sumcheck/zk_sumcheck_data.hpp | 34 ++- .../ultra_honk/decider_prover.cpp | 10 +- 6 files changed, 156 insertions(+), 142 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index feb4973ed01..996f92bca65 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -24,21 +24,20 @@ class IPATest : public CommitmentTest { TEST_F(IPATest, CommitOnManyZeroCoeffPolyWorks) { - constexpr std::array factors_of_p_minus_1 = { { 2, - 9, // 3^2 - 13, - 29, - 67, - 229, - 311, - // 983, - 11003, - 405928799, - 11465965001 } }; + constexpr std::array factors_of_p_minus_1 = { { 9, // 3^2 + 13, + 29, + 67, + 229, + 311, + // 983, + 11003, + 405928799, + 11465965001 } }; Fr num_random = Fr::random_element(); Fr prod{ 1 }; info(num_random); - for (size_t idx = 0; idx < 10; idx++) { + for (size_t idx = 0; idx < 9; idx++) { num_random = num_random.pow(factors_of_p_minus_1[idx]); prod *= Fr{ factors_of_p_minus_1[idx] }; } @@ -52,7 +51,6 @@ TEST_F(IPATest, CommitOnManyZeroCoeffPolyWorks) uint64_t two_to_16 = 1 << 16; - auto prod_chunk = Fr{ 1 }; if (num_random != Fr{ 1 }) { info("generator", num_random); Fr first_chunk = num_random.pow(limb_4); @@ -91,15 +89,15 @@ TEST_F(IPATest, CommitOnManyZeroCoeffPolyWorks) // info(Fr{ 1 } + prod * Fr{ 29 * 13 }); - if ((gen.pow(983) == Fr{ 1 }) && (gen.pow(982) != Fr{ 1 })) { + if ((gen.pow(983 * 2) == Fr{ 1 }) && (gen.pow(983) != Fr{ 1 }) && (gen.pow(2) != Fr{ 1 })) { info("gen?", gen); // for (size_t idx = 0; idx < 450; idx++) { // info(gen.pow(idx)); // } } - Fr root_of_unity = Fr::get_root_of_unity(2); - info("root of unity", root_of_unity); + // Fr root_of_unity = Fr::get_root_of_unity(2); + // info("root of unity", root_of_unity); constexpr size_t n = 4; Polynomial p(n); for (size_t i = 0; i < n - 1; i++) { diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index c4ba7152767..b6ce65343f9 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -53,7 +53,7 @@ TYPED_TEST(KZGTest, SingleInLagrangeBasis) using KZG = KZG; using Fr = typename TypeParam::ScalarField; - std::array factors_of_p_minus_1 = { 1 << 28, 9, 983, 237073, 11003, 405928799, 1670836401704629 }; + std::array factors_of_p_minus_1 = { 1 << 27, 9, 983, 237073, 11003, 405928799, 1670836401704629 }; Fr num_random = Fr::random_element(); Fr prod{ 1 }; @@ -69,7 +69,6 @@ TYPED_TEST(KZGTest, SingleInLagrangeBasis) uint64_t two_to_16 = 1 << 16; - auto prod_chunk = Fr{ 1 }; if (num_random != Fr{ 1 }) { info("generator", num_random); Fr first_chunk = num_random.pow(fourth_limb); @@ -89,11 +88,12 @@ TYPED_TEST(KZGTest, SingleInLagrangeBasis) // info(Fr{ 1 } + prod * Fr{ 29 * 13 }); - if ((gen.pow(377) == Fr{ 1 }) && (gen.pow(376) != Fr{ 1 })) { + if ((gen.pow(377 * 2) == Fr{ 1 }) && (gen.pow(377) != Fr{ 1 })) { info("gen?", gen); info("gen to 13*29? ", gen.pow(13 * 29)); info("gen to 13? ", gen.pow(13)); info("gen to 29? ", gen.pow(29)); + info("gen pow 2", gen.pow(2)); } // for (size_t idx = 0; idx < 7; idx++) { 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 e3537c00a75..7313c44f069 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -229,112 +229,112 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) * prover polynomials and their shifts. * */ -TYPED_TEST(ShpleminiTest, ShpleminiWithMaskingLibraUnivariates) -{ - using ShpleminiProver = ShpleminiProver_; - using ShpleminiVerifier = ShpleminiVerifier_; - using KZG = KZG; - using IPA = IPA; - using Fr = typename TypeParam::ScalarField; - using Commitment = typename TypeParam::AffineElement; - using Polynomial = typename bb::Polynomial; - - const size_t n = 16; - const size_t log_n = 4; - // In practice, the length of Libra univariates is equal to FLAVOR::BATCHED_RELATION_PARTIAL_LENGTH - const size_t LIBRA_UNIVARIATE_LENGTH = 12; - - std::array interpolation_domain; - for (size_t idx = 0; idx < LIBRA_UNIVARIATE_LENGTH; idx++) { - interpolation_domain[idx] = Fr(idx); - } - // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a - // random point. - auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' - auto poly1 = Polynomial::random(n); - auto poly2 = Polynomial::random(n, 1); - auto poly3 = Polynomial::random(n, 1); - auto poly4 = Polynomial::random(n); - - std::vector> libra_univariates; - std::vector libra_commitments; - std::vector libra_evaluations; - for (size_t idx = 0; idx < log_n; idx++) { - // generate random polynomial - Polynomial libra_polynomial = Polynomial::random(LIBRA_UNIVARIATE_LENGTH); - // create a univariate with the same coefficients (to store an array instead of a vector) - bb::Univariate libra_univariate; - for (size_t i = 0; i < LIBRA_UNIVARIATE_LENGTH; i++) { - libra_univariate.value_at(i) = libra_polynomial[i]; - } - libra_univariates.push_back(libra_univariate); - - // commit to libra polynomial and populate the vector of libra commitments - Commitment libra_commitment = this->commit(libra_polynomial); - libra_commitments.push_back(libra_commitment); - - // evaluate current libra univariate at the corresponding challenge and store the value in libra evaluations - libra_evaluations.push_back(libra_polynomial.evaluate(mle_opening_point[idx])); - } - - Commitment commitment1 = this->commit(poly1); - Commitment commitment2 = this->commit(poly2); - Commitment commitment3 = this->commit(poly3); - Commitment commitment4 = this->commit(poly4); - std::vector unshifted_commitments = { commitment1, commitment2, commitment3, commitment4 }; - std::vector shifted_commitments = { commitment2, commitment3 }; - auto eval1 = poly1.evaluate_mle(mle_opening_point); - auto eval2 = poly2.evaluate_mle(mle_opening_point); - auto eval3 = poly3.evaluate_mle(mle_opening_point); - auto eval4 = poly4.evaluate_mle(mle_opening_point); - auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); - auto eval3_shift = poly3.evaluate_mle(mle_opening_point, true); - - // Collect multilinear evaluations for input to prover - // std::vector multilinear_evaluations = { eval1, eval2, eval3, eval4, eval2_shift, eval3_shift }; - - auto prover_transcript = NativeTranscript::prover_init_empty(); - - // Run the full prover PCS protocol: - auto opening_claim = ShpleminiProver::prove(Fr{ n }, - RefArray{ poly1, poly2, poly3, poly4 }, - RefArray{ poly2, poly3 }, - mle_opening_point, - this->ck(), - prover_transcript, - libra_univariates, - libra_evaluations); - 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); - } - - // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation) - - auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); - - // Gemini verifier output: - // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 - auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(n, - RefVector(unshifted_commitments), - RefVector(shifted_commitments), - RefArray{ eval1, eval2, eval3, eval4 }, - RefArray{ eval2_shift, eval3_shift }, - mle_opening_point, - this->vk()->get_g1_identity(), - verifier_transcript, - {}, - RefVector(libra_commitments), - libra_evaluations); - - 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); - } -} +// TYPED_TEST(ShpleminiTest, ShpleminiWithMaskingLibraUnivariates) +// { +// using ShpleminiProver = ShpleminiProver_; +// using ShpleminiVerifier = ShpleminiVerifier_; +// using KZG = KZG; +// using IPA = IPA; +// using Fr = typename TypeParam::ScalarField; +// using Commitment = typename TypeParam::AffineElement; +// using Polynomial = typename bb::Polynomial; + +// const size_t n = 16; +// const size_t log_n = 4; +// // In practice, the length of Libra univariates is equal to FLAVOR::BATCHED_RELATION_PARTIAL_LENGTH +// const size_t LIBRA_UNIVARIATE_LENGTH = 12; + +// std::array interpolation_domain; +// for (size_t idx = 0; idx < LIBRA_UNIVARIATE_LENGTH; idx++) { +// interpolation_domain[idx] = Fr(idx); +// } +// // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a +// // random point. +// auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' +// auto poly1 = Polynomial::random(n); +// auto poly2 = Polynomial::random(n, 1); +// auto poly3 = Polynomial::random(n, 1); +// auto poly4 = Polynomial::random(n); + +// std::vector> libra_univariates; +// std::vector libra_commitments; +// std::vector libra_evaluations; +// for (size_t idx = 0; idx < log_n; idx++) { +// // generate random polynomial +// Polynomial libra_polynomial = Polynomial::random(LIBRA_UNIVARIATE_LENGTH); +// // create a univariate with the same coefficients (to store an array instead of a vector) +// bb::Univariate libra_univariate; +// for (size_t i = 0; i < LIBRA_UNIVARIATE_LENGTH; i++) { +// libra_univariate.value_at(i) = libra_polynomial[i]; +// } +// libra_univariates.push_back(libra_univariate); + +// // commit to libra polynomial and populate the vector of libra commitments +// Commitment libra_commitment = this->commit(libra_polynomial); +// libra_commitments.push_back(libra_commitment); + +// // evaluate current libra univariate at the corresponding challenge and store the value in libra evaluations +// libra_evaluations.push_back(libra_polynomial.evaluate(mle_opening_point[idx])); +// } + +// Commitment commitment1 = this->commit(poly1); +// Commitment commitment2 = this->commit(poly2); +// Commitment commitment3 = this->commit(poly3); +// Commitment commitment4 = this->commit(poly4); +// std::vector unshifted_commitments = { commitment1, commitment2, commitment3, commitment4 }; +// std::vector shifted_commitments = { commitment2, commitment3 }; +// auto eval1 = poly1.evaluate_mle(mle_opening_point); +// auto eval2 = poly2.evaluate_mle(mle_opening_point); +// auto eval3 = poly3.evaluate_mle(mle_opening_point); +// auto eval4 = poly4.evaluate_mle(mle_opening_point); +// auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); +// auto eval3_shift = poly3.evaluate_mle(mle_opening_point, true); + +// // Collect multilinear evaluations for input to prover +// // std::vector multilinear_evaluations = { eval1, eval2, eval3, eval4, eval2_shift, eval3_shift }; + +// auto prover_transcript = NativeTranscript::prover_init_empty(); + +// // Run the full prover PCS protocol: +// auto opening_claim = ShpleminiProver::prove(Fr{ n }, +// RefArray{ poly1, poly2, poly3, poly4 }, +// RefArray{ poly2, poly3 }, +// mle_opening_point, +// this->ck(), +// prover_transcript, +// libra_univariates, +// libra_evaluations); +// 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); +// } + +// // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation) + +// auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + +// // Gemini verifier output: +// // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 +// auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(n, +// RefVector(unshifted_commitments), +// RefVector(shifted_commitments), +// RefArray{ eval1, eval2, eval3, eval4 }, +// RefArray{ eval2_shift, eval3_shift }, +// mle_opening_point, +// this->vk()->get_g1_identity(), +// verifier_transcript, +// {}, +// RefVector(libra_commitments), +// libra_evaluations); + +// 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 diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index d95a2f01ad7..c8935459e1c 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -132,7 +132,7 @@ void ECCVMProver::execute_pcs_rounds() key->commitment_key, transcript, zk_sumcheck_data.libra_univariates_monomial, - sumcheck_output.claimed_libra_evaluations); + sumcheck_output.claimed_libra_evaluation); // Get the challenge at which we evaluate all transcript polynomials as univariates evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 219fc7b8d7a..8477b67f46b 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -3,6 +3,7 @@ #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include +#include #include #include @@ -21,11 +22,10 @@ template struct ZKSumcheckData { static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::MAX_PARTIAL_RELATION_LENGTH; static constexpr FF grumpkin_subgroup_generator = - FF(uint256_t("00820eccfa880378746c1f015854b884a8ffa551ab51bf15cea2cecc5d3a8850")); + FF(uint256_t("0x2b2f46dc50fb64ea8c28e6331d1371f38ef09ba413bd8287a6b182575351c177")); static constexpr FF bn_254_subgroup_generator = - FF(uint256_t("0e4061303ba140794a3a2d8659909fd6ffb3dfdc290e4d9ca93bccd950f16404")); - + FF(uint256_t("0x02d284e1a6dba4be658d3106583135d5dfc3b35febe48ca10ee1371cb197541e")); /** * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials * \f$P_1,\ldots, P_N\f$ incremented by 1, i.e. it is equal \ref MAX_PARTIAL_RELATION_LENGTH @@ -39,8 +39,11 @@ template struct ZKSumcheckData { using LibraUnivariates = std::vector>; // Container for the evaluations of Libra Univariates that have to be proven. using ClaimedLibraEvaluations = std::vector; + FF free_term{ 0 }; - std::array interpolation_domain; + std::array interpolation_domain; + // to compute product in lagrange basis + std::array extended_domain; Polynomial polynomial_lagrange_form; Polynomial concatenated; LibraUnivariates libra_univariates; @@ -62,8 +65,9 @@ template struct ZKSumcheckData { , libra_univariates_monomial(transform_to_monomial(libra_univariates)) // Required for commiting and by Shplonk { - - std::array coeffs_lagrange_subgroup; + info(bn_254_subgroup_generator.pow(2 * 29 * 13)); + info(grumpkin_subgroup_generator.pow(2 * 983)); + std::array coeffs_lagrange_subgroup; coeffs_lagrange_subgroup[0] = free_term; info(libra_univariates_monomial.size()); for (size_t poly_idx = 0; poly_idx < libra_univariates_monomial.size(); poly_idx++) { @@ -76,14 +80,26 @@ template struct ZKSumcheckData { // 377--> Flavor::SubgroupSize // create evaluation domain using the generator - for (size_t idx = 0; idx < 377; idx++) { - interpolation_domain[idx] = bn_254_subgroup_generator.pow(idx); + for (size_t idx = 0; idx < 1000; idx++) { + interpolation_domain[idx] = bn_254_subgroup_generator.pow(2 * idx); + // extended_domain[idx] = bn_254_subgroup_generator.pow(2 * idx); + // size_t wrapping_idx = 2 * 377 + idx; + // extended_domain[wrapping_idx] = bn_254_subgroup_generator.pow(idx); } polynomial_lagrange_form = Polynomial(coeffs_lagrange_subgroup); + using namespace std::chrono; + + auto total_time = 0.0; + auto start = high_resolution_clock::now(); + Polynomial polynomial_to_commit( - std::span(interpolation_domain), std::span(coeffs_lagrange_subgroup), 377); + std::span(interpolation_domain), std::span(coeffs_lagrange_subgroup), 1000); + + auto end = high_resolution_clock::now(); + total_time += duration(end - start).count(); + info("total time", total_time); // If proving_key is provided, commit to libra_univariates if (commitment_key != nullptr) { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 5f405bdee7c..c3a12b71bf7 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -77,7 +77,7 @@ template void DeciderProver_::execute_pcs_rounds( Polynomial big_sum_polynomial(377); Polynomial challenge_polynomial(377); const size_t big_sum_size = 377; - // compute challenge polynomial F with coeffs (1, u_1, u_1^2,...., u_{d-1}^12) + // compute challenge polynomial F with coeffs (1, 1, u_1, u_1^2,...., u_{d-1}^12) for (size_t poly_idx = 0; poly_idx < log_circuit_size; poly_idx++) { for (size_t idx = 0; idx < Flavor::BATCHED_RELATION_PARTIAL_LENGTH; idx++) { @@ -86,6 +86,7 @@ template void DeciderProver_::execute_pcs_rounds( challenge_polynomial.at(current_idx) = sumcheck_output.challenge[poly_idx].pow(idx); } } + // compute big sum polynomial, commit to it big_sum_polynomial.at(0) = FF(0); for (size_t idx = 1; idx < big_sum_size; idx++) { @@ -118,10 +119,9 @@ template void DeciderProver_::execute_pcs_rounds( Polynomial x_minus_g = Polynomial(x_minus_g_coeffs); info(x_minus_g.at(0)); for (size_t idx = 1; idx < big_sum_size - 1; idx++) { - batched_polynomial_lagrange.at(idx) *= x_minus_g.at(idx); - batched_polynomial_lagrange.at(idx) *= - (big_sum_polynomial.at(idx + 1) - big_sum_polynomial.at(idx) - - challenge_polynomial.at(idx) * zk_sumcheck_data.polynomial_lagrange_form.at(idx)); + batched_polynomial_lagrange.at(idx) = + x_minus_g.at(idx) * (big_sum_polynomial.at(idx + 1) - big_sum_polynomial.at(idx) - + challenge_polynomial.at(idx) * zk_sumcheck_data.polynomial_lagrange_form.at(idx)); info(batched_polynomial_lagrange.at(idx)); } From 109ac5f12c3c523d5e6ca3a3064ae1a30bf26c06 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 11 Dec 2024 11:44:14 +0000 Subject: [PATCH 04/30] enhanced zk sumcheck data struct with prover's methods, fixed subgroup generators --- .../commitment_schemes/ipa/ipa.test.cpp | 27 +- .../commitment_schemes/kzg/kzg.test.cpp | 10 +- .../sumcheck/zk_sumcheck_data.hpp | 300 +++++++++++++++--- .../ultra_honk/decider_prover.cpp | 71 ++--- 4 files changed, 293 insertions(+), 115 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index 996f92bca65..c5e76dd32d3 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -24,20 +24,21 @@ class IPATest : public CommitmentTest { TEST_F(IPATest, CommitOnManyZeroCoeffPolyWorks) { - constexpr std::array factors_of_p_minus_1 = { { 9, // 3^2 - 13, - 29, - 67, - 229, - 311, - // 983, - 11003, - 405928799, - 11465965001 } }; + constexpr std::array factors_of_p_minus_1 = { { 2, + 3, // 3^2 + 13, + // 29, + 67, + 229, + 311, + 983, + 11003, + 405928799, + 11465965001 } }; Fr num_random = Fr::random_element(); Fr prod{ 1 }; info(num_random); - for (size_t idx = 0; idx < 9; idx++) { + for (size_t idx = 0; idx < 10; idx++) { num_random = num_random.pow(factors_of_p_minus_1[idx]); prod *= Fr{ factors_of_p_minus_1[idx] }; } @@ -89,8 +90,8 @@ TEST_F(IPATest, CommitOnManyZeroCoeffPolyWorks) // info(Fr{ 1 } + prod * Fr{ 29 * 13 }); - if ((gen.pow(983 * 2) == Fr{ 1 }) && (gen.pow(983) != Fr{ 1 }) && (gen.pow(2) != Fr{ 1 })) { - info("gen?", gen); + if ((gen.pow(29 * 3) == Fr{ 1 }) && (gen.pow(29) != Fr{ 1 }) && (gen.pow(3) != Fr{ 1 })) { + info("gen? ", gen); // for (size_t idx = 0; idx < 450; idx++) { // info(gen.pow(idx)); // } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index b6ce65343f9..e1c3d401f2e 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -53,12 +53,12 @@ TYPED_TEST(KZGTest, SingleInLagrangeBasis) using KZG = KZG; using Fr = typename TypeParam::ScalarField; - std::array factors_of_p_minus_1 = { 1 << 27, 9, 983, 237073, 11003, 405928799, 1670836401704629 }; + std::array factors_of_p_minus_1 = { 1 << 28, 3, 13, 983, 237073, 11003, 405928799, 1670836401704629 }; Fr num_random = Fr::random_element(); Fr prod{ 1 }; info(num_random); - for (size_t idx = 0; idx < 7; idx++) { + for (size_t idx = 0; idx < 8; idx++) { num_random = num_random.pow(factors_of_p_minus_1[idx]); prod *= Fr{ factors_of_p_minus_1[idx] }; } @@ -88,12 +88,8 @@ TYPED_TEST(KZGTest, SingleInLagrangeBasis) // info(Fr{ 1 } + prod * Fr{ 29 * 13 }); - if ((gen.pow(377 * 2) == Fr{ 1 }) && (gen.pow(377) != Fr{ 1 })) { + if ((gen.pow(29 * 3) == Fr{ 1 }) && (gen.pow(29) != Fr{ 1 }) && (gen.pow(3) != Fr{ 1 })) { info("gen?", gen); - info("gen to 13*29? ", gen.pow(13 * 29)); - info("gen to 13? ", gen.pow(13)); - info("gen to 29? ", gen.pow(29)); - info("gen pow 2", gen.pow(2)); } // for (size_t idx = 0; idx < 7; idx++) { diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 8477b67f46b..0102ecf2c75 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -21,11 +21,17 @@ template struct ZKSumcheckData { */ static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::MAX_PARTIAL_RELATION_LENGTH; + static constexpr size_t SUBGROUP_SIZE = 87; + + static constexpr size_t BATCHED_POLYNOMIAL_LENGTH = 2 * SUBGROUP_SIZE + 2; + + static constexpr size_t QUOTIENT_LENGTH = SUBGROUP_SIZE + 2; + static constexpr FF grumpkin_subgroup_generator = - FF(uint256_t("0x2b2f46dc50fb64ea8c28e6331d1371f38ef09ba413bd8287a6b182575351c177")); + FF(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); static constexpr FF bn_254_subgroup_generator = - FF(uint256_t("0x02d284e1a6dba4be658d3106583135d5dfc3b35febe48ca10ee1371cb197541e")); + FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); /** * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials * \f$P_1,\ldots, P_N\f$ incremented by 1, i.e. it is equal \ref MAX_PARTIAL_RELATION_LENGTH @@ -34,24 +40,33 @@ template struct ZKSumcheckData { static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH; // The size of the LibraUnivariates. We ensure that they do not take extra space when Flavor runs non-ZK Sumcheck. // The size of the LibraUnivariates. We ensure that they do not take extra space when Flavor runs non-ZK Sumcheck. - static constexpr size_t LIBRA_UNIVARIATES_LENGTH = Flavor::HasZK ? Flavor::BATCHED_RELATION_PARTIAL_LENGTH : 0; + static constexpr size_t LIBRA_UNIVARIATES_LENGTH = Flavor::HasZK ? 3 : 0; // Container for the Libra Univariates. Their number depends on the size of the circuit. using LibraUnivariates = std::vector>; // Container for the evaluations of Libra Univariates that have to be proven. using ClaimedLibraEvaluations = std::vector; FF free_term{ 0 }; - std::array interpolation_domain; + std::array interpolation_domain; // to compute product in lagrange basis - std::array extended_domain; - Polynomial polynomial_lagrange_form; - Polynomial concatenated; + Polynomial libra_concatenated_lagrange_form; + Polynomial libra_concatenated_monomial_form; + + Polynomial challenge_polynomial; + Polynomial challenge_polynomial_lagrange; + + Polynomial big_sum_polynomial; + Polynomial batched_polynomial; + Polynomial batched_quotient; + LibraUnivariates libra_univariates; + size_t log_circuit_size; LibraUnivariates libra_univariates_monomial; FF libra_scaling_factor{ 1 }; FF libra_challenge; FF libra_running_sum; ClaimedLibraEvaluations libra_evaluations; + std::array big_sum_lagrange_coeffs; // Default constructor ZKSumcheckData() = default; @@ -61,52 +76,22 @@ template struct ZKSumcheckData { std::shared_ptr transcript, std::shared_ptr commitment_key = nullptr) : free_term(FF(0)) - , libra_univariates(generate_libra_univariates(multivariate_d)) // Created in Lagrange basis for Sumcheck + , libra_concatenated_monomial_form(SUBGROUP_SIZE + 2) // includes masking + , challenge_polynomial(SUBGROUP_SIZE) // public polynomial + , big_sum_polynomial(SUBGROUP_SIZE + 2) // includes masking + , batched_polynomial(BATCHED_POLYNOMIAL_LENGTH) // batched polynomial, input to shplonk prover + , batched_quotient(QUOTIENT_LENGTH) // quotient of the batched polynomial by Z_H(X) = X^87 - 1 + , libra_univariates(generate_libra_univariates(multivariate_d)) // random univariates of degree 2 + , log_circuit_size(multivariate_d) , libra_univariates_monomial(transform_to_monomial(libra_univariates)) // Required for commiting and by Shplonk { - info(bn_254_subgroup_generator.pow(2 * 29 * 13)); - info(grumpkin_subgroup_generator.pow(2 * 983)); - std::array coeffs_lagrange_subgroup; - coeffs_lagrange_subgroup[0] = free_term; - info(libra_univariates_monomial.size()); - for (size_t poly_idx = 0; poly_idx < libra_univariates_monomial.size(); poly_idx++) { - for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { - size_t idx_to_populate = 1 + poly_idx * LIBRA_UNIVARIATES_LENGTH + idx; - info(idx_to_populate); - coeffs_lagrange_subgroup[idx_to_populate] = libra_univariates_monomial[poly_idx].value_at(idx); - } - } - // 377--> Flavor::SubgroupSize - - // create evaluation domain using the generator - for (size_t idx = 0; idx < 1000; idx++) { - interpolation_domain[idx] = bn_254_subgroup_generator.pow(2 * idx); - // extended_domain[idx] = bn_254_subgroup_generator.pow(2 * idx); - // size_t wrapping_idx = 2 * 377 + idx; - // extended_domain[wrapping_idx] = bn_254_subgroup_generator.pow(idx); - } - - polynomial_lagrange_form = Polynomial(coeffs_lagrange_subgroup); - using namespace std::chrono; - - auto total_time = 0.0; - auto start = high_resolution_clock::now(); - - Polynomial polynomial_to_commit( - std::span(interpolation_domain), std::span(coeffs_lagrange_subgroup), 1000); - - auto end = high_resolution_clock::now(); - total_time += duration(end - start).count(); - - info("total time", total_time); - // If proving_key is provided, commit to libra_univariates + compute_concatenated_libra_polynomial(); + // If proving_key is provided, commit to the concatenated and masked libra polynomial if (commitment_key != nullptr) { - - auto libra_commitment = commitment_key->commit(polynomial_to_commit); + auto libra_commitment = commitment_key->commit(libra_concatenated_monomial_form); transcript->template send_to_verifier("Libra:commitment", libra_commitment); } - concatenated = polynomial_to_commit; // Compute the total sum of the Libra polynomials libra_scaling_factor = FF(1); FF libra_total_sum = compute_libra_total_sum(libra_univariates, libra_scaling_factor); @@ -221,5 +206,226 @@ template struct ZKSumcheckData { libra_running_sum += -libra_univariates[0].value_at(0) - libra_univariates[0].value_at(1); libra_running_sum *= FF(1) / FF(2); } + + // compute concatenated libra polynomial in lagrange basis, transform to monomial, add masking term Z_H(m_0 + m_1 X) + void compute_concatenated_libra_polynomial() + { + // info(bn_254_subgroup_generator.pow(29 * 3)); + // info(grumpkin_subgroup_generator.pow(2 * 983)); + std::array coeffs_lagrange_subgroup; + coeffs_lagrange_subgroup[0] = free_term; + + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + coeffs_lagrange_subgroup[idx] = FF{ 0 }; + } + // info(libra_univariates_monomial.size()); + for (size_t poly_idx = 0; poly_idx < libra_univariates_monomial.size(); poly_idx++) { + for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { + size_t idx_to_populate = 1 + poly_idx * LIBRA_UNIVARIATES_LENGTH + idx; + // info(idx_to_populate); + coeffs_lagrange_subgroup[idx_to_populate] = libra_univariates_monomial[poly_idx].value_at(idx); + } + } + // 377--> Flavor::SubgroupSize + + // create evaluation domain using the generator + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + interpolation_domain[idx] = bn_254_subgroup_generator.pow(idx); + } + + libra_concatenated_lagrange_form = Polynomial(coeffs_lagrange_subgroup); + + bb::Univariate masking_scalars = bb::Univariate::zero(); + + // using namespace std::chrono; + + // auto total_time = 0.0; + // auto start = high_resolution_clock::now(); + + auto libra_concatenated_monomial_form_unmasked = + Polynomial(interpolation_domain, coeffs_lagrange_subgroup, SUBGROUP_SIZE); + + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + libra_concatenated_monomial_form.at(idx) = libra_concatenated_monomial_form_unmasked.at(idx); + } + + libra_concatenated_monomial_form.at(0) -= masking_scalars.value_at(0); + libra_concatenated_monomial_form.at(1) += masking_scalars.value_at(1); + + libra_concatenated_monomial_form.at(SUBGROUP_SIZE) -= masking_scalars.value_at(0); + libra_concatenated_monomial_form.at(SUBGROUP_SIZE + 1) += masking_scalars.value_at(1); + // auto end = high_resolution_clock::now(); + // total_time += duration(end - start).count(); + + // info("total time", total_time); + } + void setup_challenge_polynomial(const std::vector multivariate_challenge) + { + std::array coeffs_lagrange_basis; + coeffs_lagrange_basis[0] = FF(1); + + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + coeffs_lagrange_basis[idx] = FF{ 0 }; + } + + for (size_t idx_poly = 0; idx_poly < log_circuit_size; idx_poly++) { + for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { + size_t current_idx = 1 + LIBRA_UNIVARIATES_LENGTH * idx_poly + idx; + coeffs_lagrange_basis[current_idx] = multivariate_challenge[idx_poly].pow(idx); + } + } + challenge_polynomial_lagrange = Polynomial(coeffs_lagrange_basis); + challenge_polynomial = Polynomial(interpolation_domain, coeffs_lagrange_basis, SUBGROUP_SIZE); + + info(challenge_polynomial.evaluate(interpolation_domain[84])); + // info(multivariate_challenge[84]); + } + + void setup_big_sum_polynomial() + { + big_sum_lagrange_coeffs[0] = 0; + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + size_t prev_idx = idx - 1; + big_sum_lagrange_coeffs[idx] = + big_sum_lagrange_coeffs[prev_idx] + + challenge_polynomial_lagrange.at(prev_idx) * libra_concatenated_lagrange_form.at(prev_idx); + // info("big sum coeff lagrange ", idx, " ", big_sum_lagrange_coeffs[idx]); + }; + + // get unmasked in monomial + auto big_sum_polynomial_unmasked = Polynomial(interpolation_domain, big_sum_lagrange_coeffs, SUBGROUP_SIZE); + // mask + bb::Univariate masking_scalars = bb::Univariate::zero(); + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + big_sum_polynomial.at(idx) = big_sum_polynomial_unmasked.at(idx); + } + big_sum_polynomial.at(0) -= masking_scalars.value_at(0); + big_sum_polynomial.at(1) += masking_scalars.value_at(1); + + big_sum_polynomial.at(SUBGROUP_SIZE) -= masking_scalars.value_at(0); + big_sum_polynomial.at(SUBGROUP_SIZE + 1) += masking_scalars.value_at(1); + info("should be libra opening claim", big_sum_polynomial.evaluate(interpolation_domain[80])); + }; + + void compute_batched_polynomial() + { + // compute shifted big sum + std::array shifted_big_sum_lagrange; + + shifted_big_sum_lagrange[SUBGROUP_SIZE - 1] = + big_sum_lagrange_coeffs[0] - big_sum_lagrange_coeffs[SUBGROUP_SIZE - 1]; + for (size_t idx = 0; idx < SUBGROUP_SIZE - 1; idx++) { + shifted_big_sum_lagrange[idx] = big_sum_lagrange_coeffs[idx + 1] - big_sum_lagrange_coeffs[idx]; + } + auto shifted_big_sum = Polynomial(interpolation_domain, shifted_big_sum_lagrange, SUBGROUP_SIZE); + + // compute lagrange first in monomial basis + std::array lagrange_coeffs; + lagrange_coeffs[0] = FF(1); + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + lagrange_coeffs[idx] = FF(0); + } + // todo: turn into constexpr + Polynomial lagrange_first_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + + // compute lagrange last in monomial basis + // todo: turn into constexpr + lagrange_coeffs[0] = 0; + lagrange_coeffs[SUBGROUP_SIZE - 1] = 1; + + Polynomial lagrange_last_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + + // compute the negated product of challenge_polynomial and libra_concatenated_monomial_form + Polynomial result(BATCHED_POLYNOMIAL_LENGTH); + + for (size_t i = 0; i < libra_concatenated_monomial_form.size(); ++i) { + for (size_t j = 0; j < challenge_polynomial.size(); ++j) { + result.at(i + j) -= libra_concatenated_monomial_form.at(i) * challenge_polynomial.at(j); + } + } + info("======"); + info(-result.evaluate(interpolation_domain[SUBGROUP_SIZE - 1])); + info(libra_concatenated_lagrange_form.at(SUBGROUP_SIZE - 1) * + challenge_polynomial_lagrange.at(SUBGROUP_SIZE - 1)); + info("======"); + + // compute (A(gX) - A(X) - F(X) * G(X)) + for (size_t idx = 0; idx < shifted_big_sum.size(); idx++) { + result.at(idx) += shifted_big_sum.at(idx); + } + info("eval of A(gX) - A(X) - F(X) G(X) at last element ", + result.evaluate(interpolation_domain[SUBGROUP_SIZE - 1])); + // mutiply by X-g + // shift by X + for (size_t idx = result.size() - 1; idx > 0; idx--) { + result.at(idx) = result.at(idx - 1); + } + result.at(0) = FF(0); + + // subtract g from result to get (X- 1)(A(gX) - A(X) - F(X) * G(X)) + for (size_t idx = 0; idx < result.size() - 1; idx++) { + result.at(idx) -= result.at(idx + 1) * interpolation_domain[SUBGROUP_SIZE - 1]; + } + + info("======"); + info(result.evaluate(interpolation_domain[4])); + info(big_sum_lagrange_coeffs[5] - big_sum_lagrange_coeffs[4] - + libra_concatenated_lagrange_form.at(4) * challenge_polynomial_lagrange.at(4)); + info("======"); + + lagrange_first_monomial += lagrange_last_monomial; + + // info("lagrange first plus last ", lagrange_first_monomial.evaluate(interpolation_domain[5])); + for (size_t i = 0; i < big_sum_polynomial.size(); ++i) { + for (size_t j = 0; j < lagrange_first_monomial.size(); ++j) { + result.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); + } + } + info("(lagrange first + last ) A(X) + () at 1 ", result.evaluate(interpolation_domain[SUBGROUP_SIZE - 1])); + + info("======"); + info(result.evaluate(interpolation_domain[4])); + info(big_sum_lagrange_coeffs[5] - big_sum_lagrange_coeffs[4] - + libra_concatenated_lagrange_form.at(4) * challenge_polynomial_lagrange.at(4)); + info("======"); + FF claimed_sum = big_sum_lagrange_coeffs[SUBGROUP_SIZE - 2]; + info(claimed_sum); + info("====="); + for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { + result.at(idx) -= lagrange_last_monomial.at(idx) * claimed_sum; + } + + // for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + // info(result.evaluate(interpolation_domain[idx])); + // } + info(" ===="); + batched_polynomial = result; + } + // Compute the quotient by Z_H = X^87 - 1 + void compute_batched_quotient() + { + auto remainder = batched_polynomial; + for (size_t idx = BATCHED_POLYNOMIAL_LENGTH - 1; idx > QUOTIENT_LENGTH; idx--) { + batched_quotient.at(idx - SUBGROUP_SIZE) = remainder.at(idx); + remainder.at(idx - SUBGROUP_SIZE) += remainder.at(idx); + } + + Polynomial result(BATCHED_POLYNOMIAL_LENGTH); + std::array Z_H; + for (size_t idx = 0; idx < SUBGROUP_SIZE + 1; idx++) { + Z_H[idx] = FF(0); + } + Z_H[0] = FF(-1); + Z_H[SUBGROUP_SIZE] = FF(1); + for (size_t i = 0; i < batched_quotient.size(); ++i) { + for (size_t j = 0; j < Z_H.size(); ++j) { + result.at(i + j) += batched_quotient.at(i) * Z_H[j]; + } + } + // for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + // info("product", result.evaluate(interpolation_domain[idx])); + // // info("source poly", batched_polynomial.at(idx)); + // } + } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index c3a12b71bf7..3322491ef7e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -73,58 +73,33 @@ template void DeciderProver_::execute_pcs_rounds( transcript); } else { - size_t log_circuit_size = proving_key->proving_key.log_circuit_size; - Polynomial big_sum_polynomial(377); - Polynomial challenge_polynomial(377); - const size_t big_sum_size = 377; - // compute challenge polynomial F with coeffs (1, 1, u_1, u_1^2,...., u_{d-1}^12) - for (size_t poly_idx = 0; poly_idx < log_circuit_size; poly_idx++) { - - for (size_t idx = 0; idx < Flavor::BATCHED_RELATION_PARTIAL_LENGTH; idx++) { - size_t current_idx = 1 + poly_idx * Flavor::BATCHED_RELATION_PARTIAL_LENGTH + idx; - info(current_idx); - challenge_polynomial.at(current_idx) = sumcheck_output.challenge[poly_idx].pow(idx); - } + // size_t log_circuit_size = proving_key->proving_key.log_circuit_size; + zk_sumcheck_data.setup_challenge_polynomial(sumcheck_output.challenge); + + // compute masked big sum polynomial, commit to it + zk_sumcheck_data.setup_big_sum_polynomial(); + Commitment big_sum_commitment = ck->commit(zk_sumcheck_data.big_sum_polynomial); + using namespace std::chrono; + + auto total_time = 0.0; + auto start = high_resolution_clock::now(); + + zk_sumcheck_data.compute_batched_polynomial(); + zk_sumcheck_data.compute_batched_quotient(); + auto end = high_resolution_clock::now(); + total_time += duration(end - start).count(); + + info("total time", total_time); + FF claim = FF(0); + size_t idx = 0; + for (auto poly : zk_sumcheck_data.libra_univariates_monomial) { + claim += poly.evaluate(sumcheck_output.challenge[idx]); + idx++; } - // compute big sum polynomial, commit to it - big_sum_polynomial.at(0) = FF(0); - for (size_t idx = 1; idx < big_sum_size; idx++) { - size_t prev_idx = idx - 1; - big_sum_polynomial.at(idx) = - big_sum_polynomial.at(prev_idx) + - zk_sumcheck_data.polynomial_lagrange_form.at(prev_idx) * challenge_polynomial.at(prev_idx); - // info(big_sum_polynomial.at(idx)); - } - - Commitment big_sum_commitment = ck->commit(big_sum_polynomial); + info("actual claim ", claim); transcript->template send_to_verifier("Libra:big_sum_commitment", big_sum_commitment); - // compute the quotient polynomial C(x)/Z_H(X) - // C(x) = L_g(X) A(X) + (X-g) (A(gx) - (A(x) - F(x) G(x))) + L_{1}(x)(A(x) - s) - // A = big_sum polynomial, in Lagrange basis - // F = challenge polynomial, in Lagrange basis - // G = libra in Lagrange basis, i.e. polynomial_lagrange_form - - Polynomial batched_polynomial_lagrange(big_sum_size); - batched_polynomial_lagrange.at(0) = big_sum_polynomial.at(0); - batched_polynomial_lagrange.at(big_sum_size - 2) = big_sum_polynomial.at(big_sum_size - 2); - std::vector x_minus_g_coeffs(big_sum_size); - auto generator = zk_sumcheck_data.interpolation_domain[0]; - info(generator.pow(377)); - for (auto generator_power : zk_sumcheck_data.interpolation_domain) { - x_minus_g_coeffs.push_back(generator_power - generator); - } - - Polynomial x_minus_g = Polynomial(x_minus_g_coeffs); - info(x_minus_g.at(0)); - for (size_t idx = 1; idx < big_sum_size - 1; idx++) { - batched_polynomial_lagrange.at(idx) = - x_minus_g.at(idx) * (big_sum_polynomial.at(idx + 1) - big_sum_polynomial.at(idx) - - challenge_polynomial.at(idx) * zk_sumcheck_data.polynomial_lagrange_form.at(idx)); - info(batched_polynomial_lagrange.at(idx)); - } - prover_opening_claim = ShpleminiProver_::prove(proving_key->proving_key.circuit_size, proving_key->proving_key.polynomials.get_unshifted(), proving_key->proving_key.polynomials.get_to_be_shifted(), From e9862289ad4cf1bd9f8f36afece39d3eeb8e6eff Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 11 Dec 2024 17:22:50 +0000 Subject: [PATCH 05/30] verifies, important pieces missing --- .../commitment_schemes/gemini/gemini_impl.hpp | 1 + .../commitment_schemes/shplonk/shplemini.hpp | 124 ++++++++++++------ .../commitment_schemes/shplonk/shplonk.hpp | 7 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 2 + .../barretenberg/sumcheck/sumcheck_round.hpp | 7 +- .../sumcheck/zk_sumcheck_data.hpp | 2 +- .../ultra_honk/decider_prover.cpp | 25 ++-- .../ultra_honk/decider_verifier.cpp | 10 +- 8 files changed, 119 insertions(+), 59 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..11a996425bb 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -123,6 +123,7 @@ std::vector::Claim> GeminiProver_::prove( } } const Fr r_challenge = transcript->template get_challenge("Gemini:r"); + info("gemini r! ", r_challenge); 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.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index e70c853e4f3..20e9dab94ed 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -28,7 +28,7 @@ template class ShpleminiProver_ { std::span multilinear_challenge, const std::shared_ptr>& commitment_key, const std::shared_ptr& transcript, - const std::vector>& libra_univariates = {}, + const std::array& libra_polynomials = {}, const FF& libra_evaluation = {}, RefSpan concatenated_polynomials = {}, const std::vector>& groups_to_be_concatenated = {}) @@ -46,15 +46,35 @@ template class ShpleminiProver_ { has_zk); // Create opening claims for Libra masking univariates std::vector libra_opening_claims; - size_t idx = 0; - for (auto libra_univariate : libra_univariates) { - OpeningClaim new_claim; - new_claim.polynomial = Polynomial(libra_univariate); - new_claim.opening_pair.challenge = multilinear_challenge[idx]; - new_claim.opening_pair.evaluation = libra_evaluation; - libra_opening_claims.push_back(new_claim); - idx++; - } + static constexpr FF bn_254_subgroup_generator = + FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + const auto gemini_r = opening_claims[0].opening_pair.challenge; + OpeningClaim new_claim; + + new_claim.polynomial = libra_polynomials[0]; + new_claim.opening_pair.challenge = gemini_r; + new_claim.opening_pair.evaluation = libra_polynomials[0].evaluate(gemini_r); + transcript->send_to_verifier("Libra:concatenation_eval", new_claim.opening_pair.evaluation); + libra_opening_claims.push_back(new_claim); + + new_claim.polynomial = libra_polynomials[1]; + new_claim.opening_pair.challenge = bn_254_subgroup_generator * gemini_r; + new_claim.opening_pair.evaluation = libra_polynomials[1].evaluate(new_claim.opening_pair.challenge); + transcript->send_to_verifier("Libra:shifted_big_sum_eval", new_claim.opening_pair.evaluation); + libra_opening_claims.push_back(new_claim); + + new_claim.polynomial = libra_polynomials[1]; + new_claim.opening_pair.challenge = gemini_r; + new_claim.opening_pair.evaluation = libra_polynomials[1].evaluate(gemini_r); + transcript->send_to_verifier("Libra:big_sum_eval", new_claim.opening_pair.evaluation); + libra_opening_claims.push_back(new_claim); + + new_claim.polynomial = libra_polynomials[2]; + new_claim.opening_pair.challenge = gemini_r; + new_claim.opening_pair.evaluation = libra_polynomials[2].evaluate(gemini_r); + transcript->send_to_verifier("Libra:quotient_eval", new_claim.opening_pair.evaluation); + libra_opening_claims.push_back(new_claim); + const OpeningClaim batched_claim = ShplonkProver::prove(commitment_key, opening_claims, transcript, libra_opening_claims); return batched_claim; @@ -121,6 +141,10 @@ template class ShpleminiVerifier_ { using VK = VerifierCommitmentKey; using ShplonkVerifier = ShplonkVerifier_; using GeminiVerifier = GeminiVerifier_; + static constexpr Fr bn_254_subgroup_generator = + Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + static constexpr Fr grumpkin_subgroup_generator = + Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); public: template @@ -134,7 +158,7 @@ template class ShpleminiVerifier_ { const Commitment& g1_identity, const std::shared_ptr& transcript, const RepeatedCommitmentsData& repeated_commitments = {}, - RefSpan libra_univariate_commitments = {}, + std::vector libra_commitments = {}, const Fr& libra_univariate_evaluation = Fr{ 0 }, const std::vector>& concatenation_group_commitments = {}, RefSpan concatenated_evaluations = {}) @@ -170,15 +194,25 @@ template class ShpleminiVerifier_ { // - Get Gemini evaluation challenge for Aᵢ, i = 0, … , d−1 const Fr gemini_evaluation_challenge = transcript->template get_challenge("Gemini:r"); + if (has_zk) { + } + // - Get evaluations (A₀(−r), A₁(−r²), ... , Aₙ₋₁(−r²⁽ⁿ⁻¹⁾)) const std::vector gemini_evaluations = GeminiVerifier::get_gemini_evaluations(log_circuit_size, transcript); // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size const std::vector gemini_eval_challenge_powers = gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, CONST_PROOF_SIZE_LOG_N); + std::array libra_evaluations; + libra_evaluations[0] = transcript->template receive_from_prover("Libra:concatenation_eval"); + libra_evaluations[1] = transcript->template receive_from_prover("Libra:shifted_big_sum_eval"); + libra_evaluations[2] = transcript->template receive_from_prover("Libra:big_sum_eval"); + libra_evaluations[3] = transcript->template receive_from_prover("Libra:quotient_eval"); + // Process Shplonk transcript data: // - Get Shplonk batching challenge const Fr shplonk_batching_challenge = transcript->template get_challenge("Shplonk:nu"); + info("shplonk nu verifier ", shplonk_batching_challenge); // - Get the quotient commitment for the Shplonk batching of Gemini opening claims const auto Q_commitment = transcript->template receive_from_prover("Shplonk:Q"); @@ -297,9 +331,9 @@ template class ShpleminiVerifier_ { if (has_zk) { add_zk_data(commitments, scalars, - libra_univariate_commitments, - libra_univariate_evaluation, - multivariate_challenge, + libra_commitments, + libra_evaluations, + gemini_evaluation_challenge, shplonk_batching_challenge, shplonk_evaluation_challenge); } @@ -588,7 +622,7 @@ template class ShpleminiVerifier_ { * * @param commitments * @param scalars - * @param libra_univariate_commitments + * @param libra_commitments * @param libra_univariate_evaluations * @param multivariate_challenge * @param shplonk_batching_challenge @@ -596,9 +630,9 @@ template class ShpleminiVerifier_ { */ static void add_zk_data(std::vector& commitments, std::vector& scalars, - RefSpan libra_univariate_commitments, - const Fr& libra_univariate_evaluation, - const std::vector& multivariate_challenge, + std::vector libra_commitments, + std::array libra_evaluations, + const Fr& gemini_evaluation_challenge, const Fr& shplonk_batching_challenge, const Fr& shplonk_evaluation_challenge) @@ -613,30 +647,44 @@ template class ShpleminiVerifier_ { Fr& constant_term = scalars.back(); // compute shplonk denominators and batch invert them std::vector denominators; - size_t num_libra_univariates = libra_univariate_commitments.size(); - // compute Shplonk denominators and invert them - for (size_t idx = 0; idx < num_libra_univariates; idx++) { - if constexpr (Curve::is_stdlib_type) { - denominators.push_back(Fr(1) / (shplonk_evaluation_challenge - multivariate_challenge[idx])); - } else { - denominators.push_back(shplonk_evaluation_challenge - multivariate_challenge[idx]); - } - }; - if constexpr (!Curve::is_stdlib_type) { - Fr::batch_invert(denominators); + denominators.push_back(Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge)); + denominators.push_back( + Fr(1) / (shplonk_evaluation_challenge - bn_254_subgroup_generator * gemini_evaluation_challenge)); + denominators.push_back(denominators[0]); + denominators.push_back(denominators[0]); + + for (auto denom : denominators) { + info("verifier denom", denom); } // add Libra commitments to the vector of commitments; compute corresponding scalars and the correction to // the constant term - for (const auto [libra_univariate_commitment, denominator] : - zip_view(libra_univariate_commitments, denominators)) { - commitments.push_back(std::move(libra_univariate_commitment)); - Fr scaling_factor = denominator * shplonk_challenge_power; - scalars.push_back((-scaling_factor)); - shplonk_challenge_power *= shplonk_batching_challenge; - // update the constant term of the Shplonk batched claim - constant_term += scaling_factor * libra_univariate_evaluation; - } + commitments.push_back(libra_commitments[0]); + Fr scaling_factor = denominators[0] * shplonk_challenge_power; + info(shplonk_challenge_power); + scalars.push_back(-scaling_factor); + shplonk_challenge_power *= shplonk_batching_challenge; + // update the constant term of the Shplonk batched claim + constant_term += scaling_factor * libra_evaluations[0]; + + commitments.push_back(libra_commitments[1]); + scaling_factor = denominators[1] * shplonk_challenge_power; + // scalars.push_back((-scaling_factor)); + shplonk_challenge_power *= shplonk_batching_challenge; + // update the constant term of the Shplonk batched claim + constant_term += scaling_factor * libra_evaluations[1]; + scaling_factor += denominators[2] * shplonk_challenge_power; + scalars.push_back(-scaling_factor); + constant_term += denominators[2] * shplonk_challenge_power * libra_evaluations[2]; + + shplonk_challenge_power *= shplonk_batching_challenge; + + commitments.push_back(libra_commitments[2]); + scaling_factor = denominators[3] * shplonk_challenge_power; + scalars.push_back(-scaling_factor); + shplonk_challenge_power *= shplonk_batching_challenge; + // update the constant term of the Shplonk batched claim + constant_term += scaling_factor * libra_evaluations[3]; } }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp index 5e90d4a00bb..ad65bda04a5 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp @@ -44,10 +44,11 @@ template class ShplonkProver_ { std::span> libra_opening_claims) { // Find n, the maximum size of all polynomials fⱼ(X) - size_t max_poly_size{ 0 }; + size_t max_poly_size{ 87 * 2 + 2 }; for (const auto& claim : opening_claims) { max_poly_size = std::max(max_poly_size, claim.polynomial.size()); } + // Q(X) = ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) Polynomial Q(max_poly_size); Polynomial tmp(max_poly_size); @@ -146,7 +147,10 @@ template class ShplonkProver_ { // Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ ) tmp = claim.polynomial; tmp.at(0) = tmp[0] - claim.opening_pair.evaluation; + info("prover denom", inverse_vanishing_evals[idx]); + Fr scaling_factor = current_nu * inverse_vanishing_evals[idx]; // = νʲ / (z − xⱼ ) + info("current nu ", current_nu); // Add the claim quotient to the batched quotient polynomial G.add_scaled(tmp, -scaling_factor); @@ -173,6 +177,7 @@ template class ShplonkProver_ { std::span> libra_opening_claims = {}) { const Fr nu = transcript->template get_challenge("Shplonk:nu"); + info("prover nu ", nu); auto batched_quotient = compute_batched_quotient(opening_claims, nu, libra_opening_claims); auto batched_quotient_commitment = commitment_key->commit(batched_quotient); transcript->send_to_verifier("Shplonk:Q", batched_quotient_commitment); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index fd0d574a5e8..f8e6e4be042 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -564,6 +564,7 @@ template class SumcheckVerifier { if (round_idx < multivariate_d) { bool checked = round.check_sum(round_univariate); verified = verified && checked; + info("verified round ", round_idx, " ", verified); multivariate_challenge.emplace_back(round_challenge); round.compute_next_target_sum(round_univariate, round_challenge); gate_separators.partially_evaluate(round_challenge); @@ -600,6 +601,7 @@ template class SumcheckVerifier { final_check = (full_honk_purported_value == round.target_total_sum); } verified = final_check && verified; + info("last verification ", verified); // For ZK Flavors: the evaluations of Libra univariates are included in the Sumcheck Output if constexpr (!Flavor::HasZK) { return SumcheckOutput{ multivariate_challenge, purported_evaluations, verified }; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 758797b8bcc..add7d93c78f 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -293,15 +293,16 @@ template class SumcheckProverRound { static SumcheckRoundUnivariate compute_libra_round_univariate(ZKSumcheckData zk_sumcheck_data, size_t round_idx) { - SumcheckRoundUnivariate libra_round_univariate; + bb::Univariate libra_round_univariate; + info("inside sumcheck round: ", libra_round_univariate.size()); // select the i'th column of Libra book-keeping table const auto& current_column = zk_sumcheck_data.libra_univariates[round_idx]; // the evaluation of Libra round univariate at k=0...D are equal to \f$\texttt{libra_univariates}_{i}(k)\f$ // corrected by the Libra running sum - for (size_t idx = 0; idx < BATCHED_RELATION_PARTIAL_LENGTH; ++idx) { + for (size_t idx = 0; idx < libra_round_univariate.size(); ++idx) { libra_round_univariate.value_at(idx) = current_column.value_at(idx) + zk_sumcheck_data.libra_running_sum; }; - return libra_round_univariate; + return libra_round_univariate.template extend_to(); } private: diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 0102ecf2c75..ca779b4d029 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -90,7 +90,7 @@ template struct ZKSumcheckData { // If proving_key is provided, commit to the concatenated and masked libra polynomial if (commitment_key != nullptr) { auto libra_commitment = commitment_key->commit(libra_concatenated_monomial_form); - transcript->template send_to_verifier("Libra:commitment", libra_commitment); + transcript->template send_to_verifier("Libra:concatenation_commitment", libra_commitment); } // Compute the total sum of the Libra polynomials libra_scaling_factor = FF(1); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 3322491ef7e..81b4d6dba61 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -72,6 +72,10 @@ template void DeciderProver_::execute_pcs_rounds( ck, transcript); } else { + using namespace std::chrono; + + auto total_time = 0.0; + auto start = high_resolution_clock::now(); // size_t log_circuit_size = proving_key->proving_key.log_circuit_size; zk_sumcheck_data.setup_challenge_polynomial(sumcheck_output.challenge); @@ -79,26 +83,21 @@ template void DeciderProver_::execute_pcs_rounds( // compute masked big sum polynomial, commit to it zk_sumcheck_data.setup_big_sum_polynomial(); Commitment big_sum_commitment = ck->commit(zk_sumcheck_data.big_sum_polynomial); - using namespace std::chrono; - - auto total_time = 0.0; - auto start = high_resolution_clock::now(); + transcript->template send_to_verifier("Libra:big_sum_commitment", big_sum_commitment); zk_sumcheck_data.compute_batched_polynomial(); zk_sumcheck_data.compute_batched_quotient(); + Commitment libra_batched_quotient = ck->commit(zk_sumcheck_data.batched_quotient); + transcript->template send_to_verifier("Libra:quotient_commitment", libra_batched_quotient); + auto end = high_resolution_clock::now(); total_time += duration(end - start).count(); info("total time", total_time); - FF claim = FF(0); - size_t idx = 0; - for (auto poly : zk_sumcheck_data.libra_univariates_monomial) { - claim += poly.evaluate(sumcheck_output.challenge[idx]); - idx++; - } - info("actual claim ", claim); - transcript->template send_to_verifier("Libra:big_sum_commitment", big_sum_commitment); + std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, + zk_sumcheck_data.big_sum_polynomial, + zk_sumcheck_data.batched_quotient }; prover_opening_claim = ShpleminiProver_::prove(proving_key->proving_key.circuit_size, proving_key->proving_key.polynomials.get_unshifted(), @@ -106,7 +105,7 @@ template void DeciderProver_::execute_pcs_rounds( sumcheck_output.challenge, ck, transcript, - zk_sumcheck_data.libra_univariates_monomial, + libra_polynomials, sumcheck_output.claimed_libra_evaluation); } vinfo("executed multivariate-to-univariate reduction"); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 881c73f3d08..8d57f30eabe 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -49,7 +49,8 @@ template bool DeciderVerifier_::verify() std::vector libra_commitments = {}; if constexpr (Flavor::HasZK) { - Commitment libra_commitment = transcript->template receive_from_prover("Libra:commitment"); + Commitment libra_commitment = + transcript->template receive_from_prover("Libra:concatenation_commitment"); libra_commitments.push_back(libra_commitment); } SumcheckOutput sumcheck_output = @@ -62,7 +63,10 @@ template bool DeciderVerifier_::verify() Commitment libra_big_sum_commitment = transcript->template receive_from_prover("Libra:big_sum_commitment"); libra_commitments.push_back(libra_big_sum_commitment); - info("big sum received"); + Commitment libra_quotient_commitment = + transcript->template receive_from_prover("Libra:quotient_commitment"); + libra_commitments.push_back(libra_quotient_commitment); + // info("big sum received"); } // If Sumcheck did not verify, return false @@ -81,7 +85,7 @@ template bool DeciderVerifier_::verify() Commitment::one(), transcript, Flavor::REPEATED_COMMITMENTS, - RefVector(libra_commitments), + libra_commitments, libra_evaluation); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); bool verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); From 77c386abd190db36f8f01618aea8cc0f3da00cec Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 12 Dec 2024 19:45:31 +0000 Subject: [PATCH 06/30] consistency check added --- .../commitment_schemes/shplonk/shplemini.hpp | 229 +++++++++++++----- .../commitment_schemes/shplonk/shplonk.hpp | 2 +- .../ultra_recursive_verifier.cpp | 25 +- .../stdlib_circuit_builders/mock_circuits.hpp | 2 +- .../sumcheck/zk_sumcheck_data.hpp | 43 ++-- 5 files changed, 208 insertions(+), 93 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 20e9dab94ed..5de86cbb9e6 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -5,6 +5,7 @@ #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" #include "barretenberg/commitment_schemes/verification_key.hpp" #include "barretenberg/flavor/repeated_commitments_data.hpp" +#include "barretenberg/sumcheck/zk_sumcheck_data.hpp" #include "barretenberg/transcript/transcript.hpp" namespace bb { @@ -50,30 +51,31 @@ template class ShpleminiProver_ { FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); const auto gemini_r = opening_claims[0].opening_pair.challenge; OpeningClaim new_claim; - - new_claim.polynomial = libra_polynomials[0]; - new_claim.opening_pair.challenge = gemini_r; - new_claim.opening_pair.evaluation = libra_polynomials[0].evaluate(gemini_r); - transcript->send_to_verifier("Libra:concatenation_eval", new_claim.opening_pair.evaluation); - libra_opening_claims.push_back(new_claim); - - new_claim.polynomial = libra_polynomials[1]; - new_claim.opening_pair.challenge = bn_254_subgroup_generator * gemini_r; - new_claim.opening_pair.evaluation = libra_polynomials[1].evaluate(new_claim.opening_pair.challenge); - transcript->send_to_verifier("Libra:shifted_big_sum_eval", new_claim.opening_pair.evaluation); - libra_opening_claims.push_back(new_claim); - - new_claim.polynomial = libra_polynomials[1]; - new_claim.opening_pair.challenge = gemini_r; - new_claim.opening_pair.evaluation = libra_polynomials[1].evaluate(gemini_r); - transcript->send_to_verifier("Libra:big_sum_eval", new_claim.opening_pair.evaluation); - libra_opening_claims.push_back(new_claim); - - new_claim.polynomial = libra_polynomials[2]; - new_claim.opening_pair.challenge = gemini_r; - new_claim.opening_pair.evaluation = libra_polynomials[2].evaluate(gemini_r); - transcript->send_to_verifier("Libra:quotient_eval", new_claim.opening_pair.evaluation); - libra_opening_claims.push_back(new_claim); + if (has_zk) { + new_claim.polynomial = libra_polynomials[0]; + new_claim.opening_pair.challenge = gemini_r; + new_claim.opening_pair.evaluation = libra_polynomials[0].evaluate(gemini_r); + transcript->send_to_verifier("Libra:concatenation_eval", new_claim.opening_pair.evaluation); + libra_opening_claims.push_back(new_claim); + + new_claim.polynomial = libra_polynomials[1]; + new_claim.opening_pair.challenge = bn_254_subgroup_generator * gemini_r; + new_claim.opening_pair.evaluation = libra_polynomials[1].evaluate(new_claim.opening_pair.challenge); + transcript->send_to_verifier("Libra:shifted_big_sum_eval", new_claim.opening_pair.evaluation); + libra_opening_claims.push_back(new_claim); + + new_claim.polynomial = libra_polynomials[1]; + new_claim.opening_pair.challenge = gemini_r; + new_claim.opening_pair.evaluation = libra_polynomials[1].evaluate(gemini_r); + transcript->send_to_verifier("Libra:big_sum_eval", new_claim.opening_pair.evaluation); + libra_opening_claims.push_back(new_claim); + + new_claim.polynomial = libra_polynomials[2]; + new_claim.opening_pair.challenge = gemini_r; + new_claim.opening_pair.evaluation = libra_polynomials[2].evaluate(gemini_r); + transcript->send_to_verifier("Libra:quotient_eval", new_claim.opening_pair.evaluation); + libra_opening_claims.push_back(new_claim); + } const OpeningClaim batched_claim = ShplonkProver::prove(commitment_key, opening_claims, transcript, libra_opening_claims); @@ -141,10 +143,9 @@ template class ShpleminiVerifier_ { using VK = VerifierCommitmentKey; using ShplonkVerifier = ShplonkVerifier_; using GeminiVerifier = GeminiVerifier_; - static constexpr Fr bn_254_subgroup_generator = - Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); - static constexpr Fr grumpkin_subgroup_generator = - Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); + + // static const Fr grumpkin_subgroup_generator = + // Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); public: template @@ -164,9 +165,9 @@ template class ShpleminiVerifier_ { RefSpan concatenated_evaluations = {}) { - // Extract log_circuit_size size_t log_circuit_size{ 0 }; + info(libra_univariate_evaluation); if constexpr (Curve::is_stdlib_type) { log_circuit_size = numeric::get_msb(static_cast(N.get_value())); } else { @@ -176,7 +177,7 @@ template class ShpleminiVerifier_ { Fr batched_evaluation = Fr{ 0 }; // While Shplemini is not templated on Flavor, we derive ZK flag this way - const bool has_zk = !(libra_univariate_evaluation == Fr{ 0 }); + const bool has_zk = !(libra_commitments.empty()); Commitment hiding_polynomial_commitment; if (has_zk) { hiding_polynomial_commitment = @@ -194,9 +195,6 @@ template class ShpleminiVerifier_ { // - Get Gemini evaluation challenge for Aᵢ, i = 0, … , d−1 const Fr gemini_evaluation_challenge = transcript->template get_challenge("Gemini:r"); - if (has_zk) { - } - // - Get evaluations (A₀(−r), A₁(−r²), ... , Aₙ₋₁(−r²⁽ⁿ⁻¹⁾)) const std::vector gemini_evaluations = GeminiVerifier::get_gemini_evaluations(log_circuit_size, transcript); // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size @@ -204,10 +202,12 @@ template class ShpleminiVerifier_ { gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, CONST_PROOF_SIZE_LOG_N); std::array libra_evaluations; - libra_evaluations[0] = transcript->template receive_from_prover("Libra:concatenation_eval"); - libra_evaluations[1] = transcript->template receive_from_prover("Libra:shifted_big_sum_eval"); - libra_evaluations[2] = transcript->template receive_from_prover("Libra:big_sum_eval"); - libra_evaluations[3] = transcript->template receive_from_prover("Libra:quotient_eval"); + if (has_zk) { + libra_evaluations[0] = transcript->template receive_from_prover("Libra:concatenation_eval"); + libra_evaluations[1] = transcript->template receive_from_prover("Libra:shifted_big_sum_eval"); + libra_evaluations[2] = transcript->template receive_from_prover("Libra:big_sum_eval"); + libra_evaluations[3] = transcript->template receive_from_prover("Libra:quotient_eval"); + } // Process Shplonk transcript data: // - Get Shplonk batching challenge @@ -216,8 +216,8 @@ template class ShpleminiVerifier_ { // - Get the quotient commitment for the Shplonk batching of Gemini opening claims const auto Q_commitment = transcript->template receive_from_prover("Shplonk:Q"); - // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(Aₙ₋₁), [1]₁) where fᵢ are - // the k commitments to unshifted polynomials and gⱼ are the m commitments to shifted polynomials + // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(Aₙ₋₁), [1]₁) where fᵢ + // are the k commitments to unshifted polynomials and gⱼ are the m commitments to shifted polynomials std::vector commitments{ Q_commitment }; // Get Shplonk opening point z @@ -336,8 +336,26 @@ template class ShpleminiVerifier_ { gemini_evaluation_challenge, shplonk_batching_challenge, shplonk_evaluation_challenge); - } + if constexpr (Curve::is_stdlib_type) { + auto builder = gemini_evaluation_challenge.get_context(); + size_t num_gates = builder->num_gates; + auto checked = libra_consistency_check(libra_evaluations, + gemini_evaluation_challenge, + multivariate_challenge, + libra_univariate_evaluation); + info("Libra consisitency check num gates ", builder->num_gates - num_gates); + info(checked); + } else { + auto checked = libra_consistency_check(libra_evaluations, + gemini_evaluation_challenge, + multivariate_challenge, + libra_univariate_evaluation); + info("libra consistency check", checked); + } + // info("Libra consisitency check num gates ", builder->num_gates - num_gates); + } + info("batch mul size ", commitments.size()); return { commitments, scalars, shplonk_evaluation_challenge }; }; /** @@ -386,8 +404,8 @@ template class ShpleminiVerifier_ { * @param commitments The vector of commitments to be populated. * @param scalars The vector of scalars to be populated. * @param batched_evaluation The evaluation of the batched multilinear polynomial. - * @param concatenated_scalars Scaling factors for the commitments to polynomials in concatenation groups, one for - * each group. + * @param concatenated_scalars Scaling factors for the commitments to polynomials in concatenation groups, one + * for each group. * @param concatenation_group_commitments Commitments to polynomials to be concatenated. * @param concatenated_evaluations Evaluations of the full concatenated polynomials. */ @@ -436,8 +454,8 @@ template class ShpleminiVerifier_ { current_batching_challenge *= multivariate_batching_challenge; } - // If we are performing an opening verification for the translator, add the contributions from the concatenation - // commitments and evaluations to the result + // If we are performing an opening verification for the translator, add the contributions from the + // concatenation commitments and evaluations to the result ASSERT(concatenated_evaluations.size() == concatenation_group_commitments.size()); if (!concatenation_group_commitments.empty()) { size_t concatenation_group_size = concatenation_group_commitments[0].size(); @@ -533,21 +551,21 @@ template class ShpleminiVerifier_ { } /** - * @brief Combines scalars of repeating commitments to reduce the number of scalar multiplications performed by the - * verifier. + * @brief Combines scalars of repeating commitments to reduce the number of scalar multiplications performed by + * the verifier. * - * @details The Shplemini verifier gets the access to multiple groups of commitments, some of which are duplicated - * because they correspond to polynomials whose shifts also evaluated or used in concatenation groups in - * Translator. This method combines the scalars associated with these repeating commitments, reducing the total - * number of scalar multiplications required during the verification. + * @details The Shplemini verifier gets the access to multiple groups of commitments, some of which are + * duplicated because they correspond to polynomials whose shifts also evaluated or used in concatenation groups + * in Translator. This method combines the scalars associated with these repeating commitments, reducing the + * total number of scalar multiplications required during the verification. * * More specifically, the Shplemini verifier receives two or three groups of commitments: get_unshifted() and * get_to_be_shifted() in the case of Ultra, Mega, and ECCVM Flavors; and get_unshifted_without_concatenated(), - * get_to_be_shifted(), and get_groups_to_be_concatenated() in the case of the TranslatorFlavor. The commitments are - * then placed in this specific order in a BatchOpeningClaim object containing a vector of commitments and a vector - * of scalars. The ranges with repeated commitments belong to the Flavors. This method iterates over these ranges - * and sums the scalar multipliers corresponding to the same group element. After combining the scalars, we erase - * corresponding entries in both vectors. + * get_to_be_shifted(), and get_groups_to_be_concatenated() in the case of the TranslatorFlavor. The commitments + * are then placed in this specific order in a BatchOpeningClaim object containing a vector of commitments and a + * vector of scalars. The ranges with repeated commitments belong to the Flavors. This method iterates over + * these ranges and sums the scalar multipliers corresponding to the same group element. After combining the + * scalars, we erase corresponding entries in both vectors. * */ // TODO(https://github.com/AztecProtocol/barretenberg/issues/1151) Avoid erasing vector elements. @@ -556,9 +574,9 @@ template class ShpleminiVerifier_ { const RepeatedCommitmentsData& repeated_commitments, bool has_zk) { - // We started populating commitments and scalars by adding Shplonk:Q commitmment and the corresponding scalar - // factor 1. In the case of ZK, we also added Gemini:masking_poly_comm before populating the vector with - // commitments to prover polynomials + // We started populating commitments and scalars by adding Shplonk:Q commitmment and the corresponding + // scalar factor 1. In the case of ZK, we also added Gemini:masking_poly_comm before populating the vector + // with commitments to prover polynomials const size_t offset = has_zk ? 2 : 1; // Extract the indices from the container, which is normally created in a given Flavor @@ -637,6 +655,9 @@ template class ShpleminiVerifier_ { const Fr& shplonk_evaluation_challenge) { + const Fr bn_254_subgroup_generator = + Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + // compute current power of Shplonk batching challenge taking into account the const proof size Fr shplonk_challenge_power = Fr{ 1 }; for (size_t j = 0; j < CONST_PROOF_SIZE_LOG_N + 2; ++j) { @@ -686,5 +707,97 @@ template class ShpleminiVerifier_ { // update the constant term of the Shplonk batched claim constant_term += scaling_factor * libra_evaluations[3]; } + // Need to check that L_1(r) A(r) + (r-1) (A(g*r) - A(r) - F(r) G(r)) + L_{m+1}(r) (A(r) - s) = T(r) Z_H(r) + static bool libra_consistency_check(std::array& libra_evaluations, + const Fr& gemini_evaluation_challenge, + std::vector multilinear_challenge, + const Fr& eval_claim) + { + const Fr bn_254_subgroup_generator = + Fr(1) / Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + + Fr vanishing_poly_eval = gemini_evaluation_challenge.pow(87) - Fr(1); + std::vector lagrange_coeffs(87); + // for (size_t idx = 0; idx < 87; idx++) { + // lagrange_coeffs[idx] = Fr{ 0 }; + // } + std::array challenge_polynomial_lagrange; + for (size_t idx = 0; idx < 87; idx++) { + challenge_polynomial_lagrange[idx] = Fr{ 0 }; + } + challenge_polynomial_lagrange[0] = Fr{ 1 }; + + for (size_t poly_idx = 0; poly_idx < CONST_PROOF_SIZE_LOG_N; poly_idx++) { + for (size_t exponent = 0; exponent < 3; exponent++) { + auto current_idx = 1 + poly_idx * 3 + exponent; + challenge_polynomial_lagrange[current_idx] = multilinear_challenge[poly_idx].pow(exponent); + } + } + + std::array evals = compute_barycentric_evaluation( + challenge_polynomial_lagrange, 87, gemini_evaluation_challenge, bn_254_subgroup_generator); + + auto& F_at_r = libra_evaluations[0]; + auto& big_sum_shifted_eval = libra_evaluations[1]; + auto& big_sum_eval = libra_evaluations[2]; + auto& quotient_eval = libra_evaluations[3]; + // info("verifier 1/g =", Fr(1) / bn_254_subgroup_generator); + Fr diff = evals[1] * big_sum_eval + + (gemini_evaluation_challenge - bn_254_subgroup_generator) * + (big_sum_shifted_eval - big_sum_eval - F_at_r * evals[0]) + + evals[2] * (big_sum_eval - eval_claim) - vanishing_poly_eval * quotient_eval; + + if constexpr (Curve::is_stdlib_type) { + return (diff.get_value() == Fr(0).get_value()); + } else { + return (diff == Fr(0)); + }; + } + + static std::array compute_barycentric_evaluation(std::array coeffs, + const size_t num_coeffs, + const Fr& z, + const Fr& inverse_root_of_unity) + { + std::array denominators; + Fr one = Fr{ 1 }; + Fr numerator = z; + + numerator = numerator.pow(num_coeffs) - one; + numerator *= one / Fr(num_coeffs); // (ʓ^n - 1) / n + + denominators[0] = z - one; + Fr work_root = inverse_root_of_unity; // ω^{-1} + for (size_t i = 1; i < num_coeffs; ++i) { + denominators[i] = + work_root * z; // denominators[i] will correspond to L_[i+1] (since our 'commented maths' notation + // indexes L_i from 1). So ʓ.ω^{-i} = ʓ.ω^{1-(i+1)} is correct for L_{i+1}. + denominators[i] -= one; // ʓ.ω^{-i} - 1 + work_root *= inverse_root_of_unity; + } + if constexpr (Curve::is_stdlib_type) { + for (Fr& denominator : denominators) { + denominator = one / denominator; + } + } else { + Fr::batch_invert(&denominators[0], num_coeffs); + } + std::array result = { Fr(0), Fr(0), Fr(0) }; + + for (size_t i = 0; i < num_coeffs; ++i) { + Fr temp = coeffs[i] * denominators[i]; // f_i * 1/(ʓ.ω^{-i} - 1) + result[0] = result[0] + temp; + } + + result[0] = result[0] * numerator; + result[1] = one * denominators[0] * numerator; + result[2] = one * denominators[87 - 1] * numerator; + + // \sum_{i=0}^{num_coeffs-1} f_i * [ʓ^n - 1]/[n.(ʓ.ω^{-i} - 1)] + // = \sum_{i=0}^{num_coeffs-1} f_i * L_{i+1} + // (with our somewhat messy 'commented maths' convention that L_1 corresponds to the 0th coeff). + + return result; + } }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp index ad65bda04a5..0da5f04536d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp @@ -147,7 +147,7 @@ template class ShplonkProver_ { // Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ ) tmp = claim.polynomial; tmp.at(0) = tmp[0] - claim.opening_pair.evaluation; - info("prover denom", inverse_vanishing_evals[idx]); + // info("prover denom", inverse_vanishing_evals[idx]); Fr scaling_factor = current_nu * inverse_vanishing_evals[idx]; // = νʲ / (z − xⱼ ) info("current nu ", current_nu); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index c8170f4373c..281d6fe5ae4 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -91,22 +91,27 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ // Receive commitments to Libra masking polynomials std::vector libra_commitments = {}; + FF libra_evaluation{ 0 }; if constexpr (Flavor::HasZK) { - for (size_t idx = 0; idx < log_circuit_size; idx++) { - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:commitment_" + std::to_string(idx)); - libra_commitments.push_back(libra_commitment); - }; + + Commitment libra_commitment = + transcript->template receive_from_prover("Libra:concatenation_commitment"); + libra_commitments.push_back(libra_commitment); } SumcheckOutput sumcheck_output = sumcheck.verify(verification_key->relation_parameters, verification_key->alphas, gate_challenges); // For MegaZKFlavor: the sumcheck output contains claimed evaluations of the Libra polynomials - std::vector libra_evaluations = {}; if constexpr (Flavor::HasZK) { - libra_evaluations = std::move(sumcheck_output.claimed_libra_evaluations); + libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); + Commitment libra_big_sum_commitment = + transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments.push_back(libra_big_sum_commitment); + Commitment libra_quotient_commitment = + transcript->template receive_from_prover("Libra:quotient_commitment"); + libra_commitments.push_back(libra_quotient_commitment); + // info("big sum received"); } - // Execute Shplemini to produce a batch opening claim subsequently verified by a univariate PCS const BatchOpeningClaim opening_claim = Shplemini::compute_batch_opening_claim(key->circuit_size, @@ -118,8 +123,8 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ Commitment::one(builder), transcript, Flavor::REPEATED_COMMITMENTS, - RefVector(libra_commitments), - libra_evaluations); + libra_commitments, + libra_evaluation); auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp index 070046f3f15..20b218f15ac 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp @@ -129,7 +129,7 @@ class MockCircuits { * @param num_gates */ template - static void construct_arithmetic_circuit(Builder& builder, const size_t target_log2_dyadic_size = 4) + static void construct_arithmetic_circuit(Builder& builder, const size_t target_log2_dyadic_size = 8) { const size_t target_dyadic_size = 1 << target_log2_dyadic_size; const size_t num_preamble_gates = builder.num_gates; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index ca779b4d029..1b08f250566 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -1,5 +1,6 @@ #pragma once +#include "barretenberg/constants.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include @@ -268,7 +269,7 @@ template struct ZKSumcheckData { coeffs_lagrange_basis[idx] = FF{ 0 }; } - for (size_t idx_poly = 0; idx_poly < log_circuit_size; idx_poly++) { + for (size_t idx_poly = 0; idx_poly < CONST_PROOF_SIZE_LOG_N; idx_poly++) { for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { size_t current_idx = 1 + LIBRA_UNIVARIATES_LENGTH * idx_poly + idx; coeffs_lagrange_basis[current_idx] = multivariate_challenge[idx_poly].pow(idx); @@ -361,18 +362,12 @@ template struct ZKSumcheckData { result.at(idx) = result.at(idx - 1); } result.at(0) = FF(0); - + info("last element of the domain prover ", interpolation_domain[SUBGROUP_SIZE - 1]); // subtract g from result to get (X- 1)(A(gX) - A(X) - F(X) * G(X)) for (size_t idx = 0; idx < result.size() - 1; idx++) { result.at(idx) -= result.at(idx + 1) * interpolation_domain[SUBGROUP_SIZE - 1]; } - info("======"); - info(result.evaluate(interpolation_domain[4])); - info(big_sum_lagrange_coeffs[5] - big_sum_lagrange_coeffs[4] - - libra_concatenated_lagrange_form.at(4) * challenge_polynomial_lagrange.at(4)); - info("======"); - lagrange_first_monomial += lagrange_last_monomial; // info("lagrange first plus last ", lagrange_first_monomial.evaluate(interpolation_domain[5])); @@ -381,31 +376,29 @@ template struct ZKSumcheckData { result.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); } } - info("(lagrange first + last ) A(X) + () at 1 ", result.evaluate(interpolation_domain[SUBGROUP_SIZE - 1])); - - info("======"); - info(result.evaluate(interpolation_domain[4])); - info(big_sum_lagrange_coeffs[5] - big_sum_lagrange_coeffs[4] - - libra_concatenated_lagrange_form.at(4) * challenge_polynomial_lagrange.at(4)); - info("======"); FF claimed_sum = big_sum_lagrange_coeffs[SUBGROUP_SIZE - 2]; - info(claimed_sum); + info("claimed sum as a coeff of big sum poly ", claimed_sum); info("====="); for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { result.at(idx) -= lagrange_last_monomial.at(idx) * claimed_sum; } - + // info("=== Batched poly evals in the domain"); // for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { // info(result.evaluate(interpolation_domain[idx])); // } info(" ===="); + for (size_t idx = 0; idx < BATCHED_POLYNOMIAL_LENGTH; idx++) { + info("idx ", idx, " ", result.at(idx)); + } + info("====="); batched_polynomial = result; } // Compute the quotient by Z_H = X^87 - 1 void compute_batched_quotient() - { + { // auto remainder = batched_polynomial; - for (size_t idx = BATCHED_POLYNOMIAL_LENGTH - 1; idx > QUOTIENT_LENGTH; idx--) { + for (size_t idx = BATCHED_POLYNOMIAL_LENGTH - 1; idx >= SUBGROUP_SIZE; idx--) { + info(idx - SUBGROUP_SIZE); batched_quotient.at(idx - SUBGROUP_SIZE) = remainder.at(idx); remainder.at(idx - SUBGROUP_SIZE) += remainder.at(idx); } @@ -415,6 +408,7 @@ template struct ZKSumcheckData { for (size_t idx = 0; idx < SUBGROUP_SIZE + 1; idx++) { Z_H[idx] = FF(0); } + Z_H[0] = FF(-1); Z_H[SUBGROUP_SIZE] = FF(1); for (size_t i = 0; i < batched_quotient.size(); ++i) { @@ -422,10 +416,13 @@ template struct ZKSumcheckData { result.at(i + j) += batched_quotient.at(i) * Z_H[j]; } } - // for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { - // info("product", result.evaluate(interpolation_domain[idx])); - // // info("source poly", batched_polynomial.at(idx)); - // } + info(" ===="); + for (size_t idx = 0; idx < BATCHED_POLYNOMIAL_LENGTH; idx++) { + info("idx ", idx, " ", result.at(idx)); + } + info("====="); + info("difference : ", batched_polynomial.evaluate(FF(2)) - result.evaluate(FF(2))); } }; + } // namespace bb From 0e9a384c282d953fbecb58bedf667c5636e614c8 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 13 Dec 2024 10:45:04 +0000 Subject: [PATCH 07/30] reduced the number of gates --- .../commitment_schemes/shplonk/shplemini.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 5de86cbb9e6..4936c7eaccc 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -167,7 +167,7 @@ template class ShpleminiVerifier_ { { // Extract log_circuit_size size_t log_circuit_size{ 0 }; - info(libra_univariate_evaluation); + // info(libra_univariate_evaluation); if constexpr (Curve::is_stdlib_type) { log_circuit_size = numeric::get_msb(static_cast(N.get_value())); } else { @@ -726,12 +726,12 @@ template class ShpleminiVerifier_ { challenge_polynomial_lagrange[idx] = Fr{ 0 }; } challenge_polynomial_lagrange[0] = Fr{ 1 }; - + auto challenge_sqr = Fr{ 1 }; for (size_t poly_idx = 0; poly_idx < CONST_PROOF_SIZE_LOG_N; poly_idx++) { - for (size_t exponent = 0; exponent < 3; exponent++) { - auto current_idx = 1 + poly_idx * 3 + exponent; - challenge_polynomial_lagrange[current_idx] = multilinear_challenge[poly_idx].pow(exponent); - } + challenge_polynomial_lagrange[1 + poly_idx * 3] = Fr{ 1 }; + challenge_polynomial_lagrange[1 + poly_idx * 3 + 1] = multilinear_challenge[poly_idx]; + challenge_sqr = multilinear_challenge[poly_idx] * multilinear_challenge[poly_idx]; + challenge_polynomial_lagrange[1 + poly_idx * 3 + 2] = challenge_sqr; } std::array evals = compute_barycentric_evaluation( @@ -790,8 +790,8 @@ template class ShpleminiVerifier_ { } result[0] = result[0] * numerator; - result[1] = one * denominators[0] * numerator; - result[2] = one * denominators[87 - 1] * numerator; + result[1] = denominators[0] * numerator; + result[2] = denominators[87 - 1] * numerator; // \sum_{i=0}^{num_coeffs-1} f_i * [ʓ^n - 1]/[n.(ʓ.ω^{-i} - 1)] // = \sum_{i=0}^{num_coeffs-1} f_i * L_{i+1} From d0f2ddee044619b22b2b2d8838714ea395f56268 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 13 Dec 2024 11:46:01 +0000 Subject: [PATCH 08/30] big sum masked --- .../sumcheck/zk_sumcheck_data.hpp | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 1b08f250566..5c8a05c4c6f 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -79,7 +79,7 @@ template struct ZKSumcheckData { : free_term(FF(0)) , libra_concatenated_monomial_form(SUBGROUP_SIZE + 2) // includes masking , challenge_polynomial(SUBGROUP_SIZE) // public polynomial - , big_sum_polynomial(SUBGROUP_SIZE + 2) // includes masking + , big_sum_polynomial(SUBGROUP_SIZE + 3) // includes masking , batched_polynomial(BATCHED_POLYNOMIAL_LENGTH) // batched polynomial, input to shplonk prover , batched_quotient(QUOTIENT_LENGTH) // quotient of the batched polynomial by Z_H(X) = X^87 - 1 , libra_univariates(generate_libra_univariates(multivariate_d)) // random univariates of degree 2 @@ -296,37 +296,36 @@ template struct ZKSumcheckData { // get unmasked in monomial auto big_sum_polynomial_unmasked = Polynomial(interpolation_domain, big_sum_lagrange_coeffs, SUBGROUP_SIZE); // mask - bb::Univariate masking_scalars = bb::Univariate::zero(); + bb::Univariate masking_scalars = bb::Univariate::get_random(); for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { big_sum_polynomial.at(idx) = big_sum_polynomial_unmasked.at(idx); } big_sum_polynomial.at(0) -= masking_scalars.value_at(0); - big_sum_polynomial.at(1) += masking_scalars.value_at(1); + big_sum_polynomial.at(1) -= masking_scalars.value_at(1); + big_sum_polynomial.at(2) -= masking_scalars.value_at(2); - big_sum_polynomial.at(SUBGROUP_SIZE) -= masking_scalars.value_at(0); + big_sum_polynomial.at(SUBGROUP_SIZE) += masking_scalars.value_at(0); big_sum_polynomial.at(SUBGROUP_SIZE + 1) += masking_scalars.value_at(1); + big_sum_polynomial.at(SUBGROUP_SIZE + 2) += masking_scalars.value_at(2); + info("should be libra opening claim", big_sum_polynomial.evaluate(interpolation_domain[80])); }; void compute_batched_polynomial() { // compute shifted big sum - std::array shifted_big_sum_lagrange; + Polynomial shifted_big_sum(SUBGROUP_SIZE + 3); - shifted_big_sum_lagrange[SUBGROUP_SIZE - 1] = - big_sum_lagrange_coeffs[0] - big_sum_lagrange_coeffs[SUBGROUP_SIZE - 1]; - for (size_t idx = 0; idx < SUBGROUP_SIZE - 1; idx++) { - shifted_big_sum_lagrange[idx] = big_sum_lagrange_coeffs[idx + 1] - big_sum_lagrange_coeffs[idx]; + for (size_t idx = 0; idx < SUBGROUP_SIZE + 3; idx++) { + shifted_big_sum[idx] = big_sum_polynomial.at(idx) * interpolation_domain[idx % SUBGROUP_SIZE]; } - auto shifted_big_sum = Polynomial(interpolation_domain, shifted_big_sum_lagrange, SUBGROUP_SIZE); - // compute lagrange first in monomial basis std::array lagrange_coeffs; lagrange_coeffs[0] = FF(1); for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { lagrange_coeffs[idx] = FF(0); } - // todo: turn into constexpr + Polynomial lagrange_first_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); // compute lagrange last in monomial basis @@ -344,18 +343,12 @@ template struct ZKSumcheckData { result.at(i + j) -= libra_concatenated_monomial_form.at(i) * challenge_polynomial.at(j); } } - info("======"); - info(-result.evaluate(interpolation_domain[SUBGROUP_SIZE - 1])); - info(libra_concatenated_lagrange_form.at(SUBGROUP_SIZE - 1) * - challenge_polynomial_lagrange.at(SUBGROUP_SIZE - 1)); - info("======"); // compute (A(gX) - A(X) - F(X) * G(X)) for (size_t idx = 0; idx < shifted_big_sum.size(); idx++) { - result.at(idx) += shifted_big_sum.at(idx); + result.at(idx) += shifted_big_sum.at(idx) - big_sum_polynomial.at(idx); } - info("eval of A(gX) - A(X) - F(X) G(X) at last element ", - result.evaluate(interpolation_domain[SUBGROUP_SIZE - 1])); + // mutiply by X-g // shift by X for (size_t idx = result.size() - 1; idx > 0; idx--) { @@ -370,7 +363,6 @@ template struct ZKSumcheckData { lagrange_first_monomial += lagrange_last_monomial; - // info("lagrange first plus last ", lagrange_first_monomial.evaluate(interpolation_domain[5])); for (size_t i = 0; i < big_sum_polynomial.size(); ++i) { for (size_t j = 0; j < lagrange_first_monomial.size(); ++j) { result.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); @@ -382,10 +374,7 @@ template struct ZKSumcheckData { for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { result.at(idx) -= lagrange_last_monomial.at(idx) * claimed_sum; } - // info("=== Batched poly evals in the domain"); - // for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { - // info(result.evaluate(interpolation_domain[idx])); - // } + info(" ===="); for (size_t idx = 0; idx < BATCHED_POLYNOMIAL_LENGTH; idx++) { info("idx ", idx, " ", result.at(idx)); From 31505cfaa0a419a74f0d1e88a5f95153f5e99ff9 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 13 Dec 2024 12:59:17 +0000 Subject: [PATCH 09/30] masked constant term + clean-up --- .../src/barretenberg/sumcheck/sumcheck.hpp | 1 + .../sumcheck/zk_sumcheck_data.hpp | 140 +++++++----------- 2 files changed, 51 insertions(+), 90 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index f8e6e4be042..60ec0659454 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -264,6 +264,7 @@ template class SumcheckProver { for (auto& libra_eval : zk_sumcheck_data.libra_evaluations) { libra_evaluation += libra_eval; } + libra_evaluation += zk_sumcheck_data.constant_term; std::string libra_evaluation_label = "Libra:final_evaluation"; transcript->send_to_verifier(libra_evaluation_label, libra_evaluation); }; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 5c8a05c4c6f..bf2dea3f911 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -47,7 +47,7 @@ template struct ZKSumcheckData { // Container for the evaluations of Libra Univariates that have to be proven. using ClaimedLibraEvaluations = std::vector; - FF free_term{ 0 }; + FF constant_term; std::array interpolation_domain; // to compute product in lagrange basis Polynomial libra_concatenated_lagrange_form; @@ -65,6 +65,7 @@ template struct ZKSumcheckData { LibraUnivariates libra_univariates_monomial; FF libra_scaling_factor{ 1 }; FF libra_challenge; + FF libra_total_sum; FF libra_running_sum; ClaimedLibraEvaluations libra_evaluations; std::array big_sum_lagrange_coeffs; @@ -76,7 +77,7 @@ template struct ZKSumcheckData { ZKSumcheckData(const size_t multivariate_d, std::shared_ptr transcript, std::shared_ptr commitment_key = nullptr) - : free_term(FF(0)) + : constant_term(FF::random_element()) , libra_concatenated_monomial_form(SUBGROUP_SIZE + 2) // includes masking , challenge_polynomial(SUBGROUP_SIZE) // public polynomial , big_sum_polynomial(SUBGROUP_SIZE + 3) // includes masking @@ -95,7 +96,7 @@ template struct ZKSumcheckData { } // Compute the total sum of the Libra polynomials libra_scaling_factor = FF(1); - FF libra_total_sum = compute_libra_total_sum(libra_univariates, libra_scaling_factor); + libra_total_sum = compute_libra_total_sum(libra_univariates, libra_scaling_factor, constant_term); // Send the Libra total sum to the transcript transcript->send_to_verifier("Libra:Sum", libra_total_sum); @@ -168,7 +169,9 @@ template struct ZKSumcheckData { * @param scaling_factor * @return FF */ - static FF compute_libra_total_sum(const LibraUnivariates& libra_univariates, FF& scaling_factor) + static FF compute_libra_total_sum(const LibraUnivariates& libra_univariates, + FF& scaling_factor, + const FF& free_term) { FF total_sum = 0; scaling_factor = scaling_factor / 2; @@ -179,7 +182,7 @@ template struct ZKSumcheckData { } total_sum *= scaling_factor; - return total_sum; + return total_sum + free_term * (1 << libra_univariates.size()); } /** @@ -214,20 +217,18 @@ template struct ZKSumcheckData { // info(bn_254_subgroup_generator.pow(29 * 3)); // info(grumpkin_subgroup_generator.pow(2 * 983)); std::array coeffs_lagrange_subgroup; - coeffs_lagrange_subgroup[0] = free_term; + coeffs_lagrange_subgroup[0] = constant_term; for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { coeffs_lagrange_subgroup[idx] = FF{ 0 }; } - // info(libra_univariates_monomial.size()); + for (size_t poly_idx = 0; poly_idx < libra_univariates_monomial.size(); poly_idx++) { for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { size_t idx_to_populate = 1 + poly_idx * LIBRA_UNIVARIATES_LENGTH + idx; - // info(idx_to_populate); coeffs_lagrange_subgroup[idx_to_populate] = libra_univariates_monomial[poly_idx].value_at(idx); } } - // 377--> Flavor::SubgroupSize // create evaluation domain using the generator for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { @@ -236,12 +237,7 @@ template struct ZKSumcheckData { libra_concatenated_lagrange_form = Polynomial(coeffs_lagrange_subgroup); - bb::Univariate masking_scalars = bb::Univariate::zero(); - - // using namespace std::chrono; - - // auto total_time = 0.0; - // auto start = high_resolution_clock::now(); + bb::Univariate masking_scalars = bb::Univariate::get_random(); auto libra_concatenated_monomial_form_unmasked = Polynomial(interpolation_domain, coeffs_lagrange_subgroup, SUBGROUP_SIZE); @@ -251,14 +247,10 @@ template struct ZKSumcheckData { } libra_concatenated_monomial_form.at(0) -= masking_scalars.value_at(0); - libra_concatenated_monomial_form.at(1) += masking_scalars.value_at(1); + libra_concatenated_monomial_form.at(1) -= masking_scalars.value_at(1); - libra_concatenated_monomial_form.at(SUBGROUP_SIZE) -= masking_scalars.value_at(0); + libra_concatenated_monomial_form.at(SUBGROUP_SIZE) += masking_scalars.value_at(0); libra_concatenated_monomial_form.at(SUBGROUP_SIZE + 1) += masking_scalars.value_at(1); - // auto end = high_resolution_clock::now(); - // total_time += duration(end - start).count(); - - // info("total time", total_time); } void setup_challenge_polynomial(const std::vector multivariate_challenge) { @@ -277,49 +269,44 @@ template struct ZKSumcheckData { } challenge_polynomial_lagrange = Polynomial(coeffs_lagrange_basis); challenge_polynomial = Polynomial(interpolation_domain, coeffs_lagrange_basis, SUBGROUP_SIZE); - - info(challenge_polynomial.evaluate(interpolation_domain[84])); - // info(multivariate_challenge[84]); } void setup_big_sum_polynomial() { big_sum_lagrange_coeffs[0] = 0; + + // Compute the big sum coefficients recursively for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { size_t prev_idx = idx - 1; big_sum_lagrange_coeffs[idx] = big_sum_lagrange_coeffs[prev_idx] + challenge_polynomial_lagrange.at(prev_idx) * libra_concatenated_lagrange_form.at(prev_idx); - // info("big sum coeff lagrange ", idx, " ", big_sum_lagrange_coeffs[idx]); }; - // get unmasked in monomial + // Get the coefficients in the monomial basis auto big_sum_polynomial_unmasked = Polynomial(interpolation_domain, big_sum_lagrange_coeffs, SUBGROUP_SIZE); - // mask - bb::Univariate masking_scalars = bb::Univariate::get_random(); + + // Generate random masking_term of degree 2, add Z_H(X) * masking_term + bb::Univariate masking_term = bb::Univariate::get_random(); for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { big_sum_polynomial.at(idx) = big_sum_polynomial_unmasked.at(idx); } - big_sum_polynomial.at(0) -= masking_scalars.value_at(0); - big_sum_polynomial.at(1) -= masking_scalars.value_at(1); - big_sum_polynomial.at(2) -= masking_scalars.value_at(2); - - big_sum_polynomial.at(SUBGROUP_SIZE) += masking_scalars.value_at(0); - big_sum_polynomial.at(SUBGROUP_SIZE + 1) += masking_scalars.value_at(1); - big_sum_polynomial.at(SUBGROUP_SIZE + 2) += masking_scalars.value_at(2); - info("should be libra opening claim", big_sum_polynomial.evaluate(interpolation_domain[80])); + for (size_t idx = 0; idx < masking_term.size(); idx++) { + big_sum_polynomial.at(idx) -= masking_term.value_at(idx); + big_sum_polynomial.at(idx + SUBGROUP_SIZE) += masking_term.value_at(idx); + } }; void compute_batched_polynomial() { - // compute shifted big sum + // Compute shifted big sum polynomial A(gX) Polynomial shifted_big_sum(SUBGROUP_SIZE + 3); for (size_t idx = 0; idx < SUBGROUP_SIZE + 3; idx++) { - shifted_big_sum[idx] = big_sum_polynomial.at(idx) * interpolation_domain[idx % SUBGROUP_SIZE]; + shifted_big_sum.at(idx) = big_sum_polynomial.at(idx) * interpolation_domain[idx % SUBGROUP_SIZE]; } - // compute lagrange first in monomial basis + // Compute the monomial coefficients of L_1, the first Lagrange polynomial std::array lagrange_coeffs; lagrange_coeffs[0] = FF(1); for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { @@ -328,89 +315,62 @@ template struct ZKSumcheckData { Polynomial lagrange_first_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); - // compute lagrange last in monomial basis - // todo: turn into constexpr + // Compute the monomial coefficients of L_{|H|}, the last Lagrange polynomial lagrange_coeffs[0] = 0; lagrange_coeffs[SUBGROUP_SIZE - 1] = 1; Polynomial lagrange_last_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); - // compute the negated product of challenge_polynomial and libra_concatenated_monomial_form - Polynomial result(BATCHED_POLYNOMIAL_LENGTH); + // Compute -F(X)*G(X), the negated product of challenge_polynomial and libra_concatenated_monomial_form + // Polynomial result(BATCHED_POLYNOMIAL_LENGTH); for (size_t i = 0; i < libra_concatenated_monomial_form.size(); ++i) { for (size_t j = 0; j < challenge_polynomial.size(); ++j) { - result.at(i + j) -= libra_concatenated_monomial_form.at(i) * challenge_polynomial.at(j); + batched_polynomial.at(i + j) -= libra_concatenated_monomial_form.at(i) * challenge_polynomial.at(j); } } - // compute (A(gX) - A(X) - F(X) * G(X)) + // Compute - F(X) * G(X) + A(gX) - A(X) for (size_t idx = 0; idx < shifted_big_sum.size(); idx++) { - result.at(idx) += shifted_big_sum.at(idx) - big_sum_polynomial.at(idx); + batched_polynomial.at(idx) += shifted_big_sum.at(idx) - big_sum_polynomial.at(idx); } - // mutiply by X-g - // shift by X - for (size_t idx = result.size() - 1; idx > 0; idx--) { - result.at(idx) = result.at(idx - 1); + // Mutiply - F(X) * G(X) + A(gX) - A(X) by X-g: + // 1. Multiply by X + for (size_t idx = batched_polynomial.size() - 1; idx > 0; idx--) { + batched_polynomial.at(idx) = batched_polynomial.at(idx - 1); } - result.at(0) = FF(0); - info("last element of the domain prover ", interpolation_domain[SUBGROUP_SIZE - 1]); - // subtract g from result to get (X- 1)(A(gX) - A(X) - F(X) * G(X)) - for (size_t idx = 0; idx < result.size() - 1; idx++) { - result.at(idx) -= result.at(idx + 1) * interpolation_domain[SUBGROUP_SIZE - 1]; + batched_polynomial.at(0) = FF(0); + // 2. Subtract 1/g(A(gX) - A(X) - F(X) * G(X)) + for (size_t idx = 0; idx < batched_polynomial.size() - 1; idx++) { + batched_polynomial.at(idx) -= batched_polynomial.at(idx + 1) * interpolation_domain[SUBGROUP_SIZE - 1]; } + // Add (L_1 + L_{|H|}) * A(X) to the result lagrange_first_monomial += lagrange_last_monomial; for (size_t i = 0; i < big_sum_polynomial.size(); ++i) { for (size_t j = 0; j < lagrange_first_monomial.size(); ++j) { - result.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); + batched_polynomial.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); } } - FF claimed_sum = big_sum_lagrange_coeffs[SUBGROUP_SIZE - 2]; - info("claimed sum as a coeff of big sum poly ", claimed_sum); - info("====="); - for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { - result.at(idx) -= lagrange_last_monomial.at(idx) * claimed_sum; + FF claimed_sum = constant_term; + for (FF& libra_eval : libra_evaluations) { + claimed_sum += libra_eval; } - - info(" ===="); - for (size_t idx = 0; idx < BATCHED_POLYNOMIAL_LENGTH; idx++) { - info("idx ", idx, " ", result.at(idx)); + for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { + batched_polynomial.at(idx) -= lagrange_last_monomial.at(idx) * claimed_sum; } - info("====="); - batched_polynomial = result; } - // Compute the quotient by Z_H = X^87 - 1 + + // Compute the quotient of batched_polynomial by Z_H = X^{|H|} - 1 void compute_batched_quotient() - { // + { auto remainder = batched_polynomial; for (size_t idx = BATCHED_POLYNOMIAL_LENGTH - 1; idx >= SUBGROUP_SIZE; idx--) { - info(idx - SUBGROUP_SIZE); batched_quotient.at(idx - SUBGROUP_SIZE) = remainder.at(idx); remainder.at(idx - SUBGROUP_SIZE) += remainder.at(idx); } - - Polynomial result(BATCHED_POLYNOMIAL_LENGTH); - std::array Z_H; - for (size_t idx = 0; idx < SUBGROUP_SIZE + 1; idx++) { - Z_H[idx] = FF(0); - } - - Z_H[0] = FF(-1); - Z_H[SUBGROUP_SIZE] = FF(1); - for (size_t i = 0; i < batched_quotient.size(); ++i) { - for (size_t j = 0; j < Z_H.size(); ++j) { - result.at(i + j) += batched_quotient.at(i) * Z_H[j]; - } - } - info(" ===="); - for (size_t idx = 0; idx < BATCHED_POLYNOMIAL_LENGTH; idx++) { - info("idx ", idx, " ", result.at(idx)); - } - info("====="); - info("difference : ", batched_polynomial.evaluate(FF(2)) - result.evaluate(FF(2))); } }; From 29862222e0e4715c41e9e9d29ecb226f944c07f4 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 13 Dec 2024 17:30:17 +0000 Subject: [PATCH 10/30] eccvm working --- .../commitment_schemes/shplonk/shplemini.hpp | 29 ++++++++++++------- .../src/barretenberg/eccvm/eccvm_prover.cpp | 15 ++++++++-- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 25 ++++++++++------ .../eccvm_recursive_verifier.cpp | 27 +++++++++++------ .../sumcheck/zk_sumcheck_data.hpp | 7 +++-- 5 files changed, 70 insertions(+), 33 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 4936c7eaccc..c71859a066b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -47,8 +47,10 @@ template class ShpleminiProver_ { has_zk); // Create opening claims for Libra masking univariates std::vector libra_opening_claims; - static constexpr FF bn_254_subgroup_generator = - FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + // static constexpr FF bn_254_subgroup_generator = + // FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + static constexpr FF subgroup_generator = + FF(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); const auto gemini_r = opening_claims[0].opening_pair.challenge; OpeningClaim new_claim; if (has_zk) { @@ -59,7 +61,7 @@ template class ShpleminiProver_ { libra_opening_claims.push_back(new_claim); new_claim.polynomial = libra_polynomials[1]; - new_claim.opening_pair.challenge = bn_254_subgroup_generator * gemini_r; + new_claim.opening_pair.challenge = subgroup_generator * gemini_r; new_claim.opening_pair.evaluation = libra_polynomials[1].evaluate(new_claim.opening_pair.challenge); transcript->send_to_verifier("Libra:shifted_big_sum_eval", new_claim.opening_pair.evaluation); libra_opening_claims.push_back(new_claim); @@ -339,6 +341,7 @@ template class ShpleminiVerifier_ { if constexpr (Curve::is_stdlib_type) { auto builder = gemini_evaluation_challenge.get_context(); + size_t num_gates = builder->num_gates; auto checked = libra_consistency_check(libra_evaluations, gemini_evaluation_challenge, @@ -655,8 +658,10 @@ template class ShpleminiVerifier_ { const Fr& shplonk_evaluation_challenge) { - const Fr bn_254_subgroup_generator = - Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + // const Fr bn_254_subgroup_generator = + // Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + const Fr subgroup_generator = + Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); // compute current power of Shplonk batching challenge taking into account the const proof size Fr shplonk_challenge_power = Fr{ 1 }; @@ -670,8 +675,8 @@ template class ShpleminiVerifier_ { std::vector denominators; // compute Shplonk denominators and invert them denominators.push_back(Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge)); - denominators.push_back( - Fr(1) / (shplonk_evaluation_challenge - bn_254_subgroup_generator * gemini_evaluation_challenge)); + denominators.push_back(Fr(1) / + (shplonk_evaluation_challenge - subgroup_generator * gemini_evaluation_challenge)); denominators.push_back(denominators[0]); denominators.push_back(denominators[0]); @@ -713,8 +718,10 @@ template class ShpleminiVerifier_ { std::vector multilinear_challenge, const Fr& eval_claim) { - const Fr bn_254_subgroup_generator = - Fr(1) / Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + // const Fr bn_254_subgroup_generator = + // Fr(1) / Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + const Fr subgroup_generator = + Fr(1) / Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); Fr vanishing_poly_eval = gemini_evaluation_challenge.pow(87) - Fr(1); std::vector lagrange_coeffs(87); @@ -735,7 +742,7 @@ template class ShpleminiVerifier_ { } std::array evals = compute_barycentric_evaluation( - challenge_polynomial_lagrange, 87, gemini_evaluation_challenge, bn_254_subgroup_generator); + challenge_polynomial_lagrange, 87, gemini_evaluation_challenge, subgroup_generator); auto& F_at_r = libra_evaluations[0]; auto& big_sum_shifted_eval = libra_evaluations[1]; @@ -743,7 +750,7 @@ template class ShpleminiVerifier_ { auto& quotient_eval = libra_evaluations[3]; // info("verifier 1/g =", Fr(1) / bn_254_subgroup_generator); Fr diff = evals[1] * big_sum_eval + - (gemini_evaluation_challenge - bn_254_subgroup_generator) * + (gemini_evaluation_challenge - subgroup_generator) * (big_sum_shifted_eval - big_sum_eval - F_at_r * evals[0]) + evals[2] * (big_sum_eval - eval_claim) - vanishing_poly_eval * quotient_eval; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index c8935459e1c..f28251a10c4 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -121,7 +121,18 @@ void ECCVMProver::execute_pcs_rounds() using Shplemini = ShpleminiProver_; using Shplonk = ShplonkProver_; using OpeningClaim = ProverOpeningClaim; - + zk_sumcheck_data.setup_challenge_polynomial(sumcheck_output.challenge); + zk_sumcheck_data.setup_big_sum_polynomial(); + transcript->template send_to_verifier("Libra:big_sum_commitment", + key->commitment_key->commit(zk_sumcheck_data.big_sum_polynomial)); + zk_sumcheck_data.compute_batched_polynomial(); + zk_sumcheck_data.compute_batched_quotient(); + transcript->template send_to_verifier("Libra:quotient_commitment", + key->commitment_key->commit(zk_sumcheck_data.batched_quotient)); + + std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, + zk_sumcheck_data.big_sum_polynomial, + zk_sumcheck_data.batched_quotient }; // Execute the Shplemini (Gemini + Shplonk) protocol to produce a univariate opening claim for the multilinear // evaluations produced by Sumcheck const OpeningClaim multivariate_to_univariate_opening_claim = @@ -131,7 +142,7 @@ void ECCVMProver::execute_pcs_rounds() sumcheck_output.challenge, key->commitment_key, transcript, - zk_sumcheck_data.libra_univariates_monomial, + libra_polynomials, sumcheck_output.claimed_libra_evaluation); // Get the challenge at which we evaluate all transcript polynomials as univariates diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index f4a10683335..2f1f4c72262 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -55,15 +55,22 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) } // Receive commitments to Libra masking polynomials - std::vector libra_commitments; - for (size_t idx = 0; idx < log_circuit_size; idx++) { - Commitment libra_commitment = - transcript->receive_from_prover("Libra:commitment_" + std::to_string(idx)); - libra_commitments.push_back(libra_commitment); - } + std::vector libra_commitments = {}; + + Commitment libra_commitment = + transcript->template receive_from_prover("Libra:concatenation_commitment"); + libra_commitments.push_back(libra_commitment); - auto [multivariate_challenge, claimed_evaluations, libra_evaluations, sumcheck_verified] = + auto [multivariate_challenge, claimed_evaluations, libra_evaluation, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); + + // libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); + Commitment libra_big_sum_commitment = + transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments.push_back(libra_big_sum_commitment); + Commitment libra_quotient_commitment = + transcript->template receive_from_prover("Libra:quotient_commitment"); + libra_commitments.push_back(libra_quotient_commitment); // If Sumcheck did not verify, return false if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { vinfo("eccvm sumcheck failed"); @@ -81,8 +88,8 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) key->pcs_verification_key->get_g1_identity(), transcript, Flavor::REPEATED_COMMITMENTS, - RefVector(libra_commitments), - libra_evaluations); + libra_commitments, + libra_evaluation); // Reduce the accumulator to a single opening claim const OpeningClaim multivariate_to_univariate_opening_claim = diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp index a9422482854..71016e4850c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp @@ -76,16 +76,25 @@ ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) } // Receive commitments to Libra masking polynomials - std::vector libra_commitments; - for (size_t idx = 0; idx < log_circuit_size; idx++) { - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:commitment_" + std::to_string(idx)); - libra_commitments.push_back(libra_commitment); - } + std::vector libra_commitments = {}; + FF libra_evaluation{ 0 }; + + Commitment libra_commitment = + transcript->template receive_from_prover("Libra:concatenation_commitment"); - auto [multivariate_challenge, claimed_evaluations, libra_evaluations, sumcheck_verified] = + libra_commitments.push_back(libra_commitment); + + auto [multivariate_challenge, claimed_evaluations, claimed_libra_evaluation, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); + libra_evaluation = std::move(claimed_libra_evaluation); + Commitment libra_big_sum_commitment = + transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments.push_back(libra_big_sum_commitment); + Commitment libra_quotient_commitment = + transcript->template receive_from_prover("Libra:quotient_commitment"); + libra_commitments.push_back(libra_quotient_commitment); + // Compute the Shplemini accumulator consisting of the Shplonk evaluation and the commitments and scalars vector // produced by the unified protocol BatchOpeningClaim sumcheck_batch_opening_claims = @@ -98,8 +107,8 @@ ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) key->pcs_verification_key->get_g1_identity(), transcript, Flavor::REPEATED_COMMITMENTS, - RefVector(libra_commitments), - libra_evaluations); + libra_commitments, + claimed_libra_evaluation); // Reduce the accumulator to a single opening claim const OpeningClaim multivariate_to_univariate_opening_claim = diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index bf2dea3f911..b7675c4976b 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -215,7 +215,10 @@ template struct ZKSumcheckData { void compute_concatenated_libra_polynomial() { // info(bn_254_subgroup_generator.pow(29 * 3)); - // info(grumpkin_subgroup_generator.pow(2 * 983)); + info("root of unity? ", grumpkin_subgroup_generator.pow(3 * 29)); + info("root of unity? ", grumpkin_subgroup_generator.pow(29)); + info("root of unity? ", grumpkin_subgroup_generator.pow(3)); + std::array coeffs_lagrange_subgroup; coeffs_lagrange_subgroup[0] = constant_term; @@ -232,7 +235,7 @@ template struct ZKSumcheckData { // create evaluation domain using the generator for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { - interpolation_domain[idx] = bn_254_subgroup_generator.pow(idx); + interpolation_domain[idx] = grumpkin_subgroup_generator.pow(idx); } libra_concatenated_lagrange_form = Polynomial(coeffs_lagrange_subgroup); From 4577e05e61b286a1f8d15fb8ef7f33ee3f8e0cf2 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Sat, 14 Dec 2024 21:41:48 +0000 Subject: [PATCH 11/30] cleaning up and simplifying --- .../commitment_schemes/shplonk/shplemini.hpp | 65 +++++++------------ .../src/barretenberg/eccvm/eccvm_prover.cpp | 15 ++--- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 14 ++-- .../translator_recursive_verifier.cpp | 26 +++++--- .../sumcheck/zk_sumcheck_data.hpp | 41 ++++++++---- .../translator_vm/translator_prover.cpp | 17 ++++- .../translator_vm/translator_verifier.cpp | 22 ++++--- .../ultra_honk/decider_prover.cpp | 16 +---- .../ultra_honk/decider_verifier.cpp | 15 ++--- 9 files changed, 111 insertions(+), 120 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index c71859a066b..071adf2638b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -29,7 +29,7 @@ template class ShpleminiProver_ { std::span multilinear_challenge, const std::shared_ptr>& commitment_key, const std::shared_ptr& transcript, - const std::array& libra_polynomials = {}, + const std::array& libra_polynomials = {}, const FF& libra_evaluation = {}, RefSpan concatenated_polynomials = {}, const std::vector>& groups_to_be_concatenated = {}) @@ -51,32 +51,22 @@ template class ShpleminiProver_ { // FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); static constexpr FF subgroup_generator = FF(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); - const auto gemini_r = opening_claims[0].opening_pair.challenge; OpeningClaim new_claim; + if (has_zk) { - new_claim.polynomial = libra_polynomials[0]; - new_claim.opening_pair.challenge = gemini_r; - new_claim.opening_pair.evaluation = libra_polynomials[0].evaluate(gemini_r); - transcript->send_to_verifier("Libra:concatenation_eval", new_claim.opening_pair.evaluation); - libra_opening_claims.push_back(new_claim); - - new_claim.polynomial = libra_polynomials[1]; - new_claim.opening_pair.challenge = subgroup_generator * gemini_r; - new_claim.opening_pair.evaluation = libra_polynomials[1].evaluate(new_claim.opening_pair.challenge); - transcript->send_to_verifier("Libra:shifted_big_sum_eval", new_claim.opening_pair.evaluation); - libra_opening_claims.push_back(new_claim); - - new_claim.polynomial = libra_polynomials[1]; - new_claim.opening_pair.challenge = gemini_r; - new_claim.opening_pair.evaluation = libra_polynomials[1].evaluate(gemini_r); - transcript->send_to_verifier("Libra:big_sum_eval", new_claim.opening_pair.evaluation); - libra_opening_claims.push_back(new_claim); - - new_claim.polynomial = libra_polynomials[2]; - new_claim.opening_pair.challenge = gemini_r; - new_claim.opening_pair.evaluation = libra_polynomials[2].evaluate(gemini_r); - transcript->send_to_verifier("Libra:quotient_eval", new_claim.opening_pair.evaluation); - libra_opening_claims.push_back(new_claim); + const auto gemini_r = opening_claims[0].opening_pair.challenge; + + std::array libra_eval_labels = { + "Libra:concatenation_eval", "Libra:shifted_big_sum_eval", "Libra:big_sum_eval", "Libra:quotient_eval" + }; + const std::array evaluation_points = { gemini_r, gemini_r * subgroup_generator, gemini_r, gemini_r }; + for (size_t idx = 0; idx < 4; idx++) { + new_claim.polynomial = std::move(libra_polynomials[idx]); + new_claim.opening_pair.challenge = evaluation_points[idx]; + new_claim.opening_pair.evaluation = new_claim.polynomial.evaluate(evaluation_points[idx]); + transcript->send_to_verifier(libra_eval_labels[idx], new_claim.opening_pair.evaluation); + libra_opening_claims.push_back(new_claim); + } } const OpeningClaim batched_claim = @@ -161,7 +151,7 @@ template class ShpleminiVerifier_ { const Commitment& g1_identity, const std::shared_ptr& transcript, const RepeatedCommitmentsData& repeated_commitments = {}, - std::vector libra_commitments = {}, + const std::array& libra_commitments = {}, const Fr& libra_univariate_evaluation = Fr{ 0 }, const std::vector>& concatenation_group_commitments = {}, RefSpan concatenated_evaluations = {}) @@ -214,7 +204,6 @@ template class ShpleminiVerifier_ { // Process Shplonk transcript data: // - Get Shplonk batching challenge const Fr shplonk_batching_challenge = transcript->template get_challenge("Shplonk:nu"); - info("shplonk nu verifier ", shplonk_batching_challenge); // - Get the quotient commitment for the Shplonk batching of Gemini opening claims const auto Q_commitment = transcript->template receive_from_prover("Shplonk:Q"); @@ -651,8 +640,8 @@ template class ShpleminiVerifier_ { */ static void add_zk_data(std::vector& commitments, std::vector& scalars, - std::vector libra_commitments, - std::array libra_evaluations, + const std::array& libra_commitments, + const std::array& libra_evaluations, const Fr& gemini_evaluation_challenge, const Fr& shplonk_batching_challenge, const Fr& shplonk_evaluation_challenge) @@ -690,14 +679,11 @@ template class ShpleminiVerifier_ { info(shplonk_challenge_power); scalars.push_back(-scaling_factor); shplonk_challenge_power *= shplonk_batching_challenge; - // update the constant term of the Shplonk batched claim constant_term += scaling_factor * libra_evaluations[0]; commitments.push_back(libra_commitments[1]); scaling_factor = denominators[1] * shplonk_challenge_power; - // scalars.push_back((-scaling_factor)); shplonk_challenge_power *= shplonk_batching_challenge; - // update the constant term of the Shplonk batched claim constant_term += scaling_factor * libra_evaluations[1]; scaling_factor += denominators[2] * shplonk_challenge_power; scalars.push_back(-scaling_factor); @@ -709,9 +695,9 @@ template class ShpleminiVerifier_ { scaling_factor = denominators[3] * shplonk_challenge_power; scalars.push_back(-scaling_factor); shplonk_challenge_power *= shplonk_batching_challenge; - // update the constant term of the Shplonk batched claim constant_term += scaling_factor * libra_evaluations[3]; } + // Need to check that L_1(r) A(r) + (r-1) (A(g*r) - A(r) - F(r) G(r)) + L_{m+1}(r) (A(r) - s) = T(r) Z_H(r) static bool libra_consistency_check(std::array& libra_evaluations, const Fr& gemini_evaluation_challenge, @@ -724,14 +710,9 @@ template class ShpleminiVerifier_ { Fr(1) / Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); Fr vanishing_poly_eval = gemini_evaluation_challenge.pow(87) - Fr(1); - std::vector lagrange_coeffs(87); - // for (size_t idx = 0; idx < 87; idx++) { - // lagrange_coeffs[idx] = Fr{ 0 }; - // } - std::array challenge_polynomial_lagrange; - for (size_t idx = 0; idx < 87; idx++) { - challenge_polynomial_lagrange[idx] = Fr{ 0 }; - } + + std::vector challenge_polynomial_lagrange(87); + challenge_polynomial_lagrange[0] = Fr{ 1 }; auto challenge_sqr = Fr{ 1 }; for (size_t poly_idx = 0; poly_idx < CONST_PROOF_SIZE_LOG_N; poly_idx++) { @@ -761,7 +742,7 @@ template class ShpleminiVerifier_ { }; } - static std::array compute_barycentric_evaluation(std::array coeffs, + static std::array compute_barycentric_evaluation(const std::vector& coeffs, const size_t num_coeffs, const Fr& z, const Fr& inverse_root_of_unity) diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index f28251a10c4..c918f7fedb1 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -121,16 +121,11 @@ void ECCVMProver::execute_pcs_rounds() using Shplemini = ShpleminiProver_; using Shplonk = ShplonkProver_; using OpeningClaim = ProverOpeningClaim; - zk_sumcheck_data.setup_challenge_polynomial(sumcheck_output.challenge); - zk_sumcheck_data.setup_big_sum_polynomial(); - transcript->template send_to_verifier("Libra:big_sum_commitment", - key->commitment_key->commit(zk_sumcheck_data.big_sum_polynomial)); - zk_sumcheck_data.compute_batched_polynomial(); - zk_sumcheck_data.compute_batched_quotient(); - transcript->template send_to_verifier("Libra:quotient_commitment", - key->commitment_key->commit(zk_sumcheck_data.batched_quotient)); - - std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, + + zk_sumcheck_data.compute_witnesses_and_commit(sumcheck_output.challenge, transcript, key->commitment_key); + + std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, + zk_sumcheck_data.big_sum_polynomial, zk_sumcheck_data.big_sum_polynomial, zk_sumcheck_data.batched_quotient }; // Execute the Shplemini (Gemini + Shplonk) protocol to produce a univariate opening claim for the multilinear diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 2f1f4c72262..903b7ad63f5 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -55,22 +55,16 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) } // Receive commitments to Libra masking polynomials - std::vector libra_commitments = {}; + std::array libra_commitments = {}; - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:concatenation_commitment"); - libra_commitments.push_back(libra_commitment); + libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); auto [multivariate_challenge, claimed_evaluations, libra_evaluation, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); // libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); - Commitment libra_big_sum_commitment = - transcript->template receive_from_prover("Libra:big_sum_commitment"); - libra_commitments.push_back(libra_big_sum_commitment); - Commitment libra_quotient_commitment = - transcript->template receive_from_prover("Libra:quotient_commitment"); - libra_commitments.push_back(libra_quotient_commitment); + libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); // If Sumcheck did not verify, return false if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { vinfo("eccvm sumcheck failed"); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index ce321b18ea8..260c9e10726 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -112,16 +112,22 @@ std::array TranslatorRecursiveVerifier_ libra_commitments; - for (size_t idx = 0; idx < log_circuit_size; idx++) { - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:commitment_" + std::to_string(idx)); - libra_commitments.push_back(libra_commitment); - } - auto [multivariate_challenge, claimed_evaluations, libra_evaluations, sumcheck_verified] = + + Commitment libra_commitment = + transcript->template receive_from_prover("Libra:concatenation_commitment"); + libra_commitments.push_back(libra_commitment); + + auto [multivariate_challenge, claimed_evaluations, libra_evaluation, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); - // Execute ZeroMorph rounds followed by the univariate PCS. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a - // complete description of the unrolled protocol. + Commitment libra_big_sum_commitment = + transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments.push_back(libra_big_sum_commitment); + Commitment libra_quotient_commitment = + transcript->template receive_from_prover("Libra:quotient_commitment"); + libra_commitments.push_back(libra_quotient_commitment); + + // Execute Shplemini const BatchOpeningClaim opening_claim = Shplemini::compute_batch_opening_claim(circuit_size, @@ -133,8 +139,8 @@ std::array TranslatorRecursiveVerifier_ struct ZKSumcheckData { libra_concatenated_monomial_form.at(idx) = libra_concatenated_monomial_form_unmasked.at(idx); } - libra_concatenated_monomial_form.at(0) -= masking_scalars.value_at(0); - libra_concatenated_monomial_form.at(1) -= masking_scalars.value_at(1); - - libra_concatenated_monomial_form.at(SUBGROUP_SIZE) += masking_scalars.value_at(0); - libra_concatenated_monomial_form.at(SUBGROUP_SIZE + 1) += masking_scalars.value_at(1); + for (size_t idx = 0; idx < masking_scalars.size(); idx++) { + libra_concatenated_monomial_form.at(idx) -= masking_scalars.value_at(idx); + libra_concatenated_monomial_form.at(SUBGROUP_SIZE + idx) += masking_scalars.value_at(idx); + } } - void setup_challenge_polynomial(const std::vector multivariate_challenge) + void setup_challenge_polynomial(const std::vector& multivariate_challenge) { - std::array coeffs_lagrange_basis; + std::vector coeffs_lagrange_basis(SUBGROUP_SIZE); coeffs_lagrange_basis[0] = FF(1); - for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { - coeffs_lagrange_basis[idx] = FF{ 0 }; - } - for (size_t idx_poly = 0; idx_poly < CONST_PROOF_SIZE_LOG_N; idx_poly++) { for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { size_t current_idx = 1 + LIBRA_UNIVARIATES_LENGTH * idx_poly + idx; @@ -276,6 +271,8 @@ template struct ZKSumcheckData { void setup_big_sum_polynomial() { + // setup_challenge_polynomial(multivariate_challenge); + big_sum_lagrange_coeffs[0] = 0; // Compute the big sum coefficients recursively @@ -357,24 +354,40 @@ template struct ZKSumcheckData { batched_polynomial.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); } } - FF claimed_sum = constant_term; + FF claimed_libra_evaluation = constant_term; for (FF& libra_eval : libra_evaluations) { - claimed_sum += libra_eval; + claimed_libra_evaluation += libra_eval; } for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { - batched_polynomial.at(idx) -= lagrange_last_monomial.at(idx) * claimed_sum; + batched_polynomial.at(idx) -= lagrange_last_monomial.at(idx) * claimed_libra_evaluation; } } // Compute the quotient of batched_polynomial by Z_H = X^{|H|} - 1 void compute_batched_quotient() { + auto remainder = batched_polynomial; for (size_t idx = BATCHED_POLYNOMIAL_LENGTH - 1; idx >= SUBGROUP_SIZE; idx--) { batched_quotient.at(idx - SUBGROUP_SIZE) = remainder.at(idx); remainder.at(idx - SUBGROUP_SIZE) += remainder.at(idx); } } + + void compute_witnesses_and_commit(const std::vector multivariate_challenge, + std::shared_ptr transcript, + std::shared_ptr commitment_key) + { + setup_challenge_polynomial(multivariate_challenge); + setup_big_sum_polynomial(); + + transcript->template send_to_verifier("Libra:big_sum_commitment", commitment_key->commit(big_sum_polynomial)); + + compute_batched_polynomial(); + compute_batched_quotient(); + + transcript->template send_to_verifier("Libra:quotient_commitment", commitment_key->commit(batched_quotient)); + } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index a106f571648..0456f0d7b58 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -178,6 +178,19 @@ void TranslatorProver::execute_pcs_rounds() using OpeningClaim = ProverOpeningClaim; + zk_sumcheck_data.setup_challenge_polynomial(sumcheck_output.challenge); + zk_sumcheck_data.setup_big_sum_polynomial(); + transcript->template send_to_verifier("Libra:big_sum_commitment", + key->commitment_key->commit(zk_sumcheck_data.big_sum_polynomial)); + zk_sumcheck_data.compute_batched_polynomial(); + zk_sumcheck_data.compute_batched_quotient(); + transcript->template send_to_verifier("Libra:quotient_commitment", + key->commitment_key->commit(zk_sumcheck_data.batched_quotient)); + + std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, + zk_sumcheck_data.big_sum_polynomial, + zk_sumcheck_data.batched_quotient }; + const OpeningClaim prover_opening_claim = ShpleminiProver_::prove(key->circuit_size, key->polynomials.get_unshifted_without_concatenated(), @@ -185,8 +198,8 @@ void TranslatorProver::execute_pcs_rounds() sumcheck_output.challenge, key->commitment_key, transcript, - zk_sumcheck_data.libra_univariates_monomial, - sumcheck_output.claimed_libra_evaluations, + libra_polynomials, + sumcheck_output.claimed_libra_evaluation, key->polynomials.get_concatenated(), key->polynomials.get_groups_to_be_concatenated()); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 628d3b0aab1..1438aa4751d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -104,19 +104,25 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) // Receive commitments to Libra masking polynomials std::vector libra_commitments; - for (size_t idx = 0; idx < log_circuit_size; idx++) { - Commitment libra_commitment = - transcript->receive_from_prover("Libra:commitment_" + std::to_string(idx)); - libra_commitments.push_back(libra_commitment); - } - auto [multivariate_challenge, claimed_evaluations, libra_evaluations, sumcheck_verified] = + Commitment libra_commitment = + transcript->template receive_from_prover("Libra:concatenation_commitment"); + libra_commitments.push_back(libra_commitment); + + auto [multivariate_challenge, claimed_evaluations, libra_evaluation, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); // If Sumcheck did not verify, return false if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { return false; } + + Commitment libra_big_sum_commitment = + transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments.push_back(libra_big_sum_commitment); + Commitment libra_quotient_commitment = + transcript->template receive_from_prover("Libra:quotient_commitment"); + libra_commitments.push_back(libra_quotient_commitment); // Execute Shplemini const BatchOpeningClaim opening_claim = @@ -129,8 +135,8 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) Commitment::one(), transcript, Flavor::REPEATED_COMMITMENTS, - RefVector(libra_commitments), - libra_evaluations, + libra_commitments, + libra_evaluation, commitments.get_groups_to_be_concatenated(), claimed_evaluations.get_concatenated()); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 81b4d6dba61..30b9e390c00 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -77,25 +77,15 @@ template void DeciderProver_::execute_pcs_rounds( auto total_time = 0.0; auto start = high_resolution_clock::now(); - // size_t log_circuit_size = proving_key->proving_key.log_circuit_size; - zk_sumcheck_data.setup_challenge_polynomial(sumcheck_output.challenge); - - // compute masked big sum polynomial, commit to it - zk_sumcheck_data.setup_big_sum_polynomial(); - Commitment big_sum_commitment = ck->commit(zk_sumcheck_data.big_sum_polynomial); - transcript->template send_to_verifier("Libra:big_sum_commitment", big_sum_commitment); - - zk_sumcheck_data.compute_batched_polynomial(); - zk_sumcheck_data.compute_batched_quotient(); - Commitment libra_batched_quotient = ck->commit(zk_sumcheck_data.batched_quotient); - transcript->template send_to_verifier("Libra:quotient_commitment", libra_batched_quotient); + zk_sumcheck_data.compute_witnesses_and_commit(sumcheck_output.challenge, transcript, ck); auto end = high_resolution_clock::now(); total_time += duration(end - start).count(); info("total time", total_time); - std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, + std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, + zk_sumcheck_data.big_sum_polynomial, zk_sumcheck_data.big_sum_polynomial, zk_sumcheck_data.batched_quotient }; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 8d57f30eabe..29ecdc34b37 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -46,12 +46,9 @@ template bool DeciderVerifier_::verify() auto sumcheck = SumcheckVerifier( static_cast(accumulator->verification_key->log_circuit_size), transcript, accumulator->target_sum); // For MegaZKFlavor: receive commitments to Libra masking polynomials - std::vector libra_commitments = {}; + std::array libra_commitments = {}; if constexpr (Flavor::HasZK) { - - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:concatenation_commitment"); - libra_commitments.push_back(libra_commitment); + libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); } SumcheckOutput sumcheck_output = sumcheck.verify(accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges); @@ -60,12 +57,8 @@ template bool DeciderVerifier_::verify() FF libra_evaluation{ 0 }; if constexpr (Flavor::HasZK) { libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); - Commitment libra_big_sum_commitment = - transcript->template receive_from_prover("Libra:big_sum_commitment"); - libra_commitments.push_back(libra_big_sum_commitment); - Commitment libra_quotient_commitment = - transcript->template receive_from_prover("Libra:quotient_commitment"); - libra_commitments.push_back(libra_quotient_commitment); + libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); // info("big sum received"); } From d35feb53eb9731e53e00f9f11af844e7ccd1e997 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Mon, 16 Dec 2024 15:14:53 +0000 Subject: [PATCH 12/30] clean up + adding scalar field subgroup generators to curves --- .../commitment_schemes/kzg/kzg.test.cpp | 3 +- .../commitment_schemes/shplonk/shplemini.hpp | 113 ++++++++---------- .../barretenberg/ecc/curves/bn254/bn254.hpp | 4 + .../ecc/curves/grumpkin/grumpkin.hpp | 6 + .../src/barretenberg/eccvm/eccvm_verifier.cpp | 1 + .../eccvm_recursive_verifier.cpp | 24 ++-- .../decider_recursive_verifier.cpp | 3 +- .../ultra_recursive_verifier.cpp | 17 +-- .../stdlib/primitives/curves/bn254.hpp | 9 ++ .../stdlib/primitives/curves/grumpkin.hpp | 2 + .../translator_recursive_verifier.cpp | 16 +-- .../src/barretenberg/sumcheck/sumcheck.hpp | 9 +- .../barretenberg/sumcheck/sumcheck_round.hpp | 3 +- .../sumcheck/zk_sumcheck_data.hpp | 71 ++++------- .../translator_vm/translator_prover.cpp | 14 +-- .../translator_vm/translator_verifier.cpp | 17 +-- .../ultra_honk/decider_verifier.cpp | 1 + 17 files changed, 136 insertions(+), 177 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index e1c3d401f2e..74d55c092c5 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -364,7 +364,8 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShiftAndConcatenation) mle_opening_point, this->vk()->get_g1_identity(), verifier_transcript, - {}, + /* repeated commitments= */ {}, + /* has zk = */ {}, /* libra commitments = */ {}, /* libra evaluations = */ {}, to_vector_of_ref_vectors(concatenation_groups_commitments), diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 071adf2638b..24fd9d69cca 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -49,8 +49,7 @@ template class ShpleminiProver_ { std::vector libra_opening_claims; // static constexpr FF bn_254_subgroup_generator = // FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); - static constexpr FF subgroup_generator = - FF(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); + static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; OpeningClaim new_claim; if (has_zk) { @@ -136,9 +135,6 @@ template class ShpleminiVerifier_ { using ShplonkVerifier = ShplonkVerifier_; using GeminiVerifier = GeminiVerifier_; - // static const Fr grumpkin_subgroup_generator = - // Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); - public: template static BatchOpeningClaim compute_batch_opening_claim( @@ -151,6 +147,7 @@ template class ShpleminiVerifier_ { const Commitment& g1_identity, const std::shared_ptr& transcript, const RepeatedCommitmentsData& repeated_commitments = {}, + const bool has_zk = false, const std::array& libra_commitments = {}, const Fr& libra_univariate_evaluation = Fr{ 0 }, const std::vector>& concatenation_group_commitments = {}, @@ -169,7 +166,6 @@ template class ShpleminiVerifier_ { Fr batched_evaluation = Fr{ 0 }; // While Shplemini is not templated on Flavor, we derive ZK flag this way - const bool has_zk = !(libra_commitments.empty()); Commitment hiding_polynomial_commitment; if (has_zk) { hiding_polynomial_commitment = @@ -193,7 +189,7 @@ template class ShpleminiVerifier_ { const std::vector gemini_eval_challenge_powers = gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, CONST_PROOF_SIZE_LOG_N); - std::array libra_evaluations; + std::vector libra_evaluations(4); if (has_zk) { libra_evaluations[0] = transcript->template receive_from_prover("Libra:concatenation_eval"); libra_evaluations[1] = transcript->template receive_from_prover("Libra:shifted_big_sum_eval"); @@ -641,16 +637,17 @@ template class ShpleminiVerifier_ { static void add_zk_data(std::vector& commitments, std::vector& scalars, const std::array& libra_commitments, - const std::array& libra_evaluations, + const std::vector& libra_evaluations, const Fr& gemini_evaluation_challenge, const Fr& shplonk_batching_challenge, const Fr& shplonk_evaluation_challenge) { + const Fr subgroup_generator = Curve::SUBGROUP_GENERATOR; // const Fr bn_254_subgroup_generator = // Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); - const Fr subgroup_generator = - Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); + // const Fr subgroup_generator = + // Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); // compute current power of Shplonk batching challenge taking into account the const proof size Fr shplonk_challenge_power = Fr{ 1 }; @@ -660,8 +657,13 @@ template class ShpleminiVerifier_ { // need to keep track of the contribution to the constant term Fr& constant_term = scalars.back(); - // compute shplonk denominators and batch invert them + + for (size_t idx = 0; idx < libra_commitments.size(); idx++) { + commitments.push_back(libra_commitments[idx]); + } + std::vector denominators; + std::vector tmp_scalars; // compute Shplonk denominators and invert them denominators.push_back(Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge)); denominators.push_back(Fr(1) / @@ -669,49 +671,36 @@ template class ShpleminiVerifier_ { denominators.push_back(denominators[0]); denominators.push_back(denominators[0]); - for (auto denom : denominators) { - info("verifier denom", denom); - } // add Libra commitments to the vector of commitments; compute corresponding scalars and the correction to // the constant term - commitments.push_back(libra_commitments[0]); - Fr scaling_factor = denominators[0] * shplonk_challenge_power; - info(shplonk_challenge_power); - scalars.push_back(-scaling_factor); - shplonk_challenge_power *= shplonk_batching_challenge; - constant_term += scaling_factor * libra_evaluations[0]; - - commitments.push_back(libra_commitments[1]); - scaling_factor = denominators[1] * shplonk_challenge_power; - shplonk_challenge_power *= shplonk_batching_challenge; - constant_term += scaling_factor * libra_evaluations[1]; - scaling_factor += denominators[2] * shplonk_challenge_power; - scalars.push_back(-scaling_factor); - constant_term += denominators[2] * shplonk_challenge_power * libra_evaluations[2]; - - shplonk_challenge_power *= shplonk_batching_challenge; - - commitments.push_back(libra_commitments[2]); - scaling_factor = denominators[3] * shplonk_challenge_power; - scalars.push_back(-scaling_factor); - shplonk_challenge_power *= shplonk_batching_challenge; - constant_term += scaling_factor * libra_evaluations[3]; + + for (const auto& [denominator, evaluation] : zip_view(denominators, libra_evaluations)) { + Fr scaling_factor = denominator * shplonk_challenge_power; + tmp_scalars.push_back(-scaling_factor); + shplonk_challenge_power *= shplonk_batching_challenge; + constant_term += scaling_factor * evaluation; + } + + scalars.push_back(tmp_scalars[0]); + scalars.push_back(tmp_scalars[1] + tmp_scalars[2]); + scalars.push_back(tmp_scalars[3]); } // Need to check that L_1(r) A(r) + (r-1) (A(g*r) - A(r) - F(r) G(r)) + L_{m+1}(r) (A(r) - s) = T(r) Z_H(r) - static bool libra_consistency_check(std::array& libra_evaluations, + static bool libra_consistency_check(const std::vector& libra_evaluations, const Fr& gemini_evaluation_challenge, std::vector multilinear_challenge, const Fr& eval_claim) { // const Fr bn_254_subgroup_generator = // Fr(1) / Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); - const Fr subgroup_generator = - Fr(1) / Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); + static const Fr subgroup_generator_inverse = Fr(1) / Curve::SUBGROUP_GENERATOR; - Fr vanishing_poly_eval = gemini_evaluation_challenge.pow(87) - Fr(1); + static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; - std::vector challenge_polynomial_lagrange(87); + const Fr vanishing_poly_eval = gemini_evaluation_challenge.pow(SUBGROUP_SIZE) - Fr(1); + + std::vector challenge_polynomial_lagrange(SUBGROUP_SIZE); challenge_polynomial_lagrange[0] = Fr{ 1 }; auto challenge_sqr = Fr{ 1 }; @@ -722,18 +711,18 @@ template class ShpleminiVerifier_ { challenge_polynomial_lagrange[1 + poly_idx * 3 + 2] = challenge_sqr; } - std::array evals = compute_barycentric_evaluation( - challenge_polynomial_lagrange, 87, gemini_evaluation_challenge, subgroup_generator); + auto [challenge_poly, lagrange_first, lagrange_last] = compute_barycentric_evaluation( + challenge_polynomial_lagrange, gemini_evaluation_challenge, subgroup_generator_inverse); + + const Fr& concatenated_at_r = libra_evaluations[0]; + const Fr& big_sum_shifted_eval = libra_evaluations[1]; + const Fr& big_sum_eval = libra_evaluations[2]; + const Fr& quotient_eval = libra_evaluations[3]; - auto& F_at_r = libra_evaluations[0]; - auto& big_sum_shifted_eval = libra_evaluations[1]; - auto& big_sum_eval = libra_evaluations[2]; - auto& quotient_eval = libra_evaluations[3]; - // info("verifier 1/g =", Fr(1) / bn_254_subgroup_generator); - Fr diff = evals[1] * big_sum_eval + - (gemini_evaluation_challenge - subgroup_generator) * - (big_sum_shifted_eval - big_sum_eval - F_at_r * evals[0]) + - evals[2] * (big_sum_eval - eval_claim) - vanishing_poly_eval * quotient_eval; + Fr diff = lagrange_first * big_sum_eval; + diff += (gemini_evaluation_challenge - subgroup_generator_inverse) * + (big_sum_shifted_eval - big_sum_eval - concatenated_at_r * challenge_poly); + diff += lagrange_last * (big_sum_eval - eval_claim) - vanishing_poly_eval * quotient_eval; if constexpr (Curve::is_stdlib_type) { return (diff.get_value() == Fr(0).get_value()); @@ -743,20 +732,20 @@ template class ShpleminiVerifier_ { } static std::array compute_barycentric_evaluation(const std::vector& coeffs, - const size_t num_coeffs, const Fr& z, const Fr& inverse_root_of_unity) { - std::array denominators; + static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; + std::array denominators; Fr one = Fr{ 1 }; Fr numerator = z; - numerator = numerator.pow(num_coeffs) - one; - numerator *= one / Fr(num_coeffs); // (ʓ^n - 1) / n + numerator = numerator.pow(SUBGROUP_SIZE) - one; + numerator *= one / Fr(SUBGROUP_SIZE); // (ʓ^n - 1) / n denominators[0] = z - one; Fr work_root = inverse_root_of_unity; // ω^{-1} - for (size_t i = 1; i < num_coeffs; ++i) { + for (size_t i = 1; i < SUBGROUP_SIZE; ++i) { denominators[i] = work_root * z; // denominators[i] will correspond to L_[i+1] (since our 'commented maths' notation // indexes L_i from 1). So ʓ.ω^{-i} = ʓ.ω^{1-(i+1)} is correct for L_{i+1}. @@ -768,18 +757,18 @@ template class ShpleminiVerifier_ { denominator = one / denominator; } } else { - Fr::batch_invert(&denominators[0], num_coeffs); + Fr::batch_invert(&denominators[0], SUBGROUP_SIZE); } - std::array result = { Fr(0), Fr(0), Fr(0) }; - - for (size_t i = 0; i < num_coeffs; ++i) { + std::array result; + result[0] = Fr{ 0 }; + for (size_t i = 0; i < SUBGROUP_SIZE; ++i) { Fr temp = coeffs[i] * denominators[i]; // f_i * 1/(ʓ.ω^{-i} - 1) result[0] = result[0] + temp; } result[0] = result[0] * numerator; result[1] = denominators[0] * numerator; - result[2] = denominators[87 - 1] * numerator; + result[2] = denominators[SUBGROUP_SIZE - 1] * numerator; // \sum_{i=0}^{num_coeffs-1} f_i * [ʓ^n - 1]/[n.(ʓ.ω^{-i} - 1)] // = \sum_{i=0}^{num_coeffs-1} f_i * L_{i+1} diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp index 8b2308d53b7..fbc90921f6b 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp @@ -23,5 +23,9 @@ class BN254 { // classes are instantiated with "native" curve types. Eventually, the verifier classes will be instantiated only // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = false; + + static constexpr size_t SUBGROUP_SIZE = 87; + static constexpr ScalarField SUBGROUP_GENERATOR = + ScalarField(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); }; } // namespace bb::curve \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp index cbba4dc346c..b2ad8e11e86 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp @@ -54,5 +54,11 @@ class Grumpkin { // classes are instantiated with "native" curve types. Eventually, the verifier classes will be instantiated only // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = false; + + static constexpr size_t SUBGROUP_SIZE = 87; + + static constexpr ScalarField SUBGROUP_GENERATOR = + ScalarField(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); + ; }; } // namespace bb::curve \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 903b7ad63f5..d7ad09cc7ba 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -82,6 +82,7 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) key->pcs_verification_key->get_g1_identity(), transcript, Flavor::REPEATED_COMMITMENTS, + Flavor::HasZK, libra_commitments, libra_evaluation); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp index 71016e4850c..b1408f6b022 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp @@ -3,7 +3,13 @@ #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" #include "barretenberg/transcript/transcript.hpp" +namespace bb::stdlib { +template +const typename grumpkin::ScalarField grumpkin::SUBGROUP_GENERATOR = + typename grumpkin::ScalarField( + uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); +} namespace bb { template @@ -76,24 +82,15 @@ ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) } // Receive commitments to Libra masking polynomials - std::vector libra_commitments = {}; - FF libra_evaluation{ 0 }; - - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:concatenation_commitment"); + std::array libra_commitments = {}; - libra_commitments.push_back(libra_commitment); + libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); auto [multivariate_challenge, claimed_evaluations, claimed_libra_evaluation, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); - libra_evaluation = std::move(claimed_libra_evaluation); - Commitment libra_big_sum_commitment = - transcript->template receive_from_prover("Libra:big_sum_commitment"); - libra_commitments.push_back(libra_big_sum_commitment); - Commitment libra_quotient_commitment = - transcript->template receive_from_prover("Libra:quotient_commitment"); - libra_commitments.push_back(libra_quotient_commitment); + libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); // Compute the Shplemini accumulator consisting of the Shplonk evaluation and the commitments and scalars vector // produced by the unified protocol @@ -107,6 +104,7 @@ ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) key->pcs_verification_key->get_g1_identity(), transcript, Flavor::REPEATED_COMMITMENTS, + Flavor::HasZK, libra_commitments, claimed_libra_evaluation); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp index 162a890e5ff..3be2eb346a5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp @@ -39,7 +39,8 @@ std::array DeciderRecursiveVerifier_:: multivariate_challenge, Commitment::one(builder), transcript, - Flavor::REPEATED_COMMITMENTS); + Flavor::REPEATED_COMMITMENTS, + Flavor::HasZK); auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); return pairing_points; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 281d6fe5ae4..27e217cf22b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -90,13 +90,10 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ auto sumcheck = Sumcheck(log_circuit_size, transcript); // Receive commitments to Libra masking polynomials - std::vector libra_commitments = {}; + std::array libra_commitments = {}; FF libra_evaluation{ 0 }; if constexpr (Flavor::HasZK) { - - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:concatenation_commitment"); - libra_commitments.push_back(libra_commitment); + libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); } SumcheckOutput sumcheck_output = sumcheck.verify(verification_key->relation_parameters, verification_key->alphas, gate_challenges); @@ -104,13 +101,8 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ // For MegaZKFlavor: the sumcheck output contains claimed evaluations of the Libra polynomials if constexpr (Flavor::HasZK) { libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); - Commitment libra_big_sum_commitment = - transcript->template receive_from_prover("Libra:big_sum_commitment"); - libra_commitments.push_back(libra_big_sum_commitment); - Commitment libra_quotient_commitment = - transcript->template receive_from_prover("Libra:quotient_commitment"); - libra_commitments.push_back(libra_quotient_commitment); - // info("big sum received"); + libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); } // Execute Shplemini to produce a batch opening claim subsequently verified by a univariate PCS const BatchOpeningClaim opening_claim = @@ -123,6 +115,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ Commitment::one(builder), transcript, Flavor::REPEATED_COMMITMENTS, + Flavor::HasZK, libra_commitments, libra_evaluation); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp index c15d39d586d..9fa50942d88 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp @@ -41,5 +41,14 @@ template struct bn254 { using bigfr_ct = bigfield; using g1_bigfr_ct = element; + static constexpr size_t SUBGROUP_SIZE = 87; + + static const ScalarField SUBGROUP_GENERATOR; + }; // namespace bn254 +template +const typename bn254::ScalarField bn254::SUBGROUP_GENERATOR = + typename bn254::ScalarField( + uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + } // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp index 8f8555886e6..0a88de777ca 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp @@ -32,5 +32,7 @@ template struct grumpkin { using byte_array_ct = byte_array; using bool_ct = bool_t; using uint32_ct = stdlib::uint32; + static constexpr size_t SUBGROUP_SIZE = 87; + static const ScalarField SUBGROUP_GENERATOR; }; } // namespace bb::stdlib \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index 260c9e10726..1fe3e773bd3 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -111,21 +111,14 @@ std::array TranslatorRecursiveVerifier_template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - std::vector libra_commitments; - - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:concatenation_commitment"); - libra_commitments.push_back(libra_commitment); + std::array libra_commitments = {}; + libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); auto [multivariate_challenge, claimed_evaluations, libra_evaluation, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); - Commitment libra_big_sum_commitment = - transcript->template receive_from_prover("Libra:big_sum_commitment"); - libra_commitments.push_back(libra_big_sum_commitment); - Commitment libra_quotient_commitment = - transcript->template receive_from_prover("Libra:quotient_commitment"); - libra_commitments.push_back(libra_quotient_commitment); + libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); // Execute Shplemini @@ -139,6 +132,7 @@ std::array TranslatorRecursiveVerifier_& zk_sumcheck_data, const FF round_challenge, size_t round_idx) { + constexpr FF one_half = FF(1) / FF(2); // when round_idx = d - 1, the update is not needed if (round_idx < zk_sumcheck_data.libra_univariates.size() - 1) { for (auto& univariate : zk_sumcheck_data.libra_univariates) { - univariate *= FF(1) / FF(2); + univariate *= one_half; }; // compute the evaluation \f$ \rho \cdot 2^{d-2-i} \çdot g_i(u_i) \f$ auto libra_evaluation = zk_sumcheck_data.libra_univariates[round_idx].evaluate(round_challenge); auto next_libra_univariate = zk_sumcheck_data.libra_univariates[round_idx + 1]; // update the running sum by adding g_i(u_i) and subtracting (g_i(0) + g_i(1)) zk_sumcheck_data.libra_running_sum += - -next_libra_univariate.value_at(0) - next_libra_univariate.value_at(1); - zk_sumcheck_data.libra_running_sum *= FF(1) / FF(2); + -next_libra_univariate.evaluate(FF(0)) - next_libra_univariate.evaluate(FF(1)); + zk_sumcheck_data.libra_running_sum *= one_half; zk_sumcheck_data.libra_running_sum += libra_evaluation; - zk_sumcheck_data.libra_scaling_factor *= FF(1) / FF(2); + zk_sumcheck_data.libra_scaling_factor *= one_half; zk_sumcheck_data.libra_evaluations.emplace_back(libra_evaluation / zk_sumcheck_data.libra_scaling_factor); } else { diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index add7d93c78f..3422b1dcec0 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -300,7 +300,8 @@ template class SumcheckProverRound { // the evaluation of Libra round univariate at k=0...D are equal to \f$\texttt{libra_univariates}_{i}(k)\f$ // corrected by the Libra running sum for (size_t idx = 0; idx < libra_round_univariate.size(); ++idx) { - libra_round_univariate.value_at(idx) = current_column.value_at(idx) + zk_sumcheck_data.libra_running_sum; + libra_round_univariate.value_at(idx) = + current_column.evaluate(FF(idx)) + zk_sumcheck_data.libra_running_sum; }; return libra_round_univariate.template extend_to(); } diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 467492855ed..a4539865085 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -16,23 +16,26 @@ namespace bb { */ template struct ZKSumcheckData { using FF = typename Flavor::FF; + + using Curve = Flavor::Curve; /** * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials * \f$P_1,\ldots, P_N\f$. */ static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::MAX_PARTIAL_RELATION_LENGTH; - static constexpr size_t SUBGROUP_SIZE = 87; + static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; static constexpr size_t BATCHED_POLYNOMIAL_LENGTH = 2 * SUBGROUP_SIZE + 2; static constexpr size_t QUOTIENT_LENGTH = SUBGROUP_SIZE + 2; - static constexpr FF grumpkin_subgroup_generator = - FF(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); + static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; + // static constexpr FF grumpkin_subgroup_generator = + // FF(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); - static constexpr FF bn_254_subgroup_generator = - FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + // static constexpr FF bn_254_subgroup_generator = + // FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); /** * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials * \f$P_1,\ldots, P_N\f$ incremented by 1, i.e. it is equal \ref MAX_PARTIAL_RELATION_LENGTH @@ -43,7 +46,7 @@ template struct ZKSumcheckData { // The size of the LibraUnivariates. We ensure that they do not take extra space when Flavor runs non-ZK Sumcheck. static constexpr size_t LIBRA_UNIVARIATES_LENGTH = Flavor::HasZK ? 3 : 0; // Container for the Libra Univariates. Their number depends on the size of the circuit. - using LibraUnivariates = std::vector>; + using LibraUnivariates = std::vector>; // Container for the evaluations of Libra Univariates that have to be proven. using ClaimedLibraEvaluations = std::vector; @@ -62,7 +65,7 @@ template struct ZKSumcheckData { LibraUnivariates libra_univariates; size_t log_circuit_size; - LibraUnivariates libra_univariates_monomial; + // LibraUnivariates libra_univariates_monomial; FF libra_scaling_factor{ 1 }; FF libra_challenge; FF libra_total_sum; @@ -85,10 +88,10 @@ template struct ZKSumcheckData { , batched_quotient(QUOTIENT_LENGTH) // quotient of the batched polynomial by Z_H(X) = X^87 - 1 , libra_univariates(generate_libra_univariates(multivariate_d)) // random univariates of degree 2 , log_circuit_size(multivariate_d) - , libra_univariates_monomial(transform_to_monomial(libra_univariates)) // Required for commiting and by Shplonk { compute_concatenated_libra_polynomial(); + // If proving_key is provided, commit to the concatenated and masked libra polynomial if (commitment_key != nullptr) { auto libra_commitment = commitment_key->commit(libra_concatenated_monomial_form); @@ -122,45 +125,11 @@ template struct ZKSumcheckData { LibraUnivariates libra_full_polynomials(number_of_polynomials); for (auto& libra_polynomial : libra_full_polynomials) { - libra_polynomial = bb::Univariate::get_random(); + libra_polynomial = Polynomial::random(LIBRA_UNIVARIATES_LENGTH); }; return libra_full_polynomials; }; - /** - * @brief Transform Libra univariates from Lagrange to monomial form - * - * @param libra_full_polynomials - * @return LibraUnivariates - */ - static LibraUnivariates transform_to_monomial(LibraUnivariates& libra_full_polynomials) - { - std::array interpolation_domain; - LibraUnivariates libra_univariates_monomial; - libra_univariates_monomial.reserve(libra_full_polynomials.size()); - - for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { - interpolation_domain[idx] = FF(idx); - } - - for (auto& libra_polynomial : libra_full_polynomials) { - - // Use the efficient Lagrange interpolation - Polynomial libra_polynomial_monomial(std::span(interpolation_domain), - std::span(libra_polynomial.evaluations), - LIBRA_UNIVARIATES_LENGTH); - - // To avoid storing Polynomials (coefficients are vectors), we define a univariate with the coefficients - // interpolated above - bb::Univariate libra_univariate; - for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { - libra_univariate.value_at(idx) = libra_polynomial_monomial[idx]; - } - libra_univariates_monomial.push_back(libra_univariate); - }; - return libra_univariates_monomial; - }; - /** * @brief Compute the sum of the randomly sampled multivariate polynomial \f$ G = \sum_{i=0}^{n-1} g_i(X_i) \f$ over * the Boolean hypercube. @@ -177,7 +146,7 @@ template struct ZKSumcheckData { scaling_factor = scaling_factor / 2; for (auto& univariate : libra_univariates) { - total_sum += univariate.value_at(0) + univariate.value_at(1); + total_sum += univariate.evaluate(FF(0)) + univariate.evaluate(FF(1)); scaling_factor *= 2; } total_sum *= scaling_factor; @@ -207,7 +176,7 @@ template struct ZKSumcheckData { univariate *= libra_scaling_factor; }; // subtract the contribution of the first libra univariate from libra total sum - libra_running_sum += -libra_univariates[0].value_at(0) - libra_univariates[0].value_at(1); + libra_running_sum += -libra_univariates[0].evaluate(FF(0)) - libra_univariates[0].evaluate(FF(1)); libra_running_sum *= FF(1) / FF(2); } @@ -215,9 +184,9 @@ template struct ZKSumcheckData { void compute_concatenated_libra_polynomial() { // info(bn_254_subgroup_generator.pow(29 * 3)); - info("root of unity? ", grumpkin_subgroup_generator.pow(3 * 29)); - info("root of unity? ", grumpkin_subgroup_generator.pow(29)); - info("root of unity? ", grumpkin_subgroup_generator.pow(3)); + info("root of unity? ", subgroup_generator.pow(3 * 29)); + info("root of unity? ", subgroup_generator.pow(29)); + info("root of unity? ", subgroup_generator.pow(3)); std::array coeffs_lagrange_subgroup; coeffs_lagrange_subgroup[0] = constant_term; @@ -226,16 +195,16 @@ template struct ZKSumcheckData { coeffs_lagrange_subgroup[idx] = FF{ 0 }; } - for (size_t poly_idx = 0; poly_idx < libra_univariates_monomial.size(); poly_idx++) { + for (size_t poly_idx = 0; poly_idx < log_circuit_size; poly_idx++) { for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { size_t idx_to_populate = 1 + poly_idx * LIBRA_UNIVARIATES_LENGTH + idx; - coeffs_lagrange_subgroup[idx_to_populate] = libra_univariates_monomial[poly_idx].value_at(idx); + coeffs_lagrange_subgroup[idx_to_populate] = libra_univariates[poly_idx].at(idx); } } // create evaluation domain using the generator for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { - interpolation_domain[idx] = grumpkin_subgroup_generator.pow(idx); + interpolation_domain[idx] = subgroup_generator.pow(idx); } libra_concatenated_lagrange_form = Polynomial(coeffs_lagrange_subgroup); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 0456f0d7b58..558bf5d9389 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -178,16 +178,10 @@ void TranslatorProver::execute_pcs_rounds() using OpeningClaim = ProverOpeningClaim; - zk_sumcheck_data.setup_challenge_polynomial(sumcheck_output.challenge); - zk_sumcheck_data.setup_big_sum_polynomial(); - transcript->template send_to_verifier("Libra:big_sum_commitment", - key->commitment_key->commit(zk_sumcheck_data.big_sum_polynomial)); - zk_sumcheck_data.compute_batched_polynomial(); - zk_sumcheck_data.compute_batched_quotient(); - transcript->template send_to_verifier("Libra:quotient_commitment", - key->commitment_key->commit(zk_sumcheck_data.batched_quotient)); - - std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, + zk_sumcheck_data.compute_witnesses_and_commit(sumcheck_output.challenge, transcript, key->commitment_key); + + std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, + zk_sumcheck_data.big_sum_polynomial, zk_sumcheck_data.big_sum_polynomial, zk_sumcheck_data.batched_quotient }; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 1438aa4751d..d6f9cdaaf51 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -103,11 +103,8 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) } // Receive commitments to Libra masking polynomials - std::vector libra_commitments; - - Commitment libra_commitment = - transcript->template receive_from_prover("Libra:concatenation_commitment"); - libra_commitments.push_back(libra_commitment); + std::array libra_commitments = {}; + libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); auto [multivariate_challenge, claimed_evaluations, libra_evaluation, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); @@ -117,12 +114,9 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) return false; } - Commitment libra_big_sum_commitment = - transcript->template receive_from_prover("Libra:big_sum_commitment"); - libra_commitments.push_back(libra_big_sum_commitment); - Commitment libra_quotient_commitment = - transcript->template receive_from_prover("Libra:quotient_commitment"); - libra_commitments.push_back(libra_quotient_commitment); + libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); + libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); + // Execute Shplemini const BatchOpeningClaim opening_claim = @@ -135,6 +129,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) Commitment::one(), transcript, Flavor::REPEATED_COMMITMENTS, + Flavor::HasZK, libra_commitments, libra_evaluation, commitments.get_groups_to_be_concatenated(), diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 29ecdc34b37..4a028d4e3ec 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -78,6 +78,7 @@ template bool DeciderVerifier_::verify() Commitment::one(), transcript, Flavor::REPEATED_COMMITMENTS, + Flavor::HasZK, libra_commitments, libra_evaluation); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); From c9d43c682748271138d0121b46fdd8f9f55e36b4 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Mon, 16 Dec 2024 19:15:06 +0000 Subject: [PATCH 13/30] separated zk sumcheck data from small subgroup ipa --- .../small_subgroup_ipa/small_subgroup_ipa.hpp | 220 ++++++++++++++++++ .../src/barretenberg/eccvm/eccvm_prover.cpp | 10 +- .../sumcheck/zk_sumcheck_data.hpp | 177 +------------- .../translator_vm/translator_prover.cpp | 10 +- .../ultra_honk/decider_prover.cpp | 20 +- 5 files changed, 242 insertions(+), 195 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp 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 new file mode 100644 index 00000000000..33d949e9501 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp @@ -0,0 +1,220 @@ +#pragma once + +#include "barretenberg/constants.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/sumcheck/sumcheck_output.hpp" +#include "barretenberg/sumcheck/zk_sumcheck_data.hpp" + +#include +#include +#include +#include + +namespace bb { + +/** + * @brief This structure is created to contain various polynomials and constants required by ZK Sumcheck. + * + */ +template class SmallSubgroupIPA { + using Curve = typename Flavor::Curve; + using FF = typename Flavor::FF; + + static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; + + static constexpr size_t BATCHED_POLYNOMIAL_LENGTH = 2 * SUBGROUP_SIZE + 2; + + static constexpr size_t QUOTIENT_LENGTH = SUBGROUP_SIZE + 2; + + static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; + + static constexpr size_t LIBRA_UNIVARIATES_LENGTH = 3; + + public: + class SmallSubgroupIPAProver : public SmallSubgroupIPA { + // Container for the Libra Univariates. Their number depends on the size of the circuit. + using LibraUnivariates = std::vector>; + // Container for the evaluations of Libra Univariates that have to be proven. + using ClaimedLibraEvaluations = std::vector; + + std::array interpolation_domain; + // to compute product in lagrange basis + Polynomial concatenated_polynomial; + Polynomial libra_concatenated_lagrange_form; + std::vector multivariate_challenge; + FF claimed_evaluation; + Polynomial challenge_polynomial; + Polynomial challenge_polynomial_lagrange; + + Polynomial big_sum_polynomial; + Polynomial batched_polynomial; + Polynomial batched_quotient; + + FF libra_total_sum; + FF libra_running_sum; + + std::array big_sum_lagrange_coeffs; + + // Main constructor + public: + SmallSubgroupIPAProver(ZKSumcheckData zk_sumcheck_data, + SumcheckOutput sumcheck_output, + std::shared_ptr transcript, + std::shared_ptr commitment_key = nullptr) + : interpolation_domain(zk_sumcheck_data.interpolation_domain) + , concatenated_polynomial(zk_sumcheck_data.libra_concatenated_monomial_form) + , libra_concatenated_lagrange_form(zk_sumcheck_data.libra_concatenated_lagrange_form) + , multivariate_challenge(sumcheck_output.challenge) + , claimed_evaluation(sumcheck_output.claimed_libra_evaluation) + , challenge_polynomial(SUBGROUP_SIZE) // public polynomial + , big_sum_polynomial(SUBGROUP_SIZE + 3) // includes masking + , batched_polynomial(BATCHED_POLYNOMIAL_LENGTH) // batched polynomial, input to shplonk prover + , batched_quotient(QUOTIENT_LENGTH) // quotient of the batched polynomial by Z_H(X) = X^87 - 1 + + { + + ASSERT(concatenated_polynomial.size() < SUBGROUP_SIZE + 3); + + compute_challenge_polynomial(sumcheck_output.challenge); + + compute_big_sum_polynomial(); + if (commitment_key) { + transcript->template send_to_verifier("Libra:big_sum_commitment", + commitment_key->commit(big_sum_polynomial)); + } + + compute_batched_polynomial(claimed_evaluation); + compute_batched_quotient(); + + if (commitment_key) { + transcript->template send_to_verifier("Libra:quotient_commitment", + commitment_key->commit(batched_quotient)); + } + } + + std::array, 4> get_witness_polynomials() const + { + return { concatenated_polynomial, big_sum_polynomial, big_sum_polynomial, batched_quotient }; + } + + // compute concatenated libra polynomial in lagrange basis, transform to monomial, add masking term Z_H(m_0 + + // m_1 X) + void compute_challenge_polynomial(const std::vector& multivariate_challenge) + { + std::vector coeffs_lagrange_basis(SUBGROUP_SIZE); + coeffs_lagrange_basis[0] = FF(1); + + for (size_t idx_poly = 0; idx_poly < CONST_PROOF_SIZE_LOG_N; idx_poly++) { + for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { + size_t current_idx = 1 + LIBRA_UNIVARIATES_LENGTH * idx_poly + idx; + coeffs_lagrange_basis[current_idx] = multivariate_challenge[idx_poly].pow(idx); + } + } + challenge_polynomial_lagrange = Polynomial(coeffs_lagrange_basis); + challenge_polynomial = Polynomial(interpolation_domain, coeffs_lagrange_basis, SUBGROUP_SIZE); + } + + void compute_big_sum_polynomial() + { + big_sum_lagrange_coeffs[0] = 0; + + // Compute the big sum coefficients recursively + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + size_t prev_idx = idx - 1; + big_sum_lagrange_coeffs[idx] = + big_sum_lagrange_coeffs[prev_idx] + + challenge_polynomial_lagrange.at(prev_idx) * libra_concatenated_lagrange_form.at(prev_idx); + }; + + // Get the coefficients in the monomial basis + auto big_sum_polynomial_unmasked = + Polynomial(interpolation_domain, big_sum_lagrange_coeffs, SUBGROUP_SIZE); + + // Generate random masking_term of degree 2, add Z_H(X) * masking_term + bb::Univariate masking_term = bb::Univariate::get_random(); + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + big_sum_polynomial.at(idx) = big_sum_polynomial_unmasked.at(idx); + } + + for (size_t idx = 0; idx < masking_term.size(); idx++) { + big_sum_polynomial.at(idx) -= masking_term.value_at(idx); + big_sum_polynomial.at(idx + SUBGROUP_SIZE) += masking_term.value_at(idx); + } + }; + + void compute_batched_polynomial(const FF& claimed_evaluation) + { + // Compute shifted big sum polynomial A(gX) + Polynomial shifted_big_sum(SUBGROUP_SIZE + 3); + + for (size_t idx = 0; idx < SUBGROUP_SIZE + 3; idx++) { + shifted_big_sum.at(idx) = big_sum_polynomial.at(idx) * interpolation_domain[idx % SUBGROUP_SIZE]; + } + // Compute the monomial coefficients of L_1, the first Lagrange polynomial + std::array lagrange_coeffs; + lagrange_coeffs[0] = FF(1); + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + lagrange_coeffs[idx] = FF(0); + } + + Polynomial lagrange_first_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + + // Compute the monomial coefficients of L_{|H|}, the last Lagrange polynomial + lagrange_coeffs[0] = FF(0); + lagrange_coeffs[SUBGROUP_SIZE - 1] = FF(1); + + Polynomial lagrange_last_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + + // Compute -F(X)*G(X), the negated product of challenge_polynomial and libra_concatenated_monomial_form + // Polynomial result(BATCHED_POLYNOMIAL_LENGTH); + + for (size_t i = 0; i < concatenated_polynomial.size(); ++i) { + for (size_t j = 0; j < challenge_polynomial.size(); ++j) { + batched_polynomial.at(i + j) -= concatenated_polynomial.at(i) * challenge_polynomial.at(j); + } + } + + // Compute - F(X) * G(X) + A(gX) - A(X) + for (size_t idx = 0; idx < shifted_big_sum.size(); idx++) { + batched_polynomial.at(idx) += shifted_big_sum.at(idx) - big_sum_polynomial.at(idx); + } + + // Mutiply - F(X) * G(X) + A(gX) - A(X) by X-g: + // 1. Multiply by X + for (size_t idx = batched_polynomial.size() - 1; idx > 0; idx--) { + batched_polynomial.at(idx) = batched_polynomial.at(idx - 1); + } + batched_polynomial.at(0) = FF(0); + // 2. Subtract 1/g(A(gX) - A(X) - F(X) * G(X)) + for (size_t idx = 0; idx < batched_polynomial.size() - 1; idx++) { + batched_polynomial.at(idx) -= batched_polynomial.at(idx + 1) * interpolation_domain[SUBGROUP_SIZE - 1]; + } + + // Add (L_1 + L_{|H|}) * A(X) to the result + lagrange_first_monomial += lagrange_last_monomial; + + for (size_t i = 0; i < big_sum_polynomial.size(); ++i) { + for (size_t j = 0; j < lagrange_first_monomial.size(); ++j) { + batched_polynomial.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); + } + } + + for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { + batched_polynomial.at(idx) -= lagrange_last_monomial.at(idx) * claimed_evaluation; + } + } + + // Compute the quotient of batched_polynomial by Z_H = X^{|H|} - 1 + void compute_batched_quotient() + { + + auto remainder = batched_polynomial; + for (size_t idx = BATCHED_POLYNOMIAL_LENGTH - 1; idx >= SUBGROUP_SIZE; idx--) { + batched_quotient.at(idx - SUBGROUP_SIZE) = remainder.at(idx); + remainder.at(idx - SUBGROUP_SIZE) += remainder.at(idx); + } + } + }; +}; +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index c918f7fedb1..48d358e3da5 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -3,6 +3,7 @@ #include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" +#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" #include "barretenberg/common/ref_array.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" @@ -121,13 +122,10 @@ void ECCVMProver::execute_pcs_rounds() using Shplemini = ShpleminiProver_; using Shplonk = ShplonkProver_; using OpeningClaim = ProverOpeningClaim; + using SmallSubgroupIPA = SmallSubgroupIPA::SmallSubgroupIPAProver; - zk_sumcheck_data.compute_witnesses_and_commit(sumcheck_output.challenge, transcript, key->commitment_key); + SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output, transcript, key->commitment_key); - std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, - zk_sumcheck_data.big_sum_polynomial, - zk_sumcheck_data.big_sum_polynomial, - zk_sumcheck_data.batched_quotient }; // Execute the Shplemini (Gemini + Shplonk) protocol to produce a univariate opening claim for the multilinear // evaluations produced by Sumcheck const OpeningClaim multivariate_to_univariate_opening_claim = @@ -137,7 +135,7 @@ void ECCVMProver::execute_pcs_rounds() sumcheck_output.challenge, key->commitment_key, transcript, - libra_polynomials, + small_subgroup_ipa_prover.get_witness_polynomials(), sumcheck_output.claimed_libra_evaluation); // Get the challenge at which we evaluate all transcript polynomials as univariates diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index a4539865085..35333076eee 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -18,18 +18,9 @@ template struct ZKSumcheckData { using FF = typename Flavor::FF; using Curve = Flavor::Curve; - /** - * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials - * \f$P_1,\ldots, P_N\f$. - */ - static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::MAX_PARTIAL_RELATION_LENGTH; static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; - static constexpr size_t BATCHED_POLYNOMIAL_LENGTH = 2 * SUBGROUP_SIZE + 2; - - static constexpr size_t QUOTIENT_LENGTH = SUBGROUP_SIZE + 2; - static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; // static constexpr FF grumpkin_subgroup_generator = // FF(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); @@ -56,22 +47,13 @@ template struct ZKSumcheckData { Polynomial libra_concatenated_lagrange_form; Polynomial libra_concatenated_monomial_form; - Polynomial challenge_polynomial; - Polynomial challenge_polynomial_lagrange; - - Polynomial big_sum_polynomial; - Polynomial batched_polynomial; - Polynomial batched_quotient; - LibraUnivariates libra_univariates; size_t log_circuit_size; - // LibraUnivariates libra_univariates_monomial; FF libra_scaling_factor{ 1 }; FF libra_challenge; FF libra_total_sum; FF libra_running_sum; ClaimedLibraEvaluations libra_evaluations; - std::array big_sum_lagrange_coeffs; // Default constructor ZKSumcheckData() = default; @@ -81,15 +63,13 @@ template struct ZKSumcheckData { std::shared_ptr transcript, std::shared_ptr commitment_key = nullptr) : constant_term(FF::random_element()) - , libra_concatenated_monomial_form(SUBGROUP_SIZE + 2) // includes masking - , challenge_polynomial(SUBGROUP_SIZE) // public polynomial - , big_sum_polynomial(SUBGROUP_SIZE + 3) // includes masking - , batched_polynomial(BATCHED_POLYNOMIAL_LENGTH) // batched polynomial, input to shplonk prover - , batched_quotient(QUOTIENT_LENGTH) // quotient of the batched polynomial by Z_H(X) = X^87 - 1 + , libra_concatenated_monomial_form(SUBGROUP_SIZE + 2) // includes masking , libra_univariates(generate_libra_univariates(multivariate_d)) // random univariates of degree 2 , log_circuit_size(multivariate_d) { + create_interpolation_domain(); + compute_concatenated_libra_polynomial(); // If proving_key is provided, commit to the concatenated and masked libra polynomial @@ -180,14 +160,16 @@ template struct ZKSumcheckData { libra_running_sum *= FF(1) / FF(2); } + void create_interpolation_domain() + { + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + interpolation_domain[idx] = subgroup_generator.pow(idx); + } + } + // compute concatenated libra polynomial in lagrange basis, transform to monomial, add masking term Z_H(m_0 + m_1 X) void compute_concatenated_libra_polynomial() { - // info(bn_254_subgroup_generator.pow(29 * 3)); - info("root of unity? ", subgroup_generator.pow(3 * 29)); - info("root of unity? ", subgroup_generator.pow(29)); - info("root of unity? ", subgroup_generator.pow(3)); - std::array coeffs_lagrange_subgroup; coeffs_lagrange_subgroup[0] = constant_term; @@ -202,11 +184,6 @@ template struct ZKSumcheckData { } } - // create evaluation domain using the generator - for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { - interpolation_domain[idx] = subgroup_generator.pow(idx); - } - libra_concatenated_lagrange_form = Polynomial(coeffs_lagrange_subgroup); bb::Univariate masking_scalars = bb::Univariate::get_random(); @@ -223,140 +200,6 @@ template struct ZKSumcheckData { libra_concatenated_monomial_form.at(SUBGROUP_SIZE + idx) += masking_scalars.value_at(idx); } } - void setup_challenge_polynomial(const std::vector& multivariate_challenge) - { - std::vector coeffs_lagrange_basis(SUBGROUP_SIZE); - coeffs_lagrange_basis[0] = FF(1); - - for (size_t idx_poly = 0; idx_poly < CONST_PROOF_SIZE_LOG_N; idx_poly++) { - for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { - size_t current_idx = 1 + LIBRA_UNIVARIATES_LENGTH * idx_poly + idx; - coeffs_lagrange_basis[current_idx] = multivariate_challenge[idx_poly].pow(idx); - } - } - challenge_polynomial_lagrange = Polynomial(coeffs_lagrange_basis); - challenge_polynomial = Polynomial(interpolation_domain, coeffs_lagrange_basis, SUBGROUP_SIZE); - } - - void setup_big_sum_polynomial() - { - // setup_challenge_polynomial(multivariate_challenge); - - big_sum_lagrange_coeffs[0] = 0; - - // Compute the big sum coefficients recursively - for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { - size_t prev_idx = idx - 1; - big_sum_lagrange_coeffs[idx] = - big_sum_lagrange_coeffs[prev_idx] + - challenge_polynomial_lagrange.at(prev_idx) * libra_concatenated_lagrange_form.at(prev_idx); - }; - - // Get the coefficients in the monomial basis - auto big_sum_polynomial_unmasked = Polynomial(interpolation_domain, big_sum_lagrange_coeffs, SUBGROUP_SIZE); - - // Generate random masking_term of degree 2, add Z_H(X) * masking_term - bb::Univariate masking_term = bb::Univariate::get_random(); - for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { - big_sum_polynomial.at(idx) = big_sum_polynomial_unmasked.at(idx); - } - - for (size_t idx = 0; idx < masking_term.size(); idx++) { - big_sum_polynomial.at(idx) -= masking_term.value_at(idx); - big_sum_polynomial.at(idx + SUBGROUP_SIZE) += masking_term.value_at(idx); - } - }; - - void compute_batched_polynomial() - { - // Compute shifted big sum polynomial A(gX) - Polynomial shifted_big_sum(SUBGROUP_SIZE + 3); - - for (size_t idx = 0; idx < SUBGROUP_SIZE + 3; idx++) { - shifted_big_sum.at(idx) = big_sum_polynomial.at(idx) * interpolation_domain[idx % SUBGROUP_SIZE]; - } - // Compute the monomial coefficients of L_1, the first Lagrange polynomial - std::array lagrange_coeffs; - lagrange_coeffs[0] = FF(1); - for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { - lagrange_coeffs[idx] = FF(0); - } - - Polynomial lagrange_first_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); - - // Compute the monomial coefficients of L_{|H|}, the last Lagrange polynomial - lagrange_coeffs[0] = 0; - lagrange_coeffs[SUBGROUP_SIZE - 1] = 1; - - Polynomial lagrange_last_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); - - // Compute -F(X)*G(X), the negated product of challenge_polynomial and libra_concatenated_monomial_form - // Polynomial result(BATCHED_POLYNOMIAL_LENGTH); - - for (size_t i = 0; i < libra_concatenated_monomial_form.size(); ++i) { - for (size_t j = 0; j < challenge_polynomial.size(); ++j) { - batched_polynomial.at(i + j) -= libra_concatenated_monomial_form.at(i) * challenge_polynomial.at(j); - } - } - - // Compute - F(X) * G(X) + A(gX) - A(X) - for (size_t idx = 0; idx < shifted_big_sum.size(); idx++) { - batched_polynomial.at(idx) += shifted_big_sum.at(idx) - big_sum_polynomial.at(idx); - } - - // Mutiply - F(X) * G(X) + A(gX) - A(X) by X-g: - // 1. Multiply by X - for (size_t idx = batched_polynomial.size() - 1; idx > 0; idx--) { - batched_polynomial.at(idx) = batched_polynomial.at(idx - 1); - } - batched_polynomial.at(0) = FF(0); - // 2. Subtract 1/g(A(gX) - A(X) - F(X) * G(X)) - for (size_t idx = 0; idx < batched_polynomial.size() - 1; idx++) { - batched_polynomial.at(idx) -= batched_polynomial.at(idx + 1) * interpolation_domain[SUBGROUP_SIZE - 1]; - } - - // Add (L_1 + L_{|H|}) * A(X) to the result - lagrange_first_monomial += lagrange_last_monomial; - - for (size_t i = 0; i < big_sum_polynomial.size(); ++i) { - for (size_t j = 0; j < lagrange_first_monomial.size(); ++j) { - batched_polynomial.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); - } - } - FF claimed_libra_evaluation = constant_term; - for (FF& libra_eval : libra_evaluations) { - claimed_libra_evaluation += libra_eval; - } - for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { - batched_polynomial.at(idx) -= lagrange_last_monomial.at(idx) * claimed_libra_evaluation; - } - } - - // Compute the quotient of batched_polynomial by Z_H = X^{|H|} - 1 - void compute_batched_quotient() - { - - auto remainder = batched_polynomial; - for (size_t idx = BATCHED_POLYNOMIAL_LENGTH - 1; idx >= SUBGROUP_SIZE; idx--) { - batched_quotient.at(idx - SUBGROUP_SIZE) = remainder.at(idx); - remainder.at(idx - SUBGROUP_SIZE) += remainder.at(idx); - } - } - - void compute_witnesses_and_commit(const std::vector multivariate_challenge, - std::shared_ptr transcript, - std::shared_ptr commitment_key) - { - setup_challenge_polynomial(multivariate_challenge); - setup_big_sum_polynomial(); - - transcript->template send_to_verifier("Libra:big_sum_commitment", commitment_key->commit(big_sum_polynomial)); - - compute_batched_polynomial(); - compute_batched_quotient(); - - transcript->template send_to_verifier("Libra:quotient_commitment", commitment_key->commit(batched_quotient)); - } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 558bf5d9389..969f7a94399 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -2,6 +2,7 @@ #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" +#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" @@ -178,12 +179,9 @@ void TranslatorProver::execute_pcs_rounds() using OpeningClaim = ProverOpeningClaim; - zk_sumcheck_data.compute_witnesses_and_commit(sumcheck_output.challenge, transcript, key->commitment_key); + using SmallSubgroupIPA = SmallSubgroupIPA::SmallSubgroupIPAProver; - std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, - zk_sumcheck_data.big_sum_polynomial, - zk_sumcheck_data.big_sum_polynomial, - zk_sumcheck_data.batched_quotient }; + SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output, transcript, key->commitment_key); const OpeningClaim prover_opening_claim = ShpleminiProver_::prove(key->circuit_size, @@ -192,7 +190,7 @@ void TranslatorProver::execute_pcs_rounds() sumcheck_output.challenge, key->commitment_key, transcript, - libra_polynomials, + small_subgroup_ipa_prover.get_witness_polynomials(), sumcheck_output.claimed_libra_evaluation, key->polynomials.get_concatenated(), key->polynomials.get_groups_to_be_concatenated()); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 30b9e390c00..54eac2ac452 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -1,4 +1,5 @@ #include "decider_prover.hpp" +#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" #include "barretenberg/common/op_count.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" @@ -58,6 +59,7 @@ template void DeciderProver_::execute_relation_ch template void DeciderProver_::execute_pcs_rounds() { using OpeningClaim = ProverOpeningClaim; + using SmallSubgroupIPA = SmallSubgroupIPA::SmallSubgroupIPAProver; auto& ck = proving_key->proving_key.commitment_key; ck = ck ? ck : std::make_shared(proving_key->proving_key.circuit_size); @@ -72,22 +74,8 @@ template void DeciderProver_::execute_pcs_rounds( ck, transcript); } else { - using namespace std::chrono; - auto total_time = 0.0; - auto start = high_resolution_clock::now(); - - zk_sumcheck_data.compute_witnesses_and_commit(sumcheck_output.challenge, transcript, ck); - - auto end = high_resolution_clock::now(); - total_time += duration(end - start).count(); - - info("total time", total_time); - - std::array libra_polynomials = { zk_sumcheck_data.libra_concatenated_monomial_form, - zk_sumcheck_data.big_sum_polynomial, - zk_sumcheck_data.big_sum_polynomial, - zk_sumcheck_data.batched_quotient }; + SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output, transcript, ck); prover_opening_claim = ShpleminiProver_::prove(proving_key->proving_key.circuit_size, proving_key->proving_key.polynomials.get_unshifted(), @@ -95,7 +83,7 @@ template void DeciderProver_::execute_pcs_rounds( sumcheck_output.challenge, ck, transcript, - libra_polynomials, + small_subgroup_ipa_prover.get_witness_polynomials(), sumcheck_output.claimed_libra_evaluation); } vinfo("executed multivariate-to-univariate reduction"); From 559626caddbd6bc80cd8db0cf073ae3d08c7559c Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Tue, 17 Dec 2024 16:01:38 +0000 Subject: [PATCH 14/30] isolated small subgroup ipa verifier methods --- .../barretenberg/commitment_schemes/claim.hpp | 1 + .../commitment_schemes/shplonk/shplemini.hpp | 130 +---- .../small_subgroup_ipa/small_subgroup_ipa.hpp | 484 ++++++++++++------ .../src/barretenberg/eccvm/eccvm_prover.cpp | 2 +- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 2 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 1 - .../translator_vm/translator_prover.cpp | 2 +- .../translator_vm/translator_verifier.cpp | 2 +- .../ultra_honk/decider_prover.cpp | 2 +- .../ultra_honk/decider_verifier.cpp | 2 +- 10 files changed, 344 insertions(+), 284 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp index 1afb02a3c66..d6f314b2b40 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp @@ -110,5 +110,6 @@ template struct BatchOpeningClaim { std::vector commitments; std::vector scalars; typename Curve::ScalarField evaluation_point; + bool consistency_checked = true; }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 24fd9d69cca..a4e4abffc4b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -3,6 +3,7 @@ #include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/commitment_schemes/gemini/gemini_impl.hpp" #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" +#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" #include "barretenberg/commitment_schemes/verification_key.hpp" #include "barretenberg/flavor/repeated_commitments_data.hpp" #include "barretenberg/sumcheck/zk_sumcheck_data.hpp" @@ -315,6 +316,8 @@ template class ShpleminiVerifier_ { // For ZK flavors, the sumcheck output contains the evaluations of Libra univariates that submitted to the // ShpleminiVerifier, otherwise this argument is set to be empty + bool consistency_checked = true; + info("has zk ", has_zk, " cons checked ", consistency_checked); if (has_zk) { add_zk_data(commitments, scalars, @@ -323,28 +326,12 @@ template class ShpleminiVerifier_ { gemini_evaluation_challenge, shplonk_batching_challenge, shplonk_evaluation_challenge); - if constexpr (Curve::is_stdlib_type) { - - auto builder = gemini_evaluation_challenge.get_context(); - size_t num_gates = builder->num_gates; - auto checked = libra_consistency_check(libra_evaluations, - gemini_evaluation_challenge, - multivariate_challenge, - libra_univariate_evaluation); - info("Libra consisitency check num gates ", builder->num_gates - num_gates); - info(checked); - } else { - auto checked = libra_consistency_check(libra_evaluations, - gemini_evaluation_challenge, - multivariate_challenge, - libra_univariate_evaluation); - info("libra consistency check", checked); - } - // info("Libra consisitency check num gates ", builder->num_gates - num_gates); + consistency_checked = SmallSubgroupIPAVerifier::evaluations_consistency_check( + libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation); } - info("batch mul size ", commitments.size()); - return { commitments, scalars, shplonk_evaluation_challenge }; + + return { commitments, scalars, shplonk_evaluation_challenge, consistency_checked }; }; /** * @brief Populates the vectors of commitments and scalars, and computes the evaluation of the batched @@ -644,10 +631,6 @@ template class ShpleminiVerifier_ { { const Fr subgroup_generator = Curve::SUBGROUP_GENERATOR; - // const Fr bn_254_subgroup_generator = - // Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); - // const Fr subgroup_generator = - // Fr(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); // compute current power of Shplonk batching challenge taking into account the const proof size Fr shplonk_challenge_power = Fr{ 1 }; @@ -658,6 +641,8 @@ template class ShpleminiVerifier_ { // need to keep track of the contribution to the constant term Fr& constant_term = scalars.back(); + // add Libra commitments to the vector of commitments; compute corresponding scalars and the correction to + // the constant term for (size_t idx = 0; idx < libra_commitments.size(); idx++) { commitments.push_back(libra_commitments[idx]); } @@ -671,9 +656,8 @@ template class ShpleminiVerifier_ { denominators.push_back(denominators[0]); denominators.push_back(denominators[0]); - // add Libra commitments to the vector of commitments; compute corresponding scalars and the correction to - // the constant term - + // compute the scalars to be multiplied against the commitments [libra_concatenated], [big_sum], [big_sum], and + // [libra_quotient] for (const auto& [denominator, evaluation] : zip_view(denominators, libra_evaluations)) { Fr scaling_factor = denominator * shplonk_challenge_power; tmp_scalars.push_back(-scaling_factor); @@ -681,100 +665,10 @@ template class ShpleminiVerifier_ { constant_term += scaling_factor * evaluation; } + // to save a scalar mul, add the sum of the scalars corresponding to the big sum evaluations scalars.push_back(tmp_scalars[0]); scalars.push_back(tmp_scalars[1] + tmp_scalars[2]); scalars.push_back(tmp_scalars[3]); } - - // Need to check that L_1(r) A(r) + (r-1) (A(g*r) - A(r) - F(r) G(r)) + L_{m+1}(r) (A(r) - s) = T(r) Z_H(r) - static bool libra_consistency_check(const std::vector& libra_evaluations, - const Fr& gemini_evaluation_challenge, - std::vector multilinear_challenge, - const Fr& eval_claim) - { - // const Fr bn_254_subgroup_generator = - // Fr(1) / Fr(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); - static const Fr subgroup_generator_inverse = Fr(1) / Curve::SUBGROUP_GENERATOR; - - static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; - - const Fr vanishing_poly_eval = gemini_evaluation_challenge.pow(SUBGROUP_SIZE) - Fr(1); - - std::vector challenge_polynomial_lagrange(SUBGROUP_SIZE); - - challenge_polynomial_lagrange[0] = Fr{ 1 }; - auto challenge_sqr = Fr{ 1 }; - for (size_t poly_idx = 0; poly_idx < CONST_PROOF_SIZE_LOG_N; poly_idx++) { - challenge_polynomial_lagrange[1 + poly_idx * 3] = Fr{ 1 }; - challenge_polynomial_lagrange[1 + poly_idx * 3 + 1] = multilinear_challenge[poly_idx]; - challenge_sqr = multilinear_challenge[poly_idx] * multilinear_challenge[poly_idx]; - challenge_polynomial_lagrange[1 + poly_idx * 3 + 2] = challenge_sqr; - } - - auto [challenge_poly, lagrange_first, lagrange_last] = compute_barycentric_evaluation( - challenge_polynomial_lagrange, gemini_evaluation_challenge, subgroup_generator_inverse); - - const Fr& concatenated_at_r = libra_evaluations[0]; - const Fr& big_sum_shifted_eval = libra_evaluations[1]; - const Fr& big_sum_eval = libra_evaluations[2]; - const Fr& quotient_eval = libra_evaluations[3]; - - Fr diff = lagrange_first * big_sum_eval; - diff += (gemini_evaluation_challenge - subgroup_generator_inverse) * - (big_sum_shifted_eval - big_sum_eval - concatenated_at_r * challenge_poly); - diff += lagrange_last * (big_sum_eval - eval_claim) - vanishing_poly_eval * quotient_eval; - - if constexpr (Curve::is_stdlib_type) { - return (diff.get_value() == Fr(0).get_value()); - } else { - return (diff == Fr(0)); - }; - } - - static std::array compute_barycentric_evaluation(const std::vector& coeffs, - const Fr& z, - const Fr& inverse_root_of_unity) - { - static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; - std::array denominators; - Fr one = Fr{ 1 }; - Fr numerator = z; - - numerator = numerator.pow(SUBGROUP_SIZE) - one; - numerator *= one / Fr(SUBGROUP_SIZE); // (ʓ^n - 1) / n - - denominators[0] = z - one; - Fr work_root = inverse_root_of_unity; // ω^{-1} - for (size_t i = 1; i < SUBGROUP_SIZE; ++i) { - denominators[i] = - work_root * z; // denominators[i] will correspond to L_[i+1] (since our 'commented maths' notation - // indexes L_i from 1). So ʓ.ω^{-i} = ʓ.ω^{1-(i+1)} is correct for L_{i+1}. - denominators[i] -= one; // ʓ.ω^{-i} - 1 - work_root *= inverse_root_of_unity; - } - if constexpr (Curve::is_stdlib_type) { - for (Fr& denominator : denominators) { - denominator = one / denominator; - } - } else { - Fr::batch_invert(&denominators[0], SUBGROUP_SIZE); - } - std::array result; - result[0] = Fr{ 0 }; - for (size_t i = 0; i < SUBGROUP_SIZE; ++i) { - Fr temp = coeffs[i] * denominators[i]; // f_i * 1/(ʓ.ω^{-i} - 1) - result[0] = result[0] + temp; - } - - result[0] = result[0] * numerator; - result[1] = denominators[0] * numerator; - result[2] = denominators[SUBGROUP_SIZE - 1] * numerator; - - // \sum_{i=0}^{num_coeffs-1} f_i * [ʓ^n - 1]/[n.(ʓ.ω^{-i} - 1)] - // = \sum_{i=0}^{num_coeffs-1} f_i * L_{i+1} - // (with our somewhat messy 'commented maths' convention that L_1 corresponds to the 0th coeff). - - return result; - } }; } // 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 33d949e9501..159978d50f4 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 @@ -17,7 +17,8 @@ namespace bb { * @brief This structure is created to contain various polynomials and constants required by ZK Sumcheck. * */ -template class SmallSubgroupIPA { + +template class SmallSubgroupIPAProver { using Curve = typename Flavor::Curve; using FF = typename Flavor::FF; @@ -27,194 +28,359 @@ template class SmallSubgroupIPA { static constexpr size_t QUOTIENT_LENGTH = SUBGROUP_SIZE + 2; + static constexpr size_t LIBRA_UNIVARIATES_LENGTH = 3; + static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; - static constexpr size_t LIBRA_UNIVARIATES_LENGTH = 3; + // Interpolation domain {1, g, \ldots, g^{SUBGROUP_SIZE - 1}} + std::array interpolation_domain; + + // Monomial coefficients of the concatenated Libra masking polynomial + Polynomial concatenated_polynomial; + // Lagrange coefficeints of the concatenated Libra masking polynomial = constant_term || g_0 || ... || g_{d-1} + Polynomial libra_concatenated_lagrange_form; + + // Claimed evaluation s = constant_term + g_0(u_0) + ... + g_{d-1}(u_{d-1}) + FF claimed_evaluation; + + // Monomial coefficients of the challenge polynomial + Polynomial challenge_polynomial; + // Challenge polynomial constructed as (1, 1, u_0, u_0^2, 1, u_1,..., u_{27}^2 ) + Polynomial challenge_polynomial_lagrange; + + // Monomial coefficients of the polynomial A satisfying A_0 = 0, A_{i} = A_{i-1} + F_{i-1} * G_{i-1} + Polynomial big_sum_polynomial; + std::array big_sum_lagrange_coeffs; + + // L_1(X) * A(X) + (X - 1/g) (A(gX) - A(X) - F(X) G(X)) + L_{|H|}(X)(A(X) - s) + Polynomial batched_polynomial; + + // Quotient of the batched polynomial by the subgroup vanishing polynomial X^{|H|} - 1 + Polynomial batched_quotient; public: - class SmallSubgroupIPAProver : public SmallSubgroupIPA { - // Container for the Libra Univariates. Their number depends on the size of the circuit. - using LibraUnivariates = std::vector>; - // Container for the evaluations of Libra Univariates that have to be proven. - using ClaimedLibraEvaluations = std::vector; - - std::array interpolation_domain; - // to compute product in lagrange basis - Polynomial concatenated_polynomial; - Polynomial libra_concatenated_lagrange_form; - std::vector multivariate_challenge; - FF claimed_evaluation; - Polynomial challenge_polynomial; - Polynomial challenge_polynomial_lagrange; - - Polynomial big_sum_polynomial; - Polynomial batched_polynomial; - Polynomial batched_quotient; - - FF libra_total_sum; - FF libra_running_sum; - - std::array big_sum_lagrange_coeffs; - - // Main constructor - public: - SmallSubgroupIPAProver(ZKSumcheckData zk_sumcheck_data, - SumcheckOutput sumcheck_output, - std::shared_ptr transcript, - std::shared_ptr commitment_key = nullptr) - : interpolation_domain(zk_sumcheck_data.interpolation_domain) - , concatenated_polynomial(zk_sumcheck_data.libra_concatenated_monomial_form) - , libra_concatenated_lagrange_form(zk_sumcheck_data.libra_concatenated_lagrange_form) - , multivariate_challenge(sumcheck_output.challenge) - , claimed_evaluation(sumcheck_output.claimed_libra_evaluation) - , challenge_polynomial(SUBGROUP_SIZE) // public polynomial - , big_sum_polynomial(SUBGROUP_SIZE + 3) // includes masking - , batched_polynomial(BATCHED_POLYNOMIAL_LENGTH) // batched polynomial, input to shplonk prover - , batched_quotient(QUOTIENT_LENGTH) // quotient of the batched polynomial by Z_H(X) = X^87 - 1 - - { - - ASSERT(concatenated_polynomial.size() < SUBGROUP_SIZE + 3); - - compute_challenge_polynomial(sumcheck_output.challenge); - - compute_big_sum_polynomial(); - if (commitment_key) { - transcript->template send_to_verifier("Libra:big_sum_commitment", - commitment_key->commit(big_sum_polynomial)); - } + // Default constructor for non-ZK Flavors + SmallSubgroupIPAProver() + : interpolation_domain{} + , concatenated_polynomial(0) + , libra_concatenated_lagrange_form(0) + , challenge_polynomial(0) + , challenge_polynomial_lagrange(0) // public polynomial + , big_sum_polynomial(0) // includes masking + , batched_polynomial(0) // batched polynomial, input to shplonk prover + , batched_quotient(0) + {} + + SmallSubgroupIPAProver(const ZKSumcheckData& zk_sumcheck_data, + const SumcheckOutput& sumcheck_output, + std::shared_ptr transcript, + std::shared_ptr commitment_key = nullptr) + : interpolation_domain(zk_sumcheck_data.interpolation_domain) + , concatenated_polynomial(zk_sumcheck_data.libra_concatenated_monomial_form) + , libra_concatenated_lagrange_form(zk_sumcheck_data.libra_concatenated_lagrange_form) + , challenge_polynomial(SUBGROUP_SIZE) + , challenge_polynomial_lagrange(SUBGROUP_SIZE) // public polynomial + , big_sum_polynomial(SUBGROUP_SIZE + 3) // includes masking + , batched_polynomial(BATCHED_POLYNOMIAL_LENGTH) // batched polynomial, input to shplonk prover + , batched_quotient(QUOTIENT_LENGTH) // quotient of the batched polynomial by Z_H(X) = X^87 - 1 + + { + + ASSERT(concatenated_polynomial.size() < SUBGROUP_SIZE + 3); + + compute_challenge_polynomial(sumcheck_output.challenge); + + compute_big_sum_polynomial(); + if (commitment_key) { + transcript->template send_to_verifier("Libra:big_sum_commitment", + commitment_key->commit(big_sum_polynomial)); + } - compute_batched_polynomial(claimed_evaluation); - compute_batched_quotient(); + compute_batched_polynomial(sumcheck_output.claimed_libra_evaluation); + compute_batched_quotient(); - if (commitment_key) { - transcript->template send_to_verifier("Libra:quotient_commitment", - commitment_key->commit(batched_quotient)); + if (commitment_key) { + transcript->template send_to_verifier("Libra:quotient_commitment", + commitment_key->commit(batched_quotient)); + } + } + + std::array, 4> get_witness_polynomials() const + { + return { concatenated_polynomial, big_sum_polynomial, big_sum_polynomial, batched_quotient }; + } + + // compute concatenated libra polynomial in lagrange basis, transform to monomial, add masking term Z_H(m_0 + + // m_1 X) + void compute_challenge_polynomial(const std::vector& multivariate_challenge) + { + std::vector coeffs_lagrange_basis(SUBGROUP_SIZE); + coeffs_lagrange_basis[0] = FF(1); + + for (size_t idx_poly = 0; idx_poly < CONST_PROOF_SIZE_LOG_N; idx_poly++) { + for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { + size_t current_idx = 1 + LIBRA_UNIVARIATES_LENGTH * idx_poly + idx; + coeffs_lagrange_basis[current_idx] = multivariate_challenge[idx_poly].pow(idx); } } + challenge_polynomial_lagrange = Polynomial(coeffs_lagrange_basis); + challenge_polynomial = Polynomial(interpolation_domain, coeffs_lagrange_basis, SUBGROUP_SIZE); + } + + void compute_big_sum_polynomial() + { + big_sum_lagrange_coeffs[0] = 0; + + // Compute the big sum coefficients recursively + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + size_t prev_idx = idx - 1; + big_sum_lagrange_coeffs[idx] = + big_sum_lagrange_coeffs[prev_idx] + + challenge_polynomial_lagrange.at(prev_idx) * libra_concatenated_lagrange_form.at(prev_idx); + }; + + // Get the coefficients in the monomial basis + auto big_sum_polynomial_unmasked = Polynomial(interpolation_domain, big_sum_lagrange_coeffs, SUBGROUP_SIZE); - std::array, 4> get_witness_polynomials() const - { - return { concatenated_polynomial, big_sum_polynomial, big_sum_polynomial, batched_quotient }; + // Generate random masking_term of degree 2, add Z_H(X) * masking_term + bb::Univariate masking_term = bb::Univariate::get_random(); + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + big_sum_polynomial.at(idx) = big_sum_polynomial_unmasked.at(idx); } - // compute concatenated libra polynomial in lagrange basis, transform to monomial, add masking term Z_H(m_0 + - // m_1 X) - void compute_challenge_polynomial(const std::vector& multivariate_challenge) - { - std::vector coeffs_lagrange_basis(SUBGROUP_SIZE); - coeffs_lagrange_basis[0] = FF(1); + for (size_t idx = 0; idx < masking_term.size(); idx++) { + big_sum_polynomial.at(idx) -= masking_term.value_at(idx); + big_sum_polynomial.at(idx + SUBGROUP_SIZE) += masking_term.value_at(idx); + } + }; - for (size_t idx_poly = 0; idx_poly < CONST_PROOF_SIZE_LOG_N; idx_poly++) { - for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { - size_t current_idx = 1 + LIBRA_UNIVARIATES_LENGTH * idx_poly + idx; - coeffs_lagrange_basis[current_idx] = multivariate_challenge[idx_poly].pow(idx); - } - } - challenge_polynomial_lagrange = Polynomial(coeffs_lagrange_basis); - challenge_polynomial = Polynomial(interpolation_domain, coeffs_lagrange_basis, SUBGROUP_SIZE); - } - - void compute_big_sum_polynomial() - { - big_sum_lagrange_coeffs[0] = 0; - - // Compute the big sum coefficients recursively - for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { - size_t prev_idx = idx - 1; - big_sum_lagrange_coeffs[idx] = - big_sum_lagrange_coeffs[prev_idx] + - challenge_polynomial_lagrange.at(prev_idx) * libra_concatenated_lagrange_form.at(prev_idx); - }; - - // Get the coefficients in the monomial basis - auto big_sum_polynomial_unmasked = - Polynomial(interpolation_domain, big_sum_lagrange_coeffs, SUBGROUP_SIZE); - - // Generate random masking_term of degree 2, add Z_H(X) * masking_term - bb::Univariate masking_term = bb::Univariate::get_random(); - for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { - big_sum_polynomial.at(idx) = big_sum_polynomial_unmasked.at(idx); - } + void compute_batched_polynomial(const FF& claimed_evaluation) + { + // Compute shifted big sum polynomial A(gX) + Polynomial shifted_big_sum(SUBGROUP_SIZE + 3); - for (size_t idx = 0; idx < masking_term.size(); idx++) { - big_sum_polynomial.at(idx) -= masking_term.value_at(idx); - big_sum_polynomial.at(idx + SUBGROUP_SIZE) += masking_term.value_at(idx); - } - }; + for (size_t idx = 0; idx < SUBGROUP_SIZE + 3; idx++) { + shifted_big_sum.at(idx) = big_sum_polynomial.at(idx) * interpolation_domain[idx % SUBGROUP_SIZE]; + } + // Compute the monomial coefficients of L_1, the first Lagrange polynomial + std::array lagrange_coeffs; + lagrange_coeffs[0] = FF(1); + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + lagrange_coeffs[idx] = FF(0); + } - void compute_batched_polynomial(const FF& claimed_evaluation) - { - // Compute shifted big sum polynomial A(gX) - Polynomial shifted_big_sum(SUBGROUP_SIZE + 3); + Polynomial lagrange_first_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); - for (size_t idx = 0; idx < SUBGROUP_SIZE + 3; idx++) { - shifted_big_sum.at(idx) = big_sum_polynomial.at(idx) * interpolation_domain[idx % SUBGROUP_SIZE]; - } - // Compute the monomial coefficients of L_1, the first Lagrange polynomial - std::array lagrange_coeffs; - lagrange_coeffs[0] = FF(1); - for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { - lagrange_coeffs[idx] = FF(0); - } + // Compute the monomial coefficients of L_{|H|}, the last Lagrange polynomial + lagrange_coeffs[0] = FF(0); + lagrange_coeffs[SUBGROUP_SIZE - 1] = FF(1); - Polynomial lagrange_first_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + Polynomial lagrange_last_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); - // Compute the monomial coefficients of L_{|H|}, the last Lagrange polynomial - lagrange_coeffs[0] = FF(0); - lagrange_coeffs[SUBGROUP_SIZE - 1] = FF(1); + // Compute -F(X)*G(X), the negated product of challenge_polynomial and libra_concatenated_monomial_form + // Polynomial result(BATCHED_POLYNOMIAL_LENGTH); - Polynomial lagrange_last_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + for (size_t i = 0; i < concatenated_polynomial.size(); ++i) { + for (size_t j = 0; j < challenge_polynomial.size(); ++j) { + batched_polynomial.at(i + j) -= concatenated_polynomial.at(i) * challenge_polynomial.at(j); + } + } - // Compute -F(X)*G(X), the negated product of challenge_polynomial and libra_concatenated_monomial_form - // Polynomial result(BATCHED_POLYNOMIAL_LENGTH); + // Compute - F(X) * G(X) + A(gX) - A(X) + for (size_t idx = 0; idx < shifted_big_sum.size(); idx++) { + batched_polynomial.at(idx) += shifted_big_sum.at(idx) - big_sum_polynomial.at(idx); + } - for (size_t i = 0; i < concatenated_polynomial.size(); ++i) { - for (size_t j = 0; j < challenge_polynomial.size(); ++j) { - batched_polynomial.at(i + j) -= concatenated_polynomial.at(i) * challenge_polynomial.at(j); - } - } + // Mutiply - F(X) * G(X) + A(gX) - A(X) by X-g: + // 1. Multiply by X + for (size_t idx = batched_polynomial.size() - 1; idx > 0; idx--) { + batched_polynomial.at(idx) = batched_polynomial.at(idx - 1); + } + batched_polynomial.at(0) = FF(0); + // 2. Subtract 1/g(A(gX) - A(X) - F(X) * G(X)) + for (size_t idx = 0; idx < batched_polynomial.size() - 1; idx++) { + batched_polynomial.at(idx) -= batched_polynomial.at(idx + 1) * interpolation_domain[SUBGROUP_SIZE - 1]; + } - // Compute - F(X) * G(X) + A(gX) - A(X) - for (size_t idx = 0; idx < shifted_big_sum.size(); idx++) { - batched_polynomial.at(idx) += shifted_big_sum.at(idx) - big_sum_polynomial.at(idx); - } + // Add (L_1 + L_{|H|}) * A(X) to the result + lagrange_first_monomial += lagrange_last_monomial; - // Mutiply - F(X) * G(X) + A(gX) - A(X) by X-g: - // 1. Multiply by X - for (size_t idx = batched_polynomial.size() - 1; idx > 0; idx--) { - batched_polynomial.at(idx) = batched_polynomial.at(idx - 1); - } - batched_polynomial.at(0) = FF(0); - // 2. Subtract 1/g(A(gX) - A(X) - F(X) * G(X)) - for (size_t idx = 0; idx < batched_polynomial.size() - 1; idx++) { - batched_polynomial.at(idx) -= batched_polynomial.at(idx + 1) * interpolation_domain[SUBGROUP_SIZE - 1]; + for (size_t i = 0; i < big_sum_polynomial.size(); ++i) { + for (size_t j = 0; j < lagrange_first_monomial.size(); ++j) { + batched_polynomial.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); } + } - // Add (L_1 + L_{|H|}) * A(X) to the result - lagrange_first_monomial += lagrange_last_monomial; + for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { + batched_polynomial.at(idx) -= lagrange_last_monomial.at(idx) * claimed_evaluation; + } + } - for (size_t i = 0; i < big_sum_polynomial.size(); ++i) { - for (size_t j = 0; j < lagrange_first_monomial.size(); ++j) { - batched_polynomial.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); - } - } + // Compute the quotient of batched_polynomial by Z_H = X^{|H|} - 1 + void compute_batched_quotient() + { - for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { - batched_polynomial.at(idx) -= lagrange_last_monomial.at(idx) * claimed_evaluation; - } + auto remainder = batched_polynomial; + for (size_t idx = BATCHED_POLYNOMIAL_LENGTH - 1; idx >= SUBGROUP_SIZE; idx--) { + batched_quotient.at(idx - SUBGROUP_SIZE) = remainder.at(idx); + remainder.at(idx - SUBGROUP_SIZE) += remainder.at(idx); } + } +}; + +template class SmallSubgroupIPAVerifier { + using FF = typename Curve::ScalarField; - // Compute the quotient of batched_polynomial by Z_H = X^{|H|} - 1 - void compute_batched_quotient() - { + static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; + + static constexpr size_t LIBRA_UNIVARIATES_LENGTH = 3; + + public: + /** + * @brief Verifies the consistency of polynomial evaluations provided by the prover. + * + * @details + * Given a subgroup of \f$ \mathbb{F}^\ast \f$, its generator \f$ g\f$, this function checks whether the following + * equation holds: + * \f[ L_1(r) A(r) + (r - g^{-1}) \left( A(g*r) - A(r) - F(r) G(r) \right) + L_{|H|}(r) \left( A(r) - s + * \right) = T(r) Z_H(r) \f] Where the following are sent by the prover + * - \f$ A(r), A(g\cdot r) \f$ are the evaluation of the "big sum polynomial" + * - \f$ G(r) \f$ is the evaluation of the concatenation of the coefficients of the masking Libra polynomials + * + * - \f$ T(r) \f$ is the evaluation of the quotient of the left hand side above by the vanishing polynomial for + * \f$H\f$ + * and the following evaluations computed by the verifier + * - \f$ L_1 \f$ and \f$ L_{|H|} \f$ are the Lagrange polynomials corresponding to \f$ 1 \f$ and \f$ g^{-1} \f$. + * - \f$ F(r) \f$ is the evaluation of the polynomial obtained by concatenating powers of sumcheck round challenges + * - \f$ Z_H(r) \f$ is the vanishing polynomial \f$ X^{|H|} - 1\f$ evaluated at the challenge point. + * + * @param libra_evaluations A vector of polynomial evaluations containing: + * - \f$ G(r), A(g\cdot r), A(r), T(r) \f$. + * @param gemini_evaluation_challenge The challenge point \f$ r \f$ at which evaluations are verified. + * @param multilinear_challenge A vector of sumcheck round challenges. + * @param eval_claim The claimed inner proudct of the coefficients of \f$G\f$ and \f$F\f$. + * @return True if the consistency check passes, false otherwise. + */ + static bool evaluations_consistency_check(const std::vector& libra_evaluations, + const FF& gemini_evaluation_challenge, + const std::vector& multilinear_challenge, + const FF& inner_product_eval_claim) + { + + static const FF subgroup_generator_inverse = FF(1) / Curve::SUBGROUP_GENERATOR; + + // 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); + + // 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); + + // Compute the evaluations of the challenge polynomial, Lagrange first, and Lagrange last for the fixed small + // subgroup + auto [challenge_poly, lagrange_first, lagrange_last] = compute_batched_barycentric_evaluations( + challenge_polynomial_lagrange, gemini_evaluation_challenge, subgroup_generator_inverse); + + const FF& concatenated_at_r = libra_evaluations[0]; + const FF& big_sum_shifted_eval = libra_evaluations[1]; + const FF& big_sum_eval = libra_evaluations[2]; + const FF& quotient_eval = libra_evaluations[3]; + + // Compute the evaluation of + // L_1(X) * A(X) + (X - 1/g) (A(gX) - A(X) - F(X) G(X)) + L_{|H|}(X)(A(X) - s) - Z_H(X) * Q(X) + FF diff = lagrange_first * big_sum_eval; + diff += (gemini_evaluation_challenge - subgroup_generator_inverse) * + (big_sum_shifted_eval - big_sum_eval - concatenated_at_r * challenge_poly); + diff += lagrange_last * (big_sum_eval - inner_product_eval_claim) - vanishing_poly_eval * quotient_eval; + + if constexpr (Curve::is_stdlib_type) { + return (diff.get_value() == FF(0).get_value()); + } else { + return (diff == FF(0)); + }; + } + + /** + * @brief Given the sumcheck multivariate challenge \f$ u_0,\ldots, u_{D-1}\f$, where \f$ D = + * \text{CONST_PROOF_SIZE_LOG_N}\f$, the verifier has to construct and evaluate the polynomial whose + * coefficients are given by \f$ (1, u_0, u_0^2, u_1,\ldots,1, u_{D-1}, u_{D-1}^2) \f$. We spend \f$ D \f$ + * multiplications to construct the coefficients. + * + * @param multivariate_challenge + * @return Polynomial + */ + static std::vector compute_challenge_polynomial(const std::vector& multivariate_challenge) + { + ASSERT(LIBRA_UNIVARIATES_LENGTH == 3); + + std::vector challenge_polynomial_lagrange(SUBGROUP_SIZE); + + challenge_polynomial_lagrange[0] = FF{ 1 }; + FF challenge_sqr = FF{ 1 }; + for (size_t poly_idx = 0; poly_idx < CONST_PROOF_SIZE_LOG_N; poly_idx++) { + challenge_sqr = multivariate_challenge[poly_idx] * multivariate_challenge[poly_idx]; + + challenge_polynomial_lagrange[1 + poly_idx * LIBRA_UNIVARIATES_LENGTH] = FF{ 1 }; + challenge_polynomial_lagrange[2 + poly_idx * LIBRA_UNIVARIATES_LENGTH] = multivariate_challenge[poly_idx]; + challenge_polynomial_lagrange[3 + poly_idx * LIBRA_UNIVARIATES_LENGTH] = challenge_sqr; + } - auto remainder = batched_polynomial; - for (size_t idx = BATCHED_POLYNOMIAL_LENGTH - 1; idx >= SUBGROUP_SIZE; idx--) { - batched_quotient.at(idx - SUBGROUP_SIZE) = remainder.at(idx); - remainder.at(idx - SUBGROUP_SIZE) += remainder.at(idx); + return challenge_polynomial_lagrange; + } + + /** + * @brief Efficient batch evaluation of the challenge polynomial, Lagrange first, and Lagrange last + * + * @details It is a + * + * @param coeffs Coefficients of the polynomial to be evaluated, in our case it is the challenge polynomial + * @param z Evaluation point, we are using the Gemini evaluation challenge + * @param inverse_root_of_unity Inverse of the generator of the subgroup H + * @return std::array + */ + static std::array compute_batched_barycentric_evaluations(const std::vector& coeffs, + const FF& r, + const FF& inverse_root_of_unity) + { + std::array denominators; + FF one = FF{ 1 }; + FF numerator = r; + + numerator = numerator.pow(SUBGROUP_SIZE) - one; + numerator *= one / FF(SUBGROUP_SIZE); // (r^n - 1) / n + + // Compute denominators for the barycentric interpolation over the small subgroup + denominators[0] = r - one; + FF work_root = inverse_root_of_unity; // ω^{-1} + for (size_t i = 1; i < SUBGROUP_SIZE; ++i) { + denominators[i] = + work_root * r; // denominators[i] will correspond to L_[i+1] (since our 'commented maths' notation + // indexes L_i from 1). So ʓ.ω^{-i} = ʓ.ω^{1-(i+1)} is correct for L_{i+1}. + denominators[i] -= one; // ʓ.ω^{-i} - 1 + work_root *= inverse_root_of_unity; + } + if constexpr (Curve::is_stdlib_type) { + for (FF& denominator : denominators) { + denominator = one / denominator; } + } else { + FF::batch_invert(&denominators[0], SUBGROUP_SIZE); } - }; + std::array result; + result[0] = FF{ 0 }; + for (size_t i = 0; i < SUBGROUP_SIZE; ++i) { + FF temp = coeffs[i] * denominators[i]; // f_i * 1/(ʓ.ω^{-i} - 1) + result[0] = result[0] + temp; + } + + result[0] = result[0] * numerator; + result[1] = denominators[0] * numerator; + result[2] = denominators[SUBGROUP_SIZE - 1] * numerator; + + // \sum_{i=0}^{num_coeffs-1} f_i * [ʓ^n - 1]/[n.(ʓ.ω^{-i} - 1)] + // = \sum_{i=0}^{num_coeffs-1} f_i * L_{i+1} + // (with our somewhat messy 'commented maths' convention that L_1 corresponds to the 0th coeff). + + return result; + } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 48d358e3da5..3b14ea3f38f 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -122,7 +122,7 @@ void ECCVMProver::execute_pcs_rounds() using Shplemini = ShpleminiProver_; using Shplonk = ShplonkProver_; using OpeningClaim = ProverOpeningClaim; - using SmallSubgroupIPA = SmallSubgroupIPA::SmallSubgroupIPAProver; + using SmallSubgroupIPA = SmallSubgroupIPAProver; SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output, transcript, key->commitment_key); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index d7ad09cc7ba..772aa3cf45f 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -134,6 +134,6 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) PCS::reduce_verify(key->pcs_verification_key, batch_opening_claim, ipa_transcript); vinfo("eccvm sumcheck verified?: ", sumcheck_verified.value()); vinfo("batch opening verified?: ", batched_opening_verified); - return sumcheck_verified.value() && batched_opening_verified; + return sumcheck_verified.value() && batched_opening_verified && sumcheck_batch_opening_claims.consistency_checked; } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 13ad8162cb2..2203b700096 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -581,7 +581,6 @@ template class SumcheckVerifier { if constexpr (Flavor::HasZK) { libra_evaluation = transcript->template receive_from_prover("Libra:final_evaluation"); full_libra_purported_value += libra_evaluation; - info("sumcheck verifier ", full_libra_purported_value); full_libra_purported_value *= libra_challenge; }; // Final round diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 969f7a94399..5fea8fc6ce4 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -179,7 +179,7 @@ void TranslatorProver::execute_pcs_rounds() using OpeningClaim = ProverOpeningClaim; - using SmallSubgroupIPA = SmallSubgroupIPA::SmallSubgroupIPAProver; + using SmallSubgroupIPA = SmallSubgroupIPAProver; SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output, transcript, key->commitment_key); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index d6f9cdaaf51..d9a7b89735f 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -138,7 +138,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) auto verified = key->pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); - return verified; + return verified && opening_claim.consistency_checked; } bool TranslatorVerifier::verify_translation(const TranslationEvaluations& translation_evaluations) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 54eac2ac452..205dda42af5 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -59,7 +59,7 @@ template void DeciderProver_::execute_relation_ch template void DeciderProver_::execute_pcs_rounds() { using OpeningClaim = ProverOpeningClaim; - using SmallSubgroupIPA = SmallSubgroupIPA::SmallSubgroupIPAProver; + using SmallSubgroupIPA = SmallSubgroupIPAProver; auto& ck = proving_key->proving_key.commitment_key; ck = ck ? ck : std::make_shared(proving_key->proving_key.circuit_size); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 4a028d4e3ec..1fe22bb1996 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -83,7 +83,7 @@ template bool DeciderVerifier_::verify() libra_evaluation); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); bool verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); - return sumcheck_output.verified.value() && verified; + return sumcheck_output.verified.value() && verified && opening_claim.consistency_checked; } template class DeciderVerifier_; From 48ca947eb90e3c62bf8a9b6327255debcb93898b Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Tue, 17 Dec 2024 18:56:27 +0000 Subject: [PATCH 15/30] more clean-up --- .../commitment_schemes/gemini/gemini_impl.hpp | 1 - .../commitment_schemes/ipa/ipa.test.cpp | 76 ------------ .../commitment_schemes/kzg/kzg.test.cpp | 46 ------- .../shplonk/shplemini.test.cpp | 114 ------------------ .../src/barretenberg/eccvm/eccvm_verifier.cpp | 1 - .../eccvm_recursive_verifier.cpp | 6 - .../stdlib/primitives/curves/grumpkin.hpp | 6 + .../stdlib_circuit_builders/mock_circuits.hpp | 2 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 2 - .../barretenberg/sumcheck/sumcheck_round.hpp | 1 - .../sumcheck/zk_sumcheck_data.hpp | 12 -- .../ultra_honk/decider_prover.cpp | 1 - 12 files changed, 7 insertions(+), 261 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 11a996425bb..a66387474d1 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -123,7 +123,6 @@ std::vector::Claim> GeminiProver_::prove( } } const Fr r_challenge = transcript->template get_challenge("Gemini:r"); - info("gemini r! ", r_challenge); 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/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index c5e76dd32d3..0abcb594b50 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -23,82 +23,6 @@ class IPATest : public CommitmentTest { TEST_F(IPATest, CommitOnManyZeroCoeffPolyWorks) { - - constexpr std::array factors_of_p_minus_1 = { { 2, - 3, // 3^2 - 13, - // 29, - 67, - 229, - 311, - 983, - 11003, - 405928799, - 11465965001 } }; - Fr num_random = Fr::random_element(); - Fr prod{ 1 }; - info(num_random); - for (size_t idx = 0; idx < 10; idx++) { - num_random = num_random.pow(factors_of_p_minus_1[idx]); - prod *= Fr{ factors_of_p_minus_1[idx] }; - } - auto gen = Fr{ 1 }; - - uint32_t limb_0 = 39; - uint32_t limb_1 = 1977533650; - uint32_t limb_2 = 4249115906; - uint32_t limb_3 = 2737479925; - uint32_t limb_4 = 2607196689; - - uint64_t two_to_16 = 1 << 16; - - if (num_random != Fr{ 1 }) { - info("generator", num_random); - Fr first_chunk = num_random.pow(limb_4); - - Fr second_chunk = num_random.pow(two_to_16); - second_chunk = second_chunk.pow(two_to_16); - second_chunk = second_chunk.pow(limb_3); - - Fr third_chunk = num_random.pow(two_to_16); - third_chunk = third_chunk.pow(two_to_16); - third_chunk = third_chunk.pow(two_to_16); - third_chunk = third_chunk.pow(two_to_16); - third_chunk = third_chunk.pow(limb_2); - - Fr fourth_chunk = num_random.pow(two_to_16); - fourth_chunk = fourth_chunk.pow(two_to_16); - fourth_chunk = fourth_chunk.pow(two_to_16); - fourth_chunk = fourth_chunk.pow(two_to_16); - fourth_chunk = fourth_chunk.pow(two_to_16); - fourth_chunk = fourth_chunk.pow(two_to_16); - fourth_chunk = fourth_chunk.pow(limb_1); - - Fr fifth_chunk = num_random.pow(two_to_16); - fifth_chunk = fifth_chunk.pow(two_to_16); - fifth_chunk = fifth_chunk.pow(two_to_16); - fifth_chunk = fifth_chunk.pow(two_to_16); - fifth_chunk = fifth_chunk.pow(two_to_16); - fifth_chunk = fifth_chunk.pow(two_to_16); - fifth_chunk = fifth_chunk.pow(two_to_16); - fifth_chunk = fifth_chunk.pow(two_to_16); - fifth_chunk = fifth_chunk.pow(limb_0); - - gen = first_chunk * second_chunk * third_chunk * fourth_chunk * fifth_chunk; - } - info("minus 1 ", Fr(-1)); - - // info(Fr{ 1 } + prod * Fr{ 29 * 13 }); - - if ((gen.pow(29 * 3) == Fr{ 1 }) && (gen.pow(29) != Fr{ 1 }) && (gen.pow(3) != Fr{ 1 })) { - info("gen? ", gen); - // for (size_t idx = 0; idx < 450; idx++) { - // info(gen.pow(idx)); - // } - } - - // Fr root_of_unity = Fr::get_root_of_unity(2); - // info("root of unity", root_of_unity); constexpr size_t n = 4; Polynomial p(n); for (size_t i = 0; i < n - 1; i++) { diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 74d55c092c5..c21b34d313e 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -53,52 +53,6 @@ TYPED_TEST(KZGTest, SingleInLagrangeBasis) using KZG = KZG; using Fr = typename TypeParam::ScalarField; - std::array factors_of_p_minus_1 = { 1 << 28, 3, 13, 983, 237073, 11003, 405928799, 1670836401704629 }; - - Fr num_random = Fr::random_element(); - Fr prod{ 1 }; - info(num_random); - for (size_t idx = 0; idx < 8; idx++) { - num_random = num_random.pow(factors_of_p_minus_1[idx]); - prod *= Fr{ factors_of_p_minus_1[idx] }; - } - auto gen = Fr{ 1 }; - uint32_t first_limb = 749095036; - uint32_t second_limb = 4241987048; - uint32_t fourth_limb = 1922377697; - - uint64_t two_to_16 = 1 << 16; - - if (num_random != Fr{ 1 }) { - info("generator", num_random); - Fr first_chunk = num_random.pow(fourth_limb); - Fr second_chunk = num_random.pow(two_to_16); - second_chunk = second_chunk.pow(two_to_16); - second_chunk = second_chunk.pow(second_limb); - - Fr third_chunk = num_random.pow(two_to_16); - third_chunk = third_chunk.pow(two_to_16); - third_chunk = third_chunk.pow(two_to_16); - third_chunk = third_chunk.pow(two_to_16); - third_chunk = third_chunk.pow(first_limb); - prod *= Fr(1 << 64) * Fr(first_limb) + Fr(1 << 32) * Fr(second_limb) + Fr(fourth_limb); - gen = first_chunk * second_chunk * third_chunk; - } - info("minus 1 ", Fr(-1)); - - // info(Fr{ 1 } + prod * Fr{ 29 * 13 }); - - if ((gen.pow(29 * 3) == Fr{ 1 }) && (gen.pow(29) != Fr{ 1 }) && (gen.pow(3) != Fr{ 1 })) { - info("gen?", gen); - } - - // for (size_t idx = 0; idx < 7; idx++) { - // info("gen pow ", factors_of_p_minus_1[idx], " ", gen.pow(factors_of_p_minus_1[idx])); - // } - - // for (size_t idx = 0; idx < 1000; idx++) { - // info(idx, " ", gen.pow(idx)); - // } // create a random univariate (coefficients are in Lagrange basis) auto witness = bb::Univariate::get_random(); // define the interpolation domain 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 7313c44f069..bfb9fd93169 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -223,118 +223,4 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) EXPECT_EQ(shplemini_result, expected_result); } -/** - * @brief Libra masking univariates are used in sumcheck to prevent the leakage of witness data through the evaluations - * of round univariates. Here we test the opening of log_n Libra masking univariates batched with the opening of several - * prover polynomials and their shifts. - * - */ -// TYPED_TEST(ShpleminiTest, ShpleminiWithMaskingLibraUnivariates) -// { -// using ShpleminiProver = ShpleminiProver_; -// using ShpleminiVerifier = ShpleminiVerifier_; -// using KZG = KZG; -// using IPA = IPA; -// using Fr = typename TypeParam::ScalarField; -// using Commitment = typename TypeParam::AffineElement; -// using Polynomial = typename bb::Polynomial; - -// const size_t n = 16; -// const size_t log_n = 4; -// // In practice, the length of Libra univariates is equal to FLAVOR::BATCHED_RELATION_PARTIAL_LENGTH -// const size_t LIBRA_UNIVARIATE_LENGTH = 12; - -// std::array interpolation_domain; -// for (size_t idx = 0; idx < LIBRA_UNIVARIATE_LENGTH; idx++) { -// interpolation_domain[idx] = Fr(idx); -// } -// // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a -// // random point. -// auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' -// auto poly1 = Polynomial::random(n); -// auto poly2 = Polynomial::random(n, 1); -// auto poly3 = Polynomial::random(n, 1); -// auto poly4 = Polynomial::random(n); - -// std::vector> libra_univariates; -// std::vector libra_commitments; -// std::vector libra_evaluations; -// for (size_t idx = 0; idx < log_n; idx++) { -// // generate random polynomial -// Polynomial libra_polynomial = Polynomial::random(LIBRA_UNIVARIATE_LENGTH); -// // create a univariate with the same coefficients (to store an array instead of a vector) -// bb::Univariate libra_univariate; -// for (size_t i = 0; i < LIBRA_UNIVARIATE_LENGTH; i++) { -// libra_univariate.value_at(i) = libra_polynomial[i]; -// } -// libra_univariates.push_back(libra_univariate); - -// // commit to libra polynomial and populate the vector of libra commitments -// Commitment libra_commitment = this->commit(libra_polynomial); -// libra_commitments.push_back(libra_commitment); - -// // evaluate current libra univariate at the corresponding challenge and store the value in libra evaluations -// libra_evaluations.push_back(libra_polynomial.evaluate(mle_opening_point[idx])); -// } - -// Commitment commitment1 = this->commit(poly1); -// Commitment commitment2 = this->commit(poly2); -// Commitment commitment3 = this->commit(poly3); -// Commitment commitment4 = this->commit(poly4); -// std::vector unshifted_commitments = { commitment1, commitment2, commitment3, commitment4 }; -// std::vector shifted_commitments = { commitment2, commitment3 }; -// auto eval1 = poly1.evaluate_mle(mle_opening_point); -// auto eval2 = poly2.evaluate_mle(mle_opening_point); -// auto eval3 = poly3.evaluate_mle(mle_opening_point); -// auto eval4 = poly4.evaluate_mle(mle_opening_point); -// auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); -// auto eval3_shift = poly3.evaluate_mle(mle_opening_point, true); - -// // Collect multilinear evaluations for input to prover -// // std::vector multilinear_evaluations = { eval1, eval2, eval3, eval4, eval2_shift, eval3_shift }; - -// auto prover_transcript = NativeTranscript::prover_init_empty(); - -// // Run the full prover PCS protocol: -// auto opening_claim = ShpleminiProver::prove(Fr{ n }, -// RefArray{ poly1, poly2, poly3, poly4 }, -// RefArray{ poly2, poly3 }, -// mle_opening_point, -// this->ck(), -// prover_transcript, -// libra_univariates, -// libra_evaluations); -// 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); -// } - -// // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation) - -// auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); - -// // Gemini verifier output: -// // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 -// auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(n, -// RefVector(unshifted_commitments), -// RefVector(shifted_commitments), -// RefArray{ eval1, eval2, eval3, eval4 }, -// RefArray{ eval2_shift, eval3_shift }, -// mle_opening_point, -// this->vk()->get_g1_identity(), -// verifier_transcript, -// {}, -// RefVector(libra_commitments), -// libra_evaluations); - -// 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 diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 772aa3cf45f..66acae5cd7d 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -62,7 +62,6 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) auto [multivariate_challenge, claimed_evaluations, libra_evaluation, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); - // libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); // If Sumcheck did not verify, return false diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp index b1408f6b022..982bca5a706 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp @@ -3,13 +3,7 @@ #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" #include "barretenberg/transcript/transcript.hpp" -namespace bb::stdlib { -template -const typename grumpkin::ScalarField grumpkin::SUBGROUP_GENERATOR = - typename grumpkin::ScalarField( - uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); -} namespace bb { template diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp index 0a88de777ca..6ed98142267 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp @@ -35,4 +35,10 @@ template struct grumpkin { static constexpr size_t SUBGROUP_SIZE = 87; static const ScalarField SUBGROUP_GENERATOR; }; + +template +const typename grumpkin::ScalarField grumpkin::SUBGROUP_GENERATOR = + typename grumpkin::ScalarField( + uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); + } // namespace bb::stdlib \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp index 20b218f15ac..070046f3f15 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp @@ -129,7 +129,7 @@ class MockCircuits { * @param num_gates */ template - static void construct_arithmetic_circuit(Builder& builder, const size_t target_log2_dyadic_size = 8) + static void construct_arithmetic_circuit(Builder& builder, const size_t target_log2_dyadic_size = 4) { const size_t target_dyadic_size = 1 << target_log2_dyadic_size; const size_t num_preamble_gates = builder.num_gates; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 2203b700096..2fa8590eece 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -566,7 +566,6 @@ template class SumcheckVerifier { if (round_idx < multivariate_d) { bool checked = round.check_sum(round_univariate); verified = verified && checked; - info("verified round ", round_idx, " ", verified); multivariate_challenge.emplace_back(round_challenge); round.compute_next_target_sum(round_univariate, round_challenge); gate_separators.partially_evaluate(round_challenge); @@ -602,7 +601,6 @@ template class SumcheckVerifier { final_check = (full_honk_purported_value == round.target_total_sum); } verified = final_check && verified; - info("last verification ", verified); // For ZK Flavors: the evaluations of Libra univariates are included in the Sumcheck Output if constexpr (!Flavor::HasZK) { return SumcheckOutput{ multivariate_challenge, purported_evaluations, verified }; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 3422b1dcec0..161ab5ac38e 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -294,7 +294,6 @@ template class SumcheckProverRound { size_t round_idx) { bb::Univariate libra_round_univariate; - info("inside sumcheck round: ", libra_round_univariate.size()); // select the i'th column of Libra book-keeping table const auto& current_column = zk_sumcheck_data.libra_univariates[round_idx]; // the evaluation of Libra round univariate at k=0...D are equal to \f$\texttt{libra_univariates}_{i}(k)\f$ diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 35333076eee..d68c54c8a38 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -4,7 +4,6 @@ #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include -#include #include #include @@ -22,18 +21,7 @@ template struct ZKSumcheckData { static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; - // static constexpr FF grumpkin_subgroup_generator = - // FF(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); - // static constexpr FF bn_254_subgroup_generator = - // FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); - /** - * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials - * \f$P_1,\ldots, P_N\f$ incremented by 1, i.e. it is equal \ref MAX_PARTIAL_RELATION_LENGTH - * "MAX_PARTIAL_RELATION_LENGTH + 1". - */ - static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH; - // The size of the LibraUnivariates. We ensure that they do not take extra space when Flavor runs non-ZK Sumcheck. // The size of the LibraUnivariates. We ensure that they do not take extra space when Flavor runs non-ZK Sumcheck. static constexpr size_t LIBRA_UNIVARIATES_LENGTH = Flavor::HasZK ? 3 : 0; // Container for the Libra Univariates. Their number depends on the size of the circuit. diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 205dda42af5..7356cdf6056 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -66,7 +66,6 @@ template void DeciderProver_::execute_pcs_rounds( OpeningClaim prover_opening_claim; if constexpr (!Flavor::HasZK) { - prover_opening_claim = ShpleminiProver_::prove(proving_key->proving_key.circuit_size, proving_key->proving_key.polynomials.get_unshifted(), proving_key->proving_key.polynomials.get_to_be_shifted(), From 29f6de78258018805bb4610c48edd744fd94c4b8 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Tue, 17 Dec 2024 19:45:08 +0000 Subject: [PATCH 16/30] mega with zk transcript test fixed --- .../mega_zk_flavor.hpp | 49 ++++++++++++------- .../src/barretenberg/sumcheck/sumcheck.hpp | 4 +- .../ultra_honk/mega_transcript.test.cpp | 25 +++++----- 3 files changed, 47 insertions(+), 31 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp index 59e3776201d..e2450bb561e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp @@ -47,11 +47,18 @@ class MegaZKFlavor : public bb::MegaFlavor { Commitment lookup_inverses_comm; Commitment lookup_read_counts_comm; Commitment lookup_read_tags_comm; - std::vector libra_commitments; + Commitment libra_concatenation_commitment; FF libra_sum; std::vector> sumcheck_univariates; - std::vector libra_evaluations; + FF libra_claimed_evaluation; + + Commitment libra_big_sum_commitment; + Commitment libra_quotient_commitment; std::array sumcheck_evaluations; + FF libra_concatenation_eval; + FF libra_shifted_big_sum_eval; + FF libra_big_sum_eval; + FF libra_quotient_eval; Commitment hiding_polynomial_commitment; FF hiding_polynomial_eval; std::vector gemini_fold_comms; @@ -85,7 +92,6 @@ class MegaZKFlavor : public bb::MegaFlavor { // take current proof and put them into the struct size_t num_frs_read = 0; circuit_size = deserialize_from_buffer(proof_data, num_frs_read); - size_t log_circuit_size = static_cast(numeric::get_msb(circuit_size)); public_input_size = deserialize_from_buffer(proof_data, num_frs_read); pub_inputs_offset = deserialize_from_buffer(proof_data, num_frs_read); @@ -116,10 +122,7 @@ class MegaZKFlavor : public bb::MegaFlavor { w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); lookup_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); - for (size_t i = 0; i < log_circuit_size; i++) { - libra_commitments.emplace_back(NativeTranscript::template deserialize_from_buffer( - NativeTranscript::proof_data, num_frs_read)); - }; + libra_concatenation_commitment = deserialize_from_buffer(proof_data, num_frs_read); libra_sum = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); @@ -128,11 +131,13 @@ class MegaZKFlavor : public bb::MegaFlavor { deserialize_from_buffer>(proof_data, num_frs_read)); } - for (size_t i = 0; i < log_circuit_size; i++) { - libra_evaluations.emplace_back( - NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read)); - } + libra_claimed_evaluation = deserialize_from_buffer(proof_data, num_frs_read); sumcheck_evaluations = deserialize_from_buffer>(proof_data, num_frs_read); + + libra_big_sum_commitment = deserialize_from_buffer(proof_data, num_frs_read); + + libra_quotient_commitment = deserialize_from_buffer(proof_data, num_frs_read); + hiding_polynomial_commitment = deserialize_from_buffer(proof_data, num_frs_read); hiding_polynomial_eval = deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { @@ -141,6 +146,10 @@ class MegaZKFlavor : public bb::MegaFlavor { for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { gemini_fold_evals.push_back(deserialize_from_buffer(proof_data, num_frs_read)); } + libra_concatenation_eval = deserialize_from_buffer(proof_data, num_frs_read); + libra_shifted_big_sum_eval = deserialize_from_buffer(proof_data, num_frs_read); + libra_big_sum_eval = deserialize_from_buffer(proof_data, num_frs_read); + libra_quotient_eval = deserialize_from_buffer(proof_data, num_frs_read); shplonk_q_comm = deserialize_from_buffer(proof_data, num_frs_read); kzg_w_comm = deserialize_from_buffer(proof_data, num_frs_read); @@ -149,7 +158,6 @@ class MegaZKFlavor : public bb::MegaFlavor { void serialize_full_transcript() { size_t old_proof_length = proof_data.size(); - size_t log_circuit_size = static_cast(numeric::get_msb(circuit_size)); proof_data.clear(); serialize_to_buffer(circuit_size, proof_data); serialize_to_buffer(public_input_size, proof_data); @@ -182,19 +190,19 @@ class MegaZKFlavor : public bb::MegaFlavor { serialize_to_buffer(lookup_inverses_comm, proof_data); serialize_to_buffer(z_perm_comm, proof_data); - for (size_t i = 0; i < log_circuit_size; ++i) { - NativeTranscript::template serialize_to_buffer(libra_commitments[i], NativeTranscript::proof_data); - } + serialize_to_buffer(libra_concatenation_commitment, proof_data); + NativeTranscript::template serialize_to_buffer(libra_sum, NativeTranscript::proof_data); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(sumcheck_univariates[i], proof_data); } - for (size_t i = 0; i < log_circuit_size; ++i) { - NativeTranscript::template serialize_to_buffer(libra_evaluations[i], NativeTranscript::proof_data); - } + serialize_to_buffer(libra_claimed_evaluation, proof_data); serialize_to_buffer(sumcheck_evaluations, proof_data); + serialize_to_buffer(libra_big_sum_commitment, proof_data); + serialize_to_buffer(libra_quotient_commitment, proof_data); + serialize_to_buffer(hiding_polynomial_commitment, NativeTranscript::proof_data); serialize_to_buffer(hiding_polynomial_eval, NativeTranscript::proof_data); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { @@ -203,6 +211,11 @@ class MegaZKFlavor : public bb::MegaFlavor { for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(gemini_fold_evals[i], proof_data); } + serialize_to_buffer(libra_concatenation_eval, proof_data); + serialize_to_buffer(libra_shifted_big_sum_eval, proof_data); + serialize_to_buffer(libra_big_sum_eval, proof_data); + serialize_to_buffer(libra_quotient_eval, proof_data); + serialize_to_buffer(shplonk_q_comm, proof_data); serialize_to_buffer(kzg_w_comm, proof_data); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 2fa8590eece..e15f8758ee1 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -265,7 +265,7 @@ template class SumcheckProver { libra_evaluation += libra_eval; } libra_evaluation += zk_sumcheck_data.constant_term; - std::string libra_evaluation_label = "Libra:final_evaluation"; + std::string libra_evaluation_label = "Libra:claimed_evaluation"; transcript->send_to_verifier(libra_evaluation_label, libra_evaluation); }; @@ -578,7 +578,7 @@ template class SumcheckVerifier { FF libra_evaluation{ 0 }; FF full_libra_purported_value = FF(0); if constexpr (Flavor::HasZK) { - libra_evaluation = transcript->template receive_from_prover("Libra:final_evaluation"); + libra_evaluation = transcript->template receive_from_prover("Libra:claimed_evaluation"); full_libra_purported_value += libra_evaluation; full_libra_purported_value *= libra_challenge; }; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp index 2902057f62a..38736bdda07 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp @@ -30,11 +30,10 @@ template class MegaTranscriptTests : public ::testing::Test { * * @return TranscriptManifest */ - static TranscriptManifest construct_mega_honk_manifest(size_t circuit_size = 0) + static TranscriptManifest construct_mega_honk_manifest() { using Commitment = typename Flavor::Commitment; TranscriptManifest manifest_expected; - auto log_n = numeric::get_msb(circuit_size); size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH; size_t NUM_SUBRELATIONS = Flavor::NUM_SUBRELATIONS; @@ -97,10 +96,8 @@ template class MegaTranscriptTests : public ::testing::Test { } if constexpr (Flavor::HasZK) { - for (size_t i = 0; i < log_n; i++) { - std::string label = "Libra:commitment_" + std::to_string(i); - manifest_expected.add_entry(round, label, frs_per_G); - } + + manifest_expected.add_entry(round, "Libra:concatenation_commitment", frs_per_G); manifest_expected.add_entry(round, "Libra:Sum", frs_per_Fr); manifest_expected.add_challenge(round, "Libra:Challenge"); round++; @@ -115,15 +112,15 @@ template class MegaTranscriptTests : public ::testing::Test { } if constexpr (Flavor::HasZK) { - for (size_t i = 0; i < log_n; i++) { - std::string idx = std::to_string(i); - manifest_expected.add_entry(round, "Libra:evaluation_" + idx, frs_per_Fr); - } + manifest_expected.add_entry(round, "Libra:claimed_evaluation", frs_per_Fr); } manifest_expected.add_entry(round, "Sumcheck:evaluations", frs_per_evals); if constexpr (Flavor::HasZK) { + manifest_expected.add_entry(round, "Libra:big_sum_commitment", frs_per_G); + manifest_expected.add_entry(round, "Libra:quotient_commitment", frs_per_G); + manifest_expected.add_entry(round, "Gemini:masking_poly_comm", frs_per_G); manifest_expected.add_entry(round, "Gemini:masking_poly_eval", frs_per_Fr); } @@ -141,6 +138,12 @@ template class MegaTranscriptTests : public ::testing::Test { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "Gemini:a_" + idx, frs_per_Fr); } + if constexpr (Flavor::HasZK) { + manifest_expected.add_entry(round, "Libra:concatenation_eval", frs_per_Fr); + manifest_expected.add_entry(round, "Libra:shifted_big_sum_eval", frs_per_Fr); + manifest_expected.add_entry(round, "Libra:big_sum_eval", frs_per_Fr); + manifest_expected.add_entry(round, "Libra:quotient_eval", frs_per_Fr); + } manifest_expected.add_challenge(round, "Shplonk:nu"); round++; @@ -198,7 +201,7 @@ TYPED_TEST(MegaTranscriptTests, ProverManifestConsistency) auto proof = prover.construct_proof(); // Check that the prover generated manifest agrees with the manifest hard coded in this suite - auto manifest_expected = TestFixture::construct_mega_honk_manifest(proving_key->proving_key.circuit_size); + auto manifest_expected = TestFixture::construct_mega_honk_manifest(); auto prover_manifest = prover.transcript->get_manifest(); // Note: a manifest can be printed using manifest.print() for (size_t round = 0; round < manifest_expected.size(); ++round) { From c37a3fc98f98e20b0b4b8acb95ea561ede366ece Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 18 Dec 2024 10:28:08 +0000 Subject: [PATCH 17/30] eccvm and translator transcript tests + template on curve instead of flavor --- .../small_subgroup_ipa/small_subgroup_ipa.hpp | 30 ++++------- .../src/barretenberg/eccvm/eccvm_flavor.hpp | 52 ++++++++++++------- .../src/barretenberg/eccvm/eccvm_prover.cpp | 10 ++-- .../src/barretenberg/eccvm/eccvm_prover.hpp | 5 +- .../eccvm/eccvm_transcript.test.cpp | 28 +++++----- .../src/barretenberg/sumcheck/sumcheck.hpp | 5 +- .../barretenberg/sumcheck/sumcheck.test.cpp | 10 ++-- .../barretenberg/sumcheck/sumcheck_round.hpp | 19 ++++--- .../sumcheck/zk_sumcheck_data.hpp | 11 ++-- .../translator_vm/translator_prover.cpp | 10 ++-- .../translator_vm/translator_prover.hpp | 3 +- .../ultra_honk/decider_prover.cpp | 6 +-- .../ultra_honk/decider_prover.hpp | 4 +- 13 files changed, 108 insertions(+), 85 deletions(-) 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 159978d50f4..0d0d6e2d8b9 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 @@ -18,9 +18,8 @@ namespace bb { * */ -template class SmallSubgroupIPAProver { - using Curve = typename Flavor::Curve; - using FF = typename Flavor::FF; +template class SmallSubgroupIPAProver { + using FF = typename Curve::ScalarField; static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; @@ -59,22 +58,11 @@ template class SmallSubgroupIPAProver { Polynomial batched_quotient; public: - // Default constructor for non-ZK Flavors - SmallSubgroupIPAProver() - : interpolation_domain{} - , concatenated_polynomial(0) - , libra_concatenated_lagrange_form(0) - , challenge_polynomial(0) - , challenge_polynomial_lagrange(0) // public polynomial - , big_sum_polynomial(0) // includes masking - , batched_polynomial(0) // batched polynomial, input to shplonk prover - , batched_quotient(0) - {} - - SmallSubgroupIPAProver(const ZKSumcheckData& zk_sumcheck_data, - const SumcheckOutput& sumcheck_output, - std::shared_ptr transcript, - std::shared_ptr commitment_key = nullptr) + SmallSubgroupIPAProver(ZKSumcheckData& zk_sumcheck_data, + const std::vector& multivariate_challenge, + const FF claimed_ipa_eval, + std::shared_ptr transcript, + std::shared_ptr commitment_key = nullptr) : interpolation_domain(zk_sumcheck_data.interpolation_domain) , concatenated_polynomial(zk_sumcheck_data.libra_concatenated_monomial_form) , libra_concatenated_lagrange_form(zk_sumcheck_data.libra_concatenated_lagrange_form) @@ -88,7 +76,7 @@ template class SmallSubgroupIPAProver { ASSERT(concatenated_polynomial.size() < SUBGROUP_SIZE + 3); - compute_challenge_polynomial(sumcheck_output.challenge); + compute_challenge_polynomial(multivariate_challenge); compute_big_sum_polynomial(); if (commitment_key) { @@ -96,7 +84,7 @@ template class SmallSubgroupIPAProver { commitment_key->commit(big_sum_polynomial)); } - compute_batched_polynomial(sumcheck_output.claimed_libra_evaluation); + compute_batched_polynomial(claimed_ipa_eval); compute_batched_quotient(); if (commitment_key) { diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index a44e827d90e..977ca335881 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -947,11 +947,17 @@ class ECCVMFlavor { Commitment transcript_msm_count_at_transition_inverse_comm; Commitment z_perm_comm; Commitment lookup_inverses_comm; - std::vector libra_commitments; + Commitment libra_concatenation_commitment; FF libra_sum; std::vector> sumcheck_univariates; - std::vector libra_evaluations; + FF libra_claimed_evaluation; + Commitment libra_big_sum_commitment; + Commitment libra_quotient_commitment; std::array sumcheck_evaluations; + FF libra_concatenation_eval; + FF libra_shifted_big_sum_eval; + FF libra_big_sum_eval; + FF libra_quotient_eval; Commitment hiding_polynomial_commitment; FF hiding_polynomial_eval; std::vector gemini_fold_comms; @@ -1152,11 +1158,9 @@ class ECCVMFlavor { NativeTranscript::proof_data, num_frs_read); z_perm_comm = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); - size_t log_circuit_size = static_cast(numeric::get_msb(circuit_size)); - for (size_t i = 0; i < log_circuit_size; i++) { - libra_commitments.emplace_back(NativeTranscript::template deserialize_from_buffer( - NativeTranscript::proof_data, num_frs_read)); - }; + libra_concatenation_commitment = + NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); + libra_sum = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { @@ -1165,12 +1169,15 @@ class ECCVMFlavor { NativeTranscript::proof_data, num_frs_read)); } - for (size_t i = 0; i < log_circuit_size; i++) { - libra_evaluations.emplace_back( - NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read)); - } + libra_claimed_evaluation = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); + sumcheck_evaluations = NativeTranscript::template deserialize_from_buffer>( NativeTranscript::proof_data, num_frs_read); + libra_big_sum_commitment = + NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); + + libra_quotient_commitment = + NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); hiding_polynomial_commitment = deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); hiding_polynomial_eval = deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); @@ -1181,6 +1188,11 @@ class ECCVMFlavor { for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { gemini_fold_evals.push_back(deserialize_from_buffer(proof_data, num_frs_read)); } + libra_concatenation_eval = deserialize_from_buffer(proof_data, num_frs_read); + libra_shifted_big_sum_eval = deserialize_from_buffer(proof_data, num_frs_read); + libra_big_sum_eval = deserialize_from_buffer(proof_data, num_frs_read); + libra_quotient_eval = deserialize_from_buffer(proof_data, num_frs_read); + shplonk_q_comm = deserialize_from_buffer(proof_data, num_frs_read); translation_eval_op = @@ -1200,7 +1212,6 @@ class ECCVMFlavor { void serialize_full_transcript() { size_t old_proof_length = NativeTranscript::proof_data.size(); - size_t log_circuit_size = static_cast(numeric::get_msb(circuit_size)); NativeTranscript::proof_data.clear(); @@ -1305,9 +1316,7 @@ class ECCVMFlavor { NativeTranscript::template serialize_to_buffer(lookup_inverses_comm, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(z_perm_comm, NativeTranscript::proof_data); - for (size_t i = 0; i < log_circuit_size; ++i) { - NativeTranscript::template serialize_to_buffer(libra_commitments[i], NativeTranscript::proof_data); - } + NativeTranscript::template serialize_to_buffer(libra_concatenation_commitment, proof_data); NativeTranscript::template serialize_to_buffer(libra_sum, NativeTranscript::proof_data); @@ -1315,10 +1324,12 @@ class ECCVMFlavor { NativeTranscript::template serialize_to_buffer(sumcheck_univariates[i], NativeTranscript::proof_data); } - for (size_t i = 0; i < log_circuit_size; ++i) { - NativeTranscript::template serialize_to_buffer(libra_evaluations[i], NativeTranscript::proof_data); - } + NativeTranscript::template serialize_to_buffer(libra_claimed_evaluation, proof_data); + NativeTranscript::template serialize_to_buffer(sumcheck_evaluations, NativeTranscript::proof_data); + NativeTranscript::template serialize_to_buffer(libra_big_sum_commitment, proof_data); + NativeTranscript::template serialize_to_buffer(libra_quotient_commitment, proof_data); + NativeTranscript::template serialize_to_buffer(hiding_polynomial_commitment, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(hiding_polynomial_eval, NativeTranscript::proof_data); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { @@ -1327,6 +1338,11 @@ class ECCVMFlavor { for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { NativeTranscript::template serialize_to_buffer(gemini_fold_evals[i], proof_data); } + + NativeTranscript::template serialize_to_buffer(libra_concatenation_eval, proof_data); + NativeTranscript::template serialize_to_buffer(libra_shifted_big_sum_eval, proof_data); + NativeTranscript::template serialize_to_buffer(libra_big_sum_eval, proof_data); + NativeTranscript::template serialize_to_buffer(libra_quotient_eval, proof_data); NativeTranscript::template serialize_to_buffer(shplonk_q_comm, proof_data); NativeTranscript::template serialize_to_buffer(translation_eval_op, NativeTranscript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 3b14ea3f38f..9f7de96e8bd 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -105,7 +105,7 @@ void ECCVMProver::execute_relation_check_rounds() gate_challenges[idx] = transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - zk_sumcheck_data = ZKSumcheckData(key->log_circuit_size, transcript, key->commitment_key); + zk_sumcheck_data = ZKSumcheckData(key->log_circuit_size, transcript, key->commitment_key); sumcheck_output = sumcheck.prove(key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); } @@ -122,10 +122,12 @@ void ECCVMProver::execute_pcs_rounds() using Shplemini = ShpleminiProver_; using Shplonk = ShplonkProver_; using OpeningClaim = ProverOpeningClaim; - using SmallSubgroupIPA = SmallSubgroupIPAProver; - - SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output, transcript, key->commitment_key); + SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, + sumcheck_output.challenge, + sumcheck_output.claimed_libra_evaluation, + transcript, + key->commitment_key); // Execute the Shplemini (Gemini + Shplonk) protocol to produce a univariate opening claim for the multilinear // evaluations produced by Sumcheck const OpeningClaim multivariate_to_univariate_opening_claim = diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index dab9d015ab2..d6daf525dc8 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -1,4 +1,5 @@ #pragma once +#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" #include "barretenberg/eccvm/eccvm_flavor.hpp" #include "barretenberg/goblin/translation_evaluations.hpp" #include "barretenberg/honk/proof_system/types/proof.hpp" @@ -25,6 +26,8 @@ class ECCVMProver { using Transcript = typename Flavor::Transcript; using TranslationEvaluations = bb::TranslationEvaluations_; using CircuitBuilder = typename Flavor::CircuitBuilder; + using ZKSumcheckData = ZKSumcheckData; + using SmallSubgroupIPA = SmallSubgroupIPAProver; explicit ECCVMProver(CircuitBuilder& builder, const std::shared_ptr& transcript = std::make_shared(), @@ -53,7 +56,7 @@ class ECCVMProver { std::shared_ptr key; CommitmentLabels commitment_labels; - ZKSumcheckData zk_sumcheck_data; + ZKSumcheckData zk_sumcheck_data; Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk FF nu_challenge; // needed in both Shplonk rounds diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 92d3ffc5f13..fc499714b65 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -26,10 +26,9 @@ class ECCVMTranscriptTests : public ::testing::Test { * * @return TranscriptManifest */ - TranscriptManifest construct_eccvm_honk_manifest(size_t circuit_size) + TranscriptManifest construct_eccvm_honk_manifest() { TranscriptManifest manifest_expected; - auto log_n = numeric::get_msb(circuit_size); size_t MAX_PARTIAL_RELATION_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH; // Size of types is number of bb::frs needed to represent the type size_t frs_per_Fr = bb::field_conversion::calc_num_bn254_frs(); @@ -139,10 +138,8 @@ class ECCVMTranscriptTests : public ::testing::Test { } round++; - for (size_t i = 0; i < log_n; i++) { - std::string idx = std::to_string(i); - manifest_expected.add_entry(round, "Libra:commitment_" + idx, frs_per_G); - } + manifest_expected.add_entry(round, "Libra:concatenation_commitment", frs_per_G); + manifest_expected.add_entry(round, "Libra:Sum", frs_per_Fr); // get the challenge for the ZK Sumcheck claim manifest_expected.add_challenge(round, "Libra:Challenge"); @@ -157,13 +154,12 @@ class ECCVMTranscriptTests : public ::testing::Test { round++; - for (size_t i = 0; i < log_n; i++) { - std::string idx = std::to_string(i); - manifest_expected.add_entry(round, "Libra:evaluation_" + idx, frs_per_Fr); - } - // manifest_expected.add_entry(round, "Libra:evaluation", log_n * frs_per_Fr); - + manifest_expected.add_entry(round, "Libra:claimed_evaluation", frs_per_Fr); manifest_expected.add_entry(round, "Sumcheck:evaluations", frs_per_evals); + + manifest_expected.add_entry(round, "Libra:big_sum_commitment", frs_per_G); + manifest_expected.add_entry(round, "Libra:quotient_commitment", frs_per_G); + manifest_expected.add_entry(round, "Gemini:masking_poly_comm", frs_per_G); manifest_expected.add_entry(round, "Gemini:masking_poly_eval", frs_per_Fr); @@ -180,8 +176,12 @@ class ECCVMTranscriptTests : public ::testing::Test { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "Gemini:a_" + idx, frs_per_Fr); } - + manifest_expected.add_entry(round, "Libra:concatenation_eval", frs_per_Fr); + manifest_expected.add_entry(round, "Libra:shifted_big_sum_eval", frs_per_Fr); + manifest_expected.add_entry(round, "Libra:big_sum_eval", frs_per_Fr); + manifest_expected.add_entry(round, "Libra:quotient_eval", frs_per_Fr); manifest_expected.add_challenge(round, "Shplonk:nu"); + round++; manifest_expected.add_entry(round, "Shplonk:Q", frs_per_G); manifest_expected.add_challenge(round, "Shplonk:z"); @@ -285,7 +285,7 @@ TEST_F(ECCVMTranscriptTests, ProverManifestConsistency) ECCVMProof proof = prover.construct_proof(); // Check that the prover generated manifest agrees with the manifest hard coded in this suite - auto manifest_expected = this->construct_eccvm_honk_manifest(prover.key->circuit_size); + auto manifest_expected = this->construct_eccvm_honk_manifest(); auto prover_manifest = prover.transcript->get_manifest(); // Note: a manifest can be printed using manifest.print() diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index e15f8758ee1..069c87b7401 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -153,6 +153,7 @@ template class SumcheckProver { // Define the length of Libra Univariates. For non-ZK Flavors: set to 0. static constexpr size_t LIBRA_UNIVARIATES_LENGTH = Flavor::HasZK ? Flavor::BATCHED_RELATION_PARTIAL_LENGTH : 0; using LibraUnivariates = std::vector>; + using ZKSumcheckData = ZKSumcheckData; std::shared_ptr transcript; SumcheckProverRound round; @@ -189,7 +190,7 @@ template class SumcheckProver { const bb::RelationParameters& relation_parameters, const RelationSeparator alpha, const std::vector& gate_challenges, - ZKSumcheckData zk_sumcheck_data = ZKSumcheckData()) + ZKSumcheckData zk_sumcheck_data = ZKSumcheckData()) { bb::GateSeparatorPolynomial gate_separators(gate_challenges, multivariate_d); @@ -391,7 +392,7 @@ polynomials that are sent in clear. * @param libra_running_sum * @param libra_evaluations */ - void update_zk_sumcheck_data(ZKSumcheckData& zk_sumcheck_data, const FF round_challenge, size_t round_idx) + void update_zk_sumcheck_data(ZKSumcheckData& zk_sumcheck_data, const FF round_challenge, size_t round_idx) { constexpr FF one_half = FF(1) / FF(2); // when round_idx = d - 1, the update is not needed diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp index 88cdfd405e6..eead4bb3a7a 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp @@ -21,7 +21,11 @@ template class SumcheckTests : public ::testing::Test { using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; using RelationSeparator = Flavor::RelationSeparator; + using ZKSumcheckData = + ZKSumcheckData; + const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; + static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } Polynomial random_poly(size_t size) @@ -146,7 +150,7 @@ template class SumcheckTests : public ::testing::Test { SumcheckOutput output; if constexpr (Flavor::HasZK) { - ZKSumcheckData zk_sumcheck_data(multivariate_d, transcript); + ZKSumcheckData zk_sumcheck_data(multivariate_d, transcript); output = sumcheck.prove(full_polynomials, {}, alpha, gate_challenges, zk_sumcheck_data); } else { output = sumcheck.prove(full_polynomials, {}, alpha, gate_challenges); @@ -230,7 +234,7 @@ template class SumcheckTests : public ::testing::Test { } SumcheckOutput output; if constexpr (Flavor::HasZK) { - ZKSumcheckData zk_sumcheck_data(multivariate_d, prover_transcript); + ZKSumcheckData zk_sumcheck_data(multivariate_d, prover_transcript); output = sumcheck_prover.prove( full_polynomials, relation_parameters, prover_alpha, prover_gate_challenges, zk_sumcheck_data); } else { @@ -318,7 +322,7 @@ template class SumcheckTests : public ::testing::Test { SumcheckOutput output; if constexpr (Flavor::HasZK) { // construct libra masking polynomials and compute auxiliary data - ZKSumcheckData zk_sumcheck_data(multivariate_d, prover_transcript); + ZKSumcheckData zk_sumcheck_data(multivariate_d, prover_transcript); output = sumcheck_prover.prove( full_polynomials, relation_parameters, prover_alpha, prover_gate_challenges, zk_sumcheck_data); } else { diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 161ab5ac38e..a3dd5571d50 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -40,6 +40,10 @@ template class SumcheckProverRound { public: using FF = typename Flavor::FF; using ExtendedEdges = typename Flavor::ExtendedEdges; + + using ZKSumcheckData = + ZKSumcheckData; + /** * @brief In Round \f$i = 0,\ldots, d-1\f$, equals \f$2^{d-i}\f$. */ @@ -135,13 +139,12 @@ template class SumcheckProverRound { method \ref extend_and_batch_univariates "extend and batch univariates". */ template - SumcheckRoundUnivariate compute_univariate( - const size_t round_idx, - ProverPolynomialsOrPartiallyEvaluatedMultivariates& polynomials, - const bb::RelationParameters& relation_parameters, - const bb::GateSeparatorPolynomial& gate_sparators, - const RelationSeparator alpha, - ZKSumcheckData zk_sumcheck_data) // only populated when Flavor HasZK + SumcheckRoundUnivariate compute_univariate(const size_t round_idx, + ProverPolynomialsOrPartiallyEvaluatedMultivariates& polynomials, + const bb::RelationParameters& relation_parameters, + const bb::GateSeparatorPolynomial& gate_sparators, + const RelationSeparator alpha, + ZKSumcheckData zk_sumcheck_data) // only populated when Flavor HasZK { PROFILE_THIS_NAME("compute_univariate"); @@ -290,7 +293,7 @@ template class SumcheckProverRound { * @param zk_sumcheck_data * @param round_idx */ - static SumcheckRoundUnivariate compute_libra_round_univariate(ZKSumcheckData zk_sumcheck_data, + static SumcheckRoundUnivariate compute_libra_round_univariate(const ZKSumcheckData& zk_sumcheck_data, size_t round_idx) { bb::Univariate libra_round_univariate; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index d68c54c8a38..30fff269b57 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -13,17 +13,16 @@ namespace bb { * @brief This structure is created to contain various polynomials and constants required by ZK Sumcheck. * */ -template struct ZKSumcheckData { - using FF = typename Flavor::FF; +template struct ZKSumcheckData { - using Curve = Flavor::Curve; + using FF = typename Curve::ScalarField; static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; // The size of the LibraUnivariates. We ensure that they do not take extra space when Flavor runs non-ZK Sumcheck. - static constexpr size_t LIBRA_UNIVARIATES_LENGTH = Flavor::HasZK ? 3 : 0; + static constexpr size_t LIBRA_UNIVARIATES_LENGTH = 3; // Container for the Libra Univariates. Their number depends on the size of the circuit. using LibraUnivariates = std::vector>; // Container for the evaluations of Libra Univariates that have to be proven. @@ -48,8 +47,8 @@ template struct ZKSumcheckData { // Main constructor ZKSumcheckData(const size_t multivariate_d, - std::shared_ptr transcript, - std::shared_ptr commitment_key = nullptr) + std::shared_ptr transcript, + std::shared_ptr commitment_key = nullptr) : constant_term(FF::random_element()) , libra_concatenated_monomial_form(SUBGROUP_SIZE + 2) // includes masking , libra_univariates(generate_libra_univariates(multivariate_d)) // random univariates of degree 2 diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 5fea8fc6ce4..d854ffa5f5f 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -162,7 +162,7 @@ void TranslatorProver::execute_relation_check_rounds() } // // create masking polynomials for sumcheck round univariates and auxiliary data - zk_sumcheck_data = ZKSumcheckData(key->log_circuit_size, transcript, key->commitment_key); + zk_sumcheck_data = ZKSumcheckData(key->log_circuit_size, transcript, key->commitment_key); sumcheck_output = sumcheck.prove(key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); } @@ -179,9 +179,13 @@ void TranslatorProver::execute_pcs_rounds() using OpeningClaim = ProverOpeningClaim; - using SmallSubgroupIPA = SmallSubgroupIPAProver; + using SmallSubgroupIPA = SmallSubgroupIPAProver; - SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output, transcript, key->commitment_key); + SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, + sumcheck_output.challenge, + sumcheck_output.claimed_libra_evaluation, + transcript, + key->commitment_key); const OpeningClaim prover_opening_claim = ShpleminiProver_::prove(key->circuit_size, diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp index 989596fd02b..0755a8269bb 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp @@ -22,6 +22,7 @@ class TranslatorProver { using CommitmentLabels = typename Flavor::CommitmentLabels; using PCS = typename Flavor::PCS; using Transcript = typename Flavor::Transcript; + using ZKSumcheckData = ZKSumcheckData; static constexpr size_t MINIMUM_MINI_CIRCUIT_SIZE = 2048; bool computed_witness = false; size_t total_num_gates = 0; // num_gates (already include zero row offset) (used to compute dyadic size) @@ -51,7 +52,7 @@ class TranslatorProver { CommitmentLabels commitment_labels; - ZKSumcheckData zk_sumcheck_data; + ZKSumcheckData zk_sumcheck_data; SumcheckOutput sumcheck_output; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 7356cdf6056..811952657bd 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -35,7 +35,7 @@ template void DeciderProver_::execute_relation_ch PROFILE_THIS_NAME("sumcheck.prove"); if constexpr (Flavor::HasZK) { auto commitment_key = std::make_shared(Flavor::BATCHED_RELATION_PARTIAL_LENGTH); - zk_sumcheck_data = ZKSumcheckData(numeric::get_msb(polynomial_size), transcript, commitment_key); + zk_sumcheck_data = ZKSumcheckData(numeric::get_msb(polynomial_size), transcript, commitment_key); sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, proving_key->relation_parameters, proving_key->alphas, @@ -59,7 +59,6 @@ template void DeciderProver_::execute_relation_ch template void DeciderProver_::execute_pcs_rounds() { using OpeningClaim = ProverOpeningClaim; - using SmallSubgroupIPA = SmallSubgroupIPAProver; auto& ck = proving_key->proving_key.commitment_key; ck = ck ? ck : std::make_shared(proving_key->proving_key.circuit_size); @@ -74,7 +73,8 @@ template void DeciderProver_::execute_pcs_rounds( transcript); } else { - SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output, transcript, ck); + SmallSubgroupIPA small_subgroup_ipa_prover( + zk_sumcheck_data, sumcheck_output.challenge, sumcheck_output.claimed_libra_evaluation, transcript, ck); prover_opening_claim = ShpleminiProver_::prove(proving_key->proving_key.circuit_size, proving_key->proving_key.polynomials.get_unshifted(), diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp index 1d8a7a85424..b09f27efb13 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp @@ -25,6 +25,8 @@ template class DeciderProver_ { using DeciderPK = DeciderProvingKey_; using Transcript = typename Flavor::Transcript; using RelationSeparator = typename Flavor::RelationSeparator; + using ZKSumcheckData = ZKSumcheckData; + using SmallSubgroupIPA = SmallSubgroupIPAProver; public: explicit DeciderProver_(const std::shared_ptr&, @@ -46,7 +48,7 @@ template class DeciderProver_ { Polynomial quotient_W; - ZKSumcheckData zk_sumcheck_data; + ZKSumcheckData zk_sumcheck_data; SumcheckOutput sumcheck_output; From 537f268cd535f2af9123edcc1c53950ff1e681c0 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 18 Dec 2024 11:35:31 +0000 Subject: [PATCH 18/30] bb native tests fix --- .../commitment_schemes/shplonk/shplonk.hpp | 10 ++++++++-- .../cpp/src/barretenberg/ultra_honk/decider_prover.cpp | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp index 0da5f04536d..59a3a76856f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp @@ -44,11 +44,17 @@ template class ShplonkProver_ { std::span> libra_opening_claims) { // Find n, the maximum size of all polynomials fⱼ(X) - size_t max_poly_size{ 87 * 2 + 2 }; + size_t max_poly_size{ 0 }; + + if (!libra_opening_claims.empty()) { + // Max size of the polynomials in Libra opening claims is Curve::SUBGROUP_SIZE*2 + 2; we round it up to the + // next power of 2 + const size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); + max_poly_size = 1 << (log_subgroup_size + 1); + }; for (const auto& claim : opening_claims) { max_poly_size = std::max(max_poly_size, claim.polynomial.size()); } - // Q(X) = ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) Polynomial Q(max_poly_size); Polynomial tmp(max_poly_size); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 811952657bd..61845250650 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -34,7 +34,8 @@ template void DeciderProver_::execute_relation_ch PROFILE_THIS_NAME("sumcheck.prove"); if constexpr (Flavor::HasZK) { - auto commitment_key = std::make_shared(Flavor::BATCHED_RELATION_PARTIAL_LENGTH); + const size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); + auto commitment_key = std::make_shared(1 << (log_subgroup_size + 1)); zk_sumcheck_data = ZKSumcheckData(numeric::get_msb(polynomial_size), transcript, commitment_key); sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, proving_key->relation_parameters, From ad60e4ad7d5bc70cbedb37d34adbaf12ecced65c Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 18 Dec 2024 16:24:54 +0000 Subject: [PATCH 19/30] gcc build fix + clean-up + bn254 flavors subgroup size increase --- .../barretenberg/commitment_schemes/claim.hpp | 2 +- .../commitment_schemes/shplonk/shplemini.hpp | 5 +- .../commitment_schemes/shplonk/shplonk.hpp | 4 - .../small_subgroup_ipa/small_subgroup_ipa.hpp | 101 ++++++++++++------ .../barretenberg/ecc/curves/bn254/bn254.hpp | 4 +- .../src/barretenberg/eccvm/eccvm_flavor.hpp | 6 -- .../eccvm/eccvm_transcript.test.cpp | 4 - .../src/barretenberg/eccvm/eccvm_verifier.cpp | 1 + .../stdlib/primitives/curves/bn254.hpp | 3 +- .../mega_zk_flavor.hpp | 7 -- .../src/barretenberg/sumcheck/sumcheck.hpp | 6 +- .../barretenberg/sumcheck/sumcheck.test.cpp | 1 - .../barretenberg/sumcheck/sumcheck_round.hpp | 10 +- .../sumcheck/zk_sumcheck_data.hpp | 1 - .../ultra_honk/decider_prover.cpp | 2 +- .../ultra_honk/decider_prover.hpp | 4 +- .../ultra_honk/mega_transcript.test.cpp | 2 - 17 files changed, 87 insertions(+), 76 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp index d6f314b2b40..398645a0d16 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp @@ -110,6 +110,6 @@ template struct BatchOpeningClaim { std::vector commitments; std::vector scalars; typename Curve::ScalarField evaluation_point; - bool consistency_checked = true; + bool consistency_checked = true; // Required for ZK Flavors }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index a4e4abffc4b..4e5e1fa4a57 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -48,12 +48,10 @@ template class ShpleminiProver_ { has_zk); // Create opening claims for Libra masking univariates std::vector libra_opening_claims; - // static constexpr FF bn_254_subgroup_generator = - // FF(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); - static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; OpeningClaim new_claim; if (has_zk) { + static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; const auto gemini_r = opening_claims[0].opening_pair.challenge; std::array libra_eval_labels = { @@ -317,7 +315,6 @@ template class ShpleminiVerifier_ { // For ZK flavors, the sumcheck output contains the evaluations of Libra univariates that submitted to the // ShpleminiVerifier, otherwise this argument is set to be empty bool consistency_checked = true; - info("has zk ", has_zk, " cons checked ", consistency_checked); if (has_zk) { add_zk_data(commitments, scalars, diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp index 59a3a76856f..65b0fca780d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp @@ -153,10 +153,7 @@ template class ShplonkProver_ { // Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ ) tmp = claim.polynomial; tmp.at(0) = tmp[0] - claim.opening_pair.evaluation; - // info("prover denom", inverse_vanishing_evals[idx]); - Fr scaling_factor = current_nu * inverse_vanishing_evals[idx]; // = νʲ / (z − xⱼ ) - info("current nu ", current_nu); // Add the claim quotient to the batched quotient polynomial G.add_scaled(tmp, -scaling_factor); @@ -183,7 +180,6 @@ template class ShplonkProver_ { std::span> libra_opening_claims = {}) { const Fr nu = transcript->template get_challenge("Shplonk:nu"); - info("prover nu ", nu); auto batched_quotient = compute_batched_quotient(opening_claims, nu, libra_opening_claims); auto batched_quotient_commitment = commitment_key->commit(batched_quotient); transcript->send_to_verifier("Shplonk:Q", batched_quotient_commitment); 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 0d0d6e2d8b9..6681aa00a26 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 @@ -3,21 +3,58 @@ #include "barretenberg/constants.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" -#include "barretenberg/sumcheck/sumcheck_output.hpp" #include "barretenberg/sumcheck/zk_sumcheck_data.hpp" #include -#include -#include #include namespace bb { /** - * @brief This structure is created to contain various polynomials and constants required by ZK Sumcheck. + * @brief Small Subgroup IPA Prover for Zero-Knowledge Opening of Libra Polynomials. * + * @details Implements a less general version of the protocol described in + * [Ariel's HackMD](https://hackmd.io/xYHn1qqvQjey1yJutcuXdg). This version is specialized for making + * commitments and openings of Libra polynomials zero-knowledge. + * + * ### Overview + * This class enables the prover to: + * + * - Open the commitment to concatenated Libra polynomial with zero-knowledge while proving correctness of the claimed + * inner product. The concatenated polynomial is commited to during the construction of ZKSumcheckData structure. + * + * ### Inputs + * The prover receives: + * - **ZKSumcheckData:** Contains: + * - Concatenated coefficients of the masking term and \( d \) random Libra univariates of degree 3. + * - Monomial coefficients of the masked concatenated Libra polynomial denoted by \( G \) . + * - Interpolation domain for a small subgroup \( H \subset \mathbb{F}^\ast \). + * - **Sumcheck challenges:** \( u_0, \ldots, u_{D-1} \), where \( D = \text{CONST_PROOF_SIZE_LOG_N} \). + * - **Claimed inner product:** \( s = \text{claimed\_ipa\_eval} \), defined as: + * \f[ + * s = \sum_{i=1}^{|H|} F(g^i) G(g^i), + * \f] + * where \( F(X) \) is the challenge polynomial and \( G(X) \) is the concatenated Libra polynomial. + * + * ### Prover's Construction + * 1. Define a polynomial \( A(X) \), called the **big sum polynomial**, satisfying: + * - \( A(1) = 0 \), + * - \( A(g^i) = A(g^{i-1}) + F(g^{i-1}) G(g^{i-1}) \) for \( i = 1, \ldots, |H|-1 \). + * 2. Mask \( A(X) \) by adding \( Z_H(X) R(X) \), where \( R(X) \) is a random polynomial of degree 3. + * 3. Commit to \( A(X) \) and send the commitment to the verifier. + * + * ### Key Identity + * If \( A(X) \) is honestly constructed, the following identity holds: + * \f[ + * L_1(X) A(X) + (X - g^{-1}) (A(g \cdot X) - A(X) - F(X) G(X)) + L_{|H|}(X) (A(X) - s) = Z_H(X) Q(X), + * \f] + * where \( Q(X) \) is the quotient of the left-hand side by \( Z_H(X) \). + * + * The methods of this class allow the prover to compute \( A(X) \) and \( Q(X) \). + * + * After receiveing a random evaluation challenge \f$ r \f$ , the prover sends \f$ G(r), A(g\cdot r), A(r), Q(r) \f$ to + * the verifier. In our case, \f$ r \f$ is the Gemini evaluation challenge, and this part is taken care of by Shplemini. */ - template class SmallSubgroupIPAProver { using FF = typename Curve::ScalarField; @@ -42,16 +79,11 @@ template class Sma // Claimed evaluation s = constant_term + g_0(u_0) + ... + g_{d-1}(u_{d-1}) FF claimed_evaluation; - // Monomial coefficients of the challenge polynomial Polynomial challenge_polynomial; - // Challenge polynomial constructed as (1, 1, u_0, u_0^2, 1, u_1,..., u_{27}^2 ) Polynomial challenge_polynomial_lagrange; - - // Monomial coefficients of the polynomial A satisfying A_0 = 0, A_{i} = A_{i-1} + F_{i-1} * G_{i-1} Polynomial big_sum_polynomial; std::array big_sum_lagrange_coeffs; - // L_1(X) * A(X) + (X - 1/g) (A(gX) - A(X) - F(X) G(X)) + L_{|H|}(X)(A(X) - s) Polynomial batched_polynomial; // Quotient of the batched polynomial by the subgroup vanishing polynomial X^{|H|} - 1 @@ -98,8 +130,7 @@ template class Sma return { concatenated_polynomial, big_sum_polynomial, big_sum_polynomial, batched_quotient }; } - // compute concatenated libra polynomial in lagrange basis, transform to monomial, add masking term Z_H(m_0 + - // m_1 X) + // void compute_challenge_polynomial(const std::vector& multivariate_challenge) { std::vector coeffs_lagrange_basis(SUBGROUP_SIZE); @@ -142,6 +173,10 @@ template class Sma } }; + /** + * @brief Compute \f$ L_1(X) * A(X) + (X - 1/g) (A(gX) - A(X) - F(X) G(X)) + L_{|H|}(X)(A(X) - s) \f$ + * + */ void compute_batched_polynomial(const FF& claimed_evaluation) { // Compute shifted big sum polynomial A(gX) @@ -216,6 +251,12 @@ template class Sma } }; +/** + * @brief Verifier class for Small Subgroup IPA Prover. + * + * @details Checks the consistency of polynomial evaluations provided by the prover against + * the values derived from the sumcheck challenge and a random evaluation challenge. + */ template class SmallSubgroupIPAVerifier { using FF = typename Curve::ScalarField; @@ -224,7 +265,7 @@ template class SmallSubgroupIPAVerifier { static constexpr size_t LIBRA_UNIVARIATES_LENGTH = 3; public: - /** + /*! * @brief Verifies the consistency of polynomial evaluations provided by the prover. * * @details @@ -288,9 +329,9 @@ template class SmallSubgroupIPAVerifier { } /** - * @brief Given the sumcheck multivariate challenge \f$ u_0,\ldots, u_{D-1}\f$, where \f$ D = + * @brief Given the sumcheck multivariate challenge \f$ (u_0,\ldots, u_{D-1})\f$, where \f$ D = * \text{CONST_PROOF_SIZE_LOG_N}\f$, the verifier has to construct and evaluate the polynomial whose - * coefficients are given by \f$ (1, u_0, u_0^2, u_1,\ldots,1, u_{D-1}, u_{D-1}^2) \f$. We spend \f$ D \f$ + * coefficients are given by \f$ (1, u_0, u_0^2, u_1,\ldots, 1, u_{D-1}, u_{D-1}^2) \f$. We spend \f$ D \f$ * multiplications to construct the coefficients. * * @param multivariate_challenge @@ -304,6 +345,8 @@ template class SmallSubgroupIPAVerifier { challenge_polynomial_lagrange[0] = FF{ 1 }; FF challenge_sqr = FF{ 1 }; + + // Populate the vector with the powers of the challenges for (size_t poly_idx = 0; poly_idx < CONST_PROOF_SIZE_LOG_N; poly_idx++) { challenge_sqr = multivariate_challenge[poly_idx] * multivariate_challenge[poly_idx]; @@ -318,7 +361,10 @@ template class SmallSubgroupIPAVerifier { /** * @brief Efficient batch evaluation of the challenge polynomial, Lagrange first, and Lagrange last * - * @details It is a + * @details It is a modification of \ref bb::polynomial_arithmetic::compute_barycentric_evaluation + * "compute_barycentric_evaluation" method that does not require EvaluationDomain object and outputs the barycentric + * evaluation of a polynomial along with the evaluations of the first and last Lagrange polynomials. The + * interpolation domain is given by \f$ (1, g, g^2, \ldots, g^{|H| -1 } )\f$ * * @param coeffs Coefficients of the polynomial to be evaluated, in our case it is the challenge polynomial * @param z Evaluation point, we are using the Gemini evaluation challenge @@ -336,14 +382,13 @@ template class SmallSubgroupIPAVerifier { numerator = numerator.pow(SUBGROUP_SIZE) - one; numerator *= one / FF(SUBGROUP_SIZE); // (r^n - 1) / n - // Compute denominators for the barycentric interpolation over the small subgroup denominators[0] = r - one; - FF work_root = inverse_root_of_unity; // ω^{-1} + FF work_root = inverse_root_of_unity; // g^{-1} + // + // Compute the evaluations of the Lagrange polynomials for H for (size_t i = 1; i < SUBGROUP_SIZE; ++i) { - denominators[i] = - work_root * r; // denominators[i] will correspond to L_[i+1] (since our 'commented maths' notation - // indexes L_i from 1). So ʓ.ω^{-i} = ʓ.ω^{1-(i+1)} is correct for L_{i+1}. - denominators[i] -= one; // ʓ.ω^{-i} - 1 + denominators[i] = work_root * r; + denominators[i] -= one; // r * g^{-i} - 1 work_root *= inverse_root_of_unity; } if constexpr (Curve::is_stdlib_type) { @@ -356,17 +401,13 @@ template class SmallSubgroupIPAVerifier { std::array result; result[0] = FF{ 0 }; for (size_t i = 0; i < SUBGROUP_SIZE; ++i) { - FF temp = coeffs[i] * denominators[i]; // f_i * 1/(ʓ.ω^{-i} - 1) + FF temp = coeffs[i] * denominators[i]; // coeffs_i * 1/(r * g^{-i} - 1) result[0] = result[0] + temp; } - result[0] = result[0] * numerator; - result[1] = denominators[0] * numerator; - result[2] = denominators[SUBGROUP_SIZE - 1] * numerator; - - // \sum_{i=0}^{num_coeffs-1} f_i * [ʓ^n - 1]/[n.(ʓ.ω^{-i} - 1)] - // = \sum_{i=0}^{num_coeffs-1} f_i * L_{i+1} - // (with our somewhat messy 'commented maths' convention that L_1 corresponds to the 0th coeff). + result[0] = result[0] * numerator; // The evaluation of the polynomials given by its evaluations over H + result[1] = denominators[0] * numerator; // Lagrange first evaluated at r + result[2] = denominators[SUBGROUP_SIZE - 1] * numerator; // Lagrange last evaluated at r return result; } diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp index fbc90921f6b..68c571ce731 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp @@ -24,8 +24,8 @@ class BN254 { // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = false; - static constexpr size_t SUBGROUP_SIZE = 87; + static constexpr size_t SUBGROUP_SIZE = 377; static constexpr ScalarField SUBGROUP_GENERATOR = - ScalarField(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + ScalarField(uint256_t("0e4061303ba140794a3a2d8659909fd6ffb3dfdc290e4d9ca93bccd950f16404")); }; } // namespace bb::curve \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index a7a234de62b..30dfa3a63fa 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -1163,7 +1163,6 @@ class ECCVMFlavor { num_frs_read); libra_concatenation_commitment = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); - libra_sum = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { @@ -1173,12 +1172,10 @@ class ECCVMFlavor { } libra_claimed_evaluation = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); - sumcheck_evaluations = NativeTranscript::template deserialize_from_buffer>( NativeTranscript::proof_data, num_frs_read); libra_big_sum_commitment = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); - libra_quotient_commitment = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); hiding_polynomial_commitment = @@ -1195,7 +1192,6 @@ class ECCVMFlavor { libra_shifted_big_sum_eval = deserialize_from_buffer(proof_data, num_frs_read); libra_big_sum_eval = deserialize_from_buffer(proof_data, num_frs_read); libra_quotient_eval = deserialize_from_buffer(proof_data, num_frs_read); - shplonk_q_comm = deserialize_from_buffer(proof_data, num_frs_read); translation_eval_op = @@ -1332,7 +1328,6 @@ class ECCVMFlavor { NativeTranscript::template serialize_to_buffer(sumcheck_evaluations, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(libra_big_sum_commitment, proof_data); NativeTranscript::template serialize_to_buffer(libra_quotient_commitment, proof_data); - NativeTranscript::template serialize_to_buffer(hiding_polynomial_commitment, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(hiding_polynomial_eval, NativeTranscript::proof_data); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { @@ -1341,7 +1336,6 @@ class ECCVMFlavor { for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { NativeTranscript::template serialize_to_buffer(gemini_fold_evals[i], proof_data); } - NativeTranscript::template serialize_to_buffer(libra_concatenation_eval, proof_data); NativeTranscript::template serialize_to_buffer(libra_shifted_big_sum_eval, proof_data); NativeTranscript::template serialize_to_buffer(libra_big_sum_eval, proof_data); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index fc499714b65..38c194dab69 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -139,7 +139,6 @@ class ECCVMTranscriptTests : public ::testing::Test { round++; manifest_expected.add_entry(round, "Libra:concatenation_commitment", frs_per_G); - manifest_expected.add_entry(round, "Libra:Sum", frs_per_Fr); // get the challenge for the ZK Sumcheck claim manifest_expected.add_challenge(round, "Libra:Challenge"); @@ -156,10 +155,8 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "Libra:claimed_evaluation", frs_per_Fr); manifest_expected.add_entry(round, "Sumcheck:evaluations", frs_per_evals); - manifest_expected.add_entry(round, "Libra:big_sum_commitment", frs_per_G); manifest_expected.add_entry(round, "Libra:quotient_commitment", frs_per_G); - manifest_expected.add_entry(round, "Gemini:masking_poly_comm", frs_per_G); manifest_expected.add_entry(round, "Gemini:masking_poly_eval", frs_per_Fr); @@ -181,7 +178,6 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "Libra:big_sum_eval", frs_per_Fr); manifest_expected.add_entry(round, "Libra:quotient_eval", frs_per_Fr); manifest_expected.add_challenge(round, "Shplonk:nu"); - round++; manifest_expected.add_entry(round, "Shplonk:Q", frs_per_G); manifest_expected.add_challenge(round, "Shplonk:z"); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 66acae5cd7d..a25625f020c 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -64,6 +64,7 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); + // If Sumcheck did not verify, return false if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { vinfo("eccvm sumcheck failed"); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp index 9fa50942d88..4f68e0187dc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp @@ -46,9 +46,10 @@ template struct bn254 { static const ScalarField SUBGROUP_GENERATOR; }; // namespace bn254 + template const typename bn254::ScalarField bn254::SUBGROUP_GENERATOR = typename bn254::ScalarField( - uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + uint256_t("0e4061303ba140794a3a2d8659909fd6ffb3dfdc290e4d9ca93bccd950f16404")); } // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp index 198be7788a6..9c9c396cceb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp @@ -53,7 +53,6 @@ class MegaZKFlavor : public bb::MegaFlavor { FF libra_sum; std::vector> sumcheck_univariates; FF libra_claimed_evaluation; - Commitment libra_big_sum_commitment; Commitment libra_quotient_commitment; std::array sumcheck_evaluations; @@ -135,11 +134,8 @@ class MegaZKFlavor : public bb::MegaFlavor { } libra_claimed_evaluation = deserialize_from_buffer(proof_data, num_frs_read); sumcheck_evaluations = deserialize_from_buffer>(proof_data, num_frs_read); - libra_big_sum_commitment = deserialize_from_buffer(proof_data, num_frs_read); - libra_quotient_commitment = deserialize_from_buffer(proof_data, num_frs_read); - hiding_polynomial_commitment = deserialize_from_buffer(proof_data, num_frs_read); hiding_polynomial_eval = deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { @@ -193,7 +189,6 @@ class MegaZKFlavor : public bb::MegaFlavor { serialize_to_buffer(z_perm_comm, proof_data); serialize_to_buffer(libra_concatenation_commitment, proof_data); - NativeTranscript::template serialize_to_buffer(libra_sum, NativeTranscript::proof_data); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { @@ -204,7 +199,6 @@ class MegaZKFlavor : public bb::MegaFlavor { serialize_to_buffer(sumcheck_evaluations, proof_data); serialize_to_buffer(libra_big_sum_commitment, proof_data); serialize_to_buffer(libra_quotient_commitment, proof_data); - serialize_to_buffer(hiding_polynomial_commitment, NativeTranscript::proof_data); serialize_to_buffer(hiding_polynomial_eval, NativeTranscript::proof_data); for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { @@ -217,7 +211,6 @@ class MegaZKFlavor : public bb::MegaFlavor { serialize_to_buffer(libra_shifted_big_sum_eval, proof_data); serialize_to_buffer(libra_big_sum_eval, proof_data); serialize_to_buffer(libra_quotient_eval, proof_data); - serialize_to_buffer(shplonk_q_comm, proof_data); serialize_to_buffer(kzg_w_comm, proof_data); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 04f6ee7efcb..0a532c17c10 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -153,7 +153,7 @@ template class SumcheckProver { // Define the length of Libra Univariates. For non-ZK Flavors: set to 0. static constexpr size_t LIBRA_UNIVARIATES_LENGTH = Flavor::HasZK ? Flavor::BATCHED_RELATION_PARTIAL_LENGTH : 0; using LibraUnivariates = std::vector>; - using ZKSumcheckData = ZKSumcheckData; + using ZKData = ZKSumcheckData; std::shared_ptr transcript; SumcheckProverRound round; @@ -190,7 +190,7 @@ template class SumcheckProver { const bb::RelationParameters& relation_parameters, const RelationSeparator alpha, const std::vector& gate_challenges, - ZKSumcheckData zk_sumcheck_data = ZKSumcheckData()) + ZKData zk_sumcheck_data = ZKData()) { bb::GateSeparatorPolynomial gate_separators(gate_challenges, multivariate_d); @@ -401,7 +401,7 @@ polynomials that are sent in clear. * @param libra_running_sum * @param libra_evaluations */ - void update_zk_sumcheck_data(ZKSumcheckData& zk_sumcheck_data, const FF round_challenge, size_t round_idx) + void update_zk_sumcheck_data(ZKData& zk_sumcheck_data, const FF round_challenge, size_t round_idx) { constexpr FF one_half = FF(1) / FF(2); // when round_idx = d - 1, the update is not needed diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp index 2e8236fbf68..5c379314115 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp @@ -25,7 +25,6 @@ template class SumcheckTests : public ::testing::Test { ZKSumcheckData; const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; - static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } Polynomial random_poly(size_t size) diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index dbc73b35eb3..e251b97a7b5 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -41,10 +41,7 @@ template class SumcheckProverRound { public: using FF = typename Flavor::FF; using ExtendedEdges = typename Flavor::ExtendedEdges; - - using ZKSumcheckData = - ZKSumcheckData; - + using ZKData = ZKSumcheckData; /** * @brief In Round \f$i = 0,\ldots, d-1\f$, equals \f$2^{d-i}\f$. */ @@ -145,7 +142,7 @@ template class SumcheckProverRound { const bb::RelationParameters& relation_parameters, const bb::GateSeparatorPolynomial& gate_sparators, const RelationSeparator alpha, - ZKSumcheckData zk_sumcheck_data, // only populated when Flavor HasZK + ZKData zk_sumcheck_data, // only populated when Flavor HasZK RowDisablingPolynomial row_disabling_poly) { PROFILE_THIS_NAME("compute_univariate"); @@ -337,8 +334,7 @@ template class SumcheckProverRound { * @param zk_sumcheck_data * @param round_idx */ - static SumcheckRoundUnivariate compute_libra_round_univariate(const ZKSumcheckData& zk_sumcheck_data, - size_t round_idx) + static SumcheckRoundUnivariate compute_libra_round_univariate(const ZKData& zk_sumcheck_data, size_t round_idx) { bb::Univariate libra_round_univariate; // select the i'th column of Libra book-keeping table diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 30fff269b57..257186fc715 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -4,7 +4,6 @@ #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include -#include #include namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 61845250650..f65267137f7 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -36,7 +36,7 @@ template void DeciderProver_::execute_relation_ch if constexpr (Flavor::HasZK) { const size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); auto commitment_key = std::make_shared(1 << (log_subgroup_size + 1)); - zk_sumcheck_data = ZKSumcheckData(numeric::get_msb(polynomial_size), transcript, commitment_key); + zk_sumcheck_data = ZKData(numeric::get_msb(polynomial_size), transcript, commitment_key); sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, proving_key->relation_parameters, proving_key->alphas, diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp index b09f27efb13..d40dc157c90 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp @@ -25,7 +25,7 @@ template class DeciderProver_ { using DeciderPK = DeciderProvingKey_; using Transcript = typename Flavor::Transcript; using RelationSeparator = typename Flavor::RelationSeparator; - using ZKSumcheckData = ZKSumcheckData; + using ZKData = ZKSumcheckData; using SmallSubgroupIPA = SmallSubgroupIPAProver; public: @@ -48,7 +48,7 @@ template class DeciderProver_ { Polynomial quotient_W; - ZKSumcheckData zk_sumcheck_data; + ZKData zk_sumcheck_data; SumcheckOutput sumcheck_output; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp index ce139920f74..6324b0c1c0e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp @@ -96,7 +96,6 @@ template class MegaTranscriptTests : public ::testing::Test { } if constexpr (Flavor::HasZK) { - manifest_expected.add_entry(round, "Libra:concatenation_commitment", frs_per_G); manifest_expected.add_entry(round, "Libra:Sum", frs_per_Fr); manifest_expected.add_challenge(round, "Libra:Challenge"); @@ -120,7 +119,6 @@ template class MegaTranscriptTests : public ::testing::Test { if constexpr (Flavor::HasZK) { manifest_expected.add_entry(round, "Libra:big_sum_commitment", frs_per_G); manifest_expected.add_entry(round, "Libra:quotient_commitment", frs_per_G); - manifest_expected.add_entry(round, "Gemini:masking_poly_comm", frs_per_G); manifest_expected.add_entry(round, "Gemini:masking_poly_eval", frs_per_Fr); } From e11702b291e262357d42c32520224585d3c14eab Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 18 Dec 2024 16:43:07 +0000 Subject: [PATCH 20/30] come back to 87 --- barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp | 4 ++-- .../cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp index 68c571ce731..fbc90921f6b 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp @@ -24,8 +24,8 @@ class BN254 { // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = false; - static constexpr size_t SUBGROUP_SIZE = 377; + static constexpr size_t SUBGROUP_SIZE = 87; static constexpr ScalarField SUBGROUP_GENERATOR = - ScalarField(uint256_t("0e4061303ba140794a3a2d8659909fd6ffb3dfdc290e4d9ca93bccd950f16404")); + ScalarField(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); }; } // namespace bb::curve \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp index 4f68e0187dc..2eb9b891854 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp @@ -50,6 +50,6 @@ template struct bn254 { template const typename bn254::ScalarField bn254::SUBGROUP_GENERATOR = typename bn254::ScalarField( - uint256_t("0e4061303ba140794a3a2d8659909fd6ffb3dfdc290e4d9ca93bccd950f16404")); + uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); } // namespace bb::stdlib From 63a855baf4cd232b5bd18d4a8a802a6c517eac0b Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Wed, 18 Dec 2024 19:57:17 +0000 Subject: [PATCH 21/30] adding tests --- .../small_subgroup_ipa/small_subgroup_ipa.hpp | 3 +- .../small_subgroup_ipa.test.cpp | 75 +++++++++++++++++++ .../src/barretenberg/sumcheck/sumcheck.hpp | 2 +- .../sumcheck/zk_sumcheck_data.hpp | 7 +- 4 files changed, 82 insertions(+), 5 deletions(-) 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/small_subgroup_ipa/small_subgroup_ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp index 6681aa00a26..0686323d9a2 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 @@ -129,8 +129,9 @@ template class Sma { return { concatenated_polynomial, big_sum_polynomial, big_sum_polynomial, batched_quotient }; } + // Getter for test purposes only + const Polynomial& get_batched_polynomial() const { return batched_polynomial; } - // void compute_challenge_polynomial(const std::vector& multivariate_challenge) { std::vector coeffs_lagrange_basis(SUBGROUP_SIZE); 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..3f8218e829d --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp @@ -0,0 +1,75 @@ +#pragma once +#include "../commitment_key.test.hpp" +#include +#include +#include +// #include "barretenberg/commitment_schemes/claim.hpp" + +#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" +#include "barretenberg/constants.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/sumcheck/zk_sumcheck_data.hpp" +#include "barretenberg/transcript/transcript.hpp" + +#include +#include + +namespace bb { +template class SmallSubgroupIPATest : public CommitmentTest {}; + +auto& engine = numeric::get_debug_randomness(); + +using CurveTypes = ::testing::Types; + +TYPED_TEST_SUITE(SmallSubgroupIPATest, CurveTypes); + +TYPED_TEST(SmallSubgroupIPATest, BatchedQuotientComputation) +{ + using FF = typename TypeParam::ScalarField; + using SmallSubgroupIPA = SmallSubgroupIPAProver>; + using ZKSumcheckData = ZKSumcheckData>; + static constexpr size_t SUBGROUP_SIZE = TypeParam::SUBGROUP_SIZE; + auto prover_transcript = NativeTranscript::prover_init_empty(); + + const size_t log_circuit_size = 7; + ZKSumcheckData zk_sumcheck_data = ZKSumcheckData(log_circuit_size, prover_transcript, this->ck()); + + std::vector multivariate_challenge = this->random_evaluation_point(log_circuit_size); + + FF claimed_ipa_eval = zk_sumcheck_data.constant_term; + for (auto& [challenge, libra_univariate] : zip_view(multivariate_challenge, zk_sumcheck_data.libra_univariates)) { + claimed_ipa_eval += libra_univariate.evaluate(challenge); + } + + SmallSubgroupIPA small_subgroup_ipa_prover = + SmallSubgroupIPA(zk_sumcheck_data, multivariate_challenge, claimed_ipa_eval, prover_transcript, this->ck()); + + auto batched_polynomial = small_subgroup_ipa_prover.get_batched_polynomial(); + + auto batched_quotient = small_subgroup_ipa_prover.get_witness_polynomials()[2]; + + // Check that batched polynomial is divisible by Z_H(X) + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + EXPECT_EQ(batched_polynomial.evaluate(zk_sumcheck_data.interpolation_domain[idx]), FF{ 0 }); + } + + std::vector Z_H(SUBGROUP_SIZE + 1); + Z_H[0] = -FF(1); + Z_H[SUBGROUP_SIZE] = FF(1); + + std::vector product; + for (size_t i = 0; i < Z_H.size(); i++) { + for (size_t j = 0; j < batched_quotient.size(); j++) { + product[i + j] = Z_H[i] * batched_quotient[j]; + } + } + + info("product size", product.size()); + EXPECT_EQ(product.size(), batched_polynomial.size()); + + for (auto [coeff_expected, coeff] : zip_view(product, batched_polynomial)) { + EXPECT_EQ(coeff, coeff_expected); + } +} +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 0a532c17c10..91a899c1944 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -403,7 +403,7 @@ polynomials that are sent in clear. */ void update_zk_sumcheck_data(ZKData& zk_sumcheck_data, const FF round_challenge, size_t round_idx) { - constexpr FF one_half = FF(1) / FF(2); + static constexpr FF one_half = FF(1) / FF(2); // when round_idx = d - 1, the update is not needed if (round_idx < zk_sumcheck_data.libra_univariates.size() - 1) { for (auto& univariate : zk_sumcheck_data.libra_univariates) { diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 257186fc715..8986dd8a047 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -12,7 +12,7 @@ namespace bb { * @brief This structure is created to contain various polynomials and constants required by ZK Sumcheck. * */ -template struct ZKSumcheckData { +template struct ZKSumcheckData { using FF = typename Curve::ScalarField; @@ -148,8 +148,9 @@ template struct ZK void create_interpolation_domain() { - for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { - interpolation_domain[idx] = subgroup_generator.pow(idx); + interpolation_domain[0] = FF{ 1 }; + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + interpolation_domain[idx] = interpolation_domain[idx - 1] * subgroup_generator; } } From be153e6a60efe4f999abf0abe042fcd4ffe3c29e Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 19 Dec 2024 15:04:35 +0000 Subject: [PATCH 22/30] added ifft for bn254 - no need to commit to sumcheck univariates --- .../small_subgroup_ipa/small_subgroup_ipa.hpp | 51 +++++++++++++++---- .../small_subgroup_ipa.test.cpp | 15 +++--- .../barretenberg/ecc/curves/bn254/bn254.hpp | 4 +- .../sumcheck/zk_sumcheck_data.hpp | 20 +++++++- 4 files changed, 71 insertions(+), 19 deletions(-) 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 0686323d9a2..416e955287d 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 @@ -1,6 +1,7 @@ #pragma once #include "barretenberg/constants.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/sumcheck/zk_sumcheck_data.hpp" @@ -71,6 +72,8 @@ template class Sma // Interpolation domain {1, g, \ldots, g^{SUBGROUP_SIZE - 1}} std::array interpolation_domain; + EvaluationDomain bn_evaluation_domain; + // Monomial coefficients of the concatenated Libra masking polynomial Polynomial concatenated_polynomial; // Lagrange coefficeints of the concatenated Libra masking polynomial = constant_term || g_0 || ... || g_{d-1} @@ -81,6 +84,7 @@ template class Sma Polynomial challenge_polynomial; Polynomial challenge_polynomial_lagrange; + Polynomial big_sum_polynomial_unmasked; Polynomial big_sum_polynomial; std::array big_sum_lagrange_coeffs; @@ -99,14 +103,16 @@ template class Sma , concatenated_polynomial(zk_sumcheck_data.libra_concatenated_monomial_form) , libra_concatenated_lagrange_form(zk_sumcheck_data.libra_concatenated_lagrange_form) , challenge_polynomial(SUBGROUP_SIZE) - , challenge_polynomial_lagrange(SUBGROUP_SIZE) // public polynomial + , challenge_polynomial_lagrange(SUBGROUP_SIZE) // public polynomial + , big_sum_polynomial_unmasked(SUBGROUP_SIZE) , big_sum_polynomial(SUBGROUP_SIZE + 3) // includes masking , batched_polynomial(BATCHED_POLYNOMIAL_LENGTH) // batched polynomial, input to shplonk prover , batched_quotient(QUOTIENT_LENGTH) // quotient of the batched polynomial by Z_H(X) = X^87 - 1 { - - ASSERT(concatenated_polynomial.size() < SUBGROUP_SIZE + 3); + if constexpr (std::is_same_v) { + bn_evaluation_domain = std::move(zk_sumcheck_data.bn_evaluation_domain); + } compute_challenge_polynomial(multivariate_challenge); @@ -129,8 +135,9 @@ template class Sma { return { concatenated_polynomial, big_sum_polynomial, big_sum_polynomial, batched_quotient }; } - // Getter for test purposes only + // Getters for test purposes only const Polynomial& get_batched_polynomial() const { return batched_polynomial; } + const Polynomial& get_challenge_polynomial() const { return challenge_polynomial; } void compute_challenge_polynomial(const std::vector& multivariate_challenge) { @@ -144,7 +151,14 @@ template class Sma } } challenge_polynomial_lagrange = Polynomial(coeffs_lagrange_basis); - challenge_polynomial = Polynomial(interpolation_domain, coeffs_lagrange_basis, SUBGROUP_SIZE); + if constexpr (!std::is_same_v) { + challenge_polynomial = Polynomial(interpolation_domain, coeffs_lagrange_basis, SUBGROUP_SIZE); + } else { + std::vector challenge_polynomial_ifft(SUBGROUP_SIZE); + polynomial_arithmetic::ifft( + coeffs_lagrange_basis.data(), challenge_polynomial_ifft.data(), bn_evaluation_domain); + challenge_polynomial = Polynomial(challenge_polynomial_ifft); + } } void compute_big_sum_polynomial() @@ -160,8 +174,13 @@ template class Sma }; // Get the coefficients in the monomial basis - auto big_sum_polynomial_unmasked = Polynomial(interpolation_domain, big_sum_lagrange_coeffs, SUBGROUP_SIZE); - + if constexpr (!std::is_same_v) { + big_sum_polynomial_unmasked = Polynomial(interpolation_domain, big_sum_lagrange_coeffs, SUBGROUP_SIZE); + } else { + std::vector big_sum_ifft(SUBGROUP_SIZE); + polynomial_arithmetic::ifft(big_sum_lagrange_coeffs.data(), big_sum_ifft.data(), bn_evaluation_domain); + big_sum_polynomial_unmasked = Polynomial(big_sum_ifft); + } // Generate random masking_term of degree 2, add Z_H(X) * masking_term bb::Univariate masking_term = bb::Univariate::get_random(); for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { @@ -193,13 +212,27 @@ template class Sma lagrange_coeffs[idx] = FF(0); } - Polynomial lagrange_first_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + Polynomial lagrange_first_monomial(SUBGROUP_SIZE); + if constexpr (!std::is_same_v) { + lagrange_first_monomial = Polynomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + } else { + std::vector lagrange_first_ifft(SUBGROUP_SIZE); + polynomial_arithmetic::ifft(lagrange_coeffs.data(), lagrange_first_ifft.data(), bn_evaluation_domain); + lagrange_first_monomial = Polynomial(lagrange_first_ifft); + } // Compute the monomial coefficients of L_{|H|}, the last Lagrange polynomial lagrange_coeffs[0] = FF(0); lagrange_coeffs[SUBGROUP_SIZE - 1] = FF(1); - Polynomial lagrange_last_monomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + Polynomial lagrange_last_monomial; + if constexpr (!std::is_same_v) { + lagrange_last_monomial = Polynomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + } else { + std::vector lagrange_last_ifft(SUBGROUP_SIZE); + polynomial_arithmetic::ifft(lagrange_coeffs.data(), lagrange_last_ifft.data(), bn_evaluation_domain); + lagrange_last_monomial = Polynomial(lagrange_last_ifft); + } // Compute -F(X)*G(X), the negated product of challenge_polynomial and libra_concatenated_monomial_form // Polynomial result(BATCHED_POLYNOMIAL_LENGTH); 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 3f8218e829d..1c0244b3980 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,4 +1,4 @@ -#pragma once + #include "../commitment_key.test.hpp" #include #include @@ -38,7 +38,9 @@ TYPED_TEST(SmallSubgroupIPATest, BatchedQuotientComputation) std::vector multivariate_challenge = this->random_evaluation_point(log_circuit_size); FF claimed_ipa_eval = zk_sumcheck_data.constant_term; - for (auto& [challenge, libra_univariate] : zip_view(multivariate_challenge, zk_sumcheck_data.libra_univariates)) { + // info(zk_sumcheck_data.libra_univariates[2].at(3)); + for (const auto& [challenge, libra_univariate] : + zip_view(multivariate_challenge, zk_sumcheck_data.libra_univariates)) { claimed_ipa_eval += libra_univariate.evaluate(challenge); } @@ -46,11 +48,12 @@ TYPED_TEST(SmallSubgroupIPATest, BatchedQuotientComputation) SmallSubgroupIPA(zk_sumcheck_data, multivariate_challenge, claimed_ipa_eval, prover_transcript, this->ck()); auto batched_polynomial = small_subgroup_ipa_prover.get_batched_polynomial(); + auto challenge_polynomial = small_subgroup_ipa_prover.get_challenge_polynomial(); auto batched_quotient = small_subgroup_ipa_prover.get_witness_polynomials()[2]; // Check that batched polynomial is divisible by Z_H(X) - for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + for (size_t idx = 0; idx < 4; idx++) { EXPECT_EQ(batched_polynomial.evaluate(zk_sumcheck_data.interpolation_domain[idx]), FF{ 0 }); } @@ -68,8 +71,8 @@ TYPED_TEST(SmallSubgroupIPATest, BatchedQuotientComputation) info("product size", product.size()); EXPECT_EQ(product.size(), batched_polynomial.size()); - for (auto [coeff_expected, coeff] : zip_view(product, batched_polynomial)) { - EXPECT_EQ(coeff, coeff_expected); - } + // for (auto [coeff_expected, coeff] : zip_view(product, batched_polynomial.coeffs())) { + // EXPECT_EQ(coeff, coeff_expected); + // } } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp index fbc90921f6b..a826b7594fd 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp @@ -24,8 +24,8 @@ class BN254 { // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = false; - static constexpr size_t SUBGROUP_SIZE = 87; + static constexpr size_t SUBGROUP_SIZE = 256; static constexpr ScalarField SUBGROUP_GENERATOR = - ScalarField(uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + ScalarField(uint256_t("0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76")); }; } // namespace bb::curve \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 8986dd8a047..8a6cd83525f 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -1,6 +1,7 @@ #pragma once #include "barretenberg/constants.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include @@ -28,6 +29,8 @@ template ; FF constant_term; + + EvaluationDomain bn_evaluation_domain; std::array interpolation_domain; // to compute product in lagrange basis Polynomial libra_concatenated_lagrange_form; @@ -148,6 +151,11 @@ template ) { + bn_evaluation_domain = EvaluationDomain(SUBGROUP_SIZE, SUBGROUP_SIZE); + bn_evaluation_domain.compute_lookup_table(); + } + interpolation_domain[0] = FF{ 1 }; for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { interpolation_domain[idx] = interpolation_domain[idx - 1] * subgroup_generator; @@ -175,8 +183,16 @@ template masking_scalars = bb::Univariate::get_random(); - auto libra_concatenated_monomial_form_unmasked = - Polynomial(interpolation_domain, coeffs_lagrange_subgroup, SUBGROUP_SIZE); + Polynomial libra_concatenated_monomial_form_unmasked(SUBGROUP_SIZE); + if constexpr (!std::is_same_v) { + libra_concatenated_monomial_form_unmasked = + Polynomial(interpolation_domain, coeffs_lagrange_subgroup, SUBGROUP_SIZE); + } else { + std::vector coeffs_lagrange_subgroup_ifft(SUBGROUP_SIZE); + polynomial_arithmetic::ifft( + coeffs_lagrange_subgroup.data(), coeffs_lagrange_subgroup_ifft.data(), bn_evaluation_domain); + libra_concatenated_monomial_form_unmasked = Polynomial(coeffs_lagrange_subgroup_ifft); + } for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { libra_concatenated_monomial_form.at(idx) = libra_concatenated_monomial_form_unmasked.at(idx); From 20e8b53097d16b009695160157f3f8ae3f3d8d69 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 19 Dec 2024 22:28:40 +0000 Subject: [PATCH 23/30] docs + gcc --- .../commitment_schemes/shplonk/shplemini.hpp | 1 - .../small_subgroup_ipa/small_subgroup_ipa.hpp | 223 ++++++++++++------ .../small_subgroup_ipa.test.cpp | 78 ------ .../src/barretenberg/eccvm/eccvm_prover.cpp | 2 +- .../src/barretenberg/eccvm/eccvm_prover.hpp | 6 +- .../stdlib/primitives/curves/bn254.hpp | 5 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 18 +- .../barretenberg/sumcheck/sumcheck.test.cpp | 10 +- .../barretenberg/sumcheck/sumcheck_round.hpp | 17 +- .../sumcheck/zk_sumcheck_data.hpp | 45 ++-- .../translator_vm/translator_prover.cpp | 4 +- .../translator_vm/translator_prover.hpp | 4 +- .../ultra_honk/decider_prover.cpp | 21 +- .../ultra_honk/decider_prover.hpp | 4 +- 14 files changed, 233 insertions(+), 205 deletions(-) delete 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/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 4e5e1fa4a57..7f7a087917b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -155,7 +155,6 @@ template class ShpleminiVerifier_ { { // Extract log_circuit_size size_t log_circuit_size{ 0 }; - // info(libra_univariate_evaluation); if constexpr (Curve::is_stdlib_type) { log_circuit_size = numeric::get_msb(static_cast(N.get_value())); } else { 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 416e955287d..f4f2929e2d2 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 @@ -56,101 +56,153 @@ namespace bb { * After receiveing a random evaluation challenge \f$ r \f$ , the prover sends \f$ G(r), A(g\cdot r), A(r), Q(r) \f$ to * the verifier. In our case, \f$ r \f$ is the Gemini evaluation challenge, and this part is taken care of by Shplemini. */ -template class SmallSubgroupIPAProver { +template class SmallSubgroupIPAProver { + using Curve = typename Flavor::Curve; using FF = typename Curve::ScalarField; - + // The size of a multiplicative subgroup in the ScalarField of a curve static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; - + // Size of the polynomial to be divided by Z_H static constexpr size_t BATCHED_POLYNOMIAL_LENGTH = 2 * SUBGROUP_SIZE + 2; - + // Size of Q(X) static constexpr size_t QUOTIENT_LENGTH = SUBGROUP_SIZE + 2; - - static constexpr size_t LIBRA_UNIVARIATES_LENGTH = 3; - + // The length of a random polynomial to mask Prover's Sumcheck Univariates. In the case of BN254-based Flavors, we + // send the coefficients of the univariates, hence we choose these value to be the max sumcheck univariate length + // over Translator, Ultra, and Mega. In ECCVM, the Sumcheck prover will commit to its univariates, which reduces the + // required length from 23 to 3. + static constexpr size_t LIBRA_UNIVARIATES_LENGTH = (std::is_same_v) ? 9 : 3; + // Fixed generator of H static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; - // Interpolation domain {1, g, \ldots, g^{SUBGROUP_SIZE - 1}} + // Interpolation domain {1, g, \ldots, g^{SUBGROUP_SIZE - 1}} used by ECCVM std::array interpolation_domain; - + // We use IFFT over BN254 scalar field EvaluationDomain bn_evaluation_domain; - // Monomial coefficients of the concatenated Libra masking polynomial + // Monomial coefficients of the concatenated Libra masking polynomial extracted from ZKSumcheckData Polynomial concatenated_polynomial; // Lagrange coefficeints of the concatenated Libra masking polynomial = constant_term || g_0 || ... || g_{d-1} Polynomial libra_concatenated_lagrange_form; - // Claimed evaluation s = constant_term + g_0(u_0) + ... + g_{d-1}(u_{d-1}) + // Claimed evaluation s = constant_term + g_0(u_0) + ... + g_{d-1}(u_{d-1}), where g_i is the i'th Libra masking + // univariate FF claimed_evaluation; + // The polynomial obtained by concatenated powers of sumcheck challenges Polynomial challenge_polynomial; Polynomial challenge_polynomial_lagrange; + + // Big sum polynomial A(X) Polynomial big_sum_polynomial_unmasked; Polynomial big_sum_polynomial; std::array big_sum_lagrange_coeffs; + // The RHS of the key identity, denoted C(X) in the HackMD Polynomial batched_polynomial; - // Quotient of the batched polynomial by the subgroup vanishing polynomial X^{|H|} - 1 + // Quotient of the batched polynomial C(X) by the subgroup vanishing polynomial X^{|H|} - 1 Polynomial batched_quotient; public: - SmallSubgroupIPAProver(ZKSumcheckData& zk_sumcheck_data, + SmallSubgroupIPAProver(ZKSumcheckData& zk_sumcheck_data, const std::vector& multivariate_challenge, const FF claimed_ipa_eval, - std::shared_ptr transcript, - std::shared_ptr commitment_key = nullptr) + std::shared_ptr transcript, + std::shared_ptr commitment_key = nullptr) : interpolation_domain(zk_sumcheck_data.interpolation_domain) , concatenated_polynomial(zk_sumcheck_data.libra_concatenated_monomial_form) , libra_concatenated_lagrange_form(zk_sumcheck_data.libra_concatenated_lagrange_form) , challenge_polynomial(SUBGROUP_SIZE) - , challenge_polynomial_lagrange(SUBGROUP_SIZE) // public polynomial + , challenge_polynomial_lagrange(SUBGROUP_SIZE) , big_sum_polynomial_unmasked(SUBGROUP_SIZE) - , big_sum_polynomial(SUBGROUP_SIZE + 3) // includes masking - , batched_polynomial(BATCHED_POLYNOMIAL_LENGTH) // batched polynomial, input to shplonk prover - , batched_quotient(QUOTIENT_LENGTH) // quotient of the batched polynomial by Z_H(X) = X^87 - 1 + , big_sum_polynomial(SUBGROUP_SIZE + 3) // + 3 to account for masking + , batched_polynomial(BATCHED_POLYNOMIAL_LENGTH) + , batched_quotient(QUOTIENT_LENGTH) { + // Extract the evaluation domain computed by ZKSumcheckData if constexpr (std::is_same_v) { bn_evaluation_domain = std::move(zk_sumcheck_data.bn_evaluation_domain); } + // Construct the challenge polynomial in Lagrange basis, compute its monomial coefficients compute_challenge_polynomial(multivariate_challenge); + // Construct unmasked big sum polynomial in Lagrange basis, compute its monomial coefficients, and mask it compute_big_sum_polynomial(); + + // Send masked commitment [A + Z_H * R] to the verifier, where R is of degree 2 if (commitment_key) { transcript->template send_to_verifier("Libra:big_sum_commitment", commitment_key->commit(big_sum_polynomial)); } + // Compute C(X) compute_batched_polynomial(claimed_ipa_eval); + + // Compute Q(X) compute_batched_quotient(); + // Send commitment [Q] to the verifier if (commitment_key) { transcript->template send_to_verifier("Libra:quotient_commitment", commitment_key->commit(batched_quotient)); } } + // Getter to pass the witnesses to ShpleminiProver. Big sum polynomial is evaluated at 2 points (and is small) std::array, 4> get_witness_polynomials() const { return { concatenated_polynomial, big_sum_polynomial, big_sum_polynomial, batched_quotient }; } - // Getters for test purposes only + // Getters for test purposes const Polynomial& get_batched_polynomial() const { return batched_polynomial; } const Polynomial& get_challenge_polynomial() const { return challenge_polynomial; } + /** + * @brief Computes the challenge polynomial F(X) based on the provided multivariate challenges. + * + * This method generates a polynomial in both Lagrange basis and monomial basis from Sumcheck's + * multivariate_challenge vector. The result is stored in `challenge_polynomial_lagrange` and + * `challenge_polynomial`. The former is re-used in the computation of the big sum polynomial A(X) + * + * ### Lagrange Basis + * The Lagrange basis polynomial is constructed as follows: + * - Initialize the first coefficient as `1`. + * - For each challenge index `idx_poly` in the `CONST_PROOF_SIZE_LOG_N` range, compute a sequence of coefficients + * recursively as powers of the corresponding multivariate challenge. + * - Store these coefficients in `coeffs_lagrange_basis`. + * + * ### Monomial Basis + * If the curve is not `BN254`, the monomial polynomial is constructed directly using un-optimized Lagrange + * interpolation. Otherwise, an IFFT is used to convert the Lagrange basis coefficients into monomial basis + * coefficients. + * + * ### Notes: + * - The `LIBRA_UNIVARIATES_LENGTH` determines the number of recursive powers computed per challenge. + * - For `BN254`, the polynomial is computed using an IFFT operation to convert from the Lagrange basis to the + * monomial basis. + * + * @param multivariate_challenge A vector of field elements used to compute the challenge polynomial. + */ void compute_challenge_polynomial(const std::vector& multivariate_challenge) { std::vector coeffs_lagrange_basis(SUBGROUP_SIZE); coeffs_lagrange_basis[0] = FF(1); - for (size_t idx_poly = 0; idx_poly < CONST_PROOF_SIZE_LOG_N; idx_poly++) { - for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { - size_t current_idx = 1 + LIBRA_UNIVARIATES_LENGTH * idx_poly + idx; - coeffs_lagrange_basis[current_idx] = multivariate_challenge[idx_poly].pow(idx); + for (size_t challenge_idx = 0; challenge_idx < CONST_PROOF_SIZE_LOG_N; challenge_idx++) { + // We concatenate 1 with CONST_PROOF_SIZE_LOG_N Libra Univariates of length LIBRA_UNIVARIATES_LENGTH + 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; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { + // Recursively compute the powers of the challenge + coeffs_lagrange_basis[poly_to_concatenate_start + idx] = + coeffs_lagrange_basis[poly_to_concatenate_start + idx - 1] * multivariate_challenge[challenge_idx]; } } + challenge_polynomial_lagrange = Polynomial(coeffs_lagrange_basis); + + // Compute monomial coefficients if constexpr (!std::is_same_v) { challenge_polynomial = Polynomial(interpolation_domain, coeffs_lagrange_basis, SUBGROUP_SIZE); } else { @@ -161,6 +213,23 @@ template class Sma } } + /** + * @brief Computes the big sum polynomial A(X) + * + * #### Lagrange Basis + * - First, we recursively compute the coefficients of the unmasked big sum polynomial, i.e. we set the first + * coefficient to `0`. + * - For each i, the coefficient is updated as: + * \f$ \texttt{big_sum_lagrange_coeffs} (g^{i}) = + * \texttt{big_sum_lagrange_coeffs} (g^{i-1}) + + * \texttt{challenge_polynomial_lagrange[prev_idx]} (g^{i-1}) \cdot + * \texttt{libra_concatenated_lagrange_form[prev_idx]} (g^{i-1}) \f$ + * #### Masking Term + * - A random polynomial of degree 2 is generated and added to the Big Sum Polynomial. + * - The masking term is applied as \f$ Z_H(X) \cdot \texttt{masking_term} \f$, where \f$ Z_H(X) \f$ is the + * vanishing polynomial. + * + */ void compute_big_sum_polynomial() { big_sum_lagrange_coeffs[0] = 0; @@ -205,38 +274,11 @@ template class Sma for (size_t idx = 0; idx < SUBGROUP_SIZE + 3; idx++) { shifted_big_sum.at(idx) = big_sum_polynomial.at(idx) * interpolation_domain[idx % SUBGROUP_SIZE]; } - // Compute the monomial coefficients of L_1, the first Lagrange polynomial - std::array lagrange_coeffs; - lagrange_coeffs[0] = FF(1); - for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { - lagrange_coeffs[idx] = FF(0); - } - Polynomial lagrange_first_monomial(SUBGROUP_SIZE); - if constexpr (!std::is_same_v) { - lagrange_first_monomial = Polynomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); - } else { - std::vector lagrange_first_ifft(SUBGROUP_SIZE); - polynomial_arithmetic::ifft(lagrange_coeffs.data(), lagrange_first_ifft.data(), bn_evaluation_domain); - lagrange_first_monomial = Polynomial(lagrange_first_ifft); - } - - // Compute the monomial coefficients of L_{|H|}, the last Lagrange polynomial - lagrange_coeffs[0] = FF(0); - lagrange_coeffs[SUBGROUP_SIZE - 1] = FF(1); - - Polynomial lagrange_last_monomial; - if constexpr (!std::is_same_v) { - lagrange_last_monomial = Polynomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); - } else { - std::vector lagrange_last_ifft(SUBGROUP_SIZE); - polynomial_arithmetic::ifft(lagrange_coeffs.data(), lagrange_last_ifft.data(), bn_evaluation_domain); - lagrange_last_monomial = Polynomial(lagrange_last_ifft); - } + const auto& [lagrange_first, lagrange_last] = + compute_lagrange_polynomials(interpolation_domain, bn_evaluation_domain); // Compute -F(X)*G(X), the negated product of challenge_polynomial and libra_concatenated_monomial_form - // Polynomial result(BATCHED_POLYNOMIAL_LENGTH); - for (size_t i = 0; i < concatenated_polynomial.size(); ++i) { for (size_t j = 0; j < challenge_polynomial.size(); ++j) { batched_polynomial.at(i + j) -= concatenated_polynomial.at(i) * challenge_polynomial.at(j); @@ -260,20 +302,59 @@ template class Sma } // Add (L_1 + L_{|H|}) * A(X) to the result - lagrange_first_monomial += lagrange_last_monomial; - for (size_t i = 0; i < big_sum_polynomial.size(); ++i) { - for (size_t j = 0; j < lagrange_first_monomial.size(); ++j) { - batched_polynomial.at(i + j) += big_sum_polynomial.at(i) * lagrange_first_monomial.at(j); + for (size_t j = 0; j < SUBGROUP_SIZE; ++j) { + batched_polynomial.at(i + j) += big_sum_polynomial.at(i) * (lagrange_first.at(j) + lagrange_last.at(j)); } } - - for (size_t idx = 0; idx < lagrange_last_monomial.size(); idx++) { - batched_polynomial.at(idx) -= lagrange_last_monomial.at(idx) * claimed_evaluation; + // Subtract L_{|H|} * s + for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { + batched_polynomial.at(idx) -= lagrange_last.at(idx) * claimed_evaluation; } } + /** + * @brief Compute monomial coefficients of the first and last Lagrange polynomials + * + * @param interpolation_domain + * @param bn_evaluation_domain + * @return std::array, 2> + */ + std::array, 2> static compute_lagrange_polynomials( + const std::array& interpolation_domain, const EvaluationDomain& bn_evaluation_domain) + { + // Compute the monomial coefficients of L_1 + std::array lagrange_coeffs; + lagrange_coeffs[0] = FF(1); + for (size_t idx = 1; idx < SUBGROUP_SIZE; idx++) { + lagrange_coeffs[idx] = FF(0); + } - // Compute the quotient of batched_polynomial by Z_H = X^{|H|} - 1 + Polynomial lagrange_first_monomial(SUBGROUP_SIZE); + if constexpr (!std::is_same_v) { + lagrange_first_monomial = Polynomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + } else { + std::vector lagrange_first_ifft(SUBGROUP_SIZE); + polynomial_arithmetic::ifft(lagrange_coeffs.data(), lagrange_first_ifft.data(), bn_evaluation_domain); + lagrange_first_monomial = Polynomial(lagrange_first_ifft); + } + + // Compute the monomial coefficients of L_{|H|}, the last Lagrange polynomial + lagrange_coeffs[0] = FF(0); + lagrange_coeffs[SUBGROUP_SIZE - 1] = FF(1); + + Polynomial lagrange_last_monomial; + if constexpr (!std::is_same_v) { + lagrange_last_monomial = Polynomial(interpolation_domain, lagrange_coeffs, SUBGROUP_SIZE); + } else { + std::vector lagrange_last_ifft(SUBGROUP_SIZE); + polynomial_arithmetic::ifft(lagrange_coeffs.data(), lagrange_last_ifft.data(), bn_evaluation_domain); + lagrange_last_monomial = Polynomial(lagrange_last_ifft); + } + + return { lagrange_first_monomial, lagrange_last_monomial }; + } + /** @brief Efficiently compute the quotient of batched_polynomial by Z_H = X ^ { | H | } - 1 + */ void compute_batched_quotient() { @@ -296,7 +377,7 @@ template class SmallSubgroupIPAVerifier { static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; - static constexpr size_t LIBRA_UNIVARIATES_LENGTH = 3; + static constexpr size_t LIBRA_UNIVARIATES_LENGTH = (std::is_same_v) ? 9 : 3; public: /*! @@ -373,22 +454,20 @@ template class SmallSubgroupIPAVerifier { */ static std::vector compute_challenge_polynomial(const std::vector& multivariate_challenge) { - ASSERT(LIBRA_UNIVARIATES_LENGTH == 3); - std::vector challenge_polynomial_lagrange(SUBGROUP_SIZE); challenge_polynomial_lagrange[0] = FF{ 1 }; - FF challenge_sqr = FF{ 1 }; // Populate the vector with the powers of the challenges - for (size_t poly_idx = 0; poly_idx < CONST_PROOF_SIZE_LOG_N; poly_idx++) { - challenge_sqr = multivariate_challenge[poly_idx] * multivariate_challenge[poly_idx]; - - challenge_polynomial_lagrange[1 + poly_idx * LIBRA_UNIVARIATES_LENGTH] = FF{ 1 }; - challenge_polynomial_lagrange[2 + poly_idx * LIBRA_UNIVARIATES_LENGTH] = multivariate_challenge[poly_idx]; - challenge_polynomial_lagrange[3 + poly_idx * LIBRA_UNIVARIATES_LENGTH] = challenge_sqr; + for (size_t idx_poly = 0; idx_poly < CONST_PROOF_SIZE_LOG_N; idx_poly++) { + size_t current_idx = 1 + LIBRA_UNIVARIATES_LENGTH * idx_poly; + challenge_polynomial_lagrange[current_idx] = FF(1); + for (size_t idx = 1; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { + // Recursively compute the powers of the challenge + challenge_polynomial_lagrange[current_idx + idx] = + challenge_polynomial_lagrange[current_idx + idx - 1] * multivariate_challenge[idx_poly]; + } } - return challenge_polynomial_lagrange; } 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 deleted file mode 100644 index 1c0244b3980..00000000000 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.test.cpp +++ /dev/null @@ -1,78 +0,0 @@ - -#include "../commitment_key.test.hpp" -#include -#include -#include -// #include "barretenberg/commitment_schemes/claim.hpp" - -#include "barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa.hpp" -#include "barretenberg/constants.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/polynomials/univariate.hpp" -#include "barretenberg/sumcheck/zk_sumcheck_data.hpp" -#include "barretenberg/transcript/transcript.hpp" - -#include -#include - -namespace bb { -template class SmallSubgroupIPATest : public CommitmentTest {}; - -auto& engine = numeric::get_debug_randomness(); - -using CurveTypes = ::testing::Types; - -TYPED_TEST_SUITE(SmallSubgroupIPATest, CurveTypes); - -TYPED_TEST(SmallSubgroupIPATest, BatchedQuotientComputation) -{ - using FF = typename TypeParam::ScalarField; - using SmallSubgroupIPA = SmallSubgroupIPAProver>; - using ZKSumcheckData = ZKSumcheckData>; - static constexpr size_t SUBGROUP_SIZE = TypeParam::SUBGROUP_SIZE; - auto prover_transcript = NativeTranscript::prover_init_empty(); - - const size_t log_circuit_size = 7; - ZKSumcheckData zk_sumcheck_data = ZKSumcheckData(log_circuit_size, prover_transcript, this->ck()); - - std::vector multivariate_challenge = this->random_evaluation_point(log_circuit_size); - - FF claimed_ipa_eval = zk_sumcheck_data.constant_term; - // info(zk_sumcheck_data.libra_univariates[2].at(3)); - for (const auto& [challenge, libra_univariate] : - zip_view(multivariate_challenge, zk_sumcheck_data.libra_univariates)) { - claimed_ipa_eval += libra_univariate.evaluate(challenge); - } - - SmallSubgroupIPA small_subgroup_ipa_prover = - SmallSubgroupIPA(zk_sumcheck_data, multivariate_challenge, claimed_ipa_eval, prover_transcript, this->ck()); - - auto batched_polynomial = small_subgroup_ipa_prover.get_batched_polynomial(); - auto challenge_polynomial = small_subgroup_ipa_prover.get_challenge_polynomial(); - - auto batched_quotient = small_subgroup_ipa_prover.get_witness_polynomials()[2]; - - // Check that batched polynomial is divisible by Z_H(X) - for (size_t idx = 0; idx < 4; idx++) { - EXPECT_EQ(batched_polynomial.evaluate(zk_sumcheck_data.interpolation_domain[idx]), FF{ 0 }); - } - - std::vector Z_H(SUBGROUP_SIZE + 1); - Z_H[0] = -FF(1); - Z_H[SUBGROUP_SIZE] = FF(1); - - std::vector product; - for (size_t i = 0; i < Z_H.size(); i++) { - for (size_t j = 0; j < batched_quotient.size(); j++) { - product[i + j] = Z_H[i] * batched_quotient[j]; - } - } - - info("product size", product.size()); - EXPECT_EQ(product.size(), batched_polynomial.size()); - - // for (auto [coeff_expected, coeff] : zip_view(product, batched_polynomial.coeffs())) { - // EXPECT_EQ(coeff, coeff_expected); - // } -} -} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index d44f1e6d5ec..4f7fc2d5abd 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -104,7 +104,7 @@ void ECCVMProver::execute_relation_check_rounds() gate_challenges[idx] = transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - zk_sumcheck_data = ZKSumcheckData(key->log_circuit_size, transcript, key->commitment_key); + zk_sumcheck_data = ZKData(key->log_circuit_size, transcript, key->commitment_key); sumcheck_output = sumcheck.prove(key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index d6daf525dc8..4217b381862 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -26,8 +26,8 @@ class ECCVMProver { using Transcript = typename Flavor::Transcript; using TranslationEvaluations = bb::TranslationEvaluations_; using CircuitBuilder = typename Flavor::CircuitBuilder; - using ZKSumcheckData = ZKSumcheckData; - using SmallSubgroupIPA = SmallSubgroupIPAProver; + using ZKData = ZKSumcheckData; + using SmallSubgroupIPA = SmallSubgroupIPAProver; explicit ECCVMProver(CircuitBuilder& builder, const std::shared_ptr& transcript = std::make_shared(), @@ -56,7 +56,7 @@ class ECCVMProver { std::shared_ptr key; CommitmentLabels commitment_labels; - ZKSumcheckData zk_sumcheck_data; + ZKData zk_sumcheck_data; Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk FF nu_challenge; // needed in both Shplonk rounds diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp index 2eb9b891854..80cac6bddcc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp @@ -41,8 +41,7 @@ template struct bn254 { using bigfr_ct = bigfield; using g1_bigfr_ct = element; - static constexpr size_t SUBGROUP_SIZE = 87; - + static constexpr size_t SUBGROUP_SIZE = 256; static const ScalarField SUBGROUP_GENERATOR; }; // namespace bn254 @@ -50,6 +49,6 @@ template struct bn254 { template const typename bn254::ScalarField bn254::SUBGROUP_GENERATOR = typename bn254::ScalarField( - uint256_t("0x0434c9aa553ba64b2b3f7f0762c119ec87353b7813c54205c5ec13d97d1f944e")); + uint256_t("0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76")); } // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 91a899c1944..a81635ad76b 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -153,10 +153,11 @@ template class SumcheckProver { // Define the length of Libra Univariates. For non-ZK Flavors: set to 0. static constexpr size_t LIBRA_UNIVARIATES_LENGTH = Flavor::HasZK ? Flavor::BATCHED_RELATION_PARTIAL_LENGTH : 0; using LibraUnivariates = std::vector>; - using ZKData = ZKSumcheckData; + using ZKData = ZKSumcheckData; std::shared_ptr transcript; SumcheckProverRound round; + ZKData zk_sumcheck_data; /** * @@ -190,9 +191,11 @@ template class SumcheckProver { const bb::RelationParameters& relation_parameters, const RelationSeparator alpha, const std::vector& gate_challenges, - ZKData zk_sumcheck_data = ZKData()) + const ZKData& zk_data = ZKData()) { - + if constexpr (Flavor::HasZK) { + extract_zk_data(zk_data); + } bb::GateSeparatorPolynomial gate_separators(gate_challenges, multivariate_d); std::vector multivariate_challenge; @@ -376,6 +379,15 @@ polynomials that are sent in clear. return multivariate_evaluations; }; + void extract_zk_data(const ZKSumcheckData& zk_data) + { + zk_sumcheck_data.libra_univariates = std::move(zk_data.libra_univariates); + zk_sumcheck_data.constant_term = std::move(zk_data.constant_term); + zk_sumcheck_data.libra_running_sum = std::move(zk_data.libra_running_sum); + zk_sumcheck_data.libra_challenge = std::move(zk_data.libra_challenge); + zk_sumcheck_data.libra_scaling_factor = std::move(zk_data.libra_scaling_factor); + } + /** * @brief Upon receiving the challenge \f$u_i\f$, the prover updates Libra data. If \f$ i < d-1\f$ diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp index 5c379314115..5eee79cb467 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp @@ -21,8 +21,7 @@ template class SumcheckTests : public ::testing::Test { using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; using RelationSeparator = Flavor::RelationSeparator; - using ZKSumcheckData = - ZKSumcheckData; + using ZKData = ZKSumcheckData; const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } @@ -121,6 +120,7 @@ template class SumcheckTests : public ::testing::Test { void test_prover() { + const size_t multivariate_d(2); const size_t multivariate_n(1 << multivariate_d); @@ -149,7 +149,7 @@ template class SumcheckTests : public ::testing::Test { SumcheckOutput output; if constexpr (Flavor::HasZK) { - ZKSumcheckData zk_sumcheck_data(multivariate_d, transcript); + ZKData zk_sumcheck_data(multivariate_d, transcript); output = sumcheck.prove(full_polynomials, {}, alpha, gate_challenges, zk_sumcheck_data); } else { output = sumcheck.prove(full_polynomials, {}, alpha, gate_challenges); @@ -255,7 +255,7 @@ template class SumcheckTests : public ::testing::Test { } SumcheckOutput output; if constexpr (Flavor::HasZK) { - ZKSumcheckData zk_sumcheck_data(multivariate_d, prover_transcript); + ZKData zk_sumcheck_data(multivariate_d, prover_transcript); output = sumcheck_prover.prove( full_polynomials, relation_parameters, prover_alpha, prover_gate_challenges, zk_sumcheck_data); } else { @@ -345,7 +345,7 @@ template class SumcheckTests : public ::testing::Test { SumcheckOutput output; if constexpr (Flavor::HasZK) { // construct libra masking polynomials and compute auxiliary data - ZKSumcheckData zk_sumcheck_data(multivariate_d, prover_transcript); + ZKData zk_sumcheck_data(multivariate_d, prover_transcript); output = sumcheck_prover.prove( full_polynomials, relation_parameters, prover_alpha, prover_gate_challenges, zk_sumcheck_data); } else { diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index e251b97a7b5..9a4041159b3 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -41,7 +41,7 @@ template class SumcheckProverRound { public: using FF = typename Flavor::FF; using ExtendedEdges = typename Flavor::ExtendedEdges; - using ZKData = ZKSumcheckData; + using ZKData = ZKSumcheckData; /** * @brief In Round \f$i = 0,\ldots, d-1\f$, equals \f$2^{d-i}\f$. */ @@ -64,6 +64,9 @@ template class SumcheckProverRound { static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH; using SumcheckRoundUnivariate = bb::Univariate; SumcheckTupleOfTuplesOfUnivariates univariate_accumulators; + + static constexpr size_t LIBRA_UNIVARIATES_LENGTH = + (std::is_same_v) ? BATCHED_RELATION_PARTIAL_LENGTH : 3; // Prover constructor SumcheckProverRound(size_t initial_round_size) : round_size(initial_round_size) @@ -142,7 +145,7 @@ template class SumcheckProverRound { const bb::RelationParameters& relation_parameters, const bb::GateSeparatorPolynomial& gate_sparators, const RelationSeparator alpha, - ZKData zk_sumcheck_data, // only populated when Flavor HasZK + const ZKData& zk_sumcheck_data, // only populated when Flavor HasZK RowDisablingPolynomial row_disabling_poly) { PROFILE_THIS_NAME("compute_univariate"); @@ -336,16 +339,20 @@ template class SumcheckProverRound { */ static SumcheckRoundUnivariate compute_libra_round_univariate(const ZKData& zk_sumcheck_data, size_t round_idx) { - bb::Univariate libra_round_univariate; + bb::Univariate libra_round_univariate; // select the i'th column of Libra book-keeping table const auto& current_column = zk_sumcheck_data.libra_univariates[round_idx]; // the evaluation of Libra round univariate at k=0...D are equal to \f$\texttt{libra_univariates}_{i}(k)\f$ // corrected by the Libra running sum - for (size_t idx = 0; idx < libra_round_univariate.size(); ++idx) { + for (size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; ++idx) { libra_round_univariate.value_at(idx) = current_column.evaluate(FF(idx)) + zk_sumcheck_data.libra_running_sum; }; - return libra_round_univariate.template extend_to(); + if constexpr (BATCHED_RELATION_PARTIAL_LENGTH == LIBRA_UNIVARIATES_LENGTH) { + return libra_round_univariate; + } else { + return libra_round_univariate.template extend_to(); + } } private: diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 8a6cd83525f..cb7591041bd 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -13,8 +13,8 @@ namespace bb { * @brief This structure is created to contain various polynomials and constants required by ZK Sumcheck. * */ -template struct ZKSumcheckData { - +template struct ZKSumcheckData { + using Curve = typename Flavor::Curve; using FF = typename Curve::ScalarField; static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; @@ -22,22 +22,23 @@ template >; + static constexpr size_t LIBRA_UNIVARIATES_LENGTH = (std::is_same_v) ? 9 : 3; + + static constexpr FF one_half = FF(1) / FF(2); + // Container for the evaluations of Libra Univariates that have to be proven. using ClaimedLibraEvaluations = std::vector; FF constant_term; - EvaluationDomain bn_evaluation_domain; + EvaluationDomain bn_evaluation_domain = EvaluationDomain(); std::array interpolation_domain; // to compute product in lagrange basis Polynomial libra_concatenated_lagrange_form; Polynomial libra_concatenated_monomial_form; - LibraUnivariates libra_univariates; - size_t log_circuit_size; + std::vector> libra_univariates{}; + size_t log_circuit_size{ 0 }; FF libra_scaling_factor{ 1 }; FF libra_challenge; FF libra_total_sum; @@ -49,8 +50,8 @@ template transcript, - std::shared_ptr commitment_key = nullptr) + std::shared_ptr transcript, + std::shared_ptr commitment_key = nullptr) : constant_term(FF::random_element()) , libra_concatenated_monomial_form(SUBGROUP_SIZE + 2) // includes masking , libra_univariates(generate_libra_univariates(multivariate_d)) // random univariates of degree 2 @@ -89,9 +90,9 @@ template > generate_libra_univariates(const size_t number_of_polynomials) { - LibraUnivariates libra_full_polynomials(number_of_polynomials); + std::vector> libra_full_polynomials(number_of_polynomials); for (auto& libra_polynomial : libra_full_polynomials) { libra_polynomial = Polynomial::random(LIBRA_UNIVARIATES_LENGTH); @@ -107,12 +108,12 @@ template >& libra_univariates, FF& scaling_factor, const FF& free_term) { FF total_sum = 0; - scaling_factor = scaling_factor / 2; + scaling_factor *= one_half; for (auto& univariate : libra_univariates) { total_sum += univariate.evaluate(FF(0)) + univariate.evaluate(FF(1)); @@ -146,14 +147,21 @@ template ) { bn_evaluation_domain = EvaluationDomain(SUBGROUP_SIZE, SUBGROUP_SIZE); - bn_evaluation_domain.compute_lookup_table(); + if (bn_evaluation_domain.size > 0) { + bn_evaluation_domain.compute_lookup_table(); + } } interpolation_domain[0] = FF{ 1 }; @@ -162,7 +170,10 @@ template coeffs_lagrange_subgroup; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index d854ffa5f5f..767e5524f26 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -162,7 +162,7 @@ void TranslatorProver::execute_relation_check_rounds() } // // create masking polynomials for sumcheck round univariates and auxiliary data - zk_sumcheck_data = ZKSumcheckData(key->log_circuit_size, transcript, key->commitment_key); + zk_sumcheck_data = ZKData(key->log_circuit_size, transcript, key->commitment_key); sumcheck_output = sumcheck.prove(key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); } @@ -179,7 +179,7 @@ void TranslatorProver::execute_pcs_rounds() using OpeningClaim = ProverOpeningClaim; - using SmallSubgroupIPA = SmallSubgroupIPAProver; + using SmallSubgroupIPA = SmallSubgroupIPAProver; SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output.challenge, diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp index 0755a8269bb..6632afba69d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp @@ -22,7 +22,7 @@ class TranslatorProver { using CommitmentLabels = typename Flavor::CommitmentLabels; using PCS = typename Flavor::PCS; using Transcript = typename Flavor::Transcript; - using ZKSumcheckData = ZKSumcheckData; + using ZKData = ZKSumcheckData; static constexpr size_t MINIMUM_MINI_CIRCUIT_SIZE = 2048; bool computed_witness = false; size_t total_num_gates = 0; // num_gates (already include zero row offset) (used to compute dyadic size) @@ -52,7 +52,7 @@ class TranslatorProver { CommitmentLabels commitment_labels; - ZKSumcheckData zk_sumcheck_data; + ZKData zk_sumcheck_data; SumcheckOutput sumcheck_output; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index f65267137f7..262069ba7a3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -33,21 +33,20 @@ template void DeciderProver_::execute_relation_ch { PROFILE_THIS_NAME("sumcheck.prove"); + const size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); + auto commitment_key = std::make_shared(1 << (log_subgroup_size + 1)); + if constexpr (Flavor::HasZK) { - const size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); - auto commitment_key = std::make_shared(1 << (log_subgroup_size + 1)); zk_sumcheck_data = ZKData(numeric::get_msb(polynomial_size), transcript, commitment_key); - sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, - proving_key->relation_parameters, - proving_key->alphas, - proving_key->gate_challenges, - zk_sumcheck_data); } else { - sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, - proving_key->relation_parameters, - proving_key->alphas, - proving_key->gate_challenges); + zk_sumcheck_data = ZKData(); } + + sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, + proving_key->relation_parameters, + proving_key->alphas, + proving_key->gate_challenges, + zk_sumcheck_data); } } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp index d40dc157c90..47baefd297b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp @@ -25,8 +25,8 @@ template class DeciderProver_ { using DeciderPK = DeciderProvingKey_; using Transcript = typename Flavor::Transcript; using RelationSeparator = typename Flavor::RelationSeparator; - using ZKData = ZKSumcheckData; - using SmallSubgroupIPA = SmallSubgroupIPAProver; + using ZKData = ZKSumcheckData; + using SmallSubgroupIPA = SmallSubgroupIPAProver; public: explicit DeciderProver_(const std::shared_ptr&, From 2208253cfc4eb2a23f8f2d2e6af1d44979e2f5e3 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 20 Dec 2024 09:09:05 +0000 Subject: [PATCH 24/30] minor clean-up --- .../commitment_schemes/shplonk/shplemini.hpp | 4 ++-- .../small_subgroup_ipa/small_subgroup_ipa.hpp | 13 ++++++++----- .../src/barretenberg/ecc/curves/bn254/bn254.hpp | 7 ++++++- .../barretenberg/ecc/curves/grumpkin/grumpkin.hpp | 10 +++++++--- .../stdlib/primitives/curves/bn254.hpp | 13 +++++++------ .../stdlib/primitives/curves/grumpkin.hpp | 15 +++++++++------ .../barretenberg/sumcheck/zk_sumcheck_data.hpp | 2 +- 7 files changed, 40 insertions(+), 24 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 7f7a087917b..a0254a7d3a1 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -51,7 +51,7 @@ template class ShpleminiProver_ { OpeningClaim new_claim; if (has_zk) { - static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; + static constexpr FF subgroup_generator = Curve::subgroup_generator; const auto gemini_r = opening_claims[0].opening_pair.challenge; std::array libra_eval_labels = { @@ -626,7 +626,7 @@ template class ShpleminiVerifier_ { const Fr& shplonk_evaluation_challenge) { - const Fr subgroup_generator = Curve::SUBGROUP_GENERATOR; + const Fr subgroup_generator = Curve::subgroup_generator; // compute current power of Shplonk batching challenge taking into account the const proof size Fr shplonk_challenge_power = Fr{ 1 }; 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 f4f2929e2d2..e4f59fe3a08 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 @@ -71,7 +71,7 @@ template class SmallSubgroupIPAProver { // required length from 23 to 3. static constexpr size_t LIBRA_UNIVARIATES_LENGTH = (std::is_same_v) ? 9 : 3; // Fixed generator of H - static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; + static constexpr FF subgroup_generator = Curve::subgroup_generator; // Interpolation domain {1, g, \ldots, g^{SUBGROUP_SIZE - 1}} used by ECCVM std::array interpolation_domain; @@ -411,7 +411,7 @@ template class SmallSubgroupIPAVerifier { const FF& inner_product_eval_claim) { - static const FF subgroup_generator_inverse = FF(1) / Curve::SUBGROUP_GENERATOR; + const FF subgroup_generator_inverse = Curve::subgroup_generator_inverse; // 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); @@ -498,12 +498,14 @@ template class SmallSubgroupIPAVerifier { denominators[0] = r - one; FF work_root = inverse_root_of_unity; // g^{-1} // - // Compute the evaluations of the Lagrange polynomials for H + // Compute the denominators of the Lagrange polynomials evaluated at r for (size_t i = 1; i < SUBGROUP_SIZE; ++i) { denominators[i] = work_root * r; denominators[i] -= one; // r * g^{-i} - 1 work_root *= inverse_root_of_unity; } + + // Invert/Batch invert denominators if constexpr (Curve::is_stdlib_type) { for (FF& denominator : denominators) { denominator = one / denominator; @@ -512,10 +514,11 @@ template class SmallSubgroupIPAVerifier { FF::batch_invert(&denominators[0], SUBGROUP_SIZE); } std::array result; + + // Accumulate the evaluation of the polynomials given by `coeffs` vector result[0] = FF{ 0 }; for (size_t i = 0; i < SUBGROUP_SIZE; ++i) { - FF temp = coeffs[i] * denominators[i]; // coeffs_i * 1/(r * g^{-i} - 1) - result[0] = result[0] + temp; + result[0] += coeffs[i] * denominators[i]; // + coeffs_i * 1/(r * g^{-i} - 1) } result[0] = result[0] * numerator; // The evaluation of the polynomials given by its evaluations over H diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp index a826b7594fd..d2fac553936 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp @@ -24,8 +24,13 @@ class BN254 { // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = false; + // Required by SmallSubgroupIPA argument static constexpr size_t SUBGROUP_SIZE = 256; - static constexpr ScalarField SUBGROUP_GENERATOR = + // BN254's scalar field has a multiplicative subgroup of order 2^28. It is generated by 5. The generator below is + // 5^{2^{20}}. To avoid inversion in the recursive verifier, we also store ir + static constexpr ScalarField subgroup_generator = ScalarField(uint256_t("0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76")); + static constexpr ScalarField subgroup_generator_inverse = + ScalarField(uint256_t("0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6")); }; } // namespace bb::curve \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp index b2ad8e11e86..48dd7f335ac 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp @@ -55,10 +55,14 @@ class Grumpkin { // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = false; + // Required by SmallSubgroupIPA argument static constexpr size_t SUBGROUP_SIZE = 87; - - static constexpr ScalarField SUBGROUP_GENERATOR = + // To find the generator below, we factored r - 1 into primes, where r is the modulus of the Grumkin scalar field, + // sampled a random field element, raised it to (r-1)/(3*29), and ensured that the resulting element is not + // generating a smaller subgroup. To avoid inversion in the recursive verifier, we also store its inverse. + static constexpr ScalarField subgroup_generator = ScalarField(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); - ; + static constexpr ScalarField subgroup_generator_inverse = + ScalarField("0x0c68e27477b5e78cfab790bd3b59806fa871771f71ec7452cde5384f6e3a1988"); }; } // namespace bb::curve \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp index 80cac6bddcc..5feb3b6e872 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp @@ -41,14 +41,15 @@ template struct bn254 { using bigfr_ct = bigfield; using g1_bigfr_ct = element; + // Required by SmallSubgroupIPA argument static constexpr size_t SUBGROUP_SIZE = 256; - static const ScalarField SUBGROUP_GENERATOR; + // BN254's scalar field has a multiplicative subgroup of order 2^28. It is generated by 5. The generator below is + // 5^{2^{20}}. To avoid inversion in the recursive verifier, we also store ir + static constexpr bb::fr subgroup_generator = + bb::fr(uint256_t("0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76")); + static constexpr bb::fr subgroup_generator_inverse = + bb::fr(uint256_t("0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6")); }; // namespace bn254 -template -const typename bn254::ScalarField bn254::SUBGROUP_GENERATOR = - typename bn254::ScalarField( - uint256_t("0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76")); - } // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp index 6ed98142267..c8630ac735e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp @@ -32,13 +32,16 @@ template struct grumpkin { using byte_array_ct = byte_array; using bool_ct = bool_t; using uint32_ct = stdlib::uint32; + + // Required by SmallSubgroupIPA argument static constexpr size_t SUBGROUP_SIZE = 87; - static const ScalarField SUBGROUP_GENERATOR; + // To find the generator below, we factored r - 1 into primes, where r is the modulus of the Grumkin scalar field, + // sampled a random field element, raised it to (r-1)/(3*29), and ensured that the resulting element is + // not generating a smaller subgroup. To avoid inversion in the recursive verifier, we also store its inverse. + static constexpr bb::fq subgroup_generator = + bb::fq("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b"); + static constexpr bb::fq subgroup_generator_inverse = + bb::fq("0x0c68e27477b5e78cfab790bd3b59806fa871771f71ec7452cde5384f6e3a1988"); }; -template -const typename grumpkin::ScalarField grumpkin::SUBGROUP_GENERATOR = - typename grumpkin::ScalarField( - uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); - } // namespace bb::stdlib \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index cb7591041bd..92f22a4646b 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -19,7 +19,7 @@ template struct ZKSumcheckData { static constexpr size_t SUBGROUP_SIZE = Curve::SUBGROUP_SIZE; - static constexpr FF subgroup_generator = Curve::SUBGROUP_GENERATOR; + static constexpr FF subgroup_generator = Curve::subgroup_generator; // The size of the LibraUnivariates. We ensure that they do not take extra space when Flavor runs non-ZK Sumcheck. static constexpr size_t LIBRA_UNIVARIATES_LENGTH = (std::is_same_v) ? 9 : 3; From 398f7de84b900be1e6af262fabcb7f3b50e710ea Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 20 Dec 2024 09:20:39 +0000 Subject: [PATCH 25/30] small fix --- .../src/barretenberg/commitment_schemes/shplonk/shplemini.hpp | 3 +-- barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp | 3 +-- .../cpp/src/barretenberg/translator_vm/translator_prover.cpp | 1 - .../cpp/src/barretenberg/ultra_honk/decider_prover.cpp | 3 +-- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index a0254a7d3a1..0de285b7e9c 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -31,12 +31,11 @@ template class ShpleminiProver_ { const std::shared_ptr>& commitment_key, const std::shared_ptr& transcript, const std::array& libra_polynomials = {}, - const FF& libra_evaluation = {}, RefSpan concatenated_polynomials = {}, const std::vector>& groups_to_be_concatenated = {}) { // While Shplemini is not templated on Flavor, we derive ZK flag this way - const bool has_zk = !(libra_evaluation == FF{ 0 }); + const bool has_zk = (libra_polynomials[0].size() > 0); std::vector opening_claims = GeminiProver::prove(circuit_size, f_polynomials, g_polynomials, diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 4f7fc2d5abd..35f2e319175 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -136,8 +136,7 @@ void ECCVMProver::execute_pcs_rounds() sumcheck_output.challenge, key->commitment_key, transcript, - small_subgroup_ipa_prover.get_witness_polynomials(), - sumcheck_output.claimed_libra_evaluation); + small_subgroup_ipa_prover.get_witness_polynomials()); // Get the challenge at which we evaluate all transcript polynomials as univariates evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 6dc4e231171..47f816c7d21 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -197,7 +197,6 @@ void TranslatorProver::execute_pcs_rounds() key->commitment_key, transcript, small_subgroup_ipa_prover.get_witness_polynomials(), - sumcheck_output.claimed_libra_evaluation, key->polynomials.get_concatenated(), key->polynomials.get_groups_to_be_concatenated()); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 262069ba7a3..4528c270fa8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -82,8 +82,7 @@ template void DeciderProver_::execute_pcs_rounds( sumcheck_output.challenge, ck, transcript, - small_subgroup_ipa_prover.get_witness_polynomials(), - sumcheck_output.claimed_libra_evaluation); + small_subgroup_ipa_prover.get_witness_polynomials()); } vinfo("executed multivariate-to-univariate reduction"); PCS::compute_opening_proof(ck, prover_opening_claim, transcript); From 6ab449b2f225bd4abe193ccd0d4bee51e357003d Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 2 Jan 2025 17:16:11 +0000 Subject: [PATCH 26/30] resolved comments --- .../barretenberg/commitment_schemes/claim.hpp | 1 - .../commitment_schemes/kzg/kzg.test.cpp | 2 + .../commitment_schemes/shplonk/shplemini.hpp | 50 +++++------ .../small_subgroup_ipa/small_subgroup_ipa.hpp | 90 +++++++++++-------- .../cpp/src/barretenberg/constants.hpp | 3 + .../barretenberg/ecc/curves/bn254/bn254.hpp | 7 +- .../ecc/curves/grumpkin/grumpkin.hpp | 11 ++- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 6 +- .../eccvm_recursive_verifier.cpp | 4 +- .../ultra_recursive_verifier.cpp | 4 +- .../translator_recursive_verifier.cpp | 5 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 8 +- .../barretenberg/sumcheck/sumcheck_output.hpp | 2 +- .../sumcheck/zk_sumcheck_data.hpp | 4 +- .../translator_vm/translator_verifier.cpp | 7 +- .../ultra_honk/decider_prover.cpp | 2 - .../ultra_honk/decider_verifier.cpp | 8 +- 17 files changed, 121 insertions(+), 93 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp index 398645a0d16..1afb02a3c66 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp @@ -110,6 +110,5 @@ template struct BatchOpeningClaim { std::vector commitments; std::vector scalars; typename Curve::ScalarField evaluation_point; - bool consistency_checked = true; // Required for ZK Flavors }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index c21b34d313e..dcf3b4fe315 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -309,6 +309,7 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShiftAndConcatenation) // Gemini verifier output: // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 + bool consistency_checked = true; const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(n, RefVector(unshifted_commitments), @@ -320,6 +321,7 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShiftAndConcatenation) verifier_transcript, /* repeated commitments= */ {}, /* has zk = */ {}, + &consistency_checked, /* libra commitments = */ {}, /* libra evaluations = */ {}, to_vector_of_ref_vectors(concatenation_groups_commitments), diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 0de285b7e9c..92993a23f3b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -30,7 +30,7 @@ template class ShpleminiProver_ { std::span multilinear_challenge, const std::shared_ptr>& commitment_key, const std::shared_ptr& transcript, - const std::array& libra_polynomials = {}, + const std::array& libra_polynomials = {}, RefSpan concatenated_polynomials = {}, const std::vector>& groups_to_be_concatenated = {}) { @@ -53,7 +53,7 @@ template class ShpleminiProver_ { static constexpr FF subgroup_generator = Curve::subgroup_generator; const auto gemini_r = opening_claims[0].opening_pair.challenge; - std::array libra_eval_labels = { + std::array libra_eval_labels = { "Libra:concatenation_eval", "Libra:shifted_big_sum_eval", "Libra:big_sum_eval", "Libra:quotient_eval" }; const std::array evaluation_points = { gemini_r, gemini_r * subgroup_generator, gemini_r, gemini_r }; @@ -146,7 +146,8 @@ template class ShpleminiVerifier_ { const std::shared_ptr& transcript, const RepeatedCommitmentsData& repeated_commitments = {}, const bool has_zk = false, - const std::array& libra_commitments = {}, + bool* consistency_checked = nullptr, + const std::array& libra_commitments = {}, const Fr& libra_univariate_evaluation = Fr{ 0 }, const std::vector>& concatenation_group_commitments = {}, RefSpan concatenated_evaluations = {}) @@ -186,7 +187,7 @@ template class ShpleminiVerifier_ { const std::vector gemini_eval_challenge_powers = gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, CONST_PROOF_SIZE_LOG_N); - std::vector libra_evaluations(4); + std::array libra_evaluations; if (has_zk) { libra_evaluations[0] = transcript->template receive_from_prover("Libra:concatenation_eval"); libra_evaluations[1] = transcript->template receive_from_prover("Libra:shifted_big_sum_eval"); @@ -312,7 +313,6 @@ template class ShpleminiVerifier_ { // For ZK flavors, the sumcheck output contains the evaluations of Libra univariates that submitted to the // ShpleminiVerifier, otherwise this argument is set to be empty - bool consistency_checked = true; if (has_zk) { add_zk_data(commitments, scalars, @@ -322,11 +322,11 @@ template class ShpleminiVerifier_ { shplonk_batching_challenge, shplonk_evaluation_challenge); - consistency_checked = SmallSubgroupIPAVerifier::evaluations_consistency_check( + *consistency_checked = SmallSubgroupIPAVerifier::check_evaluations_consistency( libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation); } - return { commitments, scalars, shplonk_evaluation_challenge, consistency_checked }; + return { commitments, scalars, shplonk_evaluation_challenge }; }; /** * @brief Populates the vectors of commitments and scalars, and computes the evaluation of the batched @@ -618,15 +618,13 @@ template class ShpleminiVerifier_ { */ static void add_zk_data(std::vector& commitments, std::vector& scalars, - const std::array& libra_commitments, - const std::vector& libra_evaluations, + const std::array& libra_commitments, + const std::array& libra_evaluations, const Fr& gemini_evaluation_challenge, const Fr& shplonk_batching_challenge, const Fr& shplonk_evaluation_challenge) { - const Fr subgroup_generator = Curve::subgroup_generator; - // compute current power of Shplonk batching challenge taking into account the const proof size Fr shplonk_challenge_power = Fr{ 1 }; for (size_t j = 0; j < CONST_PROOF_SIZE_LOG_N + 2; ++j) { @@ -642,28 +640,28 @@ template class ShpleminiVerifier_ { commitments.push_back(libra_commitments[idx]); } - std::vector denominators; - std::vector tmp_scalars; + std::array denominators; + std::array batching_scalars; // compute Shplonk denominators and invert them - denominators.push_back(Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge)); - denominators.push_back(Fr(1) / - (shplonk_evaluation_challenge - subgroup_generator * gemini_evaluation_challenge)); - denominators.push_back(denominators[0]); - denominators.push_back(denominators[0]); + denominators[0] = Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge); + denominators[1] = + Fr(1) / (shplonk_evaluation_challenge - Fr(Curve::subgroup_generator) * gemini_evaluation_challenge); + denominators[2] = denominators[0]; + denominators[3] = denominators[0]; // compute the scalars to be multiplied against the commitments [libra_concatenated], [big_sum], [big_sum], and // [libra_quotient] - for (const auto& [denominator, evaluation] : zip_view(denominators, libra_evaluations)) { - Fr scaling_factor = denominator * shplonk_challenge_power; - tmp_scalars.push_back(-scaling_factor); + for (size_t idx = 0; idx < libra_evaluations.size(); idx++) { + Fr scaling_factor = denominators[idx] * shplonk_challenge_power; + batching_scalars[idx] = -scaling_factor; shplonk_challenge_power *= shplonk_batching_challenge; - constant_term += scaling_factor * evaluation; + constant_term += scaling_factor * libra_evaluations[idx]; } - // to save a scalar mul, add the sum of the scalars corresponding to the big sum evaluations - scalars.push_back(tmp_scalars[0]); - scalars.push_back(tmp_scalars[1] + tmp_scalars[2]); - scalars.push_back(tmp_scalars[3]); + // to save a scalar mul, add the sum of the batching scalars corresponding to the big sum evaluations + scalars.push_back(batching_scalars[0]); + scalars.push_back(batching_scalars[1] + batching_scalars[2]); + scalars.push_back(batching_scalars[3]); } }; } // 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 e4f59fe3a08..d4166730f7c 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 @@ -19,6 +19,15 @@ namespace bb { * commitments and openings of Libra polynomials zero-knowledge. * * ### Overview + * + * Let \f$ G \f$ be the masked concatenated Libra polynomial. Without masking, it is defined by concatenating Libra + * constant term and the monomial coefficients of the Libra univariates \f$ g_i \f$ in the Lagrange basis over \f$ H + * \f$. More explicitly, unmasked concatenated Libra polynomial is given by the following vector of coefficients: + * \f[ \big( \text{libra_constant_term}, g_{0,0}, \ldots, g_{0, + * \text{LIBRA_UNIVARIATES_LENGTH} - 1}, \ldots, g_{d-1, 0}, g_{d-1, \text{LIBRA_UNIVARIATES_LENGTH} - 1} \big) \f], + * where \f$ d = \text{log_circuit_size}\f$. + * It is masked by adding \f$ (r_0 + r_1 X) Z_{H}(X)\f$, where \f$ Z_H(X) \f$ is the vanishing polynomial for \f$ H \f$. + * * This class enables the prover to: * * - Open the commitment to concatenated Libra polynomial with zero-knowledge while proving correctness of the claimed @@ -27,29 +36,36 @@ namespace bb { * ### Inputs * The prover receives: * - **ZKSumcheckData:** Contains: - * - Concatenated coefficients of the masking term and \( d \) random Libra univariates of degree 3. - * - Monomial coefficients of the masked concatenated Libra polynomial denoted by \( G \) . - * - Interpolation domain for a small subgroup \( H \subset \mathbb{F}^\ast \). + * - Monomial coefficients of the masked concatenated Libra polynomial \f$ G \f$. + * - Interpolation domain for a small subgroup \( H \subset \mathbb{F}^\ast \), where \(\mathbb{F} \) is the + * ScalarField of a given curve. * - **Sumcheck challenges:** \( u_0, \ldots, u_{D-1} \), where \( D = \text{CONST_PROOF_SIZE_LOG_N} \). * - **Claimed inner product:** \( s = \text{claimed\_ipa\_eval} \), defined as: * \f[ * s = \sum_{i=1}^{|H|} F(g^i) G(g^i), * \f] - * where \( F(X) \) is the challenge polynomial and \( G(X) \) is the concatenated Libra polynomial. + * where \( F(X) \) is the ``challenge`` polynomial constructed from the Sumcheck round challenges (see the formula + * below) and \( G(X) \) is the concatenated Libra polynomial. * * ### Prover's Construction - * 1. Define a polynomial \( A(X) \), called the **big sum polynomial**, satisfying: + * 1. Define a polynomial \( A(X) \), called the **big sum polynomial**, which is analogous to the big product + * polynomial used to prove claims about \f$ \prod_{h\in H} f(h) \cdot g(h) \f$. It is uniquely defined by the + * following: * - \( A(1) = 0 \), * - \( A(g^i) = A(g^{i-1}) + F(g^{i-1}) G(g^{i-1}) \) for \( i = 1, \ldots, |H|-1 \). * 2. Mask \( A(X) \) by adding \( Z_H(X) R(X) \), where \( R(X) \) is a random polynomial of degree 3. * 3. Commit to \( A(X) \) and send the commitment to the verifier. * * ### Key Identity - * If \( A(X) \) is honestly constructed, the following identity holds: - * \f[ - * L_1(X) A(X) + (X - g^{-1}) (A(g \cdot X) - A(X) - F(X) G(X)) + L_{|H|}(X) (A(X) - s) = Z_H(X) Q(X), - * \f] - * where \( Q(X) \) is the quotient of the left-hand side by \( Z_H(X) \). + * \( A(X) \) is honestly constructed, i.e. + * - \f$ A_0 = 0\f$, + * - \f$ A_{i} = A_{i-1} + F_{i-1} * G_{i-1}\f$ (Lagrange coefficients over \f$ H \f$) for \f$ i = 1,\ldots, |H|\f$ + * - \f$ A_{|H|} \f$ is equal to the claimed inner product \f$s\f$. + * if and only if the following identity holds: + * \f[ L_1(X) A(X) + (X - g^{-1}) (A(g \cdot X) - A(X) - + * F(X) G(X)) + L_{|H|}(X) (A(X) - s) = Z_H(X) Q(X), \f] where \( Q(X) \) is the quotient of the left-hand side by \( + * Z_H(X) \). The second summand is the translation of the second condition using the fact that the coefficients of \f$ + * A(gX) \f$ are given by a cyclic shift of the coefficients of \f$ A(X) \f$. * * The methods of this class allow the prover to compute \( A(X) \) and \( Q(X) \). * @@ -107,7 +123,7 @@ template class SmallSubgroupIPAProver { const std::vector& multivariate_challenge, const FF claimed_ipa_eval, std::shared_ptr transcript, - std::shared_ptr commitment_key = nullptr) + std::shared_ptr commitment_key) : interpolation_domain(zk_sumcheck_data.interpolation_domain) , concatenated_polynomial(zk_sumcheck_data.libra_concatenated_monomial_form) , libra_concatenated_lagrange_form(zk_sumcheck_data.libra_concatenated_lagrange_form) @@ -127,14 +143,11 @@ template class SmallSubgroupIPAProver { // Construct the challenge polynomial in Lagrange basis, compute its monomial coefficients compute_challenge_polynomial(multivariate_challenge); - // Construct unmasked big sum polynomial in Lagrange basis, compute its monomial coefficients, and mask it + // Construct unmasked big sum polynomial in Lagrange basis, compute its monomial coefficients and mask it compute_big_sum_polynomial(); // Send masked commitment [A + Z_H * R] to the verifier, where R is of degree 2 - if (commitment_key) { - transcript->template send_to_verifier("Libra:big_sum_commitment", - commitment_key->commit(big_sum_polynomial)); - } + transcript->template send_to_verifier("Libra:big_sum_commitment", commitment_key->commit(big_sum_polynomial)); // Compute C(X) compute_batched_polynomial(claimed_ipa_eval); @@ -150,7 +163,7 @@ template class SmallSubgroupIPAProver { } // Getter to pass the witnesses to ShpleminiProver. Big sum polynomial is evaluated at 2 points (and is small) - std::array, 4> get_witness_polynomials() const + std::array, NUM_LIBRA_EVALUATIONS> get_witness_polynomials() const { return { concatenated_polynomial, big_sum_polynomial, big_sum_polynomial, batched_quotient }; } @@ -171,17 +184,15 @@ template class SmallSubgroupIPAProver { * - For each challenge index `idx_poly` in the `CONST_PROOF_SIZE_LOG_N` range, compute a sequence of coefficients * recursively as powers of the corresponding multivariate challenge. * - Store these coefficients in `coeffs_lagrange_basis`. + * More explicitly, + * \f$ F = (1 , 1 , u_0, \ldots, u_0^{LIBRA_UNIVARIATES_LENGTH-1}, \ldots, 1, u_{D-1}, \ldots, + * u_{D-1}^{LIBRA_UNVIARIATES_LENGTH-1} ) \f$ in the Lagrange basis over \f$ H \f$. * * ### Monomial Basis * If the curve is not `BN254`, the monomial polynomial is constructed directly using un-optimized Lagrange * interpolation. Otherwise, an IFFT is used to convert the Lagrange basis coefficients into monomial basis * coefficients. * - * ### Notes: - * - The `LIBRA_UNIVARIATES_LENGTH` determines the number of recursive powers computed per challenge. - * - For `BN254`, the polynomial is computed using an IFFT operation to convert from the Lagrange basis to the - * monomial basis. - * * @param multivariate_challenge A vector of field elements used to compute the challenge polynomial. */ void compute_challenge_polynomial(const std::vector& multivariate_challenge) @@ -191,12 +202,12 @@ template class SmallSubgroupIPAProver { for (size_t challenge_idx = 0; challenge_idx < CONST_PROOF_SIZE_LOG_N; challenge_idx++) { // We concatenate 1 with CONST_PROOF_SIZE_LOG_N Libra Univariates of length LIBRA_UNIVARIATES_LENGTH - size_t poly_to_concatenate_start = 1 + LIBRA_UNIVARIATES_LENGTH * challenge_idx; + 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; idx < LIBRA_UNIVARIATES_LENGTH; idx++) { + 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[poly_to_concatenate_start + idx] = - coeffs_lagrange_basis[poly_to_concatenate_start + idx - 1] * multivariate_challenge[challenge_idx]; + coeffs_lagrange_basis[idx] = coeffs_lagrange_basis[idx - 1] * multivariate_challenge[challenge_idx]; } } @@ -252,9 +263,7 @@ template class SmallSubgroupIPAProver { } // Generate random masking_term of degree 2, add Z_H(X) * masking_term bb::Univariate masking_term = bb::Univariate::get_random(); - for (size_t idx = 0; idx < SUBGROUP_SIZE; idx++) { - big_sum_polynomial.at(idx) = big_sum_polynomial_unmasked.at(idx); - } + big_sum_polynomial += big_sum_polynomial_unmasked; for (size_t idx = 0; idx < masking_term.size(); idx++) { big_sum_polynomial.at(idx) -= masking_term.value_at(idx); @@ -263,7 +272,8 @@ template class SmallSubgroupIPAProver { }; /** - * @brief Compute \f$ L_1(X) * A(X) + (X - 1/g) (A(gX) - A(X) - F(X) G(X)) + L_{|H|}(X)(A(X) - s) \f$ + * @brief Compute \f$ L_1(X) * A(X) + (X - 1/g) (A(gX) - A(X) - F(X) G(X)) + L_{|H|}(X)(A(X) - s) \f$, where \f$ g + * \f$ is the fixed generator of \f$ H \f$. * */ void compute_batched_polynomial(const FF& claimed_evaluation) @@ -405,7 +415,7 @@ template class SmallSubgroupIPAVerifier { * @param eval_claim The claimed inner proudct of the coefficients of \f$G\f$ and \f$F\f$. * @return True if the consistency check passes, false otherwise. */ - static bool evaluations_consistency_check(const std::vector& libra_evaluations, + static bool check_evaluations_consistency(const std::array& libra_evaluations, const FF& gemini_evaluation_challenge, const std::vector& multilinear_challenge, const FF& inner_product_eval_claim) @@ -421,8 +431,11 @@ template class SmallSubgroupIPAVerifier { // Compute the evaluations of the challenge polynomial, Lagrange first, and Lagrange last for the fixed small // subgroup - auto [challenge_poly, lagrange_first, lagrange_last] = compute_batched_barycentric_evaluations( - challenge_polynomial_lagrange, gemini_evaluation_challenge, subgroup_generator_inverse); + auto [challenge_poly, lagrange_first, lagrange_last] = + compute_batched_barycentric_evaluations(challenge_polynomial_lagrange, + gemini_evaluation_challenge, + subgroup_generator_inverse, + vanishing_poly_eval); const FF& concatenated_at_r = libra_evaluations[0]; const FF& big_sum_shifted_eval = libra_evaluations[1]; @@ -437,6 +450,7 @@ template class SmallSubgroupIPAVerifier { diff += lagrange_last * (big_sum_eval - inner_product_eval_claim) - vanishing_poly_eval * quotient_eval; if constexpr (Curve::is_stdlib_type) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1186). Insecure pattern. return (diff.get_value() == FF(0).get_value()); } else { return (diff == FF(0)); @@ -486,13 +500,13 @@ template class SmallSubgroupIPAVerifier { */ static std::array compute_batched_barycentric_evaluations(const std::vector& coeffs, const FF& r, - const FF& inverse_root_of_unity) + const FF& inverse_root_of_unity, + const FF& vanishing_poly_eval) { std::array denominators; FF one = FF{ 1 }; - FF numerator = r; + FF numerator = vanishing_poly_eval; - numerator = numerator.pow(SUBGROUP_SIZE) - one; numerator *= one / FF(SUBGROUP_SIZE); // (r^n - 1) / n denominators[0] = r - one; @@ -517,8 +531,8 @@ template class SmallSubgroupIPAVerifier { // Accumulate the evaluation of the polynomials given by `coeffs` vector result[0] = FF{ 0 }; - for (size_t i = 0; i < SUBGROUP_SIZE; ++i) { - result[0] += coeffs[i] * denominators[i]; // + coeffs_i * 1/(r * g^{-i} - 1) + for (const auto& [coeff, denominator] : zip_view(coeffs, denominators)) { + result[0] += coeff * denominator; // + coeffs_i * 1/(r * g^{-i} - 1) } result[0] = result[0] * numerator; // The evaluation of the polynomials given by its evaluations over H diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 218761ae550..a1cfae900ad 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -20,4 +20,7 @@ static constexpr uint32_t MAX_DATABUS_SIZE = 10000; // The number of entries in ProverPolynomials reserved for randomness intended to mask witness commitments, witness // evaluation at the sumcheck challenge, and, if necessary, the evaluation of the corresponding shift static constexpr uint32_t MASKING_OFFSET = 4; +// For ZK Flavors: the number of the commitments required by Libra and SmallSubgroupIPA. +static constexpr uint32_t NUM_LIBRA_COMMITMENTS = 3; +static constexpr uint32_t NUM_LIBRA_EVALUATIONS = 4; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp index d2fac553936..b8ea6f839c8 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp @@ -24,10 +24,13 @@ class BN254 { // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = false; - // Required by SmallSubgroupIPA argument + // Required by SmallSubgroupIPA argument. This constant needs to divide the size of the multiplicative subgroup of + // the ScalarField and satisfy SUBGROUP_SIZE > CONST_PROOF_SIZE_LOG_N * Flavor::BATCHED_RELATION_PARTIAL_LENGTH, for + // each BN254-Flavor, since in every round of Sumcheck, the prover sends Flavor::BATCHED_RELATION_PARTIAL_LENGTH + // elements to the verifier. static constexpr size_t SUBGROUP_SIZE = 256; // BN254's scalar field has a multiplicative subgroup of order 2^28. It is generated by 5. The generator below is - // 5^{2^{20}}. To avoid inversion in the recursive verifier, we also store ir + // 5^{2^{20}}. To avoid inversion in the recursive verifier, we also store the inverse of the chosen generator. static constexpr ScalarField subgroup_generator = ScalarField(uint256_t("0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76")); static constexpr ScalarField subgroup_generator_inverse = diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp index 48dd7f335ac..f195fbd7e53 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp @@ -55,11 +55,14 @@ class Grumpkin { // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = false; - // Required by SmallSubgroupIPA argument + // Required by SmallSubgroupIPA argument. This constant needs to divide the size of the multiplicative subgroup of + // the ScalarField and satisfy SUBGROUP_SIZE > CONST_PROOF_SIZE_LOG_N * 3, since in every round of Sumcheck, the + // prover sends 3 elements to the verifier. static constexpr size_t SUBGROUP_SIZE = 87; - // To find the generator below, we factored r - 1 into primes, where r is the modulus of the Grumkin scalar field, - // sampled a random field element, raised it to (r-1)/(3*29), and ensured that the resulting element is not - // generating a smaller subgroup. To avoid inversion in the recursive verifier, we also store its inverse. + // The generator below was derived by factoring r - 1 into primes, where r is the modulus of the Grumkin scalar + // field. A random field element was sampled and raised to the power (r - 1) / (3 * 29). We verified that the + // resulting element does not generate a smaller subgroup by further raising it to the powers of 3 and 29. To + // optimize the recursive verifier and avoid costly inversions, we also precompute and store its inverse. static constexpr ScalarField subgroup_generator = ScalarField(uint256_t("0x147c647c09fb639514909e9f0513f31ec1a523bf8a0880bc7c24fbc962a9586b")); static constexpr ScalarField subgroup_generator_inverse = diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index a25625f020c..b2a260a8be7 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -55,7 +55,7 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) } // Receive commitments to Libra masking polynomials - std::array libra_commitments = {}; + std::array libra_commitments = {}; libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); @@ -72,6 +72,7 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) } // Compute the Shplemini accumulator consisting of the Shplonk evaluation and the commitments and scalars vector // produced by the unified protocol + bool consistency_checked = true; BatchOpeningClaim sumcheck_batch_opening_claims = Shplemini::compute_batch_opening_claim(circuit_size, commitments.get_unshifted(), @@ -83,6 +84,7 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) transcript, Flavor::REPEATED_COMMITMENTS, Flavor::HasZK, + &consistency_checked, libra_commitments, libra_evaluation); @@ -134,6 +136,6 @@ bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) PCS::reduce_verify(key->pcs_verification_key, batch_opening_claim, ipa_transcript); vinfo("eccvm sumcheck verified?: ", sumcheck_verified.value()); vinfo("batch opening verified?: ", batched_opening_verified); - return sumcheck_verified.value() && batched_opening_verified && sumcheck_batch_opening_claims.consistency_checked; + return sumcheck_verified.value() && batched_opening_verified && consistency_checked; } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp index 982bca5a706..248fa30346e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp @@ -76,7 +76,7 @@ ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) } // Receive commitments to Libra masking polynomials - std::array libra_commitments = {}; + std::array libra_commitments = {}; libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); @@ -88,6 +88,7 @@ ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) // Compute the Shplemini accumulator consisting of the Shplonk evaluation and the commitments and scalars vector // produced by the unified protocol + bool consistency_checked = true; BatchOpeningClaim sumcheck_batch_opening_claims = Shplemini::compute_batch_opening_claim(circuit_size, commitments.get_unshifted(), @@ -99,6 +100,7 @@ ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) transcript, Flavor::REPEATED_COMMITMENTS, Flavor::HasZK, + &consistency_checked, libra_commitments, claimed_libra_evaluation); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 27e217cf22b..5f0a673d531 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -90,7 +90,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ auto sumcheck = Sumcheck(log_circuit_size, transcript); // Receive commitments to Libra masking polynomials - std::array libra_commitments = {}; + std::array libra_commitments = {}; FF libra_evaluation{ 0 }; if constexpr (Flavor::HasZK) { libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); @@ -105,6 +105,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); } // Execute Shplemini to produce a batch opening claim subsequently verified by a univariate PCS + bool consistency_checked = true; const BatchOpeningClaim opening_claim = Shplemini::compute_batch_opening_claim(key->circuit_size, commitments.get_unshifted(), @@ -116,6 +117,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ transcript, Flavor::REPEATED_COMMITMENTS, Flavor::HasZK, + &consistency_checked, libra_commitments, libra_evaluation); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index 1fe3e773bd3..c0cbacf2e92 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -111,7 +111,7 @@ std::array TranslatorRecursiveVerifier_template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - std::array libra_commitments = {}; + std::array libra_commitments = {}; libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); auto [multivariate_challenge, claimed_evaluations, libra_evaluation, sumcheck_verified] = @@ -121,7 +121,7 @@ std::array TranslatorRecursiveVerifier_template receive_from_prover("Libra:quotient_commitment"); // Execute Shplemini - + bool consistency_checked = true; const BatchOpeningClaim opening_claim = Shplemini::compute_batch_opening_claim(circuit_size, commitments.get_unshifted_without_concatenated(), @@ -133,6 +133,7 @@ std::array TranslatorRecursiveVerifier_ struct SumcheckOutput challenge; // Evaluations at \f$ \vec u \f$ of the polynomials used in Sumcheck ClaimedEvaluations claimed_evaluations; - // Include ClaimedLibraEvaluations conditioned on FlavorHasZK concept + // For ZK Flavors: the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges FF claimed_libra_evaluation; // Whether or not the evaluations of multilinear polynomials \f$ P_1, \ldots, P_N \f$ and final Sumcheck evaluation // have been confirmed diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 92f22a4646b..d35f188d1a7 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -110,7 +110,7 @@ template struct ZKSumcheckData { */ static FF compute_libra_total_sum(const std::vector>& libra_univariates, FF& scaling_factor, - const FF& free_term) + const FF& constant_term) { FF total_sum = 0; scaling_factor *= one_half; @@ -121,7 +121,7 @@ template struct ZKSumcheckData { } total_sum *= scaling_factor; - return total_sum + free_term * (1 << libra_univariates.size()); + return total_sum + constant_term * (1 << libra_univariates.size()); } /** diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index d9a7b89735f..576cfde21b4 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -103,7 +103,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) } // Receive commitments to Libra masking polynomials - std::array libra_commitments = {}; + std::array libra_commitments = {}; libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); auto [multivariate_challenge, claimed_evaluations, libra_evaluation, sumcheck_verified] = @@ -118,7 +118,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); // Execute Shplemini - + bool consistency_checked = false; const BatchOpeningClaim opening_claim = Shplemini::compute_batch_opening_claim(circuit_size, commitments.get_unshifted_without_concatenated(), @@ -130,6 +130,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) transcript, Flavor::REPEATED_COMMITMENTS, Flavor::HasZK, + &consistency_checked, libra_commitments, libra_evaluation, commitments.get_groups_to_be_concatenated(), @@ -138,7 +139,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) auto verified = key->pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); - return verified && opening_claim.consistency_checked; + return verified && consistency_checked; } bool TranslatorVerifier::verify_translation(const TranslationEvaluations& translation_evaluations) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 4528c270fa8..16219465591 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -38,8 +38,6 @@ template void DeciderProver_::execute_relation_ch if constexpr (Flavor::HasZK) { zk_sumcheck_data = ZKData(numeric::get_msb(polynomial_size), transcript, commitment_key); - } else { - zk_sumcheck_data = ZKData(); } sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 1fe22bb1996..96d69a3ed30 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -46,7 +46,7 @@ template bool DeciderVerifier_::verify() auto sumcheck = SumcheckVerifier( static_cast(accumulator->verification_key->log_circuit_size), transcript, accumulator->target_sum); // For MegaZKFlavor: receive commitments to Libra masking polynomials - std::array libra_commitments = {}; + std::array libra_commitments = {}; if constexpr (Flavor::HasZK) { libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); } @@ -59,7 +59,6 @@ template bool DeciderVerifier_::verify() libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); - // info("big sum received"); } // If Sumcheck did not verify, return false @@ -67,7 +66,7 @@ template bool DeciderVerifier_::verify() info("Sumcheck verification failed."); return false; } - + bool consistency_checked = true; const BatchOpeningClaim opening_claim = Shplemini::compute_batch_opening_claim(accumulator->verification_key->circuit_size, commitments.get_unshifted(), @@ -79,11 +78,12 @@ template bool DeciderVerifier_::verify() transcript, Flavor::REPEATED_COMMITMENTS, Flavor::HasZK, + &consistency_checked, libra_commitments, libra_evaluation); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); bool verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); - return sumcheck_output.verified.value() && verified && opening_claim.consistency_checked; + return sumcheck_output.verified.value() && verified && consistency_checked; } template class DeciderVerifier_; From c7ea181bdf5d73fdb0ad1926b3d4ce3c169410d0 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Thu, 2 Jan 2025 17:58:16 +0000 Subject: [PATCH 27/30] sumcheck clean-up --- .../commitment_schemes/shplonk/shplemini.hpp | 28 +++++----- .../src/barretenberg/eccvm/eccvm_prover.cpp | 4 +- .../src/barretenberg/eccvm/eccvm_prover.hpp | 2 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 56 ++++++++----------- .../barretenberg/sumcheck/sumcheck.test.cpp | 6 +- .../translator_vm/translator_prover.cpp | 4 +- .../translator_vm/translator_prover.hpp | 2 +- .../ultra_honk/decider_prover.cpp | 4 +- .../ultra_honk/decider_prover.hpp | 2 +- 9 files changed, 49 insertions(+), 59 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 92993a23f3b..e4305474ff3 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -521,21 +521,21 @@ template class ShpleminiVerifier_ { } /** - * @brief Combines scalars of repeating commitments to reduce the number of scalar multiplications performed by - * the verifier. + * @brief Combines scalars of repeating commitments to reduce the number of scalar multiplications performed by the + * verifier. * - * @details The Shplemini verifier gets the access to multiple groups of commitments, some of which are - * duplicated because they correspond to polynomials whose shifts also evaluated or used in concatenation groups - * in Translator. This method combines the scalars associated with these repeating commitments, reducing the - * total number of scalar multiplications required during the verification. + * @details The Shplemini verifier gets the access to multiple groups of commitments, some of which are duplicated + * because they correspond to polynomials whose shifts also evaluated or used in concatenation groups in + * Translator. This method combines the scalars associated with these repeating commitments, reducing the total + * number of scalar multiplications required during the verification. * * More specifically, the Shplemini verifier receives two or three groups of commitments: get_unshifted() and * get_to_be_shifted() in the case of Ultra, Mega, and ECCVM Flavors; and get_unshifted_without_concatenated(), - * get_to_be_shifted(), and get_groups_to_be_concatenated() in the case of the TranslatorFlavor. The commitments - * are then placed in this specific order in a BatchOpeningClaim object containing a vector of commitments and a - * vector of scalars. The ranges with repeated commitments belong to the Flavors. This method iterates over - * these ranges and sums the scalar multipliers corresponding to the same group element. After combining the - * scalars, we erase corresponding entries in both vectors. + * get_to_be_shifted(), and get_groups_to_be_concatenated() in the case of the TranslatorFlavor. The commitments are + * then placed in this specific order in a BatchOpeningClaim object containing a vector of commitments and a vector + * of scalars. The ranges with repeated commitments belong to the Flavors. This method iterates over these ranges + * and sums the scalar multipliers corresponding to the same group element. After combining the scalars, we erase + * corresponding entries in both vectors. * */ // TODO(https://github.com/AztecProtocol/barretenberg/issues/1151) Avoid erasing vector elements. @@ -544,9 +544,9 @@ template class ShpleminiVerifier_ { const RepeatedCommitmentsData& repeated_commitments, bool has_zk) { - // We started populating commitments and scalars by adding Shplonk:Q commitmment and the corresponding - // scalar factor 1. In the case of ZK, we also added Gemini:masking_poly_comm before populating the vector - // with commitments to prover polynomials + // We started populating commitments and scalars by adding Shplonk:Q commitmment and the corresponding scalar + // factor 1. In the case of ZK, we also added Gemini:masking_poly_comm before populating the vector with + // commitments to prover polynomials const size_t offset = has_zk ? 2 : 1; // Extract the indices from the container, which is normally created in a given Flavor diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 35f2e319175..f446f8fc255 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -104,7 +104,7 @@ void ECCVMProver::execute_relation_check_rounds() gate_challenges[idx] = transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - zk_sumcheck_data = ZKData(key->log_circuit_size, transcript, key->commitment_key); + zk_sumcheck_data = std::make_shared(key->log_circuit_size, transcript, key->commitment_key); sumcheck_output = sumcheck.prove(key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); } @@ -122,7 +122,7 @@ void ECCVMProver::execute_pcs_rounds() using Shplonk = ShplonkProver_; using OpeningClaim = ProverOpeningClaim; - SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, + SmallSubgroupIPA small_subgroup_ipa_prover(*zk_sumcheck_data, sumcheck_output.challenge, sumcheck_output.claimed_libra_evaluation, transcript, diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index 4217b381862..17e0ff9962a 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -56,7 +56,7 @@ class ECCVMProver { std::shared_ptr key; CommitmentLabels commitment_labels; - ZKData zk_sumcheck_data; + std::shared_ptr zk_sumcheck_data; Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk FF nu_challenge; // needed in both Shplonk rounds diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 3d35137a199..0b8c1de83b3 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -158,7 +158,6 @@ template class SumcheckProver { std::shared_ptr transcript; SumcheckProverRound round; - ZKData zk_sumcheck_data; /** * @@ -192,11 +191,9 @@ template class SumcheckProver { const bb::RelationParameters& relation_parameters, const RelationSeparator alpha, const std::vector& gate_challenges, - const ZKData& zk_data = ZKData()) + const std::shared_ptr& zk_sumcheck_data = nullptr) { - if constexpr (Flavor::HasZK) { - extract_zk_data(zk_data); - } + bb::GateSeparatorPolynomial gate_separators(gate_challenges, multivariate_d); std::vector multivariate_challenge; @@ -211,7 +208,7 @@ template class SumcheckProver { relation_parameters, gate_separators, alpha, - zk_sumcheck_data, + *zk_sumcheck_data, row_disabling_polynomial); vinfo("starting sumcheck rounds..."); { @@ -244,7 +241,7 @@ template class SumcheckProver { relation_parameters, gate_separators, alpha, - zk_sumcheck_data, + *zk_sumcheck_data, row_disabling_polynomial); // Place evaluations of Sumcheck Round Univariate in the transcript transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate); @@ -275,10 +272,10 @@ template class SumcheckProver { FF libra_evaluation{ 0 }; if constexpr (Flavor::HasZK) { - for (auto& libra_eval : zk_sumcheck_data.libra_evaluations) { + for (auto& libra_eval : zk_sumcheck_data->libra_evaluations) { libra_evaluation += libra_eval; } - libra_evaluation += zk_sumcheck_data.constant_term; + libra_evaluation += zk_sumcheck_data->constant_term; std::string libra_evaluation_label = "Libra:claimed_evaluation"; transcript->send_to_verifier(libra_evaluation_label, libra_evaluation); }; @@ -380,15 +377,6 @@ polynomials that are sent in clear. return multivariate_evaluations; }; - void extract_zk_data(const ZKSumcheckData& zk_data) - { - zk_sumcheck_data.libra_univariates = std::move(zk_data.libra_univariates); - zk_sumcheck_data.constant_term = std::move(zk_data.constant_term); - zk_sumcheck_data.libra_running_sum = std::move(zk_data.libra_running_sum); - zk_sumcheck_data.libra_challenge = std::move(zk_data.libra_challenge); - zk_sumcheck_data.libra_scaling_factor = std::move(zk_data.libra_scaling_factor); - } - /** * @brief Upon receiving the challenge \f$u_i\f$, the prover updates Libra data. If \f$ i < d-1\f$ @@ -414,34 +402,36 @@ polynomials that are sent in clear. * @param libra_running_sum * @param libra_evaluations */ - void update_zk_sumcheck_data(ZKData& zk_sumcheck_data, const FF round_challenge, size_t round_idx) + void update_zk_sumcheck_data(const std::shared_ptr& zk_sumcheck_data, + const FF round_challenge, + size_t round_idx) { static constexpr FF two_inv = FF(1) / FF(2); // when round_idx = d - 1, the update is not needed - if (round_idx < zk_sumcheck_data.libra_univariates.size() - 1) { - for (auto& univariate : zk_sumcheck_data.libra_univariates) { + if (round_idx < zk_sumcheck_data->libra_univariates.size() - 1) { + for (auto& univariate : zk_sumcheck_data->libra_univariates) { univariate *= two_inv; }; // compute the evaluation \f$ \rho \cdot 2^{d-2-i} \çdot g_i(u_i) \f$ - auto libra_evaluation = zk_sumcheck_data.libra_univariates[round_idx].evaluate(round_challenge); - auto next_libra_univariate = zk_sumcheck_data.libra_univariates[round_idx + 1]; + auto libra_evaluation = zk_sumcheck_data->libra_univariates[round_idx].evaluate(round_challenge); + auto next_libra_univariate = zk_sumcheck_data->libra_univariates[round_idx + 1]; // update the running sum by adding g_i(u_i) and subtracting (g_i(0) + g_i(1)) - zk_sumcheck_data.libra_running_sum += + zk_sumcheck_data->libra_running_sum += -next_libra_univariate.evaluate(FF(0)) - next_libra_univariate.evaluate(FF(1)); - zk_sumcheck_data.libra_running_sum *= two_inv; + zk_sumcheck_data->libra_running_sum *= two_inv; - zk_sumcheck_data.libra_running_sum += libra_evaluation; - zk_sumcheck_data.libra_scaling_factor *= two_inv; + zk_sumcheck_data->libra_running_sum += libra_evaluation; + zk_sumcheck_data->libra_scaling_factor *= two_inv; - zk_sumcheck_data.libra_evaluations.emplace_back(libra_evaluation / zk_sumcheck_data.libra_scaling_factor); + zk_sumcheck_data->libra_evaluations.emplace_back(libra_evaluation / zk_sumcheck_data->libra_scaling_factor); } else { // compute the evaluation of the last Libra univariate at the challenge u_{d-1} - auto libra_evaluation = zk_sumcheck_data.libra_univariates[round_idx].evaluate(round_challenge) / - zk_sumcheck_data.libra_scaling_factor; + auto libra_evaluation = zk_sumcheck_data->libra_univariates[round_idx].evaluate(round_challenge) / + zk_sumcheck_data->libra_scaling_factor; // place the evalution into the vector of Libra evaluations - zk_sumcheck_data.libra_evaluations.emplace_back(libra_evaluation); - for (auto univariate : zk_sumcheck_data.libra_univariates) { - univariate *= FF(1) / zk_sumcheck_data.libra_challenge; + zk_sumcheck_data->libra_evaluations.emplace_back(libra_evaluation); + for (auto univariate : zk_sumcheck_data->libra_univariates) { + univariate *= FF(1) / zk_sumcheck_data->libra_challenge; } }; } diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp index 5eee79cb467..d58742a05ad 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp @@ -149,7 +149,7 @@ template class SumcheckTests : public ::testing::Test { SumcheckOutput output; if constexpr (Flavor::HasZK) { - ZKData zk_sumcheck_data(multivariate_d, transcript); + std::shared_ptr zk_sumcheck_data = std::make_shared(multivariate_d, transcript); output = sumcheck.prove(full_polynomials, {}, alpha, gate_challenges, zk_sumcheck_data); } else { output = sumcheck.prove(full_polynomials, {}, alpha, gate_challenges); @@ -255,7 +255,7 @@ template class SumcheckTests : public ::testing::Test { } SumcheckOutput output; if constexpr (Flavor::HasZK) { - ZKData zk_sumcheck_data(multivariate_d, prover_transcript); + std::shared_ptr zk_sumcheck_data = std::make_shared(multivariate_d, prover_transcript); output = sumcheck_prover.prove( full_polynomials, relation_parameters, prover_alpha, prover_gate_challenges, zk_sumcheck_data); } else { @@ -345,7 +345,7 @@ template class SumcheckTests : public ::testing::Test { SumcheckOutput output; if constexpr (Flavor::HasZK) { // construct libra masking polynomials and compute auxiliary data - ZKData zk_sumcheck_data(multivariate_d, prover_transcript); + std::shared_ptr zk_sumcheck_data = std::make_shared(multivariate_d, prover_transcript); output = sumcheck_prover.prove( full_polynomials, relation_parameters, prover_alpha, prover_gate_challenges, zk_sumcheck_data); } else { diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 47f816c7d21..14b0554b18b 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -164,7 +164,7 @@ void TranslatorProver::execute_relation_check_rounds() } // // create masking polynomials for sumcheck round univariates and auxiliary data - zk_sumcheck_data = ZKData(key->log_circuit_size, transcript, key->commitment_key); + zk_sumcheck_data = std::make_shared(key->log_circuit_size, transcript, key->commitment_key); sumcheck_output = sumcheck.prove(key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); } @@ -183,7 +183,7 @@ void TranslatorProver::execute_pcs_rounds() using SmallSubgroupIPA = SmallSubgroupIPAProver; - SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, + SmallSubgroupIPA small_subgroup_ipa_prover(*zk_sumcheck_data, sumcheck_output.challenge, sumcheck_output.claimed_libra_evaluation, transcript, diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp index 6632afba69d..1acadc885bb 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp @@ -52,7 +52,7 @@ class TranslatorProver { CommitmentLabels commitment_labels; - ZKData zk_sumcheck_data; + std::shared_ptr zk_sumcheck_data; SumcheckOutput sumcheck_output; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 16219465591..c4f201763f3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -37,7 +37,7 @@ template void DeciderProver_::execute_relation_ch auto commitment_key = std::make_shared(1 << (log_subgroup_size + 1)); if constexpr (Flavor::HasZK) { - zk_sumcheck_data = ZKData(numeric::get_msb(polynomial_size), transcript, commitment_key); + zk_sumcheck_data = std::make_shared(numeric::get_msb(polynomial_size), transcript, commitment_key); } sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, @@ -72,7 +72,7 @@ template void DeciderProver_::execute_pcs_rounds( } else { SmallSubgroupIPA small_subgroup_ipa_prover( - zk_sumcheck_data, sumcheck_output.challenge, sumcheck_output.claimed_libra_evaluation, transcript, ck); + *zk_sumcheck_data, sumcheck_output.challenge, sumcheck_output.claimed_libra_evaluation, transcript, ck); prover_opening_claim = ShpleminiProver_::prove(proving_key->proving_key.circuit_size, proving_key->proving_key.polynomials.get_unshifted(), diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp index 47baefd297b..3a7facad33f 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp @@ -48,7 +48,7 @@ template class DeciderProver_ { Polynomial quotient_W; - ZKData zk_sumcheck_data; + std::shared_ptr zk_sumcheck_data; SumcheckOutput sumcheck_output; From 90b7cde246054b62f524d2f4d03f65f4af155c30 Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 3 Jan 2025 09:30:13 +0000 Subject: [PATCH 28/30] removed noise in docs --- .../commitment_schemes/shplonk/shplemini.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index e4305474ff3..8e68b8adc81 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -201,8 +201,8 @@ template class ShpleminiVerifier_ { // - Get the quotient commitment for the Shplonk batching of Gemini opening claims const auto Q_commitment = transcript->template receive_from_prover("Shplonk:Q"); - // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(Aₙ₋₁), [1]₁) where fᵢ - // are the k commitments to unshifted polynomials and gⱼ are the m commitments to shifted polynomials + // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(Aₙ₋₁), [1]₁) where fᵢ are + // the k commitments to unshifted polynomials and gⱼ are the m commitments to shifted polynomials std::vector commitments{ Q_commitment }; // Get Shplonk opening point z @@ -374,8 +374,8 @@ template class ShpleminiVerifier_ { * @param commitments The vector of commitments to be populated. * @param scalars The vector of scalars to be populated. * @param batched_evaluation The evaluation of the batched multilinear polynomial. - * @param concatenated_scalars Scaling factors for the commitments to polynomials in concatenation groups, one - * for each group. + * @param concatenated_scalars Scaling factors for the commitments to polynomials in concatenation groups, one for + * each group. * @param concatenation_group_commitments Commitments to polynomials to be concatenated. * @param concatenated_evaluations Evaluations of the full concatenated polynomials. */ @@ -424,8 +424,8 @@ template class ShpleminiVerifier_ { current_batching_challenge *= multivariate_batching_challenge; } - // If we are performing an opening verification for the translator, add the contributions from the - // concatenation commitments and evaluations to the result + // If we are performing an opening verification for the translator, add the contributions from the concatenation + // commitments and evaluations to the result ASSERT(concatenated_evaluations.size() == concatenation_group_commitments.size()); if (!concatenation_group_commitments.empty()) { size_t concatenation_group_size = concatenation_group_commitments[0].size(); From ce8e47d0bd9827be026c7d5376e1a322c26e20fa Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Fri, 3 Jan 2025 10:31:00 +0000 Subject: [PATCH 29/30] fix tests --- .../cpp/src/barretenberg/ultra_honk/decider_prover.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index c4f201763f3..d6b3b8bcdf2 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -33,10 +33,10 @@ template void DeciderProver_::execute_relation_ch { PROFILE_THIS_NAME("sumcheck.prove"); - const size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); - auto commitment_key = std::make_shared(1 << (log_subgroup_size + 1)); if constexpr (Flavor::HasZK) { + const size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); + auto commitment_key = std::make_shared(1 << (log_subgroup_size + 1)); zk_sumcheck_data = std::make_shared(numeric::get_msb(polynomial_size), transcript, commitment_key); } From 3c8418039739acb9668348446fad3aab86e53e1c Mon Sep 17 00:00:00 2001 From: iakovenkos Date: Tue, 7 Jan 2025 12:02:20 +0000 Subject: [PATCH 30/30] review addressed --- .../commitment_schemes/shplonk/shplemini.hpp | 3 +- .../small_subgroup_ipa/small_subgroup_ipa.hpp | 2 +- .../src/barretenberg/eccvm/eccvm_prover.cpp | 4 +- .../src/barretenberg/eccvm/eccvm_prover.hpp | 2 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 155 +++++++++++++----- .../barretenberg/sumcheck/sumcheck.test.cpp | 20 +-- .../barretenberg/sumcheck/sumcheck_round.hpp | 81 +++++++-- .../translator_vm/translator_prover.cpp | 5 +- .../translator_vm/translator_prover.hpp | 2 +- .../ultra_honk/decider_prover.cpp | 21 ++- .../ultra_honk/decider_prover.hpp | 2 +- 11 files changed, 208 insertions(+), 89 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 8e68b8adc81..33075943661 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -146,7 +146,8 @@ template class ShpleminiVerifier_ { const std::shared_ptr& transcript, const RepeatedCommitmentsData& repeated_commitments = {}, const bool has_zk = false, - bool* consistency_checked = nullptr, + bool* consistency_checked = nullptr, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1191). + // Shplemini Refactoring: Remove bool pointer const std::array& libra_commitments = {}, const Fr& libra_univariate_evaluation = Fr{ 0 }, const std::vector>& concatenation_group_commitments = {}, 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 d4166730f7c..39f9b27b625 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]; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index f446f8fc255..35f2e319175 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -104,7 +104,7 @@ void ECCVMProver::execute_relation_check_rounds() gate_challenges[idx] = transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - zk_sumcheck_data = std::make_shared(key->log_circuit_size, transcript, key->commitment_key); + zk_sumcheck_data = ZKData(key->log_circuit_size, transcript, key->commitment_key); sumcheck_output = sumcheck.prove(key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); } @@ -122,7 +122,7 @@ void ECCVMProver::execute_pcs_rounds() using Shplonk = ShplonkProver_; using OpeningClaim = ProverOpeningClaim; - SmallSubgroupIPA small_subgroup_ipa_prover(*zk_sumcheck_data, + SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output.challenge, sumcheck_output.claimed_libra_evaluation, transcript, diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index 17e0ff9962a..4217b381862 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -56,7 +56,7 @@ class ECCVMProver { std::shared_ptr key; CommitmentLabels commitment_labels; - std::shared_ptr zk_sumcheck_data; + ZKData zk_sumcheck_data; Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk FF nu_challenge; // needed in both Shplonk rounds diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 0b8c1de83b3..afd1cb3a663 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -178,8 +178,8 @@ template class SumcheckProver { , partially_evaluated_polynomials(multivariate_n){}; /** - * @brief Compute round univariate, place it in transcript, compute challenge, partially evaluate. Repeat - * until final round, then get full evaluations of prover polynomials, and place them in transcript. + * @brief Non-ZK version: Compute round univariate, place it in transcript, compute challenge, partially evaluate. + * Repeat until final round, then get full evaluations of prover polynomials, and place them in transcript. * @details See Detailed description of \ref bb::SumcheckProver< Flavor > "Sumcheck Prover . * @param full_polynomials Container for ProverPolynomials * @param relation_parameters @@ -187,11 +187,89 @@ template class SumcheckProver { * @param gate_challenges * @return SumcheckOutput */ + SumcheckOutput prove(ProverPolynomials& full_polynomials, + const bb::RelationParameters& relation_parameters, + const RelationSeparator alpha, + const std::vector& gate_challenges) + { + + bb::GateSeparatorPolynomial gate_separators(gate_challenges, multivariate_d); + + std::vector multivariate_challenge; + multivariate_challenge.reserve(multivariate_d); + // In the first round, we compute the first univariate polynomial and populate the book-keeping table of + // #partially_evaluated_polynomials, which has \f$ n/2 \f$ rows and \f$ N \f$ columns. When the Flavor has ZK, + // compute_univariate also takes into account the zk_sumcheck_data. + auto round_univariate = round.compute_univariate(full_polynomials, relation_parameters, gate_separators, alpha); + vinfo("starting sumcheck rounds..."); + { + + PROFILE_THIS_NAME("rest of sumcheck round 1"); + + // Place the evaluations of the round univariate into transcript. + transcript->send_to_verifier("Sumcheck:univariate_0", round_univariate); + FF round_challenge = transcript->template get_challenge("Sumcheck:u_0"); + multivariate_challenge.emplace_back(round_challenge); + // Prepare sumcheck book-keeping table for the next round + partially_evaluate(full_polynomials, multivariate_n, round_challenge); + gate_separators.partially_evaluate(round_challenge); + round.round_size = round.round_size >> 1; // TODO(#224)(Cody): Maybe partially_evaluate should do this and + // release memory? // All but final round + // We operate on partially_evaluated_polynomials in place. + } + for (size_t round_idx = 1; round_idx < multivariate_d; round_idx++) { + + PROFILE_THIS_NAME("sumcheck loop"); + + // Write the round univariate to the transcript + round_univariate = + round.compute_univariate(partially_evaluated_polynomials, relation_parameters, gate_separators, alpha); + // Place evaluations of Sumcheck Round Univariate in the transcript + transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate); + FF round_challenge = transcript->template get_challenge("Sumcheck:u_" + std::to_string(round_idx)); + multivariate_challenge.emplace_back(round_challenge); + // Prepare sumcheck book-keeping table for the next round + partially_evaluate(partially_evaluated_polynomials, round.round_size, round_challenge); + gate_separators.partially_evaluate(round_challenge); + round.round_size = round.round_size >> 1; + } + vinfo("completed ", multivariate_d, " rounds of sumcheck"); + + // Zero univariates are used to pad the proof to the fixed size CONST_PROOF_SIZE_LOG_N. + auto zero_univariate = bb::Univariate::zero(); + for (size_t idx = multivariate_d; idx < CONST_PROOF_SIZE_LOG_N; idx++) { + transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(idx), zero_univariate); + FF round_challenge = transcript->template get_challenge("Sumcheck:u_" + std::to_string(idx)); + multivariate_challenge.emplace_back(round_challenge); + } + // Claimed evaluations of Prover polynomials are extracted and added to the transcript. When Flavor has ZK, the + // evaluations of all witnesses are masked. + ClaimedEvaluations multivariate_evaluations; + multivariate_evaluations = extract_claimed_evaluations(partially_evaluated_polynomials); + transcript->send_to_verifier("Sumcheck:evaluations", multivariate_evaluations.get_all()); + // For ZK Flavors: the evaluations of Libra univariates are included in the Sumcheck Output + + return SumcheckOutput{ multivariate_challenge, multivariate_evaluations }; + vinfo("finished sumcheck"); + }; + + /** + * @brief ZK-version of `prove` that runs Sumcheck with disabled rows and masking of Round Univariates. + * The masking is ensured by adding random Libra univariates to the Sumcheck round univariates. + * + * @param full_polynomials + * @param relation_parameters + * @param alpha + * @param gate_challenges + * @param zk_sumcheck_data + * @return SumcheckOutput + */ SumcheckOutput prove(ProverPolynomials& full_polynomials, const bb::RelationParameters& relation_parameters, const RelationSeparator alpha, const std::vector& gate_challenges, - const std::shared_ptr& zk_sumcheck_data = nullptr) + ZKData& zk_sumcheck_data) + requires FlavorHasZK { bb::GateSeparatorPolynomial gate_separators(gate_challenges, multivariate_d); @@ -208,7 +286,7 @@ template class SumcheckProver { relation_parameters, gate_separators, alpha, - *zk_sumcheck_data, + zk_sumcheck_data, row_disabling_polynomial); vinfo("starting sumcheck rounds..."); { @@ -222,10 +300,8 @@ template class SumcheckProver { // Prepare sumcheck book-keeping table for the next round partially_evaluate(full_polynomials, multivariate_n, round_challenge); // Prepare ZK Sumcheck data for the next round - if constexpr (Flavor::HasZK) { - update_zk_sumcheck_data(zk_sumcheck_data, round_challenge, round_idx); - row_disabling_polynomial.update_evaluations(round_challenge, round_idx); - }; + update_zk_sumcheck_data(zk_sumcheck_data, round_challenge, round_idx); + row_disabling_polynomial.update_evaluations(round_challenge, round_idx); gate_separators.partially_evaluate(round_challenge); round.round_size = round.round_size >> 1; // TODO(#224)(Cody): Maybe partially_evaluate should do this and // release memory? // All but final round @@ -241,7 +317,7 @@ template class SumcheckProver { relation_parameters, gate_separators, alpha, - *zk_sumcheck_data, + zk_sumcheck_data, row_disabling_polynomial); // Place evaluations of Sumcheck Round Univariate in the transcript transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate); @@ -250,10 +326,8 @@ template class SumcheckProver { // Prepare sumcheck book-keeping table for the next round partially_evaluate(partially_evaluated_polynomials, round.round_size, round_challenge); // Prepare evaluation masking and libra structures for the next round (for ZK Flavors) - if constexpr (Flavor::HasZK) { - update_zk_sumcheck_data(zk_sumcheck_data, round_challenge, round_idx); - row_disabling_polynomial.update_evaluations(round_challenge, round_idx); - }; + update_zk_sumcheck_data(zk_sumcheck_data, round_challenge, round_idx); + row_disabling_polynomial.update_evaluations(round_challenge, round_idx); gate_separators.partially_evaluate(round_challenge); round.round_size = round.round_size >> 1; @@ -271,26 +345,21 @@ template class SumcheckProver { // transcript. FF libra_evaluation{ 0 }; - if constexpr (Flavor::HasZK) { - for (auto& libra_eval : zk_sumcheck_data->libra_evaluations) { - libra_evaluation += libra_eval; - } - libra_evaluation += zk_sumcheck_data->constant_term; - std::string libra_evaluation_label = "Libra:claimed_evaluation"; - transcript->send_to_verifier(libra_evaluation_label, libra_evaluation); - }; + for (auto& libra_eval : zk_sumcheck_data.libra_evaluations) { + libra_evaluation += libra_eval; + } + libra_evaluation += zk_sumcheck_data.constant_term; + std::string libra_evaluation_label = "Libra:claimed_evaluation"; + transcript->send_to_verifier(libra_evaluation_label, libra_evaluation); // Claimed evaluations of Prover polynomials are extracted and added to the transcript. When Flavor has ZK, the // evaluations of all witnesses are masked. ClaimedEvaluations multivariate_evaluations; multivariate_evaluations = extract_claimed_evaluations(partially_evaluated_polynomials); transcript->send_to_verifier("Sumcheck:evaluations", multivariate_evaluations.get_all()); - // For ZK Flavors: the evaluations of Libra univariates are included in the Sumcheck Output - if constexpr (!Flavor::HasZK) { - return SumcheckOutput{ multivariate_challenge, multivariate_evaluations }; - } else { - return SumcheckOutput{ multivariate_challenge, multivariate_evaluations, libra_evaluation }; - } + // The sum of the Libra constant term and the evaluations of Libra univariates at corresponding sumcheck + // challenges is included in the Sumcheck Output + return SumcheckOutput{ multivariate_challenge, multivariate_evaluations, libra_evaluation }; vinfo("finished sumcheck"); }; @@ -402,36 +471,34 @@ polynomials that are sent in clear. * @param libra_running_sum * @param libra_evaluations */ - void update_zk_sumcheck_data(const std::shared_ptr& zk_sumcheck_data, - const FF round_challenge, - size_t round_idx) + void update_zk_sumcheck_data(ZKData& zk_sumcheck_data, const FF round_challenge, size_t round_idx) { static constexpr FF two_inv = FF(1) / FF(2); // when round_idx = d - 1, the update is not needed - if (round_idx < zk_sumcheck_data->libra_univariates.size() - 1) { - for (auto& univariate : zk_sumcheck_data->libra_univariates) { + if (round_idx < zk_sumcheck_data.libra_univariates.size() - 1) { + for (auto& univariate : zk_sumcheck_data.libra_univariates) { univariate *= two_inv; }; // compute the evaluation \f$ \rho \cdot 2^{d-2-i} \çdot g_i(u_i) \f$ - auto libra_evaluation = zk_sumcheck_data->libra_univariates[round_idx].evaluate(round_challenge); - auto next_libra_univariate = zk_sumcheck_data->libra_univariates[round_idx + 1]; + auto libra_evaluation = zk_sumcheck_data.libra_univariates[round_idx].evaluate(round_challenge); + auto next_libra_univariate = zk_sumcheck_data.libra_univariates[round_idx + 1]; // update the running sum by adding g_i(u_i) and subtracting (g_i(0) + g_i(1)) - zk_sumcheck_data->libra_running_sum += + zk_sumcheck_data.libra_running_sum += -next_libra_univariate.evaluate(FF(0)) - next_libra_univariate.evaluate(FF(1)); - zk_sumcheck_data->libra_running_sum *= two_inv; + zk_sumcheck_data.libra_running_sum *= two_inv; - zk_sumcheck_data->libra_running_sum += libra_evaluation; - zk_sumcheck_data->libra_scaling_factor *= two_inv; + zk_sumcheck_data.libra_running_sum += libra_evaluation; + zk_sumcheck_data.libra_scaling_factor *= two_inv; - zk_sumcheck_data->libra_evaluations.emplace_back(libra_evaluation / zk_sumcheck_data->libra_scaling_factor); + zk_sumcheck_data.libra_evaluations.emplace_back(libra_evaluation / zk_sumcheck_data.libra_scaling_factor); } else { // compute the evaluation of the last Libra univariate at the challenge u_{d-1} - auto libra_evaluation = zk_sumcheck_data->libra_univariates[round_idx].evaluate(round_challenge) / - zk_sumcheck_data->libra_scaling_factor; + auto libra_evaluation = zk_sumcheck_data.libra_univariates[round_idx].evaluate(round_challenge) / + zk_sumcheck_data.libra_scaling_factor; // place the evalution into the vector of Libra evaluations - zk_sumcheck_data->libra_evaluations.emplace_back(libra_evaluation); - for (auto univariate : zk_sumcheck_data->libra_univariates) { - univariate *= FF(1) / zk_sumcheck_data->libra_challenge; + zk_sumcheck_data.libra_evaluations.emplace_back(libra_evaluation); + for (auto univariate : zk_sumcheck_data.libra_univariates) { + univariate *= FF(1) / zk_sumcheck_data.libra_challenge; } }; } diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp index db11c457c95..1f384dae67d 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp @@ -149,7 +149,7 @@ template class SumcheckTests : public ::testing::Test { SumcheckOutput output; if constexpr (Flavor::HasZK) { - std::shared_ptr zk_sumcheck_data = std::make_shared(multivariate_d, transcript); + ZKData zk_sumcheck_data = ZKData(multivariate_d, transcript); output = sumcheck.prove(full_polynomials, {}, alpha, gate_challenges, zk_sumcheck_data); } else { output = sumcheck.prove(full_polynomials, {}, alpha, gate_challenges); @@ -255,7 +255,7 @@ template class SumcheckTests : public ::testing::Test { } SumcheckOutput output; if constexpr (Flavor::HasZK) { - std::shared_ptr zk_sumcheck_data = std::make_shared(multivariate_d, prover_transcript); + ZKData zk_sumcheck_data = ZKData(multivariate_d, prover_transcript); output = sumcheck_prover.prove( full_polynomials, relation_parameters, prover_alpha, prover_gate_challenges, zk_sumcheck_data); } else { @@ -345,7 +345,7 @@ template class SumcheckTests : public ::testing::Test { SumcheckOutput output; if constexpr (Flavor::HasZK) { // construct libra masking polynomials and compute auxiliary data - std::shared_ptr zk_sumcheck_data = std::make_shared(multivariate_d, prover_transcript); + ZKData zk_sumcheck_data = ZKData(multivariate_d, prover_transcript); output = sumcheck_prover.prove( full_polynomials, relation_parameters, prover_alpha, prover_gate_challenges, zk_sumcheck_data); } else { @@ -378,15 +378,13 @@ using FlavorTypes = testing::Types TYPED_TEST_SUITE(SumcheckTests, FlavorTypes); -#define SKIP_IF_ZK() \ - if (std::is_same::value || std::is_same::value) { \ - GTEST_SKIP() << "Skipping test for ZK-enabled flavors"; \ - } - TYPED_TEST(SumcheckTests, PolynomialNormalization) { - SKIP_IF_ZK(); - this->test_polynomial_normalization(); + if constexpr (std::is_same_v) { + this->test_polynomial_normalization(); + } else { + GTEST_SKIP() << "Skipping test for ZK-enabled flavors"; + } } // Test the prover TYPED_TEST(SumcheckTests, Prover) @@ -403,4 +401,4 @@ TYPED_TEST(SumcheckTests, ProverAndVerifierSimpleFailure) { this->test_failure_prover_verifier_flow(); } -} // namespace +} // namespace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index a4c32f314f7..092ba3ca941 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -124,8 +124,8 @@ template class SumcheckProverRound { } /** - * @brief Return the evaluations of the univariate round polynomials \f$ \tilde{S}_{i} (X_{i}) \f$ at \f$ X_{i } = - 0,\ldots, D \f$. Most likely, \f$ D \f$ is around \f$ 12 \f$. At the + * @brief Non-ZK version: Return the evaluations of the univariate round polynomials \f$ \tilde{S}_{i} (X_{i}) \f$ + at \f$ X_{i } = 0,\ldots, D \f$. Most likely, \f$ D \f$ is around \f$ 12 \f$. At the * end, reset all * univariate accumulators to be zero. * @details First, the vector of \ref pow_challenges "pow challenges" is computed. @@ -146,6 +146,61 @@ template class SumcheckProverRound { method \ref extend_and_batch_univariates "extend and batch univariates". */ template + SumcheckRoundUnivariate compute_univariate(ProverPolynomialsOrPartiallyEvaluatedMultivariates& polynomials, + const bb::RelationParameters& relation_parameters, + const bb::GateSeparatorPolynomial& gate_sparators, + const RelationSeparator alpha) + { + PROFILE_THIS_NAME("compute_univariate"); + + // Determine number of threads for multithreading. + // Note: Multithreading is "on" for every round but we reduce the number of threads from the max available based + // on a specified minimum number of iterations per thread. This eventually leads to the use of a single thread. + // For now we use a power of 2 number of threads simply to ensure the round size is evenly divided. + size_t min_iterations_per_thread = 1 << 6; // min number of iterations for which we'll spin up a unique thread + size_t num_threads = bb::calculate_num_threads_pow2(round_size, min_iterations_per_thread); + size_t iterations_per_thread = round_size / num_threads; // actual iterations per thread + + // Construct univariate accumulator containers; one per thread + std::vector thread_univariate_accumulators(num_threads); + + // Accumulate the contribution from each sub-relation accross each edge of the hyper-cube + parallel_for(num_threads, [&](size_t thread_idx) { + // Initialize the thread accumulator to 0 + Utils::zero_univariates(thread_univariate_accumulators[thread_idx]); + // Construct extended univariates containers; one per thread + ExtendedEdges extended_edges; + size_t start = thread_idx * iterations_per_thread; + size_t end = (thread_idx + 1) * iterations_per_thread; + for (size_t edge_idx = start; edge_idx < end; edge_idx += 2) { + extend_edges(extended_edges, polynomials, edge_idx); + // Compute the \f$ \ell \f$-th edge's univariate contribution, + // scale it by the corresponding \f$ pow_{\beta} \f$ contribution and add it to the accumulators for \f$ + // \tilde{S}^i(X_i) \f$. If \f$ \ell \f$'s binary representation is given by \f$ (\ell_{i+1},\ldots, + // \ell_{d-1})\f$, the \f$ pow_{\beta}\f$-contribution is \f$\beta_{i+1}^{\ell_{i+1}} \cdot \ldots \cdot + // \beta_{d-1}^{\ell_{d-1}}\f$. + accumulate_relation_univariates(thread_univariate_accumulators[thread_idx], + extended_edges, + relation_parameters, + gate_sparators[(edge_idx >> 1) * gate_sparators.periodicity]); + } + }); + + // Accumulate the per-thread univariate accumulators into a single set of accumulators + for (auto& accumulators : thread_univariate_accumulators) { + Utils::add_nested_tuples(univariate_accumulators, accumulators); + } + + // Batch the univariate contributions from each sub-relation to obtain the round univariate + return batch_over_relations(univariate_accumulators, alpha, gate_sparators); + } + + /** + * @brief ZK-version of `compute_univariate` that runs Sumcheck with disabled rows and masking of Round Univariates. + * The masking is ensured by adding random Libra univariates to the Sumcheck round univariates. + * + */ + template SumcheckRoundUnivariate compute_univariate(const size_t round_idx, ProverPolynomialsOrPartiallyEvaluatedMultivariates& polynomials, const bb::RelationParameters& relation_parameters, @@ -195,21 +250,15 @@ template class SumcheckProverRound { } // For ZK Flavors: The evaluations of the round univariates are masked by the evaluations of Libra univariates // and corrected by subtracting the contribution from the disabled rows - if constexpr (Flavor::HasZK) { - const auto contribution_from_disabled_rows = compute_disabled_contribution( - polynomials, relation_parameters, gate_sparators, alpha, round_idx, row_disabling_poly); - const auto libra_round_univariate = compute_libra_round_univariate(zk_sumcheck_data, round_idx); - // Batch the univariate contributions from each sub-relation to obtain the round univariate - const auto round_univariate = - batch_over_relations(univariate_accumulators, alpha, gate_sparators); - // Mask the round univariate - return round_univariate + libra_round_univariate - contribution_from_disabled_rows; - } + const auto contribution_from_disabled_rows = compute_disabled_contribution( + polynomials, relation_parameters, gate_sparators, alpha, round_idx, row_disabling_poly); + const auto libra_round_univariate = compute_libra_round_univariate(zk_sumcheck_data, round_idx); // Batch the univariate contributions from each sub-relation to obtain the round univariate - else { - return batch_over_relations(univariate_accumulators, alpha, gate_sparators); - } - } + const auto round_univariate = + batch_over_relations(univariate_accumulators, alpha, gate_sparators); + // Mask the round univariate + return round_univariate + libra_round_univariate - contribution_from_disabled_rows; + }; /*! * @brief For ZK Flavors: A method disabling the last 4 rows of the ProverPolynomials diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index b648765ad4f..1774a98f6f4 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -120,8 +120,7 @@ void TranslatorProver::execute_relation_check_rounds() } // // create masking polynomials for sumcheck round univariates and auxiliary data - zk_sumcheck_data = - std::make_shared(key->proving_key->log_circuit_size, transcript, key->proving_key->commitment_key); + zk_sumcheck_data = ZKData(key->proving_key->log_circuit_size, transcript, key->proving_key->commitment_key); sumcheck_output = sumcheck.prove(key->proving_key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); @@ -141,7 +140,7 @@ void TranslatorProver::execute_pcs_rounds() using SmallSubgroupIPA = SmallSubgroupIPAProver; - SmallSubgroupIPA small_subgroup_ipa_prover(*zk_sumcheck_data, + SmallSubgroupIPA small_subgroup_ipa_prover(zk_sumcheck_data, sumcheck_output.challenge, sumcheck_output.claimed_libra_evaluation, transcript, diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp index 4d81fcb1443..2acd99027cf 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp @@ -48,7 +48,7 @@ class TranslatorProver { CommitmentLabels commitment_labels; - std::shared_ptr zk_sumcheck_data; + ZKData zk_sumcheck_data; SumcheckOutput sumcheck_output; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index d6b3b8bcdf2..9317545152b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -37,14 +37,19 @@ template void DeciderProver_::execute_relation_ch if constexpr (Flavor::HasZK) { const size_t log_subgroup_size = static_cast(numeric::get_msb(Curve::SUBGROUP_SIZE)); auto commitment_key = std::make_shared(1 << (log_subgroup_size + 1)); - zk_sumcheck_data = std::make_shared(numeric::get_msb(polynomial_size), transcript, commitment_key); + zk_sumcheck_data = ZKData(numeric::get_msb(polynomial_size), transcript, commitment_key); + sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, + proving_key->relation_parameters, + proving_key->alphas, + proving_key->gate_challenges, + zk_sumcheck_data); + } else { + + sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, + proving_key->relation_parameters, + proving_key->alphas, + proving_key->gate_challenges); } - - sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, - proving_key->relation_parameters, - proving_key->alphas, - proving_key->gate_challenges, - zk_sumcheck_data); } } @@ -72,7 +77,7 @@ template void DeciderProver_::execute_pcs_rounds( } else { SmallSubgroupIPA small_subgroup_ipa_prover( - *zk_sumcheck_data, sumcheck_output.challenge, sumcheck_output.claimed_libra_evaluation, transcript, ck); + zk_sumcheck_data, sumcheck_output.challenge, sumcheck_output.claimed_libra_evaluation, transcript, ck); prover_opening_claim = ShpleminiProver_::prove(proving_key->proving_key.circuit_size, proving_key->proving_key.polynomials.get_unshifted(), diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp index 3a7facad33f..47baefd297b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp @@ -48,7 +48,7 @@ template class DeciderProver_ { Polynomial quotient_W; - std::shared_ptr zk_sumcheck_data; + ZKData zk_sumcheck_data; SumcheckOutput sumcheck_output;