-
Notifications
You must be signed in to change notification settings - Fork 310
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: fix commitments and openings of masking polynomials used in zk sumcheck #10773
Changes from 31 commits
cee04ed
b859440
ff70d41
109ac5f
e986228
77c386a
0e9a384
d0f2dde
31505cf
2986222
4577e05
d35feb5
c9d43c6
559626c
48ca947
29f6de7
c37a3fc
000347e
537f268
ad60e4a
e11702b
cfd31c1
63a855b
be153e6
20e8b53
59d485f
ee6f31d
2208253
398f7de
6ab449b
c7ea181
6e03b63
90b7cde
ce8e47d
b13eb0b
3c84180
7231860
40792a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,8 +3,10 @@ | |
#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" | ||
#include "barretenberg/transcript/transcript.hpp" | ||
|
||
namespace bb { | ||
|
@@ -28,13 +30,12 @@ template <typename Curve> class ShpleminiProver_ { | |
std::span<FF> multilinear_challenge, | ||
const std::shared_ptr<CommitmentKey<Curve>>& commitment_key, | ||
const std::shared_ptr<Transcript>& transcript, | ||
const std::vector<bb::Univariate<FF, LENGTH>>& libra_univariates = {}, | ||
const std::vector<FF>& libra_evaluations = {}, | ||
const std::array<Polynomial, NUM_LIBRA_EVALUATIONS>& libra_polynomials = {}, | ||
RefSpan<Polynomial> concatenated_polynomials = {}, | ||
const std::vector<RefVector<Polynomial>>& 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_polynomials[0].size() > 0); | ||
std::vector<OpeningClaim> opening_claims = GeminiProver::prove(circuit_size, | ||
f_polynomials, | ||
g_polynomials, | ||
|
@@ -46,15 +47,25 @@ template <typename Curve> class ShpleminiProver_ { | |
has_zk); | ||
// Create opening claims for Libra masking univariates | ||
std::vector<OpeningClaim> libra_opening_claims; | ||
size_t idx = 0; | ||
for (auto [libra_univariate, libra_evaluation] : zip_view(libra_univariates, libra_evaluations)) { | ||
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++; | ||
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<std::string, NUM_LIBRA_EVALUATIONS> libra_eval_labels = { | ||
"Libra:concatenation_eval", "Libra:shifted_big_sum_eval", "Libra:big_sum_eval", "Libra:quotient_eval" | ||
}; | ||
const std::array<FF, 4> 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 = | ||
ShplonkProver::prove(commitment_key, opening_claims, transcript, libra_opening_claims); | ||
return batched_claim; | ||
|
@@ -134,13 +145,14 @@ template <typename Curve> class ShpleminiVerifier_ { | |
const Commitment& g1_identity, | ||
const std::shared_ptr<Transcript>& transcript, | ||
const RepeatedCommitmentsData& repeated_commitments = {}, | ||
RefSpan<Commitment> libra_univariate_commitments = {}, | ||
const std::vector<Fr>& libra_univariate_evaluations = {}, | ||
const bool has_zk = false, | ||
bool* consistency_checked = nullptr, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this way, could keep it as an optional argument without polluting AVM There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why bool pointer? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue added |
||
const std::array<Commitment, NUM_LIBRA_COMMITMENTS>& libra_commitments = {}, | ||
const Fr& libra_univariate_evaluation = Fr{ 0 }, | ||
const std::vector<RefVector<Commitment>>& concatenation_group_commitments = {}, | ||
RefSpan<Fr> concatenated_evaluations = {}) | ||
|
||
{ | ||
|
||
// Extract log_circuit_size | ||
size_t log_circuit_size{ 0 }; | ||
if constexpr (Curve::is_stdlib_type) { | ||
|
@@ -152,7 +164,6 @@ template <typename Curve> 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(); | ||
Commitment hiding_polynomial_commitment; | ||
if (has_zk) { | ||
hiding_polynomial_commitment = | ||
|
@@ -176,14 +187,22 @@ template <typename Curve> class ShpleminiVerifier_ { | |
const std::vector<Fr> gemini_eval_challenge_powers = | ||
gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, CONST_PROOF_SIZE_LOG_N); | ||
|
||
std::array<Fr, NUM_LIBRA_EVALUATIONS> libra_evaluations; | ||
if (has_zk) { | ||
libra_evaluations[0] = transcript->template receive_from_prover<Fr>("Libra:concatenation_eval"); | ||
libra_evaluations[1] = transcript->template receive_from_prover<Fr>("Libra:shifted_big_sum_eval"); | ||
libra_evaluations[2] = transcript->template receive_from_prover<Fr>("Libra:big_sum_eval"); | ||
libra_evaluations[3] = transcript->template receive_from_prover<Fr>("Libra:quotient_eval"); | ||
} | ||
|
||
// Process Shplonk transcript data: | ||
// - Get Shplonk batching challenge | ||
const Fr shplonk_batching_challenge = transcript->template get_challenge<Fr>("Shplonk:nu"); | ||
// - Get the quotient commitment for the Shplonk batching of Gemini opening claims | ||
const auto Q_commitment = transcript->template receive_from_prover<Commitment>("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<Commitment> commitments{ Q_commitment }; | ||
|
||
// Get Shplonk opening point z | ||
|
@@ -297,11 +316,14 @@ template <typename Curve> class ShpleminiVerifier_ { | |
if (has_zk) { | ||
add_zk_data(commitments, | ||
scalars, | ||
libra_univariate_commitments, | ||
libra_univariate_evaluations, | ||
multivariate_challenge, | ||
libra_commitments, | ||
libra_evaluations, | ||
gemini_evaluation_challenge, | ||
shplonk_batching_challenge, | ||
shplonk_evaluation_challenge); | ||
|
||
*consistency_checked = SmallSubgroupIPAVerifier<Curve>::check_evaluations_consistency( | ||
libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation); | ||
} | ||
|
||
return { commitments, scalars, shplonk_evaluation_challenge }; | ||
|
@@ -352,8 +374,8 @@ template <typename Curve> 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. | ||
*/ | ||
|
@@ -402,8 +424,8 @@ template <typename Curve> 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 | ||
iakovenkos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// 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(); | ||
|
@@ -588,17 +610,17 @@ template <typename Curve> class ShpleminiVerifier_ { | |
* | ||
* @param commitments | ||
* @param scalars | ||
* @param libra_univariate_commitments | ||
* @param libra_commitments | ||
* @param libra_univariate_evaluations | ||
* @param multivariate_challenge | ||
* @param shplonk_batching_challenge | ||
* @param shplonk_evaluation_challenge | ||
*/ | ||
static void add_zk_data(std::vector<Commitment>& commitments, | ||
std::vector<Fr>& scalars, | ||
RefSpan<Commitment> libra_univariate_commitments, | ||
const std::vector<Fr>& libra_univariate_evaluations, | ||
const std::vector<Fr>& multivariate_challenge, | ||
const std::array<Commitment, NUM_LIBRA_COMMITMENTS>& libra_commitments, | ||
const std::array<Fr, NUM_LIBRA_EVALUATIONS>& libra_evaluations, | ||
const Fr& gemini_evaluation_challenge, | ||
const Fr& shplonk_batching_challenge, | ||
const Fr& shplonk_evaluation_challenge) | ||
|
||
|
@@ -611,32 +633,35 @@ template <typename Curve> 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 | ||
std::vector<Fr> 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); | ||
} | ||
// 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)) { | ||
commitments.push_back(std::move(libra_univariate_commitment)); | ||
Fr scaling_factor = denominator * shplonk_challenge_power; | ||
scalars.push_back((-scaling_factor)); | ||
for (size_t idx = 0; idx < libra_commitments.size(); idx++) { | ||
iakovenkos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
commitments.push_back(libra_commitments[idx]); | ||
} | ||
|
||
std::array<Fr, NUM_LIBRA_EVALUATIONS> denominators; | ||
std::array<Fr, NUM_LIBRA_EVALUATIONS> batching_scalars; | ||
// compute Shplonk denominators and invert them | ||
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 (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; | ||
// update the constant term of the Shplonk batched claim | ||
constant_term += scaling_factor * libra_univariate_evaluation; | ||
constant_term += scaling_factor * libra_evaluations[idx]; | ||
} | ||
|
||
// 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we batch the prover's opening claims from SmallSubgroupIPA