From 5389a8972d0ebe91e90bfc06986e2b4d7b26e119 Mon Sep 17 00:00:00 2001 From: maramihali Date: Wed, 18 Dec 2024 16:24:28 +0000 Subject: [PATCH 1/4] create translator proving key --- .../eccvm/eccvm_circuit_builder.hpp | 1 - .../cpp/src/barretenberg/goblin/goblin.hpp | 9 +- .../translator_recursive_verifier.test.cpp | 14 +- .../relation_correctness.test.cpp | 16 +-- .../translator_vm/translator.test.cpp | 7 +- .../translator_vm/translator_flavor.hpp | 104 +------------- .../translator_vm/translator_prover.cpp | 106 +++++--------- .../translator_vm/translator_prover.hpp | 12 +- .../translator_proving_key.cpp} | 136 +++++++++++------- .../translator_vm/translator_proving_key.hpp | 102 +++++++++++++ .../translator_vm/translator_verifier.cpp | 6 +- .../ultra_honk/decider_proving_key.hpp | 3 +- .../ultra_honk/relation_correctness.test.cpp | 1 - .../barretenberg/vm/avm/generated/prover.cpp | 1 - 14 files changed, 252 insertions(+), 266 deletions(-) rename barretenberg/cpp/src/barretenberg/{honk/proof_system/permutation_library.hpp => translator_vm/translator_proving_key.cpp} (57%) create mode 100644 barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp index 6fcea1cb32aa..29966706ee40 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp @@ -8,7 +8,6 @@ #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" -#include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp" diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index fae8b19ec451..9693c37a73d8 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -39,7 +39,7 @@ class GoblinProver { using TranslationEvaluations = ECCVMProver::TranslationEvaluations; using TranslatorBuilder = bb::TranslatorCircuitBuilder; using TranslatorProver = bb::TranslatorProver; - using TranslatorProvingKey = bb::TranslatorFlavor::ProvingKey; + using TranslatorProvingKey = bb::TranslatorProvingKey; using RecursiveMergeVerifier = bb::stdlib::recursion::goblin::MergeRecursiveVerifier_; using PairingPoints = RecursiveMergeVerifier::PairingPoints; using MergeProver = bb::MergeProver_; @@ -60,13 +60,14 @@ class GoblinProver { bool merge_proof_exists{ false }; std::shared_ptr get_eccvm_proving_key() const { return eccvm_key; } - std::shared_ptr get_translator_proving_key() const { return translator_prover->key; } + std::shared_ptr get_translator_proving_key() const { return translator_key; } private: // TODO(https://github.com/AztecProtocol/barretenberg/issues/798) unique_ptr use is a hack std::unique_ptr translator_prover; std::unique_ptr eccvm_prover; std::shared_ptr eccvm_key; + std::shared_ptr translator_key; GoblinAccumulationOutput accumulator; // Used only for ACIR methods for now @@ -211,7 +212,9 @@ class GoblinProver { auto translator_builder = std::make_unique(translation_batching_challenge_v, evaluation_challenge_x, op_queue); - translator_prover = std::make_unique(*translator_builder, transcript, commitment_key); + auto translator_proving_key = std::make_shared(*translator_builder, commitment_key); + translator_key = translator_proving_key->proving_key; + auto translator_prover = std::make_unique(translator_proving_key, transcript); } { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp index 1e2ab4beac0e..f09fc8a074ed 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp @@ -25,6 +25,7 @@ template class TranslatorRecursiveTests : public ::te public: using InnerFlavor = typename RecursiveFlavor::NativeFlavor; using InnerBuilder = typename InnerFlavor::CircuitBuilder; + using InnerProvingKey = TranslatorProvingKey; using InnerProver = TranslatorProver; using InnerVerifier = TranslatorVerifier; using InnerG1 = InnerFlavor::Commitment; @@ -68,8 +69,8 @@ template class TranslatorRecursiveTests : public ::te auto circuit_builder = InnerBuilder(translation_batching_challenge, translation_evaluation_challenge, op_queue); EXPECT_TRUE(circuit_builder.check_circuit()); - - InnerProver prover{ circuit_builder, prover_transcript }; + auto proving_key = std::make_shared(circuit_builder); + InnerProver prover{ proving_key, prover_transcript }; auto proof = prover.construct_proof(); OuterBuilder outer_circuit; @@ -79,7 +80,7 @@ template class TranslatorRecursiveTests : public ::te auto transcript = std::make_shared(stdlib_proof); transcript->template receive_from_prover("init"); - auto verification_key = std::make_shared(prover.key); + auto verification_key = std::make_shared(prover.key->proving_key); RecursiveVerifier verifier{ &outer_circuit, verification_key, transcript }; auto pairing_points = verifier.verify_proof(proof); info("Recursive Verifier: num gates = ", outer_circuit.num_gates); @@ -89,7 +90,7 @@ template class TranslatorRecursiveTests : public ::te auto native_verifier_transcript = std::make_shared(prover_transcript->proof_data); native_verifier_transcript->template receive_from_prover("init"); - InnerVerifier native_verifier(prover.key, native_verifier_transcript); + InnerVerifier native_verifier(verification_key, native_verifier_transcript); bool native_result = native_verifier.verify_proof(proof); auto recursive_result = native_verifier.key->pcs_verification_key->pairing_check(pairing_points[0].get_value(), pairing_points[1].get_value()); @@ -122,9 +123,8 @@ template class TranslatorRecursiveTests : public ::te } }; -using FlavorTypes = testing::Types, - TranslatorRecursiveFlavor_, - TranslatorRecursiveFlavor_>; +using FlavorTypes = + testing::Types, TranslatorRecursiveFlavor_>; TYPED_TEST_SUITE(TranslatorRecursiveTests, FlavorTypes); 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 ca13448d383e..6dd027d1667d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -1,7 +1,7 @@ #include "barretenberg/common/thread.hpp" -#include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/translator_vm/translator_flavor.hpp" +#include "barretenberg/translator_vm/translator_proving_key.hpp" #include #include @@ -45,7 +45,6 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) using Flavor = TranslatorFlavor; using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; - using ProvingKey = typename Flavor::ProvingKey; using Polynomial = bb::Polynomial; auto& engine = numeric::get_debug_randomness(); const size_t mini_circuit_size = 2048; @@ -59,8 +58,10 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) params.gamma = gamma; // Create storage for polynomials - auto proving_key = std::make_shared(); - + auto proving_key = std::make_shared(full_circuit_size); + TranslatorProvingKey key; + key.mini_circuit_dyadic_size = mini_circuit_size; + key.proving_key = proving_key; ProverPolynomials& prover_polynomials = proving_key->polynomials; // ensure we can shift these for (Polynomial& prover_poly : prover_polynomials.get_to_be_shifted()) { @@ -149,13 +150,13 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) 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_translator_range_constraint_ordered_polynomials(prover_polynomials, mini_circuit_size); + key.compute_translator_range_constraint_ordered_polynomials(); // Compute the fixed numerator (part of verification key) - proving_key->compute_extra_range_constraint_numerator(); + key.compute_extra_range_constraint_numerator(); // Compute concatenated polynomials (4 polynomials produced from other constraint polynomials by concatenation) - compute_concatenated_polynomials(prover_polynomials); + key.compute_concatenated_polynomials(); // Compute the grand product polynomial compute_grand_product>(prover_polynomials, params); @@ -271,7 +272,6 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) FF::random_element(), FF::random_element(), FF::random_element(), FF::random_element() }; - // Create storage for polynomials ProverPolynomials prover_polynomials; // We use polynomial ids to make shifting the polynomials easier ProverPolynomialIds prover_polynomial_ids; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index 62e3eefff307..b9f2327b747b 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -70,13 +70,14 @@ TEST_F(TranslatorTests, Basic) auto circuit_builder = CircuitBuilder(translation_batching_challenge, translation_evaluation_challenge, op_queue); EXPECT_TRUE(circuit_builder.check_circuit()); - - TranslatorProver prover{ circuit_builder, prover_transcript }; + auto proving_key = std::make_shared(circuit_builder); + TranslatorProver prover{ proving_key, prover_transcript }; auto proof = prover.construct_proof(); auto verifier_transcript = std::make_shared(prover_transcript->proof_data); verifier_transcript->template receive_from_prover("init"); - TranslatorVerifier verifier(prover.key, verifier_transcript); + auto verification_key = std::make_shared(proving_key->proving_key); + TranslatorVerifier verifier(verification_key, verifier_transcript); bool verified = verifier.verify_proof(proof); EXPECT_TRUE(verified); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index 0221f95fedfa..b25dbb2dd8fd 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -7,7 +7,6 @@ #include "barretenberg/flavor/flavor_macros.hpp" #include "barretenberg/flavor/relation_definitions.hpp" #include "barretenberg/flavor/repeated_commitments_data.hpp" -#include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/relations/relation_parameters.hpp" @@ -544,7 +543,7 @@ class TranslatorFlavor { public: DEFINE_COMPOUND_GET_ALL(PrecomputedEntities, WitnessEntities, ShiftedEntities) - auto get_precomputed() { return PrecomputedEntities::get_all(); }; + auto get_precomputed() const { return PrecomputedEntities::get_all(); }; /** * @brief Get entities concatenated for the permutation relation @@ -615,29 +614,6 @@ class TranslatorFlavor { } }; - public: - static inline size_t compute_total_num_gates(const CircuitBuilder& builder) - { - return std::max(builder.num_gates, MINIMUM_MINI_CIRCUIT_SIZE); - } - - static inline size_t compute_dyadic_circuit_size(const CircuitBuilder& builder) - { - const size_t total_num_gates = compute_total_num_gates(builder); - - // Next power of 2 - const size_t mini_circuit_dyadic_size = builder.get_circuit_subgroup_size(total_num_gates); - - // The actual circuit size is several times bigger than the trace in the builder, because we use concatenation - // to bring the degree of relations down, while extending the length. - return mini_circuit_dyadic_size * CONCATENATION_GROUP_SIZE; - } - - static inline size_t compute_mini_circuit_dyadic_size(const CircuitBuilder& builder) - { - return builder.get_circuit_subgroup_size(compute_total_num_gates(builder)); - } - /** * @brief A field element for each entity of the flavor. These entities represent the prover polynomials * evaluated at one point. @@ -704,8 +680,6 @@ class TranslatorFlavor { */ class ProvingKey : public ProvingKey_ { public: - BF batching_challenge_v = { 0 }; - BF evaluation_input_x = { 0 }; ProverPolynomials polynomials; // storage for all polynomials evaluated by the prover // Expose constructors on the base class @@ -713,80 +687,10 @@ class TranslatorFlavor { using Base::Base; ProvingKey() = default; - ProvingKey(const CircuitBuilder& builder) - : Base(compute_dyadic_circuit_size(builder), 0) - , batching_challenge_v(builder.batching_challenge_v) - , evaluation_input_x(builder.evaluation_input_x) + ProvingKey(const size_t dyadic_circuit_size, std::shared_ptr commitment_key = nullptr) + : Base(dyadic_circuit_size, 0, std::move(commitment_key)) , polynomials(this->circuit_size) - { - // First and last lagrange polynomials (in the full circuit size) - polynomials.lagrange_first.at(0) = 1; - polynomials.lagrange_last.at(circuit_size - 1) = 1; - - // 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 - compute_lagrange_polynomials(builder); - - // Compute the numerator for the permutation argument with several repetitions of steps bridging 0 and - // maximum range constraint compute_extra_range_constraint_numerator(); - compute_extra_range_constraint_numerator(); - } - - inline void compute_lagrange_polynomials(const CircuitBuilder& builder) - { - const size_t mini_circuit_dyadic_size = compute_mini_circuit_dyadic_size(builder); - - for (size_t i = 1; i < mini_circuit_dyadic_size - 1; i += 2) { - polynomials.lagrange_odd_in_minicircuit.at(i) = 1; - polynomials.lagrange_even_in_minicircuit.at(i + 1) = 1; - } - polynomials.lagrange_second.at(1) = 1; - polynomials.lagrange_second_to_last_in_minicircuit.at(mini_circuit_dyadic_size - 2) = 1; - } - - /** - * @brief Compute the extra numerator for Goblin range constraint argument - * - * @details Goblin proves that several polynomials contain only values in a certain range through 2 - * relations: 1) A grand product which ignores positions of elements (TranslatorPermutationRelation) 2) A - * relation enforcing a certain ordering on the elements of the given polynomial - * (TranslatorDeltaRangeConstraintRelation) - * - * We take the values from 4 polynomials, and spread them into 5 polynomials + add all the steps from - * MAX_VALUE to 0. We order these polynomials and use them in the denominator of the grand product, at the - * same time checking that they go from MAX_VALUE to 0. To counteract the added steps we also generate an - * extra range constraint numerator, which contains 5 MAX_VALUE, 5 (MAX_VALUE-STEP),... values - * - */ - inline void compute_extra_range_constraint_numerator() - { - auto& extra_range_constraint_numerator = polynomials.ordered_extra_range_constraints_numerator; - - static constexpr uint32_t MAX_VALUE = (1 << MICRO_LIMB_BITS) - 1; - - // Calculate how many elements there are in the sequence MAX_VALUE, MAX_VALUE - 3,...,0 - size_t sorted_elements_count = (MAX_VALUE / SORT_STEP) + 1 + (MAX_VALUE % SORT_STEP == 0 ? 0 : 1); - - // Check that we can fit every element in the polynomial - ASSERT((NUM_CONCATENATED_WIRES + 1) * sorted_elements_count < extra_range_constraint_numerator.size()); - - std::vector sorted_elements(sorted_elements_count); - - // Calculate the sequence in integers - sorted_elements[0] = MAX_VALUE; - for (size_t i = 1; i < sorted_elements_count; i++) { - sorted_elements[i] = (sorted_elements_count - 1 - i) * SORT_STEP; - } - - // TODO(#756): can be parallelized further. This will use at most 5 threads - auto fill_with_shift = [&](size_t shift) { - for (size_t i = 0; i < sorted_elements_count; i++) { - extra_range_constraint_numerator.at(shift + i * (NUM_CONCATENATED_WIRES + 1)) = sorted_elements[i]; - } - }; - // Fill polynomials with a sequence, where each element is repeated NUM_CONCATENATED_WIRES+1 times - parallel_for(NUM_CONCATENATED_WIRES + 1, fill_with_shift); - } + {} }; /** diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index a106f5716484..1076d34a2556 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -2,64 +2,20 @@ #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/commitment_schemes/shplonk/shplemini.hpp" -#include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" namespace bb { -TranslatorProver::TranslatorProver(CircuitBuilder& circuit_builder, - const std::shared_ptr& transcript, - std::shared_ptr commitment_key) - : dyadic_circuit_size(Flavor::compute_dyadic_circuit_size(circuit_builder)) - , mini_circuit_dyadic_size(Flavor::compute_mini_circuit_dyadic_size(circuit_builder)) - , transcript(transcript) - , key(std::make_shared(circuit_builder)) +TranslatorProver::TranslatorProver(std::shared_ptr& key, + const std::shared_ptr& transcript) + : transcript(transcript) + , key(key) { PROFILE_THIS(); - - key->commitment_key = commitment_key ? commitment_key : std::make_shared(key->circuit_size); - compute_witness(circuit_builder); -} - -/** - * @brief Compute witness polynomials - * - */ -void TranslatorProver::compute_witness(CircuitBuilder& circuit_builder) -{ - if (computed_witness) { - return; + if (key->proving_key->commitment_key == nullptr) { + key->proving_key->commitment_key = std::make_shared(key->proving_key->circuit_size); } - - // Populate the wire polynomials from the wire vectors in the circuit constructor. Note: In goblin translator wires - // come as is, since they have to reflect the structure of polynomials in the first 4 wires, which we've commited to - for (auto [wire_poly, wire] : zip_view(key->polynomials.get_wires(), circuit_builder.wires)) { - parallel_for_range(circuit_builder.num_gates, [&](size_t start, size_t end) { - for (size_t i = start; i < end; i++) { - if (i >= wire_poly.start_index() && i < wire_poly.end_index()) { - wire_poly.at(i) = circuit_builder.get_variable(wire[i]); - } else { - ASSERT(wire[i] == 0); - } - } - }); - } - - // We construct concatenated versions of range constraint polynomials, where several polynomials are concatenated - // into one. These polynomials are not commited to. - bb::compute_concatenated_polynomials(key->polynomials); - - // 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::compute_translator_range_constraint_ordered_polynomials(key->polynomials, mini_circuit_dyadic_size); - - computed_witness = true; -} - -void TranslatorProver::compute_commitment_key(size_t circuit_size) -{ - key->commitment_key = std::make_shared(circuit_size); } /** @@ -68,14 +24,15 @@ void TranslatorProver::compute_commitment_key(size_t circuit_size) */ void TranslatorProver::execute_preamble_round() { - const auto circuit_size = static_cast(key->circuit_size); + const auto circuit_size = static_cast(key->proving_key->circuit_size); const auto SHIFT = uint256_t(1) << Flavor::NUM_LIMB_BITS; const auto SHIFTx2 = uint256_t(1) << (Flavor::NUM_LIMB_BITS * 2); const auto SHIFTx3 = uint256_t(1) << (Flavor::NUM_LIMB_BITS * 3); - const auto accumulated_result = BF(uint256_t(key->polynomials.accumulators_binary_limbs_0[1]) + - uint256_t(key->polynomials.accumulators_binary_limbs_1[1]) * SHIFT + - uint256_t(key->polynomials.accumulators_binary_limbs_2[1]) * SHIFTx2 + - uint256_t(key->polynomials.accumulators_binary_limbs_3[1]) * SHIFTx3); + const auto accumulated_result = + BF(uint256_t(key->proving_key->polynomials.accumulators_binary_limbs_0[1]) + + uint256_t(key->proving_key->polynomials.accumulators_binary_limbs_1[1]) * SHIFT + + uint256_t(key->proving_key->polynomials.accumulators_binary_limbs_2[1]) * SHIFTx2 + + uint256_t(key->proving_key->polynomials.accumulators_binary_limbs_3[1]) * SHIFTx3); transcript->send_to_verifier("circuit_size", circuit_size); transcript->send_to_verifier("evaluation_input_x", key->evaluation_input_x); transcript->send_to_verifier("accumulated_result", accumulated_result); @@ -88,10 +45,10 @@ void TranslatorProver::execute_preamble_round() void TranslatorProver::execute_wire_and_sorted_constraints_commitments_round() { // Commit to all wire polynomials and ordered range constraint polynomials - auto wire_polys = key->polynomials.get_wires_and_ordered_range_constraints(); + auto wire_polys = key->proving_key->polynomials.get_wires_and_ordered_range_constraints(); auto labels = commitment_labels.get_wires_and_ordered_range_constraints(); for (size_t idx = 0; idx < wire_polys.size(); ++idx) { - transcript->send_to_verifier(labels[idx], key->commitment_key->commit(wire_polys[idx])); + transcript->send_to_verifier(labels[idx], key->proving_key->commitment_key->commit(wire_polys[idx])); } } @@ -115,10 +72,10 @@ void TranslatorProver::execute_grand_product_computation_round() uint_evaluation_input.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), uint_evaluation_input }; - relation_parameters.accumulated_result = { key->polynomials.accumulators_binary_limbs_0[1], - key->polynomials.accumulators_binary_limbs_1[1], - key->polynomials.accumulators_binary_limbs_2[1], - key->polynomials.accumulators_binary_limbs_3[1] }; + relation_parameters.accumulated_result = { key->proving_key->polynomials.accumulators_binary_limbs_0[1], + key->proving_key->polynomials.accumulators_binary_limbs_1[1], + key->proving_key->polynomials.accumulators_binary_limbs_2[1], + key->proving_key->polynomials.accumulators_binary_limbs_3[1] }; std::vector uint_batching_challenge_powers; auto batching_challenge_v = key->batching_challenge_v; @@ -140,9 +97,10 @@ void TranslatorProver::execute_grand_product_computation_round() }; } // Compute constraint permutation grand product - compute_grand_products(key->polynomials, relation_parameters); + compute_grand_products(key->proving_key->polynomials, relation_parameters); - transcript->send_to_verifier(commitment_labels.z_perm, key->commitment_key->commit(key->polynomials.z_perm)); + transcript->send_to_verifier(commitment_labels.z_perm, + key->proving_key->commitment_key->commit(key->proving_key->polynomials.z_perm)); } /** @@ -153,7 +111,7 @@ void TranslatorProver::execute_relation_check_rounds() { using Sumcheck = SumcheckProver; - auto sumcheck = Sumcheck(key->circuit_size, transcript); + auto sumcheck = Sumcheck(key->proving_key->circuit_size, transcript); FF alpha = transcript->template get_challenge("Sumcheck:alpha"); std::vector gate_challenges(CONST_PROOF_SIZE_LOG_N); for (size_t idx = 0; idx < gate_challenges.size(); idx++) { @@ -161,9 +119,11 @@ void TranslatorProver::execute_relation_check_rounds() } // // create masking polynomials for sumcheck round univariates and auxiliary data - zk_sumcheck_data = ZKSumcheckData(key->log_circuit_size, transcript, key->commitment_key); + zk_sumcheck_data = + ZKSumcheckData(key->proving_key->log_circuit_size, transcript, key->proving_key->commitment_key); - sumcheck_output = sumcheck.prove(key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); + sumcheck_output = + sumcheck.prove(key->proving_key->polynomials, relation_parameters, alpha, gate_challenges, zk_sumcheck_data); } /** @@ -179,18 +139,18 @@ void TranslatorProver::execute_pcs_rounds() using OpeningClaim = ProverOpeningClaim; const OpeningClaim prover_opening_claim = - ShpleminiProver_::prove(key->circuit_size, - key->polynomials.get_unshifted_without_concatenated(), - key->polynomials.get_to_be_shifted(), + ShpleminiProver_::prove(key->proving_key->circuit_size, + key->proving_key->polynomials.get_unshifted_without_concatenated(), + key->proving_key->polynomials.get_to_be_shifted(), sumcheck_output.challenge, - key->commitment_key, + key->proving_key->commitment_key, transcript, zk_sumcheck_data.libra_univariates_monomial, sumcheck_output.claimed_libra_evaluations, - key->polynomials.get_concatenated(), - key->polynomials.get_groups_to_be_concatenated()); + key->proving_key->polynomials.get_concatenated(), + key->proving_key->polynomials.get_groups_to_be_concatenated()); - PCS::compute_opening_proof(key->commitment_key, prover_opening_claim, transcript); + PCS::compute_opening_proof(key->proving_key->commitment_key, prover_opening_claim, transcript); } HonkProof TranslatorProver::export_proof() diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp index 989596fd02b7..cd7e1d6c4153 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp @@ -4,6 +4,7 @@ #include "barretenberg/sumcheck/sumcheck_output.hpp" #include "barretenberg/sumcheck/zk_sumcheck_data.hpp" #include "barretenberg/translator_vm/translator_flavor.hpp" +#include "barretenberg/translator_vm/translator_proving_key.hpp" namespace bb { @@ -23,17 +24,12 @@ class TranslatorProver { using PCS = typename Flavor::PCS; using Transcript = typename Flavor::Transcript; static constexpr size_t MINIMUM_MINI_CIRCUIT_SIZE = 2048; - bool computed_witness = false; size_t total_num_gates = 0; // num_gates (already include zero row offset) (used to compute dyadic size) size_t dyadic_circuit_size = 0; // final power-of-2 circuit size size_t mini_circuit_dyadic_size = 0; // The size of the small circuit that contains non-range constraint relations - explicit TranslatorProver(CircuitBuilder& circuit_builder, - const std::shared_ptr& transcript, - std::shared_ptr commitment_key = nullptr); - - void compute_witness(CircuitBuilder& circuit_builder); - void compute_commitment_key(size_t circuit_size); + explicit TranslatorProver(std::shared_ptr& key, + const std::shared_ptr& transcript); BB_PROFILE void execute_preamble_round(); BB_PROFILE void execute_wire_and_sorted_constraints_commitments_round(); @@ -47,7 +43,7 @@ class TranslatorProver { bb::RelationParameters relation_parameters; - std::shared_ptr key; + std::shared_ptr key; CommitmentLabels commitment_labels; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp similarity index 57% rename from barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp rename to barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp index bbe394315ad7..9400f0eee466 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -1,38 +1,15 @@ -#pragma once -#include "barretenberg/common/ref_vector.hpp" -#include "barretenberg/common/zip_view.hpp" -#include "barretenberg/relations/relation_parameters.hpp" -#include -#include - +#include "translator_proving_key.hpp" namespace bb { - -/** - * @brief Compute new polynomials which are the concatenated versions of other polynomials - * - * @details Multilinear PCS allow to provide openings for concatenated polynomials in an easy way by combining - * commitments. This method creates concatenated version of polynomials we won't need to commit to. Used in Goblin - * Translator - * - * Concatenation in Translator mean the action of constructing a new Polynomial from existing ones by writing - * their multilinear representations sequentially. For example, if we have f(x₁,x₂)={0, 1, 0, 1} and - * g(x₁,x₂)={1, 0, 0, 1} then h(x₁ ,x₂ ,x₃ )=concatenation(f(x₁,x₂),g(x₁,x₂))={0, 1, 0, 1, 1, 0, 0, 1} - * - * Since we commit to multilinear polynomials with KZG, which treats evaluations as monomial coefficients, in univariate - * form h(x)=f(x)+x⁴⋅g(x)Fr - * @tparam Flavor - * @param proving_key Can be a proving_key or an AllEntities object - */ -template void compute_concatenated_polynomials(typename Flavor::ProverPolynomials& polynomials) +void TranslatorProvingKey::compute_concatenated_polynomials() { // Concatenation groups are vectors of polynomials that are concatenated together - auto concatenation_groups = polynomials.get_groups_to_be_concatenated(); + auto concatenation_groups = proving_key->polynomials.get_groups_to_be_concatenated(); // Resulting concatenated polynomials - auto targets = polynomials.get_concatenated(); + auto targets = proving_key->polynomials.get_concatenated(); - // Targets have to be full-sized polynomials. We can compute the mini circuit size from them by dividing by - // concatenation index + // 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 = 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 @@ -40,7 +17,7 @@ template void compute_concatenated_polynomials(typename Flavor // Translator uses concatenated polynomials in the permutation argument. These polynomials contain the same // coefficients as other shorter polynomials, but we don't have to commit to them due to reusing commitments of // shorter polynomials and updating our PCS to open using them. But the prover still needs the concatenated - // polynomials. This function constructs a chunk of the polynomial. + // proving_key->polynomials. This function constructs a chunk of the polynomial. auto ordering_function = [&](size_t index) { // Get the index of the concatenated polynomial size_t i = index / concatenation_groups[0].size(); @@ -62,32 +39,29 @@ template void compute_concatenated_polynomials(typename Flavor * @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 * @param proving_key */ -template -void compute_translator_range_constraint_ordered_polynomials(typename Flavor::ProverPolynomials& polynomials, - size_t mini_circuit_dyadic_size) +void TranslatorProvingKey::compute_translator_range_constraint_ordered_polynomials() { // Get constants constexpr auto sort_step = Flavor::SORT_STEP; constexpr auto num_concatenated_wires = Flavor::NUM_CONCATENATED_WIRES; - 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 @@ -109,14 +83,14 @@ void compute_translator_range_constraint_ordered_polynomials(typename Flavor::Pr } std::vector> ordered_vectors_uint(num_concatenated_wires); - RefArray ordered_constraint_polynomials{ polynomials.ordered_range_constraints_0, - polynomials.ordered_range_constraints_1, - polynomials.ordered_range_constraints_2, - polynomials.ordered_range_constraints_3 }; + RefArray ordered_constraint_polynomials{ proving_key->polynomials.ordered_range_constraints_0, + proving_key->polynomials.ordered_range_constraints_1, + proving_key->polynomials.ordered_range_constraints_2, + proving_key->polynomials.ordered_range_constraints_3 }; std::vector extra_denominator_uint(full_circuit_size); // Get information which polynomials need to be concatenated - auto concatenation_groups = polynomials.get_groups_to_be_concatenated(); + auto concatenation_groups = proving_key->polynomials.get_groups_to_be_concatenated(); // A function that transfers elements from each of the polynomials in the chosen concatenation group in the uint // ordered polynomials @@ -136,9 +110,9 @@ void compute_translator_range_constraint_ordered_polynomials(typename Flavor::Pr 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; + auto current_offset = j * mini_circuit_dyadic_size; // For each element in the polynomial - for (size_t k = 0; k < mini_circuit_size; k++) { + for (size_t k = 0; k < mini_circuit_dyadic_size; k++) { // Put it it the target polynomial if ((current_offset + k) < free_space_before_runway) { @@ -159,8 +133,8 @@ void compute_translator_range_constraint_ordered_polynomials(typename Flavor::Pr // Sort the polynomial in nondescending order. We sort using vector with size_t elements for 2 reasons: // 1. It is faster to sort size_t - // 2. Comparison operators for finite fields are operating on internal form, so we'd have to convert them from - // Montgomery + // 2. Comparison operators for finite fields are operating on internal form, so we'd have to convert them + // from Montgomery std::sort(current_vector.begin(), current_vector.end()); // Copy the values into the actual polynomial ordered_constraint_polynomials[i].copy_vector(current_vector); @@ -184,7 +158,61 @@ void compute_translator_range_constraint_ordered_polynomials(typename Flavor::Pr #endif // Copy the values into the actual polynomial - polynomials.ordered_range_constraints_4.copy_vector(extra_denominator_uint); + proving_key->polynomials.ordered_range_constraints_4.copy_vector(extra_denominator_uint); } -} // namespace bb +void TranslatorProvingKey::compute_lagrange_polynomials() +{ + + for (size_t i = 1; i < mini_circuit_dyadic_size - 1; i += 2) { + proving_key->polynomials.lagrange_odd_in_minicircuit.at(i) = 1; + proving_key->polynomials.lagrange_even_in_minicircuit.at(i + 1) = 1; + } + proving_key->polynomials.lagrange_second.at(1) = 1; + proving_key->polynomials.lagrange_second_to_last_in_minicircuit.at(mini_circuit_dyadic_size - 2) = 1; +} + +/** + * @brief Compute the extra numerator for Goblin range constraint argument + * + * @details Goblin proves that several polynomials contain only values in a certain range through 2 + * relations: 1) A grand product which ignores positions of elements (TranslatorPermutationRelation) 2) A + * relation enforcing a certain ordering on the elements of the given polynomial + * (TranslatorDeltaRangeConstraintRelation) + * + * We take the values from 4 polynomials, and spread them into 5 polynomials + add all the steps from + * MAX_VALUE to 0. We order these polynomials and use them in the denominator of the grand product, at the + * same time checking that they go from MAX_VALUE to 0. To counteract the added steps we also generate an + * extra range constraint numerator, which contains 5 MAX_VALUE, 5 (MAX_VALUE-STEP),... values + * + */ +void TranslatorProvingKey::compute_extra_range_constraint_numerator() +{ + auto& extra_range_constraint_numerator = proving_key->polynomials.ordered_extra_range_constraints_numerator; + + static constexpr uint32_t MAX_VALUE = (1 << Flavor::MICRO_LIMB_BITS) - 1; + + // Calculate how many elements there are in the sequence MAX_VALUE, MAX_VALUE - 3,...,0 + size_t sorted_elements_count = (MAX_VALUE / Flavor::SORT_STEP) + 1 + (MAX_VALUE % Flavor::SORT_STEP == 0 ? 0 : 1); + + // Check that we can fit every element in the polynomial + ASSERT((Flavor::NUM_CONCATENATED_WIRES + 1) * sorted_elements_count < extra_range_constraint_numerator.size()); + + std::vector sorted_elements(sorted_elements_count); + + // Calculate the sequence in integers + sorted_elements[0] = MAX_VALUE; + for (size_t i = 1; i < sorted_elements_count; i++) { + sorted_elements[i] = (sorted_elements_count - 1 - i) * Flavor::SORT_STEP; + } + + // TODO(#756): can be parallelized further. This will use at most 5 threads + auto fill_with_shift = [&](size_t shift) { + for (size_t i = 0; i < sorted_elements_count; i++) { + extra_range_constraint_numerator.at(shift + i * (Flavor::NUM_CONCATENATED_WIRES + 1)) = sorted_elements[i]; + } + }; + // Fill polynomials with a sequence, where each element is repeated NUM_CONCATENATED_WIRES+1 times + parallel_for(Flavor::NUM_CONCATENATED_WIRES + 1, fill_with_shift); +} +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp new file mode 100644 index 000000000000..5fdc7b7749c5 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -0,0 +1,102 @@ +#pragma once +#include + +#include "barretenberg/translator_vm/translator_flavor.hpp" +namespace bb { +class TranslatorProvingKey { + public: + using Flavor = TranslatorFlavor; + using Circuit = typename Flavor::CircuitBuilder; + using FF = typename Flavor::FF; + using BF = typename Flavor::BF; + using ProvingKey = typename Flavor::ProvingKey; + using Polynomial = typename Flavor::Polynomial; + using CommitmentKey = typename Flavor::CommitmentKey; + + size_t mini_circuit_dyadic_size; + size_t dyadic_circuit_size; + std::shared_ptr proving_key; + + BF batching_challenge_v = { 0 }; + BF evaluation_input_x = { 0 }; + + TranslatorProvingKey() = default; + + TranslatorProvingKey(const Circuit& circuit, std::shared_ptr commitment_key = nullptr) + : mini_circuit_dyadic_size(compute_mini_circuit_dyadic_size(circuit)) + , dyadic_circuit_size(compute_dyadic_circuit_size(circuit)) + , proving_key(std::make_shared(dyadic_circuit_size, std::move(commitment_key))) + , batching_challenge_v(circuit.batching_challenge_v) + , evaluation_input_x(circuit.evaluation_input_x) + { + PROFILE_THIS_NAME("TranslatorProvingKey(TranslatorCircuit&)"); + // Populate the wire polynomials from the wire vectors in the circuit constructor. Note: In goblin translator + // wires + // come as is, since they have to reflect the structure of polynomials in the first 4 wires, which we've + // commited to + for (auto [wire_poly, wire] : zip_view(proving_key->polynomials.get_wires(), circuit.wires)) { + parallel_for_range(circuit.num_gates, [&](size_t start, size_t end) { + for (size_t i = start; i < end; i++) { + if (i >= wire_poly.start_index() && i < wire_poly.end_index()) { + wire_poly.at(i) = circuit.get_variable(wire[i]); + } else { + ASSERT(wire[i] == 0); + } + } + }); + } + + // First and last lagrange polynomials (in the full circuit size) + proving_key->polynomials.lagrange_first.at(0) = 1; + proving_key->polynomials.lagrange_last.at(dyadic_circuit_size - 1) = 1; + + // 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 + compute_lagrange_polynomials(); + + // Compute the numerator for the permutation argument with several repetitions of steps bridging 0 and + // maximum range constraint compute_extra_range_constraint_numerator(); + compute_extra_range_constraint_numerator(); + + // We construct concatenated versions of range constraint polynomials, where several polynomials are + // concatenated + // into one. These polynomials are not commited to. + compute_concatenated_polynomials(); + + // 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. + compute_translator_range_constraint_ordered_polynomials(); + }; + + static inline size_t compute_total_num_gates(const Circuit& circuit) + { + return std::max(circuit.num_gates, Flavor::MINIMUM_MINI_CIRCUIT_SIZE); + } + + static inline size_t compute_dyadic_circuit_size(const Circuit& circuit) + { + const size_t total_num_gates = compute_total_num_gates(circuit); + + // Next power of 2 + const size_t mini_circuit_dyadic_size = circuit.get_circuit_subgroup_size(total_num_gates); + + // The actual circuit size is several times bigger than the trace in the circuit, because we use concatenation + // to bring the degree of relations down, while extending the length. + return mini_circuit_dyadic_size * Flavor::CONCATENATION_GROUP_SIZE; + } + + static inline size_t compute_mini_circuit_dyadic_size(const Circuit& circuit) + { + return circuit.get_circuit_subgroup_size(compute_total_num_gates(circuit)); + } + + void compute_lagrange_polynomials(); + + void compute_extra_range_constraint_numerator(); + + void compute_concatenated_polynomials(); + + void compute_translator_range_constraint_ordered_polynomials(); +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 628d3b0aab1c..8acaa89f7369 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -5,16 +5,12 @@ namespace bb { -TranslatorVerifier::TranslatorVerifier(const std::shared_ptr& verifier_key, +TranslatorVerifier::TranslatorVerifier(const std::shared_ptr& verifier_key, const std::shared_ptr& transcript) : key(verifier_key) , transcript(transcript) {} -TranslatorVerifier::TranslatorVerifier(const std::shared_ptr& proving_key, - const std::shared_ptr& transcript) - : TranslatorVerifier(std::make_shared(proving_key), transcript){}; - void TranslatorVerifier::put_translation_data_in_relation_parameters(const uint256_t& evaluation_input_x, const BF& batching_challenge_v, const uint256_t& accumulated_result) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp index c6b5bf1b1c0c..98e62bc45f12 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp @@ -24,7 +24,6 @@ namespace bb { template class DeciderProvingKey_ { using Circuit = typename Flavor::CircuitBuilder; using ProvingKey = typename Flavor::ProvingKey; - using VerificationKey = typename Flavor::VerificationKey; using CommitmentKey = typename Flavor::CommitmentKey; using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; @@ -61,7 +60,7 @@ template class DeciderProvingKey_ { circuit.finalize_circuit(/* ensure_nonzero = */ true); - // If using a structured trace, set fixed block sizes, check their validity, and set the dyadic circuit size + // If using a structured trace, set fixed block sizes, check their validity, and set the dyadic circuit ci if constexpr (std::same_as) { dyadic_circuit_size = compute_dyadic_size(circuit); // set dyadic size directly from circuit block sizes } else if (std::same_as) { 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 334a7d6e5f02..9169f22a1839 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,3 @@ -#include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/prover.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/prover.cpp index 647e0ccdc8b3..80b993d3f4e3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/prover.cpp @@ -6,7 +6,6 @@ #include "barretenberg/common/constexpr_utils.hpp" #include "barretenberg/common/thread.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" -#include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" From f9bfe44f9125af82501e27a809e4e41d1b8e3ea1 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 19 Dec 2024 14:22:28 +0000 Subject: [PATCH 2/4] cleanup and fix segfault; add modification to avm generated files --- .../cpp/src/barretenberg/goblin/goblin.hpp | 12 ++++--- .../translator_recursive_verifier.test.cpp | 5 +-- .../relation_correctness.test.cpp | 3 +- .../translator_vm/translator_prover.cpp | 2 +- .../translator_vm/translator_prover.hpp | 2 +- .../translator_vm/translator_proving_key.cpp | 35 ++++++++++++++----- .../bb-pil-backend/templates/prover.cpp.hbs | 1 - 7 files changed, 40 insertions(+), 20 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 9693c37a73d8..26c8fc2b0dd9 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -60,14 +60,17 @@ class GoblinProver { bool merge_proof_exists{ false }; std::shared_ptr get_eccvm_proving_key() const { return eccvm_key; } - std::shared_ptr get_translator_proving_key() const { return translator_key; } + std::shared_ptr get_translator_proving_key() const + { + return translator_key->proving_key; + } private: // TODO(https://github.com/AztecProtocol/barretenberg/issues/798) unique_ptr use is a hack std::unique_ptr translator_prover; std::unique_ptr eccvm_prover; std::shared_ptr eccvm_key; - std::shared_ptr translator_key; + std::shared_ptr translator_key; GoblinAccumulationOutput accumulator; // Used only for ACIR methods for now @@ -212,9 +215,8 @@ class GoblinProver { auto translator_builder = std::make_unique(translation_batching_challenge_v, evaluation_challenge_x, op_queue); - auto translator_proving_key = std::make_shared(*translator_builder, commitment_key); - translator_key = translator_proving_key->proving_key; - auto translator_prover = std::make_unique(translator_proving_key, transcript); + translator_key = std::make_shared(*translator_builder, commitment_key); + translator_prover = std::make_unique(translator_key, transcript); } { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp index f09fc8a074ed..05bd7342ce0a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp @@ -123,8 +123,9 @@ template class TranslatorRecursiveTests : public ::te } }; -using FlavorTypes = - testing::Types, TranslatorRecursiveFlavor_>; +using FlavorTypes = testing::Types, + TranslatorRecursiveFlavor_, + TranslatorRecursiveFlavor_>; TYPED_TEST_SUITE(TranslatorRecursiveTests, FlavorTypes); 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 6dd027d1667d..1f3e3392c3bb 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -60,8 +60,8 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) // Create storage for polynomials auto proving_key = std::make_shared(full_circuit_size); TranslatorProvingKey key; - key.mini_circuit_dyadic_size = mini_circuit_size; key.proving_key = proving_key; + key.mini_circuit_dyadic_size = mini_circuit_size; ProverPolynomials& prover_polynomials = proving_key->polynomials; // ensure we can shift these for (Polynomial& prover_poly : prover_polynomials.get_to_be_shifted()) { @@ -272,6 +272,7 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) FF::random_element(), FF::random_element(), FF::random_element(), FF::random_element() }; + // Create storage for polynomials ProverPolynomials prover_polynomials; // We use polynomial ids to make shifting the polynomials easier ProverPolynomialIds prover_polynomial_ids; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 1076d34a2556..3e0485b7ede7 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -7,7 +7,7 @@ namespace bb { -TranslatorProver::TranslatorProver(std::shared_ptr& key, +TranslatorProver::TranslatorProver(const std::shared_ptr& key, const std::shared_ptr& transcript) : transcript(transcript) , key(key) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp index cd7e1d6c4153..357c7aa6a908 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp @@ -28,7 +28,7 @@ class TranslatorProver { size_t dyadic_circuit_size = 0; // final power-of-2 circuit size size_t mini_circuit_dyadic_size = 0; // The size of the small circuit that contains non-range constraint relations - explicit TranslatorProver(std::shared_ptr& key, + explicit TranslatorProver(const std::shared_ptr& key, const std::shared_ptr& transcript); BB_PROFILE void execute_preamble_round(); 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 9400f0eee466..68e48aff80ba 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.cpp @@ -1,5 +1,22 @@ #include "translator_proving_key.hpp" namespace bb { + +/** + * @brief Compute new polynomials which are the concatenated versions of other polynomials + * + * @details Multilinear PCS allow to provide openings for concatenated polynomials in an easy way by combining + * commitments. This method creates concatenated version of polynomials we won't need to commit to. Used in Goblin + * Translator + * + * Concatenation in Translator mean the action of constructing a new Polynomial from existing ones by writing + * their multilinear representations sequentially. For example, if we have f(x₁,x₂)={0, 1, 0, 1} and + * g(x₁,x₂)={1, 0, 0, 1} then h(x₁ ,x₂ ,x₃ )=concatenation(f(x₁,x₂),g(x₁,x₂))={0, 1, 0, 1, 1, 0, 0, 1} + * + * Since we commit to multilinear polynomials with KZG, which treats evaluations as monomial coefficients, in univariate + * form h(x)=f(x)+x⁴⋅g(x)Fr + * @tparam Flavor + * @param proving_key Can be a proving_key or an AllEntities object + */ void TranslatorProvingKey::compute_concatenated_polynomials() { // Concatenation groups are vectors of polynomials that are concatenated together @@ -39,19 +56,19 @@ void TranslatorProvingKey::compute_concatenated_polynomials() * @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/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs index 0a94299e2403..79d8ee68530c 100644 --- a/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs @@ -6,7 +6,6 @@ #include "barretenberg/common/constexpr_utils.hpp" #include "barretenberg/common/thread.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" -#include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" From 98e09455a332c131806ff39905386ddcdea4eba2 Mon Sep 17 00:00:00 2001 From: maramihali Date: Thu, 19 Dec 2024 19:18:22 +0000 Subject: [PATCH 3/4] modifications from PR review --- .../cpp/src/barretenberg/goblin/goblin.hpp | 20 +++++----- .../relation_correctness.test.cpp | 4 +- .../translator_vm/translator_proving_key.hpp | 38 ++++++++++--------- .../ultra_honk/decider_proving_key.hpp | 2 +- 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 26c8fc2b0dd9..b6794f78dae1 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -22,7 +22,7 @@ namespace bb { class GoblinProver { - using MegaCircuitBuilder = bb::MegaCircuitBuilder; + using MegaCircuitBuilder = MegaCircuitBuilder; using Commitment = MegaFlavor::Commitment; using FF = MegaFlavor::FF; @@ -31,18 +31,18 @@ class GoblinProver { using Fr = bb::fr; using Transcript = NativeTranscript; using MegaDeciderProvingKey = DeciderProvingKey_; - using OpQueue = bb::ECCOpQueue; - using ECCVMFlavor = bb::ECCVMFlavor; - using ECCVMBuilder = bb::ECCVMCircuitBuilder; - using ECCVMProver = bb::ECCVMProver; + using OpQueue = ECCOpQueue; + using ECCVMFlavor = ECCVMFlavor; + using ECCVMBuilder = ECCVMCircuitBuilder; + using ECCVMProver = ECCVMProver; using ECCVMProvingKey = ECCVMFlavor::ProvingKey; using TranslationEvaluations = ECCVMProver::TranslationEvaluations; - using TranslatorBuilder = bb::TranslatorCircuitBuilder; - using TranslatorProver = bb::TranslatorProver; - using TranslatorProvingKey = bb::TranslatorProvingKey; - using RecursiveMergeVerifier = bb::stdlib::recursion::goblin::MergeRecursiveVerifier_; + using TranslatorBuilder = TranslatorCircuitBuilder; + using TranslatorProver = TranslatorProver; + using TranslatorProvingKey = TranslatorProvingKey; + using RecursiveMergeVerifier = stdlib::recursion::goblin::MergeRecursiveVerifier_; using PairingPoints = RecursiveMergeVerifier::PairingPoints; - using MergeProver = bb::MergeProver_; + using MergeProver = MergeProver_; using VerificationKey = MegaFlavor::VerificationKey; using MergeProof = std::vector; /** 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 1f3e3392c3bb..292c868f2c0f 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -59,9 +59,7 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) // Create storage for polynomials auto proving_key = std::make_shared(full_circuit_size); - TranslatorProvingKey key; - key.proving_key = proving_key; - key.mini_circuit_dyadic_size = mini_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()) { 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 bb5d4932a5ce..f0ba84f368e2 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_proving_key.hpp @@ -22,14 +22,25 @@ class TranslatorProvingKey { TranslatorProvingKey() = default; + TranslatorProvingKey(std::shared_ptr& proving_key, size_t mini_circuit_dyadic_size) + : mini_circuit_dyadic_size(mini_circuit_dyadic_size) + , dyadic_circuit_size(proving_key->circuit_size) + , proving_key(proving_key) + + { + ASSERT(mini_circuit_dyadic_size * Flavor::CONCATENATION_GROUP_SIZE == dyadic_circuit_size); + } + TranslatorProvingKey(const Circuit& circuit, std::shared_ptr commitment_key = nullptr) - : mini_circuit_dyadic_size(compute_mini_circuit_dyadic_size(circuit)) - , dyadic_circuit_size(compute_dyadic_circuit_size(circuit)) - , proving_key(std::make_shared(dyadic_circuit_size, std::move(commitment_key))) - , batching_challenge_v(circuit.batching_challenge_v) + : batching_challenge_v(circuit.batching_challenge_v) , evaluation_input_x(circuit.evaluation_input_x) { PROFILE_THIS_NAME("TranslatorProvingKey(TranslatorCircuit&)"); + + compute_mini_circuit_dyadic_size(circuit); + compute_dyadic_circuit_size(); + proving_key = std::make_shared(dyadic_circuit_size, std::move(commitment_key)); + // Populate the wire polynomials from the wire vectors in the circuit constructor. Note: In goblin translator // wires // come as is, since they have to reflect the structure of polynomials in the first 4 wires, which we've @@ -71,26 +82,19 @@ class TranslatorProvingKey { compute_translator_range_constraint_ordered_polynomials(); }; - static inline size_t compute_total_num_gates(const Circuit& circuit) + inline void compute_dyadic_circuit_size() { - return std::max(circuit.num_gates, Flavor::MINIMUM_MINI_CIRCUIT_SIZE); - } - - static inline size_t compute_dyadic_circuit_size(const Circuit& circuit) - { - const size_t total_num_gates = compute_total_num_gates(circuit); - - // Next power of 2 - const size_t mini_circuit_dyadic_size = circuit.get_circuit_subgroup_size(total_num_gates); // The actual circuit size is several times bigger than the trace in the circuit, because we use concatenation // to bring the degree of relations down, while extending the length. - return mini_circuit_dyadic_size * Flavor::CONCATENATION_GROUP_SIZE; + dyadic_circuit_size = mini_circuit_dyadic_size * Flavor::CONCATENATION_GROUP_SIZE; } - static inline size_t compute_mini_circuit_dyadic_size(const Circuit& circuit) + inline void compute_mini_circuit_dyadic_size(const Circuit& circuit) { - return circuit.get_circuit_subgroup_size(compute_total_num_gates(circuit)); + 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); } void compute_lagrange_polynomials(); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp index 98e62bc45f12..5da7c7917088 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp @@ -60,7 +60,7 @@ template class DeciderProvingKey_ { circuit.finalize_circuit(/* ensure_nonzero = */ true); - // If using a structured trace, set fixed block sizes, check their validity, and set the dyadic circuit ci + // If using a structured trace, set fixed block sizes, check their validity, and set the dyadic circuit size if constexpr (std::same_as) { dyadic_circuit_size = compute_dyadic_size(circuit); // set dyadic size directly from circuit block sizes } else if (std::same_as) { From 5383e1040c7888ecad88dbd42a33fedcbb1c8c2a Mon Sep 17 00:00:00 2001 From: maramihali Date: Mon, 23 Dec 2024 13:51:51 +0000 Subject: [PATCH 4/4] fix gcc build --- .../cpp/src/barretenberg/goblin/goblin.hpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index b6794f78dae1..be0fab4ad753 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -22,25 +22,20 @@ namespace bb { class GoblinProver { - using MegaCircuitBuilder = MegaCircuitBuilder; using Commitment = MegaFlavor::Commitment; using FF = MegaFlavor::FF; public: - using Builder = MegaCircuitBuilder; + using MegaBuilder = MegaCircuitBuilder; using Fr = bb::fr; using Transcript = NativeTranscript; using MegaDeciderProvingKey = DeciderProvingKey_; using OpQueue = ECCOpQueue; - using ECCVMFlavor = ECCVMFlavor; - using ECCVMBuilder = ECCVMCircuitBuilder; - using ECCVMProver = ECCVMProver; + using ECCVMBuilder = ECCVMFlavor::CircuitBuilder; using ECCVMProvingKey = ECCVMFlavor::ProvingKey; using TranslationEvaluations = ECCVMProver::TranslationEvaluations; using TranslatorBuilder = TranslatorCircuitBuilder; - using TranslatorProver = TranslatorProver; - using TranslatorProvingKey = TranslatorProvingKey; - using RecursiveMergeVerifier = stdlib::recursion::goblin::MergeRecursiveVerifier_; + using RecursiveMergeVerifier = stdlib::recursion::goblin::MergeRecursiveVerifier_; using PairingPoints = RecursiveMergeVerifier::PairingPoints; using MergeProver = MergeProver_; using VerificationKey = MegaFlavor::VerificationKey; @@ -88,7 +83,7 @@ class GoblinProver { * * @param circuit_builder */ - GoblinAccumulationOutput accumulate(MegaCircuitBuilder& circuit_builder) + GoblinAccumulationOutput accumulate(MegaBuilder& circuit_builder) { // Complete the circuit logic by recursively verifying previous merge proof if it exists if (merge_proof_exists) { @@ -121,7 +116,7 @@ class GoblinProver { * * @param circuit_builder */ - void merge(MegaCircuitBuilder& circuit_builder) + void merge(MegaBuilder& circuit_builder) { // Append a recursive merge verification of the merge proof if (merge_proof_exists) { @@ -138,7 +133,7 @@ class GoblinProver { * @param circuit_builder * @return PairingPoints */ - PairingPoints verify_merge(MegaCircuitBuilder& circuit_builder, MergeProof& proof) const + PairingPoints verify_merge(MegaBuilder& circuit_builder, MergeProof& proof) const { PROFILE_THIS_NAME("Goblin::merge"); RecursiveMergeVerifier merge_verifier{ &circuit_builder }; @@ -150,7 +145,7 @@ class GoblinProver { * * @param circuit_builder */ - MergeProof prove_merge(MegaCircuitBuilder& circuit_builder) + MergeProof prove_merge(MegaBuilder& circuit_builder) { PROFILE_THIS_NAME("Goblin::merge"); // TODO(https://github.com/AztecProtocol/barretenberg/issues/993): Some circuits (particularly on the first call