diff --git a/cpp/src/barretenberg/honk/pcs/claim.hpp b/cpp/src/barretenberg/honk/pcs/claim.hpp index 365e663142..55f26bfd15 100644 --- a/cpp/src/barretenberg/honk/pcs/claim.hpp +++ b/cpp/src/barretenberg/honk/pcs/claim.hpp @@ -12,7 +12,7 @@ template 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; @@ -31,7 +31,7 @@ template class OpeningClaim { using Fr = typename Params::Fr; public: - // (query r, evaluation v = p(r)) + // (challenge r, evaluation v = p(r)) OpeningPair opening_pair; // commitment to univariate polynomial p(X) CommitmentAffine commitment; @@ -46,7 +46,7 @@ template class OpeningClaim { */ bool verify(CK* ck, const barretenberg::Polynomial& 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; } diff --git a/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp b/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp index 9e3924a947..e4b0126949 100644 --- a/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp +++ b/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp @@ -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, @@ -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 struct Proof { - /** @brief Commitments to folded polynomials (size = m-1) - * - * [ C₁, …, Cₘ₋₁], where Cₗ = commit(Aₗ(X)) of size 2ᵐ⁻ˡ - */ - std::vector commitments; - - /** - * @brief Evaluations of batched and folded polynomials (size m) - * - * [A₀(-r) , ..., Aₘ₋₁(-r^{2ᵐ⁻¹})] - */ - std::vector 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] @@ -100,35 +76,30 @@ template 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 */ - static ProverOutput reduce_prove(std::shared_ptr ck, - std::span mle_opening_point, - const Polynomial&& batched_shifted, /* unshifted */ - const Polynomial&& batched_to_be_shifted, /* to-be-shifted */ - ProverTranscript& transcript) + static std::vector compute_fold_polynomials(std::span 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 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); @@ -163,79 +134,64 @@ template 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 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 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 compute_fold_polynomial_evaluations(std::span mle_opening_point, + std::vector&& 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 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 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> fold_poly_opening_pairs; fold_poly_opening_pairs.reserve(num_variables + 1); - // ( r, A₀(r) ) - fold_poly_opening_pairs.emplace_back(OpeningPair{ r_challenge, a_0_pos }); - // (-r, Aₗ(−r^{2ˡ}) ) + // Compute first opening pair {r, A₀(r)} + fold_poly_opening_pairs.emplace_back( + OpeningPair{ 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{ -r_squares[l], fold_polynomial_evals[l] }); + fold_poly_opening_pairs.emplace_back( + OpeningPair{ -r_squares[l], fold_polynomials[l + 1].evaluate(-r_squares[l]) }); } return { fold_poly_opening_pairs, std::move(fold_polynomials) }; diff --git a/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp b/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp index d0f5d8cda4..17af010e23 100644 --- a/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp +++ b/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp @@ -55,11 +55,25 @@ template class GeminiTest : public CommitmentTest { // 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); diff --git a/cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp b/cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp index 17385428b3..0a38b09c3a 100644 --- a/cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp +++ b/cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp @@ -31,7 +31,7 @@ template class BilinearAccumulator { */ BilinearAccumulator(const OpeningClaim& 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) {} @@ -73,7 +73,7 @@ template 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); diff --git a/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp b/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp index 664f437cbe..ebbf44af0a 100644 --- a/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp +++ b/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp @@ -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{ query, evaluation }; + auto challenge = Fr::random_element(); + auto evaluation = witness.evaluate(challenge); + auto opening_pair = OpeningPair{ challenge, evaluation }; auto opening_claim = OpeningClaim{ opening_pair, commitment }; auto prover_transcript = ProverTranscript::init_empty(); @@ -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) diff --git a/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.hpp b/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.hpp index e73105085b..f09be9da05 100644 --- a/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.hpp +++ b/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.hpp @@ -39,7 +39,7 @@ template using OutputWitness = barretenberg::Polynomial struct ProverOutput { - OpeningPair opening_pair; // single opening pair (query, G(query) = 0) + OpeningPair opening_pair; // single opening pair (challenge, evaluation) OutputWitness witness; // single polynomial G(X) }; diff --git a/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.test.cpp b/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.test.cpp index 56b9871900..2e406414f5 100644 --- a/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.test.cpp +++ b/cpp/src/barretenberg/honk/pcs/shplonk/shplonk.test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../commitment_key.test.hpp" #include "barretenberg/honk/pcs/claim.hpp" @@ -14,56 +15,51 @@ template class ShplonkTest : public CommitmentTest {}; TYPED_TEST_SUITE(ShplonkTest, CommitmentSchemeParams); -// Test of Shplonk prover/verifier using real Gemini claim -TYPED_TEST(ShplonkTest, GeminiShplonk) +// Test of Shplonk prover/verifier for two polynomials of different size, each opened at a single (different) point +TYPED_TEST(ShplonkTest, ShplonkSimple) { using Shplonk = SingleBatchOpeningScheme; - using Gemini = gemini::MultilinearReductionScheme; using Fr = typename TypeParam::Fr; - using Commitment = typename TypeParam::Commitment; using Polynomial = typename barretenberg::Polynomial; + using OpeningPair = OpeningPair; + using OpeningClaim = OpeningClaim; const size_t n = 16; - const size_t log_n = 4; auto prover_transcript = ProverTranscript::init_empty(); - const Fr rho = Fr::random_element(); + // Generate two random (unrelated) polynomials of two different sizes, as well as their evaluations at a (single but + // different) random point and their commitments. + const auto r1 = Fr::random_element(); + auto poly1 = this->random_polynomial(n); + const auto eval1 = poly1.evaluate(r1); + const auto commitment1 = this->commit(poly1); - const auto u = this->random_evaluation_point(log_n); - auto poly = this->random_polynomial(n); - const auto commitment = this->commit(poly); - const auto eval = poly.evaluate_mle(u); + const auto r2 = Fr::random_element(); + auto poly2 = this->random_polynomial(n / 2); + const auto eval2 = poly2.evaluate(r2); + const auto commitment2 = this->commit(poly2); - // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier - std::vector multilinear_evaluations = { eval }; + // Aggregate polynomials and their opening pairs + std::vector opening_pairs = { { r1, eval1 }, { r2, eval2 } }; + std::vector polynomials = { poly1, poly2 }; - std::vector rhos = Gemini::powers_of_rho(rho, multilinear_evaluations.size()); - - // Compute batched multivariate evaluation - Fr batched_evaluation = multilinear_evaluations[0] * rhos[0]; - - Polynomial batched_unshifted(n); - Polynomial batched_to_be_shifted(n); - batched_unshifted.add_scaled(poly, rhos[0]); - - Commitment batched_commitment_unshifted = commitment * rhos[0]; - Commitment batched_commitment_to_be_shifted = Commitment::zero(); - - auto gemini_prover_output = Gemini::reduce_prove( - this->ck(), u, std::move(batched_unshifted), std::move(batched_to_be_shifted), prover_transcript); - - const auto [prover_opening_pair, shplonk_prover_witness] = Shplonk::reduce_prove( - this->ck(), gemini_prover_output.opening_pairs, gemini_prover_output.witnesses, prover_transcript); + // Execute the shplonk prover functionality + const auto [prover_opening_pair, shplonk_prover_witness] = + Shplonk::reduce_prove(this->ck(), opening_pairs, polynomials, prover_transcript); + // An intermediate check to confirm the opening of the shplonk prover witness Q this->verify_opening_pair(prover_opening_pair, shplonk_prover_witness); - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + // Aggregate polynomial commitments and their opening pairs + std::vector opening_claims; + opening_claims.emplace_back(OpeningClaim{ opening_pairs[0], commitment1 }); + opening_claims.emplace_back(OpeningClaim{ opening_pairs[1], commitment2 }); - auto gemini_verifier_claim = Gemini::reduce_verify( - u, batched_evaluation, batched_commitment_unshifted, batched_commitment_to_be_shifted, verifier_transcript); + auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); - const auto verifier_claim = Shplonk::reduce_verify(gemini_verifier_claim, verifier_transcript); + // Execute the shplonk verifier functionality + const auto verifier_claim = Shplonk::reduce_verify(opening_claims, verifier_transcript); this->verify_opening_claim(verifier_claim, shplonk_prover_witness); } diff --git a/cpp/src/barretenberg/honk/pcs/shplonk/shplonk_single.hpp b/cpp/src/barretenberg/honk/pcs/shplonk/shplonk_single.hpp index 4467128dc4..f68a0f98d5 100644 --- a/cpp/src/barretenberg/honk/pcs/shplonk/shplonk_single.hpp +++ b/cpp/src/barretenberg/honk/pcs/shplonk/shplonk_single.hpp @@ -52,12 +52,12 @@ template class SingleBatchOpeningScheme { Fr current_nu = Fr::one(); for (size_t j = 0; j < num_opening_pairs; ++j) { // (Cⱼ, xⱼ, vⱼ) - const auto& [query, evaluation] = opening_pairs[j]; + const auto& [challenge, evaluation] = opening_pairs[j]; // tmp = ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) tmp = witness_polynomials[j]; tmp[0] -= evaluation; - tmp.factor_roots(query); + tmp.factor_roots(challenge); Q.add_scaled(tmp, current_nu); current_nu *= nu; @@ -74,7 +74,7 @@ template class SingleBatchOpeningScheme { std::vector inverse_vanishing_evals; inverse_vanishing_evals.reserve(num_opening_pairs); for (const auto& pair : opening_pairs) { - inverse_vanishing_evals.emplace_back(z_challenge - pair.query); + inverse_vanishing_evals.emplace_back(z_challenge - pair.challenge); } Fr::batch_invert(inverse_vanishing_evals); @@ -86,7 +86,7 @@ template class SingleBatchOpeningScheme { current_nu = Fr::one(); for (size_t j = 0; j < num_opening_pairs; ++j) { // (Cⱼ, xⱼ, vⱼ) - const auto& [query, evaluation] = opening_pairs[j]; + const auto& [challenge, evaluation] = opening_pairs[j]; // tmp = ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ ) tmp = witness_polynomials[j]; @@ -100,7 +100,7 @@ template class SingleBatchOpeningScheme { } // Return opening pair (z, 0) and polynomial G(X) = Q(X) - Q_z(X) - return { .opening_pair = { .query = z_challenge, .evaluation = Fr::zero() }, .witness = std::move(G) }; + return { .opening_pair = { .challenge = z_challenge, .evaluation = Fr::zero() }, .witness = std::move(G) }; }; /** @@ -139,7 +139,7 @@ template class SingleBatchOpeningScheme { std::vector inverse_vanishing_evals; inverse_vanishing_evals.reserve(num_claims); for (const auto& claim : claims) { - inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.query); + inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge); } Fr::batch_invert(inverse_vanishing_evals); diff --git a/cpp/src/barretenberg/honk/proof_system/prover.cpp b/cpp/src/barretenberg/honk/proof_system/prover.cpp index 5e719dfd17..0673260973 100644 --- a/cpp/src/barretenberg/honk/proof_system/prover.cpp +++ b/cpp/src/barretenberg/honk/proof_system/prover.cpp @@ -303,23 +303,43 @@ template void Prover::execute_univariatization_rou Polynomial batched_poly_to_be_shifted(key->circuit_size); // batched to-be-shifted polynomials batched_poly_to_be_shifted.add_scaled(prover_polynomials[POLYNOMIAL::Z_PERM], rhos[NUM_UNSHIFTED_POLYS]); - // Compute d+1 Fold polynomials and their evaluations - gemini_output = Gemini::reduce_prove(commitment_key, - sumcheck_output.challenge_point, - std::move(batched_poly_unshifted), - std::move(batched_poly_to_be_shifted), - transcript); + // // Reserve space for d+1 Fold polynomials. At the end of this round, the last d-1 polynomials will + // // correspond to Fold^(i). At the end of the full Gemini prover protocol, the first two will + // // be the partially evaluated Fold polynomials Fold_{r}^(0) and Fold_{-r}^(0). + // fold_polynomials.reserve(key->log_circuit_size + 1); + // fold_polynomials.emplace_back(batched_poly_unshifted); + // fold_polynomials.emplace_back(batched_poly_to_be_shifted); + + // Compute d-1 polynomials Fold^(i), i = 1, ..., d-1. + fold_polynomials = Gemini::compute_fold_polynomials( + sumcheck_output.challenge_point, 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 < key->log_circuit_size - 1; ++l) { + std::string label = "Gemini:FOLD_" + std::to_string(l + 1); + auto commitment = commitment_key->commit(fold_polynomials[l + 2]); + transcript.send_to_verifier(label, commitment); + } } /** * - Do Fiat-Shamir to get "r" challenge - * - Compute evaluations of folded polynomials. + * - 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 void Prover::execute_pcs_evaluation_round() { - // TODO(luke): This functionality is performed within Gemini::reduce_prove(), called in the previous round. In the - // 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. + const Fr r_challenge = transcript.get_challenge("Gemini:r"); + + gemini_output = Gemini::compute_fold_polynomial_evaluations( + sumcheck_output.challenge_point, std::move(fold_polynomials), r_challenge); + + for (size_t l = 0; l < key->log_circuit_size; ++l) { + std::string label = "Gemini:a_" + std::to_string(l); + const auto& evaluation = gemini_output.opening_pairs[l + 1].evaluation; + transcript.send_to_verifier(label, evaluation); + } } /** diff --git a/cpp/src/barretenberg/honk/proof_system/prover.hpp b/cpp/src/barretenberg/honk/proof_system/prover.hpp index 97ad588e2b..20a61cc302 100644 --- a/cpp/src/barretenberg/honk/proof_system/prover.hpp +++ b/cpp/src/barretenberg/honk/proof_system/prover.hpp @@ -27,6 +27,7 @@ namespace honk { using Fr = barretenberg::fr; +using Polynomial = Polynomial; template class Prover { @@ -68,6 +69,9 @@ template class Prover { // Container for spans of all polynomials required by the prover (i.e. all multivariates evaluated by Sumcheck). std::array, honk::StandardArithmetization::POLYNOMIAL::COUNT> prover_polynomials; + // Container for d + 1 Fold polynomials produced by Gemini + std::vector fold_polynomials; + // Honk only needs a small portion of the functionality but may be fine to use existing work_queue // NOTE: this is not currently in use, but it may well be used in the future. // TODO(Adrian): Uncomment when we need this again. diff --git a/cpp/src/barretenberg/honk/proof_system/verifier.cpp b/cpp/src/barretenberg/honk/proof_system/verifier.cpp index 24cfecc6bb..8fe2587043 100644 --- a/cpp/src/barretenberg/honk/proof_system/verifier.cpp +++ b/cpp/src/barretenberg/honk/proof_system/verifier.cpp @@ -143,7 +143,7 @@ template bool Verifier::verify_pro return false; } - auto [multivariate_query, multivariate_evaluations] = *sumcheck_output; + auto [multivariate_challenge, multivariate_evaluations] = *sumcheck_output; // Execute Gemini/Shplonk verification: @@ -181,7 +181,7 @@ template bool Verifier::verify_pro // Produce a Gemini claim consisting of: // - d+1 commitments [Fold_{r}^(0)], [Fold_{-r}^(0)], and [Fold^(l)], l = 1:d-1 // - d+1 evaluations a_0_pos, and a_l, l = 0:d-1 - auto gemini_claim = Gemini::reduce_verify(multivariate_query, + auto gemini_claim = Gemini::reduce_verify(multivariate_challenge, batched_evaluation, batched_commitment_unshifted, batched_commitment_to_be_shifted, diff --git a/cpp/src/barretenberg/honk/transcript/transcript.hpp b/cpp/src/barretenberg/honk/transcript/transcript.hpp index f4846d454c..89cef26219 100644 --- a/cpp/src/barretenberg/honk/transcript/transcript.hpp +++ b/cpp/src/barretenberg/honk/transcript/transcript.hpp @@ -272,4 +272,4 @@ template class VerifierTranscript : public BaseTranscript { return element; } }; -} // namespace honk \ No newline at end of file +} // namespace honk diff --git a/cpp/src/barretenberg/honk/transcript/transcript.test.cpp b/cpp/src/barretenberg/honk/transcript/transcript.test.cpp index 5b333622dd..d9c8bc8c74 100644 --- a/cpp/src/barretenberg/honk/transcript/transcript.test.cpp +++ b/cpp/src/barretenberg/honk/transcript/transcript.test.cpp @@ -248,4 +248,4 @@ TYPED_TEST(TranscriptTest, VerifierMistake) // Challenges will not agree but neither will the manifests EXPECT_NE(prover_alpha, verifier_alpha); EXPECT_NE(prover_transcript.get_manifest(), verifier_transcript.get_manifest()); -} \ No newline at end of file +}