diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp index 129e5265480d..53d1ed7c172e 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp @@ -593,7 +593,6 @@ template class IPA { static OpeningClaim reduce_batch_opening_claim( const BatchOpeningClaim& batch_opening_claim) { - using Utils = CommitmentSchemesUtils; // Extract batch_mul arguments from the accumulator const auto& commitments = batch_opening_claim.commitments; const auto& scalars = batch_opening_claim.scalars; @@ -604,7 +603,7 @@ template class IPA { shplonk_output_commitment = GroupElement::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); } else { - shplonk_output_commitment = Utils::batch_mul_native(commitments, scalars); + shplonk_output_commitment = batch_mul_native(commitments, scalars); } // Output an opening claim to be verified by the IPA opening protocol return { { shplonk_eval_challenge, Fr(0) }, shplonk_output_commitment }; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp index 0fab4113fab5..955a9da9fe1f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp @@ -108,7 +108,6 @@ template class KZG { static VerifierAccumulator reduce_verify_batch_opening_claim(BatchOpeningClaim batch_opening_claim, const std::shared_ptr& transcript) { - using Utils = CommitmentSchemesUtils; auto quotient_commitment = transcript->template receive_from_prover("KZG:W"); // The pairing check can be expressed as @@ -125,7 +124,7 @@ template class KZG { /*max_num_bits=*/0, /*with_edgecases=*/true); } else { - P_0 = Utils::batch_mul_native(batch_opening_claim.commitments, batch_opening_claim.scalars); + P_0 = batch_mul_native(batch_opening_claim.commitments, batch_opening_claim.scalars); } auto P_1 = -quotient_commitment; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.hpp index 53893f7b0cb7..5ca984a148fb 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.hpp @@ -3,7 +3,6 @@ #include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/commitment_schemes/gemini/gemini.hpp" #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" -#include "barretenberg/commitment_schemes/utils/batch_mul_native.hpp" #include "barretenberg/commitment_schemes/verification_key.hpp" #include "barretenberg/transcript/transcript.hpp" diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.test.cpp index 45292861fae7..5fdade707b19 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.test.cpp @@ -33,7 +33,6 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) using GroupElement = typename TypeParam::Element; using Commitment = typename TypeParam::AffineElement; using Polynomial = typename bb::Polynomial; - using Utils = CommitmentSchemesUtils; const size_t n = 16; const size_t log_n = 4; @@ -111,7 +110,7 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) verifier_batched_evaluation); // Final pairing check - GroupElement shplemini_result = Utils::batch_mul_native(commitments, scalars); + GroupElement shplemini_result = batch_mul_native(commitments, scalars); EXPECT_EQ(commitments.size(), unshifted_commitments.size() + shifted_commitments.size()); EXPECT_EQ(batched_evaluation, verifier_batched_evaluation); @@ -127,7 +126,6 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) using GroupElement = typename TypeParam::Element; using Commitment = typename TypeParam::AffineElement; using Polynomial = typename bb::Polynomial; - using Utils = CommitmentSchemesUtils; const size_t n = 16; const size_t log_n = 4; @@ -221,7 +219,7 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) EXPECT_EQ(commitments.size(), prover_commitments.size()); // Compute the group element using the output of Shplemini method - GroupElement shplemini_result = Utils::batch_mul_native(commitments, scalars); + GroupElement shplemini_result = batch_mul_native(commitments, scalars); EXPECT_EQ(shplemini_result, expected_result); } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/batch_mul_native.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/batch_mul_native.hpp index 59970ea6d0b6..507e2a6d2ba8 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/batch_mul_native.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/batch_mul_native.hpp @@ -4,40 +4,48 @@ #include namespace bb { -template class CommitmentSchemesUtils { +/** + * @brief Utility for native batch multiplication of group elements + * @note This is used only for native verification and is not optimized for efficiency + */ +template +static Commitment batch_mul_native(const std::vector& _points, const std::vector& _scalars) +{ + std::vector points; + std::vector scalars; + for (size_t i = 0; i < _points.size(); ++i) { + const auto& point = _points[i]; + const auto& scalar = _scalars[i]; - public: - using Commitment = typename Curve::AffineElement; - using FF = typename Curve::ScalarField; - - /** - * @brief Utility for native batch multiplication of group elements - * @note This is used only for native verification and is not optimized for efficiency - */ - static Commitment batch_mul_native(const std::vector& _points, const std::vector& _scalars) - { - std::vector points; - std::vector scalars; - for (size_t i = 0; i < _points.size(); ++i) { - const auto& point = _points[i]; - const auto& scalar = _scalars[i]; - - // TODO: Special handling of point at infinity here due to incorrect serialization. - if (!scalar.is_zero() && !point.is_point_at_infinity() && !point.y.is_zero()) { - points.emplace_back(point); - scalars.emplace_back(scalar); - } + // TODO: Special handling of point at infinity here due to incorrect serialization. + if (!scalar.is_zero() && !point.is_point_at_infinity() && !point.y.is_zero()) { + points.emplace_back(point); + scalars.emplace_back(scalar); } + } - if (points.empty()) { - return Commitment::infinity(); - } + if (points.empty()) { + return Commitment::infinity(); + } - auto result = points[0] * scalars[0]; - for (size_t idx = 1; idx < scalars.size(); ++idx) { - result = result + points[idx] * scalars[idx]; - } - return result; + auto result = points[0] * scalars[0]; + for (size_t idx = 1; idx < scalars.size(); ++idx) { + result = result + points[idx] * scalars[idx]; + } + return result; +} + +/** + * @brief Utility for native batch multiplication of group elements + * @note This is used only for native verification and is not optimized for efficiency + */ +template static FF linear_combination(const std::vector& as, const std::vector& bs) +{ + FF result = as[0] * bs[0]; + for (size_t idx = 1; idx < as.size(); ++idx) { + result += as[idx] * bs[idx]; } -}; -} // namespace bb \ No newline at end of file + return result; +} + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp index 659fa2be2712..e1ee3b92fcdf 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp @@ -469,7 +469,6 @@ template class ZeroMorphProver_ { template class ZeroMorphVerifier_ { using FF = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; - using Utils = CommitmentSchemesUtils; public: /** @@ -549,7 +548,7 @@ template class ZeroMorphVerifier_ { return Commitment::batch_mul(commitments, scalars); } } else { - return Utils::batch_mul_native(commitments, scalars); + return batch_mul_native(commitments, scalars); } } @@ -705,7 +704,7 @@ template class ZeroMorphVerifier_ { return Commitment::batch_mul(commitments, scalars); } } else { - return Utils::batch_mul_native(commitments, scalars); + return batch_mul_native(commitments, scalars); } } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp index 37365af01566..b4276d58b7b9 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp @@ -125,11 +125,9 @@ FoldingResult ProtogalaxyProver_template get_challenge("combiner_quotient_challenge"); FoldingResult result{ .accumulator = keys[0], .proof = std::move(transcript->proof_data) }; - - // TODO(https://github.com/AztecProtocol/barretenberg/issues/881): bad pattern result.accumulator->is_accumulator = true; - // Compute the next target sum + // Compute the next target sum (for its own use; verifier must compute its own values) auto [vanishing_polynomial_at_challenge, lagranges] = Fun::compute_vanishing_polynomial_and_lagranges(combiner_challenge); result.accumulator->target_sum = perturbator_evaluation * lagranges[0] + diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index 868ba89c9c25..91e9b3bc9f54 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -1,4 +1,5 @@ #include "protogalaxy_verifier.hpp" +#include "barretenberg/commitment_schemes/utils/batch_mul_native.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_delta.hpp" #include "barretenberg/protogalaxy/prover_verifier_shared.hpp" #include "barretenberg/ultra_honk/oink_verifier.hpp" @@ -35,18 +36,51 @@ void ProtogalaxyVerifier_::run_oink_verifier_on_each_in } } +template +std::tuple> compute_vanishing_polynomial_and_lagrange_evaluations(const FF& combiner_challenge) +{ + static_assert(NUM < 5); + static constexpr FF inverse_two = FF(2).invert(); + + std::vector lagranges(NUM); + FF vanishing_polynomial_at_challenge; + if constexpr (NUM == 2) { + vanishing_polynomial_at_challenge = combiner_challenge * (combiner_challenge - FF(1)); + lagranges = { FF(1) - combiner_challenge, combiner_challenge }; + } else if constexpr (NUM == 3) { + vanishing_polynomial_at_challenge = + combiner_challenge * (combiner_challenge - FF(1)) * (combiner_challenge - FF(2)); + lagranges = { (FF(1) - combiner_challenge) * (FF(2) - combiner_challenge) * inverse_two, + combiner_challenge * (FF(2) - combiner_challenge), + combiner_challenge * (combiner_challenge - FF(1)) * inverse_two }; + } else if constexpr (NUM == 4) { + static constexpr FF inverse_six = FF(6).invert(); + vanishing_polynomial_at_challenge = combiner_challenge * (combiner_challenge - FF(1)) * + (combiner_challenge - FF(2)) * (combiner_challenge - FF(3)); + lagranges = { (FF(1) - combiner_challenge) * (FF(2) - combiner_challenge) * (FF(3) - combiner_challenge) * + inverse_six, + combiner_challenge * (FF(2) - combiner_challenge) * (FF(3) - combiner_challenge) * inverse_two, + combiner_challenge * (combiner_challenge - FF(1)) * (FF(3) - combiner_challenge) * inverse_two, + combiner_challenge * (combiner_challenge - FF(1)) * (combiner_challenge - FF(2)) * inverse_six }; + } + return std::make_tuple(vanishing_polynomial_at_challenge, lagranges); +} + template std::shared_ptr ProtogalaxyVerifier_< DeciderVerificationKeys>::verify_folding_proof(const std::vector& proof) { + static constexpr size_t BATCHED_EXTENDED_LENGTH = DeciderVerificationKeys::BATCHED_EXTENDED_LENGTH; + static constexpr size_t NUM_KEYS = DeciderVerificationKeys::NUM; + + const std::shared_ptr& accumulator = keys_to_fold[0]; + const size_t log_circuit_size = static_cast(accumulator->verification_key->log_circuit_size); + run_oink_verifier_on_each_incomplete_key(proof); + // Perturbator round const FF delta = transcript->template get_challenge("delta"); - const std::shared_ptr& accumulator = keys_to_fold[0]; // WORKTODO: move - - const size_t log_circuit_size = static_cast(accumulator->verification_key->log_circuit_size); const std::vector deltas = compute_round_challenge_pows(log_circuit_size, delta); - std::vector perturbator_coeffs(log_circuit_size + 1, 0); if (accumulator->is_accumulator) { for (size_t idx = 1; idx <= log_circuit_size; idx++) { @@ -54,104 +88,54 @@ std::shared_ptr ProtogalaxyVerifier transcript->template receive_from_prover("perturbator_" + std::to_string(idx)); } } + const FF perturbator_challenge = transcript->template get_challenge("perturbator_challenge"); + // Combiner quotient round perturbator_coeffs[0] = accumulator->target_sum; const Polynomial perturbator(perturbator_coeffs); - const FF perturbator_challenge = transcript->template get_challenge("perturbator_challenge"); const FF perturbator_evaluation = perturbator.evaluate(perturbator_challenge); - // The degree of K(X) is dk - k - 1 = k(d - 1) - 1. Hence we need k(d - 1) evaluations to represent it. - std::array - combiner_quotient_evals; - for (size_t idx = 0; idx < DeciderVerificationKeys::BATCHED_EXTENDED_LENGTH - DeciderVerificationKeys::NUM; idx++) { - combiner_quotient_evals[idx] = transcript->template receive_from_prover( - "combiner_quotient_" + std::to_string(idx + DeciderVerificationKeys::NUM)); + std::array + combiner_quotient_evals; // The degree of the combiner quotient (K in the paper) is dk - k - 1 = k(d - 1) - 1. + // Hence we need k(d - 1) evaluations to represent it. + for (size_t idx = DeciderVerificationKeys::NUM; auto& val : combiner_quotient_evals) { + val = transcript->template receive_from_prover("combiner_quotient_" + std::to_string(idx++)); } - const Univariate - combiner_quotient(combiner_quotient_evals); + + // Folding const FF combiner_challenge = transcript->template get_challenge("combiner_quotient_challenge"); + const Univariate combiner_quotient(combiner_quotient_evals); const FF combiner_quotient_evaluation = combiner_quotient.evaluate(combiner_challenge); - constexpr FF inverse_two = FF(2).invert(); - FF vanishing_polynomial_at_challenge; - std::array lagranges; - if constexpr (DeciderVerificationKeys::NUM == 2) { - vanishing_polynomial_at_challenge = combiner_challenge * (combiner_challenge - FF(1)); - lagranges = { FF(1) - combiner_challenge, combiner_challenge }; - } else if constexpr (DeciderVerificationKeys::NUM == 3) { - vanishing_polynomial_at_challenge = - combiner_challenge * (combiner_challenge - FF(1)) * (combiner_challenge - FF(2)); - lagranges = { (FF(1) - combiner_challenge) * (FF(2) - combiner_challenge) * inverse_two, - combiner_challenge * (FF(2) - combiner_challenge), - combiner_challenge * (combiner_challenge - FF(1)) * inverse_two }; - } else if constexpr (DeciderVerificationKeys::NUM == 4) { - constexpr FF inverse_six = FF(6).invert(); - vanishing_polynomial_at_challenge = combiner_challenge * (combiner_challenge - FF(1)) * - (combiner_challenge - FF(2)) * (combiner_challenge - FF(3)); - lagranges = { (FF(1) - combiner_challenge) * (FF(2) - combiner_challenge) * (FF(3) - combiner_challenge) * - inverse_six, - combiner_challenge * (FF(2) - combiner_challenge) * (FF(3) - combiner_challenge) * inverse_two, - combiner_challenge * (combiner_challenge - FF(1)) * (FF(3) - combiner_challenge) * inverse_two, - combiner_challenge * (combiner_challenge - FF(1)) * (combiner_challenge - FF(2)) * inverse_six }; - } - static_assert(DeciderVerificationKeys::NUM < 5); - - // TODO(https://github.com/AztecProtocol/barretenberg/issues/881): bad pattern auto next_accumulator = std::make_shared(); next_accumulator->verification_key = std::make_shared(*accumulator->verification_key); next_accumulator->is_accumulator = true; - size_t commitment_idx = 0; - for (auto& expected_vk : next_accumulator->verification_key->get_all()) { - size_t vk_idx = 0; - expected_vk = Commitment::infinity(); - for (auto& key : keys_to_fold) { - expected_vk = expected_vk + key->verification_key->get_all()[commitment_idx] * lagranges[vk_idx]; - vk_idx++; - } - commitment_idx++; - } - // Compute next folding parameters + const auto [vanishing_polynomial_at_challenge, lagranges] = + compute_vanishing_polynomial_and_lagrange_evaluations(combiner_challenge); next_accumulator->target_sum = perturbator_evaluation * lagranges[0] + vanishing_polynomial_at_challenge * combiner_quotient_evaluation; - next_accumulator->gate_challenges = + next_accumulator->gate_challenges = // note: known already in previous round update_gate_challenges(perturbator_challenge, accumulator->gate_challenges, deltas); - // Compute ϕ - auto& acc_witness_commitments = next_accumulator->witness_commitments; - commitment_idx = 0; - for (auto& comm : acc_witness_commitments.get_all()) { - comm = Commitment::infinity(); - size_t vk_idx = 0; - for (auto& key : keys_to_fold) { - comm = comm + key->witness_commitments.get_all()[commitment_idx] * lagranges[vk_idx]; - vk_idx++; - } - commitment_idx++; + // // Fold the commitments + for (auto [combination, to_combine] : + zip_view(next_accumulator->verification_key->get_all(), keys_to_fold.get_precomputed_commitments())) { + combination = batch_mul_native(to_combine, lagranges); + } + for (auto [combination, to_combine] : + zip_view(next_accumulator->witness_commitments.get_all(), keys_to_fold.get_witness_commitments())) { + combination = batch_mul_native(to_combine, lagranges); } - size_t alpha_idx = 0; - for (auto& alpha : next_accumulator->alphas) { - alpha = FF(0); - size_t vk_idx = 0; - for (auto& key : keys_to_fold) { - alpha += key->alphas[alpha_idx] * lagranges[vk_idx]; - vk_idx++; - } - alpha_idx++; + // Fold the relation parameters + for (auto [combination, to_combine] : zip_view(next_accumulator->alphas, keys_to_fold.get_alphas())) { + combination = linear_combination(to_combine, lagranges); } - auto& expected_parameters = next_accumulator->relation_parameters; - for (size_t vk_idx = 0; vk_idx < DeciderVerificationKeys::NUM; vk_idx++) { - auto& key = keys_to_fold[vk_idx]; - expected_parameters.eta += key->relation_parameters.eta * lagranges[vk_idx]; - expected_parameters.eta_two += key->relation_parameters.eta_two * lagranges[vk_idx]; - expected_parameters.eta_three += key->relation_parameters.eta_three * lagranges[vk_idx]; - expected_parameters.beta += key->relation_parameters.beta * lagranges[vk_idx]; - expected_parameters.gamma += key->relation_parameters.gamma * lagranges[vk_idx]; - expected_parameters.public_input_delta += key->relation_parameters.public_input_delta * lagranges[vk_idx]; - expected_parameters.lookup_grand_product_delta += - key->relation_parameters.lookup_grand_product_delta * lagranges[vk_idx]; + for (auto [combination, to_combine] : + zip_view(next_accumulator->relation_parameters.get_to_fold(), keys_to_fold.get_relation_parameters())) { + combination = linear_combination(to_combine, lagranges); } return next_accumulator; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp index cb5012bbaec2..44cb1400580d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp @@ -14,6 +14,8 @@ #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" +auto& engine = bb::numeric::get_debug_randomness(); + namespace bb::stdlib::recursion::honk { template class ProtogalaxyRecursiveTests : public testing::Test { public: @@ -72,11 +74,11 @@ template class ProtogalaxyRecursiveTests : public tes // Create 2^log_n many add gates based on input log num gates const size_t num_gates = 1 << log_num_gates; for (size_t i = 0; i < num_gates; ++i) { - fr a = fr::random_element(); + fr a = fr::random_element(&engine); uint32_t a_idx = builder.add_variable(a); - fr b = fr::random_element(); - fr c = fr::random_element(); + fr b = fr::random_element(&engine); + fr c = fr::random_element(&engine); fr d = a + b + c; uint32_t b_idx = builder.add_variable(b); uint32_t c_idx = builder.add_variable(c); @@ -86,9 +88,9 @@ template class ProtogalaxyRecursiveTests : public tes } // Define some additional non-trivial but arbitrary circuit logic - fr_ct a(public_witness_ct(&builder, fr::random_element())); - fr_ct b(public_witness_ct(&builder, fr::random_element())); - fr_ct c(public_witness_ct(&builder, fr::random_element())); + fr_ct a(public_witness_ct(&builder, fr::random_element(&engine))); + fr_ct b(public_witness_ct(&builder, fr::random_element(&engine))); + fr_ct c(public_witness_ct(&builder, fr::random_element(&engine))); for (size_t i = 0; i < 32; ++i) { a = (a * b) + b + a; @@ -98,7 +100,7 @@ template class ProtogalaxyRecursiveTests : public tes byte_array_ct to_hash(&builder, "nonsense test data"); blake3s(to_hash); - fr bigfield_data = fr::random_element(); + fr bigfield_data = fr::random_element(&engine); fr bigfield_data_a{ bigfield_data.data[0], bigfield_data.data[1], 0, 0 }; fr bigfield_data_b{ bigfield_data.data[2], bigfield_data.data[3], 0, 0 }; @@ -158,12 +160,12 @@ template class ProtogalaxyRecursiveTests : public tes std::vector coeffs; std::vector coeffs_ct; for (size_t idx = 0; idx < 8; idx++) { - auto el = fr::random_element(); + auto el = fr::random_element(&engine); coeffs.emplace_back(el); coeffs_ct.emplace_back(fr_ct(&builder, el)); } Polynomial poly(coeffs); - fr point = fr::random_element(); + fr point = fr::random_element(&engine); fr_ct point_ct(fr_ct(&builder, point)); auto res1 = poly.evaluate(point); @@ -333,7 +335,7 @@ template class ProtogalaxyRecursiveTests : public tes auto [prover_accumulator, verifier_accumulator] = fold_and_verify_native(); // Tamper with the accumulator by changing the target sum - verifier_accumulator->target_sum = FF::random_element(); + verifier_accumulator->target_sum = FF::random_element(&engine); // Create a decider proof for accumulator obtained through folding InnerDeciderProver decider_prover(prover_accumulator); @@ -361,7 +363,7 @@ template class ProtogalaxyRecursiveTests : public tes auto verification_key = std::make_shared(prover_inst->proving_key); auto verifier_inst = std::make_shared(verification_key); - prover_accumulator->proving_key.polynomials.w_l.at(1) = FF::random_element(); + prover_accumulator->proving_key.polynomials.w_l.at(1) = FF::random_element(&engine); // Generate a folding proof with the incorrect polynomials which would result in the prover having the wrong // target sum diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_keys.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_keys.hpp index 882950d95db7..e6ef907c6224 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_keys.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_keys.hpp @@ -43,9 +43,9 @@ template struct DeciderProvingKeys_ { * PK 0 PK 1 PK 2 PK 3 * q_c q_l q_r ... q_c q_l q_r ... q_c q_l q_r ... q_c q_l q_r ... * * * * * * * * * - * * * * * * * * * * a_1 a_2 a_3 ... b_1 b_2 b_3 ... c_1 c_2 c_3 ... d_1 d_2 d_3 ... * * * * * * * * * + * ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ * * and the function returns the univariates [{a_1, b_1, c_1, d_1}, {a_2, b_2, c_2, d_2}, ...] * @@ -86,6 +86,8 @@ template struct DeciderProvingKeys_ { template struct DeciderVerificationKeys_ { static_assert(NUM_ > 1, "Must have at least two decider verification keys."); using Flavor = Flavor_; + using FF = typename Flavor_::FF; + using Commitment = typename Flavor_::Commitment; using VerificationKey = typename Flavor::VerificationKey; using DeciderVK = DeciderVerificationKey_; using ArrayType = std::array, NUM_>; @@ -97,8 +99,8 @@ template struct DeciderVerificationKeys_ { std::shared_ptr const& operator[](size_t idx) const { return _data[idx]; } typename ArrayType::iterator begin() { return _data.begin(); }; typename ArrayType::iterator end() { return _data.end(); }; - DeciderVerificationKeys_() = default; + DeciderVerificationKeys_() = default; DeciderVerificationKeys_(const std::vector>& data) { ASSERT(data.size() == NUM); @@ -106,5 +108,81 @@ template struct DeciderVerificationKeys_ { _data[idx] = std::move(data[idx]); } }; + + /** + * @brief Get the precomputed commitments grouped by commitment index + * @example If the commitments are grouped as in + * VK 0 VK 1 VK 2 VK 3 + * q_c_0 q_c_1 q_c_2 q_c_3 + * q_l_0 q_l_1 q_l_2 q_l_3 + * ⋮ ⋮ ⋮ ⋮ + * + * then this function output this matrix of group elements as a vector of rows, + * i.e. it ouptuts {{q_c_0, q_c_1, q_c_2, q_c_3}, {q_l_0, q_l_1, q_l_2, q_l_3},...}. + * The "commitment index" is the index of the row. + */ + std::vector> get_precomputed_commitments() const + { + const size_t num_commitments_to_fold = _data[0]->verification_key->get_all().size(); + std::vector> result(num_commitments_to_fold, std::vector(NUM)); + for (size_t idx = 0; auto& commitment_at_idx : result) { + for (auto [elt, key] : zip_view(commitment_at_idx, _data)) { + elt = key->verification_key->get_all()[idx]; + } + idx++; + } + return result; + } + + /** + * @brief Get the witness commitments grouped by commitment index + * @details See get_precomputed_commitments; this is essentially the same. + */ + std::vector> get_witness_commitments() const + { + const size_t num_commitments_to_fold = _data[0]->witness_commitments.get_all().size(); + std::vector> result(num_commitments_to_fold, std::vector(NUM)); + for (size_t idx = 0; auto& commitment_at_idx : result) { + for (auto [elt, key] : zip_view(commitment_at_idx, _data)) { + elt = key->witness_commitments.get_all()[idx]; + } + idx++; + } + return result; + } + + /** + * @brief Get the alphas grouped by commitment index + * @details See get_precomputed_commitments; this is essentially the same. + */ + std::vector> get_alphas() const + { + const size_t num_alphas_to_fold = _data[0]->alphas.size(); + std::vector> result(num_alphas_to_fold, std::vector(NUM)); + for (size_t idx = 0; auto& alpha_at_idx : result) { + for (auto [elt, key] : zip_view(alpha_at_idx, _data)) { + elt = key->alphas[idx]; + } + idx++; + } + return result; + } + + /** + * @brief Get the relation parameters grouped by commitment index + * @details See get_precomputed_commitments; this is essentially the same. + */ + std::vector> get_relation_parameters() const + { + const size_t num_params_to_fold = _data[0]->relation_parameters.get_to_fold().size(); + std::vector> result(num_params_to_fold, std::vector(NUM)); + for (size_t idx = 0; auto& params_at_idx : result) { + for (auto [elt, key] : zip_view(params_at_idx, _data)) { + elt = key->relation_parameters.get_to_fold()[idx]; + } + idx++; + } + return result; + } }; } // namespace bb