diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp index 5c23508a9cc..b8770040beb 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp @@ -59,4 +59,100 @@ void compute_logderivative_inverse(Polynomials& polynomials, FF::batch_invert(inverse_polynomial); } +/** + * @brief Compute generic log-derivative lookup subrelation accumulation + * @details The generic log-derivative lookup relation consistes of two subrelations. The first demonstrates that the + * inverse polynomial I, defined via I_i = 1/[(read_term_i) * (write_term_i)], has been computed correctly. The second + * establishes the correctness of the lookups themselves based on the log-derivative lookup argument. Note that the + * latter subrelation is "linearly dependent" in the sense that it establishes that a sum across all rows of the + * exectution 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_i * (read_term_i) * (write_term_i) - 1 = 0 + * + * \sum_{i=0}^{n-1} [q_{logderiv_lookup} * I_i * write_term_i + read_count_i * I_i * read_term_i] = 0 + * + * The explicit expressions for read_term and write_term are dependent upon the particular structure of the lookup being + * performed and methods for computing them must be defined in the corresponding 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_lookup_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; + + auto lookup_relation = Relation(); + + using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + auto lookup_inverses = View(in.lookup_inverses); + + constexpr size_t NUM_TOTAL_TERMS = READ_TERMS + WRITE_TERMS; + std::array lookup_terms; + std::array denominator_accumulator; + + // The lookup relation = \sum_j (1 / read_term[j]) - \sum_k (read_counts[k] / write_term[k]) + // To get the inverses (1 / read_term[i]), (1 / write_term[i]), we have a commitment to the product of all inverses + // i.e. lookup_inverse = \prod_j (1 / read_term[j]) * \prod_k (1 / write_term[k]) + // The purpose of this next section is to derive individual inverse terms using `lookup_inverses` + // i.e. (1 / read_term[i]) = lookup_inverse * \prod_{j /ne i} (read_term[j]) * \prod_k (write_term[k]) + // (1 / write_term[i]) = lookup_inverse * \prod_j (read_term[j]) * \prod_{k ne i} (write_term[k]) + barretenberg::constexpr_for<0, READ_TERMS, 1>( + [&]() { lookup_terms[i] = lookup_relation.template compute_read_term(in, params); }); + barretenberg::constexpr_for<0, WRITE_TERMS, 1>([&]() { + lookup_terms[i + READ_TERMS] = lookup_relation.template compute_write_term(in, params); + }); + + barretenberg::constexpr_for<0, NUM_TOTAL_TERMS, 1>( + [&]() { denominator_accumulator[i] = lookup_terms[i]; }); + + barretenberg::constexpr_for<0, NUM_TOTAL_TERMS - 1, 1>( + [&]() { denominator_accumulator[i + 1] *= denominator_accumulator[i]; }); + + auto inverse_accumulator = Accumulator(lookup_inverses); // denominator_accumulator[NUM_TOTAL_TERMS - 1]; + + const auto inverse_exists = lookup_relation.template compute_inverse_exists(in); + + std::get<0>(accumulator) += + (denominator_accumulator[NUM_TOTAL_TERMS - 1] * lookup_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 * lookup_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 + barretenberg::constexpr_for<0, READ_TERMS, 1>([&]() { + std::get<1>(accumulator) += + lookup_relation.template compute_read_term_predicate(in) * denominator_accumulator[i]; + }); + + // each predicate is degree-1, `lookup_read_counts` is degree-1 + // degree of relation = NUM_TOTAL_TERMS + 2 + barretenberg::constexpr_for<0, WRITE_TERMS, 1>([&]() { + const auto p = lookup_relation.template compute_write_term_predicate(in); + const auto lookup_read_count = View(in.template lookup_read_counts()); + std::get<1>(accumulator) -= p * (denominator_accumulator[i + READ_TERMS] * lookup_read_count); + }); +} + } // namespace proof_system::honk::lookup_library \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_lookup_relation.cpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_lookup_relation.cpp index 2bca2f74318..23fcaf324f9 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_lookup_relation.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_lookup_relation.cpp @@ -1,5 +1,6 @@ #include "barretenberg/flavor/ecc_vm.hpp" #include "barretenberg/flavor/relation_definitions_fwd.hpp" +#include "barretenberg/honk/proof_system/lookup_library.hpp" #include "ecc_msm_relation.hpp" namespace proof_system::honk::sumcheck { @@ -24,62 +25,8 @@ void ECCVMLookupRelationBase::accumulate(ContainerOverSubrelations& accumula const Parameters& params, [[maybe_unused]] const FF& scaling_factor) { - using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; - using View = typename Accumulator::View; - - auto lookup_inverses = View(in.lookup_inverses); - - constexpr size_t NUM_TOTAL_TERMS = READ_TERMS + WRITE_TERMS; - std::array lookup_terms; - std::array denominator_accumulator; - - // The lookup relation = \sum_j (1 / read_term[j]) - \sum_k (read_counts[k] / write_term[k]) - // To get the inverses (1 / read_term[i]), (1 / write_term[i]), we have a commitment to the product of all inverses - // i.e. lookup_inverse = \prod_j (1 / read_term[j]) * \prod_k (1 / write_term[k]) - // The purpose of this next section is to derive individual inverse terms using `lookup_inverses` - // i.e. (1 / read_term[i]) = lookup_inverse * \prod_{j /ne i} (read_term[j]) * \prod_k (write_term[k]) - // (1 / write_term[i]) = lookup_inverse * \prod_j (read_term[j]) * \prod_{k ne i} (write_term[k]) - barretenberg::constexpr_for<0, READ_TERMS, 1>( - [&]() { lookup_terms[i] = compute_read_term(in, params); }); - barretenberg::constexpr_for<0, WRITE_TERMS, 1>( - [&]() { lookup_terms[i + READ_TERMS] = compute_write_term(in, params); }); - - barretenberg::constexpr_for<0, NUM_TOTAL_TERMS, 1>( - [&]() { denominator_accumulator[i] = lookup_terms[i]; }); - - barretenberg::constexpr_for<0, NUM_TOTAL_TERMS - 1, 1>( - [&]() { denominator_accumulator[i + 1] *= denominator_accumulator[i]; }); - - auto inverse_accumulator = Accumulator(lookup_inverses); // denominator_accumulator[NUM_TOTAL_TERMS - 1]; - - const auto row_has_write = View(in.precompute_select); - const auto row_has_read = View(in.msm_add) + View(in.msm_skew); - const auto inverse_exists = row_has_write + row_has_read - (row_has_write * row_has_read); - - std::get<0>(accumulator) += - (denominator_accumulator[NUM_TOTAL_TERMS - 1] * lookup_inverses - inverse_exists) * scaling_factor; - - // After this algo, total degree of denominator_accumulator = NUM_TOTAL_TERMA - 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 * lookup_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 - barretenberg::constexpr_for<0, READ_TERMS, 1>([&]() { - std::get<1>(accumulator) += compute_read_term_predicate(in) * denominator_accumulator[i]; - }); - - // each predicate is degree-1, `lookup_read_counts` is degree-1 - // degree of relation = NUM_TOTAL_TERMS + 2 = 6 + 2 - barretenberg::constexpr_for<0, WRITE_TERMS, 1>([&]() { - const auto p = compute_write_term_predicate(in); - const auto lookup_read_count = View(in.template lookup_read_counts()); - std::get<1>(accumulator) -= p * (denominator_accumulator[i + READ_TERMS] * lookup_read_count); - }); + lookup_library::accumulate_logderivative_lookup_subrelation_contributions>( + accumulator, in, params, scaling_factor); } template class ECCVMLookupRelationBase; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_lookup_relation.hpp index a59d82936a3..54413e8b244 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/ecc_vm/ecc_lookup_relation.hpp @@ -30,6 +30,16 @@ template class ECCVMLookupRelationBase { return (row.msm_add == 1) || (row.msm_skew == 1) || (row.precompute_select == 1); } + template + static Accumulator compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + + const auto row_has_write = View(in.precompute_select); + const auto row_has_read = View(in.msm_add) + View(in.msm_skew); + return row_has_write + row_has_read - (row_has_write * row_has_read); + } + template static Accumulator compute_read_term_predicate(const AllEntities& in) @@ -209,7 +219,7 @@ template class ECCVMLookupRelationBase { static void accumulate(ContainerOverSubrelations& accumulator, const AllEntities& in, const Parameters& params, - const FF& /*unused*/); + const FF& scaling_factor); }; template using ECCVMLookupRelation = Relation>;