Skip to content
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
6 changes: 3 additions & 3 deletions cpp/src/barretenberg/honk/pcs/claim.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ template <typename Params> class OpeningPair {
using Fr = typename Params::Fr;

public:
Fr query; // r
Fr challenge; // r
Fr evaluation; // v = p(r)

bool operator==(const OpeningPair& other) const = default;
Expand All @@ -31,7 +31,7 @@ template <typename Params> class OpeningClaim {
using Fr = typename Params::Fr;

public:
// (query r, evaluation v = p(r))
// (challenge r, evaluation v = p(r))
OpeningPair<Params> opening_pair;
// commitment to univariate polynomial p(X)
CommitmentAffine commitment;
Expand All @@ -46,7 +46,7 @@ template <typename Params> class OpeningClaim {
*/
bool verify(CK* ck, const barretenberg::Polynomial<Fr>& polynomial) const
{
Fr real_eval = polynomial.evaluate(opening_pair.query);
Fr real_eval = polynomial.evaluate(opening_pair.challenge);
if (real_eval != opening_pair.evaluation) {
return false;
}
Expand Down
150 changes: 53 additions & 97 deletions cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
* v = ∑ ρʲ⋅vⱼ + ∑ ρᵏ⁺ʲ⋅v↺ⱼ = F(u) + G↺(u)
*
* The prover then creates the folded polynomials A₀, ..., Aₘ₋₁,
* commits and opens them at different points, as univariates.
* and opens them at different points, as univariates.
*
* We open A₀ as univariate at r and -r.
* Since A₀ = F + G↺, but the verifier only has commitments to the gⱼs,
Expand All @@ -48,30 +48,6 @@
*/
namespace honk::pcs::gemini {

/**
* @brief A Gemini proof contains the m-1 commitments to the
* folded univariates, and corresponding evaluations
* at -r, -r², …, r^{2ᵐ⁻¹}.
*
* The evaluations allow the verifier to reconstruct the evaluation of A₀(r).
*
* @tparam Params CommitmentScheme parameters
*/
template <typename Params> struct Proof {
/** @brief Commitments to folded polynomials (size = m-1)
*
* [ C₁, …, Cₘ₋₁], where Cₗ = commit(Aₗ(X)) of size 2ᵐ⁻ˡ
*/
std::vector<typename Params::Commitment> commitments;

/**
* @brief Evaluations of batched and folded polynomials (size m)
*
* [A₀(-r) , ..., Aₘ₋₁(-r^{2ᵐ⁻¹})]
*/
std::vector<typename Params::Fr> evaluations;
};

/**
* @brief Prover output (evalutation pair, witness) that can be passed on to Shplonk batch opening.
* @details Evaluation pairs {r, A₀₊(r)}, {-r, A₀₋(-r)}, {-r^{2^j}, Aⱼ(-r^{2^j)}, j = [1, ..., m-1]
Expand Down Expand Up @@ -100,35 +76,30 @@ template <typename Params> class MultilinearReductionScheme {

public:
/**
* @brief reduces claims about multiple (shifted) MLE evaluation
*
* @param ck is the commitment key for creating the new commitments
* @param mle_opening_point u = (u₀,...,uₘ₋₁) is the MLE opening point
* @param batched_shifted batch polynomial constructed from the unshifted multivariates
* @param batched_to_be_shifted batch polynomial constructed from the to-be-shifted multivariates
* @param transcript
* @return Output (opening pairs, folded_witness_polynomials)
* @brief Computes d-1 fold polynomials Fold_i, i = 1, ..., d-1
*
* @param mle_opening_point multilinear opening point 'u'
* @param batched_unshifted F(X) = ∑ⱼ ρʲ fⱼ(X)
* @param batched_to_be_shifted G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X)
* @return std::vector<Polynomial>
*/
static ProverOutput<Params> reduce_prove(std::shared_ptr<CK> ck,
std::span<const Fr> mle_opening_point,
const Polynomial&& batched_shifted, /* unshifted */
const Polynomial&& batched_to_be_shifted, /* to-be-shifted */
ProverTranscript<Fr>& transcript)
static std::vector<Polynomial> compute_fold_polynomials(std::span<const Fr> mle_opening_point,
Polynomial&& batched_unshifted,
Polynomial&& batched_to_be_shifted)
{
const size_t num_variables = mle_opening_point.size(); // m

// Allocate space for m+1 Fold polynomials
//
// At the end, the first two will contain the batched polynomial
// partially evaluated at the challenges r,-r.
// The other m-1 polynomials correspond to the foldings of A₀
// The first two are populated here with the batched unshifted and to-be-shifted polynomial respectively.
// They will eventually contain the full batched polynomial A₀ partially evaluated at the challenges r,-r.
// This function populates the other m-1 polynomials with the foldings of A₀.
std::vector<Polynomial> fold_polynomials;
fold_polynomials.reserve(num_variables + 1);
// F(X) = ∑ⱼ ρʲ fⱼ(X)
Polynomial& batched_F = fold_polynomials.emplace_back(batched_shifted);
// G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X)
Polynomial& batched_G = fold_polynomials.emplace_back(batched_to_be_shifted);

// F(X) = ∑ⱼ ρʲ fⱼ(X) and G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X)
Polynomial& batched_F = fold_polynomials.emplace_back(std::move(batched_unshifted));
Polynomial& batched_G = fold_polynomials.emplace_back(std::move(batched_to_be_shifted));

// A₀(X) = F(X) + G↺(X) = F(X) + G(X)/X.
Polynomial A_0(batched_F);
Expand Down Expand Up @@ -163,79 +134,64 @@ template <typename Params> class MultilinearReductionScheme {
A_l = A_l_fold;
}

/*
* Create commitments C₁,…,Cₘ₋₁ to polynomials FOLD_i, i = 1,...,d-1 and add to transcript
*/
std::vector<CommitmentAffine> commitments;
commitments.reserve(num_variables - 1);
for (size_t l = 0; l < num_variables - 1; ++l) {
commitments.emplace_back(ck->commit(fold_polynomials[l + 2]));
transcript.send_to_verifier("Gemini:FOLD_" + std::to_string(l + 1), commitments[l]);
}
return fold_polynomials;
};

/*
* Generate evaluation challenge r, and compute rₗ = r^{2ˡ} for l = 0, 1, ..., m-1
*/
const Fr r_challenge = transcript.get_challenge("Gemini:r");
std::vector<Fr> r_squares = squares_of_r(r_challenge, num_variables);
/**
* @brief Computes/aggragates d+1 Fold polynomials and their opening pairs (challenge, evaluation)
*
* @details This function assumes that, upon input, last d-1 entries in fold_polynomials are Fold_i.
* The first two entries are assumed to be, respectively, the batched unshifted and batched to-be-shifted
* polynomials F(X) = ∑ⱼ ρʲfⱼ(X) and G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X). This function completes the computation
* of the first two Fold polynomials as F + G/r and F - G/r. It then evaluates each of the d+1
* fold polynomials at, respectively, the points r, rₗ = r^{2ˡ} for l = 0, 1, ..., d-1.
*
* @param mle_opening_point u = (u₀,...,uₘ₋₁) is the MLE opening point
* @param fold_polynomials vector of polynomials whose first two elements are F(X) = ∑ⱼ ρʲfⱼ(X)
* and G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X), and the next d-1 elements are Fold_i, i = 1, ..., d-1.
* @param r_challenge univariate opening challenge
*/
static ProverOutput<Params> compute_fold_polynomial_evaluations(std::span<const Fr> mle_opening_point,
std::vector<Polynomial>&& fold_polynomials,
const Fr& r_challenge)
{
const size_t num_variables = mle_opening_point.size(); // m

/*
* Compute the witness polynomials for the resulting claim
*
*
* We are batching all polynomials together, and linearly combining them with
* powers of ρ
*/
Polynomial& batched_F = fold_polynomials[0]; // F(X) = ∑ⱼ ρʲ fⱼ(X)
Polynomial& batched_G = fold_polynomials[1]; // G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X)

// 2 simulated polynomials and (m-1) polynomials from this round
// Compute univariate opening queries rₗ = r^{2ˡ} for l = 0, 1, ..., m-1
std::vector<Fr> r_squares = squares_of_r(r_challenge, num_variables);

// Compute G/r
Fr r_inv = r_challenge.invert();
// G(X) *= r⁻¹
batched_G *= r_inv;

// To avoid an extra allocation, we reuse the following polynomials
// but rename them to represent the result.
// tmp = A₀(X) (&tmp == &A_0)
// A_0_pos = F(X) (&A_0_pos == &batched_F)
Polynomial& tmp = A_0;
// Construct A₀₊ = F + G/r and A₀₋ = F - G/r in place in fold_polynomials
Polynomial tmp = batched_F;
Polynomial& A_0_pos = fold_polynomials[0];

tmp = batched_F;
// A₀₊(X) = F(X) + G(X)/r, s.t. A₀₊(r) = A₀(r)
A_0_pos += batched_G;

// Perform a swap so that tmp = G(X)/r and A_0_neg = F(X)
std::swap(tmp, batched_G);
// After the swap, we have
// tmp = G(X)/r
// A_0_neg = F(X) (since &batched_F == &A_0_neg)
Polynomial& A_0_neg = fold_polynomials[1];

// A₀₋(X) = F(X) - G(X)/r, s.t. A₀₋(-r) = A₀(-r)
A_0_neg -= tmp;

/*
* Compute the m+1 evaluations Aₗ(−r^{2ˡ}), l = 0, ..., m-1.
* Add them to the transcript
*/
std::vector<Fr> fold_polynomial_evals;
fold_polynomial_evals.reserve(num_variables);
for (size_t l = 0; l < num_variables; ++l) {
const Polynomial& A_l = fold_polynomials[l + 1];

fold_polynomial_evals.emplace_back(A_l.evaluate(-r_squares[l]));
transcript.send_to_verifier("Gemini:a_" + std::to_string(l), fold_polynomial_evals[l]);
}

// Compute evaluation A₀(r)
auto a_0_pos = fold_polynomials[0].evaluate(r_challenge);

std::vector<OpeningPair<Params>> fold_poly_opening_pairs;
fold_poly_opening_pairs.reserve(num_variables + 1);

// ( r, A₀(r) )
fold_poly_opening_pairs.emplace_back(OpeningPair<Params>{ r_challenge, a_0_pos });
// (-r, Aₗ(−r^{2ˡ}) )
// Compute first opening pair {r, A₀(r)}
fold_poly_opening_pairs.emplace_back(
OpeningPair<Params>{ r_challenge, fold_polynomials[0].evaluate(r_challenge) });

// Compute the remaining m opening pairs {−r^{2ˡ}, Aₗ(−r^{2ˡ})}, l = 0, ..., m-1.
for (size_t l = 0; l < num_variables; ++l) {
fold_poly_opening_pairs.emplace_back(OpeningPair<Params>{ -r_squares[l], fold_polynomial_evals[l] });
fold_poly_opening_pairs.emplace_back(
OpeningPair<Params>{ -r_squares[l], fold_polynomials[l + 1].evaluate(-r_squares[l]) });
}

return { fold_poly_opening_pairs, std::move(fold_polynomials) };
Expand Down
24 changes: 19 additions & 5 deletions cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,25 @@ template <class Params> class GeminiTest : public CommitmentTest<Params> {
// Compute:
// - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
// - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
auto prover_output = Gemini::reduce_prove(this->ck(),
multilinear_evaluation_point,
std::move(batched_unshifted),
std::move(batched_to_be_shifted),
prover_transcript);
auto fold_polynomials = Gemini::compute_fold_polynomials(
multilinear_evaluation_point, std::move(batched_unshifted), std::move(batched_to_be_shifted));

for (size_t l = 0; l < log_n - 1; ++l) {
std::string label = "FOLD_" + std::to_string(l + 1);
auto commitment = this->ck()->commit(fold_polynomials[l + 2]);
prover_transcript.send_to_verifier(label, commitment);
}

const Fr r_challenge = prover_transcript.get_challenge("Gemini:r");

auto prover_output = Gemini::compute_fold_polynomial_evaluations(
multilinear_evaluation_point, std::move(fold_polynomials), r_challenge);

for (size_t l = 0; l < log_n; ++l) {
std::string label = "Gemini:a_" + std::to_string(l);
const auto& evaluation = prover_output.opening_pairs[l + 1].evaluation;
prover_transcript.send_to_verifier(label, evaluation);
}

// Check that the Fold polynomials have been evaluated correctly in the prover
this->verify_batch_opening_pair(prover_output.opening_pairs, prover_output.witnesses);
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ template <typename Params> class BilinearAccumulator {
*/
BilinearAccumulator(const OpeningClaim<Params>& claim, const Commitment& proof)
: lhs(claim.commitment - (Commitment::one() * claim.opening_pair.evaluation) +
(proof * claim.opening_pair.query))
(proof * claim.opening_pair.challenge))
, rhs(-proof)
{}

Expand Down Expand Up @@ -73,7 +73,7 @@ template <typename Params> class UnivariateOpeningScheme {
{
Polynomial quotient(polynomial);
quotient[0] -= opening_pair.evaluation;
quotient.factor_roots(opening_pair.query);
quotient.factor_roots(opening_pair.challenge);
CommitmentAffine quotient_commitment = ck->commit(quotient);

transcript.send_to_verifier("KZG:W", quotient_commitment);
Expand Down
36 changes: 25 additions & 11 deletions cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ TYPED_TEST(BilinearAccumulationTest, single)

auto witness = this->random_polynomial(n);
auto commitment = this->commit(witness);
auto query = Fr::random_element();
auto evaluation = witness.evaluate(query);
auto opening_pair = OpeningPair<TypeParam>{ query, evaluation };
auto challenge = Fr::random_element();
auto evaluation = witness.evaluate(challenge);
auto opening_pair = OpeningPair<TypeParam>{ challenge, evaluation };
auto opening_claim = OpeningClaim<TypeParam>{ opening_pair, commitment };

auto prover_transcript = ProverTranscript<Fr>::init_empty();
Expand Down Expand Up @@ -112,14 +112,28 @@ TYPED_TEST(BilinearAccumulationTest, GeminiShplonkKzgWithShift)

// Run the full prover PCS protocol:

// Gemini prover output:
// - opening pairs: d+1 pairs (r, a_0_pos) and (-r^{2^l}, a_l), l = 0:d-1
// - witness: the d+1 polynomials Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), l = 1:d-1
auto gemini_prover_output = Gemini::reduce_prove(this->ck(),
mle_opening_point,
std::move(batched_unshifted),
std::move(batched_to_be_shifted),
prover_transcript);
// Compute:
// - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1
// - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1
auto fold_polynomials = Gemini::compute_fold_polynomials(
mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted));

for (size_t l = 0; l < log_n - 1; ++l) {
std::string label = "FOLD_" + std::to_string(l + 1);
auto commitment = this->ck()->commit(fold_polynomials[l + 2]);
prover_transcript.send_to_verifier(label, commitment);
}

const Fr r_challenge = prover_transcript.get_challenge("Gemini:r");

auto gemini_prover_output =
Gemini::compute_fold_polynomial_evaluations(mle_opening_point, std::move(fold_polynomials), r_challenge);

for (size_t l = 0; l < log_n; ++l) {
std::string label = "Gemini:a_" + std::to_string(l);
const auto& evaluation = gemini_prover_output.opening_pairs[l + 1].evaluation;
prover_transcript.send_to_verifier(label, evaluation);
}

// Shplonk prover output:
// - opening pair: (z_challenge, 0)
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/barretenberg/honk/pcs/shplonk/shplonk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ template <typename Params> using OutputWitness = barretenberg::Polynomial<typena
* @tparam Params CommitmentScheme parameters
*/
template <typename Params> struct ProverOutput {
OpeningPair<Params> opening_pair; // single opening pair (query, G(query) = 0)
OpeningPair<Params> opening_pair; // single opening pair (challenge, evaluation)
OutputWitness<Params> witness; // single polynomial G(X)
};

Expand Down
Loading