diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 0766722893ed..61b0d36b5d39 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -95,6 +95,7 @@ template inline std::vector powers_of_evaluation_challenge(const template class GeminiProver_ { using Fr = typename Curve::ScalarField; + using Commitment = typename Curve::AffineElement; using Polynomial = bb::Polynomial; using Claim = ProverOpeningClaim; @@ -168,7 +169,7 @@ template class GeminiVerifier_ { // compute vector of powers of random evaluation point r const Fr r = transcript->template get_challenge("Gemini:r"); - const std::vector r_squares = gemini::powers_of_evaluation_challenge(r, num_variables); + const std::vector r_squares = gemini::powers_of_evaluation_challenge(r, CONST_PROOF_SIZE_LOG_N); // Get evaluations a_i, i = 0,...,m-1 from transcript const std::vector evaluations = get_gemini_evaluations(num_variables, transcript); @@ -197,22 +198,24 @@ template class GeminiVerifier_ { return fold_polynomial_opening_claims; } - static std::vector get_fold_commitments(const size_t log_circuit_size, auto& transcript) + static std::vector get_fold_commitments([[maybe_unused]] const size_t log_circuit_size, + auto& transcript) { std::vector fold_commitments; - fold_commitments.reserve(log_circuit_size - 1); - for (size_t i = 0; i < log_circuit_size - 1; ++i) { + fold_commitments.reserve(CONST_PROOF_SIZE_LOG_N - 1); + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { const Commitment commitment = transcript->template receive_from_prover("Gemini:FOLD_" + std::to_string(i + 1)); fold_commitments.emplace_back(commitment); } return fold_commitments; } - static std::vector get_gemini_evaluations(const size_t log_circuit_size, auto& transcript) + static std::vector get_gemini_evaluations([[maybe_unused]] const size_t log_circuit_size, auto& transcript) { std::vector gemini_evaluations; - gemini_evaluations.reserve(log_circuit_size); - for (size_t i = 1; i <= log_circuit_size; ++i) { + gemini_evaluations.reserve(CONST_PROOF_SIZE_LOG_N); + + for (size_t i = 1; i <= CONST_PROOF_SIZE_LOG_N; ++i) { const Fr evaluation = transcript->template receive_from_prover("Gemini:a_" + std::to_string(i)); gemini_evaluations.emplace_back(evaluation); } @@ -241,29 +244,43 @@ template class GeminiVerifier_ { * @param fold_polynomial_evals Evaluations \f$ A_{i-1}(-r^{2^{i-1}}) \f$. * @return Evaluation \f$ A_0(r) \f$. */ - static Fr compute_gemini_batched_univariate_evaluation(size_t evaluation_point_size, - Fr& batched_eval_accumulator, - std::span evaluation_point, - std::span challenge_powers, - std::span fold_polynomial_evals) + static Fr compute_gemini_batched_univariate_evaluation( + const size_t num_variables, + Fr& batched_eval_accumulator, + std::span evaluation_point, // CONST_PROOF_SIZE + std::span challenge_powers, // r_squares CONST_PROOF_SIZE_LOG_N + std::span fold_polynomial_evals) { - const size_t num_variables = evaluation_point_size; - const auto& evals = fold_polynomial_evals; // Solve the sequence of linear equations - for (size_t l = num_variables; l != 0; --l) { + for (size_t l = CONST_PROOF_SIZE_LOG_N; l != 0; --l) { // Get r²⁽ˡ⁻¹⁾ const Fr& challenge_power = challenge_powers[l - 1]; - // Get A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) - const Fr& eval_neg = evals[l - 1]; // Get uₗ₋₁ const Fr& u = evaluation_point[l - 1]; + const Fr& eval_neg = evals[l - 1]; + // Get A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) // Compute the numerator - batched_eval_accumulator = + Fr batched_eval_round_acc = ((challenge_power * batched_eval_accumulator * 2) - eval_neg * (challenge_power * (Fr(1) - u) - u)); // Divide by the denominator - batched_eval_accumulator *= (challenge_power * (Fr(1) - u) + u).invert(); + batched_eval_round_acc *= (challenge_power * (Fr(1) - u) + u).invert(); + + bool is_dummy_round = (l > num_variables); + + if constexpr (Curve::is_stdlib_type) { + auto builder = evaluation_point[0].get_context(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure! + stdlib::bool_t dummy_round = stdlib::bool_t(builder, is_dummy_round); + batched_eval_accumulator = + Fr::conditional_assign(dummy_round, batched_eval_accumulator, batched_eval_round_acc); + + } else { + if (!is_dummy_round) { + batched_eval_accumulator = batched_eval_round_acc; + } + } } return batched_eval_accumulator; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp index 05a1cd994477..fde94fdcdb13 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -73,15 +73,23 @@ std::vector::Claim> GeminiProver_::prove( auto fold_polynomials = compute_fold_polynomials( log_n, multilinear_challenge, std::move(batched_unshifted), std::move(batched_to_be_shifted)); - for (size_t l = 0; l < log_n - 1; l++) { - transcript->send_to_verifier("Gemini:FOLD_" + std::to_string(l + 1), - commitment_key->commit(fold_polynomials[l + 2])); + for (size_t l = 0; l < CONST_PROOF_SIZE_LOG_N - 1; l++) { + if (l < log_n - 1) { + transcript->send_to_verifier("Gemini:FOLD_" + std::to_string(l + 1), + commitment_key->commit(fold_polynomials[l + 2])); + } else { + transcript->send_to_verifier("Gemini:FOLD_" + std::to_string(l + 1), Commitment::one()); + } } const Fr r_challenge = transcript->template get_challenge("Gemini:r"); std::vector claims = compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), r_challenge); - for (size_t l = 1; l <= log_n; l++) { - transcript->send_to_verifier("Gemini:a_" + std::to_string(l), claims[l].opening_pair.evaluation); + for (size_t l = 1; l <= CONST_PROOF_SIZE_LOG_N; l++) { + if (l <= log_n) { + transcript->send_to_verifier("Gemini:a_" + std::to_string(l), claims[l].opening_pair.evaluation); + } else { + transcript->send_to_verifier("Gemini:a_" + std::to_string(l), Fr::zero()); + } } return claims; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 98f4aa221477..e39b61292a3d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -128,9 +128,9 @@ template class ShpleminiVerifier_ { const Fr gemini_evaluation_challenge = transcript->template get_challenge("Gemini:r"); // - Get evaluations (A₀(−r), A₁(−r²), ... , Aₙ₋₁(−r²⁽ⁿ⁻¹⁾)) const std::vector gemini_evaluations = GeminiVerifier::get_gemini_evaluations(log_circuit_size, transcript); - // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size, I think this should be CONST_PROOF_SIZE const std::vector gemini_eval_challenge_powers = - gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, log_circuit_size); + gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, CONST_PROOF_SIZE_LOG_N); // Process Shplonk transcript data: // - Get Shplonk batching challenge @@ -143,7 +143,7 @@ template class ShpleminiVerifier_ { // Get Shplonk opening point z const Fr shplonk_evaluation_challenge = transcript->template get_challenge("Shplonk:z"); // Start computing the scalar to be multiplied by [1]₁ - Fr constant_term_accumulator{ 0 }; + Fr constant_term_accumulator = Fr(0); // Initialize the vector of scalars placing the scalar 1 correposnding to Q_commitment std::vector scalars; @@ -167,7 +167,7 @@ template class ShpleminiVerifier_ { // Place the commitments to prover polynomials in the commitments vector. Compute the evaluation of the // batched multilinear polynomial. Populate the vector of scalars for the final batch mul - Fr batched_evaluation{ 0 }; + Fr batched_evaluation = Fr(0); batch_multivariate_opening_claims(unshifted_commitments, shifted_commitments, unshifted_evaluations, @@ -334,17 +334,34 @@ template class ShpleminiVerifier_ { std::vector& scalars, Fr& constant_term_accumulator) { + // Initialize batching challenge as ν² - Fr current_batching_challenge = shplonk_batching_challenge * shplonk_batching_challenge; - for (size_t j = 0; j < log_circuit_size - 1; ++j) { + Fr current_batching_challenge = shplonk_batching_challenge.sqr(); + for (size_t j = 0; j < CONST_PROOF_SIZE_LOG_N - 1; ++j) { + bool is_dummy_round = j >= (log_circuit_size - 1); // Compute the scaling factor (ν²⁺ⁱ) / (z + r²⁽ⁱ⁺²⁾) for i = 0, … , d-2 Fr scaling_factor = current_batching_challenge * inverse_vanishing_evals[j + 2]; - // Place the scaling factor to the 'scalars' vector - scalars.emplace_back(-scaling_factor); + + if constexpr (Curve::is_stdlib_type) { + auto builder = shplonk_batching_challenge.get_context(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure! + stdlib::bool_t dummy_round = stdlib::bool_t(builder, is_dummy_round); + Fr zero = Fr(0); + zero.convert_constant_to_fixed_witness(builder); + scaling_factor = Fr::conditional_assign(dummy_round, zero, scaling_factor); + } else { + if (is_dummy_round) { + scaling_factor = 0; + } + } + // Add Aᵢ(−r²ⁱ) for i = 1, … , n-1 to the constant term accumulator constant_term_accumulator += scaling_factor * gemini_evaluations[j + 1]; // Update the batching challenge current_batching_challenge *= shplonk_batching_challenge; + + // Place the scaling factor to the 'scalars' vector + scalars.emplace_back(-scaling_factor); // Move com(Aᵢ) to the 'commitments' vector commitments.emplace_back(std::move(fold_commitments[j])); } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp index b1aad152f59b..557393601796 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -216,7 +216,6 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) scalars, expected_constant_term_accumulator); - EXPECT_EQ(commitments.size(), prover_commitments.size()); // Compute the group element using the output of Shplemini method GroupElement shplemini_result = batch_mul_native(commitments, scalars); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp index f8db79c9a2a2..c5b4d8334b02 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp @@ -31,7 +31,7 @@ template class ShplonkProver_ { public: /** - * @brief Compute batched quotient polynomial Q(X) = ∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) + * @brief Compute batched quotient polynomial Q(X) = ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) * * @param opening_claims list of prover opening claims {fⱼ(X), (xⱼ, vⱼ)} for a witness polynomial fⱼ(X), s.t. fⱼ(xⱼ) * = vⱼ. @@ -45,7 +45,7 @@ template class ShplonkProver_ { for (const auto& claim : opening_claims) { max_poly_size = std::max(max_poly_size, claim.polynomial.size()); } - // Q(X) = ∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) + // Q(X) = ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) Polynomial Q(max_poly_size); Polynomial tmp(max_poly_size); @@ -71,7 +71,7 @@ template class ShplonkProver_ { * * @param opening_pairs list of opening pairs (xⱼ, vⱼ) for a witness polynomial fⱼ(X), s.t. fⱼ(xⱼ) = vⱼ. * @param witness_polynomials list of polynomials fⱼ(X). - * @param batched_quotient_Q Q(X) = ∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) + * @param batched_quotient_Q Q(X) = ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) * @param nu_challenge * @param z_challenge * @return Output{OpeningPair, Polynomial} @@ -92,21 +92,21 @@ template class ShplonkProver_ { } Fr::batch_invert(inverse_vanishing_evals); - // G(X) = Q(X) - Q_z(X) = Q(X) - ∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ ), + // G(X) = Q(X) - Q_z(X) = Q(X) - ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( z − xⱼ ), // s.t. G(r) = 0 Polynomial G(std::move(batched_quotient_Q)); // G(X) = Q(X) - // G₀ = ∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ) + // G₀ = ∑ⱼ νʲ ⋅ vⱼ / ( z − xⱼ ) Fr current_nu = Fr::one(); Polynomial tmp(G.size()); size_t idx = 0; for (const auto& claim : opening_claims) { - // tmp = ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ ) + // tmp = νʲ ⋅ ( fⱼ(X) − vⱼ) / ( z − xⱼ ) tmp = claim.polynomial; tmp.at(0) = tmp[0] - claim.opening_pair.evaluation; - Fr scaling_factor = current_nu * inverse_vanishing_evals[idx]; // = ρʲ / ( r − xⱼ ) + Fr scaling_factor = current_nu * inverse_vanishing_evals[idx]; // = νʲ / (z − xⱼ ) - // G -= ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ ) + // G -= νʲ ⋅ ( fⱼ(X) − vⱼ) / ( z − xⱼ ) G.add_scaled(tmp, -scaling_factor); current_nu *= nu_challenge; @@ -174,15 +174,15 @@ template class ShplonkVerifier_ { const Fr z_challenge = transcript->template get_challenge("Shplonk:z"); - // [G] = [Q] - ∑ⱼ ρʲ / ( r − xⱼ )⋅[fⱼ] + G₀⋅[1] - // = [Q] - [∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ )] + // [G] = [Q] - ∑ⱼ ρʲ / (z − xⱼ )⋅[fⱼ] + G₀⋅[1] + // = [Q] - [∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / (z − xⱼ )] GroupElement G_commitment; // compute simulated commitment to [G] as a linear combination of // [Q], { [fⱼ] }, [1]: // [G] = [Q] - ∑ⱼ (1/zⱼ(r))[Bⱼ] + ( ∑ⱼ (1/zⱼ(r)) Tⱼ(r) )[1] // = [Q] - ∑ⱼ (1/zⱼ(r))[Bⱼ] + G₀ [1] - // G₀ = ∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ) + // G₀ = ∑ⱼ ρʲ ⋅ vⱼ / (z − xⱼ ) auto G_commitment_constant = Fr(0); // TODO(#673): The recursive and non-recursive (native) logic is completely separated via the following @@ -196,8 +196,8 @@ template class ShplonkVerifier_ { std::vector commitments; std::vector scalars; - // [G] = [Q] - ∑ⱼ ρʲ / ( r − xⱼ )⋅[fⱼ] + G₀⋅[1] - // = [Q] - [∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ )] + // [G] = [Q] - ∑ⱼ νʲ / (z − xⱼ )⋅[fⱼ] + G₀⋅[1] + // = [Q] - [∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / (z − xⱼ )] commitments.emplace_back(Q_commitment); scalars.emplace_back(Fr(builder, 1)); // Fr(1) @@ -215,9 +215,9 @@ template class ShplonkVerifier_ { // (Cⱼ, xⱼ, vⱼ) const auto& [opening_pair, commitment] = claims[j]; - Fr scaling_factor = current_nu * inverse_vanishing_evals[j]; // = ρʲ / ( r − xⱼ ) + Fr scaling_factor = current_nu * inverse_vanishing_evals[j]; // = νʲ / (z − xⱼ ) - // G₀ += ρʲ / ( r − xⱼ ) ⋅ vⱼ + // G₀ += νʲ / (z − xⱼ ) ⋅ vⱼ G_commitment_constant += scaling_factor * opening_pair.evaluation; current_nu *= nu; @@ -230,12 +230,12 @@ template class ShplonkVerifier_ { commitments.emplace_back(g1_identity); scalars.emplace_back(G_commitment_constant); - // [G] += G₀⋅[1] = [G] + (∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ))⋅[1] + // [G] += G₀⋅[1] = [G] + (∑ⱼ νʲ ⋅ vⱼ / (z − xⱼ ))⋅[1] G_commitment = GroupElement::batch_mul(commitments, scalars); } else { - // [G] = [Q] - ∑ⱼ ρʲ / ( r − xⱼ )⋅[fⱼ] + G₀⋅[1] - // = [Q] - [∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ )] + // [G] = [Q] - ∑ⱼ νʲ / (z − xⱼ )⋅[fⱼ] + G₀⋅[1] + // = [Q] - [∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / (z − xⱼ )] G_commitment = Q_commitment; // Compute {ẑⱼ(r)}ⱼ , where ẑⱼ(r) = 1/zⱼ(r) = 1/(r - xⱼ) @@ -252,18 +252,18 @@ template class ShplonkVerifier_ { // (Cⱼ, xⱼ, vⱼ) const auto& [opening_pair, commitment] = claims[j]; - Fr scaling_factor = current_nu * inverse_vanishing_evals[j]; // = ρʲ / ( r − xⱼ ) + Fr scaling_factor = current_nu * inverse_vanishing_evals[j]; // = νʲ / (z − xⱼ ) - // G₀ += ρʲ / ( r − xⱼ ) ⋅ vⱼ + // G₀ += νʲ / (z − xⱼ ) ⋅ vⱼ G_commitment_constant += scaling_factor * opening_pair.evaluation; - // [G] -= ρʲ / ( r − xⱼ )⋅[fⱼ] + // [G] -= νʲ / (z − xⱼ )⋅[fⱼ] G_commitment -= commitment * scaling_factor; current_nu *= nu; } - // [G] += G₀⋅[1] = [G] + (∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ))⋅[1] + // [G] += G₀⋅[1] = [G] + (∑ⱼ νʲ ⋅ vⱼ / (z − xⱼ ))⋅[1] G_commitment += g1_identity * G_commitment_constant; } @@ -273,7 +273,7 @@ template class ShplonkVerifier_ { /** * @brief Computes \f$ \frac{1}{z - r}, \frac{1}{z+r}, \ldots, \frac{1}{z+r^{2^{d-1}}} \f$. * - * @param log_circuit_size \f$ d \f$ + * @param num_gemini_claims \f$ d + 1 \f$ where d = log_circuit_size * @param shplonk_eval_challenge \f$ z \f$ * @param gemini_eval_challenge_powers \f$ (r , r^2, \ldots, r^{2^{d-1}}) \f$ * @return \f[ \left( \frac{1}{z - r}, \frac{1}{z+r}, \ldots, \frac{1}{z+r^{2^{d-1}}} \right) \f] @@ -285,8 +285,24 @@ template class ShplonkVerifier_ { std::vector inverted_denominators; inverted_denominators.reserve(num_gemini_claims); inverted_denominators.emplace_back((shplonk_eval_challenge - gemini_eval_challenge_powers[0]).invert()); + size_t i = 0; for (const auto& gemini_eval_challenge_power : gemini_eval_challenge_powers) { - inverted_denominators.emplace_back((shplonk_eval_challenge + gemini_eval_challenge_power).invert()); + bool is_dummy_round = i > num_gemini_claims; + Fr round_inverted_denominator = (shplonk_eval_challenge + gemini_eval_challenge_power).invert(); + if constexpr (Curve::is_stdlib_type) { + auto builder = shplonk_eval_challenge.get_context(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure! + stdlib::bool_t dummy_round = stdlib::bool_t(builder, is_dummy_round); + Fr zero = Fr(0); + zero.convert_constant_to_fixed_witness(builder); + round_inverted_denominator = Fr::conditional_assign(dummy_round, zero, round_inverted_denominator); + } else { + if (is_dummy_round) { + round_inverted_denominator = 0; + } + } + inverted_denominators.emplace_back(round_inverted_denominator); + i++; } return inverted_denominators; } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp index e1ee3b92fcdf..e7a59d8b3a01 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp @@ -526,7 +526,8 @@ template class ZeroMorphVerifier_ { scalar *= FF(-1); if constexpr (Curve::is_stdlib_type) { auto builder = x_challenge.get_context(); - FF zero = FF::from_witness(builder, 0); + FF zero = FF(0); + zero.convert_constant_to_fixed_witness(builder); stdlib::bool_t dummy_round = stdlib::witness_t(builder, is_dummy_round); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): is it kosher to reassign like this? scalar = FF::conditional_assign(dummy_round, zero, scalar); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp index 1398cefe7e84..02e2de4e920d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp @@ -19,7 +19,8 @@ template class ShpleminiRecursionTest : public CommitmentTest; using Transcript = bb::BaseTranscript>; - constexpr size_t N = 16; - constexpr size_t log_circuit_size = 4; - constexpr size_t NUM_UNSHIFTED = 2; - constexpr size_t NUM_SHIFTED = 1; - srs::init_crs_factory("../srs_db/ignition"); + auto run_shplemini = [](size_t log_circuit_size) { + size_t N = 1 << log_circuit_size; + constexpr size_t NUM_UNSHIFTED = 2; + constexpr size_t NUM_SHIFTED = 1; + std::vector u_challenge(log_circuit_size); + for (size_t idx = 0; idx < log_circuit_size; ++idx) { + u_challenge[idx] = NativeFr::random_element(&shplemini_engine); + }; + // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) + std::vector f_polynomials; // unshifted polynomials + std::vector v_evaluations; + for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { + f_polynomials.emplace_back(Polynomial::random(N, /*shiftable*/ 1)); + v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); + } - std::vector u_challenge(log_circuit_size); - for (size_t idx = 0; idx < log_circuit_size; ++idx) { - u_challenge[idx] = NativeFr::random_element(&shplemini_engine); - }; - // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) - std::vector f_polynomials; // unshifted polynomials - std::vector v_evaluations; - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_polynomials.emplace_back(Polynomial::random(N, /*shiftable*/ 1)); - v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); - } + // Construct some "shifted" multilinear polynomials h_i as the left-shift-by-1 of f_i + std::vector g_polynomials; // to-be-shifted polynomials + std::vector h_polynomials; // shifts of the to-be-shifted polynomials + std::vector w_evaluations; + if constexpr (NUM_SHIFTED > 0) { + for (size_t i = 0; i < NUM_SHIFTED; ++i) { + g_polynomials.emplace_back(f_polynomials[i]); + h_polynomials.emplace_back(g_polynomials[i].shifted()); + w_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge, true)); + } + } - // Construct some "shifted" multilinear polynomials h_i as the left-shift-by-1 of f_i - std::vector g_polynomials; // to-be-shifted polynomials - std::vector h_polynomials; // shifts of the to-be-shifted polynomials - std::vector w_evaluations; - if constexpr (NUM_SHIFTED > 0) { + // Compute commitments [f_i] + std::vector f_commitments; + auto commitment_key = std::make_shared(16384); + for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { + f_commitments.emplace_back(commitment_key->commit(f_polynomials[i])); + } + // Construct container of commitments of the "to-be-shifted" polynomials [g_i] (= [f_i]) + std::vector g_commitments; for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_polynomials.emplace_back(f_polynomials[i]); - h_polynomials.emplace_back(g_polynomials[i].shifted()); - w_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge, true)); + g_commitments.emplace_back(f_commitments[i]); } - } - // Compute commitments [f_i] - std::vector f_commitments; - auto commitment_key = std::make_shared(4096); - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_commitments.emplace_back(commitment_key->commit(f_polynomials[i])); - } - // Construct container of commitments of the "to-be-shifted" polynomials [g_i] (= [f_i]) - std::vector g_commitments; - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_commitments.emplace_back(f_commitments[i]); - } + // Initialize an empty NativeTranscript + auto prover_transcript = NativeTranscript::prover_init_empty(); + auto prover_opening_claims = ShpleminiProver::prove( + N, RefVector(f_polynomials), RefVector(g_polynomials), u_challenge, commitment_key, prover_transcript); + KZG::compute_opening_proof(commitment_key, prover_opening_claims, prover_transcript); + Builder builder; + StdlibProof stdlib_proof = bb::convert_proof_to_witness(&builder, prover_transcript->proof_data); + auto stdlib_verifier_transcript = std::make_shared(stdlib_proof); + stdlib_verifier_transcript->template receive_from_prover("Init"); - // Initialize an empty NativeTranscript - auto prover_transcript = NativeTranscript::prover_init_empty(); - auto prover_opening_claims = ShpleminiProver::prove( - N, RefVector(f_polynomials), RefVector(g_polynomials), u_challenge, commitment_key, prover_transcript); + // Execute Verifier protocol without the need for vk prior the final check + const auto commitments_to_witnesses = [&builder](const auto& commitments) { + std::vector commitments_in_biggroup(commitments.size()); + std::transform(commitments.begin(), + commitments.end(), + commitments_in_biggroup.begin(), + [&builder](const auto& native_commitment) { + return Commitment::from_witness(&builder, native_commitment); + }); + return commitments_in_biggroup; + }; + const auto elements_to_witness = [&](const auto& elements) { + std::vector elements_in_circuit(elements.size()); + std::transform( + elements.begin(), elements.end(), elements_in_circuit.begin(), [&builder](const auto& native_element) { + return Fr::from_witness(&builder, native_element); + }); + return elements_in_circuit; + }; + auto stdlib_f_commitments = commitments_to_witnesses(f_commitments); + auto stdlib_g_commitments = commitments_to_witnesses(g_commitments); + auto stdlib_v_evaluations = elements_to_witness(v_evaluations); + auto stdlib_w_evaluations = elements_to_witness(w_evaluations); - Builder builder; - StdlibProof stdlib_proof = bb::convert_proof_to_witness(&builder, prover_transcript->proof_data); - auto stdlib_verifier_transcript = std::make_shared(stdlib_proof); - [[maybe_unused]] auto _ = stdlib_verifier_transcript->template receive_from_prover("Init"); + std::vector u_challenge_in_circuit; + u_challenge_in_circuit.reserve(CONST_PROOF_SIZE_LOG_N); + auto u_iter = u_challenge.begin(); - // Execute Verifier protocol without the need for vk prior the final check - const auto commitments_to_witnesses = [&builder](const auto& commitments) { - std::vector commitments_in_biggroup(commitments.size()); - std::transform(commitments.begin(), - commitments.end(), - commitments_in_biggroup.begin(), - [&builder](const auto& native_commitment) { - return Commitment::from_witness(&builder, native_commitment); - }); - return commitments_in_biggroup; - }; - const auto elements_to_witness = [&](const auto& elements) { - std::vector elements_in_circuit(elements.size()); - std::transform(elements.begin(), - elements.end(), - elements_in_circuit.begin(), - [&builder](const auto& native_element) { return Fr::from_witness(&builder, native_element); }); - return elements_in_circuit; - }; - auto stdlib_f_commitments = commitments_to_witnesses(f_commitments); - auto stdlib_g_commitments = commitments_to_witnesses(g_commitments); - auto stdlib_v_evaluations = elements_to_witness(v_evaluations); - auto stdlib_w_evaluations = elements_to_witness(w_evaluations); + std::generate_n(std::back_inserter(u_challenge_in_circuit), CONST_PROOF_SIZE_LOG_N, [&] { + // We still need to do the same + Fr zero = Fr(0); + zero.convert_constant_to_fixed_witness(&builder); + if (u_iter < u_challenge.end()) { + return Fr::from_witness(&builder, *u_iter++); + } + return zero; + }); - std::vector u_challenge_in_circuit = elements_to_witness(u_challenge); + auto opening_claim = ShpleminiVerifier::compute_batch_opening_claim(Fr::from_witness(&builder, N), + RefVector(stdlib_f_commitments), + RefVector(stdlib_g_commitments), + RefVector(stdlib_v_evaluations), + RefVector(stdlib_w_evaluations), + u_challenge_in_circuit, + Commitment::one(&builder), + stdlib_verifier_transcript); + auto pairing_points = KZG::reduce_verify_batch_opening_claim(opening_claim, stdlib_verifier_transcript); + EXPECT_TRUE(CircuitChecker::check(builder)); - [[maybe_unused]] auto opening_claim = - ShpleminiVerifier::compute_batch_opening_claim(Fr::from_witness(&builder, N), - RefVector(stdlib_f_commitments), - RefVector(stdlib_g_commitments), - RefVector(stdlib_v_evaluations), - RefVector(stdlib_w_evaluations), - u_challenge_in_circuit, - Commitment::one(&builder), - stdlib_verifier_transcript); + auto vk = std::make_shared>(); + EXPECT_EQ(vk->pairing_check(pairing_points[0].get_value(), pairing_points[1].get_value()), true); + + // Return finalised number of gates; + return builder.num_gates; + }; - EXPECT_TRUE(CircuitChecker::check(builder)); + size_t num_gates_6 = run_shplemini(6); + size_t num_gates_13 = run_shplemini(13); + EXPECT_EQ(num_gates_6, num_gates_13); } diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index fccab56b551c..ef46da4014c6 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -737,6 +737,7 @@ template class SumcheckVerifier { if constexpr (IsRecursiveFlavor) { typename Flavor::CircuitBuilder* builder = round_challenge.get_context(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure! stdlib::bool_t dummy_round = stdlib::witness_t(builder, round_idx >= multivariate_d); bool checked = round.check_sum(round_univariate, dummy_round); // Only utilize the checked value if this is not a constant proof size padding round