From 2671e22867c04d7b590fc5c2fcc189df381b759b Mon Sep 17 00:00:00 2001 From: maramihali Date: Wed, 5 Feb 2025 17:21:13 +0000 Subject: [PATCH 01/10] translator simple interleaving and relation correctness refactoring --- .../src/barretenberg/eccvm/eccvm_prover.hpp | 5 - .../eccvm_verifier/eccvm_recursive_flavor.hpp | 3 - .../relation_correctness.test.cpp | 267 ++---------------- .../translator_vm/translator_flavor.hpp | 5 - .../translator_vm/translator_proving_key.cpp | 54 +++- .../translator_vm/translator_proving_key.hpp | 4 + .../translator_proving_key.test.cpp | 42 +++ 7 files changed, 107 insertions(+), 273 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index 4217b3818622..92f774242327 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -58,11 +58,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/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..4815eeaefdd7 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -45,7 +45,7 @@ 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 +61,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,71 +72,12 @@ 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 ordered range constraint polynomials that go in the denominator of the grand product polynomial key.compute_translator_range_constraint_ordered_polynomials(); @@ -160,10 +91,8 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) 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); + check_relation>(full_circuit_size, prover_polynomials, params); } TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) @@ -171,7 +100,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 +109,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 = Flavor::ProverPolynomials(circuit_size); // Construct lagrange polynomials that are needed for Translator's DeltaRangeConstraint Relation prover_polynomials.lagrange_first.at(0) = 0; @@ -233,17 +152,8 @@ 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); + check_relation>(circuit_size, prover_polynomials, params); } /** @@ -256,8 +166,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 +179,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 = TranslatorFlavor::ProverPolynomials(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 +194,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 +216,14 @@ 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); + check_relation>(circuit_size, prover_polynomials, params); // Check that Accumulator Transfer 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 that Zero Constraint relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); } /** * @brief Test the correctness of TranslatorFlavor's Decomposition Relation @@ -384,8 +235,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 +244,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 = TranslatorFlavor::ProverPolynomials(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 +564,8 @@ 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); + check_relation>(circuit_size, prover_polynomials, params); } /** @@ -769,9 +578,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 +631,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 +669,6 @@ 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); + check_relation>(circuit_size, prover_polynomials, params); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index 2dd0f7a249f4..3ccf1f558f48 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -722,11 +722,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..4e4213b09dc2 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -45,30 +45,64 @@ void TranslatorProvingKey::compute_concatenated_polynomials() // Copy into appropriate position in the concatenated polynomial // We offset by start_index() as the first 0 is not physically represented for shiftable values - for (size_t k = current_target.start_index(); k < MINI_CIRCUIT_SIZE; k++) { + for (size_t k = 0; k < MINI_CIRCUIT_SIZE; k++) { current_target.at(j * MINI_CIRCUIT_SIZE + k) = my_group[j][k]; } }; 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 concatenated polynomial from a group of polynomials by interleaving. + */ +void TranslatorProvingKey::interleave(const RefVector& group, Polynomial& result) +{ + const size_t group_size = group.size(); + const size_t polynomial_size = group[0].size(); + for (size_t j = 0; j < polynomial_size; j++) { + for (size_t k = 0; k < group_size; k++) { + result.at(k + j * group_size) = group[k][j]; + } + } +} + /** * @brief Compute denominator polynomials for Translator's range constraint permutation * * @details We need to prove that all the range constraint wires indeed have values within the given range (unless - * changed ∈ [0 , 2¹⁴ - 1]. To do this, we use several virtual concatenated wires, each of which represents a subset - * or original wires (concatenated_range_constraints_). We also generate several new polynomials of the same length - * as concatenated ones. These polynomials have values within range, but they are also constrained by the - * TranslatorFlavor's DeltaRangeConstraint relation, which ensures that sequential values differ by not more than - * 3, the last value is the maximum and the first value is zero (zero at the start allows us not to dance around - * shifts). + * changed ∈ [0 , 2¹⁴ - 1]. To do this, we use several virtual concatenated wires, each of which represents a + * subset or original wires (concatenated_range_constraints_). We also generate several new polynomials of the + * same length as concatenated ones. These polynomials have values within range, but they are also constrained by + * the TranslatorFlavor's DeltaRangeConstraint relation, which ensures that sequential values differ by not more + * than 3, the last value is the maximum and the first value is zero (zero at the start allows us not to dance + * around shifts). * * Ideally, we could simply rearrange the values in concatenated_.._0 ,..., concatenated_.._3 and get denominator * polynomials (ordered_constraints), but we could get the worst case scenario: each value in the polynomials is * maximum value. What can we do in that case? We still have to add (max_range/3)+1 values to each of the ordered - * wires for the sort constraint to hold. So we also need a and extra denominator to store k ⋅ ( max_range / 3 + 1 ) - * values that couldn't go in + ( max_range / 3 + 1 ) connecting values. To counteract the extra ( k + 1 ) ⋅ - * ⋅ (max_range / 3 + 1 ) values needed for denominator sort constraints we need a polynomial in the numerator. So we + * wires for the sort constraint to hold. So we also need a and extra denominator to store k ⋅ ( max_range / 3 + 1 + * ) values that couldn't go in + ( max_range / 3 + 1 ) connecting values. To counteract the extra ( k + 1 ) ⋅ ⋅ + * (max_range / 3 + 1 ) values needed for denominator sort constraints we need a polynomial in the numerator. So we * can construct a proof when ( k + 1 ) ⋅ ( max_range/ 3 + 1 ) < concatenated size * * @tparam Flavor 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 f0ba84f368e2..d1d836acad4a 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) @@ -104,5 +105,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..8ee5787977da --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp @@ -0,0 +1,42 @@ +#include "barretenberg/common/log.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/sumcheck/sumcheck_round.hpp" +#include "barretenberg/translator_vm/translator_circuit_builder.hpp" +#include "barretenberg/translator_vm/translator_prover.hpp" +#include "barretenberg/translator_vm/translator_verifier.hpp" + +#include +using namespace bb; + +namespace { +using CircuitBuilder = TranslatorFlavor::CircuitBuilder; +using Transcript = TranslatorFlavor::Transcript; +using OpQueue = ECCOpQueue; +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 Test the new concatenation 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); +} + +TEST_F(TranslatorProvingKeyTests, InterleaveFull) {} From f203055dd6564d3bc37fb883f3be7103ba738849 Mon Sep 17 00:00:00 2001 From: maramihali Date: Fri, 7 Feb 2025 15:41:25 +0000 Subject: [PATCH 02/10] stuff --- .../relation_correctness.test.cpp | 6 +- .../translator_vm/translator.test.cpp | 18 ----- .../translator_vm/translator_flavor.hpp | 18 ++++- .../translator_vm/translator_proving_key.cpp | 7 +- .../translator_vm/translator_proving_key.hpp | 2 +- .../translator_proving_key.test.cpp | 74 ++++++++++++++++++- .../ultra_honk/relation_correctness.test.cpp | 1 - 7 files changed, 94 insertions(+), 32 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 4815eeaefdd7..de4192825ba1 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -78,15 +78,15 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) 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(); // 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(); 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 d2666f6ffbc5..36b26a910420 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -619,10 +619,20 @@ class TranslatorFlavor { // Constructor to init all unshifted polys to the zero polynomial and set the shifted poly data ProverPolynomials(size_t circuit_size) { + size_t mini_circuit_size = circuit_size / CONCATENATION_GROUP_SIZE; + for (auto& group : get_groups_to_be_concatenated()) { + for (auto& poly : group) { + poly = Polynomial{ mini_circuit_size - 1, circuit_size, 1 }; + } + } for (auto& poly : get_to_be_shifted()) { - poly = Polynomial{ /*memory size*/ circuit_size - 1, - /*largest possible index*/ circuit_size, - /* offset */ 1 }; + if (poly.is_empty()) { + { + poly = Polynomial{ /*memory size*/ circuit_size - 1, + /*largest possible index*/ circuit_size, + /* offset */ 1 }; + } + } } for (auto& poly : get_unshifted()) { if (poly.is_empty()) { @@ -647,7 +657,7 @@ class TranslatorFlavor { PROFILE_THIS(); AllValues result; for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { - result_field = polynomial[row_idx]; + result_field = polynomial.get(row_idx); } return result; } 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 4e4213b09dc2..709acc98e3ec 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -45,7 +45,7 @@ void TranslatorProvingKey::compute_concatenated_polynomials() // Copy into appropriate position in the concatenated polynomial // We offset by start_index() as the first 0 is not physically represented for shiftable values - for (size_t k = 0; k < MINI_CIRCUIT_SIZE; k++) { + for (size_t k = current_target.start_index(); k < MINI_CIRCUIT_SIZE; k++) { current_target.at(j * MINI_CIRCUIT_SIZE + k) = my_group[j][k]; } }; @@ -77,9 +77,10 @@ void TranslatorProvingKey::compute_concatenated_polynomials_by_interleaving() */ void TranslatorProvingKey::interleave(const RefVector& group, Polynomial& result) { + const size_t group_size = group.size(); - const size_t polynomial_size = group[0].size(); - for (size_t j = 0; j < polynomial_size; j++) { + const size_t group_polynomial_size = result.size() / group_size; + for (size_t j = result.start_index(); j < group_polynomial_size; j++) { for (size_t k = 0; k < group_size; k++) { result.at(k + j * group_size) = group[k][j]; } 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 d1d836acad4a..791bf2ccae17 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -93,7 +93,7 @@ class TranslatorProvingKey { inline void compute_mini_circuit_dyadic_size(const Circuit& circuit) { - const size_t total_num_gates = std::max(circuit.num_gates, Flavor::MINIMUM_MINI_CIRCUIT_SIZE); + const size_t total_num_gates = std::max(circuit.num_gates + 1, Flavor::MINIMUM_MINI_CIRCUIT_SIZE); // Next power of 2 mini_circuit_dyadic_size = circuit.get_circuit_subgroup_size(total_num_gates); } 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 index 8ee5787977da..97b022ddfe70 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp @@ -1,5 +1,6 @@ #include "barretenberg/common/log.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/sumcheck/sumcheck_round.hpp" #include "barretenberg/translator_vm/translator_circuit_builder.hpp" @@ -22,8 +23,26 @@ class TranslatorProvingKeyTests : public ::testing::Test { }; } // namespace +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 Test the new concatenation method produces the expected results. + * @brief Simple test to check the interleaving method produces the expected results. * */ TEST_F(TranslatorProvingKeyTests, InterleaveBasic) @@ -39,4 +58,55 @@ TEST_F(TranslatorProvingKeyTests, InterleaveBasic) EXPECT_EQ(result, expected_result); } -TEST_F(TranslatorProvingKeyTests, InterleaveFull) {} +/** + * @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 + check_relation>(full_circuit_size, prover_polynomials, params); +} 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..85f62fbab494 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -28,7 +28,6 @@ void ensure_non_zero(auto& polynomial) /** * @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) { From 15b01cfaf9c1cab9e50df821a4f604debc9025ad Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 10 Feb 2025 14:00:01 +0000 Subject: [PATCH 03/10] cleanup --- .../plonk_honk_shared/relation_checker.hpp | 80 +++++------- .../ultra_honk/relation_correctness.test.cpp | 121 ++---------------- 2 files changed, 47 insertions(+), 154 deletions(-) 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..333809064502 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp @@ -17,23 +17,16 @@ template class RelationChecker { /** * @brief Check that the provided polynomials satisfy all relations for a given Flavor */ - static void check_all([[maybe_unused]] const auto& polynomials, [[maybe_unused]] const auto& params) + static bool check_all([[maybe_unused]] const auto& polynomials, [[maybe_unused]] const auto& params) { // default; do nothing } /** * @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") + static bool 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; @@ -42,33 +35,32 @@ template class RelationChecker { } 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) { - if (element != 0) { - info("RelationChecker: ", - label, - " relation (subrelation idx: ", - subrelation_idx, - ") failed at row idx: ", - i, - "."); - ASSERT(false); - } - subrelation_idx++; - } - } - } - if (!is_linearly_independent) { - // Result accumulated across entire execution trace should be zero + // 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; + // Iterate over all the subrelation results and report if a linearly independent one failed for (auto& element : result) { - if (element != 0) { - info("RelationChecker: ", label, " relation (linearly indep.) failed."); + if (element != 0 && subrelation_is_linearly_independent()) { + info("RelationChecker: ", + label, + " relation (subrelation idx: ", + subrelation_idx, + ") failed at row idx: ", + i, + "."); ASSERT(false); } + subrelation_idx++; + } + } + + size_t subrelation_idx = 0; + for (auto& element : result) { + // Check for linearly dependent subrelation and ensure their result over the entire execution trace is 0 + if (element != 0 && !subrelation_is_linearly_independent()) { + info("RelationChecker: ", label, " linearly dependent subrelation idx: ", subrelation_idx, " failed."); + ASSERT(false); } } } @@ -84,16 +76,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>(polynomials, params, "LogDerivLookup"); } }; @@ -108,12 +100,8 @@ 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>(polynomials, params, "DatabusLookup"); } }; 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..b7c6ac7a6850 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,20 @@ 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(decider_pk->proving_key.polynomials, decider_pk->relation_parameters); } 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 +232,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 From 8a5495f24029511d7bc162cca57a5748ac0ca88d Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 10 Feb 2025 14:06:00 +0000 Subject: [PATCH 04/10] fix return values --- .../src/barretenberg/plonk_honk_shared/relation_checker.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 333809064502..7726671933e7 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp @@ -17,7 +17,7 @@ template class RelationChecker { /** * @brief Check that the provided polynomials satisfy all relations for a given Flavor */ - static bool check_all([[maybe_unused]] const auto& polynomials, [[maybe_unused]] const auto& params) + static void check_all([[maybe_unused]] const auto& polynomials, [[maybe_unused]] const auto& params) { // default; do nothing } @@ -26,7 +26,7 @@ template class RelationChecker { * @brief Check that a single specified relation is satisfied for a set of polynomials */ template - static bool check(const auto& polynomials, const auto& params, std::string label = "Relation") + 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; From a44d1ef9146f3d673943ce8cd186b908d8b735c3 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 10 Feb 2025 14:08:40 +0000 Subject: [PATCH 05/10] fix --- .../barretenberg/ultra_honk/relation_correctness.test.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 b7c6ac7a6850..1d2363085a3e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -210,7 +210,10 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) ensure_non_zero(selector); } - RelationChecker::check_all(decider_pk->proving_key.polynomials, decider_pk->relation_parameters); + auto& prover_polynomials = decider_pk->proving_key.polynomials; + auto params = decider_pk->relation_parameters; + + RelationChecker::check_all(prover_polynomials, params); } TEST_F(UltraRelationCorrectnessTests, Mega) From 22f56219aadaf269bd95cfb5bdf29cfd9adc6025 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 10 Feb 2025 18:18:49 +0000 Subject: [PATCH 06/10] now it work --- .../plonk_honk_shared/relation_checker.hpp | 62 +- .../ultra_honk/mega_honk.test.cpp | 891 +++++++++--------- 2 files changed, 493 insertions(+), 460 deletions(-) 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 7726671933e7..19ec270770ca 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp @@ -25,9 +25,10 @@ template class RelationChecker { /** * @brief Check that a single specified relation is satisfied for a set of polynomials */ - template + 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) { @@ -39,31 +40,53 @@ template class RelationChecker { // 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; + // Iterate over all the subrelation results and report if a linearly independent one failed for (auto& element : result) { - if (element != 0 && subrelation_is_linearly_independent()) { + 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, + " relation (subrelation idx: ", + subrelation_idx, + ") failed at row idx: ", + i, + "."); + ASSERT(false); + } + } + subrelation_idx++; + } + } + + if constexpr (has_linearly_dependent) { + size_t subrelation_idx = 0; + for (auto& element : result) { + // Check for linearly dependent subrelation and ensure their result over the entire execution trace + // is 0 + if (element != 0 && Relation::SUBRELATION_LINEARLY_INDEPENDENT[subrelation_idx]) { info("RelationChecker: ", label, - " relation (subrelation idx: ", + " linearly dependent subrelation idx: ", subrelation_idx, - ") failed at row idx: ", - i, - "."); + " failed."); ASSERT(false); } subrelation_idx++; } } - - size_t subrelation_idx = 0; - for (auto& element : result) { - // Check for linearly dependent subrelation and ensure their result over the entire execution trace is 0 - if (element != 0 && !subrelation_is_linearly_independent()) { - info("RelationChecker: ", label, " linearly dependent subrelation idx: ", subrelation_idx, " failed."); - ASSERT(false); - } - } - } + }; }; // Specialization for Ultra @@ -85,7 +108,7 @@ template <> class RelationChecker : public RelationChecker>(polynomials, params, "Poseidon2Internal"); // Linearly dependent relations (must be satisfied as a sum across all rows) - Base::check>(polynomials, params, "LogDerivLookup"); + Base::check, true>(polynomials, params, "LogDerivLookup"); } }; @@ -101,8 +124,9 @@ template <> class RelationChecker : public RelationChecker { using FF = MegaFlavor::FF; Base::check>(polynomials, params, "EccOpQueue"); - Base::check>(polynomials, params, "DatabusLookup"); + 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/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index eaa85b26ee38..451ecf65ad9f 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -1,441 +1,450 @@ -#include -#include -#include - -#include "barretenberg/circuit_checker/circuit_checker.hpp" -#include "barretenberg/common/log.hpp" -#include "barretenberg/goblin/mock_circuits.hpp" -#include "barretenberg/plonk_honk_shared/relation_checker.hpp" -#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include "barretenberg/ultra_honk/merge_prover.hpp" -#include "barretenberg/ultra_honk/merge_verifier.hpp" -#include "barretenberg/ultra_honk/ultra_prover.hpp" -#include "barretenberg/ultra_honk/ultra_verifier.hpp" - -using namespace bb; - -auto& engine = numeric::get_debug_randomness(); - -using FlavorTypes = ::testing::Types; - -template class MegaHonkTests : public ::testing::Test { - public: - static void SetUpTestSuite() { bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); } - - using Curve = curve::BN254; - using FF = Curve::ScalarField; - using Point = Curve::AffineElement; - using CommitmentKey = bb::CommitmentKey; - using MergeProver = MergeProver_; - using MergeVerifier = MergeVerifier_; - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - using VerificationKey = typename Flavor::VerificationKey; - using DeciderProvingKey = DeciderProvingKey_; - - /** - * @brief Construct and a verify a Honk proof - * - */ - bool construct_and_verify_honk_proof(auto& builder) - { - auto proving_key = std::make_shared(builder); - Prover prover(proving_key); - auto verification_key = std::make_shared(proving_key->proving_key); - Verifier verifier(verification_key); - auto proof = prover.construct_proof(); - bool verified = verifier.verify_proof(proof); - - return verified; - } - - /** - * @brief Construct and a verify a Honk proof using a specified structured trace - * - */ - bool construct_and_verify_honk_proof_with_structured_trace(auto& builder, TraceSettings& trace_settings) - { - // no ZK flavor for now - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - using VerificationKey = typename MegaFlavor::VerificationKey; - using DeciderProvingKey = DeciderProvingKey_; - auto proving_key = std::make_shared(builder, trace_settings); - - Prover prover(proving_key); - auto verification_key = std::make_shared(proving_key->proving_key); - Verifier verifier(verification_key); - auto proof = prover.construct_proof(); - bool verified = verifier.verify_proof(proof); - - return verified; - } - - /** - * @brief Construct and verify a Goblin ECC op queue merge proof - * - */ - bool construct_and_verify_merge_proof(auto& op_queue) - { - MergeProver merge_prover{ op_queue }; - MergeVerifier merge_verifier; - auto merge_proof = merge_prover.construct_proof(); - bool verified = merge_verifier.verify_proof(merge_proof); - - return verified; - } -}; - -TYPED_TEST_SUITE(MegaHonkTests, FlavorTypes); - -/** - * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic - * gates - * - */ -TYPED_TEST(MegaHonkTests, Basic) -{ - using Flavor = TypeParam; - typename Flavor::CircuitBuilder builder; - - GoblinMockCircuits::construct_simple_circuit(builder); - - // Construct and verify Honk proof - bool honk_verified = this->construct_and_verify_honk_proof(builder); - EXPECT_TRUE(honk_verified); -} - -/** - * @brief Test proof construction/verification for a structured execution trace - * - */ -TYPED_TEST(MegaHonkTests, BasicStructured) -{ - using Flavor = TypeParam; - - // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i for - // i=1,2,3. This mechanism does not work with structured polynomials yet. - if constexpr (std::is_same_v) { - GTEST_SKIP() << "Skipping 'BasicStructured' test for MegaZKFlavor."; - } - typename Flavor::CircuitBuilder builder; - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - - GoblinMockCircuits::construct_simple_circuit(builder); - - // Construct and verify Honk proof using a structured trace - TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; - auto proving_key = std::make_shared>(builder, trace_settings); - Prover prover(proving_key); - auto verification_key = std::make_shared(proving_key->proving_key); - Verifier verifier(verification_key); - auto proof = prover.construct_proof(); - - // Sanity check: ensure z_perm is not zero everywhere - EXPECT_TRUE(!proving_key->proving_key.polynomials.z_perm.is_zero()); - - RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); - - EXPECT_TRUE(verifier.verify_proof(proof)); -} - -/** - * @brief Test that increasing the virtual size of a valid set of prover polynomials still results in a valid Megahonk - * proof - * - */ -TYPED_TEST(MegaHonkTests, DynamicVirtualSizeIncrease) -{ - using Flavor = TypeParam; - - // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i for - // i=1,2,3. This mechanism does not work with structured polynomials yet. - if constexpr (std::is_same_v) { - GTEST_SKIP() << "Skipping 'DynamicVirtualSizeIncrease' test for MegaZKFlavor."; - } - typename Flavor::CircuitBuilder builder; - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - - GoblinMockCircuits::construct_simple_circuit(builder); - - auto builder_copy = builder; - - // Construct and verify Honk proof using a structured trace - TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS }; - auto proving_key = std::make_shared>(builder, trace_settings); - auto proving_key_copy = std::make_shared>(builder_copy, trace_settings); - auto circuit_size = proving_key->proving_key.circuit_size; - - auto doubled_circuit_size = 2 * circuit_size; - proving_key_copy->proving_key.polynomials.increase_polynomials_virtual_size(doubled_circuit_size); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1158) - // proving_key_copy->proving_key.circuit_size = doubled_circuit_size; - - Prover prover(proving_key); - auto verification_key = std::make_shared(proving_key->proving_key); - - Prover prover_copy(proving_key_copy); - auto verification_key_copy = std::make_shared(proving_key_copy->proving_key); - - for (auto [entry, entry_copy] : zip_view(verification_key->get_all(), verification_key_copy->get_all())) { - EXPECT_EQ(entry, entry_copy); - } - - Verifier verifier(verification_key); - auto proof = prover.construct_proof(); - - RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); - EXPECT_TRUE(verifier.verify_proof(proof)); - - Verifier verifier_copy(verification_key_copy); - auto proof_copy = prover_copy.construct_proof(); - - RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); - EXPECT_TRUE(verifier_copy.verify_proof(proof_copy)); -} - -/** - * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic - * gates - * @note We simulate op queue interactions with a previous circuit so the actual circuit under test utilizes an op queue - * with non-empty 'previous' data. This avoid complications with zero-commitments etc. - * - */ -TYPED_TEST(MegaHonkTests, SingleCircuit) -{ - using Flavor = TypeParam; - auto op_queue = std::make_shared(); - - GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); - auto builder = typename Flavor::CircuitBuilder{ op_queue }; - - GoblinMockCircuits::construct_simple_circuit(builder); - - // Construct and verify Honk proof - bool honk_verified = this->construct_and_verify_honk_proof(builder); - EXPECT_TRUE(honk_verified); - - // Construct and verify Goblin ECC op queue Merge proof - auto merge_verified = this->construct_and_verify_merge_proof(op_queue); - EXPECT_TRUE(merge_verified); -} - -/** - * @brief Test Merge proof construction/verification for multiple circuits with ECC op gates, public inputs, and - * basic arithmetic gates - * - */ -TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly) -{ - using Flavor = TypeParam; - // Instantiate EccOpQueue. This will be shared across all circuits in the series - auto op_queue = std::make_shared(); - - GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); - - // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. - size_t NUM_CIRCUITS = 3; - for (size_t i = 0; i < NUM_CIRCUITS; ++i) { - auto builder = typename Flavor::CircuitBuilder{ op_queue }; - - GoblinMockCircuits::construct_simple_circuit(builder); - - // Construct and verify Goblin ECC op queue Merge proof - auto merge_verified = this->construct_and_verify_merge_proof(op_queue); - EXPECT_TRUE(merge_verified); - } -} - -/** - * @brief Test Honk proof construction/verification for multiple circuits with ECC op gates, public inputs, and - * basic arithmetic gates - * - */ -TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkOnly) -{ - using Flavor = TypeParam; - - // Instantiate EccOpQueue. This will be shared across all circuits in the series - auto op_queue = std::make_shared(); - - GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); - - // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. - size_t NUM_CIRCUITS = 3; - for (size_t i = 0; i < NUM_CIRCUITS; ++i) { - auto builder = typename Flavor::CircuitBuilder{ op_queue }; - - GoblinMockCircuits::construct_simple_circuit(builder); - - // Construct and verify Honk proof - bool honk_verified = this->construct_and_verify_honk_proof(builder); - EXPECT_TRUE(honk_verified); - } -} - -/** - * @brief Test Honk and Merge proof construction/verification for multiple circuits with ECC op gates, public inputs, - * and basic arithmetic gates - * - */ -TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkAndMerge) -{ - using Flavor = TypeParam; - - // Instantiate EccOpQueue. This will be shared across all circuits in the series - auto op_queue = std::make_shared(); - - GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); - - // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. - size_t NUM_CIRCUITS = 3; - for (size_t i = 0; i < NUM_CIRCUITS; ++i) { - auto builder = typename Flavor::CircuitBuilder{ op_queue }; - - GoblinMockCircuits::construct_simple_circuit(builder); - - // Construct and verify Honk proof - bool honk_verified = this->construct_and_verify_honk_proof(builder); - EXPECT_TRUE(honk_verified); - - // Construct and verify Goblin ECC op queue Merge proof - auto merge_verified = this->construct_and_verify_merge_proof(op_queue); - EXPECT_TRUE(merge_verified); - } - - // Compute the commitments to the aggregate op queue directly and check that they match those that were computed - // iteratively during transcript aggregation by the provers and stored in the op queue. - size_t aggregate_op_queue_size = op_queue->get_current_size(); - auto ultra_ops = op_queue->get_aggregate_transcript(); - auto commitment_key = std::make_shared(aggregate_op_queue_size); - size_t idx = 0; - for (const auto& result : op_queue->get_ultra_ops_commitments()) { - auto expected = commitment_key->commit({ /* start index */ 0, ultra_ops[idx++] }); - EXPECT_EQ(result, expected); - } -} - -/** - * @brief Test the structured trace overflow mechanism for various circuits which overflow in different ways - * - */ -TYPED_TEST(MegaHonkTests, StructuredTraceOverflow) -{ - using Flavor = TypeParam; - using Builder = Flavor::CircuitBuilder; - - TraceSettings trace_settings{ TINY_TEST_STRUCTURE }; - - { // Overflow in Arithmetic block only - Builder builder; - - GoblinMockCircuits::construct_simple_circuit(builder); - MockCircuits::add_arithmetic_gates(builder, 1 << 15); - - bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); - EXPECT_TRUE(verified); - - // We expect that the circuit has overflowed the provided structured trace - EXPECT_TRUE(builder.blocks.has_overflow); - } - - { // Overflow in Aux block (RAM gates; uses memory records which requires specific logic in overflow mechanism) - Builder builder; - - GoblinMockCircuits::construct_simple_circuit(builder); - MockCircuits::add_RAM_gates(builder); - - bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); - EXPECT_TRUE(verified); - - // We expect that the circuit has overflowed the provided structured trace - EXPECT_TRUE(builder.blocks.has_overflow); - } - - { // Overflow in Lookup block only - Builder builder; - - GoblinMockCircuits::construct_simple_circuit(builder); - MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); - - bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); - EXPECT_TRUE(verified); - - // We expect that the circuit has overflowed the provided structured trace - EXPECT_TRUE(builder.blocks.has_overflow); - } - - { // Overflow in Multiple blocks simultaneously - Builder builder; - - GoblinMockCircuits::construct_simple_circuit(builder); - MockCircuits::add_arithmetic_gates(builder, 1 << 15); - MockCircuits::add_RAM_gates(builder); - MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); - - bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); - EXPECT_TRUE(verified); - - // We expect that the circuit has overflowed the provided structured trace - EXPECT_TRUE(builder.blocks.has_overflow); - } -} - -/** - * @brief A sanity check that a simple std::swap on a ProverPolynomials object works as expected - * @details Constuct two valid proving keys. Tamper with the prover_polynomials of one key then swap the - * prover_polynomials of the two keys. The key who received the tampered polys leads to a failed verification while the - * other succeeds. - * - */ -TYPED_TEST(MegaHonkTests, PolySwap) -{ - using Flavor = TypeParam; - // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i, for - // i=1,2,3. This mechanism does not work with structured polynomials yet. - if constexpr (std::is_same_v) { - GTEST_SKIP() << "Skipping 'PolySwap' test for MegaZKFlavor."; - } - using Builder = Flavor::CircuitBuilder; - - TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS }; - - // Construct a simple circuit and make a copy of it - Builder builder; - GoblinMockCircuits::construct_simple_circuit(builder); - auto builder_copy = builder; - - // Construct two identical proving keys - auto proving_key_1 = std::make_shared(builder, trace_settings); - auto proving_key_2 = std::make_shared(builder_copy, trace_settings); - - // Tamper with the polys of pkey 1 in such a way that verification should fail - for (size_t i = 0; i < proving_key_1->proving_key.circuit_size; ++i) { - if (proving_key_1->proving_key.polynomials.q_arith[i] != 0) { - proving_key_1->proving_key.polynomials.w_l.at(i) += 1; - break; - } - } - - // Swap the polys of the two proving keys; result should be pkey 1 is valid and pkey 2 should fail - std::swap(proving_key_1->proving_key.polynomials, proving_key_2->proving_key.polynomials); - - { // Verification based on pkey 1 should succeed - typename TestFixture::Prover prover(proving_key_1); - auto verification_key = std::make_shared(proving_key_1->proving_key); - typename TestFixture::Verifier verifier(verification_key); - auto proof = prover.construct_proof(); - EXPECT_TRUE(verifier.verify_proof(proof)); - } - - { // Verification based on pkey 2 should fail - typename TestFixture::Prover prover(proving_key_2); - auto verification_key = std::make_shared(proving_key_2->proving_key); - typename TestFixture::Verifier verifier(verification_key); - auto proof = prover.construct_proof(); - EXPECT_FALSE(verifier.verify_proof(proof)); - } -} +// #include +// #include +// #include + +// #include "barretenberg/circuit_checker/circuit_checker.hpp" +// #include "barretenberg/common/log.hpp" +// #include "barretenberg/goblin/mock_circuits.hpp" +// #include "barretenberg/plonk_honk_shared/relation_checker.hpp" +// #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" +// #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +// #include "barretenberg/ultra_honk/merge_prover.hpp" +// #include "barretenberg/ultra_honk/merge_verifier.hpp" +// #include "barretenberg/ultra_honk/ultra_prover.hpp" +// #include "barretenberg/ultra_honk/ultra_verifier.hpp" + +// using namespace bb; + +// auto& engine = numeric::get_debug_randomness(); + +// using FlavorTypes = ::testing::Types; + +// template class MegaHonkTests : public ::testing::Test { +// public: +// static void SetUpTestSuite() { bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); } + +// using Curve = curve::BN254; +// using FF = Curve::ScalarField; +// using Point = Curve::AffineElement; +// using CommitmentKey = bb::CommitmentKey; +// using MergeProver = MergeProver_; +// using MergeVerifier = MergeVerifier_; +// using Prover = UltraProver_; +// using Verifier = UltraVerifier_; +// using VerificationKey = typename Flavor::VerificationKey; +// using DeciderProvingKey = DeciderProvingKey_; + +// /** +// * @brief Construct and a verify a Honk proof +// * +// */ +// bool construct_and_verify_honk_proof(auto& builder) +// { +// auto proving_key = std::make_shared(builder); +// Prover prover(proving_key); +// auto verification_key = std::make_shared(proving_key->proving_key); +// Verifier verifier(verification_key); +// auto proof = prover.construct_proof(); +// bool verified = verifier.verify_proof(proof); + +// return verified; +// } + +// /** +// * @brief Construct and a verify a Honk proof using a specified structured trace +// * +// */ +// bool construct_and_verify_honk_proof_with_structured_trace(auto& builder, TraceSettings& trace_settings) +// { +// // no ZK flavor for now +// using Prover = UltraProver_; +// using Verifier = UltraVerifier_; +// using VerificationKey = typename MegaFlavor::VerificationKey; +// using DeciderProvingKey = DeciderProvingKey_; +// auto proving_key = std::make_shared(builder, trace_settings); + +// Prover prover(proving_key); +// auto verification_key = std::make_shared(proving_key->proving_key); +// Verifier verifier(verification_key); +// auto proof = prover.construct_proof(); +// bool verified = verifier.verify_proof(proof); + +// return verified; +// } + +// /** +// * @brief Construct and verify a Goblin ECC op queue merge proof +// * +// */ +// bool construct_and_verify_merge_proof(auto& op_queue) +// { +// MergeProver merge_prover{ op_queue }; +// MergeVerifier merge_verifier; +// auto merge_proof = merge_prover.construct_proof(); +// bool verified = merge_verifier.verify_proof(merge_proof); + +// return verified; +// } +// }; + +// TYPED_TEST_SUITE(MegaHonkTests, FlavorTypes); + +// /** +// * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic +// * gates +// * +// */ +// TYPED_TEST(MegaHonkTests, Basic) +// { +// using Flavor = TypeParam; +// typename Flavor::CircuitBuilder builder; + +// GoblinMockCircuits::construct_simple_circuit(builder); + +// // Construct and verify Honk proof +// bool honk_verified = this->construct_and_verify_honk_proof(builder); +// EXPECT_TRUE(honk_verified); +// } + +// /** +// * @brief Test proof construction/verification for a structured execution trace +// * +// */ +// TYPED_TEST(MegaHonkTests, BasicStructured) +// { +// using Flavor = TypeParam; + +// // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i +// for +// // i=1,2,3. This mechanism does not work with structured polynomials yet. +// if constexpr (std::is_same_v) { +// GTEST_SKIP() << "Skipping 'BasicStructured' test for MegaZKFlavor."; +// } +// typename Flavor::CircuitBuilder builder; +// using Prover = UltraProver_; +// using Verifier = UltraVerifier_; + +// GoblinMockCircuits::construct_simple_circuit(builder); + +// // Construct and verify Honk proof using a structured trace +// TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; +// auto proving_key = std::make_shared>(builder, trace_settings); +// Prover prover(proving_key); +// auto verification_key = std::make_shared(proving_key->proving_key); +// Verifier verifier(verification_key); +// auto proof = prover.construct_proof(); + +// // Sanity check: ensure z_perm is not zero everywhere +// EXPECT_TRUE(!proving_key->proving_key.polynomials.z_perm.is_zero()); + +// auto& prover_polynomials = proving_key->proving_key.polynomials; +// auto params = proving_key->relation_parameters; + +// RelationChecker::check_all(prover_polynomials, params); + +// EXPECT_TRUE(verifier.verify_proof(proof)); +// } + +// /** +// * @brief Test that increasing the virtual size of a valid set of prover polynomials still results in a valid +// Megahonk +// * proof +// * +// */ +// TYPED_TEST(MegaHonkTests, DynamicVirtualSizeIncrease) +// { +// using Flavor = TypeParam; + +// // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i +// for +// // i=1,2,3. This mechanism does not work with structured polynomials yet. +// if constexpr (std::is_same_v) { +// GTEST_SKIP() << "Skipping 'DynamicVirtualSizeIncrease' test for MegaZKFlavor."; +// } +// typename Flavor::CircuitBuilder builder; +// using Prover = UltraProver_; +// using Verifier = UltraVerifier_; + +// GoblinMockCircuits::construct_simple_circuit(builder); + +// auto builder_copy = builder; + +// // Construct and verify Honk proof using a structured trace +// TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS }; +// auto proving_key = std::make_shared>(builder, trace_settings); +// auto proving_key_copy = std::make_shared>(builder_copy, trace_settings); +// auto circuit_size = proving_key->proving_key.circuit_size; + +// auto doubled_circuit_size = 2 * circuit_size; +// proving_key_copy->proving_key.polynomials.increase_polynomials_virtual_size(doubled_circuit_size); +// // TODO(https://github.com/AztecProtocol/barretenberg/issues/1158) +// // proving_key_copy->proving_key.circuit_size = doubled_circuit_size; + +// Prover prover(proving_key); +// auto verification_key = std::make_shared(proving_key->proving_key); + +// Prover prover_copy(proving_key_copy); +// auto verification_key_copy = std::make_shared(proving_key_copy->proving_key); + +// for (auto [entry, entry_copy] : zip_view(verification_key->get_all(), verification_key_copy->get_all())) { +// EXPECT_EQ(entry, entry_copy); +// } + +// Verifier verifier(verification_key); +// auto proof = prover.construct_proof(); + +// RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); +// EXPECT_TRUE(verifier.verify_proof(proof)); + +// Verifier verifier_copy(verification_key_copy); +// auto proof_copy = prover_copy.construct_proof(); + +// RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); +// EXPECT_TRUE(verifier_copy.verify_proof(proof_copy)); +// } + +// /** +// * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic +// * gates +// * @note We simulate op queue interactions with a previous circuit so the actual circuit under test utilizes an op +// queue +// * with non-empty 'previous' data. This avoid complications with zero-commitments etc. +// * +// */ +// TYPED_TEST(MegaHonkTests, SingleCircuit) +// { +// using Flavor = TypeParam; +// auto op_queue = std::make_shared(); + +// GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); +// auto builder = typename Flavor::CircuitBuilder{ op_queue }; + +// GoblinMockCircuits::construct_simple_circuit(builder); + +// // Construct and verify Honk proof +// bool honk_verified = this->construct_and_verify_honk_proof(builder); +// EXPECT_TRUE(honk_verified); + +// // Construct and verify Goblin ECC op queue Merge proof +// auto merge_verified = this->construct_and_verify_merge_proof(op_queue); +// EXPECT_TRUE(merge_verified); +// } + +// /** +// * @brief Test Merge proof construction/verification for multiple circuits with ECC op gates, public inputs, and +// * basic arithmetic gates +// * +// */ +// TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly) +// { +// using Flavor = TypeParam; +// // Instantiate EccOpQueue. This will be shared across all circuits in the series +// auto op_queue = std::make_shared(); + +// GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + +// // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. +// size_t NUM_CIRCUITS = 3; +// for (size_t i = 0; i < NUM_CIRCUITS; ++i) { +// auto builder = typename Flavor::CircuitBuilder{ op_queue }; + +// GoblinMockCircuits::construct_simple_circuit(builder); + +// // Construct and verify Goblin ECC op queue Merge proof +// auto merge_verified = this->construct_and_verify_merge_proof(op_queue); +// EXPECT_TRUE(merge_verified); +// } +// } + +// /** +// * @brief Test Honk proof construction/verification for multiple circuits with ECC op gates, public inputs, and +// * basic arithmetic gates +// * +// */ +// TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkOnly) +// { +// using Flavor = TypeParam; + +// // Instantiate EccOpQueue. This will be shared across all circuits in the series +// auto op_queue = std::make_shared(); + +// GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + +// // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. +// size_t NUM_CIRCUITS = 3; +// for (size_t i = 0; i < NUM_CIRCUITS; ++i) { +// auto builder = typename Flavor::CircuitBuilder{ op_queue }; + +// GoblinMockCircuits::construct_simple_circuit(builder); + +// // Construct and verify Honk proof +// bool honk_verified = this->construct_and_verify_honk_proof(builder); +// EXPECT_TRUE(honk_verified); +// } +// } + +// /** +// * @brief Test Honk and Merge proof construction/verification for multiple circuits with ECC op gates, public inputs, +// * and basic arithmetic gates +// * +// */ +// TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkAndMerge) +// { +// using Flavor = TypeParam; + +// // Instantiate EccOpQueue. This will be shared across all circuits in the series +// auto op_queue = std::make_shared(); + +// GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + +// // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. +// size_t NUM_CIRCUITS = 3; +// for (size_t i = 0; i < NUM_CIRCUITS; ++i) { +// auto builder = typename Flavor::CircuitBuilder{ op_queue }; + +// GoblinMockCircuits::construct_simple_circuit(builder); + +// // Construct and verify Honk proof +// bool honk_verified = this->construct_and_verify_honk_proof(builder); +// EXPECT_TRUE(honk_verified); + +// // Construct and verify Goblin ECC op queue Merge proof +// auto merge_verified = this->construct_and_verify_merge_proof(op_queue); +// EXPECT_TRUE(merge_verified); +// } + +// // Compute the commitments to the aggregate op queue directly and check that they match those that were computed +// // iteratively during transcript aggregation by the provers and stored in the op queue. +// size_t aggregate_op_queue_size = op_queue->get_current_size(); +// auto ultra_ops = op_queue->get_aggregate_transcript(); +// auto commitment_key = std::make_shared(aggregate_op_queue_size); +// size_t idx = 0; +// for (const auto& result : op_queue->get_ultra_ops_commitments()) { +// auto expected = commitment_key->commit({ /* start index */ 0, ultra_ops[idx++] }); +// EXPECT_EQ(result, expected); +// } +// } + +// /** +// * @brief Test the structured trace overflow mechanism for various circuits which overflow in different ways +// * +// */ +// TYPED_TEST(MegaHonkTests, StructuredTraceOverflow) +// { +// using Flavor = TypeParam; +// using Builder = Flavor::CircuitBuilder; + +// TraceSettings trace_settings{ TINY_TEST_STRUCTURE }; + +// { // Overflow in Arithmetic block only +// Builder builder; + +// GoblinMockCircuits::construct_simple_circuit(builder); +// MockCircuits::add_arithmetic_gates(builder, 1 << 15); + +// bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); +// EXPECT_TRUE(verified); + +// // We expect that the circuit has overflowed the provided structured trace +// EXPECT_TRUE(builder.blocks.has_overflow); +// } + +// { // Overflow in Aux block (RAM gates; uses memory records which requires specific logic in overflow mechanism) +// Builder builder; + +// GoblinMockCircuits::construct_simple_circuit(builder); +// MockCircuits::add_RAM_gates(builder); + +// bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); +// EXPECT_TRUE(verified); + +// // We expect that the circuit has overflowed the provided structured trace +// EXPECT_TRUE(builder.blocks.has_overflow); +// } + +// { // Overflow in Lookup block only +// Builder builder; + +// GoblinMockCircuits::construct_simple_circuit(builder); +// MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); + +// bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); +// EXPECT_TRUE(verified); + +// // We expect that the circuit has overflowed the provided structured trace +// EXPECT_TRUE(builder.blocks.has_overflow); +// } + +// { // Overflow in Multiple blocks simultaneously +// Builder builder; + +// GoblinMockCircuits::construct_simple_circuit(builder); +// MockCircuits::add_arithmetic_gates(builder, 1 << 15); +// MockCircuits::add_RAM_gates(builder); +// MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); + +// bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); +// EXPECT_TRUE(verified); + +// // We expect that the circuit has overflowed the provided structured trace +// EXPECT_TRUE(builder.blocks.has_overflow); +// } +// } + +// /** +// * @brief A sanity check that a simple std::swap on a ProverPolynomials object works as expected +// * @details Constuct two valid proving keys. Tamper with the prover_polynomials of one key then swap the +// * prover_polynomials of the two keys. The key who received the tampered polys leads to a failed verification while +// the +// * other succeeds. +// * +// */ +// TYPED_TEST(MegaHonkTests, PolySwap) +// { +// using Flavor = TypeParam; +// // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i, +// for +// // i=1,2,3. This mechanism does not work with structured polynomials yet. +// if constexpr (std::is_same_v) { +// GTEST_SKIP() << "Skipping 'PolySwap' test for MegaZKFlavor."; +// } +// using Builder = Flavor::CircuitBuilder; + +// TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS }; + +// // Construct a simple circuit and make a copy of it +// Builder builder; +// GoblinMockCircuits::construct_simple_circuit(builder); +// auto builder_copy = builder; + +// // Construct two identical proving keys +// auto proving_key_1 = std::make_shared(builder, trace_settings); +// auto proving_key_2 = std::make_shared(builder_copy, trace_settings); + +// // Tamper with the polys of pkey 1 in such a way that verification should fail +// for (size_t i = 0; i < proving_key_1->proving_key.circuit_size; ++i) { +// if (proving_key_1->proving_key.polynomials.q_arith[i] != 0) { +// proving_key_1->proving_key.polynomials.w_l.at(i) += 1; +// break; +// } +// } + +// // Swap the polys of the two proving keys; result should be pkey 1 is valid and pkey 2 should fail +// std::swap(proving_key_1->proving_key.polynomials, proving_key_2->proving_key.polynomials); + +// { // Verification based on pkey 1 should succeed +// typename TestFixture::Prover prover(proving_key_1); +// auto verification_key = std::make_shared(proving_key_1->proving_key); +// typename TestFixture::Verifier verifier(verification_key); +// auto proof = prover.construct_proof(); +// EXPECT_TRUE(verifier.verify_proof(proof)); +// } + +// { // Verification based on pkey 2 should fail +// typename TestFixture::Prover prover(proving_key_2); +// auto verification_key = std::make_shared(proving_key_2->proving_key); +// typename TestFixture::Verifier verifier(verification_key); +// auto proof = prover.construct_proof(); +// EXPECT_FALSE(verifier.verify_proof(proof)); +// } +// } From 66b73a50f3c98802e992fa9f3c22e02f01184380 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 10 Feb 2025 18:36:14 +0000 Subject: [PATCH 07/10] translator uses relation checker --- .../plonk_honk_shared/relation_checker.hpp | 2 +- .../relation_correctness.test.cpp | 39 +++--------- .../translator_proving_key.test.cpp | 3 +- .../ultra_honk/relation_correctness.test.cpp | 63 ------------------- 4 files changed, 11 insertions(+), 96 deletions(-) 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 19ec270770ca..bd6f80ccf3fa 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp @@ -35,7 +35,7 @@ template class RelationChecker { element = 0; } - for (size_t i = 0; i < polynomials.w_l.virtual_size(); i++) { + for (size_t i = 0; i < polynomials.get_polynomial_size(); i++) { // Evaluate each constraint in the relation and check that each is satisfied Relation::accumulate(result, polynomials.get_row(i), params, 1); 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 de4192825ba1..341f4ce17427 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()); } @@ -92,7 +69,7 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) prover_polynomials.z_perm_shift = prover_polynomials.z_perm.shifted(); // 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); } TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) @@ -153,7 +130,7 @@ TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) }); // 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); } /** @@ -217,13 +194,13 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) prover_polynomials.accumulators_binary_limbs_3.at(1) = params.accumulated_result[3]; // 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); // 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); // 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); } /** * @brief Test the correctness of TranslatorFlavor's Decomposition Relation @@ -565,7 +542,7 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) } // 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); } /** @@ -670,5 +647,5 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) } // 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); } 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 index 97b022ddfe70..c5f31e8ee5f1 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp @@ -1,6 +1,7 @@ #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/sumcheck/sumcheck_round.hpp" #include "barretenberg/translator_vm/translator_circuit_builder.hpp" @@ -108,5 +109,5 @@ TEST_F(TranslatorProvingKeyTests, InterleaveFull) prover_polynomials.z_perm_shift = prover_polynomials.z_perm.shifted(); // 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); } 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 5126dc682627..1d2363085a3e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -26,69 +26,6 @@ void ensure_non_zero(auto& polynomial) ASSERT_TRUE(has_non_zero_coefficient); } -<<<<<<< HEAD -======= -/** - * @brief Check that a given relation is satified for a set of polynomials - * - */ -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); - } -} - ->>>>>>> mm/translator-interleaving template void create_some_add_gates(auto& circuit_builder) { using FF = typename Flavor::FF; From fe4509b73db1fc520dff3bc7e870ff9d4edd9541 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 10 Feb 2025 18:44:04 +0000 Subject: [PATCH 08/10] reduce scope and cleanup --- .../translator_proving_key.test.cpp | 18 - .../ultra_honk/mega_honk.test.cpp | 891 +++++++++--------- 2 files changed, 441 insertions(+), 468 deletions(-) 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 index c5f31e8ee5f1..e05b74c79879 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp @@ -24,24 +24,6 @@ class TranslatorProvingKeyTests : public ::testing::Test { }; } // namespace -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 Simple test to check the interleaving method produces the expected results. * diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index 451ecf65ad9f..eaa85b26ee38 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -1,450 +1,441 @@ -// #include -// #include -// #include - -// #include "barretenberg/circuit_checker/circuit_checker.hpp" -// #include "barretenberg/common/log.hpp" -// #include "barretenberg/goblin/mock_circuits.hpp" -// #include "barretenberg/plonk_honk_shared/relation_checker.hpp" -// #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" -// #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -// #include "barretenberg/ultra_honk/merge_prover.hpp" -// #include "barretenberg/ultra_honk/merge_verifier.hpp" -// #include "barretenberg/ultra_honk/ultra_prover.hpp" -// #include "barretenberg/ultra_honk/ultra_verifier.hpp" - -// using namespace bb; - -// auto& engine = numeric::get_debug_randomness(); - -// using FlavorTypes = ::testing::Types; - -// template class MegaHonkTests : public ::testing::Test { -// public: -// static void SetUpTestSuite() { bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); } - -// using Curve = curve::BN254; -// using FF = Curve::ScalarField; -// using Point = Curve::AffineElement; -// using CommitmentKey = bb::CommitmentKey; -// using MergeProver = MergeProver_; -// using MergeVerifier = MergeVerifier_; -// using Prover = UltraProver_; -// using Verifier = UltraVerifier_; -// using VerificationKey = typename Flavor::VerificationKey; -// using DeciderProvingKey = DeciderProvingKey_; - -// /** -// * @brief Construct and a verify a Honk proof -// * -// */ -// bool construct_and_verify_honk_proof(auto& builder) -// { -// auto proving_key = std::make_shared(builder); -// Prover prover(proving_key); -// auto verification_key = std::make_shared(proving_key->proving_key); -// Verifier verifier(verification_key); -// auto proof = prover.construct_proof(); -// bool verified = verifier.verify_proof(proof); - -// return verified; -// } - -// /** -// * @brief Construct and a verify a Honk proof using a specified structured trace -// * -// */ -// bool construct_and_verify_honk_proof_with_structured_trace(auto& builder, TraceSettings& trace_settings) -// { -// // no ZK flavor for now -// using Prover = UltraProver_; -// using Verifier = UltraVerifier_; -// using VerificationKey = typename MegaFlavor::VerificationKey; -// using DeciderProvingKey = DeciderProvingKey_; -// auto proving_key = std::make_shared(builder, trace_settings); - -// Prover prover(proving_key); -// auto verification_key = std::make_shared(proving_key->proving_key); -// Verifier verifier(verification_key); -// auto proof = prover.construct_proof(); -// bool verified = verifier.verify_proof(proof); - -// return verified; -// } - -// /** -// * @brief Construct and verify a Goblin ECC op queue merge proof -// * -// */ -// bool construct_and_verify_merge_proof(auto& op_queue) -// { -// MergeProver merge_prover{ op_queue }; -// MergeVerifier merge_verifier; -// auto merge_proof = merge_prover.construct_proof(); -// bool verified = merge_verifier.verify_proof(merge_proof); - -// return verified; -// } -// }; - -// TYPED_TEST_SUITE(MegaHonkTests, FlavorTypes); - -// /** -// * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic -// * gates -// * -// */ -// TYPED_TEST(MegaHonkTests, Basic) -// { -// using Flavor = TypeParam; -// typename Flavor::CircuitBuilder builder; - -// GoblinMockCircuits::construct_simple_circuit(builder); - -// // Construct and verify Honk proof -// bool honk_verified = this->construct_and_verify_honk_proof(builder); -// EXPECT_TRUE(honk_verified); -// } - -// /** -// * @brief Test proof construction/verification for a structured execution trace -// * -// */ -// TYPED_TEST(MegaHonkTests, BasicStructured) -// { -// using Flavor = TypeParam; - -// // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i -// for -// // i=1,2,3. This mechanism does not work with structured polynomials yet. -// if constexpr (std::is_same_v) { -// GTEST_SKIP() << "Skipping 'BasicStructured' test for MegaZKFlavor."; -// } -// typename Flavor::CircuitBuilder builder; -// using Prover = UltraProver_; -// using Verifier = UltraVerifier_; - -// GoblinMockCircuits::construct_simple_circuit(builder); - -// // Construct and verify Honk proof using a structured trace -// TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; -// auto proving_key = std::make_shared>(builder, trace_settings); -// Prover prover(proving_key); -// auto verification_key = std::make_shared(proving_key->proving_key); -// Verifier verifier(verification_key); -// auto proof = prover.construct_proof(); - -// // Sanity check: ensure z_perm is not zero everywhere -// EXPECT_TRUE(!proving_key->proving_key.polynomials.z_perm.is_zero()); - -// auto& prover_polynomials = proving_key->proving_key.polynomials; -// auto params = proving_key->relation_parameters; - -// RelationChecker::check_all(prover_polynomials, params); - -// EXPECT_TRUE(verifier.verify_proof(proof)); -// } - -// /** -// * @brief Test that increasing the virtual size of a valid set of prover polynomials still results in a valid -// Megahonk -// * proof -// * -// */ -// TYPED_TEST(MegaHonkTests, DynamicVirtualSizeIncrease) -// { -// using Flavor = TypeParam; - -// // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i -// for -// // i=1,2,3. This mechanism does not work with structured polynomials yet. -// if constexpr (std::is_same_v) { -// GTEST_SKIP() << "Skipping 'DynamicVirtualSizeIncrease' test for MegaZKFlavor."; -// } -// typename Flavor::CircuitBuilder builder; -// using Prover = UltraProver_; -// using Verifier = UltraVerifier_; - -// GoblinMockCircuits::construct_simple_circuit(builder); - -// auto builder_copy = builder; - -// // Construct and verify Honk proof using a structured trace -// TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS }; -// auto proving_key = std::make_shared>(builder, trace_settings); -// auto proving_key_copy = std::make_shared>(builder_copy, trace_settings); -// auto circuit_size = proving_key->proving_key.circuit_size; - -// auto doubled_circuit_size = 2 * circuit_size; -// proving_key_copy->proving_key.polynomials.increase_polynomials_virtual_size(doubled_circuit_size); -// // TODO(https://github.com/AztecProtocol/barretenberg/issues/1158) -// // proving_key_copy->proving_key.circuit_size = doubled_circuit_size; - -// Prover prover(proving_key); -// auto verification_key = std::make_shared(proving_key->proving_key); - -// Prover prover_copy(proving_key_copy); -// auto verification_key_copy = std::make_shared(proving_key_copy->proving_key); - -// for (auto [entry, entry_copy] : zip_view(verification_key->get_all(), verification_key_copy->get_all())) { -// EXPECT_EQ(entry, entry_copy); -// } - -// Verifier verifier(verification_key); -// auto proof = prover.construct_proof(); - -// RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); -// EXPECT_TRUE(verifier.verify_proof(proof)); - -// Verifier verifier_copy(verification_key_copy); -// auto proof_copy = prover_copy.construct_proof(); - -// RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); -// EXPECT_TRUE(verifier_copy.verify_proof(proof_copy)); -// } - -// /** -// * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic -// * gates -// * @note We simulate op queue interactions with a previous circuit so the actual circuit under test utilizes an op -// queue -// * with non-empty 'previous' data. This avoid complications with zero-commitments etc. -// * -// */ -// TYPED_TEST(MegaHonkTests, SingleCircuit) -// { -// using Flavor = TypeParam; -// auto op_queue = std::make_shared(); - -// GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); -// auto builder = typename Flavor::CircuitBuilder{ op_queue }; - -// GoblinMockCircuits::construct_simple_circuit(builder); - -// // Construct and verify Honk proof -// bool honk_verified = this->construct_and_verify_honk_proof(builder); -// EXPECT_TRUE(honk_verified); - -// // Construct and verify Goblin ECC op queue Merge proof -// auto merge_verified = this->construct_and_verify_merge_proof(op_queue); -// EXPECT_TRUE(merge_verified); -// } - -// /** -// * @brief Test Merge proof construction/verification for multiple circuits with ECC op gates, public inputs, and -// * basic arithmetic gates -// * -// */ -// TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly) -// { -// using Flavor = TypeParam; -// // Instantiate EccOpQueue. This will be shared across all circuits in the series -// auto op_queue = std::make_shared(); - -// GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); - -// // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. -// size_t NUM_CIRCUITS = 3; -// for (size_t i = 0; i < NUM_CIRCUITS; ++i) { -// auto builder = typename Flavor::CircuitBuilder{ op_queue }; - -// GoblinMockCircuits::construct_simple_circuit(builder); - -// // Construct and verify Goblin ECC op queue Merge proof -// auto merge_verified = this->construct_and_verify_merge_proof(op_queue); -// EXPECT_TRUE(merge_verified); -// } -// } - -// /** -// * @brief Test Honk proof construction/verification for multiple circuits with ECC op gates, public inputs, and -// * basic arithmetic gates -// * -// */ -// TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkOnly) -// { -// using Flavor = TypeParam; - -// // Instantiate EccOpQueue. This will be shared across all circuits in the series -// auto op_queue = std::make_shared(); - -// GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); - -// // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. -// size_t NUM_CIRCUITS = 3; -// for (size_t i = 0; i < NUM_CIRCUITS; ++i) { -// auto builder = typename Flavor::CircuitBuilder{ op_queue }; - -// GoblinMockCircuits::construct_simple_circuit(builder); - -// // Construct and verify Honk proof -// bool honk_verified = this->construct_and_verify_honk_proof(builder); -// EXPECT_TRUE(honk_verified); -// } -// } - -// /** -// * @brief Test Honk and Merge proof construction/verification for multiple circuits with ECC op gates, public inputs, -// * and basic arithmetic gates -// * -// */ -// TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkAndMerge) -// { -// using Flavor = TypeParam; - -// // Instantiate EccOpQueue. This will be shared across all circuits in the series -// auto op_queue = std::make_shared(); - -// GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); - -// // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. -// size_t NUM_CIRCUITS = 3; -// for (size_t i = 0; i < NUM_CIRCUITS; ++i) { -// auto builder = typename Flavor::CircuitBuilder{ op_queue }; - -// GoblinMockCircuits::construct_simple_circuit(builder); - -// // Construct and verify Honk proof -// bool honk_verified = this->construct_and_verify_honk_proof(builder); -// EXPECT_TRUE(honk_verified); - -// // Construct and verify Goblin ECC op queue Merge proof -// auto merge_verified = this->construct_and_verify_merge_proof(op_queue); -// EXPECT_TRUE(merge_verified); -// } - -// // Compute the commitments to the aggregate op queue directly and check that they match those that were computed -// // iteratively during transcript aggregation by the provers and stored in the op queue. -// size_t aggregate_op_queue_size = op_queue->get_current_size(); -// auto ultra_ops = op_queue->get_aggregate_transcript(); -// auto commitment_key = std::make_shared(aggregate_op_queue_size); -// size_t idx = 0; -// for (const auto& result : op_queue->get_ultra_ops_commitments()) { -// auto expected = commitment_key->commit({ /* start index */ 0, ultra_ops[idx++] }); -// EXPECT_EQ(result, expected); -// } -// } - -// /** -// * @brief Test the structured trace overflow mechanism for various circuits which overflow in different ways -// * -// */ -// TYPED_TEST(MegaHonkTests, StructuredTraceOverflow) -// { -// using Flavor = TypeParam; -// using Builder = Flavor::CircuitBuilder; - -// TraceSettings trace_settings{ TINY_TEST_STRUCTURE }; - -// { // Overflow in Arithmetic block only -// Builder builder; - -// GoblinMockCircuits::construct_simple_circuit(builder); -// MockCircuits::add_arithmetic_gates(builder, 1 << 15); - -// bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); -// EXPECT_TRUE(verified); - -// // We expect that the circuit has overflowed the provided structured trace -// EXPECT_TRUE(builder.blocks.has_overflow); -// } - -// { // Overflow in Aux block (RAM gates; uses memory records which requires specific logic in overflow mechanism) -// Builder builder; - -// GoblinMockCircuits::construct_simple_circuit(builder); -// MockCircuits::add_RAM_gates(builder); - -// bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); -// EXPECT_TRUE(verified); - -// // We expect that the circuit has overflowed the provided structured trace -// EXPECT_TRUE(builder.blocks.has_overflow); -// } - -// { // Overflow in Lookup block only -// Builder builder; - -// GoblinMockCircuits::construct_simple_circuit(builder); -// MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); - -// bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); -// EXPECT_TRUE(verified); - -// // We expect that the circuit has overflowed the provided structured trace -// EXPECT_TRUE(builder.blocks.has_overflow); -// } - -// { // Overflow in Multiple blocks simultaneously -// Builder builder; - -// GoblinMockCircuits::construct_simple_circuit(builder); -// MockCircuits::add_arithmetic_gates(builder, 1 << 15); -// MockCircuits::add_RAM_gates(builder); -// MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); - -// bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); -// EXPECT_TRUE(verified); - -// // We expect that the circuit has overflowed the provided structured trace -// EXPECT_TRUE(builder.blocks.has_overflow); -// } -// } - -// /** -// * @brief A sanity check that a simple std::swap on a ProverPolynomials object works as expected -// * @details Constuct two valid proving keys. Tamper with the prover_polynomials of one key then swap the -// * prover_polynomials of the two keys. The key who received the tampered polys leads to a failed verification while -// the -// * other succeeds. -// * -// */ -// TYPED_TEST(MegaHonkTests, PolySwap) -// { -// using Flavor = TypeParam; -// // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i, -// for -// // i=1,2,3. This mechanism does not work with structured polynomials yet. -// if constexpr (std::is_same_v) { -// GTEST_SKIP() << "Skipping 'PolySwap' test for MegaZKFlavor."; -// } -// using Builder = Flavor::CircuitBuilder; - -// TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS }; - -// // Construct a simple circuit and make a copy of it -// Builder builder; -// GoblinMockCircuits::construct_simple_circuit(builder); -// auto builder_copy = builder; - -// // Construct two identical proving keys -// auto proving_key_1 = std::make_shared(builder, trace_settings); -// auto proving_key_2 = std::make_shared(builder_copy, trace_settings); - -// // Tamper with the polys of pkey 1 in such a way that verification should fail -// for (size_t i = 0; i < proving_key_1->proving_key.circuit_size; ++i) { -// if (proving_key_1->proving_key.polynomials.q_arith[i] != 0) { -// proving_key_1->proving_key.polynomials.w_l.at(i) += 1; -// break; -// } -// } - -// // Swap the polys of the two proving keys; result should be pkey 1 is valid and pkey 2 should fail -// std::swap(proving_key_1->proving_key.polynomials, proving_key_2->proving_key.polynomials); - -// { // Verification based on pkey 1 should succeed -// typename TestFixture::Prover prover(proving_key_1); -// auto verification_key = std::make_shared(proving_key_1->proving_key); -// typename TestFixture::Verifier verifier(verification_key); -// auto proof = prover.construct_proof(); -// EXPECT_TRUE(verifier.verify_proof(proof)); -// } - -// { // Verification based on pkey 2 should fail -// typename TestFixture::Prover prover(proving_key_2); -// auto verification_key = std::make_shared(proving_key_2->proving_key); -// typename TestFixture::Verifier verifier(verification_key); -// auto proof = prover.construct_proof(); -// EXPECT_FALSE(verifier.verify_proof(proof)); -// } -// } +#include +#include +#include + +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/common/log.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/plonk_honk_shared/relation_checker.hpp" +#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include "barretenberg/ultra_honk/merge_prover.hpp" +#include "barretenberg/ultra_honk/merge_verifier.hpp" +#include "barretenberg/ultra_honk/ultra_prover.hpp" +#include "barretenberg/ultra_honk/ultra_verifier.hpp" + +using namespace bb; + +auto& engine = numeric::get_debug_randomness(); + +using FlavorTypes = ::testing::Types; + +template class MegaHonkTests : public ::testing::Test { + public: + static void SetUpTestSuite() { bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); } + + using Curve = curve::BN254; + using FF = Curve::ScalarField; + using Point = Curve::AffineElement; + using CommitmentKey = bb::CommitmentKey; + using MergeProver = MergeProver_; + using MergeVerifier = MergeVerifier_; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = typename Flavor::VerificationKey; + using DeciderProvingKey = DeciderProvingKey_; + + /** + * @brief Construct and a verify a Honk proof + * + */ + bool construct_and_verify_honk_proof(auto& builder) + { + auto proving_key = std::make_shared(builder); + Prover prover(proving_key); + auto verification_key = std::make_shared(proving_key->proving_key); + Verifier verifier(verification_key); + auto proof = prover.construct_proof(); + bool verified = verifier.verify_proof(proof); + + return verified; + } + + /** + * @brief Construct and a verify a Honk proof using a specified structured trace + * + */ + bool construct_and_verify_honk_proof_with_structured_trace(auto& builder, TraceSettings& trace_settings) + { + // no ZK flavor for now + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = typename MegaFlavor::VerificationKey; + using DeciderProvingKey = DeciderProvingKey_; + auto proving_key = std::make_shared(builder, trace_settings); + + Prover prover(proving_key); + auto verification_key = std::make_shared(proving_key->proving_key); + Verifier verifier(verification_key); + auto proof = prover.construct_proof(); + bool verified = verifier.verify_proof(proof); + + return verified; + } + + /** + * @brief Construct and verify a Goblin ECC op queue merge proof + * + */ + bool construct_and_verify_merge_proof(auto& op_queue) + { + MergeProver merge_prover{ op_queue }; + MergeVerifier merge_verifier; + auto merge_proof = merge_prover.construct_proof(); + bool verified = merge_verifier.verify_proof(merge_proof); + + return verified; + } +}; + +TYPED_TEST_SUITE(MegaHonkTests, FlavorTypes); + +/** + * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic + * gates + * + */ +TYPED_TEST(MegaHonkTests, Basic) +{ + using Flavor = TypeParam; + typename Flavor::CircuitBuilder builder; + + GoblinMockCircuits::construct_simple_circuit(builder); + + // Construct and verify Honk proof + bool honk_verified = this->construct_and_verify_honk_proof(builder); + EXPECT_TRUE(honk_verified); +} + +/** + * @brief Test proof construction/verification for a structured execution trace + * + */ +TYPED_TEST(MegaHonkTests, BasicStructured) +{ + using Flavor = TypeParam; + + // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i for + // i=1,2,3. This mechanism does not work with structured polynomials yet. + if constexpr (std::is_same_v) { + GTEST_SKIP() << "Skipping 'BasicStructured' test for MegaZKFlavor."; + } + typename Flavor::CircuitBuilder builder; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + + GoblinMockCircuits::construct_simple_circuit(builder); + + // Construct and verify Honk proof using a structured trace + TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; + auto proving_key = std::make_shared>(builder, trace_settings); + Prover prover(proving_key); + auto verification_key = std::make_shared(proving_key->proving_key); + Verifier verifier(verification_key); + auto proof = prover.construct_proof(); + + // Sanity check: ensure z_perm is not zero everywhere + EXPECT_TRUE(!proving_key->proving_key.polynomials.z_perm.is_zero()); + + RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); + + EXPECT_TRUE(verifier.verify_proof(proof)); +} + +/** + * @brief Test that increasing the virtual size of a valid set of prover polynomials still results in a valid Megahonk + * proof + * + */ +TYPED_TEST(MegaHonkTests, DynamicVirtualSizeIncrease) +{ + using Flavor = TypeParam; + + // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i for + // i=1,2,3. This mechanism does not work with structured polynomials yet. + if constexpr (std::is_same_v) { + GTEST_SKIP() << "Skipping 'DynamicVirtualSizeIncrease' test for MegaZKFlavor."; + } + typename Flavor::CircuitBuilder builder; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + + GoblinMockCircuits::construct_simple_circuit(builder); + + auto builder_copy = builder; + + // Construct and verify Honk proof using a structured trace + TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS }; + auto proving_key = std::make_shared>(builder, trace_settings); + auto proving_key_copy = std::make_shared>(builder_copy, trace_settings); + auto circuit_size = proving_key->proving_key.circuit_size; + + auto doubled_circuit_size = 2 * circuit_size; + proving_key_copy->proving_key.polynomials.increase_polynomials_virtual_size(doubled_circuit_size); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1158) + // proving_key_copy->proving_key.circuit_size = doubled_circuit_size; + + Prover prover(proving_key); + auto verification_key = std::make_shared(proving_key->proving_key); + + Prover prover_copy(proving_key_copy); + auto verification_key_copy = std::make_shared(proving_key_copy->proving_key); + + for (auto [entry, entry_copy] : zip_view(verification_key->get_all(), verification_key_copy->get_all())) { + EXPECT_EQ(entry, entry_copy); + } + + Verifier verifier(verification_key); + auto proof = prover.construct_proof(); + + RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); + EXPECT_TRUE(verifier.verify_proof(proof)); + + Verifier verifier_copy(verification_key_copy); + auto proof_copy = prover_copy.construct_proof(); + + RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); + EXPECT_TRUE(verifier_copy.verify_proof(proof_copy)); +} + +/** + * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic + * gates + * @note We simulate op queue interactions with a previous circuit so the actual circuit under test utilizes an op queue + * with non-empty 'previous' data. This avoid complications with zero-commitments etc. + * + */ +TYPED_TEST(MegaHonkTests, SingleCircuit) +{ + using Flavor = TypeParam; + auto op_queue = std::make_shared(); + + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + auto builder = typename Flavor::CircuitBuilder{ op_queue }; + + GoblinMockCircuits::construct_simple_circuit(builder); + + // Construct and verify Honk proof + bool honk_verified = this->construct_and_verify_honk_proof(builder); + EXPECT_TRUE(honk_verified); + + // Construct and verify Goblin ECC op queue Merge proof + auto merge_verified = this->construct_and_verify_merge_proof(op_queue); + EXPECT_TRUE(merge_verified); +} + +/** + * @brief Test Merge proof construction/verification for multiple circuits with ECC op gates, public inputs, and + * basic arithmetic gates + * + */ +TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly) +{ + using Flavor = TypeParam; + // Instantiate EccOpQueue. This will be shared across all circuits in the series + auto op_queue = std::make_shared(); + + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + + // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. + size_t NUM_CIRCUITS = 3; + for (size_t i = 0; i < NUM_CIRCUITS; ++i) { + auto builder = typename Flavor::CircuitBuilder{ op_queue }; + + GoblinMockCircuits::construct_simple_circuit(builder); + + // Construct and verify Goblin ECC op queue Merge proof + auto merge_verified = this->construct_and_verify_merge_proof(op_queue); + EXPECT_TRUE(merge_verified); + } +} + +/** + * @brief Test Honk proof construction/verification for multiple circuits with ECC op gates, public inputs, and + * basic arithmetic gates + * + */ +TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkOnly) +{ + using Flavor = TypeParam; + + // Instantiate EccOpQueue. This will be shared across all circuits in the series + auto op_queue = std::make_shared(); + + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + + // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. + size_t NUM_CIRCUITS = 3; + for (size_t i = 0; i < NUM_CIRCUITS; ++i) { + auto builder = typename Flavor::CircuitBuilder{ op_queue }; + + GoblinMockCircuits::construct_simple_circuit(builder); + + // Construct and verify Honk proof + bool honk_verified = this->construct_and_verify_honk_proof(builder); + EXPECT_TRUE(honk_verified); + } +} + +/** + * @brief Test Honk and Merge proof construction/verification for multiple circuits with ECC op gates, public inputs, + * and basic arithmetic gates + * + */ +TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkAndMerge) +{ + using Flavor = TypeParam; + + // Instantiate EccOpQueue. This will be shared across all circuits in the series + auto op_queue = std::make_shared(); + + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + + // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. + size_t NUM_CIRCUITS = 3; + for (size_t i = 0; i < NUM_CIRCUITS; ++i) { + auto builder = typename Flavor::CircuitBuilder{ op_queue }; + + GoblinMockCircuits::construct_simple_circuit(builder); + + // Construct and verify Honk proof + bool honk_verified = this->construct_and_verify_honk_proof(builder); + EXPECT_TRUE(honk_verified); + + // Construct and verify Goblin ECC op queue Merge proof + auto merge_verified = this->construct_and_verify_merge_proof(op_queue); + EXPECT_TRUE(merge_verified); + } + + // Compute the commitments to the aggregate op queue directly and check that they match those that were computed + // iteratively during transcript aggregation by the provers and stored in the op queue. + size_t aggregate_op_queue_size = op_queue->get_current_size(); + auto ultra_ops = op_queue->get_aggregate_transcript(); + auto commitment_key = std::make_shared(aggregate_op_queue_size); + size_t idx = 0; + for (const auto& result : op_queue->get_ultra_ops_commitments()) { + auto expected = commitment_key->commit({ /* start index */ 0, ultra_ops[idx++] }); + EXPECT_EQ(result, expected); + } +} + +/** + * @brief Test the structured trace overflow mechanism for various circuits which overflow in different ways + * + */ +TYPED_TEST(MegaHonkTests, StructuredTraceOverflow) +{ + using Flavor = TypeParam; + using Builder = Flavor::CircuitBuilder; + + TraceSettings trace_settings{ TINY_TEST_STRUCTURE }; + + { // Overflow in Arithmetic block only + Builder builder; + + GoblinMockCircuits::construct_simple_circuit(builder); + MockCircuits::add_arithmetic_gates(builder, 1 << 15); + + bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); + EXPECT_TRUE(verified); + + // We expect that the circuit has overflowed the provided structured trace + EXPECT_TRUE(builder.blocks.has_overflow); + } + + { // Overflow in Aux block (RAM gates; uses memory records which requires specific logic in overflow mechanism) + Builder builder; + + GoblinMockCircuits::construct_simple_circuit(builder); + MockCircuits::add_RAM_gates(builder); + + bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); + EXPECT_TRUE(verified); + + // We expect that the circuit has overflowed the provided structured trace + EXPECT_TRUE(builder.blocks.has_overflow); + } + + { // Overflow in Lookup block only + Builder builder; + + GoblinMockCircuits::construct_simple_circuit(builder); + MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); + + bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); + EXPECT_TRUE(verified); + + // We expect that the circuit has overflowed the provided structured trace + EXPECT_TRUE(builder.blocks.has_overflow); + } + + { // Overflow in Multiple blocks simultaneously + Builder builder; + + GoblinMockCircuits::construct_simple_circuit(builder); + MockCircuits::add_arithmetic_gates(builder, 1 << 15); + MockCircuits::add_RAM_gates(builder); + MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); + + bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); + EXPECT_TRUE(verified); + + // We expect that the circuit has overflowed the provided structured trace + EXPECT_TRUE(builder.blocks.has_overflow); + } +} + +/** + * @brief A sanity check that a simple std::swap on a ProverPolynomials object works as expected + * @details Constuct two valid proving keys. Tamper with the prover_polynomials of one key then swap the + * prover_polynomials of the two keys. The key who received the tampered polys leads to a failed verification while the + * other succeeds. + * + */ +TYPED_TEST(MegaHonkTests, PolySwap) +{ + using Flavor = TypeParam; + // In MegaZKFlavor, we mask witness polynomials by placing random values at the indices `dyadic_circuit_size`-i, for + // i=1,2,3. This mechanism does not work with structured polynomials yet. + if constexpr (std::is_same_v) { + GTEST_SKIP() << "Skipping 'PolySwap' test for MegaZKFlavor."; + } + using Builder = Flavor::CircuitBuilder; + + TraceSettings trace_settings{ SMALL_TEST_STRUCTURE_FOR_OVERFLOWS }; + + // Construct a simple circuit and make a copy of it + Builder builder; + GoblinMockCircuits::construct_simple_circuit(builder); + auto builder_copy = builder; + + // Construct two identical proving keys + auto proving_key_1 = std::make_shared(builder, trace_settings); + auto proving_key_2 = std::make_shared(builder_copy, trace_settings); + + // Tamper with the polys of pkey 1 in such a way that verification should fail + for (size_t i = 0; i < proving_key_1->proving_key.circuit_size; ++i) { + if (proving_key_1->proving_key.polynomials.q_arith[i] != 0) { + proving_key_1->proving_key.polynomials.w_l.at(i) += 1; + break; + } + } + + // Swap the polys of the two proving keys; result should be pkey 1 is valid and pkey 2 should fail + std::swap(proving_key_1->proving_key.polynomials, proving_key_2->proving_key.polynomials); + + { // Verification based on pkey 1 should succeed + typename TestFixture::Prover prover(proving_key_1); + auto verification_key = std::make_shared(proving_key_1->proving_key); + typename TestFixture::Verifier verifier(verification_key); + auto proof = prover.construct_proof(); + EXPECT_TRUE(verifier.verify_proof(proof)); + } + + { // Verification based on pkey 2 should fail + typename TestFixture::Prover prover(proving_key_2); + auto verification_key = std::make_shared(proving_key_2->proving_key); + typename TestFixture::Verifier verifier(verification_key); + auto proof = prover.construct_proof(); + EXPECT_FALSE(verifier.verify_proof(proof)); + } +} From 94798f50a154a1daeaa9c26b00ee06475b6202d8 Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 10 Feb 2025 18:49:55 +0000 Subject: [PATCH 09/10] cleanup --- .../plonk_honk_shared/relation_checker.hpp | 4 +--- .../relation_correctness.test.cpp | 22 ++++++++++++------- .../translator_vm/translator_flavor.hpp | 18 ++++----------- .../translator_vm/translator_proving_key.cpp | 18 +++++++-------- .../translator_vm/translator_proving_key.hpp | 2 +- .../translator_proving_key.test.cpp | 3 ++- 6 files changed, 31 insertions(+), 36 deletions(-) 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 bd6f80ccf3fa..336cc2e7f4f6 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/relation_checker.hpp @@ -37,7 +37,6 @@ template class RelationChecker { for (size_t i = 0; i < polynomials.get_polynomial_size(); i++) { - // 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; @@ -73,8 +72,7 @@ template class RelationChecker { if constexpr (has_linearly_dependent) { size_t subrelation_idx = 0; for (auto& element : result) { - // Check for linearly dependent subrelation and ensure their result over the entire execution trace - // is 0 + // 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, 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 341f4ce17427..91a3009cea63 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -22,7 +22,6 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) using Flavor = TranslatorFlavor; using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; - auto& engine = numeric::get_debug_randomness(); const size_t mini_circuit_size = 2048; auto full_circuit_size = mini_circuit_size * Flavor::CONCATENATION_GROUP_SIZE; @@ -69,7 +68,8 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) 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); + RelationChecker::check>( + prover_polynomials, params, "TranslatorPermutationRelation"); } TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) @@ -130,7 +130,8 @@ TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) }); // Check that DeltaRangeConstraint relation is satisfied across each row of the prover polynomials - RelationChecker::check>(prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorDeltaRangeConstraintRelation"); } /** @@ -194,13 +195,16 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) prover_polynomials.accumulators_binary_limbs_3.at(1) = params.accumulated_result[3]; // Check that Opcode Constraint relation is satisfied across each row of the prover polynomials - RelationChecker::check>(prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorOpcodeConstraintRelation"); // Check that Accumulator Transfer relation is satisfied across each row of the prover polynomials - RelationChecker::check>(prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorAccumulatorTransferRelation"); // Check that Zero Constraint relation is satisfied across each row of the prover polynomials - RelationChecker::check>(prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorZeroConstraintsRelation"); } /** * @brief Test the correctness of TranslatorFlavor's Decomposition Relation @@ -542,7 +546,8 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) } // Check that Decomposition relation is satisfied across each row of the prover polynomials - RelationChecker::check>(prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorDecompositionRelation"); } /** @@ -647,5 +652,6 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) } // Check that Non-Native Field relation is satisfied across each row of the prover polynomials - RelationChecker::check>(prover_polynomials, params); + RelationChecker::check>( + prover_polynomials, params, "TranslatorNonNativeFieldRelation"); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index 36b26a910420..d2666f6ffbc5 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -619,20 +619,10 @@ class TranslatorFlavor { // Constructor to init all unshifted polys to the zero polynomial and set the shifted poly data ProverPolynomials(size_t circuit_size) { - size_t mini_circuit_size = circuit_size / CONCATENATION_GROUP_SIZE; - for (auto& group : get_groups_to_be_concatenated()) { - for (auto& poly : group) { - poly = Polynomial{ mini_circuit_size - 1, circuit_size, 1 }; - } - } for (auto& poly : get_to_be_shifted()) { - if (poly.is_empty()) { - { - poly = Polynomial{ /*memory size*/ circuit_size - 1, - /*largest possible index*/ circuit_size, - /* offset */ 1 }; - } - } + poly = Polynomial{ /*memory size*/ circuit_size - 1, + /*largest possible index*/ circuit_size, + /* offset */ 1 }; } for (auto& poly : get_unshifted()) { if (poly.is_empty()) { @@ -657,7 +647,7 @@ class TranslatorFlavor { PROFILE_THIS(); AllValues result; for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { - result_field = polynomial.get(row_idx); + result_field = polynomial[row_idx]; } return result; } 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 709acc98e3ec..f9a33d30e373 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -91,19 +91,19 @@ void TranslatorProvingKey::interleave(const RefVector& group, Polyno * @brief Compute denominator polynomials for Translator's range constraint permutation * * @details We need to prove that all the range constraint wires indeed have values within the given range (unless - * changed ∈ [0 , 2¹⁴ - 1]. To do this, we use several virtual concatenated wires, each of which represents a - * subset or original wires (concatenated_range_constraints_). We also generate several new polynomials of the - * same length as concatenated ones. These polynomials have values within range, but they are also constrained by - * the TranslatorFlavor's DeltaRangeConstraint relation, which ensures that sequential values differ by not more - * than 3, the last value is the maximum and the first value is zero (zero at the start allows us not to dance - * around shifts). + * changed ∈ [0 , 2¹⁴ - 1]. To do this, we use several virtual concatenated wires, each of which represents a subset + * or original wires (concatenated_range_constraints_). We also generate several new polynomials of the same length + * as concatenated ones. These polynomials have values within range, but they are also constrained by the + * TranslatorFlavor's DeltaRangeConstraint relation, which ensures that sequential values differ by not more than + * 3, the last value is the maximum and the first value is zero (zero at the start allows us not to dance around + * shifts). * * Ideally, we could simply rearrange the values in concatenated_.._0 ,..., concatenated_.._3 and get denominator * polynomials (ordered_constraints), but we could get the worst case scenario: each value in the polynomials is * maximum value. What can we do in that case? We still have to add (max_range/3)+1 values to each of the ordered - * wires for the sort constraint to hold. So we also need a and extra denominator to store k ⋅ ( max_range / 3 + 1 - * ) values that couldn't go in + ( max_range / 3 + 1 ) connecting values. To counteract the extra ( k + 1 ) ⋅ ⋅ - * (max_range / 3 + 1 ) values needed for denominator sort constraints we need a polynomial in the numerator. So we + * wires for the sort constraint to hold. So we also need a and extra denominator to store k ⋅ ( max_range / 3 + 1 ) + * values that couldn't go in + ( max_range / 3 + 1 ) connecting values. To counteract the extra ( k + 1 ) ⋅ + * ⋅ (max_range / 3 + 1 ) values needed for denominator sort constraints we need a polynomial in the numerator. So we * can construct a proof when ( k + 1 ) ⋅ ( max_range/ 3 + 1 ) < concatenated size * * @tparam Flavor 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 791bf2ccae17..d1d836acad4a 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -93,7 +93,7 @@ class TranslatorProvingKey { inline void compute_mini_circuit_dyadic_size(const Circuit& circuit) { - const size_t total_num_gates = std::max(circuit.num_gates + 1, Flavor::MINIMUM_MINI_CIRCUIT_SIZE); + const size_t total_num_gates = std::max(circuit.num_gates, Flavor::MINIMUM_MINI_CIRCUIT_SIZE); // Next power of 2 mini_circuit_dyadic_size = circuit.get_circuit_subgroup_size(total_num_gates); } 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 index e05b74c79879..339137a6faf0 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp @@ -91,5 +91,6 @@ TEST_F(TranslatorProvingKeyTests, InterleaveFull) 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); + RelationChecker::check>( + prover_polynomials, params, "TranslatorPermutationRelation"); } From 48b1b6e3f27e98bced78541162d08100eea860cb Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 10 Feb 2025 19:01:50 +0000 Subject: [PATCH 10/10] complete test --- .../translator_vm/translator_proving_key.test.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) 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 index 339137a6faf0..1ce80716b66a 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.test.cpp @@ -1,20 +1,15 @@ +#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/sumcheck/sumcheck_round.hpp" -#include "barretenberg/translator_vm/translator_circuit_builder.hpp" -#include "barretenberg/translator_vm/translator_prover.hpp" -#include "barretenberg/translator_vm/translator_verifier.hpp" +#include "barretenberg/translator_vm/translator_flavor.hpp" #include using namespace bb; namespace { -using CircuitBuilder = TranslatorFlavor::CircuitBuilder; -using Transcript = TranslatorFlavor::Transcript; -using OpQueue = ECCOpQueue; using FF = TranslatorFlavor::Curve::ScalarField; auto& engine = numeric::get_debug_randomness(); @@ -93,4 +88,7 @@ TEST_F(TranslatorProvingKeyTests, InterleaveFull) // 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"); }