From c857cd9167f696fc237b64ff579952001eba7d40 Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 15 Oct 2024 10:47:16 +0200 Subject: [PATCH] feat: Replace Zeromorph with Shplemini in ECCVM (#9102) This PR switches ECCVM to Shplemini which shaves off ~300k in the tube circuit. Now, on the verifier side, we first execute Shplemini, then reduce the BatchOpeningClaim to a single OpeningClaim by performing the batch_mul delayed by Shplemini. Then, we construct the translation OpeningClaim, and the two are being reduced to a single OpeningClaim by executing a second iteration of Shplonk. Finally, we verify the OpeningClaim via PCS. This could be further optimised as we currently perform 4 batch_muls. --- .../commitment_schemes/ipa/ipa.hpp | 2 +- .../commitment_schemes/shplonk/shplonk.hpp | 2 +- .../src/barretenberg/eccvm/eccvm_flavor.hpp | 26 ++++++----- .../src/barretenberg/eccvm/eccvm_prover.cpp | 35 ++++++++------- .../src/barretenberg/eccvm/eccvm_prover.hpp | 2 - .../eccvm/eccvm_transcript.test.cpp | 16 ++++--- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 43 +++++++++++-------- .../eccvm_recursive_verifier.cpp | 38 +++++++++------- .../stdlib/primitives/bool/bool.test.cpp | 2 + .../primitives/safe_uint/safe_uint.test.cpp | 1 + barretenberg/cpp/srs_db/Earthfile | 2 +- 11 files changed, 99 insertions(+), 70 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp index 53d1ed7c172..cbab1f00e72 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp @@ -601,7 +601,7 @@ template class IPA { GroupElement shplonk_output_commitment; if constexpr (Curve::is_stdlib_type) { shplonk_output_commitment = - GroupElement::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); + GroupElement::batch_mul(commitments, scalars); } else { shplonk_output_commitment = batch_mul_native(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 fa8deca2a6a..1322fb34c3d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp @@ -128,7 +128,7 @@ template class ShplonkProver_ { */ template static ProverOpeningClaim prove(const std::shared_ptr>& commitment_key, - std::span> opening_claims, + std::span> opening_claims, const std::shared_ptr& transcript) { const Fr nu = transcript->template get_challenge("Shplonk:nu"); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index 0cf437903c6..991c01f1257 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -935,14 +935,15 @@ class ECCVMFlavor { Commitment lookup_inverses_comm; std::vector> sumcheck_univariates; std::array sumcheck_evaluations; - std::vector zm_cq_comms; - Commitment zm_cq_comm; + std::vector gemini_fold_comms; + std::vector gemini_fold_evals; + Commitment shplonk_q_comm; FF translation_eval_op; FF translation_eval_px; FF translation_eval_py; FF translation_eval_z1; FF translation_eval_z2; - Commitment shplonk_q_comm; + Commitment shplonk_q2_comm; uint32_t ipa_poly_degree; std::vector ipa_l_comms; std::vector ipa_r_comms; @@ -1143,11 +1144,13 @@ class ECCVMFlavor { } sumcheck_evaluations = NativeTranscript::template deserialize_from_buffer>( NativeTranscript::proof_data, num_frs_read); + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { + gemini_fold_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); + } for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { - zm_cq_comms.push_back( - NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read)); + gemini_fold_evals.push_back(deserialize_from_buffer(proof_data, num_frs_read)); } - zm_cq_comm = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); + shplonk_q_comm = deserialize_from_buffer(proof_data, num_frs_read); translation_eval_op = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); @@ -1160,7 +1163,7 @@ class ECCVMFlavor { translation_eval_z2 = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); - shplonk_q_comm = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); + shplonk_q2_comm = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); ipa_poly_degree = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); @@ -1286,10 +1289,13 @@ class ECCVMFlavor { NativeTranscript::template serialize_to_buffer(sumcheck_univariates[i], NativeTranscript::proof_data); } NativeTranscript::template serialize_to_buffer(sumcheck_evaluations, NativeTranscript::proof_data); + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { + NativeTranscript::template serialize_to_buffer(gemini_fold_comms[i], proof_data); + } for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { - NativeTranscript::template serialize_to_buffer(zm_cq_comms[i], NativeTranscript::proof_data); + NativeTranscript::template serialize_to_buffer(gemini_fold_evals[i], proof_data); } - NativeTranscript::template serialize_to_buffer(zm_cq_comm, NativeTranscript::proof_data); + NativeTranscript::template serialize_to_buffer(shplonk_q_comm, proof_data); NativeTranscript::template serialize_to_buffer(translation_eval_op, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(translation_eval_px, NativeTranscript::proof_data); @@ -1297,7 +1303,7 @@ class ECCVMFlavor { NativeTranscript::template serialize_to_buffer(translation_eval_z1, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(translation_eval_z2, NativeTranscript::proof_data); - NativeTranscript::template serialize_to_buffer(shplonk_q_comm, NativeTranscript::proof_data); + NativeTranscript::template serialize_to_buffer(shplonk_q2_comm, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(ipa_poly_degree, NativeTranscript::proof_data); auto log_poly_degree = static_cast(numeric::get_msb(ipa_poly_degree)); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 7e637f48d94..7ecc89eb679 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -1,6 +1,7 @@ #include "eccvm_prover.hpp" #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" #include "barretenberg/common/ref_array.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" @@ -113,21 +114,18 @@ void ECCVMProver::execute_relation_check_rounds() void ECCVMProver::execute_pcs_rounds() { using Curve = typename Flavor::Curve; - using ZeroMorph = ZeroMorphProver_; + using Shplemini = ShpleminiProver_; using Shplonk = ShplonkProver_; using OpeningClaim = ProverOpeningClaim; - // Execute the ZeroMorph protocol to produce a univariate opening claim for the multilinear evaluations produced by - // Sumcheck - auto multivariate_to_univariate_opening_claim = - ZeroMorph::prove(key->circuit_size, - key->polynomials.get_unshifted(), - key->polynomials.get_to_be_shifted(), - sumcheck_output.claimed_evaluations.get_unshifted(), - sumcheck_output.claimed_evaluations.get_shifted(), - sumcheck_output.challenge, - key->commitment_key, - transcript); + // 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 = Shplemini::prove(key->circuit_size, + key->polynomials.get_unshifted(), + key->polynomials.get_to_be_shifted(), + sumcheck_output.challenge, + key->commitment_key, + transcript); // Get the challenge at which we evaluate all transcript polynomials as univariates evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); @@ -164,22 +162,23 @@ void ECCVMProver::execute_pcs_rounds() // Construct the batched polynomial and batched evaluation to produce the batched opening claim Polynomial batched_univariate{ key->circuit_size }; FF batched_evaluation{ 0 }; - auto batching_scalar = FF(1); + FF batching_scalar = FF(1); for (auto [polynomial, eval] : zip_view(univariate_polynomials, univariate_evaluations)) { batched_univariate.add_scaled(polynomial, batching_scalar); batched_evaluation += eval * batching_scalar; batching_scalar *= ipa_batching_challenge; } - std::array opening_claims = { multivariate_to_univariate_opening_claim, - { .polynomial = batched_univariate, - .opening_pair = { evaluation_challenge_x, batched_evaluation } } }; + const OpeningClaim translation_opening_claim = { .polynomial = batched_univariate, + .opening_pair = { evaluation_challenge_x, batched_evaluation } }; + const std::array opening_claims = { multivariate_to_univariate_opening_claim, + translation_opening_claim }; // Reduce the opening claims to a single opening claim via Shplonk - const OpeningClaim batched_opening_claim = Shplonk::prove(key->commitment_key, opening_claims, transcript); + const OpeningClaim batch_opening_claim = Shplonk::prove(key->commitment_key, opening_claims, transcript); // Compute the opening proof for the batched opening claim with the univariate PCS - PCS::compute_opening_proof(key->commitment_key, batched_opening_claim, transcript); + PCS::compute_opening_proof(key->commitment_key, batch_opening_claim, transcript); // Produce another challenge passed as input to the translator verifier translation_batching_challenge_v = transcript->template get_challenge("Translation:batching_challenge"); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index a9a8d41491a..8ce5c467d0e 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -1,5 +1,4 @@ #pragma once -#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" #include "barretenberg/eccvm/eccvm_flavor.hpp" #include "barretenberg/goblin/translation_evaluations.hpp" #include "barretenberg/honk/proof_system/types/proof.hpp" @@ -24,7 +23,6 @@ class ECCVMProver { using CommitmentLabels = typename Flavor::CommitmentLabels; using Transcript = typename Flavor::Transcript; using TranslationEvaluations = bb::TranslationEvaluations_; - using ZeroMorph = ZeroMorphProver_; using CircuitBuilder = typename Flavor::CircuitBuilder; explicit ECCVMProver(CircuitBuilder& builder, diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 9fb878c044c..fde6b109669 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -151,15 +151,21 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "rho"); round++; - for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { + for (size_t i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { + std::string idx = std::to_string(i); + manifest_expected.add_entry(round, "Gemini:FOLD_" + idx, frs_per_G); + } + manifest_expected.add_challenge(round, "Gemini:r"); + round++; + for (size_t i = 1; i <= CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); - manifest_expected.add_entry(round, "ZM:C_q_" + idx, frs_per_G); + manifest_expected.add_entry(round, "Gemini:a_" + idx, frs_per_Fr); } - manifest_expected.add_challenge(round, "ZM:y"); + manifest_expected.add_challenge(round, "Shplonk:nu"); round++; - manifest_expected.add_entry(round, "ZM:C_q", frs_per_G); - manifest_expected.add_challenge(round, "ZM:x", "ZM:z"); + manifest_expected.add_entry(round, "Shplonk:Q", frs_per_G); + manifest_expected.add_challenge(round, "Shplonk:z"); round++; manifest_expected.add_challenge(round, "Translation:evaluation_challenge_x"); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index c7bbd7ec456..46f6fe06459 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -1,6 +1,6 @@ #include "./eccvm_verifier.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" -#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" namespace bb { @@ -11,8 +11,9 @@ namespace bb { bool ECCVMVerifier::verify_proof(const HonkProof& proof) { using Curve = typename Flavor::Curve; - using ZeroMorph = ZeroMorphVerifier_; + using Shplemini = ShpleminiVerifier_; using Shplonk = ShplonkVerifier_; + using OpeningClaim = OpeningClaim; RelationParameters relation_parameters; transcript = std::make_shared(proof); @@ -60,16 +61,21 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof) return false; } - // Reduce the multivariate evaluation claims produced by sumcheck to a single univariate opening claim - auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(circuit_size, - commitments.get_unshifted(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - key->pcs_verification_key->get_g1_identity(), - transcript); - // Execute transcript consistency univariate opening round + // Compute the Shplemini accumulator consisting of the Shplonk evaluation and the commitments and scalars vector + // produced by the unified protocol + const BatchOpeningClaim sumcheck_batch_opening_claims = + Shplemini::compute_batch_opening_claim(circuit_size, + commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + key->pcs_verification_key->get_g1_identity(), + transcript); + + // Reduce the accumulator to a single opening claim + const OpeningClaim multivariate_to_univariate_opening_claim = + PCS::reduce_batch_opening_claim(sumcheck_batch_opening_claims); const FF evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); @@ -101,15 +107,18 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof) batching_scalar *= ipa_batching_challenge; } - std::array, 2> opening_claims = { multivariate_to_univariate_opening_claim, - { { evaluation_challenge_x, batched_transcript_eval }, - batched_commitment } }; + const OpeningClaim translation_opening_claim = { { evaluation_challenge_x, batched_transcript_eval }, + batched_commitment }; + + const std::array opening_claims = { multivariate_to_univariate_opening_claim, + translation_opening_claim }; // Construct and verify the combined opening claim - auto batched_opening_claim = + const OpeningClaim batch_opening_claim = Shplonk::reduce_verification(key->pcs_verification_key->get_g1_identity(), opening_claims, transcript); - bool batched_opening_verified = PCS::reduce_verify(key->pcs_verification_key, batched_opening_claim, transcript); + const bool batched_opening_verified = + PCS::reduce_verify(key->pcs_verification_key, batch_opening_claim, transcript); return sumcheck_verified.value() && batched_opening_verified; } 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 b190110ef8f..7699e4d4bcb 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 @@ -1,6 +1,6 @@ #include "./eccvm_recursive_verifier.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" -#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" #include "barretenberg/transcript/transcript.hpp" @@ -19,8 +19,9 @@ ECCVMRecursiveVerifier_::ECCVMRecursiveVerifier_( template void ECCVMRecursiveVerifier_::verify_proof(const HonkProof& proof) { using Curve = typename Flavor::Curve; - using ZeroMorph = ZeroMorphVerifier_; + using Shplemini = ShpleminiVerifier_; using Shplonk = ShplonkVerifier_; + using OpeningClaim = OpeningClaim; RelationParameters relation_parameters; @@ -72,14 +73,20 @@ template void ECCVMRecursiveVerifier_::verify_proof(co auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); - auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(circuit_size, - commitments.get_unshifted(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - key->pcs_verification_key->get_g1_identity(), - transcript); + // Compute the Shplemini accumulator consisting of the Shplonk evaluation and the commitments and scalars vector + // produced by the unified protocol + const BatchOpeningClaim sumcheck_batch_opening_claims = + Shplemini::compute_batch_opening_claim(circuit_size, + commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + key->pcs_verification_key->get_g1_identity(), + transcript); + // Reduce the accumulator to a single opening claim + const OpeningClaim multivariate_to_univariate_opening_claim = + PCS::reduce_batch_opening_claim(sumcheck_batch_opening_claims); const FF evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); @@ -112,16 +119,17 @@ template void ECCVMRecursiveVerifier_::verify_proof(co const Commitment batched_commitment = Commitment::batch_mul(transcript_commitments, batching_challenges); // Construct and verify the combined opening claim - OpeningClaim batched_univariate_claim = { { evaluation_challenge_x, batched_transcript_eval }, + const OpeningClaim translation_opening_claim = { { evaluation_challenge_x, batched_transcript_eval }, batched_commitment }; - std::array, 2> opening_claims = { multivariate_to_univariate_opening_claim, - batched_univariate_claim }; + const std::array opening_claims = { multivariate_to_univariate_opening_claim, + translation_opening_claim }; - auto batched_opening_claim = + const OpeningClaim batch_opening_claim = Shplonk::reduce_verification(key->pcs_verification_key->get_g1_identity(), opening_claims, transcript); - auto batched_opening_verified = PCS::reduce_verify(key->pcs_verification_key, batched_opening_claim, transcript); + const auto batched_opening_verified = + PCS::reduce_verify(key->pcs_verification_key, batch_opening_claim, transcript); ASSERT(sumcheck_verified && batched_opening_verified); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp index 87987906387..f26754acfeb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bool/bool.test.cpp @@ -13,6 +13,8 @@ using namespace bb; +#pragma GCC diagnostic ignored "-Wunused-const-variable" + namespace { auto& engine = numeric::get_debug_randomness(); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp index 25c7700b9b1..1df95fb7be9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp @@ -11,6 +11,7 @@ using namespace bb; #pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#pragma GCC diagnostic ignored "-Wunused-const-variable" #define STDLIB_TYPE_ALIASES \ using Builder = TypeParam; \ diff --git a/barretenberg/cpp/srs_db/Earthfile b/barretenberg/cpp/srs_db/Earthfile index 5ccba0b6d67..13d6401131e 100644 --- a/barretenberg/cpp/srs_db/Earthfile +++ b/barretenberg/cpp/srs_db/Earthfile @@ -6,7 +6,7 @@ RUN apt-get update && apt-get install -y curl build: WORKDIR /usr/src COPY ./*.sh . - RUN ./download_ignition.sh 3 + RUN ./download_ignition.sh 4 RUN ./download_grumpkin.sh # export srs-db for runners SAVE ARTIFACT ignition ignition