From 3375caf19cce8bfb41bd304594457c157aed970a Mon Sep 17 00:00:00 2001 From: Adrian Hamelink Date: Thu, 23 Feb 2023 18:27:32 +0100 Subject: [PATCH] Remove testing methods from Honk + clean up (#177) * Initial commit * Luke's comments --- .../composer/standard_honk_composer.test.cpp | 187 ++++++--------- cpp/src/aztec/honk/proof_system/verifier.cpp | 4 - .../polynomials/multivariates.test.cpp | 7 - .../honk/sumcheck/polynomials/univariate.hpp | 104 +++++---- .../relations/arithmetic_relation.hpp | 63 ++---- .../grand_product_computation_relation.hpp | 76 +++---- .../grand_product_initialization_relation.hpp | 56 ++--- .../honk/sumcheck/relations/relation.test.cpp | 213 ++++++++++++------ cpp/src/aztec/honk/sumcheck/sumcheck.test.cpp | 13 -- .../aztec/honk/sumcheck/sumcheck_round.hpp | 30 +-- 10 files changed, 330 insertions(+), 423 deletions(-) diff --git a/cpp/src/aztec/honk/composer/standard_honk_composer.test.cpp b/cpp/src/aztec/honk/composer/standard_honk_composer.test.cpp index 897cf0fb00..950c533212 100644 --- a/cpp/src/aztec/honk/composer/standard_honk_composer.test.cpp +++ b/cpp/src/aztec/honk/composer/standard_honk_composer.test.cpp @@ -1,5 +1,5 @@ #include "standard_honk_composer.hpp" -#include "common/assert.hpp" +#include "honk/sumcheck/relations/relation.hpp" #include "numeric/uint256/uint256.hpp" #include "proof_system/flavor/flavor.hpp" #include @@ -9,7 +9,6 @@ #include #include -#include #include using namespace honk; @@ -23,7 +22,7 @@ namespace test_standard_honk_composer { * 2) That if the permutation argument is computed with witness values, the values from the identity permutation and * sigma permutation are equal */ -TEST(standard_honk_composer, test_sigma_and_id_correctness) +TEST(StandardHonkComposer, SigmaIDCorrectness) { auto test_permutation = [](StandardHonkComposer& composer) { auto proving_key = composer.compute_proving_key(); @@ -133,7 +132,7 @@ TEST(standard_honk_composer, test_sigma_and_id_correctness) * @brief Check the correctness of lagrange polynomials generated during proving key computation * */ -TEST(standard_honk_composer, test_lagrange_polynomial_correctness) +TEST(StandardHonkComposer, LagrangeCorrectness) { // Create a composer and a dummy circuit with a few gates StandardHonkComposer composer = StandardHonkComposer(); @@ -181,7 +180,7 @@ TEST(standard_honk_composer, test_lagrange_polynomial_correctness) * merged. * In this test we create two almost identical circuits. They differ because one */ -TEST(standard_honk_composer, test_assert_equal) +TEST(StandardHonkComposer, AssertEquals) { /** * @brief A function that creates a simple circuit with repeated gates, leading to large permutation cycles @@ -281,7 +280,7 @@ TEST(standard_honk_composer, test_assert_equal) EXPECT_EQ(get_maximum_cycle(composer_with_assert_equal), get_maximum_cycle(composer_no_assert_equal) * 2); } -TEST(standard_honk_composer, test_verification_key_creation) +TEST(StandardHonkComposer, VerificationKeyCreation) { // Create a composer and a dummy circuit with a few gates StandardHonkComposer composer = StandardHonkComposer(); @@ -313,7 +312,7 @@ TEST(standard_honk_composer, test_verification_key_creation) * indices * */ -TEST(standard_honk_composer, test_check_sumcheck_relations_correctness) +TEST(StandardHonkComposer, SumcheckRelationCorrectness) { // Create a composer and a dummy circuit with a few gates StandardHonkComposer composer = StandardHonkComposer(); @@ -336,136 +335,80 @@ TEST(standard_honk_composer, test_check_sumcheck_relations_correctness) // Generate beta and gamma fr beta = fr::random_element(); fr gamma = fr::random_element(); - - // Compute grand product polynomial (now all the necessary polynomials are inside the proving key) - auto z_permutation = prover.compute_grand_product_polynomial(beta, gamma); + fr zeta = fr::random_element(); // Compute public input delta const auto public_inputs = composer.circuit_constructor.get_public_inputs(); auto public_input_delta = honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); - // Retrieve polynomials from proving key - polynomial w_1 = prover.wire_polynomials[0]; - polynomial w_2 = prover.wire_polynomials[1]; - polynomial w_3 = prover.wire_polynomials[2]; - polynomial q_m = prover.key->polynomial_cache.get("q_m_lagrange"); - polynomial q_1 = prover.key->polynomial_cache.get("q_1_lagrange"); - polynomial q_2 = prover.key->polynomial_cache.get("q_2_lagrange"); - polynomial q_3 = prover.key->polynomial_cache.get("q_3_lagrange"); - polynomial q_c = prover.key->polynomial_cache.get("q_c_lagrange"); - polynomial sigma_1 = prover.key->polynomial_cache.get("sigma_1_lagrange"); - polynomial sigma_2 = prover.key->polynomial_cache.get("sigma_2_lagrange"); - polynomial sigma_3 = prover.key->polynomial_cache.get("sigma_3_lagrange"); - polynomial id_1 = prover.key->polynomial_cache.get("id_1_lagrange"); - polynomial id_2 = prover.key->polynomial_cache.get("id_2_lagrange"); - polynomial id_3 = prover.key->polynomial_cache.get("id_3_lagrange"); - polynomial L_first = prover.key->polynomial_cache.get("L_first_lagrange"); - polynomial L_last = prover.key->polynomial_cache.get("L_last_lagrange"); - - // Specify sumcheck configuration - using honk::sumcheck::Univariate; - using honk::sumcheck::UnivariateView; - using SumCheckRound = honk::sumcheck::SumcheckRound; - using StandardUnivariate = Univariate; - std::vector< - std::array, bonk::StandardArithmetization::NUM_POLYNOMIALS>> - sumcheck_typed_polynomial_vector; - using ArithmeticUnivariate = Univariate::RELATION_LENGTH>; - - using GrandProductComputationUnivariate = - Univariate::RELATION_LENGTH>; - using GrandProductInitializationUnivariate = - Univariate::RELATION_LENGTH>; + sumcheck::RelationParameters params{ + .zeta = zeta, + .alpha = fr::one(), + .beta = beta, + .gamma = gamma, + .public_input_delta = public_input_delta, + }; + + constexpr size_t num_polynomials = bonk::StandardArithmetization::NUM_POLYNOMIALS; + // Compute grand product polynomial (now all the necessary polynomials are inside the proving key) + polynomial z_perm_poly = prover.compute_grand_product_polynomial(beta, gamma); + + // Create an array of spans to the underlying polynomials to more easily + // get the transposition. + // Ex: polynomial_spans[3][i] returns the i-th coefficient of the third polynomial + // in the list below + std::array, num_polynomials> evaluations_array; + + using POLYNOMIAL = bonk::StandardArithmetization::POLYNOMIAL; + evaluations_array[POLYNOMIAL::W_L] = prover.wire_polynomials[0]; + evaluations_array[POLYNOMIAL::W_R] = prover.wire_polynomials[1]; + evaluations_array[POLYNOMIAL::W_O] = prover.wire_polynomials[2]; + evaluations_array[POLYNOMIAL::Z_PERM] = z_perm_poly; + evaluations_array[POLYNOMIAL::Z_PERM_SHIFT] = z_perm_poly.shifted(); + evaluations_array[POLYNOMIAL::Q_M] = prover.key->polynomial_cache.get("q_m_lagrange"); + evaluations_array[POLYNOMIAL::Q_L] = prover.key->polynomial_cache.get("q_1_lagrange"); + evaluations_array[POLYNOMIAL::Q_R] = prover.key->polynomial_cache.get("q_2_lagrange"); + evaluations_array[POLYNOMIAL::Q_O] = prover.key->polynomial_cache.get("q_3_lagrange"); + evaluations_array[POLYNOMIAL::Q_C] = prover.key->polynomial_cache.get("q_c_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_1] = prover.key->polynomial_cache.get("sigma_1_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_2] = prover.key->polynomial_cache.get("sigma_2_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_3] = prover.key->polynomial_cache.get("sigma_3_lagrange"); + evaluations_array[POLYNOMIAL::ID_1] = prover.key->polynomial_cache.get("id_1_lagrange"); + evaluations_array[POLYNOMIAL::ID_2] = prover.key->polynomial_cache.get("id_2_lagrange"); + evaluations_array[POLYNOMIAL::ID_3] = prover.key->polynomial_cache.get("id_3_lagrange"); + evaluations_array[POLYNOMIAL::LAGRANGE_FIRST] = prover.key->polynomial_cache.get("L_first_lagrange"); + evaluations_array[POLYNOMIAL::LAGRANGE_LAST] = prover.key->polynomial_cache.get("L_last_lagrange"); // Construct the round for applying sumcheck relations and results for storing computed results auto relations = std::tuple(honk::sumcheck::ArithmeticRelation(), honk::sumcheck::GrandProductComputationRelation(), honk::sumcheck::GrandProductInitializationRelation()); - auto round = SumCheckRound(relations); - auto results = std::make_tuple( - ArithmeticUnivariate(0), GrandProductComputationUnivariate(0), GrandProductInitializationUnivariate(0)); - - // Transpose the polynomials so that each entry of the vector contains an array of polynomial entries at that - // index - std::array, bonk::StandardArithmetization::NUM_POLYNOMIALS> - univariate_array; - for (size_t i = 0; i < prover.key->circuit_size; i++) { - // We only fill in the first element of each univariate with the value of an entry from the original poynomial - StandardUnivariate w_1_univariate(0); - w_1_univariate.value_at(0) = w_1[i]; - StandardUnivariate w_2_univariate(0); - w_2_univariate.value_at(0) = w_2[i]; - StandardUnivariate w_3_univariate(0); - w_3_univariate.value_at(0) = w_3[i]; - StandardUnivariate z_perm_univariate(0); - z_perm_univariate.value_at(0) = z_permutation[i]; - StandardUnivariate z_perm_shift_univariate(0); - z_perm_shift_univariate.value_at(0) = (i < (prover.key->circuit_size - 1)) ? z_permutation[i + 1] : 0; - StandardUnivariate q_m_univariate(0); - q_m_univariate.value_at(0) = q_m[i]; - StandardUnivariate q_1_univariate(0); - q_1_univariate.value_at(0) = q_1[i]; - StandardUnivariate q_2_univariate(0); - q_2_univariate.value_at(0) = q_2[i]; - StandardUnivariate q_3_univariate(0); - q_3_univariate.value_at(0) = q_3[i]; - StandardUnivariate q_c_univariate(0); - q_c_univariate.value_at(0) = q_c[i]; - StandardUnivariate sigma_1_univariate(0); - sigma_1_univariate.value_at(0) = sigma_1[i]; - StandardUnivariate sigma_2_univariate(0); - sigma_2_univariate.value_at(0) = sigma_2[i]; - StandardUnivariate sigma_3_univariate(0); - sigma_3_univariate.value_at(0) = sigma_3[i]; - StandardUnivariate id_1_univariate(0); - id_1_univariate.value_at(0) = id_1[i]; - StandardUnivariate id_2_univariate(0); - id_2_univariate.value_at(0) = id_2[i]; - StandardUnivariate id_3_univariate(0); - id_3_univariate.value_at(0) = id_3[i]; - StandardUnivariate L_first_univariate(0); - L_first_univariate.value_at(0) = L_first[i]; - StandardUnivariate L_last_univariate(0); - L_last_univariate.value_at(0) = L_last[i]; - - using POLYNOMIAL = bonk::StandardArithmetization::POLYNOMIAL; - univariate_array[POLYNOMIAL::W_L] = w_1_univariate; - univariate_array[POLYNOMIAL::W_R] = w_2_univariate; - univariate_array[POLYNOMIAL::W_O] = w_3_univariate; - univariate_array[POLYNOMIAL::Z_PERM] = z_perm_univariate; - univariate_array[POLYNOMIAL::Z_PERM_SHIFT] = z_perm_shift_univariate; - univariate_array[POLYNOMIAL::Q_M] = q_m_univariate; - univariate_array[POLYNOMIAL::Q_L] = q_1_univariate; - univariate_array[POLYNOMIAL::Q_R] = q_2_univariate; - univariate_array[POLYNOMIAL::Q_O] = q_3_univariate; - univariate_array[POLYNOMIAL::Q_C] = q_c_univariate; - univariate_array[POLYNOMIAL::SIGMA_1] = sigma_1_univariate; - univariate_array[POLYNOMIAL::SIGMA_2] = sigma_2_univariate; - univariate_array[POLYNOMIAL::SIGMA_3] = sigma_3_univariate; - univariate_array[POLYNOMIAL::ID_1] = id_1_univariate; - univariate_array[POLYNOMIAL::ID_2] = id_2_univariate; - univariate_array[POLYNOMIAL::ID_3] = id_3_univariate; - univariate_array[POLYNOMIAL::LAGRANGE_FIRST] = L_first_univariate; - univariate_array[POLYNOMIAL::LAGRANGE_LAST] = L_last_univariate; - - sumcheck_typed_polynomial_vector.push_back(univariate_array); - } - // Check all relations at all indices + + fr result = 0; for (size_t i = 0; i < prover.key->circuit_size; i++) { - round.accumulate_relation_univariates_testing( - sumcheck_typed_polynomial_vector[i], results, { beta, gamma, public_input_delta }); - EXPECT_EQ(std::get<0>(results), ArithmeticUnivariate(0)); - EXPECT_EQ(std::get<1>(results), GrandProductComputationUnivariate(0)); - EXPECT_EQ(std::get<2>(results), GrandProductInitializationUnivariate(0)); + // Compute an array containing all the evaluations at a given row i + std::array evaluations_at_index_i; + for (size_t j = 0; j < num_polynomials; ++j) { + evaluations_at_index_i[j] = evaluations_array[j][i]; + } + + // For each relation, call the `accumulate_relation_evaluation` over all witness/selector values at the + // i-th row/vertex of the hypercube. + // We use ASSERT_EQ instead of EXPECT_EQ so that the tests stops at the first index at which the result is not + // 0, since result = 0 + C(transposed), which we expect will equal 0. + std::get<0>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); + + std::get<1>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); + + std::get<2>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); } } -TEST(StandarHonkComposer, BaseCase) +TEST(StandardHonkComposer, BaseCase) { auto composer = StandardHonkComposer(); fr a = 1; diff --git a/cpp/src/aztec/honk/proof_system/verifier.cpp b/cpp/src/aztec/honk/proof_system/verifier.cpp index a0c0e7e031..6043f71ec7 100644 --- a/cpp/src/aztec/honk/proof_system/verifier.cpp +++ b/cpp/src/aztec/honk/proof_system/verifier.cpp @@ -23,8 +23,6 @@ #include #include -#pragma GCC diagnostic ignored "-Wunused-variable" - using namespace barretenberg; using namespace honk::sumcheck; @@ -83,7 +81,6 @@ template Verifier& Verifier bool Verifier::verify_proof(const plonk::proof& proof) { - const size_t num_polys = program_settings::num_polys; using FF = typename program_settings::fr; using Commitment = barretenberg::g1::affine_element; using Transcript = typename program_settings::Transcript; @@ -94,7 +91,6 @@ template bool Verifier::verify_pro using GeminiProof = pcs::gemini::Proof; using POLYNOMIAL = bonk::StandardArithmetization::POLYNOMIAL; const size_t NUM_UNSHIFTED = bonk::StandardArithmetization::NUM_UNSHIFTED_POLYNOMIALS; - const size_t NUM_SHIFTED = bonk::StandardArithmetization::NUM_SHIFTED_POLYNOMIALS; const size_t NUM_PRECOMPUTED = bonk::StandardArithmetization::NUM_PRECOMPUTED_POLYNOMIALS; key->program_width = program_settings::program_width; diff --git a/cpp/src/aztec/honk/sumcheck/polynomials/multivariates.test.cpp b/cpp/src/aztec/honk/sumcheck/polynomials/multivariates.test.cpp index 6b6a12330d..7770fc6cff 100644 --- a/cpp/src/aztec/honk/sumcheck/polynomials/multivariates.test.cpp +++ b/cpp/src/aztec/honk/sumcheck/polynomials/multivariates.test.cpp @@ -5,8 +5,6 @@ #include #include -#pragma GCC diagnostic ignored "-Wunused-variable" - using namespace honk::sumcheck; namespace test_sumcheck_polynomials { @@ -43,7 +41,6 @@ TYPED_TEST(MultivariatesTests, FoldTwoRoundsSpecial) MULTIVARIATES_TESTS_TYPE_ALIASES // values here are chosen to check another test - const size_t num_polys(1); const size_t multivariate_d(2); const size_t multivariate_n(1 << multivariate_d); @@ -79,7 +76,6 @@ TYPED_TEST(MultivariatesTests, FoldTwoRoundsGeneric) { MULTIVARIATES_TESTS_TYPE_ALIASES - const size_t num_polys(1); const size_t multivariate_d(2); const size_t multivariate_n(1 << multivariate_d); @@ -128,7 +124,6 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsSpecial) { MULTIVARIATES_TESTS_TYPE_ALIASES - const size_t num_polys(1); const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); @@ -178,7 +173,6 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) { MULTIVARIATES_TESTS_TYPE_ALIASES - const size_t num_polys(1); const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); @@ -227,7 +221,6 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) TYPED_TEST(MultivariatesTests, FoldThreeRoundsGenericMultiplePolys) { MULTIVARIATES_TESTS_TYPE_ALIASES - const size_t num_polys(3); const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); std::array v000; diff --git a/cpp/src/aztec/honk/sumcheck/polynomials/univariate.hpp b/cpp/src/aztec/honk/sumcheck/polynomials/univariate.hpp index 02d4ccb763..961b20803b 100644 --- a/cpp/src/aztec/honk/sumcheck/polynomials/univariate.hpp +++ b/cpp/src/aztec/honk/sumcheck/polynomials/univariate.hpp @@ -22,13 +22,10 @@ template class Univariate { explicit Univariate(std::array evaluations) : evaluations(evaluations) {} - Univariate(const Univariate& other) - : evaluations(other.evaluations) - {} - Univariate(Univariate&& other) noexcept - : evaluations(std::move(other.evaluations)) - {} - + Univariate(const Univariate& other) = default; + Univariate(Univariate&& other) noexcept = default; + Univariate& operator=(const Univariate& other) = default; + Univariate& operator=(Univariate&& other) noexcept = default; // Construct Univariate from scalar explicit Univariate(Fr value) : evaluations{} @@ -47,6 +44,7 @@ template class Univariate { } Fr& value_at(size_t i) { return evaluations[i]; }; + const Fr& value_at(size_t i) const { return evaluations[i]; }; // Write the Univariate evaluations to a buffer std::vector to_buffer() const { return ::to_buffer(evaluations); } @@ -62,35 +60,23 @@ template class Univariate { } // Operations between Univariate and other Univariate - Univariate operator=(const Univariate& other) - { - evaluations = other.evaluations; - return *this; - } - - Univariate operator=(Univariate&& other) - { - evaluations = std::move(other.evaluations); - return *this; - } - bool operator==(const Univariate& other) const = default; - Univariate operator+=(const Univariate& other) + Univariate& operator+=(const Univariate& other) { for (size_t i = 0; i < _length; ++i) { evaluations[i] += other.evaluations[i]; } return *this; } - Univariate operator-=(const Univariate& other) + Univariate& operator-=(const Univariate& other) { for (size_t i = 0; i < _length; ++i) { evaluations[i] -= other.evaluations[i]; } return *this; } - Univariate operator*=(const Univariate& other) + Univariate& operator*=(const Univariate& other) { for (size_t i = 0; i < _length; ++i) { evaluations[i] *= other.evaluations[i]; @@ -118,7 +104,7 @@ template class Univariate { } // Operations between Univariate and scalar - Univariate operator+=(const Fr& scalar) + Univariate& operator+=(const Fr& scalar) { for (auto& eval : evaluations) { eval += scalar; @@ -126,14 +112,14 @@ template class Univariate { return *this; } - Univariate operator-=(const Fr& scalar) + Univariate& operator-=(const Fr& scalar) { for (auto& eval : evaluations) { eval -= scalar; } return *this; } - Univariate operator*=(const Fr& scalar) + Univariate& operator*=(const Fr& scalar) { for (auto& eval : evaluations) { eval *= scalar; @@ -141,21 +127,21 @@ template class Univariate { return *this; } - Univariate operator+(const Fr& scalar) + Univariate operator+(const Fr& scalar) const { Univariate res(*this); res += scalar; return res; } - Univariate operator-(const Fr& scalar) + Univariate operator-(const Fr& scalar) const { Univariate res(*this); res -= scalar; return res; } - Univariate operator*(const Fr& scalar) + Univariate operator*(const Fr& scalar) const { Univariate res(*this); res *= scalar; @@ -163,7 +149,7 @@ template class Univariate { } // Operations between Univariate and UnivariateView - Univariate operator+=(const UnivariateView& view) + Univariate& operator+=(const UnivariateView& view) { for (size_t i = 0; i < _length; ++i) { evaluations[i] += view.evaluations[i]; @@ -171,7 +157,7 @@ template class Univariate { return *this; } - Univariate operator-=(const UnivariateView& view) + Univariate& operator-=(const UnivariateView& view) { for (size_t i = 0; i < _length; ++i) { evaluations[i] -= view.evaluations[i]; @@ -179,7 +165,7 @@ template class Univariate { return *this; } - Univariate operator*=(const UnivariateView& view) + Univariate& operator*=(const UnivariateView& view) { for (size_t i = 0; i < _length; ++i) { evaluations[i] *= view.evaluations[i]; @@ -187,21 +173,21 @@ template class Univariate { return *this; } - Univariate operator+(const UnivariateView& view) + Univariate operator+(const UnivariateView& view) const { Univariate res(*this); res += view; return res; } - Univariate operator-(const UnivariateView& view) + Univariate operator-(const UnivariateView& view) const { Univariate res(*this); res -= view; return res; } - Univariate operator*(const UnivariateView& view) + Univariate operator*(const UnivariateView& view) const { Univariate res(*this); res *= view; @@ -227,15 +213,15 @@ template class Univariate { template class UnivariateView { public: - std::span evaluations; + std::span evaluations; UnivariateView() = default; - Fr& value_at(size_t i) { return evaluations[i]; }; + const Fr& value_at(size_t i) const { return evaluations[i]; }; template - explicit UnivariateView(Univariate& univariate_in) - : evaluations(std::span(univariate_in.evaluations.begin(), view_length)){}; + explicit UnivariateView(const Univariate& univariate_in) + : evaluations(std::span(univariate_in.evaluations.data(), view_length)){}; Univariate operator+(const UnivariateView& other) const { @@ -309,4 +295,46 @@ template class UnivariateView { return os; } }; + +/** + * @brief Create a sub-array of `elements` at the indices given in the template pack `Is`, converting them to the new + * type T. + * + * @tparam T type to convert to + * @tparam U type to convert from + * @tparam N number (deduced by `elements`) + * @tparam Is list of indices we want in the returned array. When the second argument is called with + * `std::make_index_sequence`, these will be `0, 1, ..., N-1`. + * @param elements array to convert from + * @return std::array result array s.t. result[i] = T(elements[Is[i]]). By default, Is[i] = i when + * called with `std::make_index_sequence`. + */ +template +std::array array_to_array_aux(const std::array& elements, std::index_sequence) +{ + return { { T{ elements[Is] }... } }; +}; + +/** + * @brief Given an std::array, returns an std::array, by calling the (explicit) constructor T(U). + * + * @details https://stackoverflow.com/a/32175958 + * The main use case is to convert an array of `Univariate` into `UnivariateView`. The main use case would be to let + * Sumcheck decide the required degree of the relation evaluation, rather than hardcoding it inside the relation. The + * `_aux` version could also be used to create an array of only the polynomials required by the relation, and it could + * help us implement the optimization where we extend each edge only up to the maximum degree that is required over all + * relations (for example, `L_LAST` only needs degree 3). + * + * @tparam T Output type + * @tparam U Input type (deduced from `elements`) + * @tparam N Common array size (deduced from `elements`) + * @param elements array to be converted + * @return std::array result s.t. result[i] = T(elements[i]) + */ +template std::array array_to_array(const std::array& elements) +{ + // Calls the aux method that uses the index sequence to unpack all values in `elements` + return array_to_array_aux(elements, std::make_index_sequence()); +}; + } // namespace honk::sumcheck diff --git a/cpp/src/aztec/honk/sumcheck/relations/arithmetic_relation.hpp b/cpp/src/aztec/honk/sumcheck/relations/arithmetic_relation.hpp index accaaf25cd..f79794979a 100644 --- a/cpp/src/aztec/honk/sumcheck/relations/arithmetic_relation.hpp +++ b/cpp/src/aztec/honk/sumcheck/relations/arithmetic_relation.hpp @@ -3,8 +3,8 @@ #include #include -#include "relation.hpp" #include "../polynomials/univariate.hpp" +#include "relation.hpp" namespace honk::sumcheck { @@ -14,54 +14,24 @@ template class ArithmeticRelation : public Relation { static constexpr size_t RELATION_LENGTH = 4; using MULTIVARIATE = StandardHonk::MULTIVARIATE; // could just get from StandardArithmetization - // FUTURE OPTIMIZATION: successively extend as needed? - - // This relation takes no randomness, so it will not receive challenges. - ArithmeticRelation() = default; - explicit ArithmeticRelation(auto){}; // NOLINT(readability-named-parameter) - - /** - * @brief External function used by sumcheck round - * - * @param extended_edges Contain inputs for the relation - * @param evals Contains the resulting univariate polynomial - * - * The final parameter is left to conform to the general argument structure (input,output, challenges) even though - * we don't need challenges in this relation. - */ - template - void add_edge_contribution(auto& extended_edges, - Univariate& evals, - T, - const FF& scaling_factor ) - { - add_edge_contribution_internal(extended_edges, evals, scaling_factor); - }; - /** - * @brief Same as add_edge_contribution but is used for testing + * @brief Expression for the StandardArithmetic gate. + * @details The relation is defined as C(extended_edges(X)...) = + * (q_m * w_r * w_l) + (q_l * w_l) + (q_r * w_r) + (q_o * w_o) + q_c * - * @details Arithmetic relation doesn't require challenges but it needs the same interface as those relations that - * do - * - * @tparam T - * @param extended_edges - * @param evals - * @param challenges + * @param evals transformed to `evals + C(extended_edges(X)...)*scaling_factor` + * @param extended_edges an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. */ - // TODO(kesha): Change once challenges are being supplied to regular contribution - template - void add_edge_contribution_testing(auto& extended_edges, Univariate& evals, T) + void add_edge_contribution(Univariate& evals, + const auto& extended_edges, + const RelationParameters&, + const FF& scaling_factor) const { - add_edge_contribution_internal(extended_edges, evals, FF::one()); - }; + // OPTIMIZATION?: Karatsuba in general, at least for some degrees? + // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both - // OPTIMIZATION?: Karatsuba in general, at least for some degrees? - // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both - void add_edge_contribution_internal(auto& extended_edges, - Univariate& evals, - const FF& scaling_factor) - { auto w_l = UnivariateView(extended_edges[MULTIVARIATE::W_L]); auto w_r = UnivariateView(extended_edges[MULTIVARIATE::W_R]); auto w_o = UnivariateView(extended_edges[MULTIVARIATE::W_O]); @@ -79,8 +49,9 @@ template class ArithmeticRelation : public Relation { evals += tmp; }; - template - void add_full_relation_value_contribution(auto& purported_evaluations, FF& full_honk_relation_value, T) + void add_full_relation_value_contribution(FF& full_honk_relation_value, + const auto& purported_evaluations, + const RelationParameters&) const { auto w_l = purported_evaluations[MULTIVARIATE::W_L]; auto w_r = purported_evaluations[MULTIVARIATE::W_R]; diff --git a/cpp/src/aztec/honk/sumcheck/relations/grand_product_computation_relation.hpp b/cpp/src/aztec/honk/sumcheck/relations/grand_product_computation_relation.hpp index 1911bb8976..bded8f7570 100644 --- a/cpp/src/aztec/honk/sumcheck/relations/grand_product_computation_relation.hpp +++ b/cpp/src/aztec/honk/sumcheck/relations/grand_product_computation_relation.hpp @@ -11,58 +11,33 @@ template class GrandProductComputationRelation : public Relation& evals, - const RelationParameters& relation_parameters, - const FF& scaling_factor) - { - add_edge_contribution_internal(extended_edges, - evals, - relation_parameters.beta, - relation_parameters.gamma, - relation_parameters.public_input_delta, - scaling_factor); - }; - - /** - * @brief Add contribution of the permutation relation for a given edge (used for testing, allows specifying - * challenges) - */ - // TODO(kesha): Change once challenges are being supplied to regular contribution - void add_edge_contribution_testing(auto& extended_edges, - Univariate& evals, - std::array challenges) - { - add_edge_contribution_internal(extended_edges, evals, challenges[0], challenges[1], challenges[2], FF::one()); - }; - - /** - * @brief Add contribution of the permutation relation for a given edge (internal function) + * @brief Compute contribution of the permutation relation for a given edge (internal function) * - * @detail There are 2 relations associated with enforcing the wire copy relations + * @details There are 2 relations associated with enforcing the wire copy relations * This file handles the relation that confirms faithful calculation of the grand * product polynomial Z_perm. (Initialization relation Z_perm(0) = 1 is handled elsewhere). * - * ( z_perm(X) + lagrange_first(X) )*P(X) - ( z_perm_shift(X) + delta * lagrange_last(X) )*Q(X), + * C(extended_edges(X)...) = ( z_perm(X) + lagrange_first(X) )*P(X) - ( z_perm_shift(X) + delta * lagrange_last(X) )*Q(X), * where * P(X) = Prod_{i=1:3} w_i(X) + β*(n*(i-1) + idx(X)) + γ * Q(X) = Prod_{i=1:3} w_i(X) + β*σ_i(X) + γ * delta is the public input correction term * + * @param evals transformed to `evals + C(extended_edges(X)...)*scaling_factor` + * @param extended_edges an std::array containing the fully extended Univariate edges. + * @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_internal(auto& extended_edges, - Univariate& evals, - const FF& beta, - const FF& gamma, - const FF& public_input_delta, - const FF& scaling_factor) + inline void add_edge_contribution(Univariate& evals, + const auto& extended_edges, + const RelationParameters& relation_parameters, + const FF& scaling_factor) 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 = UnivariateView(extended_edges[MULTIVARIATE::W_L]); auto w_2 = UnivariateView(extended_edges[MULTIVARIATE::W_R]); auto w_3 = UnivariateView(extended_edges[MULTIVARIATE::W_O]); @@ -85,10 +60,14 @@ template class GrandProductComputationRelation : public Relation& relation_parameters) + void add_full_relation_value_contribution(FF& 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[MULTIVARIATE::W_L]; auto w_2 = purported_evaluations[MULTIVARIATE::W_R]; auto w_3 = purported_evaluations[MULTIVARIATE::W_O]; @@ -105,13 +84,10 @@ template class GrandProductComputationRelation : public Relation class GrandProductInitializationRelation : public Relatio static constexpr size_t RELATION_LENGTH = 3; using MULTIVARIATE = StandardHonk::MULTIVARIATE; // could just get from StandardArithmetization - GrandProductInitializationRelation() = default; - explicit GrandProductInitializationRelation(auto){}; // NOLINT(readability-named-parameter) - /** * @brief Add contribution of the permutation relation for a given edge * - * @detail There are 2 relations associated with enforcing the wire copy relations + * @details There are 2 relations associated with enforcing the wire copy relations * This file handles the relation Z_perm_shift(n_last) = 0 via the relation: * * C(X) = L_LAST(X) * Z_perm_shift(X) * - * - * The final parameter is left to conform to the general argument structure (input,output, challenges) even though - * we don't need challenges in this relation. - * - */ - template - void add_edge_contribution(auto& extended_edges, - Univariate& evals, - T, - const FF& scaling_factor) - { - add_edge_contribution_internal(extended_edges, evals, scaling_factor); - }; - - /** - * @brief Internal function computing the actual contribution for GP intialization relation - * - * @param extended_edges - * @param evals + * @param evals transformed to `evals + C(extended_edges(X)...)*scaling_factor` + * @param extended_edges an std::array containing the fully extended Univariate edges. + * @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_internal(auto& extended_edges, - Univariate& evals, - const FF& scaling_factor) + void add_edge_contribution(Univariate& evals, + const auto& extended_edges, + const RelationParameters&, + const FF& scaling_factor) const { auto z_perm_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM_SHIFT]); auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); evals += (lagrange_last * z_perm_shift) * scaling_factor; - } - /** - * @brief A version of `add_edge_contribution` used for testing the relation - * - * @tparam T - * @param extended_edges - * @param evals - * @param challenges - */ - // TODO(kesha): Change once challenges are being supplied to regular contribution - template - void add_edge_contribution_testing(auto& extended_edges, Univariate& evals, T) - { - add_edge_contribution_internal(extended_edges, evals, FF::one()); - } + }; - template - void add_full_relation_value_contribution(auto& purported_evaluations, FF& full_honk_relation_value, T) + void add_full_relation_value_contribution(FF& full_honk_relation_value, + auto& purported_evaluations, + const RelationParameters&) const { auto z_perm_shift = purported_evaluations[MULTIVARIATE::Z_PERM_SHIFT]; auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; diff --git a/cpp/src/aztec/honk/sumcheck/relations/relation.test.cpp b/cpp/src/aztec/honk/sumcheck/relations/relation.test.cpp index cb7035fb44..5e87fa0eb8 100644 --- a/cpp/src/aztec/honk/sumcheck/relations/relation.test.cpp +++ b/cpp/src/aztec/honk/sumcheck/relations/relation.test.cpp @@ -4,7 +4,6 @@ #include "grand_product_initialization_relation.hpp" #include "grand_product_computation_relation.hpp" #include "../polynomials/univariate.hpp" -#include "../polynomials/barycentric_data.hpp" #include #include @@ -19,11 +18,15 @@ template class SumcheckRelation : public testing::Test { public: template using Univariate = Univariate; template using UnivariateView = UnivariateView; + static constexpr size_t FULL_RELATION_LENGH = 5; static const size_t NUM_POLYNOMIALS = bonk::StandardArithmetization::NUM_POLYNOMIALS; using POLYNOMIAL = bonk::StandardArithmetization::POLYNOMIAL; // TODO(luke): may want to make this more flexible/genericzs - static std::array, NUM_POLYNOMIALS> compute_mock_extended_edges() + // TODO(Adrian): Accept FULL_RELATION_LENGH as a template parameter for this function only, so that the test can + // decide to which degree the polynomials must be extended. Possible accept an existing list of "edges" and extend + // them to the degree. + static std::array, NUM_POLYNOMIALS> compute_mock_extended_edges() { // TODO(Cody): build from Univariate<2>'s? // evaluation form, i.e. w_l(0) = 1, w_l(1) = 2,.. The poly is x+1. @@ -72,6 +75,85 @@ template class SumcheckRelation : public testing::Test { return extended_edges; } + + /** + * @brief Returns randomly sampled parameters to feed to the relations. + * + * @return RelationParameters + */ + RelationParameters compute_mock_relation_parameters() + { + return { .zeta = FF::random_element(), + .alpha = FF::random_element(), + .beta = FF::random_element(), + .gamma = FF::random_element(), + .public_input_delta = FF::random_element() }; + } + + /** + * @brief Given an array of Univariates, create a new array containing only the i-th evaluations + * of all the univariates. + * + * @note Not really optimized, mainly used for testing that the relations evaluate to the same value when + * evaluated as Univariates, Expressions, or index-by-index + * @todo Maybe this is more helpful as part of a `check_logic` function. + * + * @tparam NUM_UNIVARIATES number of univariates in the input array (deduced from `univariates`) + * @tparam univariate_length number of evaluations (deduced from `univariates`) + * @param univariates array of Univariates + * @param i index of the evaluations we want to take from each univariate + * @return std::array such that result[j] = univariates[j].value_at(i) + */ + template + static std::array transposed_univariate_array_at( + const std::array, NUM_UNIVARIATES>& univariates, size_t i) + { + ASSERT(i < univariate_length); + std::array result; + for (size_t j = 0; j < NUM_UNIVARIATES; ++j) { + result[j] = univariates[j].value_at(i); + } + return result; + }; + + /** + * @brief Compute the evaluation of a `relation` in different ways, comparing it to the provided `expected_evals` + * + * @details Check both `add_full_relation_value_contribution` and `add_edge_contribution` by comparing the result to + * the `expected_evals` computed by the caller. + * Ensures that the relations compute the same result as the expression given in the tests. + * + * @param expected_evals Relation evaluation computed by the caller. + * @param relation being tested + * @param extended_edges + * @param relation_parameters + */ + static void validate_evaluations(const Univariate& expected_evals, + const auto relation, + const std::array, NUM_POLYNOMIALS>& extended_edges, + const RelationParameters& relation_parameters) + { + + // Compute the expression index-by-index + Univariate expected_evals_index{ 0 }; + for (size_t i = 0; i < FULL_RELATION_LENGH; ++i) { + // Get an array of the same size as `extended_edges` with only the i-th element of each extended edge. + std::array evals_i = transposed_univariate_array_at(extended_edges, i); + // Evaluate the relation + relation.add_full_relation_value_contribution( + expected_evals_index.value_at(i), evals_i, relation_parameters); + } + EXPECT_EQ(expected_evals, expected_evals_index); + + // Compute the expression using the class, that converts the extended edges to UnivariateView + auto expected_evals_view = Univariate(0); + relation.add_edge_contribution(expected_evals_view, extended_edges, relation_parameters, 1); + + // Tiny hack to reduce `expected_evals` to be of size `relation.RELATION_LENGTH` + Univariate expected_evals_restricted{ UnivariateView( + expected_evals) }; + EXPECT_EQ(expected_evals_restricted, expected_evals_view); + }; }; using FieldTypes = testing::Types; @@ -82,106 +164,93 @@ TYPED_TEST_SUITE(SumcheckRelation, FieldTypes); TYPED_TEST(SumcheckRelation, ArithmeticRelation) { SUMCHECK_RELATION_TYPE_ALIASES + using MULTIVARIATE = bonk::StandardArithmetization::POLYNOMIAL; - auto extended_edges = TestFixture::compute_mock_extended_edges(); + const auto extended_edges = TestFixture::compute_mock_extended_edges(); + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); auto relation = ArithmeticRelation(); - using MULTIVARIATE = bonk::StandardArithmetization::POLYNOMIAL; - // Manually compute the expected edge contribution - auto w_l = UnivariateView(extended_edges[MULTIVARIATE::W_L]); - auto w_r = UnivariateView(extended_edges[MULTIVARIATE::W_R]); - auto w_o = UnivariateView(extended_edges[MULTIVARIATE::W_O]); - auto q_m = UnivariateView(extended_edges[MULTIVARIATE::Q_M]); - auto q_l = UnivariateView(extended_edges[MULTIVARIATE::Q_L]); - auto q_r = UnivariateView(extended_edges[MULTIVARIATE::Q_R]); - auto q_o = UnivariateView(extended_edges[MULTIVARIATE::Q_O]); - auto q_c = UnivariateView(extended_edges[MULTIVARIATE::Q_C]); + const auto& w_l = extended_edges[MULTIVARIATE::W_L]; + const auto& w_r = extended_edges[MULTIVARIATE::W_R]; + const auto& w_o = extended_edges[MULTIVARIATE::W_O]; + const auto& q_m = extended_edges[MULTIVARIATE::Q_M]; + const auto& q_l = extended_edges[MULTIVARIATE::Q_L]; + const auto& q_r = extended_edges[MULTIVARIATE::Q_R]; + const auto& q_o = extended_edges[MULTIVARIATE::Q_O]; + const auto& q_c = extended_edges[MULTIVARIATE::Q_C]; + + // We first compute the evaluations using UnivariateViews, with the provided hard-coded formula. + // Ensure that expression changes are detected. // expected_evals, length 4, extends to { { 5, 22, 57, 116, 205} }; - Univariate expected_evals = (q_m * w_r * w_l) + (q_r * w_r) + (q_l * w_l) + (q_o * w_o) + q_c; - - auto evals = Univariate(); - relation.add_edge_contribution(extended_edges, evals, 0, FF::one()); - - EXPECT_EQ(evals, expected_evals); + auto expected_evals = (q_m * w_r * w_l) + (q_r * w_r) + (q_l * w_l) + (q_o * w_o) + (q_c); + this->validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); }; TYPED_TEST(SumcheckRelation, GrandProductComputationRelation) { SUMCHECK_RELATION_TYPE_ALIASES + using MULTIVARIATE = bonk::StandardArithmetization::POLYNOMIAL; + + const auto extended_edges = TestFixture::compute_mock_extended_edges(); + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); + + auto relation = GrandProductComputationRelation(); + const auto& beta = relation_parameters.beta; + const auto& gamma = relation_parameters.gamma; + const auto& public_input_delta = relation_parameters.public_input_delta; // TODO(luke): Write a test that illustrates the following? // Note: the below z_perm_shift = X^2 will fail because it results in a relation of degree 2*1*1*1 = 5 which // cannot be represented by 5 points. Therefore when we do the calculation then barycentrically extend, we are // effectively exprapolating a 4th degree polynomial instead of the correct 5th degree poly // auto z_perm_shift = Univariate({ 1, 4, 9, 16, 25 }); // X^2 - auto extended_edges = TestFixture::compute_mock_extended_edges(); - auto relation = GrandProductComputationRelation(); - using UnivariateView = UnivariateView; - using Univariate = Univariate; - // Manually compute the expected edge contribution - using MULTIVARIATE = bonk::StandardArithmetization::POLYNOMIAL; - - auto w_1 = UnivariateView(extended_edges[MULTIVARIATE::W_L]); - auto w_2 = UnivariateView(extended_edges[MULTIVARIATE::W_R]); - auto w_3 = UnivariateView(extended_edges[MULTIVARIATE::W_O]); - auto sigma_1 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_1]); - auto sigma_2 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_2]); - auto sigma_3 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_3]); - auto id_1 = UnivariateView(extended_edges[MULTIVARIATE::ID_1]); - auto id_2 = UnivariateView(extended_edges[MULTIVARIATE::ID_1]); - auto id_3 = UnivariateView(extended_edges[MULTIVARIATE::ID_1]); - auto z_perm = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM]); - auto z_perm_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM_SHIFT]); - auto lagrange_first = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_FIRST]); - auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); - - // TODO(luke): use real transcript/challenges once manifest is done - FF zeta = FF::random_element(); - FF beta = FF::random_element(); - FF gamma = FF::random_element(); - FF public_input_delta = FF::random_element(); - const RelationParameters relation_parameters = RelationParameters{ - .zeta = zeta, .alpha = FF ::zero(), .beta = beta, .gamma = gamma, .public_input_delta = public_input_delta - }; - - auto expected_evals = Univariate(); - // expected_evals in the below step { { 27, 250, 1029, 2916, 6655 } } - expected_evals += (z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * - (w_3 + id_3 * beta + gamma); - // expected_evals below is { { 27, 125, 343, 729, 1331 } } - expected_evals -= (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + sigma_1 * beta + gamma) * - (w_2 + sigma_2 * beta + gamma) * (w_3 + sigma_3 * beta + gamma); - - auto evals = Univariate(); - relation.add_edge_contribution(extended_edges, evals, relation_parameters, FF::one()); - - EXPECT_EQ(evals, expected_evals); + const auto& w_1 = extended_edges[MULTIVARIATE::W_L]; + const auto& w_2 = extended_edges[MULTIVARIATE::W_R]; + const auto& w_3 = extended_edges[MULTIVARIATE::W_O]; + const auto& sigma_1 = extended_edges[MULTIVARIATE::SIGMA_1]; + const auto& sigma_2 = extended_edges[MULTIVARIATE::SIGMA_2]; + const auto& sigma_3 = extended_edges[MULTIVARIATE::SIGMA_3]; + const auto& id_1 = extended_edges[MULTIVARIATE::ID_1]; + const auto& id_2 = extended_edges[MULTIVARIATE::ID_1]; + const auto& id_3 = extended_edges[MULTIVARIATE::ID_1]; + const auto& z_perm = extended_edges[MULTIVARIATE::Z_PERM]; + const auto& z_perm_shift = extended_edges[MULTIVARIATE::Z_PERM_SHIFT]; + const auto& lagrange_first = extended_edges[MULTIVARIATE::LAGRANGE_FIRST]; + const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; + + // We first compute the evaluations using UnivariateViews, with the provided hard-coded formula. + // Ensure that expression changes are detected. + // expected_evals in the below step { { 27, 250, 1029, 2916, 6655 } } - { { 27, 125, 343, 729, 1331 } } + auto expected_evals = (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) * + (w_2 + sigma_2 * beta + gamma) * (w_3 + sigma_3 * beta + gamma); + + this->validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); }; TYPED_TEST(SumcheckRelation, GrandProductInitializationRelation) { SUMCHECK_RELATION_TYPE_ALIASES + using MULTIVARIATE = bonk::StandardArithmetization::POLYNOMIAL; - auto extended_edges = TestFixture::compute_mock_extended_edges(); + const auto extended_edges = TestFixture::compute_mock_extended_edges(); + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); auto relation = GrandProductInitializationRelation(); - using UnivariateView = UnivariateView; - using Univariate = Univariate; // Manually compute the expected edge contribution - using MULTIVARIATE = bonk::StandardArithmetization::POLYNOMIAL; - auto z_perm_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM_SHIFT]); - auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); + const auto& z_perm_shift = extended_edges[MULTIVARIATE::Z_PERM_SHIFT]; + const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; + // We first compute the evaluations using UnivariateViews, with the provided hard-coded formula. + // Ensure that expression changes are detected. + // expected_evals, lenght 3 (coeff form = x^2 + x), extends to { { 0, 2, 6, 12, 20 } } auto expected_evals = z_perm_shift * lagrange_last; - // Compute the edge contribution using add_edge_contribution - auto evals = Univariate(); - relation.add_edge_contribution(extended_edges, evals, 0, FF::one()); - - EXPECT_EQ(evals, expected_evals); + this->validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); }; } // namespace honk_relation_tests \ No newline at end of file diff --git a/cpp/src/aztec/honk/sumcheck/sumcheck.test.cpp b/cpp/src/aztec/honk/sumcheck/sumcheck.test.cpp index 665d80a130..ea3be71f86 100644 --- a/cpp/src/aztec/honk/sumcheck/sumcheck.test.cpp +++ b/cpp/src/aztec/honk/sumcheck/sumcheck.test.cpp @@ -18,8 +18,6 @@ #include #include -#pragma GCC diagnostic ignored "-Wunused-variable" - using namespace honk; using namespace honk::sumcheck; @@ -136,14 +134,11 @@ Transcript produce_mocked_transcript(size_t multivariate_d, size_t num_public_in TEST(Sumcheck, PolynomialNormalization) { // Todo(Cody): We should not use real constants like this in the tests, at least not in so many of them. - const size_t num_polys(bonk::StandardArithmetization::NUM_POLYNOMIALS); const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); ; const size_t num_public_inputs(1); - constexpr size_t fr_size = 32; - // clang-format off std::array w_l = { 0, 1, 2, 3, 4, 5, 6, 7 }; std::array w_r = { 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -233,7 +228,6 @@ TEST(Sumcheck, Prover) const size_t num_public_inputs(1); // const size_t max_relation_length = 4; - constexpr size_t fr_size = 32; // clang-format off std::array w_l = { 1, 2, 0, 0}; @@ -306,11 +300,8 @@ TEST(Sumcheck, Prover) // TODO(luke): test possibly made obsolete by test ProverAndVerifierLonger TEST(Sumcheck, ProverAndVerifier) { - const size_t num_polys(bonk::StandardArithmetization::NUM_POLYNOMIALS); const size_t multivariate_d(1); const size_t multivariate_n(1 << multivariate_d); - const size_t max_relation_length = 6; - constexpr size_t fr_size = 32; const size_t num_public_inputs(1); std::array w_l = { 0, 1 }; @@ -375,14 +366,10 @@ TEST(Sumcheck, ProverAndVerifier) TEST(Sumcheck, ProverAndVerifierLonger) { auto run_test = [](bool expect_verified) { - const size_t num_polys(bonk::StandardArithmetization::NUM_POLYNOMIALS); const size_t multivariate_d(2); const size_t multivariate_n(1 << multivariate_d); const size_t num_public_inputs(0); - const size_t max_relation_length = honk::StandardHonk::MAX_RELATION_LENGTH; - constexpr size_t fr_size = 32; - // clang-format off std::array w_l; if (expect_verified) { w_l = { 0, 1, 2, 0 }; diff --git a/cpp/src/aztec/honk/sumcheck/sumcheck_round.hpp b/cpp/src/aztec/honk/sumcheck/sumcheck_round.hpp index 5d291f228f..ff2fd2a53f 100644 --- a/cpp/src/aztec/honk/sumcheck/sumcheck_round.hpp +++ b/cpp/src/aztec/honk/sumcheck/sumcheck_round.hpp @@ -151,32 +151,6 @@ template class... Relation } } - /** - * @brief Function accumulating relations for testing - * - * @details Get univariates from input instead of internal state. Uses submitted challenges - * - * @tparam relation_idx - * @tparam challenge_size - * @param internal_extended_edges - * @param internal_univariate_accumulators - * @param challenges - */ - template - void accumulate_relation_univariates_testing( - std::array, num_multivariates>& internal_extended_edges, - std::tuple::RELATION_LENGTH>...>& internal_univariate_accumulators, - std::array challenges) - { - std::get(relations).add_edge_contribution_testing( - internal_extended_edges, std::get(internal_univariate_accumulators), challenges); - - // Repeat for the next relation. - if constexpr (relation_idx + 1 < NUM_RELATIONS) { - accumulate_relation_univariates_testing( - internal_extended_edges, internal_univariate_accumulators, challenges); - } - } // TODO(Cody): make private /** * @brief For a given edge, calculate the contribution of each relation to the prover round univariate (S_l in the @@ -197,7 +171,7 @@ template class... Relation void accumulate_relation_univariates(const RelationParameters& relation_parameters, const FF& scaling_factor) { std::get(relations).add_edge_contribution( - extended_edges, std::get(univariate_accumulators), relation_parameters, scaling_factor); + std::get(univariate_accumulators), extended_edges, relation_parameters, scaling_factor); // Repeat for the next relation. if constexpr (relation_idx + 1 < NUM_RELATIONS) { @@ -221,7 +195,7 @@ template class... Relation const RelationParameters& relation_parameters) { std::get(relations).add_full_relation_value_contribution( - purported_evaluations, evaluations[relation_idx], relation_parameters); + evaluations[relation_idx], purported_evaluations, relation_parameters); // Repeat for the next relation. if constexpr (relation_idx + 1 < NUM_RELATIONS) {