From 379b5adc259ac69b01e61b852172cdfc87cf9350 Mon Sep 17 00:00:00 2001 From: Innokentii Sennovskii Date: Thu, 7 Dec 2023 00:08:40 +0000 Subject: [PATCH] feat: Log-derivative based generic permutations for AVM (#3428) Introduces a relation for constructing generic permutations that needs to be templated for PIL for AVM. Renames lookup_library to logderivative_library --- .../src/barretenberg/eccvm/eccvm_prover.cpp | 4 +- .../cpp/src/barretenberg/flavor/toy_avm.hpp | 376 ++++++++++++++++++ ..._library.hpp => logderivative_library.hpp} | 104 ++++- .../eccvm/eccvm_circuit_builder.hpp | 8 +- .../toy_avm/toy_avm_circuit_builder.hpp | 163 ++++++++ .../toy_avm/toy_avm_circuit_builder.test.cpp | 70 ++++ .../relations/databus_lookup_relation.hpp | 20 +- .../relations/ecc_vm/ecc_lookup_relation.cpp | 4 +- .../relations/ecc_vm/ecc_lookup_relation.hpp | 11 +- .../toy_avm/generic_permutation_relation.cpp | 34 ++ .../toy_avm/generic_permutation_relation.hpp | 210 ++++++++++ .../relations/toy_avm/relation_definer.hpp | 213 ++++++++++ .../sumcheck/instance/prover_instance.cpp | 4 +- .../vm/generated/AvmMini_prover.cpp | 2 +- .../barretenberg/vm/generated/Fib_prover.cpp | 2 +- 15 files changed, 1201 insertions(+), 24 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/flavor/toy_avm.hpp rename barretenberg/cpp/src/barretenberg/honk/proof_system/{lookup_library.hpp => logderivative_library.hpp} (58%) create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.hpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.cpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/toy_avm/relation_definer.hpp diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index f9b9fb6ea46..60b5804a47d 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -2,7 +2,7 @@ #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/common/ref_array.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/honk/proof_system/power_polynomial.hpp" #include "barretenberg/polynomials/polynomial.hpp" @@ -183,7 +183,7 @@ template void ECCVMProver_::execute_log_derivative_ gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr); relation_parameters.eccvm_set_permutation_delta = relation_parameters.eccvm_set_permutation_delta.invert(); // Compute inverse polynomial for our logarithmic-derivative lookup method - lookup_library::compute_logderivative_inverse( + logderivative_library::compute_logderivative_inverse( prover_polynomials, relation_parameters, key->circuit_size); transcript->send_to_verifier(commitment_labels.lookup_inverses, commitment_key->commit(key->lookup_inverses)); prover_polynomials.lookup_inverses = key->lookup_inverses; diff --git a/barretenberg/cpp/src/barretenberg/flavor/toy_avm.hpp b/barretenberg/cpp/src/barretenberg/flavor/toy_avm.hpp new file mode 100644 index 00000000000..ba0c7c2b465 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/flavor/toy_avm.hpp @@ -0,0 +1,376 @@ +#pragma once +#include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/commitment_schemes/kzg/kzg.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/flavor/flavor_macros.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/relations/relation_types.hpp" +#include "barretenberg/relations/toy_avm/generic_permutation_relation.hpp" +#include "barretenberg/relations/toy_avm/relation_definer.hpp" +#include "relation_definitions_fwd.hpp" +#include +#include +#include +#include +#include +#include + +// NOLINTBEGIN(cppcoreguidelines-avoid-const-or-ref-data-members) + +namespace proof_system::honk { +namespace flavor { + +/** + * @brief This class provides an example flavor for using GenericPermutationRelations with various settings to make + * integrating those mechanisms into AVM easier + * + */ +class ToyAVM { + public: + using Curve = curve::BN254; + using FF = Curve::ScalarField; + using GroupElement = Curve::Element; + using Commitment = Curve::AffineElement; + using CommitmentHandle = Curve::AffineElement; + using PCS = pcs::kzg::KZG; + using Polynomial = barretenberg::Polynomial; + using PolynomialHandle = std::span; + using CommitmentKey = pcs::CommitmentKey; + using VerifierCommitmentKey = pcs::VerifierCommitmentKey; + + // The number of wires is 5. The set of tuples (permutation_set_column_1,permutation_set_column_2) should be + // equivalent to (permutation_set_column_3, permutation_set_column_4) and the self_permutation_column contains 2 + // subsets which are permutations of each other + static constexpr size_t NUM_WIRES = 5; + + // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often + // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. + // Note: this number does not include the individual sorted list polynomials. + static constexpr size_t NUM_ALL_ENTITIES = 12; + // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying + // assignment of witnesses. We again choose a neutral name. + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 5; + // The total number of witness entities not including shifts. + static constexpr size_t NUM_WITNESS_ENTITIES = 7; + + // define the tuple of Relations that comprise the Sumcheck relation + using Relations = std::tuple>; + + static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); + + // BATCHED_RELATION_PARTIAL_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` + // random polynomial e.g. For \sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation + // length = 3 + static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1; + static constexpr size_t NUM_RELATIONS = std::tuple_size::value; + + // Instantiate the BarycentricData needed to extend each Relation Univariate + + // define the containers for storing the contributions from each relation in Sumcheck + using SumcheckTupleOfTuplesOfUnivariates = decltype(create_sumcheck_tuple_of_tuples_of_univariates()); + using TupleOfArraysOfValues = decltype(create_tuple_of_arrays_of_values()); + + private: + /** + * @brief A base class labelling precomputed entities and (ordered) subsets of interest. + * @details Used to build the proving key and verification key. + */ + template class PrecomputedEntities : public PrecomputedEntitiesBase { + public: + using DataType = DataType_; + DEFINE_FLAVOR_MEMBERS(DataType, + lagrange_first, // column 0 + enable_tuple_set_permutation, // column 1 + enable_single_column_permutation, // column 2 + enable_first_set_permutation, // column 3 + enable_second_set_permutation) // column 4 + + RefVector get_selectors() + { + return { lagrange_first, + enable_tuple_set_permutation, + enable_single_column_permutation, + enable_first_set_permutation, + enable_second_set_permutation }; + }; + RefVector get_sigma_polynomials() { return {}; }; + RefVector get_id_polynomials() { return {}; }; + RefVector get_table_polynomials() { return {}; }; + }; + + /** + * @brief Container for all witness polynomials used/constructed by the prover. + * @details Shifts are not included here since they do not occupy their own memory. + */ + + template class WitnessEntities { + public: + DEFINE_FLAVOR_MEMBERS(DataType, + permutation_set_column_1, // Column 0 + permutation_set_column_2, // Column 1 + permutation_set_column_3, // Column 2 + permutation_set_column_4, // Column 3 + self_permutation_column, // Column 4 + tuple_permutation_inverses, // Column 5 + single_permutation_inverses) // Column 6 + + RefVector get_wires() + { + return { permutation_set_column_1, + permutation_set_column_2, + permutation_set_column_3, + permutation_set_column_4, + self_permutation_column }; + }; + }; + + /** + * @brief A base class labelling all entities (for instance, all of the polynomials used by the prover during + * sumcheck) in this Honk variant along with particular subsets of interest + * @details Used to build containers for: the prover's polynomial during sumcheck; the sumcheck's folded + * polynomials; the univariates consturcted during during sumcheck; the evaluations produced by sumcheck. + * + * Symbolically we have: AllEntities = PrecomputedEntities + WitnessEntities + "ShiftedEntities". It could be + * implemented as such, but we have this now. + */ + + template class AllEntities { + public: + DEFINE_FLAVOR_MEMBERS(DataType, + lagrange_first, // Column 0 + enable_tuple_set_permutation, // Column 1 + enable_single_column_permutation, // Column 2 + enable_first_set_permutation, // Column 3 + enable_second_set_permutation, // Column 4 + permutation_set_column_1, // Column 5 + permutation_set_column_2, // Column 6 + permutation_set_column_3, // Column 7 + permutation_set_column_4, // Column 8 + self_permutation_column, // Column 9 + tuple_permutation_inverses, // Column 10 + single_permutation_inverses) // Column 11 + + RefVector get_wires() + { + return { + permutation_set_column_1, permutation_set_column_2, permutation_set_column_3, permutation_set_column_4 + }; + }; + RefVector get_unshifted() + { + return { lagrange_first, + enable_tuple_set_permutation, + enable_single_column_permutation, + enable_first_set_permutation, + enable_second_set_permutation, + permutation_set_column_1, + permutation_set_column_2, + permutation_set_column_3, + permutation_set_column_4, + self_permutation_column, + tuple_permutation_inverses, + single_permutation_inverses }; + }; + RefVector get_to_be_shifted() { return {}; }; + RefVector get_shifted() { return {}; }; + }; + + public: + /** + * @brief The proving key is responsible for storing the polynomials used by the prover. + * @note TODO(Cody): Maybe multiple inheritance is the right thing here. In that case, nothing should eve inherit + * from ProvingKey. + */ + class ProvingKey : public ProvingKey_, WitnessEntities> { + public: + // Expose constructors on the base class + using Base = ProvingKey_, WitnessEntities>; + using Base::Base; + + // The plookup wires that store plookup read data. + std::array get_table_column_wires() { return {}; }; + }; + + /** + * @brief The verification key is responsible for storing the the commitments to the precomputed (non-witnessk) + * polynomials used by the verifier. + * + * @note Note the discrepancy with what sort of data is stored here vs in the proving key. We may want to resolve + * that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for portability of our + * circuits. + */ + using VerificationKey = VerificationKey_>; + + /** + * @brief A field element for each entity of the flavor. These entities represent the prover polynomials evaluated + * at one point. + */ + class AllValues : public AllEntities { + public: + using Base = AllEntities; + using Base::Base; + }; + + /** + * @brief An owning container of polynomials. + * @warning When this was introduced it broke some of our design principles. + * - Execution trace builders don't handle "polynomials" because the interpretation of the execution trace + * columns as polynomials is a detail of the proving system, and trace builders are (sometimes in practice, + * always in principle) reusable for different proving protocols (e.g., Plonk and Honk). + * - Polynomial storage is handled by key classes. Polynomials aren't moved, but are accessed elsewhere by + * std::spans. + * + * We will consider revising this data model: TODO(https://github.com/AztecProtocol/barretenberg/issues/743) + */ + class AllPolynomials : public AllEntities { + public: + [[nodiscard]] size_t get_polynomial_size() const { return this->lagrange_first.size(); } + AllValues get_row(const size_t row_idx) const + { + AllValues result; + for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { + result_field = polynomial[row_idx]; + } + return result; + } + }; + /** + * @brief A container for polynomials handles; only stores spans. + */ + class ProverPolynomials : public AllEntities { + public: + [[nodiscard]] size_t get_polynomial_size() const { return enable_tuple_set_permutation.size(); } + [[nodiscard]] AllValues get_row(const size_t row_idx) const + { + AllValues result; + for (auto [result_field, polynomial] : zip_view(result.get_all(), get_all())) { + result_field = polynomial[row_idx]; + } + return result; + } + }; + + /** + * @brief A container for storing the partially evaluated multivariates produced by sumcheck. + */ + class PartiallyEvaluatedMultivariates : public AllEntities { + + public: + PartiallyEvaluatedMultivariates() = default; + PartiallyEvaluatedMultivariates(const size_t circuit_size) + { + // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + for (auto& poly : this->get_all()) { + poly = Polynomial(circuit_size / 2); + } + } + }; + /** + * @brief A container for univariates used during Protogalaxy folding and sumcheck. + * @details During folding and sumcheck, the prover evaluates the relations on these univariates. + */ + template using ProverUnivariates = AllEntities>; + + /** + * @brief A container for univariates produced during the hot loop in sumcheck. + */ + using ExtendedEdges = ProverUnivariates; + + /** + * @brief A container for the witness commitments. + */ + + using WitnessCommitments = WitnessEntities; + + /** + * @brief A container for commitment labels. + * @note It's debatable whether this should inherit from AllEntities. since most entries are not strictly needed. It + * has, however, been useful during debugging to have these labels available. + * + */ + class CommitmentLabels : public AllEntities { + private: + using Base = AllEntities; + + public: + CommitmentLabels() + : AllEntities() + { + Base::permutation_set_column_1 = "PERMUTATION_SET_COLUMN_1"; + Base::permutation_set_column_2 = "PERMUTATION_SET_COLUMN_2"; + Base::permutation_set_column_3 = "PERMUTATION_SET_COLUMN_3"; + Base::permutation_set_column_4 = "PERMUTATION_SET_COLUMN_4"; + Base::self_permutation_column = "SELF_PERMUTATION_COLUMN"; + Base::tuple_permutation_inverses = "TUPLE_PERMUTATION_INVERSES"; + Base::single_permutation_inverses = "SINGLE_PERMUTATION_INVERSES"; + // The ones beginning with "__" are only used for debugging + Base::lagrange_first = "__LAGRANGE_FIRST"; + Base::enable_tuple_set_permutation = "__ENABLE_SET_PERMUTATION"; + Base::enable_single_column_permutation = "__ENABLE_SINGLE_COLUMN_PERMUTATION"; + Base::enable_first_set_permutation = "__ENABLE_FIRST_SET_PERMUTATION"; + Base::enable_second_set_permutation = "__ENABLE_SECOND_SET_PERMUTATION"; + }; + }; + + class VerifierCommitments : public AllEntities { + + public: + VerifierCommitments(const std::shared_ptr& verification_key) + { + lagrange_first = verification_key->lagrange_first; + enable_tuple_set_permutation = verification_key->enable_tuple_set_permutation; + enable_single_column_permutation = verification_key->enable_single_column_permutation; + enable_first_set_permutation = verification_key->enable_first_set_permutation; + enable_second_set_permutation = verification_key->enable_second_set_permutation; + } + }; + + /** + * @brief Derived class that defines proof structure for ECCVM proofs, as well as supporting functions. + * + */ + class Transcript : public BaseTranscript { + public: + uint32_t circuit_size; + Commitment column_0_comm; + Commitment column_1_comm; + Commitment permutation_inverses_comm; + std::vector> sumcheck_univariates; + std::array sumcheck_evaluations; + + std::vector zm_cq_comms; + Commitment zm_cq_comm; + Commitment zm_pi_comm; + + Transcript() = default; + + Transcript(const std::vector& proof) + : BaseTranscript(proof) + {} + + void deserialize_full_transcript() + { + // TODO. Codepath is dead for now, because there is no composer + abort(); + // take current proof and put them into the struct + } + + void serialize_full_transcript() + { + // TODO. Codepath is dead for now, because there is no composer + abort(); + } + }; +}; + +// NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members) + +} // namespace flavor +namespace sumcheck { + +DECLARE_IMPLEMENTATIONS_FOR_ALL_SETTINGS(GenericPermutationRelationImpl, flavor::ToyAVM) + +} // namespace sumcheck +} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp similarity index 58% rename from barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp rename to barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp index 820bc2907a5..4a86cf74075 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp @@ -1,7 +1,7 @@ #pragma once #include -namespace proof_system::honk::lookup_library { +namespace proof_system::honk::logderivative_library { /** * @brief Compute the inverse polynomial I(X) required for logderivative lookups @@ -29,12 +29,12 @@ void compute_logderivative_inverse(Polynomials& polynomials, auto& relation_para using Accumulator = typename Relation::ValueAccumulator0; constexpr size_t READ_TERMS = Relation::READ_TERMS; constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS; - auto& inverse_polynomial = polynomials.lookup_inverses; auto lookup_relation = Relation(); + auto& inverse_polynomial = lookup_relation.template get_inverse_polynomial(polynomials); for (size_t i = 0; i < circuit_size; ++i) { auto row = polynomials.get_row(i); - bool has_inverse = lookup_relation.lookup_exists_at_row(row); + bool has_inverse = lookup_relation.operation_exists_at_row(row); if (!has_inverse) { continue; } @@ -97,7 +97,7 @@ void accumulate_logderivative_lookup_subrelation_contributions(ContainerOverSubr using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; using View = typename Accumulator::View; - auto lookup_inverses = View(in.lookup_inverses); + auto lookup_inverses = View(lookup_relation.template get_inverse_polynomial(in)); constexpr size_t NUM_TOTAL_TERMS = READ_TERMS + WRITE_TERMS; std::array lookup_terms; @@ -153,4 +153,98 @@ void accumulate_logderivative_lookup_subrelation_contributions(ContainerOverSubr }); } -} // namespace proof_system::honk::lookup_library \ No newline at end of file +/** + * @brief Compute generic log-derivative set permutation subrelation accumulation + * @details The generic log-derivative lookup relation consistes of two subrelations. The first demonstrates that the + * inverse polynomial I, defined via I = 1/[(read_term) * (write_term)], has been computed correctly. The second + * establishes the correctness of the permutation itself based on the log-derivative argument. Note that the + * latter subrelation is "linearly dependent" in the sense that it establishes that a sum across all rows of the + * execution trace is zero, rather than that some expression holds independently at each row. Accordingly, this + * subrelation is not multiplied by a scaling factor at each accumulation step. The subrelation expressions are + * respectively: + * + * I * (read_term) * (write_term) - q_{permutation_enabler} = 0 + * + * \sum_{i=0}^{n-1} [q_{write_enabler} * I * write_term + q_{read_enabler} * I * read_term] = 0 + * + * The explicit expressions for read_term and write_term are dependent upon the particular structure of the permutation + * being performed and methods for computing them must be defined in the corresponding relation class. The entities + * which are used to determine the use of permutation (is it enabled, is the first "read" set enabled, is the second + * "write" set enabled) must be defined in the relation class. + * + * @tparam FF + * @tparam Relation + * @tparam ContainerOverSubrelations + * @tparam AllEntities + * @tparam Parameters + * @param accumulator + * @param in + * @param params + * @param scaling_factor + */ +template +void accumulate_logderivative_permutation_subrelation_contributions(ContainerOverSubrelations& accumulator, + const AllEntities& in, + const Parameters& params, + const FF& scaling_factor) +{ + constexpr size_t READ_TERMS = Relation::READ_TERMS; + constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS; + + // For now we only do simple permutations over tuples with 1 read and 1 write term + static_assert(READ_TERMS == 1); + static_assert(WRITE_TERMS == 1); + + auto permutation_relation = Relation(); + + using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + auto permutation_inverses = View(permutation_relation.template get_inverse_polynomial(in)); + + constexpr size_t NUM_TOTAL_TERMS = 2; + std::array permutation_terms; + std::array denominator_accumulator; + + // The permutation relation = 1 / read_term - 1 / write_term + // To get the inverses (1 / read_term), (1 / write_term), we have a commitment to the product ofinver ses + // i.e. permutation_inverses = (1 / read_term) * (1 / write_term) + // The purpose of this next section is to derive individual inverse terms using `permutation_inverses` + // i.e. (1 / read_term) = permutation_inverses * write_term + // (1 / write_term) = permutation_inverses * read_term + permutation_terms[0] = permutation_relation.template compute_read_term(in, params); + permutation_terms[1] = permutation_relation.template compute_write_term(in, params); + + barretenberg::constexpr_for<0, NUM_TOTAL_TERMS, 1>( + [&]() { denominator_accumulator[i] = permutation_terms[i]; }); + + barretenberg::constexpr_for<0, NUM_TOTAL_TERMS - 1, 1>( + [&]() { denominator_accumulator[i + 1] *= denominator_accumulator[i]; }); + + auto inverse_accumulator = Accumulator(permutation_inverses); // denominator_accumulator[NUM_TOTAL_TERMS - 1]; + + const auto inverse_exists = permutation_relation.template compute_inverse_exists(in); + + // Note: the lookup_inverses are computed so that the value is 0 if !inverse_exists + std::get<0>(accumulator) += + (denominator_accumulator[NUM_TOTAL_TERMS - 1] * permutation_inverses - inverse_exists) * scaling_factor; + + // After this algo, total degree of denominator_accumulator = NUM_TOTAL_TERMS + for (size_t i = 0; i < NUM_TOTAL_TERMS - 1; ++i) { + denominator_accumulator[NUM_TOTAL_TERMS - 1 - i] = + denominator_accumulator[NUM_TOTAL_TERMS - 2 - i] * inverse_accumulator; + inverse_accumulator = inverse_accumulator * permutation_terms[NUM_TOTAL_TERMS - 1 - i]; + } + denominator_accumulator[0] = inverse_accumulator; + + // each predicate is degree-1 + // degree of relation at this point = NUM_TOTAL_TERMS + 1 + std::get<1>(accumulator) += + permutation_relation.template compute_read_term_predicate(in) * denominator_accumulator[0]; + + // each predicate is degree-1 + // degree of relation = NUM_TOTAL_TERMS + 1 + std::get<1>(accumulator) -= + permutation_relation.template compute_write_term_predicate(in) * denominator_accumulator[1]; +} +} // namespace proof_system::honk::logderivative_library \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp index 4abbd5bc91f..bdcbd4fa4ad 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp @@ -7,7 +7,7 @@ #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include "barretenberg/flavor/ecc_vm.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/proof_system/op_queue/ecc_op_queue.hpp" #include "barretenberg/relations/relation_parameters.hpp" @@ -505,9 +505,9 @@ template class ECCVMCircuitBuilder { auto polynomials = compute_polynomials(); const size_t num_rows = polynomials.get_polynomial_size(); - proof_system::honk::lookup_library::compute_logderivative_inverse>( - polynomials, params, num_rows); + proof_system::honk::logderivative_library:: + compute_logderivative_inverse>( + polynomials, params, num_rows); honk::permutation_library::compute_permutation_grand_product>( num_rows, polynomials, params); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.hpp new file mode 100644 index 00000000000..659187b4131 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.hpp @@ -0,0 +1,163 @@ +/** + * @file avm_template_circuit_builder.hpp + * @author Rumata888 + * @brief A circuit builder for the AVM toy version used to showcase permutation and lookup mechanisms for PIL + * + */ +#pragma once + +#include "barretenberg/common/constexpr_utils.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/flavor/toy_avm.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/relations/toy_avm/generic_permutation_relation.hpp" + +namespace proof_system { + +/** + * @brief Circuit builder for the ToyAVM that is used to explain generic permutation settings + * + * @tparam Flavor + */ +template class ToyAVMCircuitBuilder { + public: + using FF = typename Flavor::FF; + using Polynomial = typename Flavor::Polynomial; + + static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; + static constexpr size_t NUM_WIRES = Flavor::NUM_WIRES; + + using AllPolynomials = typename Flavor::AllPolynomials; + size_t num_gates = 0; + std::array, NUM_WIRES> wires; + ToyAVMCircuitBuilder() = default; + + void add_row(const std::array row) + { + for (size_t i = 0; i < NUM_WIRES; i++) { + wires[i].emplace_back(row[i]); + } + num_gates = wires[0].size(); + } + + /** + * @brief Compute the AVM Template flavor polynomial data required to generate a proof + * + * @return AllPolynomials + */ + AllPolynomials compute_polynomials() + { + + const auto num_gates_log2 = static_cast(numeric::get_msb64(num_gates)); + size_t num_gates_pow2 = 1UL << (num_gates_log2 + (1UL << num_gates_log2 == num_gates ? 0 : 1)); + + AllPolynomials polys; + for (auto& poly : polys.get_all()) { + poly = Polynomial(num_gates_pow2); + } + + polys.lagrange_first[0] = 1; + + for (size_t i = 0; i < num_gates; ++i) { + // Fill out the witness polynomials + polys.permutation_set_column_1[i] = wires[0][i]; + polys.permutation_set_column_2[i] = wires[1][i]; + polys.permutation_set_column_3[i] = wires[2][i]; + polys.permutation_set_column_4[i] = wires[3][i]; + polys.self_permutation_column[i] = wires[4][i]; + // By default the permutation is over all rows where we place data + polys.enable_tuple_set_permutation[i] = 1; + // The same column permutation alternates between even and odd values + polys.enable_single_column_permutation[i] = 1; + polys.enable_first_set_permutation[i] = i & 1; + polys.enable_second_set_permutation[i] = 1 - (i & 1); + } + return polys; + } + + /** + * @brief Check that the circuit is correct (proof should work) + * + */ + bool check_circuit() + { + // using FirstPermutationRelation = typename std::tuple_element_t<0, Flavor::Relations>; + // For now only gamma and beta are used + const FF gamma = FF::random_element(); + const FF beta = FF::random_element(); + proof_system::RelationParameters params{ + .eta = 0, + .beta = beta, + .gamma = gamma, + .public_input_delta = 0, + .lookup_grand_product_delta = 0, + .beta_sqr = 0, + .beta_cube = 0, + .eccvm_set_permutation_delta = 0, + }; + + // Compute polynomial values + auto polynomials = compute_polynomials(); + const size_t num_rows = polynomials.get_polynomial_size(); + + // Check the tuple permutation relation + proof_system::honk::logderivative_library::compute_logderivative_inverse< + Flavor, + honk::sumcheck::GenericPermutationRelation>( + polynomials, params, num_rows); + + using PermutationRelation = + honk::sumcheck::GenericPermutationRelation; + typename honk::sumcheck::GenericPermutationRelation::SumcheckArrayOfValuesOverSubrelations + permutation_result; + for (auto& r : permutation_result) { + r = 0; + } + for (size_t i = 0; i < num_rows; ++i) { + PermutationRelation::accumulate(permutation_result, polynomials.get_row(i), params, 1); + } + for (auto r : permutation_result) { + if (r != 0) { + info("Tuple GenericPermutationRelation failed."); + return false; + } + } + // Check the single permutation relation + proof_system::honk::logderivative_library::compute_logderivative_inverse< + Flavor, + honk::sumcheck::GenericPermutationRelation>( + polynomials, params, num_rows); + + using SameWirePermutationRelation = + honk::sumcheck::GenericPermutationRelation; + typename honk::sumcheck::GenericPermutationRelation::SumcheckArrayOfValuesOverSubrelations + second_permutation_result; + for (auto& r : second_permutation_result) { + r = 0; + } + for (size_t i = 0; i < num_rows; ++i) { + SameWirePermutationRelation::accumulate(second_permutation_result, polynomials.get_row(i), params, 1); + } + for (auto r : second_permutation_result) { + if (r != 0) { + info("Same wire GenericPermutationRelation failed."); + return false; + } + } + return true; + } + + [[nodiscard]] size_t get_num_gates() const { return num_gates; } + + [[nodiscard]] size_t get_circuit_subgroup_size(const size_t num_rows) const + { + + const auto num_rows_log2 = static_cast(numeric::get_msb64(num_rows)); + size_t num_rows_pow2 = 1UL << (num_rows_log2 + (1UL << num_rows_log2 == num_rows ? 0 : 1)); + return num_rows_pow2; + } +}; +} // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.test.cpp new file mode 100644 index 00000000000..62b2e4d83c3 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.test.cpp @@ -0,0 +1,70 @@ +#include "toy_avm_circuit_builder.hpp" +#include "barretenberg/crypto/generators/generator_data.hpp" +#include + +using namespace barretenberg; + +namespace { +auto& engine = numeric::random::get_debug_engine(); +} + +namespace toy_avm_circuit_builder_tests { + +/** + * @brief A test explaining the work of the permutations in Toy AVM + * + */ +TEST(ToyAVMCircuitBuilder, BaseCase) +{ + + using FF = proof_system::honk::flavor::ToyAVM::FF; + const size_t circuit_size = 16; + proof_system::ToyAVMCircuitBuilder circuit_builder; + + // Sample 2*16 random elements for the tuple permutation example + std::vector column_0; + std::vector column_1; + for (size_t i = 0; i < circuit_size; i++) { + column_0.emplace_back(FF::random_element()); + column_1.emplace_back(FF::random_element()); + } + + // Sample 8 random elements for the single column permutation + std::vector column_2; + for (size_t i = 0; i < circuit_size / 2; i++) { + column_2.emplace_back(FF::random_element()); + } + + for (size_t i = 0; i < circuit_size; i++) { + // We put the same tuple of values in the first 2 wires and in the next 2 to at different rows + // We also put the same value in the self_permutation column in 2 consecutive rows + circuit_builder.add_row({ column_0[i], column_1[i], column_0[15 - i], column_1[15 - i], column_2[i / 2] }); + } + + // Test that permutations with correct values work + bool result = circuit_builder.check_circuit(); + EXPECT_EQ(result, true); + + // Store value temporarily + FF tmp = circuit_builder.wires[0][5]; + + // Replace one of the values in a tuple permutation column with a random one, breaking the permutation + circuit_builder.wires[0][5] = FF::random_element(); + + // Check that it fails + result = circuit_builder.check_circuit(); + EXPECT_EQ(result, false); + + // Restore value + circuit_builder.wires[0][5] = tmp; + + // Check circuit passes + result = circuit_builder.check_circuit(); + EXPECT_EQ(result, true); + + // Break single-column permutation + circuit_builder.wires[circuit_builder.wires.size() - 1][0] = FF::random_element(); + result = circuit_builder.check_circuit(); + EXPECT_EQ(result, false); +} +} // namespace toy_avm_circuit_builder_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp index da659a321e9..5508a72c292 100644 --- a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp @@ -3,7 +3,7 @@ #include #include "barretenberg/common/constexpr_utils.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/relations/relation_types.hpp" @@ -37,11 +37,19 @@ template class DatabusLookupRelationImpl { * @return true * @return false */ - template static bool lookup_exists_at_row(const AllValues& row) + template static bool operation_exists_at_row(const AllValues& row) { return (row.q_busread == 1 || row.calldata_read_counts > 0); } + /** + * @brief Get the lookup inverse polynomial + * + * @tparam AllEntities + * @param in + * @return auto& + */ + template static auto& get_inverse_polynomial(AllEntities& in) { return in.lookup_inverses; } /** * @brief Compute the Accumulator whose values indicate whether the inverse is computed or not * @details This is needed for efficiency since we don't need to compute the inverse unless the log derivative @@ -154,7 +162,7 @@ template class DatabusLookupRelationImpl { /** * @brief Accumulate the contribution from two surelations for the log derivative databus lookup argument - * @details See lookup_library.hpp for details of the generic log-derivative lookup argument + * @details See logderivative_library.hpp for details of the generic log-derivative lookup argument * * @param accumulator transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Accumulator edges. @@ -167,9 +175,9 @@ template class DatabusLookupRelationImpl { const Parameters& params, const FF& scaling_factor) { - honk::lookup_library::accumulate_logderivative_lookup_subrelation_contributions>( - accumulator, in, params, scaling_factor); + honk::logderivative_library:: + accumulate_logderivative_lookup_subrelation_contributions>( + accumulator, in, params, scaling_factor); } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp index 1daf3469bc7..e52e297cfa4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp @@ -1,6 +1,6 @@ #include "barretenberg/flavor/ecc_vm.hpp" #include "barretenberg/flavor/relation_definitions_fwd.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "ecc_msm_relation.hpp" namespace proof_system::honk::sumcheck { @@ -25,7 +25,7 @@ void ECCVMLookupRelationImpl::accumulate(ContainerOverSubrelations& accumula const Parameters& params, const FF& scaling_factor) { - lookup_library::accumulate_logderivative_lookup_subrelation_contributions>( + logderivative_library::accumulate_logderivative_lookup_subrelation_contributions>( accumulator, in, params, scaling_factor); } diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp index 35af59f7490..aa3afffc87f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp @@ -24,12 +24,21 @@ template class ECCVMLookupRelationImpl { static constexpr std::array SUBRELATION_LINEARLY_INDEPENDENT = { true, false }; - template static bool lookup_exists_at_row(const AllValues& row) + template static bool operation_exists_at_row(const AllValues& row) { return (row.msm_add == 1) || (row.msm_skew == 1) || (row.precompute_select == 1); } + /** + * @brief Get the inverse lookup polynomial + * + * @tparam AllEntities + * @param in + * @return auto& + */ + template static auto& get_inverse_polynomial(AllEntities& in) { return in.lookup_inverses; } + template static Accumulator compute_inverse_exists(const AllEntities& in) { diff --git a/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.cpp b/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.cpp new file mode 100644 index 00000000000..1822c388c4e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.cpp @@ -0,0 +1,34 @@ +#include "generic_permutation_relation.hpp" +#include "barretenberg/flavor/relation_definitions_fwd.hpp" +#include "barretenberg/flavor/toy_avm.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" +#include "relation_definer.hpp" + +namespace proof_system::honk::sumcheck { + +/** + * @brief Expression for generic log-derivative-based set permutation. + * @param accumulator transformed to `evals + C(in(X)...)*scaling_factor` + * @param in an std::array containing the fully extended Accumulator edges. + * @param relation_params contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ +template +template +void GenericPermutationRelationImpl::accumulate(ContainerOverSubrelations& accumulator, + const AllEntities& in, + const Parameters& params, + const FF& scaling_factor) +{ + logderivative_library::accumulate_logderivative_permutation_subrelation_contributions< + FF, + GenericPermutationRelationImpl>(accumulator, in, params, scaling_factor); +} + +// template class GenericPermutationRelationImpl; +// template +// using GenericPermutationRelationExampleSettingsImpl = GenericPermutationRelationImpl; DEFINE_SUMCHECK_RELATION_CLASS(GenericPermutationRelationExampleSettingsImpl, flavor::AVMTemplate); + +DEFINE_IMPLEMENTATIONS_FOR_ALL_SETTINGS(GenericPermutationRelationImpl, flavor::ToyAVM); +} // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.hpp new file mode 100644 index 00000000000..d4246a423f5 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.hpp @@ -0,0 +1,210 @@ +/** + * @file generic_permutation_relation.hpp + * @author Rumata888 + * @brief This file contains the template for the generic permutation that can be specialized to enforce various + * permutations (for explanation on how to define them, see "relation_definer.hpp") + * + */ +#pragma once +#include +#include + +#include "barretenberg/common/constexpr_utils.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/relations/relation_types.hpp" + +namespace proof_system::honk::sumcheck { +/** + * @brief Specifies positions of elements in the tuple of entities received from methods in the Settings class + * + */ +enum GenericPermutationSettingIndices { + INVERSE_POLYNOMIAL_INDEX, /* The index of the inverse polynomial*/ + ENABLE_INVERSE_CORRECTNESS_CHECK_POLYNOMIAL_INDEX, /* The index of the polynomial enabling first subrelation*/ + FIRST_PERMUTATION_SET_ENABLE_POLYNOMIAL_INDEX, /* The index of the polynomial that adds an element from the first + set to the sum*/ + SECOND_PERMUTATION_SET_ENABLE_POLYNOMIAL_INDEX, /* The index of the polynomial that adds an element from the second + set to the sum*/ + + PERMUTATION_SETS_START_POLYNOMIAL_INDEX, /* The starting index of the polynomials that are used in the permutation + sets*/ +}; + +template class GenericPermutationRelationImpl { + public: + using FF = FF_; + // Read and write terms counts should stay set to 1 unless we want to permute several columns at once as accumulated + // sets (not as tuples). + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + // 1 + polynomial degree of this relation + static constexpr size_t LENGTH = READ_TERMS + WRITE_TERMS + 3; // 5 + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + LENGTH, // inverse polynomial correctness sub-relation + LENGTH // log-derived terms subrelation + }; + + /** + * @brief We apply the power polynomial only to the first subrelation + * + *@details The first subrelation establishes correspondence between the inverse polynomial elements and the terms. + *The second relation computes the inverses of individual terms, which are then summed up with sumcheck + * + */ + static constexpr std::array SUBRELATION_LINEARLY_INDEPENDENT = { true, false }; + + /** + * @brief Check if we need to compute the inverse polynomial element value for this row + * @details This proxies to a method in the Settings class + * + * @param row All values at row + */ + template static bool operation_exists_at_row(const AllValues& row) + + { + return Settings::inverse_polynomial_is_computed_at_row(row); + } + + /** + * @brief Get the inverse permutation polynomial (needed to compute its value) + * + */ + template static auto& get_inverse_polynomial(AllEntities& in) + { + // WIRE containing the inverse of the product of terms at this row. Used to reconstruct individual inversed + // terms + return std::get(Settings::get_nonconst_entities(in)); + } + + /** + * @brief Get selector/wire switching on(1) or off(0) inverse computation + * + */ + template + static Accumulator compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + + // WIRE/SELECTOR enabling the permutation used in the sumcheck computation. This affects the first subrelation + return Accumulator( + View(std::get(Settings::get_const_entities(in)))); + } + + /** + * @brief Compute if the value from the first set exists in this row + * + * @tparam read_index Kept for compatibility with lookups, behavior doesn't change + */ + template + static Accumulator compute_read_term_predicate(const AllEntities& in) + + { + static_assert(read_index < WRITE_TERMS); + using View = typename Accumulator::View; + + // The selector/wire value that determines that an element from the first set needs to be included. Can be + // different from the wire used in the write part. + return Accumulator( + View(std::get(Settings::get_const_entities(in)))); + } + + /** + * @brief Compute if the value from the second set exists in this row + * + * @tparam write_index Kept for compatibility with lookups, behavior doesn't change + */ + template + static Accumulator compute_write_term_predicate(const AllEntities& in) + { + static_assert(write_index < WRITE_TERMS); + using View = typename Accumulator::View; + + // The selector/wire value that determines that an element from the second set needs to be included. Can be + // different from the wire used in the read part. + return Accumulator( + View(std::get(Settings::get_const_entities(in)))); + } + + /** + * @brief Compute the value of a single item in the set + * + * @details Computes the polynomial \gamma + \sum_{i=0}^{num_columns}(column_i*\beta^i), so the tuple of columns is + * in the first set + * + * @tparam read_index Kept for compatibility with lookups, behavior doesn't change + * + * @param params Used for beta and gamma + */ + template + static Accumulator compute_read_term(const AllEntities& in, const Parameters& params) + { + using View = typename Accumulator::View; + + static_assert(read_index < READ_TERMS); + + // Retrieve all polynomials used + const auto all_polynomials = Settings::get_const_entities(in); + + auto result = Accumulator(0); + + // Iterate over tuple and sum as a polynomial over beta + barretenberg::constexpr_for( + [&]() { result = result * params.beta + View(std::get(all_polynomials)); }); + + const auto& gamma = params.gamma; + return result + gamma; + } + + /** + * @brief Compute the value of a single item in the set + * + * @details Computes the polynomial \gamma + \sum_{i=0}^{num_columns}(column_i*\beta^i), so the tuple of columns is + * in the second set + * + * @tparam write_index Kept for compatibility with lookups, behavior doesn't change + * + * @param params Used for beta and gamma + */ + template + static Accumulator compute_write_term(const AllEntities& in, const Parameters& params) + { + using View = typename Accumulator::View; + + static_assert(write_index < WRITE_TERMS); + + // Get all used entities + const auto& used_entities = Settings::get_const_entities(in); + + auto result = Accumulator(0); + // Iterate over tuple and sum as a polynomial over beta + barretenberg::constexpr_for( + [&]() { result = result * params.beta + View(std::get(used_entities)); }); + + const auto& gamma = params.gamma; + return result + gamma; + } + + /** + * @brief Expression for generic log-derivative-based set permutation. + * @param accumulator transformed to `evals + C(in(X)...)*scaling_factor` + * @param in an std::array containing the fully extended Accumulator edges. + * @param relation_params contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + template + static void accumulate(ContainerOverSubrelations& accumulator, + const AllEntities& in, + const Parameters& params, + const FF& scaling_factor); +}; + +template +using GenericPermutationRelation = Relation>; + +} // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/relations/toy_avm/relation_definer.hpp b/barretenberg/cpp/src/barretenberg/relations/toy_avm/relation_definer.hpp new file mode 100644 index 00000000000..4771c1260b7 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/toy_avm/relation_definer.hpp @@ -0,0 +1,213 @@ +/** + * @file relation_definer.hpp + * @author Rumata888 + * @brief This file contains settings for the General Permutation Relation implementations and (in the future) Lookup + * implementations + * + */ +#pragma once +#include +#include +namespace proof_system::honk::sumcheck { + +/** + * @brief This class contains an example of how to set PermutationSettings classes used by the + * GenericPermutationRelationImpl class to specify a concrete permutation + * + * @details To create your own permutation: + * 1) Create a copy of this class and rename it + * 2) Update all the values with the ones needed for your permutation + * 3) Update "DECLARE_IMPLEMENTATIONS_FOR_ALL_SETTINGS" and "DEFINE_IMPLEMENTATIONS_FOR_ALL_SETTINGS" to include the new + * settings + * 4) Add the relation with the chosen settings to Relations in the flavor (for example,"` + * using Relations = std::tuple>;)` + * + */ +class ExampleTuplePermutationSettings { + public: + // This constant defines how many columns are bundled together to form each set. For example, in this case we are + // bundling tuples of (permutation_set_column_1, permutation_set_column_2) to be a permutation of + // (permutation_set_column_3,permutation_set_column_4). As the tuple has 2 elements, set the value to 2 + constexpr static size_t COLUMNS_PER_SET = 2; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + * + */ + template static inline bool inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.enable_tuple_set_permutation == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple( + in.tuple_permutation_inverses, /* The polynomial containing the inverse product*/ + in.enable_tuple_set_permutation, /* The polynomial enabling the product check subrelation */ + in.enable_tuple_set_permutation, /* Enables adding first set to the sum */ + in.enable_tuple_set_permutation, /* Enables adding second set to the sum */ + in.permutation_set_column_3, /* The first entry in the first set tuple */ + in.permutation_set_column_4, /* The second entry in the first set tuple */ + in.permutation_set_column_1, /* The first entry in the second set tuple */ + in.permutation_set_column_2); /* The second entry in the second set tuple */ + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple( + in.tuple_permutation_inverses, /* The polynomial containing the inverse product*/ + in.enable_tuple_set_permutation, /* The polynomial enabling the product check subrelation */ + in.enable_tuple_set_permutation, /* Enables adding first set to the sum */ + in.enable_tuple_set_permutation, /* Enables adding second set to the sum */ + in.permutation_set_column_3, /* The first entry in the first set tuple */ + in.permutation_set_column_4, /* The second entry in the first set tuple */ + in.permutation_set_column_1, /* The first entry in the second set tuple */ + in.permutation_set_column_2); /* The second entry in the second set tuple */ + } +}; + +/** + * @brief This class contains an example of how to set PermutationSettings classes used by the + * GenericPermutationRelationImpl class to specify a concrete permutation + * + * @details To create your own permutation: + * 1) Create a copy of this class and rename it + * 2) Update all the values with the ones needed for your permutation + * 3) Update "DECLARE_IMPLEMENTATIONS_FOR_ALL_SETTINGS" and "DEFINE_IMPLEMENTATIONS_FOR_ALL_SETTINGS" to include the new + * settings + * 4) Add the relation with the chosen settings to Relations in the flavor (for example,"` + * using Relations = std::tuple>;)` + * + */ +class ExampleSameWirePermutationSettings { + public: + // This constant defines how many columns are bundled together to form each set. For example, in this case we are + // permuting entries in the column with itself (self_permutation_column), so we choose just one + constexpr static size_t COLUMNS_PER_SET = 1; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + * + */ + template static inline bool inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.enable_single_column_permutation == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple( + in.single_permutation_inverses, /* The polynomial containing the inverse product*/ + in.enable_single_column_permutation, /* The polynomial enabling the product check subrelation */ + in.enable_first_set_permutation, /* Enables adding first set to the sum */ + in.enable_second_set_permutation, /* Enables adding second set to the sum */ + in.self_permutation_column, /* The first set column */ + in.self_permutation_column /* The second set column which in this case is the same as the first set column + */ + ); + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple( + in.single_permutation_inverses, /* The polynomial containing the inverse product*/ + in.enable_single_column_permutation, /* The polynomial enabling the product check subrelation */ + in.enable_first_set_permutation, /* Enables adding first set to the sum */ + in.enable_second_set_permutation, /* Enables adding second set to the sum */ + in.self_permutation_column, /* The first set column */ + in.self_permutation_column /* The second set column which in this case is the same as the first set column + */ + ); + } +}; + +#define DEFINE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, Settings) \ + template class RelationImplementation; \ + template using RelationImplementation##Settings = RelationImplementation; \ + DEFINE_SUMCHECK_RELATION_CLASS(RelationImplementation##Settings, flavor); + +#define DEFINE_IMPLEMENTATIONS_FOR_ALL_SETTINGS(RelationImplementation, flavor) \ + DEFINE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, ExampleTuplePermutationSettings); \ + DEFINE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, ExampleSameWirePermutationSettings); + +#define DECLARE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, Settings) \ + extern template class RelationImplementation; \ + template using RelationImplementation##Settings = RelationImplementation; \ + DECLARE_SUMCHECK_RELATION_CLASS(RelationImplementation##Settings, flavor); + +#define DECLARE_IMPLEMENTATIONS_FOR_ALL_SETTINGS(RelationImplementation, flavor) \ + DECLARE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, ExampleTuplePermutationSettings); \ + DECLARE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, ExampleSameWirePermutationSettings); +} // namespace proof_system::honk::sumcheck \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp index 3a62affd0ac..8e1a6ede949 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp @@ -1,5 +1,5 @@ #include "prover_instance.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" #include "barretenberg/proof_system/composer/permutation_lib.hpp" #include "barretenberg/proof_system/library/grand_product_delta.hpp" @@ -453,7 +453,7 @@ void ProverInstance_::compute_logderivative_inverse(FF beta, FF gamma) relation_parameters.gamma = gamma; // Compute permutation and lookup grand product polynomials - lookup_library::compute_logderivative_inverse( + logderivative_library::compute_logderivative_inverse( prover_polynomials, relation_parameters, proving_key->circuit_size); } diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp index 913dc121988..b7daa36ddb3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp @@ -3,7 +3,7 @@ #include "AvmMini_prover.hpp" #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/honk/proof_system/power_polynomial.hpp" #include "barretenberg/polynomials/polynomial.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp index b8cd3fe8907..a5ade6bdf00 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp @@ -3,7 +3,7 @@ #include "Fib_prover.hpp" #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/honk/proof_system/power_polynomial.hpp" #include "barretenberg/polynomials/polynomial.hpp"