Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: eccvm sumcheck with commitments to round univariates #11206

Merged
merged 32 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
9a71a91
eccvm sumcheck butchered
iakovenkos Jan 10, 2025
1b18f05
wip wip
iakovenkos Jan 10, 2025
e00dd04
eccvm verifies
iakovenkos Jan 14, 2025
682c075
build fixed recursion failing
iakovenkos Jan 14, 2025
af6d6e6
debugging rec verifier
iakovenkos Jan 14, 2025
9323abe
recursion fix
iakovenkos Jan 14, 2025
230ce10
sumcheck output unified
iakovenkos Jan 14, 2025
f1eb3c5
remove self reduce
iakovenkos Jan 15, 2025
8cb98b0
trying to constify eccvm recursive
iakovenkos Jan 15, 2025
806ef49
Merge branch 'master' into si/fixing-eccvm-zk-sumcheck
iakovenkos Jan 16, 2025
41654f3
Merge branch 'master' into si/fixing-eccvm-zk-sumcheck
iakovenkos Jan 16, 2025
c91f533
build fix
iakovenkos Jan 16, 2025
e1d1d11
Merge branch 'si/fixing-eccvm-zk-sumcheck' of github.com:AztecProtoco…
iakovenkos Jan 16, 2025
7c73666
tests fixed
iakovenkos Jan 16, 2025
f525ef2
Merge branch 'master' into si/fixing-eccvm-zk-sumcheck
iakovenkos Jan 16, 2025
6aec0f7
commited sumcheck test added
iakovenkos Jan 17, 2025
74cd1a8
test cleaned up
iakovenkos Jan 17, 2025
f53a308
creating test for pcs
iakovenkos Jan 17, 2025
2f1f99d
Merge branch 'si/fixing-eccvm-zk-sumcheck' of github.com:AztecProtoco…
iakovenkos Jan 17, 2025
35df724
Merge branch 'master' into si/fixing-eccvm-zk-sumcheck
iakovenkos Jan 17, 2025
f4c3dc8
shplemini test + clean-up + figuring out constness
iakovenkos Jan 18, 2025
1587941
const proof size + clean up + docs
iakovenkos Jan 20, 2025
e94c031
eccvm bench correction
iakovenkos Jan 20, 2025
9e5e4e7
build fix
iakovenkos Jan 20, 2025
51b3766
Merge branch 'master' into si/fixing-eccvm-zk-sumcheck
iakovenkos Jan 20, 2025
6731c5d
more clean-up
iakovenkos Jan 20, 2025
fc108a3
Merge branch 'si/fixing-eccvm-zk-sumcheck' of github.com:AztecProtoco…
iakovenkos Jan 20, 2025
80b6bf0
Merge branch 'master' into si/fixing-eccvm-zk-sumcheck
iakovenkos Jan 20, 2025
48a1a18
eccvm recursive failure tests fixed
iakovenkos Jan 20, 2025
fdb62f1
bug fix
iakovenkos Jan 20, 2025
4a3f07b
resolving comments
iakovenkos Jan 21, 2025
98d304f
killed optional bool in sumcheck output + resolving comments
iakovenkos Jan 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ void eccvm_prove(State& state) noexcept
};
}

BENCHMARK(eccvm_generate_prover)->Unit(kMillisecond)->DenseRange(12, 18);
BENCHMARK(eccvm_prove)->Unit(kMillisecond)->DenseRange(12, 18);
BENCHMARK(eccvm_generate_prover)->Unit(kMillisecond)->DenseRange(12, CONST_ECCVM_LOG_N);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was hitting an assert in ipa

BENCHMARK(eccvm_prove)->Unit(kMillisecond)->DenseRange(12, CONST_ECCVM_LOG_N);
} // namespace

BENCHMARK_MAIN();
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShiftAndConcatenation)
&consistency_checked,
/* libra commitments = */ {},
/* libra evaluations = */ {},
{},
{},
to_vector_of_ref_vectors(concatenation_groups_commitments),
RefVector(c_evaluations));
const auto pairing_points = KZG::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript);
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "barretenberg/commitment_schemes/utils/instance_witness_generator.hpp"
#include "barretenberg/commitment_schemes/utils/test_settings.hpp"
#include "barretenberg/ecc/curves/bn254/g1.hpp"
#include "barretenberg/sumcheck/sumcheck.hpp"

#include <gtest/gtest.h>
#include <vector>
Expand All @@ -18,10 +19,53 @@ namespace bb {

template <class Flavor> class ShpleminiTest : public CommitmentTest<typename Flavor::Curve> {
public:
// Size of the test polynomials
static constexpr size_t n = 32;
static constexpr size_t log_n = 5;
// Total number of random polynomials in each test
static constexpr size_t num_polynomials = 5;
// Number of shiftable polynomials
static constexpr size_t num_shiftable = 2;

// The length of the mock sumcheck univariates.
static constexpr size_t sumcheck_univariate_length = 24;

using Fr = typename Flavor::Curve::ScalarField;
using GroupElement = typename Flavor::Curve::Element;
using Commitment = typename Flavor::Curve::AffineElement;
using CK = typename Flavor::CommitmentKey;

void compute_sumcheck_opening_data(std::vector<bb::Polynomial<Fr>>& round_univariates,
std::vector<Commitment>& sumcheck_commitments,
std::vector<std::array<Fr, 3>>& sumcheck_evaluations,
std::vector<Fr>& challenge,
std::shared_ptr<CK>& ck)
{
// Generate valid sumcheck polynomials of given length
auto mock_sumcheck_polynomials = ZKSumcheckData<Flavor>(log_n, sumcheck_univariate_length);
for (size_t idx = 0; idx < log_n; idx++) {
bb::Polynomial<Fr> round_univariate = mock_sumcheck_polynomials.libra_univariates[idx];

round_univariate.at(0) += mock_sumcheck_polynomials.libra_running_sum;

sumcheck_commitments.push_back(ck->commit(round_univariate));

sumcheck_evaluations.push_back({ round_univariate.at(0),
round_univariate.evaluate(Fr(1)),
round_univariate.evaluate(challenge[idx]) });

mock_sumcheck_polynomials.update_zk_sumcheck_data(challenge[idx], idx);
round_univariates.push_back(round_univariate);
}

// Simulate the `const proof size` logic
auto round_univariate = bb::Polynomial<Fr>(this->n);
for (size_t idx = this->log_n; idx < CONST_PROOF_SIZE_LOG_N; idx++) {
round_univariates.push_back(round_univariate);
sumcheck_commitments.push_back(ck->commit(round_univariate));
sumcheck_evaluations.push_back({ Fr(0), Fr(0), Fr(0) });
}
}
};

using TestSettings = ::testing::Types<BN254Settings, GrumpkinSettings>;
Expand Down Expand Up @@ -229,10 +273,10 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching)

/**
* @brief Test Shplemini with ZK data consisting of a hiding polynomial generated by GeminiProver and Libra polynomials
* used to mask Sumcheck Round Univariates.
* used to mask Sumcheck Round Univariates. This abstracts the PCS step in each ZK Flavor running over BN254.
*
*/
TYPED_TEST(ShpleminiTest, ShpleminiWithZK)
TYPED_TEST(ShpleminiTest, ShpleminiZKNoSumcheckOpenings)
{
using ZKData = ZKSumcheckData<TypeParam>;
using Curve = TypeParam::Curve;
Expand All @@ -259,8 +303,8 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK)
const_size_mle_opening_point.begin() + this->log_n);

// Generate random prover polynomials, compute their evaluations and commitments
auto pcs_instance_witness =
InstanceWitnessGenerator<Curve>(this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck);
InstanceWitnessGenerator<Curve> pcs_instance_witness(
this->n, this->num_polynomials, this->num_shiftable, mle_opening_point, ck);

// Compute the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges
const Fr claimed_inner_product = SmallSubgroupIPAProver<TypeParam>::compute_claimed_inner_product(
Expand All @@ -269,7 +313,7 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK)
prover_transcript->template send_to_verifier("Libra:claimed_evaluation", claimed_inner_product);

// Instantiate SmallSubgroupIPAProver, this prover sends commitments to Big Sum and Quotient polynomials
auto small_subgroup_ipa_prover = SmallSubgroupIPAProver<TypeParam>(
SmallSubgroupIPAProver<TypeParam> small_subgroup_ipa_prover(
zk_sumcheck_data, const_size_mle_opening_point, claimed_inner_product, prover_transcript, ck);

// Reduce to KZG or IPA based on the curve used in the test Flavor
Expand Down Expand Up @@ -341,4 +385,116 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithZK)
}
}

/**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, we need more granular tests for all zk methods in Shplemini, but this one covers the situation we currently have in ECCVM

* @brief Test Shplemini with ZK data consisting of a hiding polynomial generated by GeminiProver, Libra polynomials
* used to mask Sumcheck Round Univariates and prove/verify the claimed evaluations of committed sumcheck round
* univariates. This test abstracts the PCS step in each ZK Flavor running over Grumpkin.
*
*/
TYPED_TEST(ShpleminiTest, ShpleminiZKWithSumcheckOpenings)
{
using Curve = TypeParam::Curve;
using Fr = typename Curve::ScalarField;
using Commitment = typename Curve::AffineElement;
using CK = typename TypeParam::CommitmentKey;

using ShpleminiProver = ShpleminiProver_<Curve>;
using ShpleminiVerifier = ShpleminiVerifier_<Curve>;

std::shared_ptr<CK> ck = create_commitment_key<CK>(4096);

// Generate Sumcheck challenge, current implementation of Sumcheck Round Univariates batching in Shplemini assumes
// that the challenge is of CONST_PROOF_SIZE_LOG_N
std::vector<Fr> challenge = this->random_evaluation_point(CONST_PROOF_SIZE_LOG_N);

auto prover_transcript = TypeParam::Transcript::prover_init_empty();

// Generate masking polynomials for Sumcheck Round Univariates
ZKSumcheckData<TypeParam> zk_sumcheck_data(this->log_n, prover_transcript, ck);
// Generate mock witness
InstanceWitnessGenerator<Curve> pcs_instance_witness(this->n, 1);

// Generate valid sumcheck polynomials of given length
pcs_instance_witness.template compute_sumcheck_opening_data<TypeParam>(
this->n, this->log_n, this->sumcheck_univariate_length, challenge, ck);

// Compute the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges
const Fr claimed_inner_product =
SmallSubgroupIPAProver<TypeParam>::compute_claimed_inner_product(zk_sumcheck_data, challenge, this->log_n);

prover_transcript->template send_to_verifier("Libra:claimed_evaluation", claimed_inner_product);

// Instantiate SmallSubgroupIPAProver, this prover sends commitments to Big Sum and Quotient polynomials
SmallSubgroupIPAProver<TypeParam> small_subgroup_ipa_prover(
zk_sumcheck_data, challenge, claimed_inner_product, prover_transcript, ck);

// Reduce proving to a single claimed fed to KZG or IPA
const auto opening_claim = ShpleminiProver::prove(this->n,
RefVector(pcs_instance_witness.unshifted_polynomials),
RefVector(pcs_instance_witness.to_be_shifted_polynomials),
challenge,
ck,
prover_transcript,
small_subgroup_ipa_prover.get_witness_polynomials(),
pcs_instance_witness.round_univariates,
pcs_instance_witness.sumcheck_evaluations);

if constexpr (std::is_same_v<TypeParam, GrumpkinSettings>) {
IPA<Curve>::compute_opening_proof(this->ck(), opening_claim, prover_transcript);
} else {
KZG<Curve>::compute_opening_proof(this->ck(), opening_claim, prover_transcript);
}

// Initialize verifier's transcript
auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);

std::array<Commitment, NUM_LIBRA_COMMITMENTS> libra_commitments = {};
libra_commitments[0] =
verifier_transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");

// Place Libra data to the transcript
const Fr libra_total_sum = verifier_transcript->template receive_from_prover<Fr>("Libra:Sum");
const Fr libra_challenge = verifier_transcript->template get_challenge<Fr>("Libra:Challenge");
const Fr libra_evaluation = verifier_transcript->template receive_from_prover<Fr>("Libra:claimed_evaluation");

// Check that transcript is consistent
EXPECT_EQ(libra_total_sum, zk_sumcheck_data.libra_total_sum);
EXPECT_EQ(libra_challenge, zk_sumcheck_data.libra_challenge);
EXPECT_EQ(libra_evaluation, claimed_inner_product);

// Finalize the array of Libra/SmallSubgroupIpa commitments
libra_commitments[1] = verifier_transcript->template receive_from_prover<Commitment>("Libra:big_sum_commitment");
libra_commitments[2] = verifier_transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");

bool consistency_checked = true;

// Run Shplemini
const auto batch_opening_claim =
ShpleminiVerifier::compute_batch_opening_claim(this->n,
RefVector(pcs_instance_witness.unshifted_commitments),
{},
RefVector(pcs_instance_witness.unshifted_evals),
{},
challenge,
this->vk()->get_g1_identity(),
verifier_transcript,
{},
true,
&consistency_checked,
libra_commitments,
libra_evaluation,
pcs_instance_witness.sumcheck_commitments,
pcs_instance_witness.sumcheck_evaluations);
// Verify claim using KZG or IPA
if constexpr (std::is_same_v<TypeParam, GrumpkinSettings>) {
auto result =
IPA<Curve>::reduce_verify_batch_opening_claim(batch_opening_claim, this->vk(), verifier_transcript);
EXPECT_EQ(result, true);
} else {
const auto pairing_points =
KZG<Curve>::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
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ template <typename Curve> class ShplonkProver_ {
*/
static Polynomial compute_batched_quotient(std::span<const ProverOpeningClaim<Curve>> opening_claims,
const Fr& nu,
std::span<const ProverOpeningClaim<Curve>> libra_opening_claims)
std::span<const ProverOpeningClaim<Curve>> libra_opening_claims,
std::span<const ProverOpeningClaim<Curve>> sumcheck_round_claims)
{
// Find n, the maximum size of all polynomials fⱼ(X)
size_t max_poly_size{ 0 };
Expand Down Expand Up @@ -86,6 +87,18 @@ template <typename Curve> class ShplonkProver_ {
Q.add_scaled(tmp, current_nu);
current_nu *= nu;
}

for (const auto& claim : sumcheck_round_claims) {

// Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ )
tmp = claim.polynomial;
tmp.at(0) = tmp[0] - claim.opening_pair.evaluation;
tmp.factor_roots(claim.opening_pair.challenge);

// Add the claim quotient to the batched quotient polynomial
Q.add_scaled(tmp, current_nu);
current_nu *= nu;
}
// Return batched quotient polynomial Q(X)
return Q;
};
Expand All @@ -105,7 +118,8 @@ template <typename Curve> class ShplonkProver_ {
Polynomial& batched_quotient_Q,
const Fr& nu_challenge,
const Fr& z_challenge,
std::span<const ProverOpeningClaim<Curve>> libra_opening_claims = {})
std::span<const ProverOpeningClaim<Curve>> libra_opening_claims = {},
std::span<const ProverOpeningClaim<Curve>> sumcheck_opening_claims = {})
{
const size_t num_opening_claims = opening_claims.size();

Expand All @@ -120,6 +134,11 @@ template <typename Curve> class ShplonkProver_ {
for (const auto& claim : libra_opening_claims) {
inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
}

for (const auto& claim : sumcheck_opening_claims) {
inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
}

Fr::batch_invert(inverse_vanishing_evals);

// G(X) = Q(X) - Q_z(X) = Q(X) - ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( z − xⱼ ),
Expand Down Expand Up @@ -160,6 +179,17 @@ template <typename Curve> class ShplonkProver_ {
idx++;
current_nu *= nu_challenge;
}

for (const auto& claim : sumcheck_opening_claims) {
tmp = claim.polynomial;
tmp.at(0) = tmp[0] - claim.opening_pair.evaluation;
Fr scaling_factor = current_nu * inverse_vanishing_evals[idx]; // = νʲ / (z − xⱼ )

// Add the claim quotient to the batched quotient polynomial
G.add_scaled(tmp, -scaling_factor);
idx++;
current_nu *= nu_challenge;
}
// Return opening pair (z, 0) and polynomial G(X) = Q(X) - Q_z(X)
return { .polynomial = G, .opening_pair = { .challenge = z_challenge, .evaluation = Fr::zero() } };
};
Expand All @@ -177,15 +207,17 @@ template <typename Curve> class ShplonkProver_ {
static ProverOpeningClaim<Curve> prove(const std::shared_ptr<CommitmentKey<Curve>>& commitment_key,
std::span<const ProverOpeningClaim<Curve>> opening_claims,
const std::shared_ptr<Transcript>& transcript,
std::span<const ProverOpeningClaim<Curve>> libra_opening_claims = {})
std::span<const ProverOpeningClaim<Curve>> libra_opening_claims = {},
std::span<const ProverOpeningClaim<Curve>> sumcheck_round_claims = {})
{
const Fr nu = transcript->template get_challenge<Fr>("Shplonk:nu");
auto batched_quotient = compute_batched_quotient(opening_claims, nu, libra_opening_claims);
auto batched_quotient =
compute_batched_quotient(opening_claims, nu, libra_opening_claims, sumcheck_round_claims);
auto batched_quotient_commitment = commitment_key->commit(batched_quotient);
transcript->send_to_verifier("Shplonk:Q", batched_quotient_commitment);
const Fr z = transcript->template get_challenge<Fr>("Shplonk:z");
return compute_partially_evaluated_batched_quotient(
opening_claims, batched_quotient, nu, z, libra_opening_claims);
opening_claims, batched_quotient, nu, z, libra_opening_claims, sumcheck_round_claims);
}
};

Expand Down
Loading
Loading