From 5c34ef3d466180dad8b5ba8c6f60e8086ebf25bf Mon Sep 17 00:00:00 2001 From: maramihali Date: Wed, 2 Oct 2024 18:17:01 +0000 Subject: [PATCH 01/13] translator flavor tiny cleanup --- .../honk/proof_system/permutation_library.hpp | 6 +- .../translator_recursive_verifier.cpp | 4 +- .../relation_correctness.test.cpp | 7 +- .../translator_vm/translator_flavor.hpp | 255 +++++------------- .../translator_vm/translator_prover.cpp | 6 +- .../translator_vm/translator_verifier.cpp | 4 +- .../ultra_honk/decider_proving_key.hpp | 2 +- 7 files changed, 83 insertions(+), 201 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp index 01693c4766a..023d1e81b3f 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp @@ -26,10 +26,10 @@ namespace bb { template void compute_concatenated_polynomials(typename Flavor::ProverPolynomials& polynomials) { // Concatenation groups are vectors of polynomials that are concatenated together - auto concatenation_groups = polynomials.get_concatenation_groups(); + auto concatenation_groups = polynomials.get_groups_to_be_concatenated(); // Resulting concatenated polynomials - auto targets = polynomials.get_concatenated_constraints(); + auto targets = polynomials.get_concatenated(); // Targets have to be full-sized polynomials. We can compute the mini circuit size from them by dividing by // concatenation index @@ -116,7 +116,7 @@ void compute_translator_range_constraint_ordered_polynomials(typename Flavor::Pr std::vector extra_denominator_uint(full_circuit_size); // Get information which polynomials need to be concatenated - auto concatenation_groups = polynomials.get_concatenation_groups(); + auto concatenation_groups = polynomials.get_groups_to_be_concatenated(); // A function that transfers elements from each of the polynomials in the chosen concatenation group in the uint // ordered polynomials diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index 234122e1ec3..9604db9eb92 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -125,8 +125,8 @@ std::array TranslatorRecursiveVerifier_; auto& engine = numeric::get_debug_randomness(); const size_t mini_circuit_size = 2048; @@ -56,7 +57,9 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) params.gamma = gamma; // Create storage for polynomials - ProverPolynomials prover_polynomials; + auto proving_key = std::make_shared(); + + ProverPolynomials& prover_polynomials = proving_key->polynomials; // ensure we can shift these for (Polynomial& prover_poly : prover_polynomials.get_to_be_shifted()) { prover_poly = Polynomial::shiftable(full_circuit_size); @@ -147,7 +150,7 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) compute_translator_range_constraint_ordered_polynomials(prover_polynomials, mini_circuit_size); // Compute the fixed numerator (part of verification key) - prover_polynomials.compute_extra_range_constraint_numerator(); + proving_key->compute_extra_range_constraint_numerator(); // Compute concatenated polynomials (4 polynomials produced from other constraint polynomials by concatenation) compute_concatenated_polynomials(prover_polynomials); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index 205d0dd9853..7d06b956169 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -128,65 +128,6 @@ class TranslatorFlavor { lagrange_even_in_minicircuit, // column 4 lagrange_second, // column 5 lagrange_second_to_last_in_minicircuit); // column 6 - auto get_selectors() { return RefArray{}; }; - auto get_sigma_polynomials() { return RefArray{}; }; - auto get_id_polynomials() { return RefArray{}; }; - - inline void compute_lagrange_polynomials(const CircuitBuilder& builder) - { - const size_t mini_circuit_dyadic_size = compute_mini_circuit_dyadic_size(builder); - - for (size_t i = 1; i < mini_circuit_dyadic_size - 1; i += 2) { - this->lagrange_odd_in_minicircuit.at(i) = 1; - this->lagrange_even_in_minicircuit.at(i + 1) = 1; - } - this->lagrange_second.at(1) = 1; - this->lagrange_second_to_last_in_minicircuit.at(mini_circuit_dyadic_size - 2) = 1; - } - - /** - * @brief Compute the extra numerator for Goblin range constraint argument - * - * @details Goblin proves that several polynomials contain only values in a certain range through 2 relations: - * 1) A grand product which ignores positions of elements (TranslatorPermutationRelation) - * 2) A relation enforcing a certain ordering on the elements of the given polynomial - * (TranslatorDeltaRangeConstraintRelation) - * - * We take the values from 4 polynomials, and spread them into 5 polynomials + add all the steps from MAX_VALUE - * to 0. We order these polynomials and use them in the denominator of the grand product, at the same time - * checking that they go from MAX_VALUE to 0. To counteract the added steps we also generate an extra range - * constraint numerator, which contains 5 MAX_VALUE, 5 (MAX_VALUE-STEP),... values - * - */ - inline void compute_extra_range_constraint_numerator() - { - auto& extra_range_constraint_numerator = this->ordered_extra_range_constraints_numerator; - - static constexpr uint32_t MAX_VALUE = (1 << MICRO_LIMB_BITS) - 1; - - // Calculate how many elements there are in the sequence MAX_VALUE, MAX_VALUE - 3,...,0 - size_t sorted_elements_count = (MAX_VALUE / SORT_STEP) + 1 + (MAX_VALUE % SORT_STEP == 0 ? 0 : 1); - - // Check that we can fit every element in the polynomial - ASSERT((NUM_CONCATENATED_WIRES + 1) * sorted_elements_count < extra_range_constraint_numerator.size()); - - std::vector sorted_elements(sorted_elements_count); - - // Calculate the sequence in integers - sorted_elements[0] = MAX_VALUE; - for (size_t i = 1; i < sorted_elements_count; i++) { - sorted_elements[i] = (sorted_elements_count - 1 - i) * SORT_STEP; - } - - // TODO(#756): can be parallelized further. This will use at most 5 threads - auto fill_with_shift = [&](size_t shift) { - for (size_t i = 0; i < sorted_elements_count; i++) { - extra_range_constraint_numerator.at(shift + i * (NUM_CONCATENATED_WIRES + 1)) = sorted_elements[i]; - } - }; - // Fill polynomials with a sequence, where each element is repeated NUM_CONCATENATED_WIRES+1 times - parallel_for(NUM_CONCATENATED_WIRES + 1, fill_with_shift); - } }; template class ConcatenatedRangeConstraints { @@ -356,14 +297,6 @@ class TranslatorFlavor { DerivedWitnessEntities::get_all(), ConcatenatedRangeConstraints::get_all()); } - std::vector get_unshifted_labels() - { - return concatenate(WireNonshiftedEntities::get_labels(), - WireToBeShiftedEntities::get_labels(), - OrderedRangeConstraints::get_labels(), - DerivedWitnessEntities::get_labels(), - ConcatenatedRangeConstraints::get_labels()); - } auto get_to_be_shifted() { return concatenate(WireToBeShiftedEntities::get_all(), @@ -372,18 +305,16 @@ class TranslatorFlavor { }; /** - * @brief Get the polynomials that need to be constructed from other polynomials by concatenation + * @brief Getter for entities constructed by concatenation * - * @return auto */ - auto get_concatenated_constraints() { return ConcatenatedRangeConstraints::get_all(); } + auto get_concatenated() { return ConcatenatedRangeConstraints::get_all(); } /** * @brief Get the polynomials that are concatenated for the permutation relation * - * @return std::vector */ - std::vector> get_concatenation_groups() + std::vector> get_groups_to_be_concatenated() { return { { @@ -582,112 +513,21 @@ class TranslatorFlavor { auto get_precomputed() { return PrecomputedEntities::get_all(); }; /** - * @brief Get the polynomials that are concatenated for the permutation relation + * @brief Get the polynomials concatenated for the permutation relation * - * @return std::vector + * @details Each group is concatenated into a single polynomial */ - std::vector> get_concatenation_groups() + std::vector> get_groups_to_be_concatenated() { - return { - { - this->p_x_low_limbs_range_constraint_0, - this->p_x_low_limbs_range_constraint_1, - this->p_x_low_limbs_range_constraint_2, - this->p_x_low_limbs_range_constraint_3, - this->p_x_low_limbs_range_constraint_4, - this->p_x_low_limbs_range_constraint_tail, - this->p_x_high_limbs_range_constraint_0, - this->p_x_high_limbs_range_constraint_1, - this->p_x_high_limbs_range_constraint_2, - this->p_x_high_limbs_range_constraint_3, - this->p_x_high_limbs_range_constraint_4, - this->p_x_high_limbs_range_constraint_tail, - this->p_y_low_limbs_range_constraint_0, - this->p_y_low_limbs_range_constraint_1, - this->p_y_low_limbs_range_constraint_2, - this->p_y_low_limbs_range_constraint_3, - }, - { - this->p_y_low_limbs_range_constraint_4, - this->p_y_low_limbs_range_constraint_tail, - this->p_y_high_limbs_range_constraint_0, - this->p_y_high_limbs_range_constraint_1, - this->p_y_high_limbs_range_constraint_2, - this->p_y_high_limbs_range_constraint_3, - this->p_y_high_limbs_range_constraint_4, - this->p_y_high_limbs_range_constraint_tail, - this->z_low_limbs_range_constraint_0, - this->z_low_limbs_range_constraint_1, - this->z_low_limbs_range_constraint_2, - this->z_low_limbs_range_constraint_3, - this->z_low_limbs_range_constraint_4, - this->z_low_limbs_range_constraint_tail, - this->z_high_limbs_range_constraint_0, - this->z_high_limbs_range_constraint_1, - }, - { - this->z_high_limbs_range_constraint_2, - this->z_high_limbs_range_constraint_3, - this->z_high_limbs_range_constraint_4, - this->z_high_limbs_range_constraint_tail, - this->accumulator_low_limbs_range_constraint_0, - this->accumulator_low_limbs_range_constraint_1, - this->accumulator_low_limbs_range_constraint_2, - this->accumulator_low_limbs_range_constraint_3, - this->accumulator_low_limbs_range_constraint_4, - this->accumulator_low_limbs_range_constraint_tail, - this->accumulator_high_limbs_range_constraint_0, - this->accumulator_high_limbs_range_constraint_1, - this->accumulator_high_limbs_range_constraint_2, - this->accumulator_high_limbs_range_constraint_3, - this->accumulator_high_limbs_range_constraint_4, - this->accumulator_high_limbs_range_constraint_tail, - }, - { - this->quotient_low_limbs_range_constraint_0, - this->quotient_low_limbs_range_constraint_1, - this->quotient_low_limbs_range_constraint_2, - this->quotient_low_limbs_range_constraint_3, - this->quotient_low_limbs_range_constraint_4, - this->quotient_low_limbs_range_constraint_tail, - this->quotient_high_limbs_range_constraint_0, - this->quotient_high_limbs_range_constraint_1, - this->quotient_high_limbs_range_constraint_2, - this->quotient_high_limbs_range_constraint_3, - this->quotient_high_limbs_range_constraint_4, - this->quotient_high_limbs_range_constraint_tail, - this->relation_wide_limbs_range_constraint_0, - this->relation_wide_limbs_range_constraint_1, - this->relation_wide_limbs_range_constraint_2, - this->relation_wide_limbs_range_constraint_3, - }, - }; + return WitnessEntities::get_groups_to_be_concatenated(); } /** * @brief Get the polynomials that need to be constructed from other polynomials by concatenation * * @return auto */ - auto get_concatenated_constraints() { return ConcatenatedRangeConstraints::get_all(); }; - /** - * @brief Get the polynomials from the grand product denominator - * - * @return auto - */ - auto get_ordered_constraints() - { - return RefArray{ this->ordered_range_constraints_0, - this->ordered_range_constraints_1, - this->ordered_range_constraints_2, - this->ordered_range_constraints_3, - this->ordered_range_constraints_4 }; - }; + auto get_concatenated() { return ConcatenatedRangeConstraints::get_all(); }; - // Gemini-specific getters. - auto get_unshifted() - { - return concatenate(PrecomputedEntities::get_all(), WitnessEntities::get_unshifted()); - } // everything but ConcatenatedRangeConstraints (used for ZeroMorph input since concatenated handled separately) // TODO(https://github.com/AztecProtocol/barretenberg/issues/810) auto get_unshifted_without_concatenated() @@ -698,29 +538,12 @@ class TranslatorFlavor { // get_to_be_shifted is inherited auto get_shifted() { return ShiftedEntities::get_all(); }; // this getter is necessary for more uniform zk verifiers - auto get_shifted_witnesses() { return ShiftedEntities::get_all(); }; + auto get_shifted_witnesses() { return get_shifted(); }; auto get_wires_and_ordered_range_constraints() { return WitnessEntities::get_wires_and_ordered_range_constraints(); }; - /** - * @brief Polynomials/commitments, that can be constructed only after the r challenge has been received from - * gemini - * - * @return auto - */ - auto get_special() { return get_concatenated_constraints(); } - - auto get_unshifted_then_shifted_then_special() - { - auto result{ this->get_unshifted() }; - auto shifted{ get_shifted() }; - auto special{ get_special() }; - result.insert(result.end(), shifted.begin(), shifted.end()); - result.insert(result.end(), special.begin(), special.end()); - return result; - } // Get witness polynomials including shifts. This getter is required by ZK-Sumcheck. auto get_all_witnesses() { @@ -854,11 +677,67 @@ class TranslatorFlavor { // Compute polynomials with odd and even indices set to 1 up to the minicircuit margin + lagrange // polynomials at second and second to last indices in the minicircuit - polynomials.compute_lagrange_polynomials(builder); + compute_lagrange_polynomials(builder); // Compute the numerator for the permutation argument with several repetitions of steps bridging 0 and // maximum range constraint compute_extra_range_constraint_numerator(); - polynomials.compute_extra_range_constraint_numerator(); + compute_extra_range_constraint_numerator(); + } + + inline void compute_lagrange_polynomials(const CircuitBuilder& builder) + { + const size_t mini_circuit_dyadic_size = compute_mini_circuit_dyadic_size(builder); + + for (size_t i = 1; i < mini_circuit_dyadic_size - 1; i += 2) { + polynomials.lagrange_odd_in_minicircuit.at(i) = 1; + polynomials.lagrange_even_in_minicircuit.at(i + 1) = 1; + } + polynomials.lagrange_second.at(1) = 1; + polynomials.lagrange_second_to_last_in_minicircuit.at(mini_circuit_dyadic_size - 2) = 1; + } + + /** + * @brief Compute the extra numerator for Goblin range constraint argument + * + * @details Goblin proves that several polynomials contain only values in a certain range through 2 relations: + * 1) A grand product which ignores positions of elements (TranslatorPermutationRelation) + * 2) A relation enforcing a certain ordering on the elements of the given polynomial + * (TranslatorDeltaRangeConstraintRelation) + * + * We take the values from 4 polynomials, and spread them into 5 polynomials + add all the steps from MAX_VALUE + * to 0. We order these polynomials and use them in the denominator of the grand product, at the same time + * checking that they go from MAX_VALUE to 0. To counteract the added steps we also generate an extra range + * constraint numerator, which contains 5 MAX_VALUE, 5 (MAX_VALUE-STEP),... values + * + */ + inline void compute_extra_range_constraint_numerator() + { + auto& extra_range_constraint_numerator = polynomials.ordered_extra_range_constraints_numerator; + + static constexpr uint32_t MAX_VALUE = (1 << MICRO_LIMB_BITS) - 1; + + // Calculate how many elements there are in the sequence MAX_VALUE, MAX_VALUE - 3,...,0 + size_t sorted_elements_count = (MAX_VALUE / SORT_STEP) + 1 + (MAX_VALUE % SORT_STEP == 0 ? 0 : 1); + + // Check that we can fit every element in the polynomial + ASSERT((NUM_CONCATENATED_WIRES + 1) * sorted_elements_count < extra_range_constraint_numerator.size()); + + std::vector sorted_elements(sorted_elements_count); + + // Calculate the sequence in integers + sorted_elements[0] = MAX_VALUE; + for (size_t i = 1; i < sorted_elements_count; i++) { + sorted_elements[i] = (sorted_elements_count - 1 - i) * SORT_STEP; + } + + // TODO(#756): can be parallelized further. This will use at most 5 threads + auto fill_with_shift = [&](size_t shift) { + for (size_t i = 0; i < sorted_elements_count; i++) { + extra_range_constraint_numerator.at(shift + i * (NUM_CONCATENATED_WIRES + 1)) = sorted_elements[i]; + } + }; + // Fill polynomials with a sequence, where each element is repeated NUM_CONCATENATED_WIRES+1 times + parallel_for(NUM_CONCATENATED_WIRES + 1, fill_with_shift); } }; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index b172d003f77..ec6f5a897c6 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -185,9 +185,9 @@ void TranslatorProver::execute_pcs_rounds() sumcheck_output.challenge, commitment_key, transcript, - key->polynomials.get_concatenated_constraints(), - sumcheck_output.claimed_evaluations.get_concatenated_constraints(), - key->polynomials.get_concatenation_groups()); + key->polynomials.get_concatenated(), + sumcheck_output.claimed_evaluations.get_concatenated(), + key->polynomials.get_groups_to_be_concatenated()); PCS::compute_opening_proof(commitment_key, prover_opening_claim, transcript); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 59429a35927..f217e62bb6e 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -121,8 +121,8 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) multivariate_challenge, Commitment::one(), transcript, - commitments.get_concatenation_groups(), - claimed_evaluations.get_concatenated_constraints()); + commitments.get_groups_to_be_concatenated(), + claimed_evaluations.get_concatenated()); auto pairing_points = PCS::reduce_verify(opening_claim, transcript); auto verified = key->pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp index 2bfd069a5a4..ed4362071d4 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp @@ -13,7 +13,7 @@ namespace bb { /** * @brief A DeciderProvingKey is normally constructed from a finalized circuit and it contains all the information - * required by an Ultra Goblin Honk prover to create a proof. A DeciderProvingKey is also the result of running the + * required by an Mega Honk prover to create a proof. A DeciderProvingKey is also the result of running the * Protogalaxy prover, in which case it becomes a relaxed counterpart with the folding parameters (target sum and gate * challenges set to non-zero values). * From d10e18195598b13809ee37ccbef121f601f7f9ce Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 3 Oct 2024 09:46:06 +0000 Subject: [PATCH 02/13] fix test crashing --- .../relation_correctness.test.cpp | 4 +- .../translator_vm/translator_flavor.hpp | 59 +++++++++++-------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp index c4b178cac46..4ae6375ba04 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -224,8 +224,8 @@ TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) prover_polynomials.ordered_range_constraints_0.coeffs().begin(), [](uint64_t in) { return FF(in); }); - // Copy the same polynomial into the 4 other ordered polynomials (they are not the same in an actual proof, but we - // only need to check the correctness of the relation and it acts independently on each polynomial) + // Copy the same polynomial into the 4 other ordered polynomials (they are not the same in an actual proof, but + // we only need to check the correctness of the relation and it acts independently on each polynomial) parallel_for(4, [&](size_t i) { std::copy(prover_polynomials.ordered_range_constraints_0.coeffs().begin(), prover_polynomials.ordered_range_constraints_0.coeffs().end(), diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index 7d06b956169..e76b0526e9d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -305,14 +305,16 @@ class TranslatorFlavor { }; /** - * @brief Getter for entities constructed by concatenation + * @brief Get the polynomials that need to be constructed from other polynomials by concatenation * + * @return auto */ auto get_concatenated() { return ConcatenatedRangeConstraints::get_all(); } /** - * @brief Get the polynomials that are concatenated for the permutation relation + * @brief Get the entities concatenated for the permutation relation * + * @return std::vector */ std::vector> get_groups_to_be_concatenated() { @@ -501,34 +503,43 @@ class TranslatorFlavor { public WitnessEntities, public ShiftedEntities { public: - // Initialize members - AllEntities() - : PrecomputedEntities{} - , WitnessEntities{} - , ShiftedEntities{} - {} - DEFINE_COMPOUND_GET_ALL(PrecomputedEntities, WitnessEntities, ShiftedEntities) auto get_precomputed() { return PrecomputedEntities::get_all(); }; /** - * @brief Get the polynomials concatenated for the permutation relation + * @brief Get entities concatenated for the permutation relation * - * @details Each group is concatenated into a single polynomial */ std::vector> get_groups_to_be_concatenated() { return WitnessEntities::get_groups_to_be_concatenated(); } /** - * @brief Get the polynomials that need to be constructed from other polynomials by concatenation + * @brief Getter for entities constructed by concatenation + */ + auto get_concatenated() { return ConcatenatedRangeConstraints::get_all(); }; + /** + * @brief Get the polynomials from the grand product denominator * * @return auto */ - auto get_concatenated() { return ConcatenatedRangeConstraints::get_all(); }; + auto get_ordered_constraints() + { + return RefArray{ this->ordered_range_constraints_0, + this->ordered_range_constraints_1, + this->ordered_range_constraints_2, + this->ordered_range_constraints_3, + this->ordered_range_constraints_4 }; + }; - // everything but ConcatenatedRangeConstraints (used for ZeroMorph input since concatenated handled separately) + // Gemini-specific getters. + auto get_unshifted() + { + return concatenate(PrecomputedEntities::get_all(), WitnessEntities::get_unshifted()); + } + // everything but ConcatenatedRangeConstraints (used for ZeroMorph input since concatenated handled + // separately) // TODO(https://github.com/AztecProtocol/barretenberg/issues/810) auto get_unshifted_without_concatenated() { @@ -538,7 +549,7 @@ class TranslatorFlavor { // get_to_be_shifted is inherited auto get_shifted() { return ShiftedEntities::get_all(); }; // this getter is necessary for more uniform zk verifiers - auto get_shifted_witnesses() { return get_shifted(); }; + auto get_shifted_witnesses() { return this->get_shifted(); }; auto get_wires_and_ordered_range_constraints() { return WitnessEntities::get_wires_and_ordered_range_constraints(); @@ -580,8 +591,8 @@ class TranslatorFlavor { // Next power of 2 const size_t mini_circuit_dyadic_size = builder.get_circuit_subgroup_size(total_num_gates); - // The actual circuit size is several times bigger than the trace in the builder, because we use concatenation - // to bring the degree of relations down, while extending the length. + // The actual circuit size is several times bigger than the trace in the builder, because we use + // concatenation to bring the degree of relations down, while extending the length. return mini_circuit_dyadic_size * CONCATENATION_GROUP_SIZE; } @@ -699,15 +710,15 @@ class TranslatorFlavor { /** * @brief Compute the extra numerator for Goblin range constraint argument * - * @details Goblin proves that several polynomials contain only values in a certain range through 2 relations: - * 1) A grand product which ignores positions of elements (TranslatorPermutationRelation) - * 2) A relation enforcing a certain ordering on the elements of the given polynomial + * @details Goblin proves that several polynomials contain only values in a certain range through 2 + * relations: 1) A grand product which ignores positions of elements (TranslatorPermutationRelation) 2) A + * relation enforcing a certain ordering on the elements of the given polynomial * (TranslatorDeltaRangeConstraintRelation) * - * We take the values from 4 polynomials, and spread them into 5 polynomials + add all the steps from MAX_VALUE - * to 0. We order these polynomials and use them in the denominator of the grand product, at the same time - * checking that they go from MAX_VALUE to 0. To counteract the added steps we also generate an extra range - * constraint numerator, which contains 5 MAX_VALUE, 5 (MAX_VALUE-STEP),... values + * We take the values from 4 polynomials, and spread them into 5 polynomials + add all the steps from + * MAX_VALUE to 0. We order these polynomials and use them in the denominator of the grand product, at the + * same time checking that they go from MAX_VALUE to 0. To counteract the added steps we also generate an + * extra range constraint numerator, which contains 5 MAX_VALUE, 5 (MAX_VALUE-STEP),... values * */ inline void compute_extra_range_constraint_numerator() From 0e0bd86eb21469439857d99fcf3552609aa06b10 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 3 Oct 2024 09:49:58 +0000 Subject: [PATCH 03/13] more cleanup --- .../src/barretenberg/translator_vm/translator_flavor.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index e76b0526e9d..a6578e68aa9 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -538,8 +538,6 @@ class TranslatorFlavor { { return concatenate(PrecomputedEntities::get_all(), WitnessEntities::get_unshifted()); } - // everything but ConcatenatedRangeConstraints (used for ZeroMorph input since concatenated handled - // separately) // TODO(https://github.com/AztecProtocol/barretenberg/issues/810) auto get_unshifted_without_concatenated() { @@ -591,8 +589,8 @@ class TranslatorFlavor { // Next power of 2 const size_t mini_circuit_dyadic_size = builder.get_circuit_subgroup_size(total_num_gates); - // The actual circuit size is several times bigger than the trace in the builder, because we use - // concatenation to bring the degree of relations down, while extending the length. + // The actual circuit size is several times bigger than the trace in the builder, because we use concatenation + // to bring the degree of relations down, while extending the length. return mini_circuit_dyadic_size * CONCATENATION_GROUP_SIZE; } From 68cd5a3bc54682be811320ffcc9461c99eaa1238 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 3 Oct 2024 16:08:12 +0000 Subject: [PATCH 04/13] start --- .../commitment_schemes/gemini/gemini.hpp | 19 ++++++--- .../commitment_schemes/gemini/gemini_impl.hpp | 41 ++++++++++++++----- .../commitment_schemes/shplonk/shplemini.hpp | 35 +++++++++++----- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index d8fa2ab6e54..c5b6010fddc 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -115,7 +115,10 @@ template class GeminiProver_ { RefSpan g_polynomials, std::span multilinear_challenge, const std::shared_ptr>& commitment_key, - const std::shared_ptr& transcript); + const std::shared_ptr& transcript, + RefSpan concatenated_polynomials = {}, + const std::vector>& groups_to_be_concatenated = {}); + }; // namespace bb template class GeminiVerifier_ { @@ -136,11 +139,15 @@ template class GeminiVerifier_ { * @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 multilinear_challenge, - std::span multilinear_evaluations, - RefSpan unshifted_commitments, - RefSpan to_be_shifted_commitments, - auto& transcript) + static std::vector> reduce_verification( + std::span multilinear_challenge, + std::span multilinear_evaluations, + RefSpan unshifted_commitments, + RefSpan to_be_shifted_commitments, + auto& transcript, + [[]] const std::vector>& concatenation_group_commitments = {}, + [[maybe_unused]] RefSpan concatenated_evaluations = {}) + { const size_t num_variables = multilinear_challenge.size(); 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 fde94fdcdb1..4872123c95a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -47,28 +47,50 @@ std::vector::Claim> GeminiProver_::prove( RefSpan g_polynomials, // to-be-shifted std::span multilinear_challenge, const std::shared_ptr>& commitment_key, - const std::shared_ptr& transcript) + const std::shared_ptr& transcript, + RefSpan concatenated_polynomials, + const std::vector>& groups_to_be_concatenated) + { size_t log_n = numeric::get_msb(static_cast(circuit_size)); size_t n = 1 << log_n; Fr rho = transcript->template get_challenge("rho"); - std::vector rhos = gemini::powers_of_rho(rho, f_polynomials.size() + g_polynomials.size()); // Compute batched polynomials Polynomial batched_unshifted(n); Polynomial batched_to_be_shifted = Polynomial::shiftable(1 << log_n); - const size_t num_unshifted = f_polynomials.size(); - const size_t num_to_be_shifted = g_polynomials.size(); - for (size_t i = 0; i < num_unshifted; i++) { - Fr rho_challenge = rhos[i]; + Fr rho_challenge{ 1 }; + for (size_t i = 0; i < f_polynomials.size(); i++) { batched_unshifted.add_scaled(f_polynomials[i], rho_challenge); + rho_challenge *= rho; } - for (size_t i = 0; i < num_to_be_shifted; i++) { - Fr rho_challenge = rhos[num_unshifted + i]; + for (size_t i = 0; i < g_polynomials.size(); i++) { batched_to_be_shifted.add_scaled(g_polynomials[i], rho_challenge); + rho_challenge *= rho; + } + + size_t num_groups = groups_to_be_concatenated.size(); + size_t num_chunks_per_group = groups_to_be_concatenated.empty() ? 0 : groups_to_be_concatenated[0].size(); + // Concatenated polynomials + Polynomial batched_concatenated(n); + + // construct concatention_groups_batched + std::vector batched_groups_to_be_concatenated; + for (size_t i = 0; i < num_chunks_per_group; ++i) { + batched_groups_to_be_concatenated.push_back(Polynomial(n)); + } + // for each group + for (size_t i = 0; i < num_groups; ++i) { + batched_concatenated.add_scaled(concatenated_polynomials[i], rho_challenge); + // for each element in a group + for (size_t j = 0; j < num_chunks_per_group; ++j) { + batched_groups_to_be_concatenated[j].add_scaled(groups_to_be_concatenated[i][j], rho_challenge); + } + rho_challenge *= rho; } + batched_unshifted += batched_concatenated; auto fold_polynomials = compute_fold_polynomials( log_n, multilinear_challenge, std::move(batched_unshifted), std::move(batched_to_be_shifted)); @@ -229,8 +251,7 @@ std::vector::Claim> GeminiProver_::compute_ // Compute first opening pair {r, A₀(r)} Fr evaluation = fold_polynomials[0].evaluate(r_challenge); - opening_claims.emplace_back( - Claim{ fold_polynomials[0], { r_challenge, fold_polynomials[0].evaluate(r_challenge) } }); + opening_claims.emplace_back(Claim{ fold_polynomials[0], { r_challenge, evaluation } }); // Compute the remaining m opening pairs {−r^{2ˡ}, Aₗ(−r^{2ˡ})}, l = 0, ..., m-1. for (size_t l = 0; l < num_variables; ++l) { evaluation = fold_polynomials[l + 1].evaluate(-r_squares[l]); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 1d5aae300ce..60b52230cc3 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -26,10 +26,18 @@ template class ShpleminiProver_ { RefSpan g_polynomials, std::span multilinear_challenge, const std::shared_ptr>& commitment_key, - const std::shared_ptr& transcript) + const std::shared_ptr& transcript, + RefSpan concatenated_polynomials = {}, + const std::vector>& groups_to_be_concatenated = {}) { - std::vector opening_claims = GeminiProver::prove( - circuit_size, f_polynomials, g_polynomials, multilinear_challenge, commitment_key, transcript); + std::vector opening_claims = GeminiProver::prove(circuit_size, + f_polynomials, + g_polynomials, + multilinear_challenge, + commitment_key, + transcript, + concatenated_polynomials, + groups_to_be_concatenated); OpeningClaim batched_claim = ShplonkProver::prove(commitment_key, opening_claims, transcript); return batched_claim; @@ -99,14 +107,18 @@ template class ShpleminiVerifier_ { public: template - static BatchOpeningClaim compute_batch_opening_claim(const Fr N, - RefSpan unshifted_commitments, - RefSpan shifted_commitments, - RefSpan unshifted_evaluations, - RefSpan shifted_evaluations, - const std::vector& multivariate_challenge, - const Commitment& g1_identity, - const std::shared_ptr& transcript) + static BatchOpeningClaim compute_batch_opening_claim( + const Fr N, + RefSpan unshifted_commitments, + RefSpan shifted_commitments, + RefSpan unshifted_evaluations, + RefSpan shifted_evaluations, + const std::vector& multivariate_challenge, + const Commitment& g1_identity, + const std::shared_ptr& transcript, + [[maybe_unused]] const std::vector>& concatenation_group_commitments = {}, + [[maybe_unused]] RefSpan concatenated_evaluations = {}) + { // Extract log_circuit_size @@ -260,6 +272,7 @@ template class ShpleminiVerifier_ { RefSpan shifted_commitments, RefSpan unshifted_evaluations, RefSpan shifted_evaluations, + RefSpan concatenated_evaluations, const Fr& multivariate_batching_challenge, const Fr& unshifted_scalar, const Fr& shifted_scalar, From 11cf6ba93a196c9c1d2e7cc078a375e9daafbd2a Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 8 Oct 2024 14:27:22 +0000 Subject: [PATCH 05/13] I have advanced, still not fully working --- .../commitment_schemes/gemini/gemini.hpp | 172 +++++++++++++----- .../commitment_schemes/gemini/gemini.test.cpp | 151 +++++++++++++-- .../commitment_schemes/gemini/gemini_impl.hpp | 24 +-- .../commitment_schemes/ipa/ipa.test.cpp | 3 +- .../commitment_schemes/kzg/kzg.test.cpp | 3 +- .../commitment_schemes/shplonk/shplemini.hpp | 7 +- 6 files changed, 275 insertions(+), 85 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index c5b6010fddc..9eca5a97cc7 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -141,34 +141,36 @@ template class GeminiVerifier_ { */ static std::vector> reduce_verification( std::span multilinear_challenge, - std::span multilinear_evaluations, + RefSpan unshifted_evaluations, + RefSpan shifted_evaluations, RefSpan unshifted_commitments, RefSpan to_be_shifted_commitments, auto& transcript, - [[]] const std::vector>& concatenation_group_commitments = {}, + [[maybe_unused]] const std::vector>& concatenation_group_commitments = {}, [[maybe_unused]] RefSpan concatenated_evaluations = {}) { const size_t num_variables = multilinear_challenge.size(); + const size_t N = 1 << num_variables; + Fr rho = transcript->template get_challenge("rho"); - std::vector rhos = gemini::powers_of_rho(rho, multilinear_evaluations.size()); GroupElement batched_commitment_unshifted = GroupElement::zero(); GroupElement batched_commitment_to_be_shifted = GroupElement::zero(); - Fr batched_evaluation = Fr::zero(); - for (size_t i = 0; i < multilinear_evaluations.size(); ++i) { - batched_evaluation += multilinear_evaluations[i] * rhos[i]; + Fr batched_evaluation = Fr(0); + Fr batching_scalar = Fr(1); + for (auto [eval, comm] : zip_view(unshifted_evaluations, unshifted_commitments)) { + batched_evaluation += eval * batching_scalar; + batched_commitment_unshifted += comm * batching_scalar; + batching_scalar *= rho; } - const size_t num_unshifted = unshifted_commitments.size(); - const size_t num_to_be_shifted = to_be_shifted_commitments.size(); - for (size_t i = 0; i < num_unshifted; i++) { - batched_commitment_unshifted += unshifted_commitments[i] * rhos[i]; - } - for (size_t i = 0; i < num_to_be_shifted; i++) { - batched_commitment_to_be_shifted += to_be_shifted_commitments[i] * rhos[num_unshifted + i]; + for (auto [eval, comm] : zip_view(shifted_evaluations, to_be_shifted_commitments)) { + batched_evaluation += eval * batching_scalar; + batched_commitment_to_be_shifted += comm * batching_scalar; + batching_scalar *= rho; } // Get polynomials Fold_i, i = 1,...,m-1 from transcript @@ -178,24 +180,94 @@ template class GeminiVerifier_ { const Fr r = transcript->template get_challenge("Gemini:r"); const std::vector r_squares = gemini::powers_of_evaluation_challenge(r, CONST_PROOF_SIZE_LOG_N); + // have to do it both with and without minus (i.e. r and -r) + + GroupElement batched_concatenated_pos = GroupElement::zero(); + GroupElement batched_concatenated_neg = GroupElement::zero(); + + Fr r_inv = r.invert(); // r⁻¹ + + ASSERT(concatenated_evaluations.size() == concatenation_group_commitments.size()); + if (!concatenation_group_commitments.empty()) { + size_t CONCATENATION_GROUP_SIZE = concatenation_group_commitments[0].size(); + size_t MINICIRCUIT_N = N / CONCATENATION_GROUP_SIZE; + std::vector r_shifts_pos; + std::vector r_shifts_neg; + auto current_r_shift_pos = r; + auto current_r_shift_neg = r_inv; + auto r_to_minicircuit_n_pos = r.pow(MINICIRCUIT_N); + auto r_to_minicircuit_n_neg = r_inv.pow(MINICIRCUIT_N); + for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { + r_shifts_pos.emplace_back(current_r_shift_pos); + r_shifts_neg.emplace_back(current_r_shift_neg); + current_r_shift_pos *= r_to_minicircuit_n_pos; + current_r_shift_neg *= r_to_minicircuit_n_neg; + } + size_t j = 0; + for (auto& concatenation_group_commitment : concatenation_group_commitments) { + for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { + batched_concatenated_pos += concatenation_group_commitment[i] * batching_scalar * r_shifts_pos[i]; + batched_concatenated_neg += concatenation_group_commitment[i] * batching_scalar * r_shifts_neg[i]; + } + batched_evaluation += concatenated_evaluations[j] * batching_scalar; + batching_scalar *= rho; + j++; + } + } + // Get evaluations a_i, i = 0,...,m-1 from transcript const std::vector evaluations = get_gemini_evaluations(num_variables, transcript); // Compute evaluation A₀(r) + // I think this stays as it is, it includes concatenated shit auto a_0_pos = compute_gemini_batched_univariate_evaluation( num_variables, batched_evaluation, multilinear_challenge, r_squares, evaluations); + // C₀ᵣ₊ = [F] + r⁻¹⋅[G] + GroupElement C0_r_pos; + + // C₀ᵣ₊ = [F] + r⁻¹⋅[G] GroupElement C0_r_pos; + // C₀ᵣ₋ = [F] - r⁻¹⋅[G] + GroupElement C0_r_neg; + + // If in a recursive setting, perform a batch mul. Otherwise, accumulate directly. + // TODO(#673): The following if-else represents the stldib/native code paths. Once the "native" verifier is + // achieved through a builder Simulator, the stdlib codepath should become the only codepath. + // if constexpr (Curve::is_stdlib_type) { + // std::vector commitments = { batched_commitment_unshifted, batched_commitment_to_be_shifted + // }; auto builder = r.get_context(); auto one = Fr(builder, 1); + // // TODO(#707): these batch muls include the use of 1 as a scalar. This is handled appropriately as a + // non-mul + // // (add-accumulate) in the goblin batch_mul but is done inefficiently as a scalar mul in the conventional + // // emulated batch mul. + // C0_r_pos = GroupElement::batch_mul(commitments, { one, r_inv }); + // C0_r_neg = GroupElement::batch_mul(commitments, { one, -r_inv }); + // } else { + C0_r_pos = batched_commitment_unshifted; + C0_r_neg = batched_commitment_unshifted; + if (!batched_commitment_to_be_shifted.is_point_at_infinity()) { + batched_commitment_to_be_shifted = batched_commitment_to_be_shifted * r_inv; + C0_r_pos += batched_commitment_to_be_shifted; + C0_r_pos += batched_concatenated_pos; + + C0_r_neg -= batched_commitment_to_be_shifted; + C0_r_neg += batched_concatenated_neg; + } + // } + + // here we use the commitments to concatenated groups, shifting by r // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] + r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] - r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] - auto [c0_r_pos, c0_r_neg] = - compute_simulated_commitments(batched_commitment_unshifted, batched_commitment_to_be_shifted, r); + // auto [c0_r_pos, c0_r_neg] = + // compute_simulated_commitments(batched_commitment_unshifted, batched_commitment_to_be_shifted, r); std::vector> fold_polynomial_opening_claims; fold_polynomial_opening_claims.reserve(num_variables + 1); + // we // ( [A₀₊], r, A₀(r) ) - fold_polynomial_opening_claims.emplace_back(OpeningClaim{ { r, a_0_pos }, c0_r_pos }); + 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 }); + 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( @@ -299,39 +371,39 @@ template class GeminiVerifier_ { * @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_commitment_unshifted, GroupElement& batched_commitment_to_be_shifted, Fr r) - { - // C₀ᵣ₊ = [F] + r⁻¹⋅[G] - GroupElement C0_r_pos; - // C₀ᵣ₋ = [F] - r⁻¹⋅[G] - GroupElement C0_r_neg; - Fr r_inv = r.invert(); // r⁻¹ - - // If in a recursive setting, perform a batch mul. Otherwise, accumulate directly. - // TODO(#673): The following if-else represents the stldib/native code paths. Once the "native" verifier is - // achieved through a builder Simulator, the stdlib codepath should become the only codepath. - if constexpr (Curve::is_stdlib_type) { - std::vector commitments = { batched_commitment_unshifted, batched_commitment_to_be_shifted }; - auto builder = r.get_context(); - auto one = Fr(builder, 1); - // TODO(#707): these batch muls include the use of 1 as a scalar. This is handled appropriately as a non-mul - // (add-accumulate) in the goblin batch_mul but is done inefficiently as a scalar mul in the conventional - // emulated batch mul. - C0_r_pos = GroupElement::batch_mul(commitments, { one, r_inv }); - C0_r_neg = GroupElement::batch_mul(commitments, { one, -r_inv }); - } else { - C0_r_pos = batched_commitment_unshifted; - C0_r_neg = batched_commitment_unshifted; - if (!batched_commitment_to_be_shifted.is_point_at_infinity()) { - batched_commitment_to_be_shifted = batched_commitment_to_be_shifted * r_inv; - C0_r_pos += batched_commitment_to_be_shifted; - C0_r_neg -= batched_commitment_to_be_shifted; - } - } - - return { C0_r_pos, C0_r_neg }; - } + // static std::pair compute_simulated_commitments( + // GroupElement& batched_commitment_unshifted, GroupElement& batched_commitment_to_be_shifted, Fr r) + // { + // // C₀ᵣ₊ = [F] + r⁻¹⋅[G] + // GroupElement C0_r_pos; + // // C₀ᵣ₋ = [F] - r⁻¹⋅[G] + // GroupElement C0_r_neg; + // Fr r_inv = r.invert(); // r⁻¹ + + // // If in a recursive setting, perform a batch mul. Otherwise, accumulate directly. + // // TODO(#673): The following if-else represents the stldib/native code paths. Once the "native" verifier is + // // achieved through a builder Simulator, the stdlib codepath should become the only codepath. + // if constexpr (Curve::is_stdlib_type) { + // std::vector commitments = { batched_commitment_unshifted, batched_commitment_to_be_shifted + // }; auto builder = r.get_context(); auto one = Fr(builder, 1); + // // TODO(#707): these batch muls include the use of 1 as a scalar. This is handled appropriately as a + // non-mul + // // (add-accumulate) in the goblin batch_mul but is done inefficiently as a scalar mul in the conventional + // // emulated batch mul. + // C0_r_pos = GroupElement::batch_mul(commitments, { one, r_inv }); + // C0_r_neg = GroupElement::batch_mul(commitments, { one, -r_inv }); + // } else { + // C0_r_pos = batched_commitment_unshifted; + // C0_r_neg = batched_commitment_unshifted; + // if (!batched_commitment_to_be_shifted.is_point_at_infinity()) { + // batched_commitment_to_be_shifted = batched_commitment_to_be_shifted * r_inv; + // C0_r_pos += batched_commitment_to_be_shifted; + // C0_r_neg -= batched_commitment_to_be_shifted; + // } + // } + + // return { C0_r_pos, C0_r_neg }; + // } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp index ebb8e2ccb2e..e02800020ea 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp @@ -13,12 +13,19 @@ template class GeminiTest : public CommitmentTest { using GroupElement = typename Curve::Element; public: - void execute_gemini_and_verify_claims(std::vector& multilinear_evaluation_point, - std::vector& multilinear_evaluations, - RefSpan> multilinear_polynomials, - RefSpan> multilinear_polynomials_to_be_shifted, - RefVector multilinear_commitments, - RefVector multilinear_commitments_to_be_shifted) + void execute_gemini_and_verify_claims( + std::vector& multilinear_evaluation_point, + RefVector multilinear_evaluations_unshifted, + RefVector multilinear_evaluations_shifted, + RefSpan> multilinear_polynomials, + RefSpan> multilinear_polynomials_to_be_shifted, + RefVector multilinear_commitments, + RefVector multilinear_commitments_to_be_shifted, + RefSpan> concatenated_polynomials = {}, + RefSpan concatenated_evaluations = {}, + const std::vector>>& groups_to_be_concatenated = {}, + const std::vector>& concatenation_group_commitments = {}) + { auto prover_transcript = NativeTranscript::prover_init_empty(); @@ -30,7 +37,9 @@ template class GeminiTest : public CommitmentTest { multilinear_polynomials_to_be_shifted, multilinear_evaluation_point, this->commitment_key, - prover_transcript); + prover_transcript, + concatenated_polynomials, + groups_to_be_concatenated); // Check that the Fold polynomials have been evaluated correctly in the prover this->verify_batch_opening_pair(prover_output); @@ -42,10 +51,13 @@ template class GeminiTest : public CommitmentTest { // - 2 partially evaluated Fold polynomial commitments [Fold_{r}^(0)] and [Fold_{-r}^(0)] // Aggregate: d+1 opening pairs and d+1 Fold poly commitments into verifier claim auto verifier_claims = GeminiVerifier::reduce_verification(multilinear_evaluation_point, - multilinear_evaluations, - RefVector(multilinear_commitments), - RefVector(multilinear_commitments_to_be_shifted), - verifier_transcript); + multilinear_evaluations_unshifted, + multilinear_evaluations_shifted, + multilinear_commitments, + multilinear_commitments_to_be_shifted, + verifier_transcript, + concatenation_group_commitments, + concatenated_evaluations); // Check equality of the opening pairs computed by prover and verifier for (auto [prover_claim, verifier_claim] : zip_view(prover_output, verifier_claims)) { @@ -72,14 +84,16 @@ TYPED_TEST(GeminiTest, Single) auto eval = poly.evaluate_mle(u); // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier - std::vector multilinear_evaluations = { eval }; + std::vector multilinear_evaluations_unshifted = { eval }; + std::vector multilinear_evaluations_shifted = {}; std::vector> multilinear_polynomials = { poly.share() }; std::vector> multilinear_polynomials_to_be_shifted = {}; std::vector multilinear_commitments = { commitment }; std::vector multilinear_commitments_to_be_shifted = {}; this->execute_gemini_and_verify_claims(u, - multilinear_evaluations, + RefVector(multilinear_evaluations_unshifted), + RefVector(multilinear_evaluations_shifted), RefVector(multilinear_polynomials), RefVector(multilinear_polynomials_to_be_shifted), RefVector(multilinear_commitments), @@ -103,14 +117,16 @@ TYPED_TEST(GeminiTest, SingleShift) auto eval_shift = poly.evaluate_mle(u, true); // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier - std::vector multilinear_evaluations = { eval_shift }; + std::vector multilinear_evaluations_unshifted = {}; + std::vector multilinear_evaluations_shifted = { eval_shift }; std::vector> multilinear_polynomials = {}; std::vector> multilinear_polynomials_to_be_shifted = { poly.share() }; std::vector multilinear_commitments = {}; std::vector multilinear_commitments_to_be_shifted = { commitment }; this->execute_gemini_and_verify_claims(u, - multilinear_evaluations, + RefVector(multilinear_evaluations_unshifted), + RefVector(multilinear_evaluations_shifted), RefVector(multilinear_polynomials), RefVector(multilinear_polynomials_to_be_shifted), RefVector(multilinear_commitments), @@ -137,14 +153,16 @@ TYPED_TEST(GeminiTest, Double) auto eval2 = poly2.evaluate_mle(u); // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier - std::vector multilinear_evaluations = { eval1, eval2 }; + std::vector multilinear_evaluations_unshifted = { eval1, eval2 }; + std::vector multilinear_evaluations_shifted = {}; std::vector> multilinear_polynomials = { poly1.share(), poly2.share() }; std::vector> multilinear_polynomials_to_be_shifted = {}; std::vector multilinear_commitments = { commitment1, commitment2 }; std::vector multilinear_commitments_to_be_shifted = {}; this->execute_gemini_and_verify_claims(u, - multilinear_evaluations, + RefVector(multilinear_evaluations_unshifted), + RefVector(multilinear_evaluations_shifted), RefVector(multilinear_polynomials), RefVector(multilinear_polynomials_to_be_shifted), RefVector(multilinear_commitments), @@ -172,16 +190,111 @@ TYPED_TEST(GeminiTest, DoubleWithShift) auto eval2_shift = poly2.evaluate_mle(u, true); // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier - std::vector multilinear_evaluations = { eval1, eval2, eval2_shift }; + std::vector multilinear_evaluations_unshifted = { eval1, eval2 }; + std::vector multilinear_evaluations_shifted = { eval2_shift }; std::vector> multilinear_polynomials = { poly1.share(), poly2.share() }; std::vector> multilinear_polynomials_to_be_shifted = { poly2.share() }; std::vector multilinear_commitments = { commitment1, commitment2 }; std::vector multilinear_commitments_to_be_shifted = { commitment2 }; this->execute_gemini_and_verify_claims(u, - multilinear_evaluations, + RefVector(multilinear_evaluations_unshifted), + RefVector(multilinear_evaluations_shifted), RefVector(multilinear_polynomials), RefVector(multilinear_polynomials_to_be_shifted), RefVector(multilinear_commitments), RefVector(multilinear_commitments_to_be_shifted)); } + +TYPED_TEST(GeminiTest, DoubleWithShiftAndConcatenation) +{ + using Fr = typename TypeParam::ScalarField; + using GroupElement = typename TypeParam::Element; + using Polynomial = bb::Polynomial; + + const size_t n = 16; + const size_t log_n = 4; + + auto u = this->random_evaluation_point(log_n); + + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, 1); // make 'shiftable' + + auto commitment1 = this->commit(poly1); + auto commitment2 = this->commit(poly2); + + auto eval1 = poly1.evaluate_mle(u); + auto eval2 = poly2.evaluate_mle(u); + auto eval2_shift = poly2.evaluate_mle(u, true); + + // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier + std::vector multilinear_evaluations_unshifted = { eval1, eval2 }; + std::vector multilinear_evaluations_shifted = { eval2_shift }; + std::vector multilinear_polynomials = { poly1.share(), poly2.share() }; + std::vector multilinear_polynomials_to_be_shifted = { poly2.share() }; + std::vector multilinear_commitments = { commitment1, commitment2 }; + std::vector multilinear_commitments_to_be_shifted = { commitment2 }; + + size_t concatenation_index = 2; + size_t N = n; + size_t MINI_CIRCUIT_N = N / concatenation_index; + + // Polynomials "chunks" that are concatenated in the PCS + std::vector> concatenation_groups; + + // Concatenated polynomials + std::vector concatenated_polynomials; + + // Evaluations of concatenated polynomials + std::vector c_evaluations; + size_t NUM_CONCATENATED = 3; + // For each polynomial to be concatenated + for (size_t i = 0; i < NUM_CONCATENATED; ++i) { + std::vector concatenation_group; + Polynomial concatenated_polynomial(N); + // For each chunk + for (size_t j = 0; j < concatenation_index; j++) { + Polynomial chunk_polynomial(N); + // Fill the chunk polynomial with random values and appropriately fill the space in + // concatenated_polynomial + for (size_t k = 0; k < MINI_CIRCUIT_N; k++) { + // Chunks should be shiftable + auto tmp = Fr(0); + if (k > 0) { + tmp = Fr::random_element(this->engine); + } + chunk_polynomial.at(k) = tmp; + concatenated_polynomial.at(j * MINI_CIRCUIT_N + k) = tmp; + } + concatenation_group.emplace_back(chunk_polynomial); + } + // Store chunks + concatenation_groups.emplace_back(concatenation_group); + // Store concatenated polynomial + concatenated_polynomials.emplace_back(concatenated_polynomial); + // Get evaluation + c_evaluations.emplace_back(concatenated_polynomial.evaluate_mle(u)); + } + + // Compute commitments of all polynomial chunks + std::vector> concatenation_groups_commitments; + for (size_t i = 0; i < NUM_CONCATENATED; ++i) { + std::vector concatenation_group_commitment; + for (size_t j = 0; j < concatenation_index; j++) { + concatenation_group_commitment.emplace_back(this->commit(concatenation_groups[i][j])); + } + concatenation_groups_commitments.emplace_back(concatenation_group_commitment); + } + + this->execute_gemini_and_verify_claims(u, + RefVector(multilinear_evaluations_unshifted), + RefVector(multilinear_evaluations_shifted), + RefVector(multilinear_polynomials), + RefVector(multilinear_polynomials_to_be_shifted), + RefVector(multilinear_commitments), + RefVector(multilinear_commitments_to_be_shifted), + RefVector(concatenated_polynomials), + RefVector(c_evaluations), + to_vector_of_ref_vectors(concatenation_groups), + to_vector_of_ref_vectors(concatenation_groups_commitments)); +} 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 4872123c95a..f92f61d1df5 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -49,7 +49,7 @@ std::vector::Claim> GeminiProver_::prove( const std::shared_ptr>& commitment_key, const std::shared_ptr& transcript, RefSpan concatenated_polynomials, - const std::vector>& groups_to_be_concatenated) + [[maybe_unused]] const std::vector>& groups_to_be_concatenated) { size_t log_n = numeric::get_msb(static_cast(circuit_size)); @@ -72,26 +72,27 @@ std::vector::Claim> GeminiProver_::prove( } size_t num_groups = groups_to_be_concatenated.size(); - size_t num_chunks_per_group = groups_to_be_concatenated.empty() ? 0 : groups_to_be_concatenated[0].size(); + // size_t num_chunks_per_group = groups_to_be_concatenated.empty() ? 0 : groups_to_be_concatenated[0].size(); // Concatenated polynomials Polynomial batched_concatenated(n); // construct concatention_groups_batched - std::vector batched_groups_to_be_concatenated; - for (size_t i = 0; i < num_chunks_per_group; ++i) { - batched_groups_to_be_concatenated.push_back(Polynomial(n)); - } + // std::vector batched_groups_to_be_concatenated; + // for (size_t i = 0; i < num_chunks_per_group; ++i) { + // batched_groups_to_be_concatenated.push_back(Polynomial(n)); + // } // for each group for (size_t i = 0; i < num_groups; ++i) { - batched_concatenated.add_scaled(concatenated_polynomials[i], rho_challenge); + batched_unshifted.add_scaled(concatenated_polynomials[i], rho_challenge); // for each element in a group - for (size_t j = 0; j < num_chunks_per_group; ++j) { - batched_groups_to_be_concatenated[j].add_scaled(groups_to_be_concatenated[i][j], rho_challenge); - } + // TODO: do sth with the concatenated groups + // for (size_t j = 0; j < num_chunks_per_group; ++j) { + // batched_groups_to_be_concatenated[j].add_scaled(groups_to_be_concatenated[i][j], rho_challenge); + // } rho_challenge *= rho; } - batched_unshifted += batched_concatenated; + // let's say we leave this as it is because the batched_concatenated are after all unshifted polynomials auto fold_polynomials = compute_fold_polynomials( log_n, multilinear_challenge, std::move(batched_unshifted), std::move(batched_to_be_shifted)); @@ -104,6 +105,7 @@ std::vector::Claim> GeminiProver_::prove( } } const Fr r_challenge = transcript->template get_challenge("Gemini:r"); + // here I need to calculate using the concatenated groups std::vector claims = compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), r_challenge); for (size_t l = 1; l <= CONST_PROOF_SIZE_LOG_N; l++) { diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index 7db3ea01e3b..10d0bca5440 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -272,7 +272,8 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); auto gemini_verifier_claim = GeminiVerifier::reduce_verification(mle_opening_point, - multilinear_evaluations, + RefArray{ eval1, eval2 }, + RefArray{ eval2_shift }, RefArray{ commitment1, commitment2 }, RefArray{ commitment2 }, verifier_transcript); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index e23a6d90c77..027d81e02ad 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -106,7 +106,8 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) // Gemini verifier output: // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 auto gemini_verifier_claim = GeminiVerifier::reduce_verification(mle_opening_point, - multilinear_evaluations, + RefArray{ eval1, eval2 }, + RefArray{ eval2_shift }, RefArray{ commitment1, commitment2 }, RefArray{ commitment2 }, verifier_transcript); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 60b52230cc3..b1333190bb9 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -272,14 +272,15 @@ template class ShpleminiVerifier_ { RefSpan shifted_commitments, RefSpan unshifted_evaluations, RefSpan shifted_evaluations, - RefSpan concatenated_evaluations, const Fr& multivariate_batching_challenge, - const Fr& unshifted_scalar, + const Fr& unshifted_scalar, // possibly these need to be modified const Fr& shifted_scalar, std::vector& commitments, std::vector& scalars, - Fr& batched_evaluation) + Fr& batched_evaluation, + [[maybe_unused]] RefSpan concatenated_evaluations = {}) { + // I think what needs to happen here is that i construct without doingt he MSM Fr current_batching_challenge = Fr(1); for (auto [unshifted_commitment, unshifted_evaluation] : zip_view(unshifted_commitments, unshifted_evaluations)) { From 8a147c29fdd6dbb34cd40f0b955d76d02fc845b6 Mon Sep 17 00:00:00 2001 From: maramihali Date: Wed, 9 Oct 2024 14:04:49 +0000 Subject: [PATCH 06/13] still trying --- .../commitment_schemes/gemini/gemini.hpp | 10 ++- .../commitment_schemes/gemini/gemini_impl.hpp | 69 ++++++++++++++----- .../shplonk/shplemini.test.cpp | 4 +- 3 files changed, 61 insertions(+), 22 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 9eca5a97cc7..ba5089c829f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -105,9 +105,12 @@ template class GeminiProver_ { Polynomial&& batched_unshifted, Polynomial&& batched_to_be_shifted); - static std::vector compute_fold_polynomial_evaluations(const size_t log_N, - std::vector&& fold_polynomials, - const Fr& r_challenge); + static std::vector compute_fold_polynomial_evaluations( + const size_t log_N, + std::vector&& fold_polynomials, + Polynomial&& batched_unshifted, + const Fr& r_challenge, + std::vector&& batched_groups_to_be_concatenated = {}); template static std::vector prove(const Fr circuit_size, @@ -191,6 +194,7 @@ template class GeminiVerifier_ { if (!concatenation_group_commitments.empty()) { size_t CONCATENATION_GROUP_SIZE = concatenation_group_commitments[0].size(); size_t MINICIRCUIT_N = N / CONCATENATION_GROUP_SIZE; + info("Verifer side ", MINICIRCUIT_N); std::vector r_shifts_pos; std::vector r_shifts_neg; auto current_r_shift_pos = r; 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 f92f61d1df5..a6ce7485f73 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -72,29 +72,32 @@ std::vector::Claim> GeminiProver_::prove( } size_t num_groups = groups_to_be_concatenated.size(); - // size_t num_chunks_per_group = groups_to_be_concatenated.empty() ? 0 : groups_to_be_concatenated[0].size(); + size_t num_chunks_per_group = groups_to_be_concatenated.empty() ? 0 : groups_to_be_concatenated[0].size(); // Concatenated polynomials Polynomial batched_concatenated(n); // construct concatention_groups_batched - // std::vector batched_groups_to_be_concatenated; - // for (size_t i = 0; i < num_chunks_per_group; ++i) { - // batched_groups_to_be_concatenated.push_back(Polynomial(n)); - // } + std::vector batched_groups_to_be_concatenated; + for (size_t i = 0; i < num_chunks_per_group; ++i) { + batched_groups_to_be_concatenated.push_back(Polynomial(n)); + } // for each group for (size_t i = 0; i < num_groups; ++i) { - batched_unshifted.add_scaled(concatenated_polynomials[i], rho_challenge); + batched_concatenated.add_scaled(concatenated_polynomials[i], rho_challenge); // for each element in a group // TODO: do sth with the concatenated groups - // for (size_t j = 0; j < num_chunks_per_group; ++j) { - // batched_groups_to_be_concatenated[j].add_scaled(groups_to_be_concatenated[i][j], rho_challenge); - // } + for (size_t j = 0; j < num_chunks_per_group; ++j) { + batched_groups_to_be_concatenated[j].add_scaled(groups_to_be_concatenated[i][j], rho_challenge); + } rho_challenge *= rho; } + Polynomial batched_unshifted_copy = batched_unshifted; + batched_unshifted_copy += batched_concatenated; + // let's say we leave this as it is because the batched_concatenated are after all unshifted polynomials auto fold_polynomials = compute_fold_polynomials( - log_n, multilinear_challenge, std::move(batched_unshifted), std::move(batched_to_be_shifted)); + log_n, multilinear_challenge, std::move(batched_unshifted_copy), std::move(batched_to_be_shifted)); for (size_t l = 0; l < CONST_PROOF_SIZE_LOG_N - 1; l++) { if (l < log_n - 1) { @@ -106,7 +109,11 @@ std::vector::Claim> GeminiProver_::prove( } const Fr r_challenge = transcript->template get_challenge("Gemini:r"); // here I need to calculate using the concatenated groups - std::vector claims = compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), r_challenge); + std::vector claims = compute_fold_polynomial_evaluations(log_n, + std::move(fold_polynomials), + std::move(batched_unshifted), + r_challenge, + std::move(batched_groups_to_be_concatenated)); for (size_t l = 1; l <= CONST_PROOF_SIZE_LOG_N; l++) { if (l <= log_n) { @@ -173,8 +180,8 @@ std::vector::Polynomial> GeminiProver_::com // size of the previous polynomial/2 const size_t n_l = 1 << (num_variables - l - 1); - // Use as many threads as it is useful so that 1 thread doesn't process 1 element, but make sure that there is - // at least 1 + // Use as many threads as it is useful so that 1 thread doesn't process 1 element, but make sure that there + // is at least 1 size_t num_used_threads = std::min(n_l / efficient_operations_per_thread, num_threads); num_used_threads = num_used_threads ? num_used_threads : 1; size_t chunk_size = n_l / num_used_threads; @@ -220,25 +227,35 @@ std::vector::Polynomial> GeminiProver_::com */ template std::vector::Claim> GeminiProver_::compute_fold_polynomial_evaluations( - const size_t log_N, std::vector&& fold_polynomials, const Fr& r_challenge) + const size_t log_N, + std::vector&& fold_polynomials, + Polynomial&& batched_unshifted, + const Fr& r_challenge, + [[maybe_unused]] std::vector&& batched_groups_to_be_concatenated) { - const size_t num_variables = log_N; + Fr r_inv = r_challenge.invert(); + + const size_t num_variables = log_N; + info(batched_unshifted); Polynomial& batched_F = fold_polynomials[0]; // F(X) = ∑ⱼ ρʲ fⱼ(X) + info(fold_polynomials[0]); + batched_F = batched_unshifted; // I made fold_polynomials[0] be just batch unshifted without concatenation + info(fold_polynomials[0]); Polynomial& batched_G = fold_polynomials[1]; // G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) // Compute univariate opening queries rₗ = r^{2ˡ} for l = 0, 1, ..., m-1 std::vector r_squares = gemini::powers_of_evaluation_challenge(r_challenge, num_variables); // Compute G/r - Fr r_inv = r_challenge.invert(); batched_G *= r_inv; // 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]; + Polynomial& A_0_pos = fold_polynomials[0]; // already modified to only be the unshifted stuff // A₀₊(X) = F(X) + G(X)/r, s.t. A₀₊(r) = A₀(r) + // here A_0_pos += batched_G; // Perform a swap so that tmp = G(X)/r and A_0_neg = F(X) @@ -246,8 +263,26 @@ std::vector::Claim> GeminiProver_::compute_ Polynomial& A_0_neg = fold_polynomials[1]; // A₀₋(X) = F(X) - G(X)/r, s.t. A₀₋(-r) = A₀(-r) + // here A_0_neg -= tmp; + if (!batched_groups_to_be_concatenated.empty()) { + size_t N = 1 << log_N; + size_t MINICIRCUIT_N = N / batched_groups_to_be_concatenated.size(); + info("Prover side ", MINICIRCUIT_N); + + auto current_r_shift_pos = r_challenge; + auto current_r_shift_neg = r_inv; + auto r_to_minicircuit_n_pos = r_challenge.pow(MINICIRCUIT_N); + auto r_to_minicircuit_n_neg = r_inv.pow(MINICIRCUIT_N); + for (size_t i = 0; i < batched_groups_to_be_concatenated.size(); i++) { + A_0_pos.add_scaled(batched_groups_to_be_concatenated[i], current_r_shift_pos); + A_0_neg.add_scaled(batched_groups_to_be_concatenated[i], current_r_shift_neg); + current_r_shift_pos *= r_to_minicircuit_n_pos; + current_r_shift_neg *= r_to_minicircuit_n_neg; + } + } + std::vector opening_claims; opening_claims.reserve(num_variables + 1); 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 55739360179..3e5c141c33b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -173,8 +173,8 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) prover_commitments.emplace_back(commitment); } - const auto opening_claims = - GeminiProver::compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), gemini_eval_challenge); + const auto opening_claims = GeminiProver::compute_fold_polynomial_evaluations( + log_n, std::move(fold_polynomials), std::move(batched_unshifted), gemini_eval_challenge); std::vector prover_evaluations; for (size_t l = 0; l < log_n; ++l) { From eb2197ec7d3831dcbc3970994610c69ab39a68f7 Mon Sep 17 00:00:00 2001 From: maramihali Date: Wed, 9 Oct 2024 17:41:38 +0000 Subject: [PATCH 07/13] stuff --- .../src/barretenberg/commitment_schemes/gemini/gemini.hpp | 4 ++-- .../barretenberg/commitment_schemes/gemini/gemini.test.cpp | 5 ++++- .../barretenberg/commitment_schemes/gemini/gemini_impl.hpp | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index ba5089c829f..8b80d6496d3 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -197,8 +197,8 @@ template class GeminiVerifier_ { info("Verifer side ", MINICIRCUIT_N); std::vector r_shifts_pos; std::vector r_shifts_neg; - auto current_r_shift_pos = r; - auto current_r_shift_neg = r_inv; + auto current_r_shift_pos = Fr(1); + auto current_r_shift_neg = Fr(1); auto r_to_minicircuit_n_pos = r.pow(MINICIRCUIT_N); auto r_to_minicircuit_n_neg = r_inv.pow(MINICIRCUIT_N); for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp index e02800020ea..a61a2e65120 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp @@ -60,9 +60,12 @@ template class GeminiTest : public CommitmentTest { concatenated_evaluations); // Check equality of the opening pairs computed by prover and verifier + size_t i = 0; for (auto [prover_claim, verifier_claim] : zip_view(prover_output, verifier_claims)) { - ASSERT_EQ(prover_claim.opening_pair, verifier_claim.opening_pair); + info(i); this->verify_opening_claim(verifier_claim, prover_claim.polynomial); + ASSERT_EQ(prover_claim.opening_pair, verifier_claim.opening_pair); + i++; } } }; 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 a6ce7485f73..46f00e057f0 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -271,8 +271,8 @@ std::vector::Claim> GeminiProver_::compute_ size_t MINICIRCUIT_N = N / batched_groups_to_be_concatenated.size(); info("Prover side ", MINICIRCUIT_N); - auto current_r_shift_pos = r_challenge; - auto current_r_shift_neg = r_inv; + auto current_r_shift_pos = Fr(1); + auto current_r_shift_neg = Fr(1); auto r_to_minicircuit_n_pos = r_challenge.pow(MINICIRCUIT_N); auto r_to_minicircuit_n_neg = r_inv.pow(MINICIRCUIT_N); for (size_t i = 0; i < batched_groups_to_be_concatenated.size(); i++) { From 48ab8778dfe6dac01efc7f092402341265846f92 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 14 Oct 2024 12:02:17 +0000 Subject: [PATCH 08/13] it works --- .../cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp | 3 ++- .../barretenberg/commitment_schemes/gemini/gemini_impl.hpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 8b80d6496d3..bb95d3e98b7 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -189,6 +189,7 @@ template class GeminiVerifier_ { GroupElement batched_concatenated_neg = GroupElement::zero(); Fr r_inv = r.invert(); // r⁻¹ + Fr r_minus = -r; ASSERT(concatenated_evaluations.size() == concatenation_group_commitments.size()); if (!concatenation_group_commitments.empty()) { @@ -200,7 +201,7 @@ template class GeminiVerifier_ { auto current_r_shift_pos = Fr(1); auto current_r_shift_neg = Fr(1); auto r_to_minicircuit_n_pos = r.pow(MINICIRCUIT_N); - auto r_to_minicircuit_n_neg = r_inv.pow(MINICIRCUIT_N); + auto r_to_minicircuit_n_neg = r_minus.pow(MINICIRCUIT_N); for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { r_shifts_pos.emplace_back(current_r_shift_pos); r_shifts_neg.emplace_back(current_r_shift_neg); 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 46f00e057f0..f6074dddbf6 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -270,11 +270,11 @@ std::vector::Claim> GeminiProver_::compute_ size_t N = 1 << log_N; size_t MINICIRCUIT_N = N / batched_groups_to_be_concatenated.size(); info("Prover side ", MINICIRCUIT_N); - + auto r_minus = r_challenge; auto current_r_shift_pos = Fr(1); auto current_r_shift_neg = Fr(1); auto r_to_minicircuit_n_pos = r_challenge.pow(MINICIRCUIT_N); - auto r_to_minicircuit_n_neg = r_inv.pow(MINICIRCUIT_N); + auto r_to_minicircuit_n_neg = r_minus.pow(MINICIRCUIT_N); for (size_t i = 0; i < batched_groups_to_be_concatenated.size(); i++) { A_0_pos.add_scaled(batched_groups_to_be_concatenated[i], current_r_shift_pos); A_0_neg.add_scaled(batched_groups_to_be_concatenated[i], current_r_shift_neg); From cfb7b98d655765f859c4fcf9c686f11c3afd192c Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 21 Oct 2024 15:56:32 +0000 Subject: [PATCH 09/13] translator on shplemini --- .../commitment_schemes/gemini/gemini.hpp | 1 - .../commitment_schemes/gemini/gemini_impl.hpp | 48 +++---- .../commitment_schemes/kzg/kzg.test.cpp | 59 ++++++++- .../commitment_schemes/shplonk/shplemini.hpp | 117 ++++++++++++++---- .../shplonk/shplemini.test.cpp | 4 +- .../translator_recursive_verifier.cpp | 27 ++-- .../translator_vm/translator_prover.cpp | 26 ++-- .../translator_vm/translator_verifier.cpp | 27 ++-- 8 files changed, 208 insertions(+), 101 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index bb95d3e98b7..91ecf89c19e 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -230,7 +230,6 @@ template class GeminiVerifier_ { // C₀ᵣ₊ = [F] + r⁻¹⋅[G] GroupElement C0_r_pos; - // C₀ᵣ₊ = [F] + r⁻¹⋅[G] GroupElement C0_r_pos; // C₀ᵣ₋ = [F] - r⁻¹⋅[G] GroupElement C0_r_neg; 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 f6074dddbf6..37348d712b3 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -73,31 +73,27 @@ std::vector::Claim> GeminiProver_::prove( size_t num_groups = groups_to_be_concatenated.size(); size_t num_chunks_per_group = groups_to_be_concatenated.empty() ? 0 : groups_to_be_concatenated[0].size(); - // Concatenated polynomials - Polynomial batched_concatenated(n); - // construct concatention_groups_batched - std::vector batched_groups_to_be_concatenated; + // Allocate space for the groups to be concatenated and for the concatenated polynomials + Polynomial batched_concatenated(n); + std::vector batched_group; for (size_t i = 0; i < num_chunks_per_group; ++i) { - batched_groups_to_be_concatenated.push_back(Polynomial(n)); + batched_group.push_back(Polynomial(n)); } - // for each group + for (size_t i = 0; i < num_groups; ++i) { batched_concatenated.add_scaled(concatenated_polynomials[i], rho_challenge); - // for each element in a group - // TODO: do sth with the concatenated groups for (size_t j = 0; j < num_chunks_per_group; ++j) { - batched_groups_to_be_concatenated[j].add_scaled(groups_to_be_concatenated[i][j], rho_challenge); + batched_group[j].add_scaled(groups_to_be_concatenated[i][j], rho_challenge); } rho_challenge *= rho; } - Polynomial batched_unshifted_copy = batched_unshifted; - batched_unshifted_copy += batched_concatenated; + Polynomial& batched_unshifted_and_concatenated = batched_concatenated; + batched_unshifted_and_concatenated += batched_unshifted; - // let's say we leave this as it is because the batched_concatenated are after all unshifted polynomials auto fold_polynomials = compute_fold_polynomials( - log_n, multilinear_challenge, std::move(batched_unshifted_copy), std::move(batched_to_be_shifted)); + log_n, multilinear_challenge, std::move(batched_unshifted_and_concatenated), std::move(batched_to_be_shifted)); for (size_t l = 0; l < CONST_PROOF_SIZE_LOG_N - 1; l++) { if (l < log_n - 1) { @@ -108,12 +104,9 @@ std::vector::Claim> GeminiProver_::prove( } } const Fr r_challenge = transcript->template get_challenge("Gemini:r"); - // here I need to calculate using the concatenated groups - std::vector claims = compute_fold_polynomial_evaluations(log_n, - std::move(fold_polynomials), - std::move(batched_unshifted), - r_challenge, - std::move(batched_groups_to_be_concatenated)); + + std::vector claims = compute_fold_polynomial_evaluations( + log_n, std::move(fold_polynomials), std::move(batched_unshifted), r_challenge, std::move(batched_group)); for (size_t l = 1; l <= CONST_PROOF_SIZE_LOG_N; l++) { if (l <= log_n) { @@ -129,8 +122,11 @@ std::vector::Claim> GeminiProver_::prove( /** * @brief Computes d-1 fold polynomials Fold_i, i = 1, ..., d-1 * + * @details If proving the opening for translator, batch_unshifted contains the sum of unshifted ond concatenated + * polynomials, scaled by the appropriate power of ρ, F(X) = ∑ⱼ ρʲ fⱼ(X) + ∑ₗ ρᵏ⁺ᵐ⁺ˡ concatenated_polynomials(X) + * * @param mle_opening_point multilinear opening point 'u' - * @param batched_unshifted F(X) = ∑ⱼ ρʲ fⱼ(X) + * @param batched_unshifted F(X) = ∑ⱼ ρʲ fⱼ(X) . * @param batched_to_be_shifted G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) * @return std::vector */ @@ -237,11 +233,8 @@ std::vector::Claim> GeminiProver_::compute_ Fr r_inv = r_challenge.invert(); const size_t num_variables = log_N; - info(batched_unshifted); Polynomial& batched_F = fold_polynomials[0]; // F(X) = ∑ⱼ ρʲ fⱼ(X) - info(fold_polynomials[0]); batched_F = batched_unshifted; // I made fold_polynomials[0] be just batch unshifted without concatenation - info(fold_polynomials[0]); Polynomial& batched_G = fold_polynomials[1]; // G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) // Compute univariate opening queries rₗ = r^{2ˡ} for l = 0, 1, ..., m-1 @@ -255,7 +248,6 @@ std::vector::Claim> GeminiProver_::compute_ Polynomial& A_0_pos = fold_polynomials[0]; // already modified to only be the unshifted stuff // A₀₊(X) = F(X) + G(X)/r, s.t. A₀₊(r) = A₀(r) - // here A_0_pos += batched_G; // Perform a swap so that tmp = G(X)/r and A_0_neg = F(X) @@ -263,18 +255,14 @@ std::vector::Claim> GeminiProver_::compute_ Polynomial& A_0_neg = fold_polynomials[1]; // A₀₋(X) = F(X) - G(X)/r, s.t. A₀₋(-r) = A₀(-r) - // here A_0_neg -= tmp; if (!batched_groups_to_be_concatenated.empty()) { - size_t N = 1 << log_N; - size_t MINICIRCUIT_N = N / batched_groups_to_be_concatenated.size(); - info("Prover side ", MINICIRCUIT_N); - auto r_minus = r_challenge; + size_t MINICIRCUIT_N = (1 << log_N) / batched_groups_to_be_concatenated.size(); auto current_r_shift_pos = Fr(1); auto current_r_shift_neg = Fr(1); auto r_to_minicircuit_n_pos = r_challenge.pow(MINICIRCUIT_N); - auto r_to_minicircuit_n_neg = r_minus.pow(MINICIRCUIT_N); + auto r_to_minicircuit_n_neg = (-r_challenge).pow(MINICIRCUIT_N); for (size_t i = 0; i < batched_groups_to_be_concatenated.size(); i++) { A_0_pos.add_scaled(batched_groups_to_be_concatenated[i], current_r_shift_pos); A_0_neg.add_scaled(batched_groups_to_be_concatenated[i], current_r_shift_neg); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 027d81e02ad..2c59317e916 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -161,6 +161,57 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShift) // Collect multilinear evaluations for input to prover std::vector multilinear_evaluations = { eval1, eval2, eval3, eval1_shift, eval3_shift }; + size_t concatenation_index = 2; + size_t N = n; + size_t MINI_CIRCUIT_N = N / concatenation_index; + + // Polynomials "chunks" that are concatenated in the PCS + std::vector> concatenation_groups; + + // Concatenated polynomials + std::vector concatenated_polynomials; + + // Evaluations of concatenated polynomials + std::vector c_evaluations; + size_t NUM_CONCATENATED = 3; + // For each polynomial to be concatenated + for (size_t i = 0; i < NUM_CONCATENATED; ++i) { + std::vector concatenation_group; + Polynomial concatenated_polynomial(N); + // For each chunk + for (size_t j = 0; j < concatenation_index; j++) { + Polynomial chunk_polynomial(N); + // Fill the chunk polynomial with random values and appropriately fill the space in + // concatenated_polynomial + for (size_t k = 0; k < MINI_CIRCUIT_N; k++) { + // Chunks should be shiftable + auto tmp = Fr(0); + if (k > 0) { + tmp = Fr::random_element(this->engine); + } + chunk_polynomial.at(k) = tmp; + concatenated_polynomial.at(j * MINI_CIRCUIT_N + k) = tmp; + } + concatenation_group.emplace_back(chunk_polynomial); + } + // Store chunks + concatenation_groups.emplace_back(concatenation_group); + // Store concatenated polynomial + concatenated_polynomials.emplace_back(concatenated_polynomial); + // Get evaluation + c_evaluations.emplace_back(concatenated_polynomial.evaluate_mle(mle_opening_point)); + } + + // Compute commitments of all polynomial chunks + std::vector> concatenation_groups_commitments; + for (size_t i = 0; i < NUM_CONCATENATED; ++i) { + std::vector concatenation_group_commitment; + for (size_t j = 0; j < concatenation_index; j++) { + concatenation_group_commitment.emplace_back(this->commit(concatenation_groups[i][j])); + } + concatenation_groups_commitments.emplace_back(concatenation_group_commitment); + } + auto prover_transcript = NativeTranscript::prover_init_empty(); // Run the full prover PCS protocol: @@ -173,7 +224,9 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShift) RefArray{ poly1, poly3 }, mle_opening_point, this->ck(), - prover_transcript); + prover_transcript, + RefVector(concatenated_polynomials), + to_vector_of_ref_vectors(concatenation_groups)); // Shplonk prover output: // - opening pair: (z_challenge, 0) @@ -198,7 +251,9 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShift) RefArray{ eval1_shift, eval3_shift }, mle_opening_point, this->vk()->get_g1_identity(), - verifier_transcript); + verifier_transcript, + to_vector_of_ref_vectors(concatenation_groups_commitments), + RefVector(c_evaluations)); const auto pairing_points = KZG::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript); // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index b1333190bb9..30bb8084b90 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -123,9 +123,12 @@ template class ShpleminiVerifier_ { // Extract log_circuit_size size_t log_circuit_size{ 0 }; + size_t circuit_size{ 0 }; if constexpr (Curve::is_stdlib_type) { + circuit_size = static_cast(N.get_value()); log_circuit_size = numeric::get_msb(static_cast(N.get_value())); } else { + circuit_size = static_cast(N); log_circuit_size = numeric::get_msb(static_cast(N)); } @@ -138,9 +141,11 @@ template class ShpleminiVerifier_ { GeminiVerifier::get_fold_commitments(log_circuit_size, transcript); // - Get Gemini evaluation challenge for Aᵢ, i = 0, … , d−1 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, I think this should be CONST_PROOF_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, CONST_PROOF_SIZE_LOG_N); @@ -150,10 +155,13 @@ template class ShpleminiVerifier_ { // - Get the quotient commitment for the Shplonk batching of Gemini opening claims const auto Q_commitment = transcript->template receive_from_prover("Shplonk:Q"); - // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(Aₙ₋₁), [1]₁) + // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(Aₙ₋₁), [1]₁) where fᵢ are + // the k commitments to unshifted polynomials and gⱼ are the m commitments to shifted polynomials std::vector commitments{ Q_commitment }; + // 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 = Fr(0); @@ -165,18 +173,46 @@ template class ShpleminiVerifier_ { } else { scalars.emplace_back(Fr(1)); } - // Compute 1/(z − r), 1/(z + r), 1/(z + r²), … , 1/(z + r²⁽ⁿ⁻¹⁾) needed for Shplonk batching + + // Compute 1/(z − r), 1/(z + r), 1/(z + r²), … , 1/(z + r²⁽ⁿ⁻¹⁾) + // These represent the denominators of the summand terms in Shplonk partially evaluated polynomial Q_z const std::vector inverse_vanishing_evals = ShplonkVerifier::compute_inverted_gemini_denominators( log_circuit_size + 1, shplonk_evaluation_challenge, gemini_eval_challenge_powers); + // Compute the additional factors to be multiplied with unshifted and shifted commitments when lazily + // reconstructing thec commitment of Q_z + // i-th unshifted commitment is multiplied by −ρⁱ and the unshifted_scalar ( 1/(z−r) + ν/(z+r) ) const Fr unshifted_scalar = inverse_vanishing_evals[0] + shplonk_batching_challenge * inverse_vanishing_evals[1]; - // i-th shifted commitment is multiplied by −ρⁱ⁺ᵏ and the shifted_scalar r⁻¹ ⋅ (1/(z−r) − ν/(z+r)) + + // j-th shifted commitment is multiplied by −ρᵏ⁺ʲ⁻¹ and the shifted_scalar r⁻¹ ⋅ (1/(z−r) − ν/(z+r)) const Fr shifted_scalar = gemini_evaluation_challenge.invert() * (inverse_vanishing_evals[0] - shplonk_batching_challenge * inverse_vanishing_evals[1]); + std::vector concatenation_scalars; + if (!concatenation_group_commitments.empty()) { + const size_t concatenation_group_size = concatenation_group_commitments[0].size(); + // The "real" size of each polynomial in concatenation groups (i.e. the nummber of non-zero values) + const size_t mini_circuit_size = circuit_size / concatenation_group_size; + auto r_shift_pos = Fr(1); + auto r_shift_neg = Fr(1); + auto r_pow_minicircuit = gemini_evaluation_challenge.pow(mini_circuit_size); + auto r_neg_pow_minicircuit = (-gemini_evaluation_challenge).pow(mini_circuit_size); + + for (size_t i = 0; i < concatenation_group_size; ++i) { + // The commitments in the l-th concatenation group will be multiplied by -ρᵏ⁺ᵐ⁺ˡ and + // ( r_shift_pos/(z−r) + ν ⋅ r_shift_neg /(z+r) ) + concatenation_scalars.emplace_back(r_shift_pos * inverse_vanishing_evals[0] + + r_shift_neg * shplonk_batching_challenge * + inverse_vanishing_evals[1]); + + r_shift_pos *= r_pow_minicircuit; + r_shift_neg *= r_neg_pow_minicircuit; + } + } + // 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 = Fr(0); @@ -189,7 +225,10 @@ template class ShpleminiVerifier_ { shifted_scalar, commitments, scalars, - batched_evaluation); + batched_evaluation, + concatenation_scalars, + concatenation_group_commitments, + concatenated_evaluations); // Place the commitments to Gemini Aᵢ to the vector of commitments, compute the contributions from // Aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars @@ -262,25 +301,31 @@ template class ShpleminiVerifier_ { * @param shifted_commitments Commitments to shifted polynomials. * @param claimed_evaluations Claimed evaluations of the corresponding polynomials. * @param multivariate_batching_challenge Random challenge used for batching of multivariate evaluation claims. - * @param unshifted_scalar Scaling factor for unshifted polynomials. - * @param shifted_scalar Scaling factor for shifted polynomials. + * @param unshifted_scalar Scaling factor for commitments to unshifted polynomials. + * @param shifted_scalar Scaling factor for commitments to shifted polynomials. * @param commitments The vector of commitments to be populated. * @param scalars The vector of scalars to be populated. * @param batched_evaluation The evaluation of the batched multilinear polynomial. + * @param concatenated_scalars Scaling factors for the commitments to polynomials in concatenation groups, one for + * each group. + * @param concatenation_group_commitments Commitments to polynomials to be concatenated. + * @param concatenated_evaluations Evaluations of the full concatenated polynomials. */ - static void batch_multivariate_opening_claims(RefSpan unshifted_commitments, - RefSpan shifted_commitments, - RefSpan unshifted_evaluations, - RefSpan shifted_evaluations, - const Fr& multivariate_batching_challenge, - const Fr& unshifted_scalar, // possibly these need to be modified - const Fr& shifted_scalar, - std::vector& commitments, - std::vector& scalars, - Fr& batched_evaluation, - [[maybe_unused]] RefSpan concatenated_evaluations = {}) + static void batch_multivariate_opening_claims( + RefSpan unshifted_commitments, + RefSpan shifted_commitments, + RefSpan unshifted_evaluations, + RefSpan shifted_evaluations, + const Fr& multivariate_batching_challenge, + const Fr& unshifted_scalar, + const Fr& shifted_scalar, + std::vector& commitments, + std::vector& scalars, + Fr& batched_evaluation, + std::vector concatenated_scalars = {}, + const std::vector>& concatenation_group_commitments = {}, + RefSpan concatenated_evaluations = {}) { - // I think what needs to happen here is that i construct without doingt he MSM Fr current_batching_challenge = Fr(1); for (auto [unshifted_commitment, unshifted_evaluation] : zip_view(unshifted_commitments, unshifted_evaluations)) { @@ -296,20 +341,40 @@ template class ShpleminiVerifier_ { for (auto [shifted_commitment, shifted_evaluation] : zip_view(shifted_commitments, shifted_evaluations)) { // Move shifted commitments to the 'commitments' vector commitments.emplace_back(std::move(shifted_commitment)); - // Compute −ρ⁽ⁱ⁺ᵏ⁾ ⋅ r⁻¹ ⋅ (1/(z−r) − ν/(z+r)) and place into 'scalars' + // Compute −ρ⁽ᵏ⁺ʲ⁾ ⋅ r⁻¹ ⋅ (1/(z−r) − ν/(z+r)) and place into 'scalars' scalars.emplace_back(-shifted_scalar * current_batching_challenge); - // Accumulate the evaluation of ∑ ρ⁽ⁱ⁺ᵏ⁾ ⋅ f_shift, i at the sumcheck challenge + // Accumulate the evaluation of ∑ ρ⁽ᵏ⁺ʲ⁾ ⋅ f_shift at the sumcheck challenge batched_evaluation += shifted_evaluation * current_batching_challenge; - // Update the batching challenge + // Update the batching challenge ρ current_batching_challenge *= multivariate_batching_challenge; } + + // If we are performing an opening verification for the translator, add the contributions from the concatenation + // commitments and evaluations to the result + ASSERT(concatenated_evaluations.size() == concatenation_group_commitments.size()); + if (!concatenation_group_commitments.empty()) { + size_t concatenation_group_size = concatenation_group_commitments[0].size(); + size_t group_idx = 0; + for (auto concatenation_group_commitment : concatenation_group_commitments) { + for (size_t i = 0; i < concatenation_group_size; ++i) { + commitments.emplace_back(std::move(concatenation_group_commitment[i])); + scalars.emplace_back(-current_batching_challenge * concatenated_scalars[i]); + } + // Accumulate the batched evaluations of concatenated polynomials + batched_evaluation += concatenated_evaluations[group_idx] * current_batching_challenge; + // Update the batching challenge ρ + current_batching_challenge *= multivariate_batching_challenge; + group_idx++; + } + } } + /** - * @brief Populates the 'commitments' and 'scalars' vectors with the commitments to Gemini fold polynomials \f$ A_i - * \f$. + * @brief Populates the 'commitments' and 'scalars' vectors with the commitments to Gemini fold polynomials \f$ + * A_i \f$. * - * @details Once the commitments to Gemini "fold" polynomials \f$ A_i \f$ and their evaluations at \f$ -r^{2^i} \f$, - * where \f$ i = 1, \ldots, n-1 \f$, are received by the verifier, it performs the following operations: + * @details Once the commitments to Gemini "fold" polynomials \f$ A_i \f$ and their evaluations at \f$ -r^{2^i} + * \f$, where \f$ i = 1, \ldots, n-1 \f$, are received by the verifier, it performs the following operations: * * 1. Moves the vector * \f[ 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 3e5c141c33b..ddfd83c1a8a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -164,6 +164,7 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) // 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 batched_unshifted_copy = batched_unshifted; auto fold_polynomials = GeminiProver::compute_fold_polynomials( log_n, mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); @@ -172,9 +173,8 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) auto commitment = this->ck()->commit(fold_polynomials[l + 2]); prover_commitments.emplace_back(commitment); } - const auto opening_claims = GeminiProver::compute_fold_polynomial_evaluations( - log_n, std::move(fold_polynomials), std::move(batched_unshifted), gemini_eval_challenge); + log_n, std::move(fold_polynomials), std::move(batched_unshifted_copy), gemini_eval_challenge); std::vector prover_evaluations; for (size_t l = 0; l < log_n; ++l) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index 9604db9eb92..cd1bcd3ce1c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -1,5 +1,5 @@ #include "./translator_recursive_verifier.hpp" -#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/common/throw_or_abort.hpp" #include "barretenberg/relations/translator_vm/translator_decomposition_relation_impl.hpp" #include "barretenberg/relations/translator_vm/translator_delta_range_constraint_relation_impl.hpp" @@ -62,7 +62,7 @@ std::array TranslatorRecursiveVerifier_; using PCS = typename Flavor::PCS; using Curve = typename Flavor::Curve; - using ZeroMorph = ::bb::ZeroMorphVerifier_; + using Shplemini = ::bb::ShpleminiVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; using CommitmentLabels = typename Flavor::CommitmentLabels; @@ -117,17 +117,18 @@ std::array TranslatorRecursiveVerifier_; - auto prover_opening_claim = - ZeroMorph::prove(key->circuit_size, - key->polynomials.get_unshifted_without_concatenated(), - key->polynomials.get_to_be_shifted(), - sumcheck_output.claimed_evaluations.get_unshifted_without_concatenated(), - sumcheck_output.claimed_evaluations.get_shifted(), - sumcheck_output.challenge, - commitment_key, - transcript, - key->polynomials.get_concatenated(), - sumcheck_output.claimed_evaluations.get_concatenated(), - key->polynomials.get_groups_to_be_concatenated()); + using OpeningClaim = ProverOpeningClaim; + + const OpeningClaim prover_opening_claim = + ShpleminiProver_::prove(key->circuit_size, + key->polynomials.get_unshifted_without_concatenated(), + key->polynomials.get_to_be_shifted(), + sumcheck_output.challenge, + commitment_key, + transcript, + key->polynomials.get_concatenated(), + key->polynomials.get_groups_to_be_concatenated()); PCS::compute_opening_proof(commitment_key, prover_opening_claim, transcript); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index f217e62bb6e..60262aaa7bd 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -1,5 +1,5 @@ #include "./translator_verifier.hpp" -#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" #include "barretenberg/transcript/transcript.hpp" @@ -55,7 +55,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) { using Curve = typename Flavor::Curve; using PCS = typename Flavor::PCS; - using ZeroMorph = ::bb::ZeroMorphVerifier_; + using Shplemini = ShpleminiVerifier_; batching_challenge_v = transcript->template get_challenge("Translation:batching_challenge"); @@ -113,17 +113,18 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description ofthe // unrolled protocol. - auto opening_claim = ZeroMorph::verify(circuit_size, - commitments.get_unshifted_without_concatenated(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted_without_concatenated(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - Commitment::one(), - transcript, - commitments.get_groups_to_be_concatenated(), - claimed_evaluations.get_concatenated()); - auto pairing_points = PCS::reduce_verify(opening_claim, transcript); + auto opening_claim = + Shplemini::compute_batch_opening_claim(circuit_size, + commitments.get_unshifted_without_concatenated(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted_without_concatenated(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + Commitment::one(), + transcript, + commitments.get_groups_to_be_concatenated(), + claimed_evaluations.get_concatenated()); + auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); auto verified = key->pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); From 5491b58ac7b0d9c9bb056dd799ea96e16c650aed Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 22 Oct 2024 11:12:16 +0000 Subject: [PATCH 10/13] cleanup and explanations --- .../commitment_schemes/gemini/gemini.hpp | 145 ++++----------- .../commitment_schemes/gemini/gemini.test.cpp | 166 +++++++++--------- .../commitment_schemes/gemini/gemini_impl.hpp | 65 ++++--- .../commitment_schemes/ipa/ipa.test.cpp | 6 +- .../commitment_schemes/kzg/kzg.test.cpp | 143 +++++++++------ .../commitment_schemes/shplonk/shplemini.hpp | 14 +- .../shplonk/shplemini.test.cpp | 5 +- .../commitment_schemes/utils/test_utils.hpp | 77 ++++++++ .../zeromorph/zeromorph.test.cpp | 4 +- 9 files changed, 333 insertions(+), 292 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_utils.hpp diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 91ecf89c19e..4282bee62cf 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -103,12 +103,12 @@ template class GeminiProver_ { static std::vector compute_fold_polynomials(const size_t log_N, std::span multilinear_challenge, Polynomial&& batched_unshifted, - Polynomial&& batched_to_be_shifted); + Polynomial&& batched_to_be_shifted, + Polynomial&& batched_concatenated = {}); static std::vector compute_fold_polynomial_evaluations( const size_t log_N, std::vector&& fold_polynomials, - Polynomial&& batched_unshifted, const Fr& r_challenge, std::vector&& batched_groups_to_be_concatenated = {}); @@ -126,8 +126,8 @@ template class GeminiProver_ { template class GeminiVerifier_ { using Fr = typename Curve::ScalarField; - using GroupElement = typename Curve::Element; using Commitment = typename Curve::AffineElement; + using GroupElement = typename Curve::Element; public: /** @@ -146,11 +146,11 @@ template class GeminiVerifier_ { std::span multilinear_challenge, RefSpan unshifted_evaluations, RefSpan shifted_evaluations, - RefSpan unshifted_commitments, - RefSpan to_be_shifted_commitments, + RefSpan unshifted_commitments, + RefSpan to_be_shifted_commitments, auto& transcript, - [[maybe_unused]] const std::vector>& concatenation_group_commitments = {}, - [[maybe_unused]] RefSpan concatenated_evaluations = {}) + const std::vector>& concatenation_group_commitments = {}, + RefSpan concatenated_evaluations = {}) { const size_t num_variables = multilinear_challenge.size(); @@ -183,34 +183,43 @@ template class GeminiVerifier_ { const Fr r = transcript->template get_challenge("Gemini:r"); const std::vector r_squares = gemini::powers_of_evaluation_challenge(r, CONST_PROOF_SIZE_LOG_N); - // have to do it both with and without minus (i.e. r and -r) + // Get evaluations a_i, i = 0,...,m-1 from transcript + const std::vector evaluations = get_gemini_evaluations(num_variables, transcript); - GroupElement batched_concatenated_pos = GroupElement::zero(); - GroupElement batched_concatenated_neg = GroupElement::zero(); + GroupElement C0_r_pos = batched_commitment_unshifted; + GroupElement C0_r_neg = batched_commitment_unshifted; - Fr r_inv = r.invert(); // r⁻¹ - Fr r_minus = -r; + Fr r_inv = r.invert(); + if (!batched_commitment_to_be_shifted.is_point_at_infinity()) { + batched_commitment_to_be_shifted = batched_commitment_to_be_shifted * r_inv; + C0_r_pos += batched_commitment_to_be_shifted; + C0_r_neg -= batched_commitment_to_be_shifted; + } + // If verifying the opening for the translator VM, we reconstruct the commitment of the batched concatenated + // polynomials, partially evaluated in r and -r, using the commitments in the concatenation groups ASSERT(concatenated_evaluations.size() == concatenation_group_commitments.size()); if (!concatenation_group_commitments.empty()) { - size_t CONCATENATION_GROUP_SIZE = concatenation_group_commitments[0].size(); - size_t MINICIRCUIT_N = N / CONCATENATION_GROUP_SIZE; - info("Verifer side ", MINICIRCUIT_N); + size_t concatenation_group_size = concatenation_group_commitments[0].size(); + // The "real" size of polynomials in concatenation groups (i.e. the number of non-zero values) + const size_t mini_circuit_size = N / concatenation_group_size; + Fr current_r_shift_pos = Fr(1); + Fr current_r_shift_neg = Fr(1); + const Fr r_pow_minicircuit = r.pow(mini_circuit_size); + const Fr r_neg_pow_minicircuit = (-r).pow(mini_circuit_size); std::vector r_shifts_pos; std::vector r_shifts_neg; - auto current_r_shift_pos = Fr(1); - auto current_r_shift_neg = Fr(1); - auto r_to_minicircuit_n_pos = r.pow(MINICIRCUIT_N); - auto r_to_minicircuit_n_neg = r_minus.pow(MINICIRCUIT_N); - for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { + for (size_t i = 0; i < concatenation_group_size; ++i) { r_shifts_pos.emplace_back(current_r_shift_pos); r_shifts_neg.emplace_back(current_r_shift_neg); - current_r_shift_pos *= r_to_minicircuit_n_pos; - current_r_shift_neg *= r_to_minicircuit_n_neg; + current_r_shift_pos *= r_pow_minicircuit; + current_r_shift_neg *= r_neg_pow_minicircuit; } size_t j = 0; + GroupElement batched_concatenated_pos = GroupElement::zero(); + GroupElement batched_concatenated_neg = GroupElement::zero(); for (auto& concatenation_group_commitment : concatenation_group_commitments) { - for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { + for (size_t i = 0; i < concatenation_group_size; ++i) { batched_concatenated_pos += concatenation_group_commitment[i] * batching_scalar * r_shifts_pos[i]; batched_concatenated_neg += concatenation_group_commitment[i] * batching_scalar * r_shifts_neg[i]; } @@ -218,56 +227,17 @@ template class GeminiVerifier_ { batching_scalar *= rho; j++; } - } - - // Get evaluations a_i, i = 0,...,m-1 from transcript - const std::vector evaluations = get_gemini_evaluations(num_variables, transcript); - // Compute evaluation A₀(r) - // I think this stays as it is, it includes concatenated shit - auto a_0_pos = compute_gemini_batched_univariate_evaluation( - num_variables, batched_evaluation, multilinear_challenge, r_squares, evaluations); - // C₀ᵣ₊ = [F] + r⁻¹⋅[G] - GroupElement C0_r_pos; - - // C₀ᵣ₋ = [F] - r⁻¹⋅[G] - GroupElement C0_r_neg; - - // If in a recursive setting, perform a batch mul. Otherwise, accumulate directly. - // TODO(#673): The following if-else represents the stldib/native code paths. Once the "native" verifier is - // achieved through a builder Simulator, the stdlib codepath should become the only codepath. - // if constexpr (Curve::is_stdlib_type) { - // std::vector commitments = { batched_commitment_unshifted, batched_commitment_to_be_shifted - // }; auto builder = r.get_context(); auto one = Fr(builder, 1); - // // TODO(#707): these batch muls include the use of 1 as a scalar. This is handled appropriately as a - // non-mul - // // (add-accumulate) in the goblin batch_mul but is done inefficiently as a scalar mul in the conventional - // // emulated batch mul. - // C0_r_pos = GroupElement::batch_mul(commitments, { one, r_inv }); - // C0_r_neg = GroupElement::batch_mul(commitments, { one, -r_inv }); - // } else { - C0_r_pos = batched_commitment_unshifted; - C0_r_neg = batched_commitment_unshifted; - if (!batched_commitment_to_be_shifted.is_point_at_infinity()) { - batched_commitment_to_be_shifted = batched_commitment_to_be_shifted * r_inv; - C0_r_pos += batched_commitment_to_be_shifted; C0_r_pos += batched_concatenated_pos; - - C0_r_neg -= batched_commitment_to_be_shifted; C0_r_neg += batched_concatenated_neg; } - // } - - // here we use the commitments to concatenated groups, shifting by r - // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] + r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] - // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] - r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] - // auto [c0_r_pos, c0_r_neg] = - // compute_simulated_commitments(batched_commitment_unshifted, batched_commitment_to_be_shifted, r); + // Compute evaluation A₀(r) + auto a_0_pos = compute_gemini_batched_univariate_evaluation( + num_variables, batched_evaluation, multilinear_challenge, r_squares, evaluations); std::vector> fold_polynomial_opening_claims; fold_polynomial_opening_claims.reserve(num_variables + 1); - // we // ( [A₀₊], r, A₀(r) ) fold_polynomial_opening_claims.emplace_back(OpeningClaim{ { r, a_0_pos }, C0_r_pos }); // ( [A₀₋], -r, A₀(-r) ) @@ -352,7 +322,8 @@ template class GeminiVerifier_ { if constexpr (Curve::is_stdlib_type) { auto builder = evaluation_point[0].get_context(); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure! + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): + // insecure! stdlib::bool_t dummy_round = stdlib::witness_t(builder, l > num_variables); batched_eval_accumulator = Fr::conditional_assign(dummy_round, batched_eval_accumulator, batched_eval_round_acc); @@ -366,48 +337,6 @@ template class GeminiVerifier_ { return batched_eval_accumulator; } - - /** - * @brief Computes two commitments to A₀ partially evaluated in r and -r. - * - * @param batched_commitment_unshifted batched commitment to non-shifted polynomials - * @param batched_commitment_to_be_shifted 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_commitment_unshifted, GroupElement& batched_commitment_to_be_shifted, Fr r) - // { - // // C₀ᵣ₊ = [F] + r⁻¹⋅[G] - // GroupElement C0_r_pos; - // // C₀ᵣ₋ = [F] - r⁻¹⋅[G] - // GroupElement C0_r_neg; - // Fr r_inv = r.invert(); // r⁻¹ - - // // If in a recursive setting, perform a batch mul. Otherwise, accumulate directly. - // // TODO(#673): The following if-else represents the stldib/native code paths. Once the "native" verifier is - // // achieved through a builder Simulator, the stdlib codepath should become the only codepath. - // if constexpr (Curve::is_stdlib_type) { - // std::vector commitments = { batched_commitment_unshifted, batched_commitment_to_be_shifted - // }; auto builder = r.get_context(); auto one = Fr(builder, 1); - // // TODO(#707): these batch muls include the use of 1 as a scalar. This is handled appropriately as a - // non-mul - // // (add-accumulate) in the goblin batch_mul but is done inefficiently as a scalar mul in the conventional - // // emulated batch mul. - // C0_r_pos = GroupElement::batch_mul(commitments, { one, r_inv }); - // C0_r_neg = GroupElement::batch_mul(commitments, { one, -r_inv }); - // } else { - // C0_r_pos = batched_commitment_unshifted; - // C0_r_neg = batched_commitment_unshifted; - // if (!batched_commitment_to_be_shifted.is_point_at_infinity()) { - // batched_commitment_to_be_shifted = batched_commitment_to_be_shifted * r_inv; - // C0_r_pos += batched_commitment_to_be_shifted; - // C0_r_neg -= batched_commitment_to_be_shifted; - // } - // } - - // return { C0_r_pos, C0_r_neg }; - // } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp index a61a2e65120..b57c58b765d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp @@ -1,6 +1,7 @@ #include "gemini_impl.hpp" #include "../commitment_key.test.hpp" +#include "barretenberg/commitment_schemes/utils/test_utils.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/transcript/transcript.hpp" @@ -10,21 +11,64 @@ template class GeminiTest : public CommitmentTest { using GeminiProver = GeminiProver_; using GeminiVerifier = GeminiVerifier_; using Fr = typename Curve::ScalarField; - using GroupElement = typename Curve::Element; + using Commitment = typename Curve::AffineElement; public: - void execute_gemini_and_verify_claims( + void execute_gemini_and_verify_claims(std::vector& multilinear_evaluation_point, + RefVector multilinear_evaluations_unshifted, + RefVector multilinear_evaluations_shifted, + RefSpan> multilinear_polynomials, + RefSpan> multilinear_polynomials_to_be_shifted, + RefVector multilinear_commitments, + RefVector multilinear_commitments_to_be_shifted) + { + auto prover_transcript = NativeTranscript::prover_init_empty(); + + // 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 = GeminiProver::prove(1 << multilinear_evaluation_point.size(), + multilinear_polynomials, + multilinear_polynomials_to_be_shifted, + multilinear_evaluation_point, + this->commitment_key, + prover_transcript); + + // Check that the Fold polynomials have been evaluated correctly in the prover + this->verify_batch_opening_pair(prover_output); + + auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + + // Compute: + // - Single opening pair: {r, \hat{a}_0} + // - 2 partially evaluated Fold polynomial commitments [Fold_{r}^(0)] and [Fold_{-r}^(0)] + // Aggregate: d+1 opening pairs and d+1 Fold poly commitments into verifier claim + auto verifier_claims = GeminiVerifier::reduce_verification(multilinear_evaluation_point, + multilinear_evaluations_unshifted, + multilinear_evaluations_shifted, + multilinear_commitments, + multilinear_commitments_to_be_shifted, + verifier_transcript); + + // Check equality of the opening pairs computed by prover and verifier + for (auto [prover_claim, verifier_claim] : zip_view(prover_output, verifier_claims)) { + this->verify_opening_claim(verifier_claim, prover_claim.polynomial); + ASSERT_EQ(prover_claim.opening_pair, verifier_claim.opening_pair); + } + } + + void execute_gemini_and_verify_claims_with_concatenation( std::vector& multilinear_evaluation_point, RefVector multilinear_evaluations_unshifted, RefVector multilinear_evaluations_shifted, RefSpan> multilinear_polynomials, RefSpan> multilinear_polynomials_to_be_shifted, - RefVector multilinear_commitments, - RefVector multilinear_commitments_to_be_shifted, + RefVector multilinear_commitments, + RefVector multilinear_commitments_to_be_shifted, RefSpan> concatenated_polynomials = {}, RefSpan concatenated_evaluations = {}, const std::vector>>& groups_to_be_concatenated = {}, - const std::vector>& concatenation_group_commitments = {}) + const std::vector>& concatenation_group_commitments = {}) { auto prover_transcript = NativeTranscript::prover_init_empty(); @@ -60,12 +104,9 @@ template class GeminiTest : public CommitmentTest { concatenated_evaluations); // Check equality of the opening pairs computed by prover and verifier - size_t i = 0; for (auto [prover_claim, verifier_claim] : zip_view(prover_output, verifier_claims)) { - info(i); this->verify_opening_claim(verifier_claim, prover_claim.polynomial); ASSERT_EQ(prover_claim.opening_pair, verifier_claim.opening_pair); - i++; } } }; @@ -76,7 +117,7 @@ TYPED_TEST_SUITE(GeminiTest, ParamsTypes); TYPED_TEST(GeminiTest, Single) { using Fr = typename TypeParam::ScalarField; - using GroupElement = typename TypeParam::Element; + using Commitment = typename TypeParam::AffineElement; const size_t n = 16; const size_t log_n = 4; @@ -91,8 +132,8 @@ TYPED_TEST(GeminiTest, Single) std::vector multilinear_evaluations_shifted = {}; std::vector> multilinear_polynomials = { poly.share() }; std::vector> multilinear_polynomials_to_be_shifted = {}; - std::vector multilinear_commitments = { commitment }; - std::vector multilinear_commitments_to_be_shifted = {}; + std::vector multilinear_commitments = { commitment }; + std::vector multilinear_commitments_to_be_shifted = {}; this->execute_gemini_and_verify_claims(u, RefVector(multilinear_evaluations_unshifted), @@ -106,7 +147,7 @@ TYPED_TEST(GeminiTest, Single) TYPED_TEST(GeminiTest, SingleShift) { using Fr = typename TypeParam::ScalarField; - using GroupElement = typename TypeParam::Element; + using Commitment = typename TypeParam::AffineElement; const size_t n = 16; const size_t log_n = 4; @@ -124,8 +165,8 @@ TYPED_TEST(GeminiTest, SingleShift) std::vector multilinear_evaluations_shifted = { eval_shift }; std::vector> multilinear_polynomials = {}; std::vector> multilinear_polynomials_to_be_shifted = { poly.share() }; - std::vector multilinear_commitments = {}; - std::vector multilinear_commitments_to_be_shifted = { commitment }; + std::vector multilinear_commitments = {}; + std::vector multilinear_commitments_to_be_shifted = { commitment }; this->execute_gemini_and_verify_claims(u, RefVector(multilinear_evaluations_unshifted), @@ -139,7 +180,7 @@ TYPED_TEST(GeminiTest, SingleShift) TYPED_TEST(GeminiTest, Double) { using Fr = typename TypeParam::ScalarField; - using GroupElement = typename TypeParam::Element; + using Commitment = typename TypeParam::AffineElement; const size_t n = 16; const size_t log_n = 4; @@ -160,8 +201,8 @@ TYPED_TEST(GeminiTest, Double) std::vector multilinear_evaluations_shifted = {}; std::vector> multilinear_polynomials = { poly1.share(), poly2.share() }; std::vector> multilinear_polynomials_to_be_shifted = {}; - std::vector multilinear_commitments = { commitment1, commitment2 }; - std::vector multilinear_commitments_to_be_shifted = {}; + std::vector multilinear_commitments = { commitment1, commitment2 }; + std::vector multilinear_commitments_to_be_shifted = {}; this->execute_gemini_and_verify_claims(u, RefVector(multilinear_evaluations_unshifted), @@ -175,7 +216,7 @@ TYPED_TEST(GeminiTest, Double) TYPED_TEST(GeminiTest, DoubleWithShift) { using Fr = typename TypeParam::ScalarField; - using GroupElement = typename TypeParam::Element; + using Commitment = typename TypeParam::AffineElement; const size_t n = 16; const size_t log_n = 4; @@ -197,8 +238,8 @@ TYPED_TEST(GeminiTest, DoubleWithShift) std::vector multilinear_evaluations_shifted = { eval2_shift }; std::vector> multilinear_polynomials = { poly1.share(), poly2.share() }; std::vector> multilinear_polynomials_to_be_shifted = { poly2.share() }; - std::vector multilinear_commitments = { commitment1, commitment2 }; - std::vector multilinear_commitments_to_be_shifted = { commitment2 }; + std::vector multilinear_commitments = { commitment1, commitment2 }; + std::vector multilinear_commitments_to_be_shifted = { commitment2 }; this->execute_gemini_and_verify_claims(u, RefVector(multilinear_evaluations_unshifted), @@ -212,7 +253,7 @@ TYPED_TEST(GeminiTest, DoubleWithShift) TYPED_TEST(GeminiTest, DoubleWithShiftAndConcatenation) { using Fr = typename TypeParam::ScalarField; - using GroupElement = typename TypeParam::Element; + using Commitment = typename TypeParam::AffineElement; using Polynomial = bb::Polynomial; const size_t n = 16; @@ -235,69 +276,22 @@ TYPED_TEST(GeminiTest, DoubleWithShiftAndConcatenation) std::vector multilinear_evaluations_shifted = { eval2_shift }; std::vector multilinear_polynomials = { poly1.share(), poly2.share() }; std::vector multilinear_polynomials_to_be_shifted = { poly2.share() }; - std::vector multilinear_commitments = { commitment1, commitment2 }; - std::vector multilinear_commitments_to_be_shifted = { commitment2 }; - - size_t concatenation_index = 2; - size_t N = n; - size_t MINI_CIRCUIT_N = N / concatenation_index; - - // Polynomials "chunks" that are concatenated in the PCS - std::vector> concatenation_groups; - - // Concatenated polynomials - std::vector concatenated_polynomials; - - // Evaluations of concatenated polynomials - std::vector c_evaluations; - size_t NUM_CONCATENATED = 3; - // For each polynomial to be concatenated - for (size_t i = 0; i < NUM_CONCATENATED; ++i) { - std::vector concatenation_group; - Polynomial concatenated_polynomial(N); - // For each chunk - for (size_t j = 0; j < concatenation_index; j++) { - Polynomial chunk_polynomial(N); - // Fill the chunk polynomial with random values and appropriately fill the space in - // concatenated_polynomial - for (size_t k = 0; k < MINI_CIRCUIT_N; k++) { - // Chunks should be shiftable - auto tmp = Fr(0); - if (k > 0) { - tmp = Fr::random_element(this->engine); - } - chunk_polynomial.at(k) = tmp; - concatenated_polynomial.at(j * MINI_CIRCUIT_N + k) = tmp; - } - concatenation_group.emplace_back(chunk_polynomial); - } - // Store chunks - concatenation_groups.emplace_back(concatenation_group); - // Store concatenated polynomial - concatenated_polynomials.emplace_back(concatenated_polynomial); - // Get evaluation - c_evaluations.emplace_back(concatenated_polynomial.evaluate_mle(u)); - } - - // Compute commitments of all polynomial chunks - std::vector> concatenation_groups_commitments; - for (size_t i = 0; i < NUM_CONCATENATED; ++i) { - std::vector concatenation_group_commitment; - for (size_t j = 0; j < concatenation_index; j++) { - concatenation_group_commitment.emplace_back(this->commit(concatenation_groups[i][j])); - } - concatenation_groups_commitments.emplace_back(concatenation_group_commitment); - } - - this->execute_gemini_and_verify_claims(u, - RefVector(multilinear_evaluations_unshifted), - RefVector(multilinear_evaluations_shifted), - RefVector(multilinear_polynomials), - RefVector(multilinear_polynomials_to_be_shifted), - RefVector(multilinear_commitments), - RefVector(multilinear_commitments_to_be_shifted), - RefVector(concatenated_polynomials), - RefVector(c_evaluations), - to_vector_of_ref_vectors(concatenation_groups), - to_vector_of_ref_vectors(concatenation_groups_commitments)); + std::vector multilinear_commitments = { commitment1, commitment2 }; + std::vector multilinear_commitments_to_be_shifted = { commitment2 }; + + auto [concatenation_groups, concatenated_polynomials, c_evaluations, concatenation_groups_commitments] = + concatenation_inputs(u, 3, 2, this->ck()); + + this->execute_gemini_and_verify_claims_with_concatenation( + u, + RefVector(multilinear_evaluations_unshifted), + RefVector(multilinear_evaluations_shifted), + RefVector(multilinear_polynomials), + RefVector(multilinear_polynomials_to_be_shifted), + RefVector(multilinear_commitments), + RefVector(multilinear_commitments_to_be_shifted), + RefVector(concatenated_polynomials), + RefVector(c_evaluations), + to_vector_of_ref_vectors(concatenation_groups), + to_vector_of_ref_vectors(concatenation_groups_commitments)); } 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 37348d712b3..ceeb95f7df2 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -49,7 +49,7 @@ std::vector::Claim> GeminiProver_::prove( const std::shared_ptr>& commitment_key, const std::shared_ptr& transcript, RefSpan concatenated_polynomials, - [[maybe_unused]] const std::vector>& groups_to_be_concatenated) + const std::vector>& groups_to_be_concatenated) { size_t log_n = numeric::get_msb(static_cast(circuit_size)); @@ -89,11 +89,11 @@ std::vector::Claim> GeminiProver_::prove( rho_challenge *= rho; } - Polynomial& batched_unshifted_and_concatenated = batched_concatenated; - batched_unshifted_and_concatenated += batched_unshifted; - - auto fold_polynomials = compute_fold_polynomials( - log_n, multilinear_challenge, std::move(batched_unshifted_and_concatenated), std::move(batched_to_be_shifted)); + auto fold_polynomials = compute_fold_polynomials(log_n, + multilinear_challenge, + std::move(batched_unshifted), + std::move(batched_to_be_shifted), + std::move(batched_concatenated)); for (size_t l = 0; l < CONST_PROOF_SIZE_LOG_N - 1; l++) { if (l < log_n - 1) { @@ -105,8 +105,8 @@ std::vector::Claim> GeminiProver_::prove( } const Fr r_challenge = transcript->template get_challenge("Gemini:r"); - std::vector claims = compute_fold_polynomial_evaluations( - log_n, std::move(fold_polynomials), std::move(batched_unshifted), r_challenge, std::move(batched_group)); + std::vector claims = + compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), r_challenge, std::move(batched_group)); for (size_t l = 1; l <= CONST_PROOF_SIZE_LOG_N; l++) { if (l <= log_n) { @@ -122,23 +122,20 @@ std::vector::Claim> GeminiProver_::prove( /** * @brief Computes d-1 fold polynomials Fold_i, i = 1, ..., d-1 * - * @details If proving the opening for translator, batch_unshifted contains the sum of unshifted ond concatenated - * polynomials, scaled by the appropriate power of ρ, F(X) = ∑ⱼ ρʲ fⱼ(X) + ∑ₗ ρᵏ⁺ᵐ⁺ˡ concatenated_polynomials(X) - * * @param mle_opening_point multilinear opening point 'u' * @param batched_unshifted F(X) = ∑ⱼ ρʲ fⱼ(X) . * @param batched_to_be_shifted G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) + * @param batched_concatenated The sum of batched concatenated polynomial, * @return std::vector */ template std::vector::Polynomial> GeminiProver_::compute_fold_polynomials( - const size_t log_N, + const size_t num_variables, std::span mle_opening_point, Polynomial&& batched_unshifted, - Polynomial&& batched_to_be_shifted) + Polynomial&& batched_to_be_shifted, + Polynomial&& batched_concatenated) { - const size_t num_variables = log_N; - const size_t num_threads = get_num_cpus_pow2(); constexpr size_t efficient_operations_per_thread = 64; // A guess of the number of operation for which there // would be a point in sending them to a separate thread @@ -157,6 +154,10 @@ std::vector::Polynomial> GeminiProver_::com constexpr size_t offset_to_folded = 2; // Offset because of F an G // A₀(X) = F(X) + G↺(X) = F(X) + G(X)/X. Polynomial A_0 = batched_F; + + // If proving the opening for translator, add a non-zero contribution of the batched concatenation polynomials + A_0 += batched_concatenated; + A_0 += batched_G.shifted(); // Allocate everything before parallel computation @@ -223,18 +224,16 @@ std::vector::Polynomial> GeminiProver_::com */ template std::vector::Claim> GeminiProver_::compute_fold_polynomial_evaluations( - const size_t log_N, + const size_t num_variables, std::vector&& fold_polynomials, - Polynomial&& batched_unshifted, const Fr& r_challenge, - [[maybe_unused]] std::vector&& batched_groups_to_be_concatenated) + std::vector&& batched_groups_to_be_concatenated) { Fr r_inv = r_challenge.invert(); - const size_t num_variables = log_N; Polynomial& batched_F = fold_polynomials[0]; // F(X) = ∑ⱼ ρʲ fⱼ(X) - batched_F = batched_unshifted; // I made fold_polynomials[0] be just batch unshifted without concatenation + Polynomial& batched_G = fold_polynomials[1]; // G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) // Compute univariate opening queries rₗ = r^{2ˡ} for l = 0, 1, ..., m-1 @@ -257,17 +256,29 @@ std::vector::Claim> GeminiProver_::compute_ // A₀₋(X) = F(X) - G(X)/r, s.t. A₀₋(-r) = A₀(-r) A_0_neg -= tmp; + // Reconstruct the concatenated polynomials from its corresponding groups, partially evaluated at r and -r and add + // the result to A₀₊(X) an A₀₋(X). Assume P is the concatenated polynomial formed from group G = {p₀, p₁, p₂, p₃} + // then P(x) = p₀(x)+ xˢ p₁(x) + x²ˢ p₂(x) + x³ˢp₃(x) where s is the mini_circuit_size i.e. the number of non-zero + // values in polynomials part of the concatenation groups Then P_r(x) will be the partial evaluation of P(x) = p₀(x) + // + rˢ p₁(x) + r²ˢ p₂(x) + r³ˢp₃(x) is the partial evaluation of P(x) at a value r. We follow this technique + // rather than simply adding the contribution of the batched concatenated polynomial because, on the verifier side, + // this enables us reconstruct [P_r] from [p₀], [p₁], [p₂], [p₃] hence removing the need for the prover to commit to + // P if (!batched_groups_to_be_concatenated.empty()) { - size_t MINICIRCUIT_N = (1 << log_N) / batched_groups_to_be_concatenated.size(); - auto current_r_shift_pos = Fr(1); - auto current_r_shift_neg = Fr(1); - auto r_to_minicircuit_n_pos = r_challenge.pow(MINICIRCUIT_N); - auto r_to_minicircuit_n_neg = (-r_challenge).pow(MINICIRCUIT_N); + // The "real" size of polynomials in concatenation groups (i.e. the number of non-zero values) + const size_t mini_circuit_size = (1 << num_variables) / batched_groups_to_be_concatenated.size(); + Fr current_r_shift_pos = Fr(1); + Fr current_r_shift_neg = Fr(1); + + const Fr r_pow_minicircuit = r_challenge.pow(mini_circuit_size); + const Fr r_neg_pow_minicircuit = (-r_challenge).pow(mini_circuit_size); for (size_t i = 0; i < batched_groups_to_be_concatenated.size(); i++) { + // Reconstruct the batched concationation polynomial partially evaluated at r and -r from the polynomials + // in the batched concatenation group. A_0_pos.add_scaled(batched_groups_to_be_concatenated[i], current_r_shift_pos); A_0_neg.add_scaled(batched_groups_to_be_concatenated[i], current_r_shift_neg); - current_r_shift_pos *= r_to_minicircuit_n_pos; - current_r_shift_neg *= r_to_minicircuit_n_neg; + current_r_shift_pos *= r_pow_minicircuit; + current_r_shift_neg *= r_neg_pow_minicircuit; } } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index 10d0bca5440..9d17d7b3cc0 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -55,7 +55,7 @@ TEST_F(IPATest, OpenZeroPolynomial) constexpr size_t n = 4; Polynomial poly(n); // Commit to a zero polynomial - GroupElement commitment = this->commit(poly); + Commitment commitment = this->commit(poly); EXPECT_TRUE(commitment.is_point_at_infinity()); auto [x, eval] = this->random_eval(poly); @@ -247,8 +247,8 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) auto poly1 = Polynomial::random(n); auto poly2 = Polynomial::random(n, /*shiftable*/ 1); - GroupElement commitment1 = this->commit(poly1); - GroupElement commitment2 = this->commit(poly2); + Commitment commitment1 = this->commit(poly1); + Commitment commitment2 = this->commit(poly2); auto eval1 = poly1.evaluate_mle(mle_opening_point); auto eval2 = poly2.evaluate_mle(mle_opening_point); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 2c59317e916..3cdcda728a9 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -1,11 +1,11 @@ #include "kzg.hpp" +#include "../commitment_key.test.hpp" #include "../gemini/gemini.hpp" #include "../shplonk/shplemini.hpp" #include "../shplonk/shplonk.hpp" - -#include "../commitment_key.test.hpp" #include "barretenberg/commitment_schemes/claim.hpp" +#include "barretenberg/commitment_schemes/utils/test_utils.hpp" namespace bb { @@ -13,7 +13,6 @@ template class KZGTest : public CommitmentTest { public: using Fr = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; - using GroupElement = typename Curve::Element; using Polynomial = bb::Polynomial; }; @@ -58,7 +57,7 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) using GeminiVerifier = GeminiVerifier_; using KZG = KZG; using Fr = typename TypeParam::ScalarField; - using GroupElement = typename TypeParam::Element; + using Commitment = typename TypeParam::AffineElement; using Polynomial = typename bb::Polynomial; const size_t n = 16; @@ -70,8 +69,8 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) auto poly1 = Polynomial::random(n); auto poly2 = Polynomial::random(n, 1); // make 'shiftable' - GroupElement commitment1 = this->commit(poly1); - GroupElement commitment2 = this->commit(poly2); + Commitment commitment1 = this->commit(poly1); + Commitment commitment2 = this->commit(poly2); auto eval1 = poly1.evaluate_mle(mle_opening_point); auto eval2 = poly2.evaluate_mle(mle_opening_point); @@ -161,56 +160,88 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShift) // Collect multilinear evaluations for input to prover std::vector multilinear_evaluations = { eval1, eval2, eval3, eval1_shift, eval3_shift }; - size_t concatenation_index = 2; - size_t N = n; - size_t MINI_CIRCUIT_N = N / concatenation_index; - - // Polynomials "chunks" that are concatenated in the PCS - std::vector> concatenation_groups; - - // Concatenated polynomials - std::vector concatenated_polynomials; - - // Evaluations of concatenated polynomials - std::vector c_evaluations; - size_t NUM_CONCATENATED = 3; - // For each polynomial to be concatenated - for (size_t i = 0; i < NUM_CONCATENATED; ++i) { - std::vector concatenation_group; - Polynomial concatenated_polynomial(N); - // For each chunk - for (size_t j = 0; j < concatenation_index; j++) { - Polynomial chunk_polynomial(N); - // Fill the chunk polynomial with random values and appropriately fill the space in - // concatenated_polynomial - for (size_t k = 0; k < MINI_CIRCUIT_N; k++) { - // Chunks should be shiftable - auto tmp = Fr(0); - if (k > 0) { - tmp = Fr::random_element(this->engine); - } - chunk_polynomial.at(k) = tmp; - concatenated_polynomial.at(j * MINI_CIRCUIT_N + k) = tmp; - } - concatenation_group.emplace_back(chunk_polynomial); - } - // Store chunks - concatenation_groups.emplace_back(concatenation_group); - // Store concatenated polynomial - concatenated_polynomials.emplace_back(concatenated_polynomial); - // Get evaluation - c_evaluations.emplace_back(concatenated_polynomial.evaluate_mle(mle_opening_point)); - } - - // Compute commitments of all polynomial chunks - std::vector> concatenation_groups_commitments; - for (size_t i = 0; i < NUM_CONCATENATED; ++i) { - std::vector concatenation_group_commitment; - for (size_t j = 0; j < concatenation_index; j++) { - concatenation_group_commitment.emplace_back(this->commit(concatenation_groups[i][j])); - } - concatenation_groups_commitments.emplace_back(concatenation_group_commitment); - } + auto prover_transcript = NativeTranscript::prover_init_empty(); + + // Run the full prover PCS protocol: + + // 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_opening_claims = GeminiProver::prove(n, + RefArray{ poly1, poly2, poly3, poly4 }, + RefArray{ poly1, poly3 }, + mle_opening_point, + this->ck(), + prover_transcript); + + // Shplonk prover output: + // - opening pair: (z_challenge, 0) + // - witness: polynomial Q - Q_z + const auto opening_claim = ShplonkProver::prove(this->ck(), prover_opening_claims, prover_transcript); + + // KZG prover: + // - Adds commitment [W] to transcript + KZG::compute_opening_proof(this->ck(), opening_claim, prover_transcript); + + // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation) + + auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + + // Gemini verifier output: + // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 + const auto batch_opening_claim = + ShpleminiVerifier::compute_batch_opening_claim(n, + RefVector(unshifted_commitments), + RefVector(shifted_commitments), + RefArray{ eval1, eval2, eval3, eval4 }, + RefArray{ eval1_shift, eval3_shift }, + mle_opening_point, + this->vk()->get_g1_identity(), + verifier_transcript); + const auto pairing_points = KZG::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript); + // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2) + + EXPECT_EQ(this->vk()->pairing_check(pairing_points[0], pairing_points[1]), true); +} + +TYPED_TEST(KZGTest, ShpleminiKzgWithShiftAndConcatenation) +{ + using ShplonkProver = ShplonkProver_; + using GeminiProver = GeminiProver_; + using ShpleminiVerifier = ShpleminiVerifier_; + using KZG = KZG; + using Fr = typename TypeParam::ScalarField; + using Commitment = typename TypeParam::AffineElement; + using Polynomial = typename bb::Polynomial; + + const size_t n = 16; + const size_t log_n = 4; + // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random + // point. + auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' + auto poly1 = Polynomial::random(n, 1); + auto poly2 = Polynomial::random(n); + auto poly3 = Polynomial::random(n, 1); + auto poly4 = Polynomial::random(n); + + Commitment commitment1 = this->commit(poly1); + Commitment commitment2 = this->commit(poly2); + Commitment commitment3 = this->commit(poly3); + Commitment commitment4 = this->commit(poly4); + std::vector unshifted_commitments = { commitment1, commitment2, commitment3, commitment4 }; + std::vector shifted_commitments = { commitment1, commitment3 }; + auto eval1 = poly1.evaluate_mle(mle_opening_point); + auto eval2 = poly2.evaluate_mle(mle_opening_point); + auto eval3 = poly3.evaluate_mle(mle_opening_point); + auto eval4 = poly4.evaluate_mle(mle_opening_point); + auto eval1_shift = poly1.evaluate_mle(mle_opening_point, true); + auto eval3_shift = poly3.evaluate_mle(mle_opening_point, true); + + // Collect multilinear evaluations for input to prover + std::vector multilinear_evaluations = { eval1, eval2, eval3, eval1_shift, eval3_shift }; + + auto [concatenation_groups, concatenated_polynomials, c_evaluations, concatenation_groups_commitments] = + concatenation_inputs(mle_opening_point, 3, 2, this->ck()); auto prover_transcript = NativeTranscript::prover_init_empty(); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 30bb8084b90..be65bf2f01f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -194,16 +194,16 @@ template class ShpleminiVerifier_ { std::vector concatenation_scalars; if (!concatenation_group_commitments.empty()) { const size_t concatenation_group_size = concatenation_group_commitments[0].size(); - // The "real" size of each polynomial in concatenation groups (i.e. the nummber of non-zero values) + // The "real" size of polynomials in concatenation groups (i.e. the number of non-zero values) const size_t mini_circuit_size = circuit_size / concatenation_group_size; - auto r_shift_pos = Fr(1); - auto r_shift_neg = Fr(1); - auto r_pow_minicircuit = gemini_evaluation_challenge.pow(mini_circuit_size); - auto r_neg_pow_minicircuit = (-gemini_evaluation_challenge).pow(mini_circuit_size); + Fr r_shift_pos = Fr(1); + Fr r_shift_neg = Fr(1); + const Fr r_pow_minicircuit = gemini_evaluation_challenge.pow(mini_circuit_size); + const Fr r_neg_pow_minicircuit = (-gemini_evaluation_challenge).pow(mini_circuit_size); for (size_t i = 0; i < concatenation_group_size; ++i) { - // The commitments in the l-th concatenation group will be multiplied by -ρᵏ⁺ᵐ⁺ˡ and - // ( r_shift_pos/(z−r) + ν ⋅ r_shift_neg /(z+r) ) + // The l-th commitment in each concatenation group will be multiplied by -ρᵏ⁺ᵐ⁺ˡ and + // ( rˡˢ /(z−r) + ν ⋅ (-r)ˡˢ /(z+r) ) where s is the mini circuit size concatenation_scalars.emplace_back(r_shift_pos * inverse_vanishing_evals[0] + r_shift_neg * shplonk_batching_challenge * inverse_vanishing_evals[1]); 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 ddfd83c1a8a..703f4866c13 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -164,7 +164,6 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) // 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 batched_unshifted_copy = batched_unshifted; auto fold_polynomials = GeminiProver::compute_fold_polynomials( log_n, mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); @@ -173,8 +172,8 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) auto commitment = this->ck()->commit(fold_polynomials[l + 2]); prover_commitments.emplace_back(commitment); } - const auto opening_claims = GeminiProver::compute_fold_polynomial_evaluations( - log_n, std::move(fold_polynomials), std::move(batched_unshifted_copy), gemini_eval_challenge); + const auto opening_claims = + GeminiProver::compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), gemini_eval_challenge); std::vector prover_evaluations; for (size_t l = 0; l < log_n; ++l) { diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_utils.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_utils.hpp new file mode 100644 index 00000000000..cdb55a7d9d5 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_utils.hpp @@ -0,0 +1,77 @@ +#pragma once +#include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include + +namespace bb { +/** + * @brief Generate the tuple of concatenation inputs used to test the opening protocol special functionality that avoids + * high degrees in the Goblin Translator. + */ +template +static std::tuple>>, + std::vector>, + std::vector, + std::vector>> +concatenation_inputs(std::vector& u_challenge, + size_t NUM_CONCATENATED, + size_t concatenation_index, + std::shared_ptr> ck) +{ + using Fr = typename Curve::ScalarField; + using Commitment = typename Curve::AffineElement; + using Polynomial = bb::Polynomial; + + size_t N = 1 << u_challenge.size(); + size_t MINI_CIRCUIT_N = N / concatenation_index; + + // Polynomials "chunks" that are concatenated in the PCS + std::vector> concatenation_groups; + + // Concatenated polynomials + std::vector concatenated_polynomials; + + // Evaluations of concatenated polynomials + std::vector c_evaluations; + + // For each polynomial to be concatenated + for (size_t i = 0; i < NUM_CONCATENATED; ++i) { + std::vector concatenation_group; + Polynomial concatenated_polynomial(N); + // For each chunk + for (size_t j = 0; j < concatenation_index; j++) { + Polynomial chunk_polynomial(N); + // Fill the chunk polynomial with random values and appropriately fill the space in + // concatenated_polynomial + for (size_t k = 0; k < MINI_CIRCUIT_N; k++) { + // Chunks should be shiftable + auto tmp = Fr(0); + if (k > 0) { + tmp = Fr::random_element(); + } + chunk_polynomial.at(k) = tmp; + concatenated_polynomial.at(j * MINI_CIRCUIT_N + k) = tmp; + } + concatenation_group.emplace_back(chunk_polynomial); + } + // Store chunks + concatenation_groups.emplace_back(concatenation_group); + // Store concatenated polynomial + concatenated_polynomials.emplace_back(concatenated_polynomial); + // Get evaluation + c_evaluations.emplace_back(concatenated_polynomial.evaluate_mle(u_challenge)); + } + + // Compute commitments of all polynomial chunks + std::vector> concatenation_groups_commitments; + for (size_t i = 0; i < NUM_CONCATENATED; ++i) { + std::vector concatenation_group_commitment; + for (size_t j = 0; j < concatenation_index; j++) { + concatenation_group_commitment.emplace_back(ck->commit(concatenation_groups[i][j])); + } + concatenation_groups_commitments.emplace_back(concatenation_group_commitment); + } + + return { concatenation_groups, concatenated_polynomials, c_evaluations, concatenation_groups_commitments }; +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp index 1f060410679..d3b87d8563f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp @@ -142,8 +142,8 @@ template class ZeroMorphTest : public CommitmentTest u_challenge, size_t NUM_CONCATENATED) { From 8ea510aeb1b39824b3c487dd030294748c9cdcdc Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 22 Oct 2024 12:23:56 +0000 Subject: [PATCH 11/13] cleanup --- .../commitment_schemes/gemini/gemini.test.cpp | 2 +- .../commitment_schemes/gemini/gemini_impl.hpp | 24 +++++++++---------- .../commitment_schemes/kzg/kzg.test.cpp | 3 ++- .../commitment_schemes/shplonk/shplemini.hpp | 12 ++++------ .../shplonk/shplemini.test.cpp | 1 + .../commitment_schemes/utils/test_utils.hpp | 13 +++++----- .../zeromorph/zeromorph.test.cpp | 8 +++---- .../translator_recursive_verifier.cpp | 4 ++-- .../translator_vm/translator_verifier.cpp | 4 ++-- 9 files changed, 34 insertions(+), 37 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp index 567f75246ed..10874e00750 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp @@ -280,7 +280,7 @@ TYPED_TEST(GeminiTest, DoubleWithShiftAndConcatenation) std::vector multilinear_commitments_to_be_shifted = { commitment2 }; auto [concatenation_groups, concatenated_polynomials, c_evaluations, concatenation_groups_commitments] = - generate_concatenation_inputs(u, 3, 2, this->ck()); + generate_concatenation_inputs(u, /*mun_concatenated=*/3, /*concatenation_index=*/2, this->ck()); this->execute_gemini_and_verify_claims_with_concatenation( u, 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 ceeb95f7df2..8ffc2d32902 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -177,8 +177,8 @@ std::vector::Polynomial> GeminiProver_::com // size of the previous polynomial/2 const size_t n_l = 1 << (num_variables - l - 1); - // Use as many threads as it is useful so that 1 thread doesn't process 1 element, but make sure that there - // is at least 1 + // Use as many threads as it is useful so that 1 thread doesn't process 1 element, but make sure that there is + // at least 1 size_t num_used_threads = std::min(n_l / efficient_operations_per_thread, num_threads); num_used_threads = num_used_threads ? num_used_threads : 1; size_t chunk_size = n_l / num_used_threads; @@ -230,8 +230,6 @@ std::vector::Claim> GeminiProver_::compute_ std::vector&& batched_groups_to_be_concatenated) { - Fr r_inv = r_challenge.invert(); - Polynomial& batched_F = fold_polynomials[0]; // F(X) = ∑ⱼ ρʲ fⱼ(X) Polynomial& batched_G = fold_polynomials[1]; // G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) @@ -240,11 +238,12 @@ std::vector::Claim> GeminiProver_::compute_ std::vector r_squares = gemini::powers_of_evaluation_challenge(r_challenge, num_variables); // Compute G/r + Fr r_inv = r_challenge.invert(); batched_G *= r_inv; // 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]; // already modified to only be the unshifted stuff + Polynomial& A_0_pos = fold_polynomials[0]; // A₀₊(X) = F(X) + G(X)/r, s.t. A₀₊(r) = A₀(r) A_0_pos += batched_G; @@ -256,13 +255,14 @@ std::vector::Claim> GeminiProver_::compute_ // A₀₋(X) = F(X) - G(X)/r, s.t. A₀₋(-r) = A₀(-r) A_0_neg -= tmp; - // Reconstruct the concatenated polynomials from its corresponding groups, partially evaluated at r and -r and add - // the result to A₀₊(X) an A₀₋(X). Assume P is the concatenated polynomial formed from group G = {p₀, p₁, p₂, p₃} - // then P(x) = p₀(x)+ xˢ p₁(x) + x²ˢ p₂(x) + x³ˢp₃(x) where s is the mini_circuit_size i.e. the number of non-zero - // values in polynomials part of the concatenation groups Then P_r(x) will be the partial evaluation of P(x) = p₀(x) - // + rˢ p₁(x) + r²ˢ p₂(x) + r³ˢp₃(x) is the partial evaluation of P(x) at a value r. We follow this technique - // rather than simply adding the contribution of the batched concatenated polynomial because, on the verifier side, - // this enables us reconstruct [P_r] from [p₀], [p₁], [p₂], [p₃] hence removing the need for the prover to commit to + // Reconstruct the batched concatenated polynomial from the batched groups, partially evaluated at r and -r and add + // the result to A₀₊(X) and A₀₋(X). Explanation (for simplification assume a single concatenated polynomial): + // Let P be the concatenated polynomial formed from group G = {p₀, p₁, p₂, p₃} then + // P(x) = p₀(x)+ xˢ p₁(x) + x²ˢ p₂(x) + x³ˢp₃(x) where s is the mini_circuit_size i.e. the number of non-zero values + // in the polynomials part of G. Then P_r(x) = p₀(x) + rˢ p₁(x) + r²ˢ p₂(x) + r³ˢp₃(x) is the + // partial evaluation of P(x) at a value r. We follow this technique rather than simply adding the contribution of P + // to A₀₊(X) an A₀₋(X) because, on the verifier side, when constructing the commitments [A₀₊] an [A₀₋], this + // enables us to reconstruct [P_r] from [p₀], [p₁], [p₂], [p₃], hence removing the need for the prover to commit to // P if (!batched_groups_to_be_concatenated.empty()) { // The "real" size of polynomials in concatenation groups (i.e. the number of non-zero values) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 1f78810d8e1..155d0a0f214 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -241,7 +241,8 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShiftAndConcatenation) std::vector multilinear_evaluations = { eval1, eval2, eval3, eval1_shift, eval3_shift }; auto [concatenation_groups, concatenated_polynomials, c_evaluations, concatenation_groups_commitments] = - generate_concatenation_inputs(mle_opening_point, 3, 2, this->ck()); + generate_concatenation_inputs( + mle_opening_point, /*num_concatenated=*/3, /*concatenation_index=*/2, this->ck()); auto prover_transcript = NativeTranscript::prover_init_empty(); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index be65bf2f01f..2f247d8d1ee 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -116,19 +116,16 @@ template class ShpleminiVerifier_ { const std::vector& multivariate_challenge, const Commitment& g1_identity, const std::shared_ptr& transcript, - [[maybe_unused]] const std::vector>& concatenation_group_commitments = {}, - [[maybe_unused]] RefSpan concatenated_evaluations = {}) + const std::vector>& concatenation_group_commitments = {}, + RefSpan concatenated_evaluations = {}) { // Extract log_circuit_size size_t log_circuit_size{ 0 }; - size_t circuit_size{ 0 }; if constexpr (Curve::is_stdlib_type) { - circuit_size = static_cast(N.get_value()); log_circuit_size = numeric::get_msb(static_cast(N.get_value())); } else { - circuit_size = static_cast(N); log_circuit_size = numeric::get_msb(static_cast(N)); } @@ -144,8 +141,7 @@ template class ShpleminiVerifier_ { // - 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, I think this should be - // CONST_PROOF_SIZE + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size const std::vector gemini_eval_challenge_powers = gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, CONST_PROOF_SIZE_LOG_N); @@ -195,7 +191,7 @@ template class ShpleminiVerifier_ { if (!concatenation_group_commitments.empty()) { const size_t concatenation_group_size = concatenation_group_commitments[0].size(); // The "real" size of polynomials in concatenation groups (i.e. the number of non-zero values) - const size_t mini_circuit_size = circuit_size / concatenation_group_size; + const size_t mini_circuit_size = (1 << log_circuit_size) / concatenation_group_size; Fr r_shift_pos = Fr(1); Fr r_shift_neg = Fr(1); const Fr r_pow_minicircuit = gemini_evaluation_challenge.pow(mini_circuit_size); 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 703f4866c13..55739360179 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -172,6 +172,7 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) auto commitment = this->ck()->commit(fold_polynomials[l + 2]); prover_commitments.emplace_back(commitment); } + const auto opening_claims = GeminiProver::compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), gemini_eval_challenge); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_utils.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_utils.hpp index 8df7c749ecc..edc227037fd 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_utils.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/test_utils.hpp @@ -5,8 +5,7 @@ namespace bb { /** - * @brief Generate the tuple of concatenation inputs used to test the opening protocol special functionality that avoids - * high degrees in the Goblin Translator. + * @brief Generate the tuple of concatenation inputs used for testing the opening protocol when used for Translator VM. */ template static std::tuple>>, @@ -14,9 +13,9 @@ static std::tuple, std::vector>> generate_concatenation_inputs(std::vector& u_challenge, - size_t NUM_CONCATENATED, - size_t concatenation_index, - std::shared_ptr> ck) + const size_t num_concatenated, + const size_t concatenation_index, + const std::shared_ptr> ck) { using Fr = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; @@ -35,7 +34,7 @@ generate_concatenation_inputs(std::vector& u_challe std::vector c_evaluations; // For each polynomial to be concatenated - for (size_t i = 0; i < NUM_CONCATENATED; ++i) { + for (size_t i = 0; i < num_concatenated; ++i) { std::vector concatenation_group; Polynomial concatenated_polynomial(N); // For each chunk @@ -64,7 +63,7 @@ generate_concatenation_inputs(std::vector& u_challe // Compute commitments of all polynomial chunks std::vector> concatenation_groups_commitments; - for (size_t i = 0; i < NUM_CONCATENATED; ++i) { + for (size_t i = 0; i < num_concatenated; ++i) { std::vector concatenation_group_commitment; for (size_t j = 0; j < concatenation_index; j++) { concatenation_group_commitment.emplace_back(ck->commit(concatenation_groups[i][j])); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp index 1f78edd4705..1f060410679 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp @@ -142,10 +142,10 @@ template class ZeroMorphTest : public CommitmentTest u_challenge, size_t NUM_CONCATENATED) + ConcatenationInputs concatenation_inputs(std::vector u_challenge, size_t NUM_CONCATENATED) { size_t concatenation_index = 2; @@ -256,7 +256,7 @@ template class ZeroMorphTest : public CommitmentTest u_challenge, size_t NUM_CONCATENATED) { - ConcatenationInputs concatenation = generate_concatenation_inputs(u_challenge, NUM_CONCATENATED); + ConcatenationInputs concatenation = concatenation_inputs(u_challenge, NUM_CONCATENATED); auto prover_transcript = NativeTranscript::prover_init_empty(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index cd1bcd3ce1c..fb5a030844f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -117,7 +117,7 @@ std::array TranslatorRecursiveVerifier_ opening_claim = Shplemini::compute_batch_opening_claim(circuit_size, commitments.get_unshifted_without_concatenated(), commitments.get_to_be_shifted(), @@ -128,7 +128,7 @@ std::array TranslatorRecursiveVerifier_ opening_claim = Shplemini::compute_batch_opening_claim(circuit_size, commitments.get_unshifted_without_concatenated(), commitments.get_to_be_shifted(), @@ -124,7 +124,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) transcript, commitments.get_groups_to_be_concatenated(), claimed_evaluations.get_concatenated()); - auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); + const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); auto verified = key->pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); From 60dd83c6477f9b28fd29e15f59ee16afcd33d7db Mon Sep 17 00:00:00 2001 From: maramihali Date: Tue, 22 Oct 2024 12:39:43 +0000 Subject: [PATCH 12/13] a bit more cleanup --- .../src/barretenberg/commitment_schemes/gemini/gemini.hpp | 8 +++++--- .../commitment_schemes/gemini/gemini.test.cpp | 2 -- .../src/barretenberg/commitment_schemes/ipa/ipa.test.cpp | 8 +------- .../src/barretenberg/commitment_schemes/kzg/kzg.test.cpp | 4 +--- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 4282bee62cf..d6d2ecb7d39 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -126,8 +126,8 @@ template class GeminiProver_ { template class GeminiVerifier_ { using Fr = typename Curve::ScalarField; - using Commitment = typename Curve::AffineElement; using GroupElement = typename Curve::Element; + using Commitment = typename Curve::AffineElement; public: /** @@ -186,6 +186,8 @@ template class GeminiVerifier_ { // Get evaluations a_i, i = 0,...,m-1 from transcript const std::vector evaluations = get_gemini_evaluations(num_variables, transcript); + // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] + r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] + // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] - r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] GroupElement C0_r_pos = batched_commitment_unshifted; GroupElement C0_r_neg = batched_commitment_unshifted; @@ -228,6 +230,7 @@ template class GeminiVerifier_ { j++; } + // Add the contributions from concatenation groups to get the final [A₀₊] and [A₀₋] C0_r_pos += batched_concatenated_pos; C0_r_neg += batched_concatenated_neg; } @@ -322,8 +325,7 @@ template class GeminiVerifier_ { if constexpr (Curve::is_stdlib_type) { auto builder = evaluation_point[0].get_context(); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): - // insecure! + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure! stdlib::bool_t dummy_round = stdlib::witness_t(builder, l > num_variables); batched_eval_accumulator = Fr::conditional_assign(dummy_round, batched_eval_accumulator, batched_eval_round_acc); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp index 10874e00750..af478b9743f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp @@ -2,8 +2,6 @@ #include "../commitment_key.test.hpp" #include "barretenberg/commitment_schemes/utils/test_utils.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/transcript/transcript.hpp" using namespace bb; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index 9d17d7b3cc0..07d22793c0f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -1,13 +1,7 @@ -#include "../gemini/gemini.hpp" -#include "../shplonk/shplemini.hpp" -#include "../shplonk/shplonk.hpp" #include "./mock_transcript.hpp" #include "barretenberg/commitment_schemes/commitment_key.test.hpp" -#include "barretenberg/common/mem.hpp" -#include "barretenberg/ecc/curves/bn254/fq12.hpp" -#include "barretenberg/ecc/curves/types.hpp" -#include "barretenberg/polynomials/polynomial_arithmetic.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" using namespace bb; namespace { diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 155d0a0f214..4b951685549 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -1,10 +1,8 @@ #include "kzg.hpp" #include "../commitment_key.test.hpp" -#include "../gemini/gemini.hpp" -#include "../shplonk/shplemini.hpp" -#include "../shplonk/shplonk.hpp" #include "barretenberg/commitment_schemes/claim.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" #include "barretenberg/commitment_schemes/utils/test_utils.hpp" namespace bb { From 27f43e6fe5f9e6a62c0dc8f03a7611e0516aabe0 Mon Sep 17 00:00:00 2001 From: maramihali Date: Wed, 23 Oct 2024 10:41:40 +0000 Subject: [PATCH 13/13] add some more comments --- .../barretenberg/commitment_schemes/gemini/gemini.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index d6d2ecb7d39..aa9b6c8d787 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -186,8 +186,8 @@ template class GeminiVerifier_ { // Get evaluations a_i, i = 0,...,m-1 from transcript const std::vector evaluations = get_gemini_evaluations(num_variables, transcript); - // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] + r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] - // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] - r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] + // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] + r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ], the commitment to A₀₊ + // C₀_r_neg = ∑ⱼ ρʲ⋅[fⱼ] - r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ], the commitment to A₀₋ GroupElement C0_r_pos = batched_commitment_unshifted; GroupElement C0_r_neg = batched_commitment_unshifted; @@ -199,7 +199,8 @@ template class GeminiVerifier_ { } // If verifying the opening for the translator VM, we reconstruct the commitment of the batched concatenated - // polynomials, partially evaluated in r and -r, using the commitments in the concatenation groups + // polynomials, partially evaluated in r and -r, using the commitments in the concatenation groups and add their + // contribution as well to to C₀_r_pos and C₀_r_neg ASSERT(concatenated_evaluations.size() == concatenation_group_commitments.size()); if (!concatenation_group_commitments.empty()) { size_t concatenation_group_size = concatenation_group_commitments[0].size(); @@ -221,6 +222,10 @@ template class GeminiVerifier_ { GroupElement batched_concatenated_pos = GroupElement::zero(); GroupElement batched_concatenated_neg = GroupElement::zero(); for (auto& concatenation_group_commitment : concatenation_group_commitments) { + // Compute the contribution from each group j of commitments Gⱼ = {C₀, C₁, C₂, C₃, ...} + // where s = mini_circuit_size as + // C₀_r_pos += ∑ᵢ ρᵏ⁺ᵐ⁺ʲ⋅ rⁱˢ ⋅ Cᵢ + // C₀_r_neg += ∑ᵢ ρᵏ⁺ᵐ⁺ʲ⋅ (-r)ⁱˢ ⋅ Cᵢ for (size_t i = 0; i < concatenation_group_size; ++i) { batched_concatenated_pos += concatenation_group_commitment[i] * batching_scalar * r_shifts_pos[i]; batched_concatenated_neg += concatenation_group_commitment[i] * batching_scalar * r_shifts_neg[i];