From e194f55f8747405e6cc01a2d47bb3e6e5d170e3d Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 15 Aug 2023 15:53:17 +0000 Subject: [PATCH] tests passing through gemini --- .../barretenberg/honk/pcs/gemini/gemini.cpp | 129 ---------------- .../barretenberg/honk/pcs/gemini/gemini.hpp | 142 ++++++++++++++++-- .../verifier/ultra_recursive_verifier.cpp | 34 ++--- .../recursion/honk/verifier/verifier.test.cpp | 4 +- 4 files changed, 141 insertions(+), 168 deletions(-) diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.cpp index fe2b0dbde86f..3f5bf74fc5f7 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.cpp @@ -186,136 +186,7 @@ ProverOutput GeminiProver_::compute_fold_polynomial_evaluations(st return { fold_poly_opening_pairs, std::move(fold_polynomials) }; }; -/** - * @brief Returns univariate opening claims for the Fold polynomials to be checked later - * - * @param mle_opening_point the MLE evaluation point u - * @param batched_evaluation batched evaluation from multivariate evals at the point u - * @param batched_f batched commitment to unshifted polynomials - * @param batched_g batched commitment to to-be-shifted polynomials - * @param proof commitments to the m-1 folded polynomials, and alleged evaluations. - * @param transcript - * @return Fold polynomial opening claims: (r, A₀(r), C₀₊), (-r, A₀(-r), C₀₋), and - * (Cⱼ, Aⱼ(-r^{2ʲ}), -r^{2}), j = [1, ..., m-1] - */ - -template -std::vector> GeminiVerifier_::reduce_verification(std::span mle_opening_point, /* u */ - const Fr batched_evaluation, /* all */ - GroupElement& batched_f, /* unshifted */ - GroupElement& batched_g, /* to-be-shifted */ - VerifierTranscript& transcript) -{ - const size_t num_variables = mle_opening_point.size(); - - // Get polynomials Fold_i, i = 1,...,m-1 from transcript - std::vector commitments; - commitments.reserve(num_variables - 1); - for (size_t i = 0; i < num_variables - 1; ++i) { - auto commitment = transcript.template receive_from_prover("Gemini:FOLD_" + std::to_string(i + 1)); - commitments.emplace_back(commitment); - } - - // compute vector of powers of random evaluation point r - const Fr r = transcript.get_challenge("Gemini:r"); - std::vector r_squares = squares_of_r(r, num_variables); - - // Get evaluations a_i, i = 0,...,m-1 from transcript - std::vector evaluations; - evaluations.reserve(num_variables); - for (size_t i = 0; i < num_variables; ++i) { - auto eval = transcript.template receive_from_prover("Gemini:a_" + std::to_string(i)); - evaluations.emplace_back(eval); - } - - // Compute evaluation A₀(r) - auto a_0_pos = compute_eval_pos(batched_evaluation, mle_opening_point, r_squares, evaluations); - - // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] + r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] - // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] - r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] - auto [c0_r_pos, c0_r_neg] = compute_simulated_commitments(batched_f, batched_g, r); - - std::vector> fold_polynomial_opening_claims; - fold_polynomial_opening_claims.reserve(num_variables + 1); - - // ( [A₀₊], r, A₀(r) ) - fold_polynomial_opening_claims.emplace_back(OpeningClaim{ { r, a_0_pos }, c0_r_pos }); - // ( [A₀₋], -r, A₀(-r) ) - fold_polynomial_opening_claims.emplace_back(OpeningClaim{ { -r, evaluations[0] }, c0_r_neg }); - for (size_t l = 0; l < num_variables - 1; ++l) { - // ([A₀₋], −r^{2ˡ}, Aₗ(−r^{2ˡ}) ) - fold_polynomial_opening_claims.emplace_back( - OpeningClaim{ { -r_squares[l + 1], evaluations[l + 1] }, commitments[l] }); - } - - return fold_polynomial_opening_claims; -}; - -/** - * @brief Compute the expected evaluation of the univariate commitment to the batched polynomial. - * - * @param batched_mle_eval The evaluation of the folded polynomials - * @param mle_vars MLE opening point u - * @param r_squares squares of r, r², ..., r^{2ᵐ⁻¹} - * @param fold_polynomial_evals series of Aᵢ₋₁(−r^{2ⁱ⁻¹}) - * @return evaluation A₀(r) - */ -template -typename Curve::ScalarField GeminiVerifier_::compute_eval_pos(const Fr batched_mle_eval, - std::span mle_vars, - std::span r_squares, - std::span fold_polynomial_evals) -{ - const size_t num_variables = mle_vars.size(); - - const auto& evals = fold_polynomial_evals; - - // Initialize eval_pos with batched MLE eval v = ∑ⱼ ρʲ vⱼ + ∑ⱼ ρᵏ⁺ʲ v↺ⱼ - Fr eval_pos = batched_mle_eval; - for (size_t l = num_variables; l != 0; --l) { - const Fr r = r_squares[l - 1]; // = rₗ₋₁ = r^{2ˡ⁻¹} - const Fr eval_neg = evals[l - 1]; // = Aₗ₋₁(−r^{2ˡ⁻¹}) - const Fr u = mle_vars[l - 1]; // = uₗ₋₁ - - // The folding property ensures that - // Aₗ₋₁(r^{2ˡ⁻¹}) + Aₗ₋₁(−r^{2ˡ⁻¹}) Aₗ₋₁(r^{2ˡ⁻¹}) - Aₗ₋₁(−r^{2ˡ⁻¹}) - // Aₗ(r^{2ˡ}) = (1-uₗ₋₁) ----------------------------- + uₗ₋₁ ----------------------------- - // 2 2r^{2ˡ⁻¹} - // We solve the above equation in Aₗ₋₁(r^{2ˡ⁻¹}), using the previously computed Aₗ(r^{2ˡ}) in eval_pos - // and using Aₗ₋₁(−r^{2ˡ⁻¹}) sent by the prover in the proof. - eval_pos = ((r * eval_pos * 2) - eval_neg * (r * (Fr(1) - u) - u)) / (r * (Fr(1) - u) + u); - } - - return eval_pos; // return A₀(r) -}; - -/** - * @brief Computes two commitments to A₀ partially evaluated in r and -r. - * - * @param batched_f batched commitment to non-shifted polynomials - * @param batched_g batched commitment to to-be-shifted polynomials - * @param r evaluation point at which we have partially evaluated A₀ at r and -r. - * @return std::pair c0_r_pos, c0_r_neg - */ -template -std::pair GeminiVerifier_::compute_simulated_commitments( - GroupElement& batched_f, GroupElement& batched_g, Fr r) -{ - // C₀ᵣ₊ = [F] + r⁻¹⋅[G] - GroupElement C0_r_pos = batched_f; - // C₀ᵣ₋ = [F] - r⁻¹⋅[G] - GroupElement C0_r_neg = batched_f; - Fr r_inv = r.invert(); - if (!batched_g.is_point_at_infinity()) { - batched_g *= r_inv; - C0_r_pos += batched_g; - C0_r_neg -= batched_g; - } - return { C0_r_pos, C0_r_neg }; -}; template class GeminiProver_; template class GeminiProver_; -template class GeminiVerifier_; -template class GeminiVerifier_; }; // namespace proof_system::honk::pcs::gemini diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp index 27ab3969762a..0a84028a676d 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp @@ -64,11 +64,11 @@ template struct ProverOutput { /** * @brief Compute powers of challenge ρ - * - * @tparam Fr - * @param rho - * @param num_powers - * @return std::vector + * + * @tparam Fr + * @param rho + * @param num_powers + * @return std::vector */ template inline std::vector powers_of_rho(const Fr rho, const size_t num_powers) { @@ -107,8 +107,8 @@ template class GeminiProver_ { Polynomial&& batched_to_be_shifted); static ProverOutput compute_fold_polynomial_evaluations(std::span mle_opening_point, - std::vector&& fold_polynomials, - const Fr& r_challenge); + std::vector&& fold_polynomials, + const Fr& r_challenge); }; // namespace proof_system::honk::pcs::gemini template class GeminiVerifier_ { @@ -117,26 +117,136 @@ template class GeminiVerifier_ { using Commitment = typename Curve::AffineElement; public: + /** + * @brief Returns univariate opening claims for the Fold polynomials to be checked later + * + * @param mle_opening_point the MLE evaluation point u + * @param batched_evaluation batched evaluation from multivariate evals at the point u + * @param batched_f batched commitment to unshifted polynomials + * @param batched_g batched commitment to to-be-shifted polynomials + * @param proof commitments to the m-1 folded polynomials, and alleged evaluations. + * @param transcript + * @return Fold polynomial opening claims: (r, A₀(r), C₀₊), (-r, A₀(-r), C₀₋), and + * (Cⱼ, Aⱼ(-r^{2ʲ}), -r^{2}), j = [1, ..., m-1] + */ static std::vector> reduce_verification(std::span mle_opening_point, /* u */ - const Fr batched_evaluation, /* all */ - GroupElement& batched_f, /* unshifted */ - GroupElement& batched_g, /* to-be-shifted */ - VerifierTranscript& transcript); + const Fr batched_evaluation, /* all */ + GroupElement& batched_f, /* unshifted */ + GroupElement& batched_g, /* to-be-shifted */ + auto& transcript) + { + const size_t num_variables = mle_opening_point.size(); + + // Get polynomials Fold_i, i = 1,...,m-1 from transcript + std::vector commitments; + commitments.reserve(num_variables - 1); + for (size_t i = 0; i < num_variables - 1; ++i) { + auto commitment = + transcript.template receive_from_prover("Gemini:FOLD_" + std::to_string(i + 1)); + commitments.emplace_back(commitment); + } + + // compute vector of powers of random evaluation point r + const Fr r = transcript.get_challenge("Gemini:r"); + std::vector r_squares = squares_of_r(r, num_variables); + + // Get evaluations a_i, i = 0,...,m-1 from transcript + std::vector evaluations; + evaluations.reserve(num_variables); + for (size_t i = 0; i < num_variables; ++i) { + auto eval = transcript.template receive_from_prover("Gemini:a_" + std::to_string(i)); + evaluations.emplace_back(eval); + } + + // Compute evaluation A₀(r) + auto a_0_pos = compute_eval_pos(batched_evaluation, mle_opening_point, r_squares, evaluations); + + // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] + r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] + // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] - r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] + auto [c0_r_pos, c0_r_neg] = compute_simulated_commitments(batched_f, batched_g, r); + + std::vector> fold_polynomial_opening_claims; + fold_polynomial_opening_claims.reserve(num_variables + 1); + + // ( [A₀₊], r, A₀(r) ) + fold_polynomial_opening_claims.emplace_back(OpeningClaim{ { r, a_0_pos }, c0_r_pos }); + // ( [A₀₋], -r, A₀(-r) ) + fold_polynomial_opening_claims.emplace_back(OpeningClaim{ { -r, evaluations[0] }, c0_r_neg }); + for (size_t l = 0; l < num_variables - 1; ++l) { + // ([A₀₋], −r^{2ˡ}, Aₗ(−r^{2ˡ}) ) + fold_polynomial_opening_claims.emplace_back( + OpeningClaim{ { -r_squares[l + 1], evaluations[l + 1] }, commitments[l] }); + } + + return fold_polynomial_opening_claims; + } private: + /** + * @brief Compute the expected evaluation of the univariate commitment to the batched polynomial. + * + * @param batched_mle_eval The evaluation of the folded polynomials + * @param mle_vars MLE opening point u + * @param r_squares squares of r, r², ..., r^{2ᵐ⁻¹} + * @param fold_polynomial_evals series of Aᵢ₋₁(−r^{2ⁱ⁻¹}) + * @return evaluation A₀(r) + */ static Fr compute_eval_pos(const Fr batched_mle_eval, std::span mle_vars, std::span r_squares, - std::span fold_polynomial_evals); + std::span fold_polynomial_evals) + { + const size_t num_variables = mle_vars.size(); + + const auto& evals = fold_polynomial_evals; + + // Initialize eval_pos with batched MLE eval v = ∑ⱼ ρʲ vⱼ + ∑ⱼ ρᵏ⁺ʲ v↺ⱼ + Fr eval_pos = batched_mle_eval; + for (size_t l = num_variables; l != 0; --l) { + const Fr r = r_squares[l - 1]; // = rₗ₋₁ = r^{2ˡ⁻¹} + const Fr eval_neg = evals[l - 1]; // = Aₗ₋₁(−r^{2ˡ⁻¹}) + const Fr u = mle_vars[l - 1]; // = uₗ₋₁ + // The folding property ensures that + // Aₗ₋₁(r^{2ˡ⁻¹}) + Aₗ₋₁(−r^{2ˡ⁻¹}) Aₗ₋₁(r^{2ˡ⁻¹}) - Aₗ₋₁(−r^{2ˡ⁻¹}) + // Aₗ(r^{2ˡ}) = (1-uₗ₋₁) ----------------------------- + uₗ₋₁ ----------------------------- + // 2 2r^{2ˡ⁻¹} + // We solve the above equation in Aₗ₋₁(r^{2ˡ⁻¹}), using the previously computed Aₗ(r^{2ˡ}) in eval_pos + // and using Aₗ₋₁(−r^{2ˡ⁻¹}) sent by the prover in the proof. + eval_pos = ((r * eval_pos * 2) - eval_neg * (r * (Fr(1) - u) - u)) / (r * (Fr(1) - u) + u); + } + + return eval_pos; // return A₀(r) + } + + /** + * @brief Computes two commitments to A₀ partially evaluated in r and -r. + * + * @param batched_f batched commitment to non-shifted polynomials + * @param batched_g batched commitment to to-be-shifted polynomials + * @param r evaluation point at which we have partially evaluated A₀ at r and -r. + * @return std::pair c0_r_pos, c0_r_neg + */ static std::pair compute_simulated_commitments(GroupElement& batched_f, GroupElement& batched_g, - Fr r); + Fr r) + { + // C₀ᵣ₊ = [F] + r⁻¹⋅[G] + GroupElement C0_r_pos = batched_f; + // C₀ᵣ₋ = [F] - r⁻¹⋅[G] + GroupElement C0_r_neg = batched_f; + Fr r_inv = r.invert(); + // WORKTODO: reinstate some kind of !batched_g.is_point_at_infinity() check for stdlib? + // if (!batched_g.is_point_at_infinity()) { + batched_g = batched_g * r_inv; + C0_r_pos += batched_g; + C0_r_neg -= batched_g; + // } + return { C0_r_pos, C0_r_neg }; + } + }; // namespace proof_system::honk::pcs::gemini extern template class GeminiProver_; extern template class GeminiProver_; -extern template class GeminiVerifier_; -extern template class GeminiVerifier_; - } // namespace proof_system::honk::pcs::gemini diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp index 68066b495c1f..644c2614baf3 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp @@ -42,10 +42,10 @@ template bool UltraRecursiveVerifier_::verify_proof(co using FF = typename Flavor::FF; using GroupElement = typename Flavor::GroupElement; using Commitment = typename Flavor::Commitment; - // using Curve = typename Flavor::Curve; - // using PCS = typename Flavor::PCS; - // using Gemini = ::proof_system::honk::pcs::gemini::GeminiVerifier_; + using Curve = typename Flavor::Curve; + using Gemini = ::proof_system::honk::pcs::gemini::GeminiVerifier_; // using Shplonk = pcs::shplonk::ShplonkVerifier_; + // using PCS = typename Flavor::PCS; using VerifierCommitments = typename Flavor::VerifierCommitments; using CommitmentLabels = typename Flavor::CommitmentLabels; @@ -133,20 +133,10 @@ template bool UltraRecursiveVerifier_::verify_proof(co if (!sumcheck_output.has_value()) { return false; } - // else { - // return true; - // } + // Extract multivariate opening point u = (u_0, ..., u_{d-1}) and purported multivariate evaluations at u auto [multivariate_challenge, purported_evaluations] = *sumcheck_output; - // Execute Gemini/Shplonk verification: - - // Construct inputs for Gemini verifier: - // - Multivariate opening point u = (u_0, ..., u_{d-1}) - // - batched unshifted and to-be-shifted polynomial commitments - // auto batched_commitment_unshifted = GroupElement(GroupElement::NativeGroup::zero()); - // auto batched_commitment_to_be_shifted = GroupElement(0); - // Compute powers of batching challenge rho FF rho = transcript.get_challenge("rho"); std::vector rhos = ::proof_system::honk::pcs::gemini::powers_of_rho(rho, Flavor::NUM_ALL_ENTITIES); @@ -175,20 +165,22 @@ template bool UltraRecursiveVerifier_::verify_proof(co // do something silly like set it to rho.pow(0) in the fctn to make it work both native and stdlib? scalars_unshifted[0] = FF::from_witness(builder, 1); + // Batch the commitments to the unshifted and to-be-shifted polynomials using powers of rho auto batched_commitment_unshifted = GroupElement::batch_mul(commitments.get_unshifted(), scalars_unshifted); auto batched_commitment_to_be_shifted = GroupElement::batch_mul(commitments.get_to_be_shifted(), scalars_to_be_shifted); - (void)batched_commitment_unshifted; - (void)batched_commitment_to_be_shifted; // 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_verification(multivariate_challenge, - // batched_evaluation, - // batched_commitment_unshifted, - // batched_commitment_to_be_shifted, - // transcript); + auto gemini_claim = Gemini::reduce_verification(multivariate_challenge, + batched_evaluation, + batched_commitment_unshifted, + batched_commitment_to_be_shifted, + transcript); + + // Note(luke): Temporary. Done only to complete manifest through Gemini. Delete once we proceed to Shplonk. + [[maybe_unused]] FF nu = transcript.get_challenge("Shplonk:nu"); // DEBUG! return true; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp index 8244f08cc912..17507b2d6dcd 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp @@ -90,11 +90,11 @@ template class RecursiveVerifierTest : public testing:: auto recursive_manifest = verifier.transcript.get_manifest(); auto native_manifest = native_verifier.transcript.get_manifest(); // Note: Recursive manifest currently goes only though sumcheck + recursive_manifest.print(); + native_manifest.print(); for (size_t i = 0; i < recursive_manifest.size(); ++i) { EXPECT_EQ(recursive_manifest[i], native_manifest[i]); } - recursive_manifest.print(); - native_manifest.print(); }; public: