From efe5787260ca575440b54a6ef4a95285390fa75f Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Mon, 12 Jun 2023 15:10:59 -0700 Subject: [PATCH] feat(honk): Shared relation arithmetic (https://github.com/AztecProtocol/barretenberg/pull/514) * a working version of shared relation arithmetic * add RelationWrapper --- .../src/barretenberg/honk/flavor/standard.hpp | 3 - .../relations/arithmetic_relation.hpp | 66 ++-- .../sumcheck/relations/auxiliary_relation.hpp | 323 +++--------------- .../sumcheck/relations/elliptic_relation.hpp | 123 ++----- .../relations/gen_perm_sort_relation.hpp | 104 ++---- .../sumcheck/relations/lookup_relation.hpp | 160 +++------ .../relations/permutation_relation.hpp | 208 ++++------- .../relations/relation_consistency.test.cpp | 8 +- .../sumcheck/relations/relation_types.hpp | 87 +++++ .../relations/ultra_arithmetic_relation.hpp | 103 ++---- .../ultra_relation_consistency.test.cpp | 24 +- .../proof_system/flavor/flavor.hpp | 17 - 12 files changed, 368 insertions(+), 858 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_types.hpp diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp index f777d62fd82..02a7a8a6964 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp @@ -66,9 +66,6 @@ class Standard { using RelationUnivariates = decltype(create_relation_univariates_container()); using RelationValues = decltype(create_relation_values_container()); - // define utilities to extend univarates from RELATION_LENGTH to MAX_RELATION_LENGTH for each Relation - // using BarycentricUtils = decltype(create_barycentric_utils()); - private: /** * @brief A base class labelling precomputed entities and (ordered) subsets of interest. diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp index 1f0349fae5b..e54d14e205f 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp @@ -4,19 +4,17 @@ #include "../polynomials/univariate.hpp" #include "relation_parameters.hpp" +#include "relation_types.hpp" namespace proof_system::honk::sumcheck { -template class ArithmeticRelation { +template class ArithmeticRelationBase { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 4; - static constexpr size_t NUM_CONSTRAINTS = 1; - static constexpr std::array CONSTRAINT_LENGTH = { 4 }; - - using RelationUnivariates = std::tuple>; - using RelationValues = std::array; + static constexpr size_t LEN_1 = 4; // arithmetic sub-relation + using LENGTHS = LengthsWrapper; /** * @brief Expression for the StandardArithmetic gate. @@ -28,55 +26,33 @@ template class ArithmeticRelation { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - void add_edge_contribution(RelationUnivariates& evals, - const auto& extended_edges, - const RelationParameters&, - const FF& scaling_factor) const + template + void static add_edge_contribution_impl(typename TypeMuncher::Accumulators& accumulator, + const auto& extended_edges, + const RelationParameters&, + const FF& scaling_factor) { // OPTIMIZATION?: Karatsuba in general, at least for some degrees? // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both - auto w_l = UnivariateView(extended_edges.w_l); - auto w_r = UnivariateView(extended_edges.w_r); - auto w_o = UnivariateView(extended_edges.w_o); - auto q_m = UnivariateView(extended_edges.q_m); - auto q_l = UnivariateView(extended_edges.q_l); - auto q_r = UnivariateView(extended_edges.q_r); - auto q_o = UnivariateView(extended_edges.q_o); - auto q_c = UnivariateView(extended_edges.q_c); + using View = typename std::tuple_element<0, typename TypeMuncher::AccumulatorViews>::type; + auto w_l = View(extended_edges.w_l); + auto w_r = View(extended_edges.w_r); + auto w_o = View(extended_edges.w_o); + auto q_m = View(extended_edges.q_m); + auto q_l = View(extended_edges.q_l); + auto q_r = View(extended_edges.q_r); + auto q_o = View(extended_edges.q_o); + auto q_c = View(extended_edges.q_c); auto tmp = w_l * (q_m * w_r + q_l); tmp += q_r * w_r; tmp += q_o * w_o; tmp += q_c; tmp *= scaling_factor; - std::get<0>(evals) += tmp; - }; - - /** - * @brief Add the result of each identity in this relation evaluated at the multivariate evaluations produced by the - * Sumcheck Prover. - * - * @param full_honk_relation_value - * @param purported_evaluations - */ - void add_full_relation_value_contribution(RelationValues& full_honk_relation_value, - const auto& purported_evaluations, - const RelationParameters&) const - { - auto w_l = purported_evaluations.w_l; - auto w_r = purported_evaluations.w_r; - auto w_o = purported_evaluations.w_o; - auto q_m = purported_evaluations.q_m; - auto q_l = purported_evaluations.q_l; - auto q_r = purported_evaluations.q_r; - auto q_o = purported_evaluations.q_o; - auto q_c = purported_evaluations.q_c; - - std::get<0>(full_honk_relation_value) += w_l * (q_m * w_r + q_l); - std::get<0>(full_honk_relation_value) += q_r * w_r; - std::get<0>(full_honk_relation_value) += q_o * w_o; - std::get<0>(full_honk_relation_value) += q_c; + std::get<0>(accumulator) += tmp; }; }; + +template using ArithmeticRelation = RelationWrapper; } // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/auxiliary_relation.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/auxiliary_relation.hpp index 890e16326b3..a417bb8e508 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/auxiliary_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/auxiliary_relation.hpp @@ -5,24 +5,22 @@ #include "../polynomials/univariate.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" #include "relation_parameters.hpp" +#include "relation_types.hpp" namespace proof_system::honk::sumcheck { -template class AuxiliaryRelation { +template class AuxiliaryRelationBase { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 6; - static constexpr size_t NUM_CONSTRAINTS = 6; - static constexpr std::array CONSTRAINT_LENGTH = { 6, 6, 6, 6, 6, 6 }; // Each has degree 5 - - using RelationUnivariates = std::tuple, - Univariate, - Univariate, - Univariate, - Univariate, - Univariate>; - using RelationValues = std::array; + static constexpr size_t LEN_1 = 6; // auxiliary sub-relation + static constexpr size_t LEN_2 = 6; // ROM consistency sub-relation 1 + static constexpr size_t LEN_3 = 6; // ROM consistency sub-relation 2 + static constexpr size_t LEN_4 = 6; // RAM consistency sub-relation 1 + static constexpr size_t LEN_5 = 6; // RAM consistency sub-relation 2 + static constexpr size_t LEN_6 = 6; // RAM consistency sub-relation 3 + using LENGTHS = LengthsWrapper; /** * @brief Expression for the generalized permutation sort gate. @@ -58,33 +56,36 @@ template class AuxiliaryRelation { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - void add_edge_contribution(RelationUnivariates& evals, - const auto& extended_edges, - const RelationParameters& relation_parameters, - const FF& scaling_factor) const + template + inline static void add_edge_contribution_impl(typename TypeMuncher::Accumulators& accumulators, + const auto& extended_edges, + const RelationParameters& relation_parameters, + const FF& scaling_factor) { // OPTIMIZATION?: Karatsuba in general, at least for some degrees? // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both const auto& eta = relation_parameters.eta; - auto w_1 = UnivariateView(extended_edges.w_l); - auto w_2 = UnivariateView(extended_edges.w_r); - auto w_3 = UnivariateView(extended_edges.w_o); - auto w_4 = UnivariateView(extended_edges.w_4); - auto w_1_shift = UnivariateView(extended_edges.w_l_shift); - auto w_2_shift = UnivariateView(extended_edges.w_r_shift); - auto w_3_shift = UnivariateView(extended_edges.w_o_shift); - auto w_4_shift = UnivariateView(extended_edges.w_4_shift); - - auto q_1 = UnivariateView(extended_edges.q_l); - auto q_2 = UnivariateView(extended_edges.q_r); - auto q_3 = UnivariateView(extended_edges.q_o); - auto q_4 = UnivariateView(extended_edges.q_4); - auto q_m = UnivariateView(extended_edges.q_m); - auto q_c = UnivariateView(extended_edges.q_c); - auto q_arith = UnivariateView(extended_edges.q_arith); - auto q_aux = UnivariateView(extended_edges.q_aux); + // All subrelations have the same length so we use the same length view for all calculations + using View = typename std::tuple_element<0, typename TypeMuncher::AccumulatorViews>::type; + auto w_1 = View(extended_edges.w_l); + auto w_2 = View(extended_edges.w_r); + auto w_3 = View(extended_edges.w_o); + auto w_4 = View(extended_edges.w_4); + auto w_1_shift = View(extended_edges.w_l_shift); + auto w_2_shift = View(extended_edges.w_r_shift); + auto w_3_shift = View(extended_edges.w_o_shift); + auto w_4_shift = View(extended_edges.w_4_shift); + + auto q_1 = View(extended_edges.q_l); + auto q_2 = View(extended_edges.q_r); + auto q_3 = View(extended_edges.q_o); + auto q_4 = View(extended_edges.q_4); + auto q_m = View(extended_edges.q_m); + auto q_c = View(extended_edges.q_c); + auto q_arith = View(extended_edges.q_arith); + auto q_aux = View(extended_edges.q_aux); const FF LIMB_SIZE(uint256_t(1) << 68); const FF SUBLIMB_SHIFT(uint256_t(1) << 14); @@ -211,8 +212,9 @@ template class AuxiliaryRelation { auto adjacent_values_match_if_adjacent_indices_match = (index_delta * FF(-1) + FF(1)) * record_delta; - std::get<1>(evals) += adjacent_values_match_if_adjacent_indices_match * (q_1 * q_2) * (q_aux * scaling_factor); - std::get<2>(evals) += index_is_monotonically_increasing * (q_1 * q_2) * (q_aux * scaling_factor); + std::get<1>(accumulators) += + adjacent_values_match_if_adjacent_indices_match * (q_1 * q_2) * (q_aux * scaling_factor); + std::get<2>(accumulators) += index_is_monotonically_increasing * (q_1 * q_2) * (q_aux * scaling_factor); auto ROM_consistency_check_identity = memory_record_check * (q_1 * q_2); /** @@ -256,10 +258,11 @@ template class AuxiliaryRelation { auto next_gate_access_type_is_boolean = next_gate_access_type * next_gate_access_type - next_gate_access_type; // Putting it all together... - std::get<3>(evals) += adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation * - (q_arith) * (q_aux * scaling_factor); - std::get<4>(evals) += index_is_monotonically_increasing * (q_arith) * (q_aux * scaling_factor); - std::get<5>(evals) += next_gate_access_type_is_boolean * (q_arith) * (q_aux * scaling_factor); + std::get<3>(accumulators) += + adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation * (q_arith) * + (q_aux * scaling_factor); + std::get<4>(accumulators) += index_is_monotonically_increasing * (q_arith) * (q_aux * scaling_factor); + std::get<5>(accumulators) += next_gate_access_type_is_boolean * (q_arith) * (q_aux * scaling_factor); auto RAM_consistency_check_identity = access_check * (q_arith); /** @@ -287,247 +290,9 @@ template class AuxiliaryRelation { auto auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; auxiliary_identity *= (q_aux * scaling_factor); - std::get<0>(evals) += auxiliary_identity; - }; - - /** - * @brief Add the result of each identity in this relation evaluated at the multivariate evaluations produced by the - * Sumcheck Prover. - * - * @param full_honk_relation_value - * @param purported_evaluations - */ - void add_full_relation_value_contribution(RelationValues& full_honk_relation_value, - const auto& purported_evaluations, - const RelationParameters& relation_parameters) const - { - const auto& eta = relation_parameters.eta; - - auto w_1 = purported_evaluations.w_l; - auto w_2 = purported_evaluations.w_r; - auto w_3 = purported_evaluations.w_o; - auto w_4 = purported_evaluations.w_4; - auto w_1_shift = purported_evaluations.w_l_shift; - auto w_2_shift = purported_evaluations.w_r_shift; - auto w_3_shift = purported_evaluations.w_o_shift; - auto w_4_shift = purported_evaluations.w_4_shift; - - auto q_1 = purported_evaluations.q_l; - auto q_2 = purported_evaluations.q_r; - auto q_3 = purported_evaluations.q_o; - auto q_4 = purported_evaluations.q_4; - auto q_m = purported_evaluations.q_m; - auto q_c = purported_evaluations.q_c; - auto q_arith = purported_evaluations.q_arith; - auto q_aux = purported_evaluations.q_aux; - - constexpr FF LIMB_SIZE(uint256_t(1) << 68); - constexpr FF SUBLIMB_SHIFT(uint256_t(1) << 14); - - /** - * Non native field arithmetic gate 2 - * - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - **/ - auto limb_subproduct = w_1 * w_2_shift + w_1_shift * w_2; - auto non_native_field_gate_2 = (w_1 * w_4 + w_2 * w_3 - w_3_shift); - non_native_field_gate_2 *= LIMB_SIZE; - non_native_field_gate_2 -= w_4_shift; - non_native_field_gate_2 += limb_subproduct; - non_native_field_gate_2 *= q_4; - - limb_subproduct *= LIMB_SIZE; - limb_subproduct += (w_1_shift * w_2_shift); - auto non_native_field_gate_1 = limb_subproduct; - non_native_field_gate_1 -= (w_3 + w_4); - non_native_field_gate_1 *= q_3; - - auto non_native_field_gate_3 = limb_subproduct; - non_native_field_gate_3 += w_4; - non_native_field_gate_3 -= (w_3_shift + w_4_shift); - non_native_field_gate_3 *= q_m; - - auto non_native_field_identity = non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3; - non_native_field_identity *= q_2; - - auto limb_accumulator_1 = w_2_shift; - limb_accumulator_1 *= SUBLIMB_SHIFT; - limb_accumulator_1 += w_1_shift; - limb_accumulator_1 *= SUBLIMB_SHIFT; - limb_accumulator_1 += w_3; - limb_accumulator_1 *= SUBLIMB_SHIFT; - limb_accumulator_1 += w_2; - limb_accumulator_1 *= SUBLIMB_SHIFT; - limb_accumulator_1 += w_1; - limb_accumulator_1 -= w_4; - limb_accumulator_1 *= q_4; - - auto limb_accumulator_2 = w_3_shift; - limb_accumulator_2 *= SUBLIMB_SHIFT; - limb_accumulator_2 += w_2_shift; - limb_accumulator_2 *= SUBLIMB_SHIFT; - limb_accumulator_2 += w_1_shift; - limb_accumulator_2 *= SUBLIMB_SHIFT; - limb_accumulator_2 += w_4; - limb_accumulator_2 *= SUBLIMB_SHIFT; - limb_accumulator_2 += w_3; - limb_accumulator_2 -= w_4_shift; - limb_accumulator_2 *= q_m; - - auto limb_accumulator_identity = limb_accumulator_1 + limb_accumulator_2; - limb_accumulator_identity *= q_3; - - /** - * MEMORY - * - * A RAM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) - * * v: `value` of memory cell being accessed - * * a: `access` type of record. read: 0 = read, 1 = write - * * r: `record` of memory cell. record = access + index * eta + timestamp * eta^2 + value * eta^3 - * - * A ROM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * r: `record` of memory cell. record = index * eta + value2 * eta^2 + value1 * eta^3 - * - * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + - * selectors, depending on whether the gate is a RAM read/write or a ROM read - * - * | gate type | i | v2/t | v | a | r | - * | --------- | -- | ----- | -- | -- | -- | - * | ROM | w1 | w2 | w3 | -- | w4 | - * | RAM | w1 | w2 | w3 | qc | w4 | - * - * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on - * `w2` to fix its value) - * - **/ - - /** - * Memory Record Check - * - * A ROM/ROM access gate can be evaluated with the identity: - * - * qc + w1 \eta + w2 \eta^2 + w3 \eta^3 - w4 = 0 - * - * For ROM gates, qc = 0 - */ - auto memory_record_check = w_3; - memory_record_check *= eta; - memory_record_check += w_2; - memory_record_check *= eta; - memory_record_check += w_1; - memory_record_check *= eta; - memory_record_check += q_c; - auto partial_record_check = memory_record_check; // used in RAM consistency check - memory_record_check = memory_record_check - w_4; - - /** - * ROM Consistency Check - * - * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of - * records that are sorted. - * - * We apply the following checks for the sorted records: - * - * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 - * 2. index values for adjacent records are monotonically increasing - * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} - * - */ - auto index_delta = w_1_shift - w_1; - auto record_delta = w_4_shift - w_4; - - auto index_is_monotonically_increasing = index_delta.sqr() - index_delta; - - auto adjacent_values_match_if_adjacent_indices_match = (FF(1) - index_delta) * record_delta; - - std::get<1>(full_honk_relation_value) += adjacent_values_match_if_adjacent_indices_match * (q_1 * q_2) * q_aux; - std::get<2>(full_honk_relation_value) += index_is_monotonically_increasing * (q_1 * q_2) * q_aux; - auto ROM_consistency_check_identity = memory_record_check * (q_1 * q_2); - - /** - * RAM Consistency Check - * - * The 'access' type of the record is extracted with the expression `w_4 - partial_record_check` - * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. - * This is validated by requiring `access` to be boolean - * - * For two adjacent entries in the sorted list if _both_ - * A) index values match - * B) adjacent access value is 0 (i.e. next gate is a READ) - * then - * C) both values must match. - * The gate boolean check is - * (A && B) => C === !(A && B) || C === !A || !B || C - * - * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized - * with a WRITE operation. - */ - auto access_type = (w_4 - partial_record_check); // will be 0 or 1 for honest Prover - auto access_check = access_type.sqr() - access_type; // check value is 0 or 1 - - // TODO: oof nasty compute here. If we sorted in reverse order we could re-use `partial_record_check` - auto next_gate_access_type = w_3_shift; - next_gate_access_type *= eta; - next_gate_access_type += w_2_shift; - next_gate_access_type *= eta; - next_gate_access_type += w_1_shift; - next_gate_access_type *= eta; - next_gate_access_type = w_4_shift - next_gate_access_type; - - auto value_delta = w_3_shift - w_3; - auto adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = - (FF(1) - index_delta) * value_delta * (FF(1) - next_gate_access_type); - - // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the - // next gate would make the identity fail). - // We need to validate that its 'access type' bool is correct. Can't do - // with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access type is - // correct, to cover this edge case - auto next_gate_access_type_is_boolean = next_gate_access_type.sqr() - next_gate_access_type; - - // Putting it all together... - std::get<3>(full_honk_relation_value) += - adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation * (q_arith)*q_aux; - std::get<4>(full_honk_relation_value) += index_is_monotonically_increasing * (q_arith)*q_aux; - std::get<5>(full_honk_relation_value) += next_gate_access_type_is_boolean * (q_arith)*q_aux; - auto RAM_consistency_check_identity = access_check * (q_arith); - - /** - * RAM Timestamp Consistency Check - * - * | w1 | w2 | w3 | w4 | - * | index | timestamp | timestamp_check | -- | - * - * Let delta_index = index_{i + 1} - index_{i} - * - * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i - * Else timestamp_check = 0 - */ - auto timestamp_delta = w_2_shift - w_2; - auto RAM_timestamp_check_identity = (FF(1) - index_delta) * timestamp_delta - w_3; - - /** - * The complete RAM/ROM memory identity - * - */ - auto memory_identity = ROM_consistency_check_identity; - memory_identity += RAM_timestamp_check_identity * q_1 * q_4; - memory_identity += memory_record_check * q_1 * q_m; - memory_identity += RAM_consistency_check_identity; - - // auto auxiliary_identity = limb_accumulator_identity; - auto auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; - auxiliary_identity *= q_aux; - std::get<0>(full_honk_relation_value) += auxiliary_identity; + std::get<0>(accumulators) += auxiliary_identity; }; }; + +template using AuxiliaryRelation = RelationWrapper; } // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/elliptic_relation.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/elliptic_relation.hpp index f05cacbf5b0..43938221982 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/elliptic_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/elliptic_relation.hpp @@ -4,19 +4,18 @@ #include "../polynomials/univariate.hpp" #include "relation_parameters.hpp" +#include "relation_types.hpp" namespace proof_system::honk::sumcheck { -template class EllipticRelation { +template class EllipticRelationBase { public: // 1 + polynomial degree of this relation - static constexpr size_t RELATION_LENGTH = 5; // degree(q_elliptic * q_beta * x^3) = 5 + static constexpr size_t RELATION_LENGTH = 6; // degree(q_elliptic * q_beta * x^3) = 5 - static constexpr size_t NUM_CONSTRAINTS = 2; - static constexpr std::array CONSTRAINT_LENGTH = { 6, 5 }; - - using RelationUnivariates = std::tuple, Univariate>; - using RelationValues = std::array; + static constexpr size_t LEN_1 = 6; // x-coordinate sub-relation + static constexpr size_t LEN_2 = 5; // y-coordinate sub-relation + using LENGTHS = LengthsWrapper; /** * @brief Expression for the Ultra Arithmetic gate. @@ -28,28 +27,29 @@ template class EllipticRelation { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - void add_edge_contribution(RelationUnivariates& evals, - const auto& extended_edges, - const RelationParameters&, - const FF& scaling_factor) const { + template + static void add_edge_contribution_impl(typename TypeMuncher::Accumulators& accumulators, + const auto& extended_edges, + const RelationParameters&, + const FF& scaling_factor){ // OPTIMIZATION?: Karatsuba in general, at least for some degrees? // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both // TODO(luke): Formatter doesnt properly handle explicit scoping below so turning off. Whats up? // clang-format off // Contribution (1) { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[0]; - auto x_1 = UnivariateView(extended_edges.w_r); - auto y_1 = UnivariateView(extended_edges.w_o); + using View = typename std::tuple_element<0, typename TypeMuncher::AccumulatorViews>::type; + auto x_1 = View(extended_edges.w_r); + auto y_1 = View(extended_edges.w_o); - auto x_2 = UnivariateView(extended_edges.w_l_shift); - auto y_2 = UnivariateView(extended_edges.w_4_shift); - auto x_3 = UnivariateView(extended_edges.w_r_shift); + auto x_2 = View(extended_edges.w_l_shift); + auto y_2 = View(extended_edges.w_4_shift); + auto x_3 = View(extended_edges.w_r_shift); - auto q_sign = UnivariateView(extended_edges.q_l); - auto q_beta = UnivariateView(extended_edges.q_o); - auto q_beta_sqr = UnivariateView(extended_edges.q_4); - auto q_elliptic = UnivariateView(extended_edges.q_elliptic); + auto q_sign = View(extended_edges.q_l); + auto q_beta = View(extended_edges.q_o); + auto q_beta_sqr = View(extended_edges.q_4); + auto q_elliptic = View(extended_edges.q_elliptic); auto beta_term = x_2 * x_1 * (x_3 + x_3 + x_1) * FF(-1); // -x_1 * x_2 * (2 * x_3 + x_1) auto beta_sqr_term = x_2 * x_2; // x_2^2 @@ -68,22 +68,22 @@ template class EllipticRelation { auto x_identity = beta_term + beta_sqr_term + sign_term + leftovers; x_identity *= q_elliptic; x_identity *= scaling_factor; - std::get<0>(evals) += x_identity; + std::get<0>(accumulators) += x_identity; } // Contribution (2) { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[1]; - auto x_1 = UnivariateView(extended_edges.w_r); - auto y_1 = UnivariateView(extended_edges.w_o); + using View = typename std::tuple_element<1, typename TypeMuncher::AccumulatorViews>::type; + auto x_1 = View(extended_edges.w_r); + auto y_1 = View(extended_edges.w_o); - auto x_2 = UnivariateView(extended_edges.w_l_shift); - auto y_2 = UnivariateView(extended_edges.w_4_shift); - auto x_3 = UnivariateView(extended_edges.w_r_shift); - auto y_3 = UnivariateView(extended_edges.w_o_shift); + auto x_2 = View(extended_edges.w_l_shift); + auto y_2 = View(extended_edges.w_4_shift); + auto x_3 = View(extended_edges.w_r_shift); + auto y_3 = View(extended_edges.w_o_shift); - auto q_sign = UnivariateView(extended_edges.q_l); - auto q_beta = UnivariateView(extended_edges.q_o); - auto q_elliptic = UnivariateView(extended_edges.q_elliptic); + auto q_sign = View(extended_edges.q_l); + auto q_beta = View(extended_edges.q_o); + auto q_elliptic = View(extended_edges.q_elliptic); auto beta_term = x_2 * (y_3 + y_1) * q_beta; // β * x_2 * (y_3 + y_1) auto sign_term = y_2 * (x_1 - x_3) * q_sign * FF(-1); // - signt * y_2 * (x_1 - x_3) @@ -93,63 +93,12 @@ template class EllipticRelation { auto y_identity = beta_term + sign_term + leftovers; y_identity *= q_elliptic; y_identity *= scaling_factor; - std::get<1>(evals) += y_identity; + std::get<1>(accumulators) += y_identity; } }; - - /** - * @brief Add the result of each identity in this relation evaluated at the multivariate evaluations produced by the - * Sumcheck Prover. - * - * @param full_honk_relation_value - * @param purported_evaluations - */ - void add_full_relation_value_contribution(RelationValues& full_honk_relation_value, - const auto& purported_evaluations, - const RelationParameters&) const - { - auto x_1 = purported_evaluations.w_r; - auto y_1 = purported_evaluations.w_o; - - auto x_2 = purported_evaluations.w_l_shift; - auto y_2 = purported_evaluations.w_4_shift; - auto x_3 = purported_evaluations.w_r_shift; - auto y_3 = purported_evaluations.w_o_shift; - - auto q_sign = purported_evaluations.q_l; - auto q_beta = purported_evaluations.q_o; - auto q_beta_sqr = purported_evaluations.q_4; - auto q_elliptic = purported_evaluations.q_elliptic; - - // Contribution (1) - auto beta_term = x_2 * x_1 * (x_3 + x_3 + x_1) * FF(-1); // -x_1 * x_2 * (2 * x_3 + x_1) - auto beta_sqr_term = x_2 * x_2; // x_2^2 - auto leftovers = beta_sqr_term; // x_2^2 - beta_sqr_term *= (x_3 - x_1); // x_2^2 * (x_3 - x_1) - auto sign_term = y_2 * y_1; // y_1 * y_2 - sign_term += sign_term; // 2 * y_1 * y_2 - beta_term *= q_beta; // -β * x_1 * x_2 * (2 * x_3 + x_1) - beta_sqr_term *= q_beta_sqr; // β^2 * x_2^2 * (x_3 - x_1) - sign_term *= q_sign; // 2 * y_1 * y_2 * sign - leftovers *= x_2; // x_2^3 - leftovers += x_1 * x_1 * (x_3 + x_1); // x_2^3 + x_1 * (x_3 + x_1) - leftovers -= (y_2 * y_2 + y_1 * y_1); // x_2^3 + x_1 * (x_3 + x_1) - y_2^2 - y_1^2 - - // Can be found in class description - auto x_identity = beta_term + beta_sqr_term + sign_term + leftovers; - x_identity *= q_elliptic; - std::get<0>(full_honk_relation_value) += x_identity; - - // Contribution (2) - beta_term = x_2 * (y_3 + y_1) * q_beta; // β * x_2 * (y_3 + y_1) - sign_term = y_2 * (x_1 - x_3) * q_sign * FF(-1); // - signt * y_2 * (x_1 - x_3) - // TODO: remove extra additions if we decide to stay with this implementation - leftovers = x_1 * (y_3 + y_1) * FF(-1) + y_1 * (x_1 - x_3); // -x_1 * y_3 - x_1 * y_1 + y_1 * x_1 - y_1 * x_3 - - auto y_identity = beta_term + sign_term + leftovers; - y_identity *= q_elliptic; - std::get<1>(full_honk_relation_value) += y_identity; - }; }; + +template +using EllipticRelation = RelationWrapper; // clang-format on } // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/gen_perm_sort_relation.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/gen_perm_sort_relation.hpp index d4649acafaa..394b2968732 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/gen_perm_sort_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/gen_perm_sort_relation.hpp @@ -4,22 +4,20 @@ #include "../polynomials/univariate.hpp" #include "relation_parameters.hpp" +#include "relation_types.hpp" namespace proof_system::honk::sumcheck { -template class GenPermSortRelation { +template class GenPermSortRelationBase { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 6; // degree(q_sort * D(D - 1)(D - 2)(D - 3)) = 5 - static constexpr size_t NUM_CONSTRAINTS = 4; - static constexpr std::array CONSTRAINT_LENGTH = { 6, 6, 6, 6 }; - - using RelationUnivariates = std::tuple, - Univariate, - Univariate, - Univariate>; - using RelationValues = std::array; + static constexpr size_t LEN_1 = 6; // range constrain sub-relation 1 + static constexpr size_t LEN_2 = 6; // range constrain sub-relation 2 + static constexpr size_t LEN_3 = 6; // range constrain sub-relation 3 + static constexpr size_t LEN_4 = 6; // range constrain sub-relation 4 + using LENGTHS = LengthsWrapper; /** * @brief Expression for the generalized permutation sort gate. @@ -36,20 +34,22 @@ template class GenPermSortRelation { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - void add_edge_contribution(RelationUnivariates& evals, - const auto& extended_edges, - const RelationParameters&, - const FF& scaling_factor) const + template + void static add_edge_contribution_impl(typename TypeMuncher::Accumulators& accumulators, + const auto& extended_edges, + const RelationParameters&, + const FF& scaling_factor) { // OPTIMIZATION?: Karatsuba in general, at least for some degrees? // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both - auto w_1 = UnivariateView(extended_edges.w_l); - auto w_2 = UnivariateView(extended_edges.w_r); - auto w_3 = UnivariateView(extended_edges.w_o); - auto w_4 = UnivariateView(extended_edges.w_4); - auto w_1_shift = UnivariateView(extended_edges.w_l_shift); - auto q_sort = UnivariateView(extended_edges.q_sort); + using View = typename std::tuple_element<0, typename TypeMuncher::AccumulatorViews>::type; + auto w_1 = View(extended_edges.w_l); + auto w_2 = View(extended_edges.w_r); + auto w_3 = View(extended_edges.w_o); + auto w_4 = View(extended_edges.w_4); + auto w_1_shift = View(extended_edges.w_l_shift); + auto q_sort = View(extended_edges.q_sort); static const FF minus_one = FF(-1); static const FF minus_two = FF(-2); @@ -68,7 +68,7 @@ template class GenPermSortRelation { tmp_1 *= (delta_1 + minus_three); tmp_1 *= q_sort; tmp_1 *= scaling_factor; - std::get<0>(evals) += tmp_1; + std::get<0>(accumulators) += tmp_1; // Contribution (2) auto tmp_2 = delta_2; @@ -77,7 +77,7 @@ template class GenPermSortRelation { tmp_2 *= (delta_2 + minus_three); tmp_2 *= q_sort; tmp_2 *= scaling_factor; - std::get<1>(evals) += tmp_2; + std::get<1>(accumulators) += tmp_2; // Contribution (3) auto tmp_3 = delta_3; @@ -86,7 +86,7 @@ template class GenPermSortRelation { tmp_3 *= (delta_3 + minus_three); tmp_3 *= q_sort; tmp_3 *= scaling_factor; - std::get<2>(evals) += tmp_3; + std::get<2>(accumulators) += tmp_3; // Contribution (4) auto tmp_4 = delta_4; @@ -95,64 +95,10 @@ template class GenPermSortRelation { tmp_4 *= (delta_4 + minus_three); tmp_4 *= q_sort; tmp_4 *= scaling_factor; - std::get<3>(evals) += tmp_4; + std::get<3>(accumulators) += tmp_4; }; +}; - /** - * @brief Add the result of each identity in this relation evaluated at the multivariate evaluations produced by the - * Sumcheck Prover. - * - * @param full_honk_relation_value - * @param purported_evaluations - */ - void add_full_relation_value_contribution(RelationValues& full_honk_relation_value, - const auto& purported_evaluations, - const RelationParameters&) const - { - auto w_1 = purported_evaluations.w_l; - auto w_2 = purported_evaluations.w_r; - auto w_3 = purported_evaluations.w_o; - auto w_4 = purported_evaluations.w_4; - auto w_1_shift = purported_evaluations.w_l_shift; - auto q_sort = purported_evaluations.q_sort; - - static const FF minus_one = FF(-1); - static const FF minus_two = FF(-2); - static const FF minus_three = FF(-3); - - // Compute wire differences - auto delta_1 = w_2 - w_1; - auto delta_2 = w_3 - w_2; - auto delta_3 = w_4 - w_3; - auto delta_4 = w_1_shift - w_4; - - auto tmp_1 = delta_1; - tmp_1 *= (delta_1 + minus_one); - tmp_1 *= (delta_1 + minus_two); - tmp_1 *= (delta_1 + minus_three); - tmp_1 *= q_sort; - std::get<0>(full_honk_relation_value) += tmp_1; - - auto tmp_2 = delta_2; - tmp_2 *= (delta_2 + minus_one); - tmp_2 *= (delta_2 + minus_two); - tmp_2 *= (delta_2 + minus_three); - tmp_2 *= q_sort; - std::get<1>(full_honk_relation_value) += tmp_2; - - auto tmp_3 = delta_3; - tmp_3 *= (delta_3 + minus_one); - tmp_3 *= (delta_3 + minus_two); - tmp_3 *= (delta_3 + minus_three); - tmp_3 *= q_sort; - std::get<2>(full_honk_relation_value) += tmp_3; +template using GenPermSortRelation = RelationWrapper; - auto tmp_4 = delta_4; - tmp_4 *= (delta_4 + minus_one); - tmp_4 *= (delta_4 + minus_two); - tmp_4 *= (delta_4 + minus_three); - tmp_4 *= q_sort; - std::get<3>(full_honk_relation_value) += tmp_4; - }; -}; } // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/lookup_relation.hpp index b08a2bdeddb..e4f320db2cf 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/lookup_relation.hpp @@ -1,22 +1,21 @@ #pragma once #include "relation_parameters.hpp" #include "../polynomials/univariate.hpp" +#include "relation_types.hpp" #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wunused-parameter" namespace proof_system::honk::sumcheck { -template class LookupRelation { +template class LookupRelationBase { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 6; // deg(z_lookup * column_selector * wire * q_lookup * table) = 5 - static constexpr size_t NUM_CONSTRAINTS = 2; - static constexpr std::array CONSTRAINT_LENGTH = { 6, 3 }; - - using RelationUnivariates = std::tuple, Univariate>; - using RelationValues = std::array; + static constexpr size_t LEN_1 = 6; // grand product construction sub-relation + static constexpr size_t LEN_2 = 3; // left-shiftable polynomial sub-relation + using LENGTHS = LengthsWrapper; /** * @brief Compute contribution of the lookup grand prod relation for a given edge (internal function) @@ -36,10 +35,11 @@ template class LookupRelation { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - inline void add_edge_contribution(RelationUnivariates& evals, - const auto& extended_edges, - const RelationParameters& relation_parameters, - const FF& scaling_factor) const + template + inline static void add_edge_contribution_impl(typename TypeMuncher::Accumulators& accumulators, + const auto& extended_edges, + const RelationParameters& relation_parameters, + const FF& scaling_factor) { const auto& eta = relation_parameters.eta; const auto& beta = relation_parameters.beta; @@ -53,39 +53,39 @@ template class LookupRelation { // Contribution (1) { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[0]; - auto w_1 = UnivariateView(extended_edges.w_l); - auto w_2 = UnivariateView(extended_edges.w_r); - auto w_3 = UnivariateView(extended_edges.w_o); + using View = typename std::tuple_element<0, typename TypeMuncher::AccumulatorViews>::type; + auto w_1 = View(extended_edges.w_l); + auto w_2 = View(extended_edges.w_r); + auto w_3 = View(extended_edges.w_o); - auto w_1_shift = UnivariateView(extended_edges.w_l_shift); - auto w_2_shift = UnivariateView(extended_edges.w_r_shift); - auto w_3_shift = UnivariateView(extended_edges.w_o_shift); + auto w_1_shift = View(extended_edges.w_l_shift); + auto w_2_shift = View(extended_edges.w_r_shift); + auto w_3_shift = View(extended_edges.w_o_shift); - auto table_1 = UnivariateView(extended_edges.table_1); - auto table_2 = UnivariateView(extended_edges.table_2); - auto table_3 = UnivariateView(extended_edges.table_3); - auto table_4 = UnivariateView(extended_edges.table_4); + auto table_1 = View(extended_edges.table_1); + auto table_2 = View(extended_edges.table_2); + auto table_3 = View(extended_edges.table_3); + auto table_4 = View(extended_edges.table_4); - auto table_1_shift = UnivariateView(extended_edges.table_1_shift); - auto table_2_shift = UnivariateView(extended_edges.table_2_shift); - auto table_3_shift = UnivariateView(extended_edges.table_3_shift); - auto table_4_shift = UnivariateView(extended_edges.table_4_shift); + auto table_1_shift = View(extended_edges.table_1_shift); + auto table_2_shift = View(extended_edges.table_2_shift); + auto table_3_shift = View(extended_edges.table_3_shift); + auto table_4_shift = View(extended_edges.table_4_shift); - auto s_accum = UnivariateView(extended_edges.sorted_accum); - auto s_accum_shift = UnivariateView(extended_edges.sorted_accum_shift); + auto s_accum = View(extended_edges.sorted_accum); + auto s_accum_shift = View(extended_edges.sorted_accum_shift); - auto z_lookup = UnivariateView(extended_edges.z_lookup); - auto z_lookup_shift = UnivariateView(extended_edges.z_lookup_shift); + auto z_lookup = View(extended_edges.z_lookup); + auto z_lookup_shift = View(extended_edges.z_lookup_shift); - auto table_index = UnivariateView(extended_edges.q_o); - auto column_1_step_size = UnivariateView(extended_edges.q_r); - auto column_2_step_size = UnivariateView(extended_edges.q_m); - auto column_3_step_size = UnivariateView(extended_edges.q_c); - auto q_lookup = UnivariateView(extended_edges.q_lookup); + auto table_index = View(extended_edges.q_o); + auto column_1_step_size = View(extended_edges.q_r); + auto column_2_step_size = View(extended_edges.q_m); + auto column_3_step_size = View(extended_edges.q_c); + auto q_lookup = View(extended_edges.q_lookup); - auto lagrange_first = UnivariateView(extended_edges.lagrange_first); - auto lagrange_last = UnivariateView(extended_edges.lagrange_last); + auto lagrange_first = View(extended_edges.lagrange_first); + auto lagrange_last = View(extended_edges.lagrange_last); // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η²(w_3 + q_c*w_3_shift) + η³q_index. auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + @@ -103,93 +103,19 @@ template class LookupRelation { tmp *= (z_lookup + lagrange_first); tmp -= (z_lookup_shift + lagrange_last * grand_product_delta) * (s_accum + s_accum_shift * beta + gamma_by_one_plus_beta); - std::get<0>(evals) += tmp * scaling_factor; + std::get<0>(accumulators) += tmp * scaling_factor; } { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[1]; - auto z_lookup_shift = UnivariateView(extended_edges.z_lookup_shift); - auto lagrange_last = UnivariateView(extended_edges.lagrange_last); + using View = typename std::tuple_element<1, typename TypeMuncher::AccumulatorViews>::type; + auto z_lookup_shift = View(extended_edges.z_lookup_shift); + auto lagrange_last = View(extended_edges.lagrange_last); // Contribution (2) - std::get<1>(evals) += (lagrange_last * z_lookup_shift) * scaling_factor; + std::get<1>(accumulators) += (lagrange_last * z_lookup_shift) * scaling_factor; } }; +}; - /** - * @brief Add the result of each identity in this relation evaluated at the multivariate evaluations produced by the - * Sumcheck Prover. - * - * @param full_honk_relation_value - * @param purported_evaluations - */ - void add_full_relation_value_contribution(RelationValues& full_honk_relation_value, - auto& purported_evaluations, - const RelationParameters& relation_parameters) const - { - const auto& eta = relation_parameters.eta; - const auto& beta = relation_parameters.beta; - const auto& gamma = relation_parameters.gamma; - const auto& grand_product_delta = relation_parameters.lookup_grand_product_delta; - - const auto one_plus_beta = FF::one() + beta; - const auto gamma_by_one_plus_beta = gamma * one_plus_beta; - const auto eta_sqr = eta * eta; - const auto eta_cube = eta_sqr * eta; - - auto w_1 = purported_evaluations.w_l; - auto w_2 = purported_evaluations.w_r; - auto w_3 = purported_evaluations.w_o; - - auto w_1_shift = purported_evaluations.w_l_shift; - auto w_2_shift = purported_evaluations.w_r_shift; - auto w_3_shift = purported_evaluations.w_o_shift; - - auto table_1 = purported_evaluations.table_1; - auto table_2 = purported_evaluations.table_2; - auto table_3 = purported_evaluations.table_3; - auto table_4 = purported_evaluations.table_4; - - auto table_1_shift = purported_evaluations.table_1_shift; - auto table_2_shift = purported_evaluations.table_2_shift; - auto table_3_shift = purported_evaluations.table_3_shift; - auto table_4_shift = purported_evaluations.table_4_shift; - - auto s_accum = purported_evaluations.sorted_accum; - auto s_accum_shift = purported_evaluations.sorted_accum_shift; - - auto z_lookup = purported_evaluations.z_lookup; - auto z_lookup_shift = purported_evaluations.z_lookup_shift; - - auto table_index = purported_evaluations.q_o; - auto column_1_step_size = purported_evaluations.q_r; - auto column_2_step_size = purported_evaluations.q_m; - auto column_3_step_size = purported_evaluations.q_c; - auto q_lookup = purported_evaluations.q_lookup; - - auto lagrange_first = purported_evaluations.lagrange_first; - auto lagrange_last = purported_evaluations.lagrange_last; - - // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η²(w_3 + q_c*w_3_shift) + η³q_index. - auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + - (w_3 + column_3_step_size * w_3_shift) * eta_sqr + table_index * eta_cube; - - // t_1 + ηt_2 + η²t_3 + η³t_4 - auto table_accum = table_1 + table_2 * eta + table_3 * eta_sqr + table_4 * eta_cube; - // t_1_shift + ηt_2_shift + η²t_3_shift + η³t_4_shift - auto table_accum_shift = - table_1_shift + table_2_shift * eta + table_3_shift * eta_sqr + table_4_shift * eta_cube; +template using LookupRelation = RelationWrapper; - // Contribution (1) - auto tmp = (q_lookup * wire_accum + gamma); - tmp *= (table_accum + beta * table_accum_shift + gamma_by_one_plus_beta); - tmp *= one_plus_beta; - tmp *= (z_lookup + lagrange_first); - tmp -= (z_lookup_shift + lagrange_last * grand_product_delta) * - (s_accum + beta * s_accum_shift + gamma_by_one_plus_beta); - std::get<0>(full_honk_relation_value) += tmp; - - // Contribution (2) - std::get<1>(full_honk_relation_value) += lagrange_last * z_lookup_shift; - }; -}; } // namespace proof_system::honk::sumcheck \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/permutation_relation.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/permutation_relation.hpp index f613f0c3b6b..126630ddbd3 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/permutation_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/permutation_relation.hpp @@ -1,20 +1,19 @@ #pragma once #include "relation_parameters.hpp" #include "../polynomials/univariate.hpp" +#include "relation_types.hpp" // TODO(luke): change name of this file to permutation_grand_product_relation(s).hpp and move 'init' relation into it. namespace proof_system::honk::sumcheck { -template class PermutationRelation { +template class PermutationRelationBase { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 5; - static constexpr size_t NUM_CONSTRAINTS = 2; - static constexpr std::array CONSTRAINT_LENGTH = { 5, 3 }; - - using RelationUnivariates = std::tuple, Univariate>; - using RelationValues = std::array; + static constexpr size_t LEN_1 = 5; // grand product construction sub-relation + static constexpr size_t LEN_2 = 3; // left-shiftable polynomial sub-relation + using LENGTHS = LengthsWrapper; /** * @brief Compute contribution of the permutation relation for a given edge (internal function) @@ -34,33 +33,34 @@ template class PermutationRelation { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - inline void add_edge_contribution(RelationUnivariates& evals, - const auto& extended_edges, - const RelationParameters& relation_parameters, - const FF& scaling_factor) const + template + inline static void add_edge_contribution_impl(typename TypeMuncher::Accumulators& accumulator, + const auto& input, + const RelationParameters& relation_parameters, + const FF& scaling_factor) { const auto& beta = relation_parameters.beta; const auto& gamma = relation_parameters.gamma; const auto& public_input_delta = relation_parameters.public_input_delta; { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[0]; - auto w_1 = UnivariateView(extended_edges.w_l); - auto w_2 = UnivariateView(extended_edges.w_r); - auto w_3 = UnivariateView(extended_edges.w_o); - auto sigma_1 = UnivariateView(extended_edges.sigma_1); - auto sigma_2 = UnivariateView(extended_edges.sigma_2); - auto sigma_3 = UnivariateView(extended_edges.sigma_3); - auto id_1 = UnivariateView(extended_edges.id_1); - auto id_2 = UnivariateView(extended_edges.id_2); - auto id_3 = UnivariateView(extended_edges.id_3); - auto z_perm = UnivariateView(extended_edges.z_perm); - auto z_perm_shift = UnivariateView(extended_edges.z_perm_shift); - auto lagrange_first = UnivariateView(extended_edges.lagrange_first); - auto lagrange_last = UnivariateView(extended_edges.lagrange_last); + using View = typename std::tuple_element<0, typename TypeMuncher::AccumulatorViews>::type; + auto w_1 = View(input.w_l); + auto w_2 = View(input.w_r); + auto w_3 = View(input.w_o); + auto sigma_1 = View(input.sigma_1); + auto sigma_2 = View(input.sigma_2); + auto sigma_3 = View(input.sigma_3); + auto id_1 = View(input.id_1); + auto id_2 = View(input.id_2); + auto id_3 = View(input.id_3); + auto z_perm = View(input.z_perm); + auto z_perm_shift = View(input.z_perm_shift); + auto lagrange_first = View(input.lagrange_first); + auto lagrange_last = View(input.lagrange_last); // Contribution (1) - std::get<0>(evals) += + std::get<0>(accumulator) += (((z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * (w_3 + id_3 * beta + gamma)) - ((z_perm_shift + lagrange_last * public_input_delta) * (w_1 + sigma_1 * beta + gamma) * @@ -68,68 +68,26 @@ template class PermutationRelation { scaling_factor; } { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[1]; - auto z_perm_shift = UnivariateView(extended_edges.z_perm_shift); - auto lagrange_last = UnivariateView(extended_edges.lagrange_last); + using View = typename std::tuple_element<1, typename TypeMuncher::AccumulatorViews>::type; + auto z_perm_shift = View(input.z_perm_shift); + auto lagrange_last = View(input.lagrange_last); // Contribution (2) - std::get<1>(evals) += (lagrange_last * z_perm_shift) * scaling_factor; + std::get<1>(accumulator) += (lagrange_last * z_perm_shift) * scaling_factor; } }; - - /** - * @brief Add the result of each identity in this relation evaluated at the multivariate evaluations produced by the - * Sumcheck Prover. - * - * @param full_honk_relation_value - * @param purported_evaluations - */ - void add_full_relation_value_contribution(RelationValues& full_honk_relation_value, - auto& purported_evaluations, - const RelationParameters& relation_parameters) const - { - const auto& beta = relation_parameters.beta; - const auto& gamma = relation_parameters.gamma; - const auto& public_input_delta = relation_parameters.public_input_delta; - - auto w_1 = purported_evaluations.w_l; - auto w_2 = purported_evaluations.w_r; - auto w_3 = purported_evaluations.w_o; - auto sigma_1 = purported_evaluations.sigma_1; - auto sigma_2 = purported_evaluations.sigma_2; - auto sigma_3 = purported_evaluations.sigma_3; - auto id_1 = purported_evaluations.id_1; - auto id_2 = purported_evaluations.id_2; - auto id_3 = purported_evaluations.id_3; - auto z_perm = purported_evaluations.z_perm; - auto z_perm_shift = purported_evaluations.z_perm_shift; - auto lagrange_first = purported_evaluations.lagrange_first; - auto lagrange_last = purported_evaluations.lagrange_last; - - // Contribution (1) - std::get<0>(full_honk_relation_value) += - ((z_perm + lagrange_first) * (w_1 + beta * id_1 + gamma) * (w_2 + beta * id_2 + gamma) * - (w_3 + beta * id_3 + gamma) - - (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + beta * sigma_1 + gamma) * - (w_2 + beta * sigma_2 + gamma) * (w_3 + beta * sigma_3 + gamma)); - - // Contribution (2) - std::get<1>(full_honk_relation_value) += lagrange_last * z_perm_shift; - }; }; // TODO(luke): With Cody's Flavor work it should be easier to create a simple templated relation // for handling arbitrary width. For now I'm duplicating the width 3 logic for width 4. -template class UltraPermutationRelation { +template class UltraPermutationRelationBase { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 6; - static constexpr size_t NUM_CONSTRAINTS = 2; - static constexpr std::array CONSTRAINT_LENGTH = { 6, 3 }; - - using RelationUnivariates = std::tuple, Univariate>; - using RelationValues = std::array; + static constexpr size_t LEN_1 = 6; // grand product construction sub-relation + static constexpr size_t LEN_2 = 3; // left-shiftable polynomial sub-relation + using LENGTHS = LengthsWrapper; /** * @brief Compute contribution of the permutation relation for a given edge (internal function) @@ -142,10 +100,11 @@ template class UltraPermutationRelation { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - inline void add_edge_contribution(RelationUnivariates& evals, - const auto& extended_edges, - const RelationParameters& relation_parameters, - const FF& scaling_factor) const + template + inline static void add_edge_contribution_impl(typename TypeMuncher::Accumulators& accumulators, + const auto& extended_edges, + const RelationParameters& relation_parameters, + const FF& scaling_factor) { const auto& beta = relation_parameters.beta; const auto& gamma = relation_parameters.gamma; @@ -153,25 +112,25 @@ template class UltraPermutationRelation { // Contribution (1) { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[0]; - auto w_1 = UnivariateView(extended_edges.w_l); - auto w_2 = UnivariateView(extended_edges.w_r); - auto w_3 = UnivariateView(extended_edges.w_o); - auto w_4 = UnivariateView(extended_edges.w_4); - auto sigma_1 = UnivariateView(extended_edges.sigma_1); - auto sigma_2 = UnivariateView(extended_edges.sigma_2); - auto sigma_3 = UnivariateView(extended_edges.sigma_3); - auto sigma_4 = UnivariateView(extended_edges.sigma_4); - auto id_1 = UnivariateView(extended_edges.id_1); - auto id_2 = UnivariateView(extended_edges.id_2); - auto id_3 = UnivariateView(extended_edges.id_3); - auto id_4 = UnivariateView(extended_edges.id_4); - auto z_perm = UnivariateView(extended_edges.z_perm); - auto z_perm_shift = UnivariateView(extended_edges.z_perm_shift); - auto lagrange_first = UnivariateView(extended_edges.lagrange_first); - auto lagrange_last = UnivariateView(extended_edges.lagrange_last); - - std::get<0>(evals) += + using View = typename std::tuple_element<0, typename TypeMuncher::AccumulatorViews>::type; + auto w_1 = View(extended_edges.w_l); + auto w_2 = View(extended_edges.w_r); + auto w_3 = View(extended_edges.w_o); + auto w_4 = View(extended_edges.w_4); + auto sigma_1 = View(extended_edges.sigma_1); + auto sigma_2 = View(extended_edges.sigma_2); + auto sigma_3 = View(extended_edges.sigma_3); + auto sigma_4 = View(extended_edges.sigma_4); + auto id_1 = View(extended_edges.id_1); + auto id_2 = View(extended_edges.id_2); + auto id_3 = View(extended_edges.id_3); + auto id_4 = View(extended_edges.id_4); + auto z_perm = View(extended_edges.z_perm); + auto z_perm_shift = View(extended_edges.z_perm_shift); + auto lagrange_first = View(extended_edges.lagrange_first); + auto lagrange_last = View(extended_edges.lagrange_last); + + std::get<0>(accumulators) += (((z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * (w_3 + id_3 * beta + gamma) * (w_4 + id_4 * beta + gamma)) - ((z_perm_shift + lagrange_last * public_input_delta) * (w_1 + sigma_1 * beta + gamma) * @@ -180,55 +139,16 @@ template class UltraPermutationRelation { } // Contribution (2) { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[1]; - auto z_perm_shift = UnivariateView(extended_edges.z_perm_shift); - auto lagrange_last = UnivariateView(extended_edges.lagrange_last); + using View = typename std::tuple_element<1, typename TypeMuncher::AccumulatorViews>::type; + auto z_perm_shift = View(extended_edges.z_perm_shift); + auto lagrange_last = View(extended_edges.lagrange_last); - std::get<1>(evals) += (lagrange_last * z_perm_shift) * scaling_factor; + std::get<1>(accumulators) += (lagrange_last * z_perm_shift) * scaling_factor; } }; +}; - /** - * @brief Add the result of each identity in this relation evaluated at the multivariate evaluations produced by the - * Sumcheck Prover. - * - * @param full_honk_relation_value - * @param purported_evaluations - */ - void add_full_relation_value_contribution(RelationValues& full_honk_relation_value, - auto& purported_evaluations, - const RelationParameters& relation_parameters) const - { - const auto& beta = relation_parameters.beta; - const auto& gamma = relation_parameters.gamma; - const auto& public_input_delta = relation_parameters.public_input_delta; - - auto w_1 = purported_evaluations.w_l; - auto w_2 = purported_evaluations.w_r; - auto w_3 = purported_evaluations.w_o; - auto w_4 = purported_evaluations.w_4; - auto sigma_1 = purported_evaluations.sigma_1; - auto sigma_2 = purported_evaluations.sigma_2; - auto sigma_3 = purported_evaluations.sigma_3; - auto sigma_4 = purported_evaluations.sigma_4; - auto id_1 = purported_evaluations.id_1; - auto id_2 = purported_evaluations.id_2; - auto id_3 = purported_evaluations.id_3; - auto id_4 = purported_evaluations.id_4; - auto z_perm = purported_evaluations.z_perm; - auto z_perm_shift = purported_evaluations.z_perm_shift; - auto lagrange_first = purported_evaluations.lagrange_first; - auto lagrange_last = purported_evaluations.lagrange_last; - - // Contribution (1) - std::get<0>(full_honk_relation_value) += - ((z_perm + lagrange_first) * (w_1 + beta * id_1 + gamma) * (w_2 + beta * id_2 + gamma) * - (w_3 + beta * id_3 + gamma) * (w_4 + beta * id_4 + gamma) - - (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + beta * sigma_1 + gamma) * - (w_2 + beta * sigma_2 + gamma) * (w_3 + beta * sigma_3 + gamma) * (w_4 + beta * sigma_4 + gamma)); +template using PermutationRelation = RelationWrapper; - // Contribution (2) - std::get<1>(full_honk_relation_value) += lagrange_last * z_perm_shift; - }; -}; +template using UltraPermutationRelation = RelationWrapper; } // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp index f794b166037..cb3c5ce36c2 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp @@ -216,8 +216,8 @@ TEST_F(StandardRelationConsistency, ArithmeticRelation) // Compute expected full length Univariates using straight forward expressions. // Note: expect { { 5, 22, 57, 116, 205} } for input polynomial {1, 2} - constexpr std::size_t NUM_CONSTRAINTS = decltype(relation)::NUM_CONSTRAINTS; - auto expected_full_length_univariates = std::array, NUM_CONSTRAINTS>(); + constexpr std::size_t NUM_SUBRELATIONS = std::tuple_size_v; + auto expected_full_length_univariates = std::array, NUM_SUBRELATIONS>(); expected_full_length_univariates[0] = (q_m * w_r * w_l) + (q_r * w_r) + (q_l * w_l) + (q_o * w_o) + (q_c); validate_evaluations(expected_full_length_univariates, relation, extended_edges, relation_parameters); @@ -274,8 +274,8 @@ TEST_F(StandardRelationConsistency, PermutationRelation) const auto& lagrange_last = extended_edges.lagrange_last; // Compute expected full length Univariates using straight forward expressions - constexpr std::size_t NUM_CONSTRAINTS = decltype(relation)::NUM_CONSTRAINTS; - auto expected_full_length_univariates = std::array, NUM_CONSTRAINTS>(); + constexpr std::size_t NUM_SUBRELATIONS = std::tuple_size_v; + auto expected_full_length_univariates = std::array, NUM_SUBRELATIONS>(); expected_full_length_univariates[0] = (z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * (w_3 + id_3 * beta + gamma) - diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_types.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_types.hpp new file mode 100644 index 00000000000..e9489223894 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_types.hpp @@ -0,0 +1,87 @@ +#pragma once +#include +#include + +#include "../polynomials/univariate.hpp" +#include "relation_parameters.hpp" + +namespace proof_system::honk::sumcheck { + +/** + * @brief The templates defined herein facilitate sharing the relation arithmetic between the prover and the verifier. + * + * The sumcheck prover and verifier accumulate the contributions from each relation (really, each sub-relation) into, + * respectively, Univariates and individual field elements. When performing relation arithmetic on Univariates, we + * introduce UnivariateViews to reduce full length Univariates to the minimum required length and to avoid unnecessary + * copies. + * + * To share the relation arithmetic, we introduce simple structs that specify two types: Accumulators and + * AccumulatorViews. For the prover, who accumulates Univariates, these are respectively std::tuple and + * std::tuple. For the verifier, who accumulates FFs, both types are simply aliases for std::array + * (since no "view" type is necessary). The containers std::tuple and std::array are needed to accommodate multiple + * sub-relations within each relation, where, for efficiency, each sub-relation has its own specified degree. + */ + +// Helper struct to allow passing an arbitrary collection of lengths to the AccumulatorTypes +template struct LengthsWrapper {}; + +// Forward declarations of AccumulatorTypesHelpers +template struct UnivariateAccumulatorTypesHelper; +template struct ValueAccumulatorTypesHelper; + +// Helper to define value (FF) based accumulator types +template struct ValueAccumulatorTypesHelper> { + using Accumulators = std::array; + using AccumulatorViews = std::array; // there is no "view" type here +}; + +// Accumulator types for values (FFs) +template using ValueAccumulatorTypes = ValueAccumulatorTypesHelper; + +// Helper to define Univariate based accumulator types +template struct UnivariateAccumulatorTypesHelper> { + using Accumulators = std::tuple...>; + using AccumulatorViews = std::tuple...>; +}; + +// Accumulator types for Univariates +template +using UnivariateAccumulatorTypes = UnivariateAccumulatorTypesHelper; + +/** + * @brief A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribution of + * a given relation to the corresponding accumulator. + * + * @tparam FF + * @tparam RelationBase Base class that implements the arithmetic for a given relation (or set of sub-relations) + */ +template typename RelationBase> class RelationWrapper { + public: + using Relation = RelationBase; + using UnivariateAccumTypes = UnivariateAccumulatorTypes; + using ValueAccumTypes = ValueAccumulatorTypes; + + using RelationUnivariates = typename UnivariateAccumTypes::Accumulators; + using RelationValues = typename ValueAccumTypes::Accumulators; + static constexpr size_t RELATION_LENGTH = Relation::RELATION_LENGTH; + + inline void add_edge_contribution(auto& accumulator, + const auto& input, + const RelationParameters& relation_parameters, + const FF& scaling_factor) const + { + Relation::template add_edge_contribution_impl( + accumulator, input, relation_parameters, scaling_factor); + } + + void add_full_relation_value_contribution(RelationValues& accumulator, + auto& input, + const RelationParameters& relation_parameters, + const FF& scaling_factor = 1) const + { + Relation::template add_edge_contribution_impl( + accumulator, input, relation_parameters, scaling_factor); + } +}; + +} // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp index 1ea1de263e6..e5393d3cdf2 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp @@ -4,20 +4,18 @@ #include "../polynomials/univariate.hpp" #include "relation_parameters.hpp" +#include "relation_types.hpp" namespace proof_system::honk::sumcheck { -template class UltraArithmeticRelation { +template class UltraArithmeticRelationBase { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 6; // degree(q_arith^2 * q_m * w_r * w_l) = 5 - static constexpr size_t NUM_CONSTRAINTS = 2; - // TODO(luke): The degree of the identities varies based on q_arith. Can we do something to improve efficiency here? - static constexpr std::array CONSTRAINT_LENGTH = { 6, 5 }; - - using RelationUnivariates = std::tuple, Univariate>; - using RelationValues = std::array; + static constexpr size_t LEN_1 = 6; // primary arithmetic sub-relation + static constexpr size_t LEN_2 = 5; // secondary arithmetic sub-relation + using LENGTHS = LengthsWrapper; /** * @brief Expression for the Ultra Arithmetic gate. @@ -70,28 +68,29 @@ template class UltraArithmeticRelation { * @param parameters contains beta, gamma, and public_input_delta, .... * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - void add_edge_contribution(RelationUnivariates& evals, - const auto& extended_edges, - const RelationParameters&, - const FF& scaling_factor) const { + template + void static add_edge_contribution_impl(typename TypeMuncher::Accumulators& evals, + const auto& extended_edges, + const RelationParameters&, + const FF& scaling_factor){ // OPTIMIZATION?: Karatsuba in general, at least for some degrees? // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both // clang-format off // Contribution 1 { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[0]; - auto w_l = UnivariateView(extended_edges.w_l); - auto w_r = UnivariateView(extended_edges.w_r); - auto w_o = UnivariateView(extended_edges.w_o); - auto w_4 = UnivariateView(extended_edges.w_4); - auto w_4_shift = UnivariateView(extended_edges.w_4_shift); - auto q_m = UnivariateView(extended_edges.q_m); - auto q_l = UnivariateView(extended_edges.q_l); - auto q_r = UnivariateView(extended_edges.q_r); - auto q_o = UnivariateView(extended_edges.q_o); - auto q_4 = UnivariateView(extended_edges.q_4); - auto q_c = UnivariateView(extended_edges.q_c); - auto q_arith = UnivariateView(extended_edges.q_arith); + using View = typename std::tuple_element<0, typename TypeMuncher::AccumulatorViews>::type; + auto w_l = View(extended_edges.w_l); + auto w_r = View(extended_edges.w_r); + auto w_o = View(extended_edges.w_o); + auto w_4 = View(extended_edges.w_4); + auto w_4_shift = View(extended_edges.w_4_shift); + auto q_m = View(extended_edges.q_m); + auto q_l = View(extended_edges.q_l); + auto q_r = View(extended_edges.q_r); + auto q_o = View(extended_edges.q_o); + auto q_4 = View(extended_edges.q_4); + auto q_c = View(extended_edges.q_c); + auto q_arith = View(extended_edges.q_arith); static const FF neg_half = FF(-2).invert(); @@ -104,12 +103,12 @@ template class UltraArithmeticRelation { } // Contribution 2 { - static constexpr size_t LENGTH = CONSTRAINT_LENGTH[1]; - auto w_l = UnivariateView(extended_edges.w_l); - auto w_4 = UnivariateView(extended_edges.w_4); - auto w_l_shift = UnivariateView(extended_edges.w_l_shift); - auto q_m = UnivariateView(extended_edges.q_m); - auto q_arith = UnivariateView(extended_edges.q_arith); + using View = typename std::tuple_element<1, typename TypeMuncher::AccumulatorViews>::type; + auto w_l = View(extended_edges.w_l); + auto w_4 = View(extended_edges.w_4); + auto w_l_shift = View(extended_edges.w_l_shift); + auto q_m = View(extended_edges.q_m); + auto q_arith = View(extended_edges.q_arith); auto tmp = w_l + w_4 - w_l_shift + q_m; tmp *= (q_arith - 2); @@ -119,48 +118,10 @@ template class UltraArithmeticRelation { std::get<1>(evals) += tmp; } }; // namespace proof_system::honk::sumcheck +}; - /** - * @brief Add the result of each identity in this relation evaluated at the multivariate evaluations produced by the - * Sumcheck Prover. - * - * @param full_honk_relation_value - * @param purported_evaluations - */ - void add_full_relation_value_contribution(RelationValues& full_honk_relation_value, - const auto& purported_evaluations, - const RelationParameters&) const - { - auto w_l = purported_evaluations.w_l; - auto w_l_shift = purported_evaluations.w_l_shift; - auto w_r = purported_evaluations.w_r; - auto w_o = purported_evaluations.w_o; - auto w_4 = purported_evaluations.w_4; - auto w_4_shift = purported_evaluations.w_4_shift; - auto q_m = purported_evaluations.q_m; - auto q_l = purported_evaluations.q_l; - auto q_r = purported_evaluations.q_r; - auto q_o = purported_evaluations.q_o; - auto q_4 = purported_evaluations.q_4; - auto q_c = purported_evaluations.q_c; - auto q_arith = purported_evaluations.q_arith; - - static const FF neg_half = FF(-2).invert(); - - // Contribution 1 - auto tmp = (q_arith - 3) * (q_m * w_r * w_l) * neg_half; - tmp += (q_l * w_l) + (q_r * w_r) + (q_o * w_o) + (q_4 * w_4) + q_c; - tmp += (q_arith - 1) * w_4_shift; - tmp *= q_arith; - std::get<0>(full_honk_relation_value) += tmp; +template +using UltraArithmeticRelation = RelationWrapper; - // Contribution 2 - tmp = w_l + w_4 - w_l_shift + q_m; - tmp *= (q_arith - 2); - tmp *= (q_arith - 1); - tmp *= q_arith; - std::get<1>(full_honk_relation_value) += tmp; - }; -}; // clang-format on } // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp index 1be27d4bda7..ddf85ef38b5 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp @@ -220,8 +220,8 @@ TEST_F(UltraRelationConsistency, UltraArithmeticRelation) static const FF neg_half = FF(-2).invert(); - constexpr std::size_t NUM_CONSTRAINTS = decltype(relation)::NUM_CONSTRAINTS; - auto expected_full_length_univariates = std::array, NUM_CONSTRAINTS>(); + constexpr std::size_t NUM_SUBRELATIONS = std::tuple_size_v; + auto expected_full_length_univariates = std::array, NUM_SUBRELATIONS>(); // Contribution 1 auto contribution_1 = (q_arith - 3) * (q_m * w_2 * w_1) * neg_half; @@ -280,8 +280,8 @@ TEST_F(UltraRelationConsistency, UltraPermutationRelation) const auto& lagrange_first = extended_edges.lagrange_first; const auto& lagrange_last = extended_edges.lagrange_last; - constexpr std::size_t NUM_CONSTRAINTS = decltype(relation)::NUM_CONSTRAINTS; - auto expected_full_length_univariates = std::array, NUM_CONSTRAINTS>(); + constexpr std::size_t NUM_SUBRELATIONS = std::tuple_size_v; + auto expected_full_length_univariates = std::array, NUM_SUBRELATIONS>(); // Compute the expected result using a simple to read version of the relation expression @@ -369,8 +369,8 @@ TEST_F(UltraRelationConsistency, LookupRelation) auto table_accum = table_1 + table_2 * eta + table_3 * eta_sqr + table_4 * eta_cube; auto table_accum_shift = table_1_shift + table_2_shift * eta + table_3_shift * eta_sqr + table_4_shift * eta_cube; - constexpr std::size_t NUM_CONSTRAINTS = decltype(relation)::NUM_CONSTRAINTS; - auto expected_full_length_univariates = std::array, NUM_CONSTRAINTS>(); + constexpr std::size_t NUM_SUBRELATIONS = std::tuple_size_v; + auto expected_full_length_univariates = std::array, NUM_SUBRELATIONS>(); // Compute the expected result using a simple to read version of the relation expression @@ -425,8 +425,8 @@ TEST_F(UltraRelationConsistency, GenPermSortRelation) auto delta_3 = w_4 - w_3; auto delta_4 = w_1_shift - w_4; - constexpr std::size_t NUM_CONSTRAINTS = decltype(relation)::NUM_CONSTRAINTS; - auto expected_full_length_univariates = std::array, NUM_CONSTRAINTS>(); + constexpr std::size_t NUM_SUBRELATIONS = std::tuple_size_v; + auto expected_full_length_univariates = std::array, NUM_SUBRELATIONS>(); // Compute the expected result using a simple to read version of the relation expression auto contribution_1 = delta_1 * (delta_1 - 1) * (delta_1 - 2) * (delta_1 - 3); @@ -476,8 +476,8 @@ TEST_F(UltraRelationConsistency, EllipticRelation) const auto& q_beta_sqr = extended_edges.q_4; const auto& q_elliptic = extended_edges.q_elliptic; - constexpr std::size_t NUM_CONSTRAINTS = decltype(relation)::NUM_CONSTRAINTS; - auto expected_full_length_univariates = std::array, NUM_CONSTRAINTS>(); + constexpr std::size_t NUM_SUBRELATIONS = std::tuple_size_v; + auto expected_full_length_univariates = std::array, NUM_SUBRELATIONS>(); // Compute x/y coordinate identities @@ -539,8 +539,8 @@ TEST_F(UltraRelationConsistency, AuxiliaryRelation) const auto& q_arith = extended_edges.q_arith; const auto& q_aux = extended_edges.q_aux; - constexpr std::size_t NUM_CONSTRAINTS = decltype(relation)::NUM_CONSTRAINTS; - auto expected_full_length_univariates = std::array, NUM_CONSTRAINTS>(); + constexpr std::size_t NUM_SUBRELATIONS = std::tuple_size_v; + auto expected_full_length_univariates = std::array, NUM_SUBRELATIONS>(); constexpr FF LIMB_SIZE(uint256_t(1) << 68); constexpr FF SUBLIMB_SHIFT(uint256_t(1) << 14); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp index d0b5d022d8c..f1f76caef10 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp @@ -269,23 +269,6 @@ template static conste } } -/** - * @brief Recursive helper function to construct BarycentricData to extend each Relation in a tuple - * - */ -template -static constexpr auto create_barycentric_utils() -{ - if constexpr (Index >= std::tuple_size::value) { - return std::tuple<>{}; // Return empty when reach end of the tuple - } else { - constexpr size_t relation_length = std::tuple_element_t::RELATION_LENGTH; - using BarycentricType = sumcheck::BarycentricData; - return std::tuple_cat(std::tuple{}, - create_barycentric_utils()); - } -} - } // namespace proof_system::honk::flavor // Forward declare honk flavors