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

Lde/gemini shplonk in prover #67

Merged
merged 14 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from 13 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 @@ -232,7 +232,7 @@ std::shared_ptr<waffle::proving_key> ComposerHelper<CircuitConstructor>::compute
compute_first_and_last_lagrange_polynomials(circuit_proving_key.get());

// TODO(Cody): this is a workaround
circuit_proving_key->polynomial_cache.put("z_perm", Polynomial<barretenberg::fr>(1));
circuit_proving_key->polynomial_cache.put("z_perm_lagrange", Polynomial<barretenberg::fr>(1));

return circuit_proving_key;
}
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/aztec/honk/composer/standard_honk_composer.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,8 @@ TEST(StandarHonkComposer, BaseCase)

auto prover = composer.create_unrolled_prover();
// waffle::Verifier verifier = composer.create_verifier();
auto multivariates = honk::sumcheck::Multivariates<fr, waffle::STANDARD_HONK_MANIFEST_SIZE>(prover.proving_key);
(void)multivariates;
// auto multivariates = honk::sumcheck::Multivariates<fr, waffle::STANDARD_HONK_MANIFEST_SIZE>(prover.proving_key);
// (void)multivariates;
waffle::plonk_proof proof = prover.construct_proof();

// bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2);
Expand Down
5 changes: 5 additions & 0 deletions cpp/src/aztec/honk/pcs/claim.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ template <typename Params> struct MLEOpeningClaim {
using Commitment = typename Params::Commitment;
using Fr = typename Params::Fr;

MLEOpeningClaim(auto commitment, auto evaluation)
Copy link
Collaborator

Choose a reason for hiding this comment

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

You explained that adding this is necessary to work around an optimization targeting the recursive case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah this was so I could construct MLEOpeningClaims in place with emplace_back in the prover. Need a constructor for that and there was previously no need for one.

: commitment(commitment)
, evaluation(evaluation)
{}

// commitment to a univariate polynomial
// whose coefficients are the multi-linear evaluations
// of C = [f]
Expand Down
21 changes: 11 additions & 10 deletions cpp/src/aztec/honk/pcs/commitment_key.test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <concepts>
#include <algorithm>
#include <memory>
#include <string_view>

#include <polynomials/polynomial.hpp>
Expand All @@ -23,19 +24,20 @@ namespace {
constexpr std::string_view kzg_srs_path = "../srs_db/ignition";
}

template <class CK> inline CK* CreateCommitmentKey();
template <class CK> inline std::shared_ptr<CK> CreateCommitmentKey();
Copy link
Collaborator

Choose a reason for hiding this comment

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

IOU on what the right data structure is here, but we should just use this for now.


template <> inline kzg::CommitmentKey* CreateCommitmentKey<kzg::CommitmentKey>()
template <> inline std::shared_ptr<kzg::CommitmentKey> CreateCommitmentKey<kzg::CommitmentKey>()
{
const size_t n = 128;
return new kzg::CommitmentKey(n, kzg_srs_path);
return std::make_shared<kzg::CommitmentKey>(n, kzg_srs_path);
}

template <typename CK> inline CK* CreateCommitmentKey()
template <typename CK> inline std::shared_ptr<CK> CreateCommitmentKey()
// requires std::default_initializable<CK>
{
return new CK();
return std::make_shared<CK>();
}

template <class VK> inline VK* CreateVerificationKey();

template <> inline kzg::VerificationKey* CreateVerificationKey<kzg::VerificationKey>()
Expand Down Expand Up @@ -63,7 +65,7 @@ template <typename Params> class CommitmentTest : public ::testing::Test {
: engine{ &numeric::random::get_debug_engine() }
{}

CK* ck() { return commitment_key; }
std::shared_ptr<CK> ck() { return commitment_key; }
VK* vk() { return verification_key; }

Commitment commit(const Polynomial& polynomial) { return commitment_key->commit(polynomial); }
Expand Down Expand Up @@ -188,17 +190,16 @@ template <typename Params> class CommitmentTest : public ::testing::Test {
// Can be omitted if not needed.
static void TearDownTestSuite()
{
delete commitment_key;
commitment_key = nullptr;
delete verification_key;
verification_key = nullptr;
}

static typename Params::CK* commitment_key;
static typename std::shared_ptr<typename Params::CK> commitment_key;
static typename Params::VK* verification_key;
};

template <typename Params> typename Params::CK* CommitmentTest<Params>::commitment_key = nullptr;
template <typename Params>
typename std::shared_ptr<typename Params::CK> CommitmentTest<Params>::commitment_key = nullptr;
template <typename Params> typename Params::VK* CommitmentTest<Params>::verification_key = nullptr;

using CommitmentSchemeParams = ::testing::Types<kzg::Params>;
Expand Down
3 changes: 2 additions & 1 deletion cpp/src/aztec/honk/pcs/gemini/gemini.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "polynomials/polynomial.hpp"

#include <common/assert.hpp>
#include <memory>
#include <vector>

/**
Expand Down Expand Up @@ -145,7 +146,7 @@ template <typename Params> class MultilinearReductionScheme {
* @param transcript
* @return Output (result_claims, proof, folded_witness_polynomials)
*/
static ProverOutput<Params> reduce_prove(CK* ck,
static ProverOutput<Params> reduce_prove(std::shared_ptr<CK> ck,
std::span<const Fr> mle_opening_point,
std::span<const MLEOpeningClaim<Params>> claims,
std::span<const MLEOpeningClaim<Params>> claims_shifted,
Expand Down
3 changes: 2 additions & 1 deletion cpp/src/aztec/honk/pcs/kzg/kzg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "../claim.hpp"
#include "polynomials/polynomial.hpp"

#include <memory>
#include <utility>

namespace honk::pcs::kzg {
Expand Down Expand Up @@ -68,7 +69,7 @@ template <typename Params> class UnivariateOpeningScheme {
* @param polynomial the witness polynomial for C
* @return Output{Accumulator, Proof}
*/
static Output reduce_prove(CK* ck, const OpeningClaim<Params>& claim, const Polynomial& polynomial)
static Output reduce_prove(std::shared_ptr<CK> ck, const OpeningClaim<Params>& claim, const Polynomial& polynomial)
{
Polynomial quotient(polynomial);
quotient[0] -= claim.eval;
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/aztec/honk/pcs/shplonk/shplonk_multi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ template <typename Params> class MultiBatchOpeningScheme {
* @param transcript
* @return Output{OpeningClaim, WitnessPolynomial, Proof}
*/
static ProverOutput<Params> reduce_prove(CK* ck,
static ProverOutput<Params> reduce_prove(std::shared_ptr<CK> ck,
std::span<const MultiOpeningClaim<Params>> multi_claims,
std::span<const Polynomial> witness_polynomials,
const auto& transcript)
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/aztec/honk/pcs/shplonk/shplonk_single.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ template <typename Params> class SingleBatchOpeningScheme {
* @param transcript
* @return Output{OpeningClaim, WitnessPolynomial, Proof}
*/
static ProverOutput<Params> reduce_prove(CK* ck,
static ProverOutput<Params> reduce_prove(std::shared_ptr<CK> ck,
std::span<const OpeningClaim<Params>> claims,
std::span<const Polynomial> witness_polynomials,
const auto& transcript)
Expand Down
139 changes: 93 additions & 46 deletions cpp/src/aztec/honk/proof_system/prover.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include "prover.hpp"
#include <cstddef>
#include <honk/sumcheck/sumcheck.hpp> // will need
#include <array>
#include <honk/sumcheck/polynomials/univariate.hpp> // will go away
#include <honk/pcs/commitment_key.hpp>
#include <memory>
#include <vector>
#include "ecc/curves/bn254/fr.hpp"
#include "ecc/curves/bn254/g1.hpp"
Expand All @@ -11,11 +13,17 @@
#include <honk/sumcheck/relations/grand_product_computation_relation.hpp>
#include <honk/sumcheck/relations/grand_product_initialization_relation.hpp>
#include "plonk/proof_system/types/polynomial_manifest.hpp"
#include "polynomials/polynomial.hpp"
#include "proof_system/flavor/flavor.hpp"
#include "transcript/transcript_wrappers.hpp"
#include <string>
#include <honk/pcs/claim.hpp>

namespace honk {

using Fr = barretenberg::fr;
using Polynomial = barretenberg::Polynomial<Fr>;

/**
* Create Prover from proving key, witness and manifest.
*
Expand Down Expand Up @@ -50,7 +58,7 @@ template <typename settings> void Prover<settings>::compute_wire_commitments()
std::string wire_tag = "w_" + std::to_string(i + 1) + "_lagrange";
std::string commit_tag = "W_" + std::to_string(i + 1);

std::span<barretenberg::fr> wire_polynomial = proving_key->polynomial_cache.get(wire_tag);
std::span<Fr> wire_polynomial = proving_key->polynomial_cache.get(wire_tag);
auto commitment = commitment_key->commit(wire_polynomial);

transcript.add_element(commit_tag, commitment.to_buffer());
Expand Down Expand Up @@ -83,11 +91,8 @@ template <typename settings> void Prover<settings>::compute_wire_commitments()
* Note: Step (4) utilizes Montgomery batch inversion to replace n-many inversions with
* one batch inversion (at the expense of more multiplications)
*/
template <typename settings> void Prover<settings>::compute_grand_product_polynomial(barretenberg::fr beta)
template <typename settings> void Prover<settings>::compute_grand_product_polynomial(Fr beta)
{
// TODO: Fr to become template param
using Fr = barretenberg::fr;
using barretenberg::polynomial;
using barretenberg::polynomial_arithmetic::copy_polynomial;
static const size_t program_width = settings::program_width;

Expand Down Expand Up @@ -157,7 +162,7 @@ template <typename settings> void Prover<settings>::compute_grand_product_polyno

// Construct permutation polynomial 'z_perm' in lagrange form as:
// z_perm = [1 numererator_accum[0][0] numererator_accum[0][1] ... numererator_accum[0][n-2]]
polynomial z_perm(proving_key->n, proving_key->n);
Polynomial z_perm(proving_key->n, proving_key->n);
Copy link
Collaborator

Choose a reason for hiding this comment

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

polynomial ~> Polynomial is you renaming?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah they both alias the same thing, just trying to make it consistent throughout the prover and I prefer Polynomial

Copy link
Collaborator

Choose a reason for hiding this comment

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

Aha, thanks

z_perm[0] = Fr::one();
copy_polynomial(numererator_accum[0], &z_perm[1], proving_key->n - 1, proving_key->n - 1);

Expand All @@ -169,7 +174,7 @@ template <typename settings> void Prover<settings>::compute_grand_product_polyno

// TODO(luke): Commit to z_perm here? This would match Plonk but maybe best to do separately?

proving_key->polynomial_cache.put("z_perm", std::move(z_perm));
proving_key->polynomial_cache.put("z_perm_lagrange", std::move(z_perm));
}

/**
Expand Down Expand Up @@ -218,8 +223,8 @@ template <typename settings> void Prover<settings>::execute_wire_commitments_rou
compute_wire_commitments();

// Add public inputs to transcript
const barretenberg::polynomial& public_wires_source = proving_key->polynomial_cache.get("w_2_lagrange");
std::vector<barretenberg::fr> public_wires;
const Polynomial& public_wires_source = proving_key->polynomial_cache.get("w_2_lagrange");
std::vector<Fr> public_wires;
for (size_t i = 0; i < proving_key->num_public_inputs; ++i) {
public_wires.push_back(public_wires_source[i]);
}
Expand Down Expand Up @@ -259,7 +264,7 @@ template <typename settings> void Prover<settings>::execute_grand_product_comput

auto beta = transcript.get_challenge_field_element("beta");
compute_grand_product_polynomial(beta);
std::span<barretenberg::fr> z_perm = proving_key->polynomial_cache.get("z_perm");
std::span<Fr> z_perm = proving_key->polynomial_cache.get("z_perm_lagrange");
auto commitment = commitment_key->commit(z_perm);
transcript.add_element("Z_PERM", commitment.to_buffer());
}
Expand All @@ -280,7 +285,7 @@ template <typename settings> void Prover<settings>::execute_relation_check_round
{
// queue.flush_queue(); // NOTE: Don't remove; we may reinstate the queue

using Multivariates = sumcheck::Multivariates<barretenberg::fr, waffle::STANDARD_HONK_MANIFEST_SIZE>;
using Multivariates = sumcheck::Multivariates<Fr, waffle::TOTAL_NUM_POLYNOMIALS>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should contain the words HONK and STANDARD in it somewhere.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good call, done.

using Transcript = transcript::StandardTranscript;
using Sumcheck = sumcheck::Sumcheck<Multivariates,
Transcript,
Expand All @@ -296,24 +301,18 @@ template <typename settings> void Prover<settings>::execute_relation_check_round

sumcheck.execute_prover();

// TODO(Cody): Execute as a loop over polynomial manifest? Things thare are called *_lagrange
transcript.add_element("w_1", multivariates.folded_polynomials[1][0].to_buffer());
transcript.add_element("w_2", multivariates.folded_polynomials[1][0].to_buffer());
transcript.add_element("w_3", multivariates.folded_polynomials[2][0].to_buffer());
transcript.add_element("z_perm", multivariates.folded_polynomials[3][0].to_buffer());
transcript.add_element("q_m", multivariates.folded_polynomials[4][0].to_buffer());
transcript.add_element("q_1", multivariates.folded_polynomials[5][0].to_buffer());
transcript.add_element("q_2", multivariates.folded_polynomials[6][0].to_buffer());
transcript.add_element("q_3", multivariates.folded_polynomials[7][0].to_buffer());
transcript.add_element("q_c", multivariates.folded_polynomials[8][0].to_buffer());
transcript.add_element("sigma_1", multivariates.folded_polynomials[9][0].to_buffer());
transcript.add_element("sigma_2", multivariates.folded_polynomials[10][0].to_buffer());
transcript.add_element("sigma_3", multivariates.folded_polynomials[11][0].to_buffer());
transcript.add_element("id_1", multivariates.folded_polynomials[12][0].to_buffer());
transcript.add_element("id_2", multivariates.folded_polynomials[13][0].to_buffer());
transcript.add_element("id_3", multivariates.folded_polynomials[14][0].to_buffer());
transcript.add_element("L_first", multivariates.folded_polynomials[15][0].to_buffer());
transcript.add_element("L_last", multivariates.folded_polynomials[16][0].to_buffer());
// Add the multilinear evaluations produced by Sumcheck to the transcript.
// Note: The number of evaluations is poly manifest size + number of shifted polys.
size_t poly_idx = 0;
for (auto& entry : proving_key->polynomial_manifest.get()) {
std::string label(entry.polynomial_label);
transcript.add_element(label, multivariates.folded_polynomials[poly_idx][0].to_buffer());
++poly_idx;
if (entry.requires_shifted_evaluation) {
transcript.add_element(label + "_shift", multivariates.folded_polynomials[poly_idx][0].to_buffer());
++poly_idx;
}
}
}

/**
Expand All @@ -325,11 +324,58 @@ template <typename settings> void Prover<settings>::execute_relation_check_round
* */
template <typename settings> void Prover<settings>::execute_univariatization_round()
{
transcript.apply_fiat_shamir("rho");
// TODO(Cody): Implement
for (size_t round_idx = 1; round_idx < proving_key->log_n; round_idx++) {
transcript.add_element("FOLD_" + std::to_string(round_idx), barretenberg::g1::affine_one.to_buffer());
using Gemini = pcs::gemini::MultilinearReductionScheme<pcs::kzg::Params>;
using MLEOpeningClaim = pcs::MLEOpeningClaim<pcs::kzg::Params>;

// Construct inputs for Gemini:
// - Multivariate opening point u = (u_1, ..., u_d)
// - MLE opening claim = {commitment, eval} for each multivariate and shifted multivariate polynomial
// - Pointers to multivariate and shifted multivariate polynomials
std::vector<Fr> opening_point;
std::vector<MLEOpeningClaim> opening_claims;
std::vector<MLEOpeningClaim> opening_claims_shifted;
std::vector<Polynomial*> multivariate_polynomials;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is idiomatic to Gemini -- raw pointers are in use there?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, just matching what's done in Gemini. Should probably change in the future

std::vector<Polynomial*> multivariate_polynomials_shifted;
// TODO(luke): Currently feeding in mock commitments for non-WITNESS polynomials. This may be sufficient for simple
// proof verification since the other commitments are only needed to produce 'claims' in gemini.reduce_prove, they
// are not needed in the proof itself.

// Construct MLE opening point
for (size_t round_idx = 0; round_idx < proving_key->log_n; round_idx++) {
std::string label = "u_" + std::to_string(round_idx + 1);
opening_point.emplace_back(transcript.get_challenge_field_element(label));
}

// Construct opening claims and polynomials
for (auto& entry : proving_key->polynomial_manifest.get()) {
std::string label(entry.polynomial_label);
std::string commitment_label(entry.commitment_label);
auto evaluation = Fr::serialize_from_buffer(&transcript.get_element(label)[0]);
barretenberg::g1::affine_element commitment;
if (entry.source == waffle::WITNESS) {
commitment =
barretenberg::g1::affine_element::serialize_from_buffer(&transcript.get_element(commitment_label)[0]);
} else { // SELECTOR, PERMUTATION, OTHER
commitment = barretenberg::g1::affine_one; // mock commitment
}
opening_claims.emplace_back(commitment, evaluation);
multivariate_polynomials.emplace_back(&proving_key->polynomial_cache.get(label));
if (entry.requires_shifted_evaluation) {
// Note: For a polynomial p for which we need the shift p_shift, we provide Gemini with the SHIFTED
// evaluation p_shift(u), but the UNSHIFTED polynomial p and its UNSHIFTED commitment [p].
auto shifted_evaluation = Fr::serialize_from_buffer(&transcript.get_element(label + "_shift")[0]);
opening_claims_shifted.emplace_back(commitment, shifted_evaluation);
multivariate_polynomials_shifted.emplace_back(&proving_key->polynomial_cache.get(label));
}
}

gemini_output = Gemini::reduce_prove(commitment_key,
opening_point,
opening_claims,
opening_claims_shifted,
multivariate_polynomials,
multivariate_polynomials_shifted,
&transcript);
}

/**
Expand All @@ -343,11 +389,9 @@ template <typename settings> void Prover<settings>::execute_univariatization_rou
* */
template <typename settings> void Prover<settings>::execute_pcs_evaluation_round()
{
transcript.apply_fiat_shamir("r");
// TODO(Cody): Implement
for (size_t round_idx = 0; round_idx < proving_key->log_n; round_idx++) {
transcript.add_element("a_" + std::to_string(round_idx), barretenberg::fr(round_idx + 1000).to_buffer());
}
// TODO(luke): This functionality is performed within Gemini::reduce_prove(), called in the previous round. In the
Copy link
Collaborator

Choose a reason for hiding this comment

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

Right, we discussed this a week or two ago.

// future we could (1) split the Gemini functionality to match the round structure defined here, or (2) remove this
// function from the prover. The former may be necessary to maintain the work_queue paradigm.
}

/**
Expand All @@ -359,10 +403,8 @@ template <typename settings> void Prover<settings>::execute_pcs_evaluation_round
* */
template <typename settings> void Prover<settings>::execute_shplonk_round()
{
// TODO(luke): Do Fiat-Shamir to get "nu" challenge.
// TODO(luke): Get Shplonk opening point [Q]_1
transcript.apply_fiat_shamir("nu");
transcript.add_element("Q", barretenberg::g1::affine_one.to_buffer());
using Shplonk = pcs::shplonk::SingleBatchOpeningScheme<pcs::kzg::Params>;
shplonk_output = Shplonk::reduce_prove(commitment_key, gemini_output.claim, gemini_output.witness, &transcript);
}

/**
Expand All @@ -377,12 +419,17 @@ template <typename settings> void Prover<settings>::execute_shplonk_round()
* */
template <typename settings> void Prover<settings>::execute_kzg_round()
{
transcript.apply_fiat_shamir("z");
// TODO(luke): Do Fiat-Shamir to get "z" challenge.
// Note(luke): Fiat-Shamir to get "z" challenge is done in Shplonk::reduce_prove
// TODO(luke): Get KZG opening point [W]_1
transcript.add_element("W", barretenberg::g1::affine_one.to_buffer());
// transcript.apply_fiat_shamir("separator");
using KZG = pcs::kzg::UnivariateOpeningScheme<pcs::kzg::Params>;
using KzgOutput = pcs::kzg::UnivariateOpeningScheme<pcs::kzg::Params>::Output;
KzgOutput kzg_output = KZG::reduce_prove(commitment_key, shplonk_output.claim, shplonk_output.witness);

auto W_commitment = static_cast<barretenberg::g1::affine_element>(kzg_output.proof).to_buffer();

transcript.add_element("W", W_commitment);
}

template <typename settings> waffle::plonk_proof& Prover<settings>::export_proof()
{
proof.proof_data = transcript.export_transcript();
Expand Down
Loading