diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp index 9878925c236..8e805a54b6a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp @@ -563,17 +563,17 @@ template class ZeroMorphVerifier_ { // If applicable, add contribution from concatenated polynomial commitments // Note: this is an implementation detail related to Goblin Translator and is not part of the standard protocol. if (!concatenation_groups_commitments.empty()) { - size_t CONCATENATION_INDEX = concatenation_groups_commitments[0].size(); - size_t MINICIRCUIT_N = N / CONCATENATION_INDEX; + size_t CONCATENATION_GROUP_SIZE = concatenation_groups_commitments[0].size(); + size_t MINICIRCUIT_N = N / CONCATENATION_GROUP_SIZE; std::vector x_shifts; auto current_x_shift = x_challenge; auto x_to_minicircuit_n = x_challenge.pow(MINICIRCUIT_N); - for (size_t i = 0; i < CONCATENATION_INDEX; ++i) { + for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { x_shifts.emplace_back(current_x_shift); current_x_shift *= x_to_minicircuit_n; } for (auto& concatenation_group_commitment : concatenation_groups_commitments) { - for (size_t i = 0; i < CONCATENATION_INDEX; ++i) { + for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { scalars.emplace_back(rho_pow * x_shifts[i]); commitments.emplace_back(concatenation_group_commitment[i]); } diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_translator.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_translator.hpp index 062c0bf4814..f18a480f176 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_translator.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_translator.hpp @@ -44,13 +44,13 @@ class GoblinTranslator { // None of this parameters can be changed // How many mini_circuit_size polynomials are concatenated in one concatenated_* - static constexpr size_t CONCATENATION_INDEX = 16; + static constexpr size_t CONCATENATION_GROUP_SIZE = 16; // The number of concatenated_* wires static constexpr size_t NUM_CONCATENATED_WIRES = 4; // Actual circuit size - static constexpr size_t FULL_CIRCUIT_SIZE = MINI_CIRCUIT_SIZE * CONCATENATION_INDEX; + static constexpr size_t FULL_CIRCUIT_SIZE = MINI_CIRCUIT_SIZE * CONCATENATION_GROUP_SIZE; // Number of wires static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp index e69fa414b98..6deaa03df7a 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp @@ -190,6 +190,10 @@ template void compute_concatenated_pol // Resulting concatenated polynomials auto targets = proving_key->get_concatenated_constraints(); + // Targets have to be full-sized polynomials. We can compute the mini circuit size from them by dividing by + // concatenation index + const size_t MINI_CIRCUIT_SIZE = targets[0].size() / Flavor::CONCATENATION_GROUP_SIZE; + ASSERT(MINI_CIRCUIT_SIZE * Flavor::CONCATENATION_GROUP_SIZE == targets[0].size()); // A function that produces 1 concatenated polynomial // TODO(#756): This can be rewritten to use more cores. Currently uses at maximum the number of concatenated // polynomials (4 in Goblin Translator) @@ -201,8 +205,8 @@ template void compute_concatenated_pol for (size_t j = 0; j < my_group.size(); j++) { auto starting_write_offset = current_target.begin(); auto finishing_read_offset = my_group[j].begin(); - std::advance(starting_write_offset, j * Flavor::MINI_CIRCUIT_SIZE); - std::advance(finishing_read_offset, Flavor::MINI_CIRCUIT_SIZE); + std::advance(starting_write_offset, j * MINI_CIRCUIT_SIZE); + std::advance(finishing_read_offset, MINI_CIRCUIT_SIZE); // Copy into appropriate position in the concatenated polynomial std::copy(my_group[j].begin(), finishing_read_offset, starting_write_offset); } @@ -233,7 +237,8 @@ template void compute_concatenated_pol * @param proving_key */ template -void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandle* proving_key) +void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandle* proving_key, + size_t mini_circuit_dyadic_size) { using FF = typename Flavor::FF; @@ -241,8 +246,8 @@ void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandl // Get constants constexpr auto sort_step = Flavor::SORT_STEP; constexpr auto num_concatenated_wires = Flavor::NUM_CONCATENATED_WIRES; - constexpr auto full_circuit_size = Flavor::FULL_CIRCUIT_SIZE; - constexpr auto mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE; + const auto mini_circuit_size = mini_circuit_dyadic_size; + const auto full_circuit_size = mini_circuit_dyadic_size * Flavor::CONCATENATION_GROUP_SIZE; // The value we have to end polynomials with constexpr uint32_t max_value = (1 << Flavor::MICRO_LIMB_BITS) - 1; @@ -251,7 +256,7 @@ void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandl constexpr size_t sorted_elements_count = (max_value / sort_step) + 1 + (max_value % sort_step == 0 ? 0 : 1); // Check if we can construct these polynomials - static_assert((num_concatenated_wires + 1) * sorted_elements_count < full_circuit_size); + ASSERT((num_concatenated_wires + 1) * sorted_elements_count < full_circuit_size); // First use integers (easier to sort) std::vector sorted_elements(sorted_elements_count); @@ -278,7 +283,7 @@ void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandl // Get the group and the main target vector auto my_group = concatenation_groups[i]; auto& current_vector = ordered_vectors_uint[i]; - current_vector.resize(Flavor::FULL_CIRCUIT_SIZE); + current_vector.resize(full_circuit_size); // Calculate how much space there is for values from the original polynomials auto free_space_before_runway = full_circuit_size - sorted_elements_count; @@ -287,7 +292,7 @@ void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandl size_t extra_denominator_offset = i * sorted_elements_count; // Go through each polynomial in the concatenation group - for (size_t j = 0; j < Flavor::CONCATENATION_INDEX; j++) { + for (size_t j = 0; j < Flavor::CONCATENATION_GROUP_SIZE; j++) { // Calculate the offset in the target vector auto current_offset = j * mini_circuit_size; @@ -362,12 +367,14 @@ void compute_goblin_translator_range_constraint_ordered_polynomials(StorageHandl * contains 5 MAX_VALUE, 5 (MAX_VALUE-STEP),... values * * @param key Proving key where we will save the polynomials + * @param dyadic_circuit_size The full size of the circuit */ -template inline void compute_extra_range_constraint_numerator(auto proving_key) +template +inline void compute_extra_range_constraint_numerator(auto proving_key, size_t dyadic_circuit_size) { // Get the full goblin circuits size (this is the length of concatenated range constraint polynomials) - auto full_circuit_size = Flavor::FULL_CIRCUIT_SIZE; + auto full_circuit_size = dyadic_circuit_size; auto sort_step = Flavor::SORT_STEP; auto num_concatenated_wires = Flavor::NUM_CONCATENATED_WIRES; @@ -403,8 +410,10 @@ template inline void compute_extra_range_constraint_numerator( * @brief Compute odd and even largrange polynomials (up to mini_circuit length) and put them in the polynomial cache * * @param key Proving key where we will save the polynomials + * @param mini_circuit_dyadic_size The size of the part of the circuit where the computation of translated value happens */ -template inline void compute_lagrange_polynomials_for_goblin_translator(auto proving_key) +template +inline void compute_lagrange_polynomials_for_goblin_translator(auto proving_key, size_t mini_circuit_dyadic_size) { const size_t n = proving_key->circuit_size; @@ -413,7 +422,7 @@ template inline void compute_lagrange_polynomials_for_goblin_t typename Flavor::Polynomial lagrange_polynomial_second(n); typename Flavor::Polynomial lagrange_polynomial_second_to_last_in_minicircuit(n); - for (size_t i = 1; i < Flavor::MINI_CIRCUIT_SIZE - 1; i += 2) { + for (size_t i = 1; i < mini_circuit_dyadic_size - 1; i += 2) { lagrange_polynomial_odd_in_minicircuit[i] = 1; lagrange_polynomial_even_in_minicircut[i + 1] = 1; } @@ -421,7 +430,7 @@ template inline void compute_lagrange_polynomials_for_goblin_t proving_key->lagrange_even_in_minicircuit = lagrange_polynomial_even_in_minicircut.share(); lagrange_polynomial_second[1] = 1; - lagrange_polynomial_second_to_last_in_minicircuit[Flavor::MINI_CIRCUIT_SIZE - 2] = 1; + lagrange_polynomial_second_to_last_in_minicircuit[mini_circuit_dyadic_size - 2] = 1; proving_key->lagrange_second_to_last_in_minicircuit = lagrange_polynomial_second_to_last_in_minicircuit.share(); proving_key->lagrange_second = lagrange_polynomial_second.share(); } diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp index 79cbd878335..41865d083a1 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp @@ -184,7 +184,7 @@ class GoblinTranslatorCircuitBuilder : public CircuitBuilderBase { }; - // Basic goblin translator has the minicircuit size of 2048, so optimize for that case + // Basic goblin translator has the minimum minicircuit size of 2048, so optimize for that case // For context, minicircuit is the part of the final polynomials fed into the proving system, where we have all the // arithmetic logic. However, the full circuit is several times larger (we use a trick to bring down the degree of // the permutation argument) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.cpp index 285546ee4b7..64846fcc7bb 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.cpp @@ -33,22 +33,14 @@ using Transcript = typename Flavor::Transcript; void GoblinTranslatorComposer::compute_circuit_size_parameters(CircuitBuilder& circuit_builder) { - const size_t num_gates = circuit_builder.num_gates; - - // number of populated rows in the execution trace - size_t num_rows_populated_in_execution_trace = num_gates; - - // Goblin translator circuits always have a predefined size and are structured as a VM (no concept of selectors) - ASSERT(MINI_CIRCUIT_SIZE >= num_rows_populated_in_execution_trace); - - total_num_gates = std::max(MINI_CIRCUIT_SIZE, num_rows_populated_in_execution_trace); + total_num_gates = std::max(circuit_builder.num_gates, MINIMUM_MINI_CIRCUIT_SIZE); // Next power of 2 mini_circuit_dyadic_size = circuit_builder.get_circuit_subgroup_size(total_num_gates); // The actual circuit size is several times bigger than the trace in the builder, because we use concatenation to // bring the degree of relations down, while extending the length. - dyadic_circuit_size = mini_circuit_dyadic_size * Flavor::CONCATENATION_INDEX; + dyadic_circuit_size = mini_circuit_dyadic_size * Flavor::CONCATENATION_GROUP_SIZE; } /** @@ -189,7 +181,7 @@ void GoblinTranslatorComposer::compute_witness(CircuitBuilder& circuit_builder) // We also contruct ordered polynomials, which have the same values as concatenated ones + enough values to bridge // the range from 0 to maximum range defined by the range constraint. bb::honk::permutation_library::compute_goblin_translator_range_constraint_ordered_polynomials( - proving_key.get()); + proving_key.get(), mini_circuit_dyadic_size); computed_witness = true; } @@ -273,11 +265,13 @@ std::shared_ptr GoblinTranslatorComposer::compute_p // Compute polynomials with odd and even indices set to 1 up to the minicircuit margin + lagrange polynomials at // second and second to last indices in the minicircuit - bb::honk::permutation_library::compute_lagrange_polynomials_for_goblin_translator(proving_key.get()); + bb::honk::permutation_library::compute_lagrange_polynomials_for_goblin_translator(proving_key.get(), + mini_circuit_dyadic_size); // Compute the numerator for the permutation argument with several repetitions of steps bridging 0 and maximum range // constraint - bb::honk::permutation_library::compute_extra_range_constraint_numerator(proving_key.get()); + bb::honk::permutation_library::compute_extra_range_constraint_numerator(proving_key.get(), + dyadic_circuit_size); return proving_key; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.hpp index 4f1d4a9d219..55e2ed944ba 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.hpp @@ -20,10 +20,11 @@ class GoblinTranslatorComposer { using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; using Polynomial = typename Flavor::Polynomial; using Transcript = BaseTranscript; - static constexpr size_t MINI_CIRCUIT_SIZE = Flavor::MINI_CIRCUIT_SIZE; static constexpr std::string_view NAME_STRING = "GoblinTranslator"; static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; + // The minimum size of the mini-circuit (or sorted constraints won't work) + static constexpr size_t MINIMUM_MINI_CIRCUIT_SIZE = 2048; std::shared_ptr proving_key; std::shared_ptr verification_key; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp index f9988f38ed2..beeb72e3646 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp @@ -22,9 +22,6 @@ class GoblinTranslatorProver { using Curve = typename Flavor::Curve; using Transcript = typename Flavor::Transcript; - static size_t constexpr MINI_CIRCUIT_SIZE = Flavor::MINI_CIRCUIT_SIZE; - static size_t constexpr FULL_CIRCUIT_SIZE = Flavor::FULL_CIRCUIT_SIZE; - public: explicit GoblinTranslatorProver(const std::shared_ptr& input_key, const std::shared_ptr& commitment_key, 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 bbecb252bf6..b9313be2496 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -379,7 +379,8 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorPermutationRelationCorrectness) using Polynomial = bb::Polynomial; using namespace bb::honk::permutation_library; auto& engine = numeric::get_debug_randomness(); - auto circuit_size = Flavor::MINI_CIRCUIT_SIZE * Flavor::CONCATENATION_INDEX; + const size_t mini_circuit_size = 2048; + auto full_circuit_size = mini_circuit_size * Flavor::CONCATENATION_GROUP_SIZE; // We only need gamma, because permutationr elation only uses gamma FF gamma = FF::random_element(); @@ -391,16 +392,16 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorPermutationRelationCorrectness) // Create storage for polynomials ProverPolynomials prover_polynomials; for (Polynomial& prover_poly : prover_polynomials.get_all()) { - prover_poly = Polynomial{ circuit_size }; + prover_poly = Polynomial{ full_circuit_size }; } // Fill in lagrange polynomials used in the permutation relation prover_polynomials.lagrange_first[0] = 1; - prover_polynomials.lagrange_last[circuit_size - 1] = 1; + prover_polynomials.lagrange_last[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 = 0; i < Flavor::MINI_CIRCUIT_SIZE; i++) { + for (size_t i = 0; i < mini_circuit_size; i++) { polynomial[i] = engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1); } }; @@ -470,23 +471,23 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorPermutationRelationCorrectness) fill_polynomial_with_random_14_bit_values(prover_polynomials.relation_wide_limbs_range_constraint_3); // Compute ordered range constraint polynomials that go in the denominator of the grand product polynomial - compute_goblin_translator_range_constraint_ordered_polynomials(&prover_polynomials); + compute_goblin_translator_range_constraint_ordered_polynomials(&prover_polynomials, mini_circuit_size); // Compute the fixed numerator (part of verification key) - compute_extra_range_constraint_numerator(&prover_polynomials); + compute_extra_range_constraint_numerator(&prover_polynomials, full_circuit_size); // Compute concatenated polynomials (4 polynomials produced from other constraint polynomials by concatenation) compute_concatenated_polynomials(&prover_polynomials); // Compute the grand product polynomial grand_product_library::compute_grand_product>( - circuit_size, prover_polynomials, params); + full_circuit_size, 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>(circuit_size, prover_polynomials, params); + check_relation>(full_circuit_size, prover_polynomials, params); } TEST_F(RelationCorrectnessTests, GoblinTranslatorGenPermSortRelationCorrectness) @@ -496,8 +497,8 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorGenPermSortRelationCorrectness) using ProverPolynomials = typename Flavor::ProverPolynomials; using Polynomial = bb::Polynomial; auto& engine = numeric::get_debug_randomness(); - - const auto circuit_size = Flavor::FULL_CIRCUIT_SIZE; + const size_t mini_circuit_size = 2048; + const auto circuit_size = Flavor::CONCATENATION_GROUP_SIZE * mini_circuit_size; const auto sort_step = Flavor::SORT_STEP; const auto max_value = (1 << Flavor::MICRO_LIMB_BITS) - 1; @@ -579,8 +580,8 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorExtraRelationsCorrectness) auto& engine = numeric::get_debug_randomness(); - auto circuit_size = Flavor::FULL_CIRCUIT_SIZE; - auto mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE; + const size_t mini_circuit_size = 2048; + const auto circuit_size = Flavor::CONCATENATION_GROUP_SIZE * mini_circuit_size; // We only use accumulated_result from relation parameters in this relation RelationParameters params; @@ -681,7 +682,8 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorDecompositionRelationCorrectnes using Polynomial = bb::Polynomial; auto& engine = numeric::get_debug_randomness(); - auto circuit_size = Flavor::FULL_CIRCUIT_SIZE; + constexpr size_t mini_circuit_size = 2048; + const auto circuit_size = Flavor::CONCATENATION_GROUP_SIZE * mini_circuit_size; // Decomposition relation doesn't use any relation parameters RelationParameters params; @@ -723,7 +725,7 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorDecompositionRelationCorrectnes } // Fill in lagrange odd polynomial (the only non-witness one we are using) - for (size_t i = 1; i < Flavor::MINI_CIRCUIT_SIZE - 1; i += 2) { + for (size_t i = 1; i < mini_circuit_size - 1; i += 2) { prover_polynomials.lagrange_odd_in_minicircuit[i] = 1; } @@ -811,7 +813,7 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorDecompositionRelationCorrectnes }; // Put random values in all the non-concatenated constraint polynomials used to range constrain the values - for (size_t i = 1; i < Flavor::MINI_CIRCUIT_SIZE - 1; i += 2) { + for (size_t i = 1; i < mini_circuit_size - 1; i += 2) { // P.x prover_polynomials.x_lo_y_hi[i] = FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1)); prover_polynomials.x_hi_z_1[i] = FF(engine.get_random_uint256() & ((uint256_t(1) << HIGH_WIDE_LIMB_WIDTH) - 1)); @@ -1055,15 +1057,15 @@ TEST_F(RelationCorrectnessTests, GoblinTranslatorNonNativeRelationCorrectness) using Polynomial = bb::Polynomial; constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS; - constexpr auto circuit_size = Flavor::FULL_CIRCUIT_SIZE; - constexpr auto mini_circuit_size = Flavor::MINI_CIRCUIT_SIZE; + constexpr auto mini_circuit_size = 2048; + constexpr auto circuit_size = Flavor::CONCATENATION_GROUP_SIZE * mini_circuit_size; auto& engine = numeric::get_debug_randomness(); auto op_queue = std::make_shared(); // Generate random EccOpQueue actions - for (size_t i = 0; i < ((Flavor::MINI_CIRCUIT_SIZE >> 1) - 1); i++) { + for (size_t i = 0; i < ((mini_circuit_size >> 1) - 1); i++) { switch (engine.get_random_uint8() & 3) { case 0: op_queue->empty_row();