Skip to content

Commit

Permalink
feat: Replace Zeromorph with Shplemini in ECCVM (#9102)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
maramihali authored Oct 15, 2024
1 parent b259f33 commit c857cd9
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ template <typename Curve_> 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ template <typename Curve> class ShplonkProver_ {
*/
template <typename Transcript>
static ProverOpeningClaim<Curve> prove(const std::shared_ptr<CommitmentKey<Curve>>& commitment_key,
std::span<ProverOpeningClaim<Curve>> opening_claims,
std::span<const ProverOpeningClaim<Curve>> opening_claims,
const std::shared_ptr<Transcript>& transcript)
{
const Fr nu = transcript->template get_challenge<Fr>("Shplonk:nu");
Expand Down
26 changes: 16 additions & 10 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -935,14 +935,15 @@ class ECCVMFlavor {
Commitment lookup_inverses_comm;
std::vector<bb::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>> sumcheck_univariates;
std::array<FF, NUM_ALL_ENTITIES> sumcheck_evaluations;
std::vector<Commitment> zm_cq_comms;
Commitment zm_cq_comm;
std::vector<Commitment> gemini_fold_comms;
std::vector<FF> 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<Commitment> ipa_l_comms;
std::vector<Commitment> ipa_r_comms;
Expand Down Expand Up @@ -1143,11 +1144,13 @@ class ECCVMFlavor {
}
sumcheck_evaluations = NativeTranscript::template deserialize_from_buffer<std::array<FF, NUM_ALL_ENTITIES>>(
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<Commitment>(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<Commitment>(proof_data, num_frs_read));
gemini_fold_evals.push_back(deserialize_from_buffer<FF>(proof_data, num_frs_read));
}
zm_cq_comm = NativeTranscript::template deserialize_from_buffer<Commitment>(proof_data, num_frs_read);
shplonk_q_comm = deserialize_from_buffer<Commitment>(proof_data, num_frs_read);

translation_eval_op =
NativeTranscript::template deserialize_from_buffer<FF>(NativeTranscript::proof_data, num_frs_read);
Expand All @@ -1160,7 +1163,7 @@ class ECCVMFlavor {
translation_eval_z2 =
NativeTranscript::template deserialize_from_buffer<FF>(NativeTranscript::proof_data, num_frs_read);

shplonk_q_comm = NativeTranscript::template deserialize_from_buffer<Commitment>(proof_data, num_frs_read);
shplonk_q2_comm = NativeTranscript::template deserialize_from_buffer<Commitment>(proof_data, num_frs_read);

ipa_poly_degree = NativeTranscript::template deserialize_from_buffer<uint32_t>(NativeTranscript::proof_data,
num_frs_read);
Expand Down Expand Up @@ -1286,18 +1289,21 @@ 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);
NativeTranscript::template serialize_to_buffer(translation_eval_py, NativeTranscript::proof_data);
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<size_t>(numeric::get_msb(ipa_poly_degree));
Expand Down
35 changes: 17 additions & 18 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -113,21 +114,18 @@ void ECCVMProver::execute_relation_check_rounds()
void ECCVMProver::execute_pcs_rounds()
{
using Curve = typename Flavor::Curve;
using ZeroMorph = ZeroMorphProver_<Curve>;
using Shplemini = ShpleminiProver_<Curve>;
using Shplonk = ShplonkProver_<Curve>;
using OpeningClaim = ProverOpeningClaim<Curve>;

// 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<FF>("Translation:evaluation_challenge_x");
Expand Down Expand Up @@ -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<OpeningClaim, 2> 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<OpeningClaim, 2> 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<FF>("Translation:batching_challenge");
Expand Down
2 changes: 0 additions & 2 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -24,7 +23,6 @@ class ECCVMProver {
using CommitmentLabels = typename Flavor::CommitmentLabels;
using Transcript = typename Flavor::Transcript;
using TranslationEvaluations = bb::TranslationEvaluations_<FF, BF>;
using ZeroMorph = ZeroMorphProver_<PCS>;
using CircuitBuilder = typename Flavor::CircuitBuilder;

explicit ECCVMProver(CircuitBuilder& builder,
Expand Down
16 changes: 11 additions & 5 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
43 changes: 26 additions & 17 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -11,8 +11,9 @@ namespace bb {
bool ECCVMVerifier::verify_proof(const HonkProof& proof)
{
using Curve = typename Flavor::Curve;
using ZeroMorph = ZeroMorphVerifier_<Curve>;
using Shplemini = ShpleminiVerifier_<Curve>;
using Shplonk = ShplonkVerifier_<Curve>;
using OpeningClaim = OpeningClaim<Curve>;

RelationParameters<FF> relation_parameters;
transcript = std::make_shared<Transcript>(proof);
Expand Down Expand Up @@ -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<Curve> 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<FF>("Translation:evaluation_challenge_x");

Expand Down Expand Up @@ -101,15 +107,18 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof)
batching_scalar *= ipa_batching_challenge;
}

std::array<OpeningClaim<Curve>, 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<OpeningClaim, 2> 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;
}
Expand Down
Loading

0 comments on commit c857cd9

Please sign in to comment.