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: ZM updates for Translator concatenated polys #3343

Merged
merged 10 commits into from
Nov 17, 2023
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once
#include "barretenberg/common/zip_view.hpp"
#include "barretenberg/polynomials/polynomial.hpp"

namespace proof_system::honk::pcs::zeromorph {

/**
Expand Down Expand Up @@ -188,7 +188,7 @@ template <typename Curve> class ZeroMorphProver_ {
*
* where f_batched = \sum_{i=0}^{m-1}\rho^i*f_i, g_batched = \sum_{i=0}^{l-1}\rho^{m+i}*g_i
*
* and concatenation_term = \sum_{i=0}^{concatenation_index}(x^{i * min_N + 1}concatenation_groups_batched_{i})
* and concatenation_term = \sum_{i=0}^{num_chunks_per_group}(x^{i * min_N + 1}concatenation_groups_batched_{i})
*
* @note The concatenation term arises from an implementation detail in the Goblin Translator and is not part of the
* conventional ZM protocol
Expand Down Expand Up @@ -240,7 +240,7 @@ template <typename Curve> class ZeroMorphProver_ {
}

// If necessary, add to Z_x the contribution related to concatenated polynomials:
// \sum_{i=0}^{concatenation_index}(x^{i * min_n + 1}concatenation_groups_batched_{i}).
// \sum_{i=0}^{num_chunks_per_group}(x^{i * min_n + 1}concatenation_groups_batched_{i}).
// We are effectively reconstructing concatenated polynomials from their chunks now that we know x
// Note: this is an implementation detail related to Goblin Translator and is not part of the standard protocol.
if (!concatenation_groups_batched.empty()) {
Expand Down Expand Up @@ -314,18 +314,20 @@ template <typename Curve> class ZeroMorphProver_ {
*/
static void prove(const auto& f_polynomials,
const auto& g_polynomials,
auto& evaluations,
auto&& f_evaluations,
auto&& g_shift_evaluations,
auto& multilinear_challenge,
auto& commitment_key,
auto& transcript)
auto& transcript,
const std::vector<std::span<FF>>& concatenated_polynomials = {},
std::vector<FF>&& concatenated_evaluations = {},
const std::vector<std::vector<std::span<FF>>>& concatenation_groups = {})
{
// Generate batching challenge \rho and powers 1,...,\rho^{m-1}
FF rho = transcript.get_challenge("rho");
std::vector<FF> rhos = powers_of_challenge(rho, evaluations.size());

// Extract multilinear challenge u and claimed multilinear evaluations from Sumcheck output
std::span<FF> u_challenge = multilinear_challenge;
auto claimed_evaluations = evaluations.pointer_view();
size_t log_N = u_challenge.size();
size_t N = 1 << log_N;

Expand All @@ -337,24 +339,47 @@ template <typename Curve> class ZeroMorphProver_ {
// evaluations produced by sumcheck of h_i = g_i_shifted.
auto batched_evaluation = FF(0);
Polynomial f_batched(N); // batched unshifted polynomials
size_t poly_idx = 0; // TODO(#391) zip
for (auto& f_poly : f_polynomials) {
f_batched.add_scaled(f_poly, rhos[poly_idx]);
batched_evaluation += rhos[poly_idx] * (*claimed_evaluations[poly_idx]);
++poly_idx;
FF batching_scalar = FF(1);
for (auto [f_poly, f_eval] : zip_view(f_polynomials, f_evaluations)) {
f_batched.add_scaled(f_poly, batching_scalar);
batched_evaluation += batching_scalar * f_eval;
batching_scalar *= rho;
}

Polynomial g_batched(N); // batched to-be-shifted polynomials
for (auto& g_poly : g_polynomials) {
g_batched.add_scaled(g_poly, rhos[poly_idx]);
batched_evaluation += rhos[poly_idx] * (*claimed_evaluations[poly_idx]);
++poly_idx;
for (auto [g_poly, g_shift_eval] : zip_view(g_polynomials, g_shift_evaluations)) {
g_batched.add_scaled(g_poly, batching_scalar);
batched_evaluation += batching_scalar * g_shift_eval;
batching_scalar *= rho;
};

size_t num_groups = concatenation_groups.size();
size_t num_chunks_per_group = concatenation_groups.empty() ? 0 : concatenation_groups[0].size();
// Concatenated polynomials
// std::vector<Polynomial> concatenated_polynomials;
Polynomial concatenated_batched(N);

// construct concatention_groups_batched
std::vector<Polynomial> concatenation_groups_batched;
for (size_t i = 0; i < num_chunks_per_group; ++i) {
concatenation_groups_batched.push_back(Polynomial(N));
}
// for each group
for (size_t i = 0; i < num_groups; ++i) {
concatenated_batched.add_scaled(concatenated_polynomials[i], batching_scalar);
// for each element in a group
for (size_t j = 0; j < num_chunks_per_group; ++j) {
concatenation_groups_batched[j].add_scaled(concatenation_groups[i][j], batching_scalar);
}
batched_evaluation += batching_scalar * concatenated_evaluations[i];
batching_scalar *= rho;
}

// Compute the full batched polynomial f = f_batched + g_batched.shifted() = f_batched + h_batched. This is the
// polynomial for which we compute the quotients q_k and prove f(u) = v_batched.
auto f_polynomial = f_batched;
f_polynomial += g_batched.shifted();
f_polynomial += concatenated_batched;

// Compute the multilinear quotients q_k = q_k(X_0, ..., X_{k-1})
auto quotients = compute_multilinear_quotients(f_polynomial, u_challenge);
Expand Down Expand Up @@ -386,8 +411,13 @@ template <typename Curve> class ZeroMorphProver_ {
compute_partially_evaluated_degree_check_polynomial(batched_quotient, quotients, y_challenge, x_challenge);

// Compute ZeroMorph identity polynomial Z partially evaluated at x
auto Z_x = compute_partially_evaluated_zeromorph_identity_polynomial(
f_batched, g_batched, quotients, batched_evaluation, u_challenge, x_challenge);
auto Z_x = compute_partially_evaluated_zeromorph_identity_polynomial(f_batched,
g_batched,
quotients,
batched_evaluation,
u_challenge,
x_challenge,
concatenation_groups_batched);

// Compute batched degree-check and ZM-identity quotient polynomial pi
auto pi_polynomial =
Expand Down Expand Up @@ -468,7 +498,7 @@ template <typename Curve> class ZeroMorphVerifier_ {
* + concatentation_term
* where
*
* concatenation_term = \sum{i=0}^{o-1}\sum_{j=0}^{concatenation_index}(rho^{m+l+i} * x^{j * min_N + 1}
* concatenation_term = \sum{i=0}^{o-1}\sum_{j=0}^{num_chunks_per_group}(rho^{m+l+i} * x^{j * min_N + 1}
* * concatenation_groups_commitments_{i}_{j})
*
* @note The concatenation term arises from an implementation detail in the Goblin Translator and is not part of the
Expand All @@ -490,7 +520,7 @@ template <typename Curve> class ZeroMorphVerifier_ {
FF batched_evaluation,
FF x_challenge,
std::vector<FF> u_challenge,
std::vector<std::vector<Commitment>> concatenation_groups_commitments = {})
const std::vector<std::vector<Commitment>>& concatenation_groups_commitments = {})
{
size_t log_N = C_q_k.size();
size_t N = 1 << log_N;
Expand Down Expand Up @@ -600,23 +630,32 @@ template <typename Curve> class ZeroMorphVerifier_ {
* @param transcript
* @return std::array<Commitment, 2> Inputs to the final pairing check
*/
static std::array<Commitment, 2> verify(auto& commitments,
auto& claimed_evaluations,
static std::array<Commitment, 2> verify(auto&& unshifted_commitments,
auto&& to_be_shifted_commitments,
auto&& unshifted_evaluations,
auto&& shifted_evaluations,
auto& multivariate_challenge,
auto& transcript)
auto& transcript,
std::vector<std::vector<Commitment>>&& concatenation_group_commitments = {},
std::vector<FF>&& concatenated_evaluations = {})
{
size_t log_N = multivariate_challenge.size();
FF rho = transcript.get_challenge("rho");

// Compute powers of batching challenge rho
std::vector<FF> rhos = pcs::zeromorph::powers_of_challenge(rho, claimed_evaluations.size());

// Construct batched evaluation v = sum_{i=0}^{m-1}\rho^i*f_i(u) + sum_{i=0}^{l-1}\rho^{m+i}*h_i(u)
FF batched_evaluation = FF(0);
size_t evaluation_idx = 0;
for (auto& value : claimed_evaluations.get_unshifted_then_shifted()) {
batched_evaluation += value * rhos[evaluation_idx];
++evaluation_idx;
FF batching_scalar = FF(1);
for (auto& value : unshifted_evaluations) {
batched_evaluation += value * batching_scalar;
batching_scalar *= rho;
}
for (auto& value : shifted_evaluations) {
batched_evaluation += value * batching_scalar;
batching_scalar *= rho;
}
for (auto& value : concatenated_evaluations) {
batched_evaluation += value * batching_scalar;
batching_scalar *= rho;
}

// Receive commitments [q_k]
Expand All @@ -639,13 +678,14 @@ template <typename Curve> class ZeroMorphVerifier_ {
auto C_zeta_x = compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge);

// Compute commitment C_{Z_x}
Commitment C_Z_x = compute_C_Z_x(commitments.get_unshifted(),
commitments.get_to_be_shifted(),
Commitment C_Z_x = compute_C_Z_x(unshifted_commitments,
to_be_shifted_commitments,
C_q_k,
rho,
batched_evaluation,
x_challenge,
multivariate_challenge);
multivariate_challenge,
concatenation_group_commitments);

// Compute commitment C_{\zeta,Z}
auto C_zeta_Z = C_zeta_x + C_Z_x * z_challenge;
Expand Down
4 changes: 4 additions & 0 deletions barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,8 @@ class GoblinUltra {
return { table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, w_r_shift,
w_o_shift, w_4_shift, sorted_accum_shift, z_perm_shift, z_lookup_shift };
};
std::vector<HandleType> get_unshifted_then_shifted_then_special() { return {}; }
std::vector<HandleType> get_concatenated_constraints() { return {}; }
};

public:
Expand Down Expand Up @@ -539,6 +541,8 @@ class GoblinUltra {

class VerifierCommitments : public AllEntities<Commitment, CommitmentHandle> {
public:
static std::vector<std::vector<CommitmentHandle>> get_concatenation_groups() { return {}; }; // WORKTODO
Copy link
Contributor

Choose a reason for hiding this comment

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

WORKTODO: adding these when they're not used is a hack, added this to remind myself to look for a better way, maybe a requires. Do you see a way to improve or do you think just tech debt this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Turns out that moving the extraction of unshifted, shifted etc to outside of ZM made it easy to get rid of these since now they are only called from within the translator on input to prove and verify. Could add a concept but as long as no one trues to instantiate the Translator with say the Ultra flavor there's no issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

More accurately - they WILL only be called from the translator. Those calls don't exist in this branch but with these updates we're no longer instantiating any classes that need to call them with flavors that don't implement them.


VerifierCommitments(std::shared_ptr<VerificationKey> verification_key,
[[maybe_unused]] const BaseTranscript<FF>& transcript)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ template <typename BuilderType> class GoblinUltraRecursive_ {
return { table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, w_r_shift,
w_o_shift, w_4_shift, sorted_accum_shift, z_perm_shift, z_lookup_shift };
};
std::vector<HandleType> get_unshifted_then_shifted_then_special() { return {}; }
std::vector<HandleType> get_concatenated_constraints() { return {}; }
};

public:
Expand Down Expand Up @@ -529,6 +531,8 @@ template <typename BuilderType> class GoblinUltraRecursive_ {

class VerifierCommitments : public AllEntities<Commitment, CommitmentHandle> {
public:
std::vector<std::vector<CommitmentHandle>> get_concatenation_groups() { return {}; };

VerifierCommitments(std::shared_ptr<VerificationKey> verification_key)
{
this->q_m = verification_key->q_m;
Expand Down
4 changes: 4 additions & 0 deletions barretenberg/cpp/src/barretenberg/flavor/ultra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ class Ultra {
return { table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, w_r_shift,
w_o_shift, w_4_shift, sorted_accum_shift, z_perm_shift, z_lookup_shift };
};
std::vector<HandleType> get_concatenated_constraints() { return {}; }
std::vector<HandleType> get_unshifted_then_shifted_then_special() { return {}; }
};

public:
Expand Down Expand Up @@ -440,6 +442,8 @@ class Ultra {

class VerifierCommitments : public AllEntities<Commitment, CommitmentHandle> {
public:
static std::vector<std::vector<CommitmentHandle>> get_concatenation_groups() { return {}; };

VerifierCommitments(std::shared_ptr<VerificationKey> verification_key,
[[maybe_unused]] const BaseTranscript<FF>& transcript)
{
Expand Down
4 changes: 4 additions & 0 deletions barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ template <typename BuilderType> class UltraRecursive_ {
return { table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, w_r_shift,
w_o_shift, w_4_shift, sorted_accum_shift, z_perm_shift, z_lookup_shift };
};
std::vector<HandleType> get_unshifted_then_shifted_then_special() { return {}; }
std::vector<HandleType> get_concatenated_constraints() { return {}; }
};

public:
Expand Down Expand Up @@ -401,6 +403,8 @@ template <typename BuilderType> class UltraRecursive_ {

class VerifierCommitments : public AllEntities<Commitment, CommitmentHandle> {
public:
std::vector<std::vector<CommitmentHandle>> get_concatenation_groups() { return {}; };

VerifierCommitments(std::shared_ptr<VerificationKey> verification_key)
{
this->q_m = verification_key->q_m;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,12 @@ std::array<typename Flavor::GroupElement, 2> UltraRecursiveVerifier_<Flavor>::ve
auto [multivariate_challenge, claimed_evaluations, verified] = sumcheck.verify(relation_parameters, transcript);

// Execute ZeroMorph multilinear PCS evaluation verifier
auto pairing_points = ZeroMorph::verify(commitments, claimed_evaluations, multivariate_challenge, transcript);

auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(),
commitments.get_to_be_shifted(),
claimed_evaluations.get_unshifted(),
claimed_evaluations.get_shifted(),
multivariate_challenge,
transcript);
return pairing_points;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ template <UltraFlavor Flavor> void UltraProver_<Flavor>::execute_zeromorph_round
{
ZeroMorph::prove(instance->prover_polynomials.get_unshifted(),
instance->prover_polynomials.get_to_be_shifted(),
sumcheck_output.claimed_evaluations,
sumcheck_output.claimed_evaluations.get_unshifted(),
sumcheck_output.claimed_evaluations.get_shifted(),
sumcheck_output.challenge,
commitment_key,
transcript);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,12 @@ template <typename Flavor> bool UltraVerifier_<Flavor>::verify_proof(const plonk

// Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the
// unrolled protocol.
auto pairing_points = ZeroMorph::verify(commitments, claimed_evaluations, multivariate_challenge, transcript);
auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(),
commitments.get_to_be_shifted(),
claimed_evaluations.get_unshifted(),
claimed_evaluations.get_shifted(),
multivariate_challenge,
transcript);

auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]);

Expand Down