diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index 6a8a2b4e1793..e14a2b2ef029 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -61,11 +61,6 @@ class ECCVMProver { CommitmentLabels commitment_labels; ZKData zk_sumcheck_data; - Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk - FF nu_challenge; // needed in both Shplonk rounds - - Polynomial quotient_W; - FF evaluation_challenge_x; FF translation_batching_challenge_v; // to be rederived by the translator verifier diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp index 07f2685ec403..336cc2e7f4f6 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp @@ -24,29 +24,36 @@ template class RelationChecker { /** * @brief Check that a single specified relation is satisfied for a set of polynomials - * - * @tparam Relation a linearly independent Relation to be checked - * @param polynomials prover polynomials - * @param params a RelationParameters instance */ - template - static void check(const auto& polynomials, - const auto& params, - bool is_linearly_independent, - std::string label = "Relation") + template + static void check(const auto& polynomials, const auto& params, std::string label = "Relation") { + // Define the appropriate accumulator type for the relation and initialize to zero typename Relation::SumcheckArrayOfValuesOverSubrelations result; for (auto& element : result) { element = 0; } - for (size_t i = 0; i < polynomials.w_l.virtual_size(); i++) { - if (is_linearly_independent) { - // Evaluate each constraint in the relation and check that each is satisfied - Relation::accumulate(result, polynomials.get_row(i), params, 1); - size_t subrelation_idx = 0; - for (auto& element : result) { + for (size_t i = 0; i < polynomials.get_polynomial_size(); i++) { + + Relation::accumulate(result, polynomials.get_row(i), params, 1); + size_t subrelation_idx = 0; + + // Iterate over all the subrelation results and report if a linearly independent one failed + for (auto& element : result) { + if constexpr (has_linearly_dependent) { + if (element != 0 && Relation::SUBRELATION_LINEARLY_INDEPENDENT[subrelation_idx]) { + info("RelationChecker: ", + label, + " relation (subrelation idx: ", + subrelation_idx, + ") failed at row idx: ", + i, + "."); + ASSERT(false); + } + } else { if (element != 0) { info("RelationChecker: ", label, @@ -57,21 +64,27 @@ template class RelationChecker { "."); ASSERT(false); } - subrelation_idx++; } + subrelation_idx++; } } - if (!is_linearly_independent) { - // Result accumulated across entire execution trace should be zero + if constexpr (has_linearly_dependent) { + size_t subrelation_idx = 0; for (auto& element : result) { - if (element != 0) { - info("RelationChecker: ", label, " relation (linearly indep.) failed."); + // Check that linearly dependent subrelation result is 0 over the entire execution trace + if (element != 0 && Relation::SUBRELATION_LINEARLY_INDEPENDENT[subrelation_idx]) { + info("RelationChecker: ", + label, + " linearly dependent subrelation idx: ", + subrelation_idx, + " failed."); ASSERT(false); } + subrelation_idx++; } } - } + }; }; // Specialization for Ultra @@ -84,16 +97,16 @@ template <> class RelationChecker : public RelationChecker>(polynomials, params, true, "UltraArithmetic"); - Base::check>(polynomials, params, true, "UltraPermutation"); - Base::check>(polynomials, params, true, "DeltaRangeConstraint"); - Base::check>(polynomials, params, true, "Elliptic"); - Base::check>(polynomials, params, true, "Auxiliary"); - Base::check>(polynomials, params, true, "Poseidon2External"); - Base::check>(polynomials, params, true, "Poseidon2Internal"); + Base::check>(polynomials, params, "UltraArithmetic"); + Base::check>(polynomials, params, "UltraPermutation"); + Base::check>(polynomials, params, "DeltaRangeConstraint"); + Base::check>(polynomials, params, "Elliptic"); + Base::check>(polynomials, params, "Auxiliary"); + Base::check>(polynomials, params, "Poseidon2External"); + Base::check>(polynomials, params, "Poseidon2Internal"); // Linearly dependent relations (must be satisfied as a sum across all rows) - Base::check>(polynomials, params, false, "LogDerivLookup"); + Base::check, true>(polynomials, params, "LogDerivLookup"); } }; @@ -108,13 +121,10 @@ template <> class RelationChecker : public RelationChecker { RelationChecker::check_all(polynomials, params); using FF = MegaFlavor::FF; - - // Linearly independent relations (must be satisfied at each row) - Base::check>(polynomials, params, true, "EccOpQueue"); - - // Linearly dependent relations (must be satisfied as a sum across all rows) - Base::check>(polynomials, params, false, "DatabusLookup"); + Base::check>(polynomials, params, "EccOpQueue"); + Base::check, true>(polynomials, params, "DatabusLookup"); } }; +} // namespace bb -} // namespace bb \ No newline at end of file +// namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_flavor.hpp index 2c4277050635..498c4bc4998d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_flavor.hpp @@ -54,9 +54,6 @@ template class ECCVMRecursiveFlavor_ { // Reuse the Relations from ECCVM using Relations = ECCVMFlavor::Relations_; - // think these two are not needed for recursive verifier land - // using GrandProductRelations = std::tuple>; - // using LookupRelation = ECCVMLookupRelation; static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = ECCVMFlavor::MAX_PARTIAL_RELATION_LENGTH; // BATCHED_RELATION_PARTIAL_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` 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 ad10259ad9c0..b4e00fbe3aef 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -1,5 +1,6 @@ #include "barretenberg/common/thread.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" +#include "barretenberg/plonk_honk_shared/relation_checker.hpp" #include "barretenberg/translator_vm/translator_flavor.hpp" #include "barretenberg/translator_vm/translator_proving_key.hpp" @@ -7,30 +8,6 @@ #include using namespace bb; -/** - * @brief Check that a given relation is satified for a set of polynomials - * - * @tparam relation_idx Index into a tuple of provided relations - * @tparam Flavor - */ -template void check_relation(auto circuit_size, auto& polynomials, auto params) -{ - for (size_t i = 0; i < circuit_size; i++) { - // Define the appropriate SumcheckArrayOfValuesOverSubrelations type for this relation and initialize to zero - using SumcheckArrayOfValuesOverSubrelations = typename Relation::SumcheckArrayOfValuesOverSubrelations; - SumcheckArrayOfValuesOverSubrelations result; - for (auto& element : result) { - element = 0; - } - - // Evaluate each constraint in the relation and check that each is satisfied - Relation::accumulate(result, polynomials.get_row(i), params, 1); - for (auto& element : result) { - ASSERT_EQ(element, 0); - } - } -} - class TranslatorRelationCorrectnessTests : public ::testing::Test { protected: static void SetUpTestSuite() { bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); } @@ -45,7 +22,6 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) using Flavor = TranslatorFlavor; using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; - using Polynomial = bb::Polynomial; auto& engine = numeric::get_debug_randomness(); const size_t mini_circuit_size = 2048; auto full_circuit_size = mini_circuit_size * Flavor::CONCATENATION_GROUP_SIZE; @@ -61,16 +37,6 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) auto proving_key = std::make_shared(full_circuit_size); TranslatorProvingKey key{ proving_key, mini_circuit_size }; 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); - } - - for (Polynomial& prover_poly : prover_polynomials.get_all()) { - if (prover_poly.is_empty()) { - prover_poly = Polynomial{ full_circuit_size }; - } - } // Fill in lagrange polynomials used in the permutation relation prover_polynomials.lagrange_first.at(0) = 1; @@ -82,70 +48,14 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) polynomial.at(i) = engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1); } }; - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_low_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_low_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_low_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_low_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_low_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_low_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_high_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_high_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_high_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_high_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_high_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_high_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_low_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_low_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_low_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_low_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_low_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_low_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_high_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_high_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_high_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_high_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_high_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.p_y_high_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_low_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_low_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_low_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_low_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_low_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_low_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_high_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_high_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_high_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_high_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_high_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.z_high_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_low_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_low_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_low_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_low_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_low_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_low_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_high_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_high_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_high_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_high_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_high_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.accumulator_high_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_low_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_low_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_low_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_low_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_low_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_low_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_high_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_high_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_high_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_high_limbs_range_constraint_3); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_high_limbs_range_constraint_4); - fill_polynomial_with_random_14_bit_values(prover_polynomials.quotient_high_limbs_range_constraint_tail); - fill_polynomial_with_random_14_bit_values(prover_polynomials.relation_wide_limbs_range_constraint_0); - fill_polynomial_with_random_14_bit_values(prover_polynomials.relation_wide_limbs_range_constraint_1); - fill_polynomial_with_random_14_bit_values(prover_polynomials.relation_wide_limbs_range_constraint_2); - fill_polynomial_with_random_14_bit_values(prover_polynomials.relation_wide_limbs_range_constraint_3); + + for (const auto& group : prover_polynomials.get_groups_to_be_concatenated()) { + for (auto& poly : group) { + fill_polynomial_with_random_14_bit_values(poly); + } + } + // Compute concatenated polynomials (4 polynomials produced from other constraint polynomials by concatenation) + key.compute_concatenated_polynomials(); // Compute ordered range constraint polynomials that go in the denominator of the grand product polynomial key.compute_translator_range_constraint_ordered_polynomials(); @@ -153,17 +63,13 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) // Compute the fixed numerator (part of verification key) key.compute_extra_range_constraint_numerator(); - // Compute concatenated polynomials (4 polynomials produced from other constraint polynomials by concatenation) - key.compute_concatenated_polynomials(); - // Compute the grand product polynomial compute_grand_product>(prover_polynomials, params); prover_polynomials.z_perm_shift = prover_polynomials.z_perm.shifted(); - using Relations = typename Flavor::Relations; - // Check that permutation relation is satisfied across each row of the prover polynomials - check_relation>(full_circuit_size, prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorPermutationRelation"); } TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) @@ -171,7 +77,6 @@ TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) using Flavor = TranslatorFlavor; using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; - using Polynomial = bb::Polynomial; auto& engine = numeric::get_debug_randomness(); const size_t mini_circuit_size = 2048; const auto circuit_size = Flavor::CONCATENATION_GROUP_SIZE * mini_circuit_size; @@ -181,16 +86,7 @@ TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) // No relation parameters are used in this relation RelationParameters params; - ProverPolynomials prover_polynomials; - // Allocate polynomials - for (Polynomial& prover_poly : prover_polynomials.get_to_be_shifted()) { - prover_poly = Polynomial::shiftable(circuit_size); - } - for (Polynomial& prover_poly : prover_polynomials.get_all()) { - if (prover_poly.is_empty()) { - prover_poly = Polynomial{ circuit_size }; - } - } + ProverPolynomials prover_polynomials(circuit_size); // Construct lagrange polynomials that are needed for Translator's DeltaRangeConstraint Relation prover_polynomials.lagrange_first.at(0) = 0; @@ -233,17 +129,9 @@ TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) polynomial_pointers[i + 1]->coeffs().begin()); }); - // Get shifted polynomials - prover_polynomials.ordered_range_constraints_0_shift = prover_polynomials.ordered_range_constraints_0.shifted(); - prover_polynomials.ordered_range_constraints_1_shift = prover_polynomials.ordered_range_constraints_1.shifted(); - prover_polynomials.ordered_range_constraints_2_shift = prover_polynomials.ordered_range_constraints_2.shifted(); - prover_polynomials.ordered_range_constraints_3_shift = prover_polynomials.ordered_range_constraints_3.shifted(); - prover_polynomials.ordered_range_constraints_4_shift = prover_polynomials.ordered_range_constraints_4.shifted(); - - using Relations = typename Flavor::Relations; - // Check that DeltaRangeConstraint relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorDeltaRangeConstraintRelation"); } /** @@ -256,8 +144,6 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) using Flavor = TranslatorFlavor; using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; - using ProverPolynomialIds = typename Flavor::ProverPolynomialIds; - using Polynomial = bb::Polynomial; auto& engine = numeric::get_debug_randomness(); @@ -271,46 +157,7 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) }; // Create storage for polynomials - ProverPolynomials prover_polynomials; - // We use polynomial ids to make shifting the polynomials easier - ProverPolynomialIds prover_polynomial_ids; - auto polynomial_id_get_all = prover_polynomial_ids.get_all(); - std::vector polynomial_container; - std::vector polynomial_ids; - for (size_t i = 0; i < polynomial_id_get_all.size(); i++) { - // Allocate polynomials - polynomial_container.emplace_back(circuit_size); - // Push sequential ids to polynomial ids - polynomial_ids.push_back(i); - polynomial_id_get_all[i] = polynomial_ids[i]; - } - // Get ids of shifted polynomials and put them in a set - auto shifted_ids = prover_polynomial_ids.get_shifted(); - auto to_be_shifted_ids = prover_polynomial_ids.get_to_be_shifted(); - std::unordered_set shifted_id_set; - for (auto& id : shifted_ids) { - shifted_id_set.emplace(id); - } - for (auto& id : to_be_shifted_ids) { - // allow shifting - polynomial_container[id] = Polynomial{ circuit_size - 1, circuit_size, 1 }; - } - // Assign to non-shifted prover polynomials - auto polynomial_get_all = prover_polynomials.get_all(); - for (size_t i = 0; i < polynomial_get_all.size(); i++) { - if (!shifted_id_set.contains(i)) { - polynomial_get_all[i] = polynomial_container[i].share(); - } - } - - // Assign to shifted prover polynomials using ids - for (size_t i = 0; i < shifted_ids.size(); i++) { - auto shifted_id = shifted_ids[i]; - auto to_be_shifted_id = to_be_shifted_ids[i]; - // Ensure we can shift this - polynomial_get_all[shifted_id] = polynomial_container[to_be_shifted_id].shifted(); - } - + ProverPolynomials prover_polynomials(circuit_size); // Fill in lagrange even polynomial for (size_t i = 1; i < mini_circuit_size - 1; i += 2) { prover_polynomials.lagrange_odd_in_minicircuit.at(i) = 1; @@ -325,22 +172,6 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) possible_opcode_values[static_cast(engine.get_random_uint8() % NUMBER_OF_POSSIBLE_OPCODES)]; } - std::unordered_set range_constraint_polynomial_ids; - for (auto& concatenation_group : prover_polynomial_ids.get_groups_to_be_concatenated()) { - for (auto& id : concatenation_group) { - range_constraint_polynomial_ids.insert(id); - } - } - - // Assign random values to the mini-circuit part of the range constraint polynomials - for (const auto& range_constraint_polynomial_id : range_constraint_polynomial_ids) { - parallel_for_range(mini_circuit_size - 2, [&](size_t start, size_t end) { - // We want to iterate from 1 to mini_circuit_size - 2 (inclusive) - for (size_t i = start + 1; i < end + 1; i++) { - polynomial_container[range_constraint_polynomial_id].at(i) = fr::random_element(); - } - }); - } // Initialize used lagrange polynomials prover_polynomials.lagrange_second.at(1) = 1; prover_polynomials.lagrange_second_to_last_in_minicircuit.at(mini_circuit_size - 2) = 1; @@ -363,16 +194,17 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) prover_polynomials.accumulators_binary_limbs_2.at(1) = params.accumulated_result[2]; prover_polynomials.accumulators_binary_limbs_3.at(1) = params.accumulated_result[3]; - using Relations = typename Flavor::Relations; - // Check that Opcode Constraint relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorOpcodeConstraintRelation"); // Check that Accumulator Transfer relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorAccumulatorTransferRelation"); // Check that Zero Constraint relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorZeroConstraintsRelation"); } /** * @brief Test the correctness of TranslatorFlavor's Decomposition Relation @@ -384,8 +216,6 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) using FF = typename Flavor::FF; using BF = typename Flavor::BF; using ProverPolynomials = typename Flavor::ProverPolynomials; - using ProverPolynomialIds = typename Flavor::ProverPolynomialIds; - using Polynomial = bb::Polynomial; auto& engine = numeric::get_debug_randomness(); constexpr size_t mini_circuit_size = 2048; @@ -395,46 +225,7 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) RelationParameters params; // Create storage for polynomials - ProverPolynomials prover_polynomials; - // We use polynomial ids to make shifting the polynomials easier - ProverPolynomialIds prover_polynomial_ids; - std::vector polynomial_container; - std::vector polynomial_ids; - auto polynomial_id_get_all = prover_polynomial_ids.get_all(); - auto polynomial_get_all = prover_polynomials.get_all(); - for (size_t i = 0; i < polynomial_id_get_all.size(); i++) { - Polynomial temporary_polynomial(circuit_size); - // Allocate polynomials - polynomial_container.push_back(temporary_polynomial); - // Push sequential ids to polynomial ids - polynomial_ids.push_back(i); - polynomial_id_get_all[i] = polynomial_ids[i]; - } - // Get ids of shifted polynomials and put them in a set - auto shifted_ids = prover_polynomial_ids.get_shifted(); - auto to_be_shifted_ids = prover_polynomial_ids.get_to_be_shifted(); - std::unordered_set shifted_id_set; - for (auto& id : shifted_ids) { - shifted_id_set.emplace(id); - } - for (auto& id : to_be_shifted_ids) { - // allow shifting - polynomial_container[id] = Polynomial{ circuit_size - 1, circuit_size, 1 }; - } - // Assign spans to non-shifted prover polynomials - for (size_t i = 0; i < polynomial_get_all.size(); i++) { - if (!shifted_id_set.contains(i)) { - polynomial_get_all[i] = polynomial_container[i].share(); - } - } - - // Assign shifted spans to shifted prover polynomials using ids - for (size_t i = 0; i < shifted_ids.size(); i++) { - auto shifted_id = shifted_ids[i]; - auto to_be_shifted_id = to_be_shifted_ids[i]; - // Ensure we can shift this - polynomial_get_all[shifted_id] = polynomial_container[to_be_shifted_id].shifted(); - } + ProverPolynomials prover_polynomials(circuit_size); // Fill in lagrange odd polynomial (the only non-witness one we are using) for (size_t i = 1; i < mini_circuit_size - 1; i += 2) { @@ -754,9 +545,9 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) prover_polynomials.quotient_high_limbs_range_constraint_tail.at(i + 1)); } - using Relations = Flavor::Relations; // Check that Decomposition relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorDecompositionRelation"); } /** @@ -769,9 +560,7 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) using FF = typename Flavor::FF; using BF = typename Flavor::BF; using ProverPolynomials = typename Flavor::ProverPolynomials; - using ProverPolynomialIds = typename Flavor::ProverPolynomialIds; using GroupElement = typename Flavor::GroupElement; - using Polynomial = bb::Polynomial; constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS; constexpr auto mini_circuit_size = 2048; @@ -824,46 +613,7 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) uint_input_x }; // Create storage for polynomials - ProverPolynomials prover_polynomials; - // We use polynomial ids to make shifting the polynomials easier - ProverPolynomialIds prover_polynomial_ids; - std::vector polynomial_container; - std::vector polynomial_ids; - auto polynomial_get_all = prover_polynomials.get_all(); - auto polynomial_id_get_all = prover_polynomial_ids.get_all(); - for (size_t i = 0; i < polynomial_get_all.size(); i++) { - Polynomial temporary_polynomial(circuit_size); - // Allocate polynomials - polynomial_container.push_back(temporary_polynomial); - // Push sequential ids to polynomial ids - polynomial_ids.push_back(i); - polynomial_id_get_all[i] = polynomial_ids[i]; - } - // Get ids of shifted polynomials and put them in a set - auto shifted_ids = prover_polynomial_ids.get_shifted(); - auto to_be_shifted_ids = prover_polynomial_ids.get_to_be_shifted(); - std::unordered_set shifted_id_set; - for (auto& id : shifted_ids) { - shifted_id_set.emplace(id); - } - for (auto& id : to_be_shifted_ids) { - // allow shifting - polynomial_container[id] = Polynomial{ circuit_size - 1, circuit_size, 1 }; - } - // Assign to non-shifted prover polynomials - for (size_t i = 0; i < polynomial_get_all.size(); i++) { - if (!shifted_id_set.contains(i)) { - polynomial_get_all[i] = polynomial_container[i].share(); - } - } - - // Assign to shifted prover polynomials using ids - for (size_t i = 0; i < shifted_ids.size(); i++) { - auto shifted_id = shifted_ids[i]; - auto to_be_shifted_id = to_be_shifted_ids[i]; - // Ensure we can shift this - polynomial_get_all[shifted_id] = polynomial_container[to_be_shifted_id].shifted(); - } + ProverPolynomials prover_polynomials = TranslatorFlavor::ProverPolynomials(circuit_size); // Copy values of wires used in the non-native field relation from the circuit builder for (size_t i = 1; i < circuit_builder.get_estimated_num_finalized_gates(); i++) { @@ -901,7 +651,7 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) prover_polynomials.lagrange_odd_in_minicircuit.at(i) = 1; } - using Relations = Flavor::Relations; // Check that Non-Native Field relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorNonNativeFieldRelation"); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index ef4c99e7d6b2..ed0503a82e81 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -15,24 +15,6 @@ using Transcript = TranslatorFlavor::Transcript; using OpQueue = ECCOpQueue; auto& engine = numeric::get_debug_randomness(); -std::vector add_variables(auto& circuit_constructor, std::vector variables) -{ - std::vector res; - for (fr& variable : variables) { - res.emplace_back(circuit_constructor.add_variable(variable)); - } - return res; -} - -void ensure_non_zero(auto& polynomial) -{ - bool has_non_zero_coefficient = false; - for (auto& coeff : polynomial) { - has_non_zero_coefficient |= !coeff.is_zero(); - } - ASSERT_TRUE(has_non_zero_coefficient); -} - class TranslatorTests : public ::testing::Test { protected: static void SetUpTestSuite() { bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index 2f2fff063ecc..f686b0c8545b 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -721,11 +721,6 @@ class TranslatorFlavor { lagrange_second_to_last_in_minicircuit); }; - /** - * @brief A container for easier mapping of polynomials - */ - using ProverPolynomialIds = AllEntities; - /** * @brief A container for storing the partially evaluated multivariates produced by sumcheck. */ diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index 68e48aff80ba..8629c0bfee1f 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -52,6 +52,44 @@ void TranslatorProvingKey::compute_concatenated_polynomials() parallel_for(concatenation_groups.size() * concatenation_groups[0].size(), ordering_function); } +/** + * @brief Sequential method for computing the concatenated polynomials by interleaving. + * + * @note This is not currently used in the implementation. + */ +void TranslatorProvingKey::compute_concatenated_polynomials_by_interleaving() +{ + auto groups = proving_key->polynomials.get_groups_to_be_concatenated(); + auto concatenated_polynomials = proving_key->polynomials.get_concatenated(); + + // Targets have to be full-sized proving_key->polynomials. We can compute the mini circuit size from them by + // dividing by concatenation index + const size_t MINI_CIRCUIT_SIZE = concatenated_polynomials[0].size() / Flavor::CONCATENATION_GROUP_SIZE; + ASSERT(MINI_CIRCUIT_SIZE * Flavor::CONCATENATION_GROUP_SIZE == concatenated_polynomials[0].size()); + + for (auto [concatenated, group] : zip_view(concatenated_polynomials, groups)) { + interleave(group, concatenated); + } +} + +/** + * @brief Construct a polynomial from a group of polynomial by interleaving their elements. + */ +void TranslatorProvingKey::interleave(const RefVector& group, Polynomial& result) +{ + + const size_t group_size = group.size(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1250): Initialise the group polynomials on their + // correct sizes so we could call group[0].size() here + const size_t group_polynomial_size = result.size() / group_size; + ASSERT(group_polynomial_size * group_size == result.size()); + for (size_t j = group[0].start_index(); j < group_polynomial_size; j++) { + for (size_t k = 0; k < group_size; k++) { + result.at(j * group_size + k) = group[k][j]; + } + } +} + /** * @brief Compute denominator polynomials for Translator's range constraint permutation * diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp index 31fbf94dead8..7d3d33c49743 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -29,6 +29,7 @@ class TranslatorProvingKey { { ASSERT(mini_circuit_dyadic_size * Flavor::CONCATENATION_GROUP_SIZE == dyadic_circuit_size); + proving_key->polynomials = Flavor::ProverPolynomials(dyadic_circuit_size); } TranslatorProvingKey(const Circuit& circuit, std::shared_ptr commitment_key = nullptr) @@ -110,5 +111,8 @@ class TranslatorProvingKey { void compute_concatenated_polynomials(); void compute_translator_range_constraint_ordered_polynomials(); + + void compute_concatenated_polynomials_by_interleaving(); + static void interleave(const RefVector&, Polynomial&); }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp new file mode 100644 index 000000000000..1ce80716b66a --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp @@ -0,0 +1,94 @@ +#include "translator_proving_key.hpp" +#include "barretenberg/common/log.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" +#include "barretenberg/plonk_honk_shared/relation_checker.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/translator_vm/translator_flavor.hpp" + +#include +using namespace bb; + +namespace { +using FF = TranslatorFlavor::Curve::ScalarField; +auto& engine = numeric::get_debug_randomness(); + +class TranslatorProvingKeyTests : public ::testing::Test { + protected: + static void SetUpTestSuite() { bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); } +}; +} // namespace + +/** + * @brief Simple test to check the interleaving method produces the expected results. + * + */ +TEST_F(TranslatorProvingKeyTests, InterleaveBasic) +{ + std::vector values = { FF{ 1 }, FF{ 2 }, FF{ 3 } }; + std::vector> group = { Polynomial(std::span(values)), + Polynomial(std::span(values)), + Polynomial(std::span(values)) }; + Polynomial result(group.size() * group[0].size()); + TranslatorProvingKey::interleave(RefVector(group), result); + std::vector vec = { FF{ 1 }, FF{ 1 }, FF{ 1 }, FF{ 2 }, FF{ 2 }, FF{ 2 }, FF{ 3 }, FF{ 3 }, FF{ 3 } }; + Polynomial expected_result{ std::span(vec) }; + EXPECT_EQ(result, expected_result); +} + +/** + * @brief Ensures the concatenation by interleaving function still preserves the correctness of relations. + * + */ +TEST_F(TranslatorProvingKeyTests, InterleaveFull) +{ + const size_t mini_circuit_size = 2048; + auto full_circuit_size = mini_circuit_size * TranslatorFlavor::CONCATENATION_GROUP_SIZE; + + // We only need gamma, because permutationr elation only uses gamma + FF gamma = FF::random_element(); + + // Fill relation parameters + RelationParameters params; + params.gamma = gamma; + + // Create storage for polynomials + auto proving_key = std::make_shared(full_circuit_size); + TranslatorProvingKey key{ proving_key, mini_circuit_size }; + TranslatorFlavor::ProverPolynomials& prover_polynomials = proving_key->polynomials; + + // Fill in lagrange polynomials used in the permutation relation + prover_polynomials.lagrange_first.at(0) = 1; + prover_polynomials.lagrange_last.at(full_circuit_size - 1) = 1; + + // Put random values in all the non-concatenated constraint polynomials used to range constrain the values + auto fill_polynomial_with_random_14_bit_values = [&](auto& polynomial) { + for (size_t i = polynomial.start_index(); i < mini_circuit_size; i++) { + polynomial.at(i) = engine.get_random_uint16() & ((1 << TranslatorFlavor::MICRO_LIMB_BITS) - 1); + } + }; + + for (const auto& group : prover_polynomials.get_groups_to_be_concatenated()) { + for (auto& poly : group) { + fill_polynomial_with_random_14_bit_values(poly); + } + } + + key.compute_concatenated_polynomials_by_interleaving(); + // Compute ordered range constraint polynomials that go in the denominator of the grand product polynomial + key.compute_translator_range_constraint_ordered_polynomials(); + + // Compute the fixed numerator (part of verification key) + key.compute_extra_range_constraint_numerator(); + + // Compute the grand product polynomial + compute_grand_product>(prover_polynomials, params); + prover_polynomials.z_perm_shift = prover_polynomials.z_perm.shifted(); + + // Check that permutation relation is satisfied across each row of the prover polynomials + RelationChecker::check>( + prover_polynomials, params, "TranslatorPermutationRelation"); + // Check that delta range constraint relation is satisfied across each row of the prover polynomials + RelationChecker::check>( + prover_polynomials, params, "TranslatorOpcodeConstraintRelation"); +} diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp index cf58de7cf06d..1d2363085a3e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -1,4 +1,5 @@ #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" +#include "barretenberg/plonk_honk_shared/relation_checker.hpp" #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/ecc_op_queue_relation.hpp" @@ -25,67 +26,6 @@ void ensure_non_zero(auto& polynomial) ASSERT_TRUE(has_non_zero_coefficient); } -/** - * @brief Check that a given relation is satified for a set of polynomials - * - * @tparam relation_idx Index into a tuple of provided relations - */ -template void check_relation(auto circuit_size, auto& polynomials, auto params) -{ - for (size_t i = 0; i < circuit_size; i++) { - // Define the appropriate SumcheckArrayOfValuesOverSubrelations type for this relation and initialize to zero - using SumcheckArrayOfValuesOverSubrelations = typename Relation::SumcheckArrayOfValuesOverSubrelations; - SumcheckArrayOfValuesOverSubrelations result; - for (auto& element : result) { - element = 0; - } - - // Evaluate each constraint in the relation and check that each is satisfied - Relation::accumulate(result, polynomials.get_row(i), params, 1); - for (auto& element : result) { - ASSERT_EQ(element, 0); - } - } -} - -/** - * @brief Check that a given linearly dependent relation is satisfied for a set of polynomials - * @details We refer to a relation as linearly dependent if it defines a constraint on the sum across the full execution - * trace rather than at each individual row. For example, a subrelation of this type arises in the log derivative lookup - * argument. - * - * @tparam relation_idx Index into a tuple of provided relations - * @tparam Flavor - */ -template -void check_linearly_dependent_relation(auto circuit_size, auto& polynomials, auto params) -{ - using AllValues = typename Flavor::AllValues; - // Define the appropriate SumcheckArrayOfValuesOverSubrelations type for this relation and initialize to zero - using SumcheckArrayOfValuesOverSubrelations = typename Relation::SumcheckArrayOfValuesOverSubrelations; - SumcheckArrayOfValuesOverSubrelations result; - for (auto& element : result) { - element = 0; - } - - for (size_t i = 0; i < circuit_size; i++) { - - // Extract an array containing all the polynomial evaluations at a given row i - AllValues evaluations_at_index_i; - for (auto [eval, poly] : zip_view(evaluations_at_index_i.get_all(), polynomials.get_all())) { - eval = poly[i]; - } - - // Evaluate each constraint in the relation and check that each is satisfied - Relation::accumulate(result, evaluations_at_index_i, params, 1); - } - - // Result accumulated across entire execution trace should be zero - for (auto& element : result) { - ASSERT_EQ(element, 0); - } -} - template void create_some_add_gates(auto& circuit_builder) { using FF = typename Flavor::FF; @@ -247,7 +187,6 @@ class UltraRelationCorrectnessTests : public ::testing::Test { TEST_F(UltraRelationCorrectnessTests, Ultra) { using Flavor = UltraFlavor; - using FF = typename Flavor::FF; // Create a builder and then add an assortment of gates designed to ensure that the constraint(s) represented // by each relation are non-trivially exercised. @@ -263,32 +202,23 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) // Create a prover (it will compute proving key and witness) auto decider_pk = std::make_shared>(builder); auto& proving_key = decider_pk->proving_key; - auto circuit_size = proving_key.circuit_size; WitnessComputation::complete_proving_key_for_test(decider_pk); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution - ensure_non_zero(proving_key.polynomials.q_arith); - ensure_non_zero(proving_key.polynomials.q_delta_range); - ensure_non_zero(proving_key.polynomials.q_lookup); - ensure_non_zero(proving_key.polynomials.q_elliptic); - ensure_non_zero(proving_key.polynomials.q_aux); + for (auto selector : proving_key.polynomials.get_gate_selectors()) { + ensure_non_zero(selector); + } auto& prover_polynomials = decider_pk->proving_key.polynomials; auto params = decider_pk->relation_parameters; - // Check that each relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_linearly_dependent_relation>(circuit_size, prover_polynomials, params); + + RelationChecker::check_all(prover_polynomials, params); } TEST_F(UltraRelationCorrectnessTests, Mega) { using Flavor = MegaFlavor; - using FF = typename Flavor::FF; // Create a composer and then add an assortment of gates designed to ensure that the constraint(s) represented // by each relation are non-trivially exercised. @@ -305,42 +235,20 @@ TEST_F(UltraRelationCorrectnessTests, Mega) // Create a prover (it will compute proving key and witness) auto decider_pk = std::make_shared>(builder); auto& proving_key = decider_pk->proving_key; - auto circuit_size = proving_key.circuit_size; WitnessComputation::complete_proving_key_for_test(decider_pk); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution - ensure_non_zero(proving_key.polynomials.q_arith); - ensure_non_zero(proving_key.polynomials.q_delta_range); - ensure_non_zero(proving_key.polynomials.q_lookup); - ensure_non_zero(proving_key.polynomials.q_elliptic); - ensure_non_zero(proving_key.polynomials.q_aux); - ensure_non_zero(proving_key.polynomials.q_busread); - ensure_non_zero(proving_key.polynomials.q_poseidon2_external); - ensure_non_zero(proving_key.polynomials.q_poseidon2_internal); - - ensure_non_zero(proving_key.polynomials.calldata); - ensure_non_zero(proving_key.polynomials.calldata_read_counts); - ensure_non_zero(proving_key.polynomials.calldata_inverses); - ensure_non_zero(proving_key.polynomials.secondary_calldata); - ensure_non_zero(proving_key.polynomials.secondary_calldata_read_counts); - ensure_non_zero(proving_key.polynomials.secondary_calldata_inverses); - ensure_non_zero(proving_key.polynomials.return_data); - ensure_non_zero(proving_key.polynomials.return_data_read_counts); - ensure_non_zero(proving_key.polynomials.return_data_inverses); + for (auto selector : proving_key.polynomials.get_gate_selectors()) { + ensure_non_zero(selector); + } + // Check the databus entities are non-zero + for (auto selector : proving_key.polynomials.get_databus_entities()) { + ensure_non_zero(selector); + } auto& prover_polynomials = decider_pk->proving_key.polynomials; auto params = decider_pk->relation_parameters; - // Check that each relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_linearly_dependent_relation>(circuit_size, prover_polynomials, params); - check_linearly_dependent_relation>(circuit_size, prover_polynomials, params); + RelationChecker::check_all(prover_polynomials, params); } \ No newline at end of file