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: Integrate ZeroMorph into Honk #2774

Merged
merged 7 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -136,7 +136,7 @@ TEST_F(GoblinUltraHonkComposerTests, MultipleCircuitsMergeOnly)

auto composer = GoblinUltraComposer();

// Construct and verify Goblin ECC op queue Merge its proof
// Construct and verify Goblin ECC op queue Merge proof
auto merge_verified = construct_and_verify_merge_proof(composer, op_queue);
EXPECT_TRUE(merge_verified);
}
Expand Down Expand Up @@ -196,7 +196,7 @@ TEST_F(GoblinUltraHonkComposerTests, MultipleCircuitsHonkAndMerge)
auto honk_verified = construct_and_verify_honk_proof(composer, builder);
EXPECT_TRUE(honk_verified);

// Construct and verify Goblin ECC op queue Merge its proof
// Construct and verify Goblin ECC op queue Merge proof
auto merge_verified = construct_and_verify_merge_proof(composer, op_queue);
EXPECT_TRUE(merge_verified);
}
Expand Down
371 changes: 305 additions & 66 deletions barretenberg/cpp/src/barretenberg/honk/pcs/zeromorph/zeromorph.hpp

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -81,24 +81,24 @@ template <class Curve> class ZeroMorphTest : public CommitmentTest<Curve> {

// Execute Prover protocol
{
auto alpha = prover_transcript.get_challenge("ZM:alpha");
auto rho = prover_transcript.get_challenge("ZM:rho");

// Compute batching of f_i and g_i polynomials: sum_{i=0}^{m-1}\alpha^i*f_i and
// sum_{i=0}^{l-1}\alpha^{m+i}*h_i, and also batched evaluation v = sum_{i=0}^{m-1}\alpha^i*v_i +
// sum_{i=0}^{l-1}\alpha^{m+i}*w_i.
// Compute batching of f_i and g_i polynomials: sum_{i=0}^{m-1}\rho^i*f_i and
// sum_{i=0}^{l-1}\rho^{m+i}*h_i, and also batched evaluation v = sum_{i=0}^{m-1}\rho^i*v_i +
// sum_{i=0}^{l-1}\rho^{m+i}*w_i.
auto f_batched = Polynomial(N);
auto g_batched = Polynomial(N);
auto v_evaluation = Fr(0);
auto alpha_pow = Fr(1);
auto rho_pow = Fr(1);
for (size_t i = 0; i < NUM_UNSHIFTED; ++i) {
f_batched.add_scaled(f_polynomials[i], alpha_pow);
v_evaluation += alpha_pow * v_evaluations[i];
alpha_pow *= alpha;
f_batched.add_scaled(f_polynomials[i], rho_pow);
v_evaluation += rho_pow * v_evaluations[i];
rho_pow *= rho;
}
for (size_t i = 0; i < NUM_SHIFTED; ++i) {
g_batched.add_scaled(g_polynomials[i], alpha_pow);
v_evaluation += alpha_pow * w_evaluations[i];
alpha_pow *= alpha;
g_batched.add_scaled(g_polynomials[i], rho_pow);
v_evaluation += rho_pow * w_evaluations[i];
rho_pow *= rho;
}

// The new f is f_batched + g_batched.shifted() = f_batched + h_batched
Expand Down Expand Up @@ -151,19 +151,19 @@ template <class Curve> class ZeroMorphTest : public CommitmentTest<Curve> {

// Execute Verifier protocol
{
// Challenge alpha
auto alpha = verifier_transcript.get_challenge("ZM:alpha");
// Challenge rho
auto rho = verifier_transcript.get_challenge("ZM:rho");

// Construct batched evaluation v = sum_{i=0}^{m-1}\alpha^i*v_i + sum_{i=0}^{l-1}\alpha^{m+i}*w_i
// Construct batched evaluation v = sum_{i=0}^{m-1}\rho^i*v_i + sum_{i=0}^{l-1}\rho^{m+i}*w_i
auto v_evaluation = Fr(0);
auto alpha_pow = Fr(1);
auto rho_pow = Fr(1);
for (size_t i = 0; i < NUM_UNSHIFTED; ++i) {
v_evaluation += alpha_pow * v_evaluations[i];
alpha_pow *= alpha;
v_evaluation += rho_pow * v_evaluations[i];
rho_pow *= rho;
}
for (size_t i = 0; i < NUM_SHIFTED; ++i) {
v_evaluation += alpha_pow * w_evaluations[i];
alpha_pow *= alpha;
v_evaluation += rho_pow * w_evaluations[i];
rho_pow *= rho;
}

// Receive commitments [q_k]
Expand All @@ -183,15 +183,12 @@ template <class Curve> class ZeroMorphTest : public CommitmentTest<Curve> {
// Challenges x, z
auto [x_challenge, z_challenge] = verifier_transcript.get_challenges("ZM:x", "ZM:z");

// Compute commitment C_{v,x} = v * x * \Phi_n(x) * [1]_1
auto C_v_x = Commitment::one() * v_evaluation * x_challenge * this->Phi(x_challenge, log_N);

// Compute commitment C_{\zeta_x}
auto C_zeta_x = ZeroMorphVerifier::compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge);

// Compute commitment C_{Z_x}
Commitment C_Z_x = ZeroMorphVerifier::compute_C_Z_x(
C_v_x, f_commitments, g_commitments, C_q_k, alpha, x_challenge, u_challenge);
f_commitments, g_commitments, C_q_k, rho, v_evaluation, x_challenge, u_challenge);

// Compute commitment C_{\zeta,Z}
auto C_zeta_Z = C_zeta_x + C_Z_x * z_challenge;
Expand Down Expand Up @@ -418,13 +415,13 @@ TYPED_TEST(ZeroMorphTest, PartiallyEvaluatedQuotientZ)
Fr v_evaluation = multilinear_f.evaluate_mle(u_challenge);
Fr w_evaluation = multilinear_g.evaluate_mle(u_challenge, /* shift = */ true);

auto alpha = Fr::random_element();
auto rho = Fr::random_element();

// compute batched polynomial and evaluation
auto f_batched = multilinear_f;
auto g_batched = multilinear_g;
g_batched *= alpha;
auto v_batched = v_evaluation + alpha * w_evaluation;
g_batched *= rho;
auto v_batched = v_evaluation + rho * w_evaluation;

// Define some mock q_k with deg(q_k) = 2^k - 1
auto q_0 = this->random_polynomial(1 << 0);
Expand Down
126 changes: 12 additions & 114 deletions barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#include "ultra_prover.hpp"
#include "barretenberg/honk/pcs/claim.hpp"
#include "barretenberg/honk/sumcheck/sumcheck.hpp"
#include "barretenberg/honk/utils/power_polynomial.hpp"
#include "barretenberg/polynomials/polynomial.hpp"
#include "barretenberg/transcript/transcript_wrappers.hpp"

namespace proof_system::honk {

Expand Down Expand Up @@ -111,99 +108,18 @@ template <UltraFlavor Flavor> void UltraProver_<Flavor>::execute_relation_check_
}

/**
* - Get rho challenge
* - Compute d+1 Fold polynomials and their evaluations.
* @brief Execute the ZeroMorph protocol to prove the multilinear evaluations produced by Sumcheck
* @details See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol.
*
* */
template <UltraFlavor Flavor> void UltraProver_<Flavor>::execute_univariatization_round()
template <UltraFlavor Flavor> void UltraProver_<Flavor>::execute_zeromorph_rounds()
{
const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES;

// Generate batching challenge ρ and powers 1,ρ,…,ρᵐ⁻¹
FF rho = transcript.get_challenge("rho");
std::vector<FF> rhos = pcs::gemini::powers_of_rho(rho, NUM_POLYNOMIALS);

// Batch the unshifted polynomials and the to-be-shifted polynomials using ρ
Polynomial batched_poly_unshifted(instance->proving_key->circuit_size); // batched unshifted polynomials
size_t poly_idx = 0; // TODO(https://github.com/AztecProtocol/barretenberg/issues/391) zip
for (auto& unshifted_poly : instance->prover_polynomials.get_unshifted()) {
batched_poly_unshifted.add_scaled(unshifted_poly, rhos[poly_idx]);
++poly_idx;
}

Polynomial batched_poly_to_be_shifted(instance->proving_key->circuit_size); // batched to-be-shifted polynomials
for (auto& to_be_shifted_poly : instance->prover_polynomials.get_to_be_shifted()) {
batched_poly_to_be_shifted.add_scaled(to_be_shifted_poly, rhos[poly_idx]);
++poly_idx;
};

// Compute d-1 polynomials Fold^(i), i = 1, ..., d-1.
gemini_polynomials = Gemini::compute_gemini_polynomials(
sumcheck_output.challenge, std::move(batched_poly_unshifted), std::move(batched_poly_to_be_shifted));

// Compute and add to trasnscript the commitments [Fold^(i)], i = 1, ..., d-1
for (size_t l = 0; l < instance->proving_key->log_circuit_size - 1; ++l) {
queue.add_commitment(gemini_polynomials[l + 2], "Gemini:FOLD_" + std::to_string(l + 1));
}
}

/**
* - Do Fiat-Shamir to get "r" challenge
* - Compute remaining two partially evaluated Fold polynomials Fold_{r}^(0) and Fold_{-r}^(0).
* - Compute and aggregate opening pairs (challenge, evaluation) for each of d Fold polynomials.
* - Add d-many Fold evaluations a_i, i = 0, ..., d-1 to the transcript, excluding eval of Fold_{r}^(0)
* */
template <UltraFlavor Flavor> void UltraProver_<Flavor>::execute_pcs_evaluation_round()
{
const FF r_challenge = transcript.get_challenge("Gemini:r");
univariate_openings = Gemini::compute_fold_polynomial_evaluations(
sumcheck_output.challenge, std::move(gemini_polynomials), r_challenge);

for (size_t l = 0; l < instance->proving_key->log_circuit_size; ++l) {
std::string label = "Gemini:a_" + std::to_string(l);
const auto& evaluation = univariate_openings.opening_pairs[l + 1].evaluation;
transcript.send_to_verifier(label, evaluation);
}
}

/**
* - Do Fiat-Shamir to get "nu" challenge.
* - Compute commitment [Q]_1
* */
template <UltraFlavor Flavor> void UltraProver_<Flavor>::execute_shplonk_batched_quotient_round()
{
nu_challenge = transcript.get_challenge("Shplonk:nu");

batched_quotient_Q = Shplonk::compute_batched_quotient(
univariate_openings.opening_pairs, univariate_openings.witnesses, nu_challenge);

// commit to Q(X) and add [Q] to the transcript
queue.add_commitment(batched_quotient_Q, "Shplonk:Q");
}

/**
* - Do Fiat-Shamir to get "z" challenge.
* - Compute polynomial Q(X) - Q_z(X)
* */
template <UltraFlavor Flavor> void UltraProver_<Flavor>::execute_shplonk_partial_evaluation_round()
{
const FF z_challenge = transcript.get_challenge("Shplonk:z");

shplonk_output = Shplonk::compute_partially_evaluated_batched_quotient(univariate_openings.opening_pairs,
univariate_openings.witnesses,
std::move(batched_quotient_Q),
nu_challenge,
z_challenge);
}
/**
* - Compute final PCS opening proof:
* - For KZG, this is the quotient commitmecnt [W]_1
* - For IPA, the vectors L and R
* */
template <UltraFlavor Flavor> void UltraProver_<Flavor>::execute_final_pcs_round()
{
PCS::compute_opening_proof(pcs_commitment_key, shplonk_output.opening_pair, shplonk_output.witness, transcript);
// queue.add_commitment(quotient_W, "KZG:W");
ZeroMorph::prove(instance->prover_polynomials.get_unshifted(),
instance->prover_polynomials.get_to_be_shifted(),
sumcheck_output.claimed_evaluations,
sumcheck_output.challenge,
pcs_commitment_key,
transcript);
}

template <UltraFlavor Flavor> plonk::proof& UltraProver_<Flavor>::export_proof()
Expand Down Expand Up @@ -234,27 +150,9 @@ template <UltraFlavor Flavor> plonk::proof& UltraProver_<Flavor>::construct_proo
// Run sumcheck subprotocol.
execute_relation_check_rounds();

// Fiat-Shamir: rho
// Compute Fold polynomials and their commitments.
execute_univariatization_round();
queue.process_queue();

// Fiat-Shamir: r
// Compute Fold evaluations
execute_pcs_evaluation_round();

// Fiat-Shamir: nu
// Compute Shplonk batched quotient commitment Q
execute_shplonk_batched_quotient_round();
queue.process_queue();

// Fiat-Shamir: z
// Compute partial evaluation Q_z
execute_shplonk_partial_evaluation_round();

// Fiat-Shamir: z
// Compute PCS opening proof (either KZG quotient commitment or IPA opening proof)
execute_final_pcs_round();
// Fiat-Shamir: rho, y, x, z
// Execute Zeromorph multilinear PCS
execute_zeromorph_rounds();

return export_proof();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
#include "barretenberg/honk/flavor/ultra.hpp"
#include "barretenberg/honk/flavor/ultra_grumpkin.hpp"
#include "barretenberg/honk/instance/prover_instance.hpp"
#include "barretenberg/honk/pcs/gemini/gemini.hpp"
#include "barretenberg/honk/pcs/shplonk/shplonk.hpp"
#include "barretenberg/honk/pcs/zeromorph/zeromorph.hpp"
#include "barretenberg/honk/proof_system/work_queue.hpp"
#include "barretenberg/honk/sumcheck/sumcheck_output.hpp"
#include "barretenberg/honk/transcript/transcript.hpp"
Expand All @@ -16,15 +15,13 @@ namespace proof_system::honk {
template <UltraFlavor Flavor> class UltraProver_ {
using FF = typename Flavor::FF;
using Commitment = typename Flavor::Commitment;
using PCS = typename Flavor::PCS;
using CommitmentKey = typename Flavor::CommitmentKey;
using ProvingKey = typename Flavor::ProvingKey;
using Polynomial = typename Flavor::Polynomial;
using ProverPolynomials = typename Flavor::ProverPolynomials;
using CommitmentLabels = typename Flavor::CommitmentLabels;
using Curve = typename Flavor::Curve;
using Instance = ProverInstance_<Flavor>;
using OpenPair = pcs::OpeningPair<Curve>;

public:
explicit UltraProver_(std::shared_ptr<Instance>);
Expand All @@ -33,12 +30,7 @@ template <UltraFlavor Flavor> class UltraProver_ {
void execute_sorted_list_accumulator_round();
void execute_grand_product_computation_round();
void execute_relation_check_rounds();
void execute_univariatization_round();
void execute_pcs_evaluation_round();
void execute_op_queue_transcript_aggregation_round();
void execute_shplonk_batched_quotient_round();
void execute_shplonk_partial_evaluation_round();
void execute_final_pcs_round();
void execute_zeromorph_rounds();

plonk::proof& export_proof();
plonk::proof& construct_proof();
Expand All @@ -50,25 +42,16 @@ template <UltraFlavor Flavor> class UltraProver_ {

CommitmentLabels commitment_labels;

// Container for d + 1 Fold polynomials produced by Gemini
std::vector<Polynomial> gemini_polynomials;

Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk
FF nu_challenge; // needed in both Shplonk rounds

Polynomial quotient_W;

work_queue<Curve> queue;

std::shared_ptr<Instance> instance;

sumcheck::SumcheckOutput<Flavor> sumcheck_output;
pcs::gemini::ProverOutput<Curve> univariate_openings;
pcs::shplonk::ProverOutput<Curve> shplonk_output;
std::shared_ptr<CommitmentKey> pcs_commitment_key;

using Gemini = pcs::gemini::GeminiProver_<Curve>;
using Shplonk = pcs::shplonk::ShplonkProver_<Curve>;
using ZeroMorph = pcs::zeromorph::ZeroMorphProver_<Curve>;

private:
plonk::proof proof;
Expand Down
Loading