diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp index 1211313af4a..e820310f7e0 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp @@ -38,7 +38,7 @@ TEST(Flavor, StandardGetters) Flavor::VerificationKey verification_key; Flavor::ProverPolynomials prover_polynomials; Flavor::ExtendedEdges edges; - Flavor::PurportedEvaluations evals; + Flavor::ClaimedEvaluations evals; Flavor::CommitmentLabels commitment_labels; // Globals are also available through STL container sizes @@ -120,11 +120,11 @@ TEST(Flavor, AllEntitiesSpecialMemberFunctions) { using Flavor = proof_system::honk::flavor::Standard; using FF = Flavor::FF; - using FoldedPolynomials = Flavor::FoldedPolynomials; + using PartiallyEvaluatedMultivariates = Flavor::PartiallyEvaluatedMultivariates; using Polynomial = Polynomial; - FoldedPolynomials polynomials_A; - std::vector random_poly{ 10 }; + PartiallyEvaluatedMultivariates polynomials_A; + auto random_poly = Polynomial(10); for (auto& coeff : random_poly) { coeff = FF::random_element(); } @@ -135,10 +135,10 @@ TEST(Flavor, AllEntitiesSpecialMemberFunctions) ASSERT_EQ(random_poly, polynomials_A.w_l); - FoldedPolynomials polynomials_B(polynomials_A); + PartiallyEvaluatedMultivariates polynomials_B(polynomials_A); ASSERT_EQ(random_poly, polynomials_B.w_l); - FoldedPolynomials polynomials_C(std::move(polynomials_B)); + PartiallyEvaluatedMultivariates polynomials_C(std::move(polynomials_B)); ASSERT_EQ(random_poly, polynomials_C.w_l); } diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp index a88c1b6cfc8..1557fb8814b 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp @@ -6,8 +6,12 @@ #include #include #include "barretenberg/honk/pcs/commitment_key.hpp" +#include "barretenberg/honk/sumcheck/polynomials/barycentric_data.hpp" #include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" #include "barretenberg/ecc/curves/bn254/g1.hpp" +#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" #include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/polynomials/evaluation_domain.hpp" @@ -48,6 +52,19 @@ class Standard { // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = 4; + // define the tuple of Relations that comprise the Sumcheck relation + using Relations = std::tuple, + sumcheck::GrandProductComputationRelation, + sumcheck::GrandProductInitializationRelation>; + + static constexpr size_t MAX_RELATION_LENGTH = get_max_relation_length(); + static constexpr size_t NUM_RELATIONS = std::tuple_size::value; + + // define the container for storing the univariate contribution from each relation in Sumcheck + using UnivariateTuple = decltype(create_univariate_tuple()); + // 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. @@ -190,10 +207,20 @@ class Standard { using ProverPolynomials = AllEntities; /** - * @brief A container for polynomials produced after the first round of sumcheck. - * @todo TODO(#394) Use polynomial classes for guaranteed memory alignment. + * @brief A container for storing the partially evaluated multivariates produced by sumcheck. */ - using FoldedPolynomials = AllEntities, PolynomialHandle>; + class PartiallyEvaluatedMultivariates : public AllEntities { + + public: + PartiallyEvaluatedMultivariates() = default; + PartiallyEvaluatedMultivariates(const size_t circuit_size) + { + // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + for (auto& poly : this->_data) { + poly = Polynomial(circuit_size / 2); + } + } + }; /** * @brief A container for univariates produced during the hot loop in sumcheck. @@ -207,11 +234,11 @@ class Standard { * @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the * evaluations of polynomials committed in earlier rounds. */ - class PurportedEvaluations : public AllEntities { + class ClaimedEvaluations : public AllEntities { public: using Base = AllEntities; using Base::Base; - PurportedEvaluations(std::array _data_in) { this->_data = _data_in; } + ClaimedEvaluations(std::array _data_in) { this->_data = _data_in; } }; /** diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp index 1c9ac163261..a3d016bd602 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp @@ -6,6 +6,7 @@ #include #include #include "barretenberg/honk/pcs/commitment_key.hpp" +#include "barretenberg/honk/sumcheck/polynomials/barycentric_data.hpp" #include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" #include "barretenberg/ecc/curves/bn254/g1.hpp" #include "barretenberg/honk/transcript/transcript.hpp" @@ -15,6 +16,14 @@ #include "barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp" #include "barretenberg/srs/reference_string/reference_string.hpp" #include "barretenberg/proof_system/flavor/flavor.hpp" +#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/gen_perm_sort_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/elliptic_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/auxiliary_relation.hpp" namespace proof_system::honk::flavor { @@ -41,6 +50,25 @@ class Ultra { // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = 11; + // define the tuple of Relations that comprise the Sumcheck relation + using Relations = std::tuple, + sumcheck::UltraArithmeticRelationSecondary, + sumcheck::UltraGrandProductComputationRelation, + sumcheck::UltraGrandProductInitializationRelation, + sumcheck::LookupGrandProductComputationRelation, + sumcheck::LookupGrandProductInitializationRelation, + sumcheck::GenPermSortRelation, + sumcheck::EllipticRelation, + sumcheck::AuxiliaryRelation>; + + static constexpr size_t MAX_RELATION_LENGTH = get_max_relation_length(); + static constexpr size_t NUM_RELATIONS = std::tuple_size::value; + + // define the container for storing the univariate contribution from each relation in Sumcheck + using UnivariateTuple = decltype(create_univariate_tuple()); + // define utilities to extend univarates from RELATION_LENGTH to MAX_RELATION_LENGTH for each Relation + using BarycentricUtils = decltype(create_barycentric_utils()); + private: template /** @@ -249,10 +277,20 @@ class Ultra { using ProverPolynomials = AllEntities; /** - * @brief A container for polynomials produced after the first round of sumcheck. - * @todo TODO(#394) Use polynomial classes for guaranteed memory alignment. + * @brief A container for storing the partially evaluated multivariates produced by sumcheck. */ - using FoldedPolynomials = AllEntities, PolynomialHandle>; + class PartiallyEvaluatedMultivariates : public AllEntities { + + public: + PartiallyEvaluatedMultivariates() = default; + PartiallyEvaluatedMultivariates(const size_t circuit_size) + { + // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + for (auto& poly : this->_data) { + poly = Polynomial(circuit_size / 2); + } + } + }; /** * @brief A container for univariates produced during the hot loop in sumcheck. @@ -266,11 +304,11 @@ class Ultra { * @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the * evaluations of polynomials committed in earlier rounds. */ - class PurportedEvaluations : public AllEntities { + class ClaimedEvaluations : public AllEntities { public: using Base = AllEntities; using Base::Base; - PurportedEvaluations(std::array _data_in) { this->_data = _data_in; } + ClaimedEvaluations(std::array _data_in) { this->_data = _data_in; } }; /** diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp index ca92ca8f271..6747fc0bee4 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp @@ -3,9 +3,6 @@ #include "barretenberg/honk/sumcheck/sumcheck.hpp" #include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/honk/utils/power_polynomial.hpp" -#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" #include "barretenberg/honk/flavor/standard.hpp" namespace proof_system::honk { @@ -130,11 +127,7 @@ template void StandardProver_::execute_grand_pro * */ template void StandardProver_::execute_relation_check_rounds() { - using Sumcheck = sumcheck::Sumcheck, - sumcheck::ArithmeticRelation, - sumcheck::GrandProductComputationRelation, - sumcheck::GrandProductInitializationRelation>; + using Sumcheck = sumcheck::Sumcheck>; auto sumcheck = Sumcheck(key->circuit_size, transcript); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp index ad6cb81d70d..f0d7d26089c 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp @@ -2,8 +2,6 @@ #include #include #include "barretenberg/honk/proof_system/prover_library.hpp" -#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp" #include "barretenberg/honk/sumcheck/sumcheck.hpp" #include #include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" // will go away @@ -15,13 +13,6 @@ #include #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/ecc/curves/bn254/g1.hpp" -#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/gen_perm_sort_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/elliptic_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/auxiliary_relation.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/transcript/transcript_wrappers.hpp" #include @@ -191,17 +182,7 @@ template void UltraProver_::execute_grand_product_c */ template void UltraProver_::execute_relation_check_rounds() { - using Sumcheck = sumcheck::Sumcheck, - sumcheck::UltraArithmeticRelation, - sumcheck::UltraArithmeticRelationSecondary, - sumcheck::UltraGrandProductComputationRelation, - sumcheck::UltraGrandProductInitializationRelation, - sumcheck::LookupGrandProductComputationRelation, - sumcheck::LookupGrandProductInitializationRelation, - sumcheck::GenPermSortRelation, - sumcheck::EllipticRelation, - sumcheck::AuxiliaryRelation>; + using Sumcheck = sumcheck::Sumcheck>; auto sumcheck = Sumcheck(key->circuit_size, transcript); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp index 194d44b6e95..628a969d26c 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp @@ -4,14 +4,6 @@ #include "barretenberg/honk/flavor/standard.hpp" #include "barretenberg/ecc/curves/bn254/scalar_multiplication/scalar_multiplication.hpp" #include "barretenberg/honk/utils/power_polynomial.hpp" -#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/gen_perm_sort_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/elliptic_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/auxiliary_relation.hpp" #pragma GCC diagnostic ignored "-Wunused-variable" @@ -107,17 +99,7 @@ template bool UltraVerifier_::verify_proof(const plonk commitments.z_lookup = transcript.template receive_from_prover(commitment_labels.z_lookup); // Execute Sumcheck Verifier - auto sumcheck = Sumcheck, - honk::sumcheck::UltraArithmeticRelation, - honk::sumcheck::UltraArithmeticRelationSecondary, - honk::sumcheck::UltraGrandProductComputationRelation, - honk::sumcheck::UltraGrandProductInitializationRelation, - honk::sumcheck::LookupGrandProductComputationRelation, - honk::sumcheck::LookupGrandProductInitializationRelation, - honk::sumcheck::GenPermSortRelation, - honk::sumcheck::EllipticRelation, - honk::sumcheck::AuxiliaryRelation>(circuit_size, transcript); + auto sumcheck = Sumcheck>(circuit_size, transcript); std::optional sumcheck_output = sumcheck.execute_verifier(relation_parameters); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp index 6238f6e2e1f..3506f15aaa9 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp @@ -4,9 +4,6 @@ #include "barretenberg/honk/flavor/standard.hpp" #include "barretenberg/ecc/curves/bn254/scalar_multiplication/scalar_multiplication.hpp" #include "barretenberg/honk/utils/power_polynomial.hpp" -#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" using namespace barretenberg; using namespace proof_system::honk::sumcheck; @@ -111,11 +108,7 @@ template bool StandardVerifier_::verify_proof(const pl commitments.z_perm = transcript.template receive_from_prover(commitment_labels.z_perm); // Execute Sumcheck Verifier - auto sumcheck = Sumcheck, - honk::sumcheck::ArithmeticRelation, - honk::sumcheck::GrandProductComputationRelation, - honk::sumcheck::GrandProductInitializationRelation>(circuit_size, transcript); + auto sumcheck = Sumcheck>(circuit_size, transcript); std::optional sumcheck_output = sumcheck.execute_verifier(relation_parameters); // If Sumcheck does not return an output, sumcheck verification has failed diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/barycentric_data.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/barycentric_data.hpp index ae2d5f5d9b2..f7e13ceabf5 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/barycentric_data.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/barycentric_data.hpp @@ -6,12 +6,10 @@ /* IMPROVEMENT(Cody): This could or should be improved in various ways. In no particular order: 1) Edge cases are not considered. One non-use case situation (I forget which) leads to a segfault. - 2) This could all be constexpr. - - 3) Precomputing for all possible size pairs is probably feasible and might be a better solution than instantiating + 2) Precomputing for all possible size pairs is probably feasible and might be a better solution than instantiating many instances separately. Then perhaps we could infer input type to `extend`. - 4) There should be more thorough testing of this class in isolation. + 3) There should be more thorough testing of this class in isolation. */ namespace proof_system::honk::sumcheck { @@ -23,54 +21,77 @@ namespace proof_system::honk::sumcheck { template class BarycentricData { public: static constexpr size_t big_domain_size = std::max(domain_size, num_evals); - // TODO(#224)(Cody): these should be static, also constexpr, but arrays are not constexpr - std::array big_domain; - std::array lagrange_denominators; - std::array precomputed_denominator_inverses; - std::array full_numerator_values; - constexpr BarycentricData() + /** + * Static constexpr methods for computing arrays of precomputable data used for barycentric extension and evaluation + */ + + // build big_domain, currently the set of x_i in {0, 1, ..., t-1} + static constexpr std::array construct_big_domain() { - // build big_domain, currently the set of x_i in {0, 1, ..., t-1} - for (size_t i = 0; i != big_domain_size; ++i) { - big_domain[i] = i; + std::array result; + for (size_t i = 0; i < big_domain_size; ++i) { + result[i] = static_cast(i); } + return result; + } - // build set of lagrange_denominators d_i = \prod_{j!=i} x_i - x_j + // build set of lagrange_denominators d_i = \prod_{j!=i} x_i - x_j + static constexpr std::array construct_lagrange_denominators(const auto& big_domain) + { + std::array result; for (size_t i = 0; i != domain_size; ++i) { - lagrange_denominators[i] = 1; + result[i] = 1; for (size_t j = 0; j != domain_size; ++j) { if (j != i) { - lagrange_denominators[i] *= big_domain[i] - big_domain[j]; + result[i] *= big_domain[i] - big_domain[j]; } } } + return result; + } - // for each x_k in the big domain, build set of domain size-many denominator inverses - // 1/(d_i*(x_k - x_j)). will multiply against each of these (rather than to divide by something) - // for each barycentric evaluation - for (size_t k = domain_size; k != num_evals; ++k) { - for (size_t j = 0; j != domain_size; ++j) { + // for each x_k in the big domain, build set of domain size-many denominator inverses + // 1/(d_i*(x_k - x_j)). will multiply against each of these (rather than to divide by something) + // for each barycentric evaluation + static constexpr std::array construct_denominator_inverses( + const auto& big_domain, const auto& lagrange_denominators) + { + std::array result{}; // default init to 0 since below does not init all elements + for (size_t k = domain_size; k < num_evals; ++k) { + for (size_t j = 0; j < domain_size; ++j) { Fr inv = lagrange_denominators[j]; inv *= (big_domain[k] - big_domain[j]); inv = Fr(1) / inv; // prob have self_inverse method; should be part of Field concept - precomputed_denominator_inverses[k * domain_size + j] = inv; + result[k * domain_size + j] = inv; } } + return result; + } - // get full numerator values - // full numerator is M(x) = \prod_{i} (x-x_i) - // these will be zero for i < domain_size, but that's ok because - // at such entries we will already have the evaluations of the polynomial + // get full numerator values + // full numerator is M(x) = \prod_{i} (x-x_i) + // these will be zero for i < domain_size, but that's ok because + // at such entries we will already have the evaluations of the polynomial + static constexpr std::array construct_full_numerator_values(const auto& big_domain) + { + std::array result; for (size_t i = 0; i != num_evals; ++i) { - full_numerator_values[i] = 1; + result[i] = 1; Fr v_i = i; for (size_t j = 0; j != domain_size; ++j) { - full_numerator_values[i] *= v_i - big_domain[j]; + result[i] *= v_i - big_domain[j]; } } + return result; } + static constexpr auto big_domain = construct_big_domain(); + static constexpr auto lagrange_denominators = construct_lagrange_denominators(big_domain); + static constexpr auto precomputed_denominator_inverses = + construct_denominator_inverses(big_domain, lagrange_denominators); + static constexpr auto full_numerator_values = construct_full_numerator_values(big_domain); + /** * @brief Given A univariate f represented by {f(0), ..., f(t-1)}, compute {f(t), ..., f(u-1)} * and return the Univariate represented by {f(0), ..., f(u-1)}. diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp index 3e40df01134..f7417d5624d 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp @@ -61,23 +61,23 @@ TYPED_TEST(MultivariatesTests, FoldTwoRoundsSpecial) auto full_polynomials = std::array, 1>({ f0 }); auto transcript = Transcript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto sumcheck = Sumcheck(multivariate_n, transcript); FF round_challenge_0 = { 0x6c7301b49d85a46c, 0x44311531e39c64f6, 0xb13d66d8d6c1a24c, 0x04410c360230a295 }; round_challenge_0.self_to_montgomery_form(); FF expected_lo = v00 * (FF(1) - round_challenge_0) + v10 * round_challenge_0; FF expected_hi = v01 * (FF(1) - round_challenge_0) + v11 * round_challenge_0; - sumcheck.fold(full_polynomials, multivariate_n, round_challenge_0); + sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], round_challenge_0); - EXPECT_EQ(sumcheck.folded_polynomials[0][1], FF(0)); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], round_challenge_0); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][1], FF(0)); FF round_challenge_1 = 2; FF expected_val = expected_lo * (FF(1) - round_challenge_1) + expected_hi * round_challenge_1; - sumcheck.fold(sumcheck.folded_polynomials, multivariate_n >> 1, round_challenge_1); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_val); + sumcheck.partially_evaluate(sumcheck.partially_evaluated_polynomials, multivariate_n >> 1, round_challenge_1); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], expected_val); } TYPED_TEST(MultivariatesTests, FoldTwoRoundsGeneric) @@ -98,21 +98,21 @@ TYPED_TEST(MultivariatesTests, FoldTwoRoundsGeneric) auto full_polynomials = std::array, 1>({ f0 }); auto transcript = Transcript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto sumcheck = Sumcheck(multivariate_n, transcript); FF round_challenge_0 = FF::random_element(); FF expected_lo = v00 * (FF(1) - round_challenge_0) + v10 * round_challenge_0; FF expected_hi = v01 * (FF(1) - round_challenge_0) + v11 * round_challenge_0; - sumcheck.fold(full_polynomials, multivariate_n, round_challenge_0); + sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_lo); - EXPECT_EQ(sumcheck.folded_polynomials[0][1], expected_hi); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], expected_lo); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][1], expected_hi); FF round_challenge_1 = FF::random_element(); FF expected_val = expected_lo * (FF(1) - round_challenge_1) + expected_hi * round_challenge_1; - sumcheck.fold(sumcheck.folded_polynomials, multivariate_n >> 1, round_challenge_1); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_val); + sumcheck.partially_evaluate(sumcheck.partially_evaluated_polynomials, multivariate_n >> 1, round_challenge_1); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], expected_val); } /* @@ -159,7 +159,7 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsSpecial) auto full_polynomials = std::array, 1>({ f0 }); auto transcript = Transcript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto sumcheck = Sumcheck(multivariate_n, transcript); FF round_challenge_0 = 1; FF expected_q1 = v000 * (FF(1) - round_challenge_0) + v100 * round_challenge_0; // 2 @@ -167,25 +167,25 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsSpecial) FF expected_q3 = v001 * (FF(1) - round_challenge_0) + v101 * round_challenge_0; // 6 FF expected_q4 = v011 * (FF(1) - round_challenge_0) + v111 * round_challenge_0; // 8 - sumcheck.fold(full_polynomials, multivariate_n, round_challenge_0); + sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_q1); - EXPECT_EQ(sumcheck.folded_polynomials[0][1], expected_q2); - EXPECT_EQ(sumcheck.folded_polynomials[0][2], expected_q3); - EXPECT_EQ(sumcheck.folded_polynomials[0][3], expected_q4); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], expected_q1); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][1], expected_q2); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][2], expected_q3); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][3], expected_q4); FF round_challenge_1 = 2; FF expected_lo = expected_q1 * (FF(1) - round_challenge_1) + expected_q2 * round_challenge_1; // 6 FF expected_hi = expected_q3 * (FF(1) - round_challenge_1) + expected_q4 * round_challenge_1; // 10 - sumcheck.fold(sumcheck.folded_polynomials, multivariate_n >> 1, round_challenge_1); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_lo); - EXPECT_EQ(sumcheck.folded_polynomials[0][1], expected_hi); + sumcheck.partially_evaluate(sumcheck.partially_evaluated_polynomials, multivariate_n >> 1, round_challenge_1); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], expected_lo); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][1], expected_hi); FF round_challenge_2 = 3; FF expected_val = expected_lo * (FF(1) - round_challenge_2) + expected_hi * round_challenge_2; // 18 - sumcheck.fold(sumcheck.folded_polynomials, multivariate_n >> 2, round_challenge_2); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_val); + sumcheck.partially_evaluate(sumcheck.partially_evaluated_polynomials, multivariate_n >> 2, round_challenge_2); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], expected_val); } TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) @@ -210,7 +210,7 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) auto full_polynomials = std::array, 1>({ f0 }); auto transcript = Transcript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto sumcheck = Sumcheck(multivariate_n, transcript); FF round_challenge_0 = FF::random_element(); FF expected_q1 = v000 * (FF(1) - round_challenge_0) + v100 * round_challenge_0; @@ -218,25 +218,25 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) FF expected_q3 = v001 * (FF(1) - round_challenge_0) + v101 * round_challenge_0; FF expected_q4 = v011 * (FF(1) - round_challenge_0) + v111 * round_challenge_0; - sumcheck.fold(full_polynomials, multivariate_n, round_challenge_0); + sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_q1); - EXPECT_EQ(sumcheck.folded_polynomials[0][1], expected_q2); - EXPECT_EQ(sumcheck.folded_polynomials[0][2], expected_q3); - EXPECT_EQ(sumcheck.folded_polynomials[0][3], expected_q4); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], expected_q1); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][1], expected_q2); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][2], expected_q3); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][3], expected_q4); FF round_challenge_1 = FF::random_element(); FF expected_lo = expected_q1 * (FF(1) - round_challenge_1) + expected_q2 * round_challenge_1; FF expected_hi = expected_q3 * (FF(1) - round_challenge_1) + expected_q4 * round_challenge_1; - sumcheck.fold(sumcheck.folded_polynomials, multivariate_n >> 1, round_challenge_1); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_lo); - EXPECT_EQ(sumcheck.folded_polynomials[0][1], expected_hi); + sumcheck.partially_evaluate(sumcheck.partially_evaluated_polynomials, multivariate_n >> 1, round_challenge_1); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], expected_lo); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][1], expected_hi); FF round_challenge_2 = FF::random_element(); FF expected_val = expected_lo * (FF(1) - round_challenge_2) + expected_hi * round_challenge_2; - sumcheck.fold(sumcheck.folded_polynomials, multivariate_n >> 2, round_challenge_2); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_val); + sumcheck.partially_evaluate(sumcheck.partially_evaluated_polynomials, multivariate_n >> 2, round_challenge_2); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[0][0], expected_val); } TYPED_TEST(MultivariatesTests, FoldThreeRoundsGenericMultiplePolys) @@ -272,7 +272,7 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGenericMultiplePolys) auto full_polynomials = std::array, 3>{ f0, f1, f2 }; auto transcript = Transcript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto sumcheck = Sumcheck(multivariate_n, transcript); std::array expected_q1; std::array expected_q2; @@ -286,12 +286,12 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGenericMultiplePolys) expected_q4[i] = v011[i] * (FF(1) - round_challenge_0) + v111[i] * round_challenge_0; } - sumcheck.fold(full_polynomials, multivariate_n, round_challenge_0); + sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); for (size_t i = 0; i < 3; i++) { - EXPECT_EQ(sumcheck.folded_polynomials[i][0], expected_q1[i]); - EXPECT_EQ(sumcheck.folded_polynomials[i][1], expected_q2[i]); - EXPECT_EQ(sumcheck.folded_polynomials[i][2], expected_q3[i]); - EXPECT_EQ(sumcheck.folded_polynomials[i][3], expected_q4[i]); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[i][0], expected_q1[i]); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[i][1], expected_q2[i]); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[i][2], expected_q3[i]); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[i][3], expected_q4[i]); } FF round_challenge_1 = FF::random_element(); @@ -301,19 +301,19 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGenericMultiplePolys) expected_lo[i] = expected_q1[i] * (FF(1) - round_challenge_1) + expected_q2[i] * round_challenge_1; expected_hi[i] = expected_q3[i] * (FF(1) - round_challenge_1) + expected_q4[i] * round_challenge_1; } - sumcheck.fold(sumcheck.folded_polynomials, multivariate_n >> 1, round_challenge_1); + sumcheck.partially_evaluate(sumcheck.partially_evaluated_polynomials, multivariate_n >> 1, round_challenge_1); for (size_t i = 0; i < 3; i++) { - EXPECT_EQ(sumcheck.folded_polynomials[i][0], expected_lo[i]); - EXPECT_EQ(sumcheck.folded_polynomials[i][1], expected_hi[i]); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[i][0], expected_lo[i]); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[i][1], expected_hi[i]); } FF round_challenge_2 = FF::random_element(); std::array expected_val; for (size_t i = 0; i < 3; i++) { expected_val[i] = expected_lo[i] * (FF(1) - round_challenge_2) + expected_hi[i] * round_challenge_2; } - sumcheck.fold(sumcheck.folded_polynomials, multivariate_n >> 2, round_challenge_2); + sumcheck.partially_evaluate(sumcheck.partially_evaluated_polynomials, multivariate_n >> 2, round_challenge_2); for (size_t i = 0; i < 3; i++) { - EXPECT_EQ(sumcheck.folded_polynomials[i][0], expected_val[i]); + EXPECT_EQ(sumcheck.partially_evaluated_polynomials[i][0], expected_val[i]); } } diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp index be3cce97088..0747a5b4f0c 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp @@ -33,7 +33,7 @@ class StandardRelationConsistency : public testing::Test { public: using Flavor = honk::flavor::Standard; using FF = typename Flavor::FF; - using PurportedEvaluations = typename Flavor::PurportedEvaluations; + using ClaimedEvaluations = typename Flavor::ClaimedEvaluations; // TODO(#390): Move MAX_RELATION_LENGTH into Flavor and simplify this. template using ExtendedEdges = typename Flavor::template ExtendedEdges; @@ -82,7 +82,7 @@ class StandardRelationConsistency : public testing::Test { * @return std::array such that result[j] = univariates[j].value_at(i) */ template - static PurportedEvaluations transposed_univariate_array_at(ExtendedEdges univariates, size_t i) + static ClaimedEvaluations transposed_univariate_array_at(ExtendedEdges univariates, size_t i) { ASSERT(i < univariate_length); std::array result; @@ -117,7 +117,7 @@ class StandardRelationConsistency : public testing::Test { Univariate expected_evals_index{ 0 }; for (size_t i = 0; i < FULL_RELATION_LENGTH; ++i) { // Get an array of the same size as `extended_edges` with only the i-th element of each extended edge. - PurportedEvaluations evals_i = transposed_univariate_array_at(extended_edges, i); + ClaimedEvaluations 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); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp index d9b1bc3a3e5..704cdc82e9b 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp @@ -42,7 +42,7 @@ TEST(RelationCorrectness, StandardRelationCorrectness) using Flavor = honk::flavor::Standard; using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; - using PurportedEvaluations = typename Flavor::PurportedEvaluations; + using ClaimedEvaluations = typename Flavor::ClaimedEvaluations; // Create a composer and a dummy circuit with a few gates auto composer = StandardHonkComposer(); @@ -115,7 +115,7 @@ TEST(RelationCorrectness, StandardRelationCorrectness) for (size_t i = 0; i < prover.key->circuit_size; i++) { // Compute an array containing all the evaluations at a given row i - PurportedEvaluations evaluations_at_index_i; + ClaimedEvaluations evaluations_at_index_i; size_t poly_idx = 0; for (auto& polynomial : prover_polynomials) { evaluations_at_index_i[poly_idx] = polynomial[i]; @@ -154,7 +154,7 @@ TEST(RelationCorrectness, UltraRelationCorrectness) using Flavor = honk::flavor::Ultra; using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; - using PurportedEvaluations = typename Flavor::PurportedEvaluations; + using ClaimedEvaluations = typename Flavor::ClaimedEvaluations; // Create a composer and then add an assortment of gates designed to ensure that the constraint(s) represented // by each relation are non-trivially exercised. @@ -379,7 +379,7 @@ TEST(RelationCorrectness, UltraRelationCorrectness) fr result = 0; for (size_t i = 0; i < prover.key->circuit_size; i++) { // Compute an array containing all the evaluations at a given row i - PurportedEvaluations evaluations_at_index_i; + ClaimedEvaluations evaluations_at_index_i; size_t poly_idx = 0; for (auto& polynomial : prover_polynomials) { evaluations_at_index_i[poly_idx] = polynomial[i]; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp index e363dd8725b..ce44727e480 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp @@ -36,7 +36,7 @@ class UltraRelationConsistency : public testing::Test { public: using Flavor = honk::flavor::Ultra; using FF = typename Flavor::FF; - using PurportedEvaluations = typename Flavor::PurportedEvaluations; + using ClaimedEvaluations = typename Flavor::ClaimedEvaluations; // TODO(#390): Move MAX_RELATION_LENGTH into Flavor and simplify this. template using ExtendedEdges = typename Flavor::template ExtendedEdges; @@ -83,7 +83,7 @@ class UltraRelationConsistency : public testing::Test { * @return std::array such that result[j] = univariates[j].value_at(i) */ template - static PurportedEvaluations transposed_univariate_array_at(ExtendedEdges univariates, size_t i) + static ClaimedEvaluations transposed_univariate_array_at(ExtendedEdges univariates, size_t i) { ASSERT(i < univariate_length); std::array result; @@ -118,7 +118,7 @@ class UltraRelationConsistency : public testing::Test { Univariate expected_evals_index{ 0 }; for (size_t i = 0; i < FULL_RELATION_LENGTH; ++i) { // Get an array of the same size as `extended_edges` with only the i-th element of each extended edge. - PurportedEvaluations evals_i = transposed_univariate_array_at(extended_edges, i); + ClaimedEvaluations 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); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp index 8968ee12609..3e6794e18a7 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp @@ -18,29 +18,31 @@ namespace proof_system::honk::sumcheck { -template class... Relations> class Sumcheck { +template class Sumcheck { public: using FF = typename Flavor::FF; - using FoldedPolynomials = typename Flavor::FoldedPolynomials; - using PurportedEvaluations = typename Flavor::PurportedEvaluations; + using PartiallyEvaluatedMultivariates = typename Flavor::PartiallyEvaluatedMultivariates; + using ClaimedEvaluations = typename Flavor::ClaimedEvaluations; - static constexpr size_t MAX_RELATION_LENGTH = std::max({ Relations::RELATION_LENGTH... }); + static constexpr size_t MAX_RELATION_LENGTH = Flavor::MAX_RELATION_LENGTH; static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; Transcript& transcript; const size_t multivariate_n; const size_t multivariate_d; - SumcheckRound round; + SumcheckRound round; /** * - * @brief (folded_polynomials) Suppose the Honk polynomials (multilinear in d variables) are called P_1, ..., P_N. + * @brief (partially_evaluated_polynomials) Suppose the Honk polynomials (multilinear in d variables) are called P_1, + ..., P_N. * At initialization, * we think of these as lying in a two-dimensional array, where each column records the value of one P_i on H^d. - * After the first round, the array will be updated ('folded'), so that the first n/2 rows will represent the + * After the first round, the array will be updated (partially evaluated), so that the first n/2 rows will represent + the * evaluations P_i(u0, X1, ..., X_{d-1}) as a low-degree extension on H^{d-1}. In reality, we elude copying all - * of the polynomial-defining data by only populating folded_multivariates after the first round. I.e.: + * of the polynomial-defining data by only populating partially_evaluated_polynomials after the first round. I.e.: We imagine all of the defining polynomial data in a matrix like this: | P_1 | P_2 | P_3 | P_4 | ... | P_N | N = number of multivariatesk @@ -54,7 +56,7 @@ template class... Relations \-| * | * | * | * | ... | * | vertex n-1 m = n/2 * - Each group consists of N edges |, and our construction of univariates and folding + Each group consists of N edges |, and our construction of univariates and partial evaluation * operations naturally operate on these groups of edges @@ -62,30 +64,26 @@ template class... Relations * NOTE: With ~40 columns, prob only want to allocate 256 EdgeGroup's at once to keep stack under 1MB? * TODO(#224)(Cody): might want to just do C-style multidimensional array? for guaranteed adjacency? */ - FoldedPolynomials folded_polynomials; + PartiallyEvaluatedMultivariates partially_evaluated_polynomials; // prover instantiates sumcheck with circuit size and a prover transcript Sumcheck(size_t multivariate_n, ProverTranscript& transcript) : transcript(transcript) , multivariate_n(multivariate_n) , multivariate_d(numeric::get_msb(multivariate_n)) - , round(multivariate_n, std::tuple(Relations()...)) - { - for (auto& polynomial : folded_polynomials) { - polynomial.resize(multivariate_n >> 1); - } - }; + , round(multivariate_n) + , partially_evaluated_polynomials(multivariate_n){}; // verifier instantiates sumcheck with circuit size and a verifier transcript explicit Sumcheck(size_t multivariate_n, VerifierTranscript& transcript) : transcript(transcript) , multivariate_n(multivariate_n) , multivariate_d(numeric::get_msb(multivariate_n)) - , round(std::tuple(Relations()...)){}; + , round(){}; /** - * @brief Compute univariate restriction place in transcript, generate challenge, fold,... repeat until final round, - * then compute multivariate evaluations and place in transcript. + * @brief Compute univariate restriction place in transcript, generate challenge, partially evaluate,... repeat + * until final round, then compute multivariate evaluations and place in transcript. * * @details */ @@ -100,32 +98,34 @@ template class... Relations multivariate_challenge.reserve(multivariate_d); // First round - // This populates folded_polynomials. + // This populates partially_evaluated_polynomials. auto round_univariate = round.compute_univariate(full_polynomials, relation_parameters, pow_univariate, alpha); transcript.send_to_verifier("Sumcheck:univariate_0", round_univariate); FF round_challenge = transcript.get_challenge("Sumcheck:u_0"); multivariate_challenge.emplace_back(round_challenge); - fold(full_polynomials, multivariate_n, round_challenge); + partially_evaluate(full_polynomials, multivariate_n, round_challenge); pow_univariate.partially_evaluate(round_challenge); - round.round_size = round.round_size >> 1; // TODO(#224)(Cody): Maybe fold should do this and release memory? + round.round_size = + round.round_size >> 1; // TODO(#224)(Cody): Maybe partially_evaluate should do this and release memory? // All but final round - // We operate on folded_polynomials in place. + // We operate on partially_evaluated_polynomials in place. for (size_t round_idx = 1; round_idx < multivariate_d; round_idx++) { // Write the round univariate to the transcript - round_univariate = round.compute_univariate(folded_polynomials, relation_parameters, pow_univariate, alpha); + round_univariate = + round.compute_univariate(partially_evaluated_polynomials, relation_parameters, pow_univariate, alpha); transcript.send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate); FF round_challenge = transcript.get_challenge("Sumcheck:u_" + std::to_string(round_idx)); multivariate_challenge.emplace_back(round_challenge); - fold(folded_polynomials, round.round_size, round_challenge); + partially_evaluate(partially_evaluated_polynomials, round.round_size, round_challenge); pow_univariate.partially_evaluate(round_challenge); round.round_size = round.round_size >> 1; } - // Final round: Extract multivariate evaluations from folded_polynomials and add to transcript - PurportedEvaluations multivariate_evaluations; + // Final round: Extract multivariate evaluations from partially_evaluated_polynomials and add to transcript + ClaimedEvaluations multivariate_evaluations; size_t evaluation_idx = 0; - for (auto& polynomial : folded_polynomials) { // TODO(#391) zip + for (auto& polynomial : partially_evaluated_polynomials) { // TODO(#391) zip multivariate_evaluations[evaluation_idx] = polynomial[0]; ++evaluation_idx; } @@ -178,7 +178,7 @@ template class... Relations } // Final round - PurportedEvaluations purported_evaluations = + ClaimedEvaluations purported_evaluations = transcript.template receive_from_prover>("Sumcheck:evaluations"); FF full_honk_relation_purported_value = round.compute_full_honk_relation_purported_value( @@ -191,14 +191,12 @@ template class... Relations return SumcheckOutput{ multivariate_challenge, purported_evaluations }; }; - // TODO(#224)(Cody): Rename. fold is not descriptive, and it's already in use in the Gemini context. - // Probably just call it partial_evaluation? /** * @brief Evaluate at the round challenge and prepare class for next round. * Illustration of layout in example of first round when d==3 (showing just one Honk polynomial, * i.e., what happens in just one column of our two-dimensional array): * - * groups vertex terms collected vertex terms groups after folding + * groups vertex terms collected vertex terms groups after partial evaluation * g0 -- v0 (1-X0)(1-X1)(1-X2) --- (v0(1-X0) + v1 X0) (1-X1)(1-X2) ---- (v0(1-u0) + v1 u0) (1-X1)(1-X2) * \- v1 X0 (1-X1)(1-X2) --/ --- (v2(1-u0) + v3 u0) X1 (1-X2) * g1 -- v2 (1-X0) X1 (1-X2) --- (v2(1-X0) + v3 X0) X1 (1-X2)-/ -- (v4(1-u0) + v5 u0) (1-X1) X2 @@ -210,12 +208,12 @@ template class... Relations * * @param challenge */ - void fold(auto& polynomials, size_t round_size, FF round_challenge) + void partially_evaluate(auto& polynomials, size_t round_size, FF round_challenge) { - // after the first round, operate in place on folded_polynomials + // after the first round, operate in place on partially_evaluated_polynomials for (size_t j = 0; j < polynomials.size(); ++j) { for (size_t i = 0; i < round_size; i += 2) { - folded_polynomials[j][i >> 1] = + partially_evaluated_polynomials[j][i >> 1] = polynomials[j][i] + round_challenge * (polynomials[j][i + 1] - polynomials[j][i]); } } diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp index 356ad662b9b..f319872b156 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp @@ -138,11 +138,7 @@ TEST(Sumcheck, PolynomialNormalization) auto transcript = ProverTranscript::init_empty(); - auto sumcheck = Sumcheck, - ArithmeticRelation, - GrandProductComputationRelation, - GrandProductInitializationRelation>(multivariate_n, transcript); + auto sumcheck = Sumcheck>(multivariate_n, transcript); auto [multivariate_challenge, evaluations] = sumcheck.execute_prover(full_polynomials, {}); @@ -178,7 +174,7 @@ TEST(Sumcheck, PolynomialNormalization) l_2 * full_polynomials[i][2] + l_3 * full_polynomials[i][3] + l_4 * full_polynomials[i][4] + l_5 * full_polynomials[i][5] + l_6 * full_polynomials[i][6] + l_7 * full_polynomials[i][7]; - EXPECT_EQ(hand_computed_value, sumcheck.folded_polynomials[i][0]); + EXPECT_EQ(hand_computed_value, sumcheck.partially_evaluated_polynomials[i][0]); } } @@ -238,11 +234,7 @@ TEST(Sumcheck, Prover) auto transcript = ProverTranscript::init_empty(); - auto sumcheck = Sumcheck, - ArithmeticRelation, - GrandProductComputationRelation, - GrandProductInitializationRelation>(multivariate_n, transcript); + auto sumcheck = Sumcheck>(multivariate_n, transcript); auto [multivariate_challenge, evaluations] = sumcheck.execute_prover(full_polynomials, {}); FF u_0 = multivariate_challenge[0]; @@ -319,21 +311,13 @@ TEST(Sumcheck, ProverAndVerifier) auto prover_transcript = ProverTranscript::init_empty(); - auto sumcheck_prover = Sumcheck, - ArithmeticRelation, - GrandProductComputationRelation, - GrandProductInitializationRelation>(multivariate_n, prover_transcript); + auto sumcheck_prover = Sumcheck>(multivariate_n, prover_transcript); auto prover_output = sumcheck_prover.execute_prover(full_polynomials, relation_parameters); auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); - auto sumcheck_verifier = Sumcheck, - ArithmeticRelation, - GrandProductComputationRelation, - GrandProductInitializationRelation>(multivariate_n, verifier_transcript); + auto sumcheck_verifier = Sumcheck>(multivariate_n, verifier_transcript); std::optional verifier_output = sumcheck_verifier.execute_verifier(relation_parameters); @@ -401,21 +385,13 @@ TEST(Sumcheck, ProverAndVerifierLonger) auto prover_transcript = ProverTranscript::init_empty(); - auto sumcheck_prover = Sumcheck, - ArithmeticRelation, - GrandProductComputationRelation, - GrandProductInitializationRelation>(multivariate_n, prover_transcript); + auto sumcheck_prover = Sumcheck>(multivariate_n, prover_transcript); auto prover_output = sumcheck_prover.execute_prover(full_polynomials, relation_parameters); auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); - auto sumcheck_verifier = Sumcheck, - ArithmeticRelation, - GrandProductComputationRelation, - GrandProductInitializationRelation>(multivariate_n, verifier_transcript); + auto sumcheck_verifier = Sumcheck>(multivariate_n, verifier_transcript); std::optional verifier_output = sumcheck_verifier.execute_verifier(relation_parameters); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_output.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_output.hpp index cfe3dfb09bd..c83d85c15a0 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_output.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_output.hpp @@ -10,16 +10,16 @@ namespace proof_system::honk::sumcheck { */ template struct SumcheckOutput { using FF = typename Flavor::FF; - using PurportedEvaluations = typename Flavor::PurportedEvaluations; + using ClaimedEvaluations = typename Flavor::ClaimedEvaluations; // u = (u_0, ..., u_{d-1}) std::vector challenge_point; // Evaluations in `u` of the polynomials used in Sumcheck - PurportedEvaluations purported_evaluations; + ClaimedEvaluations purported_evaluations; SumcheckOutput() : purported_evaluations(std::array()){}; - SumcheckOutput(const std::vector& _challenge_point, const PurportedEvaluations& _purported_evaluations) + SumcheckOutput(const std::vector& _challenge_point, const ClaimedEvaluations& _purported_evaluations) : challenge_point(_challenge_point) , purported_evaluations(_purported_evaluations){}; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp index 0aea53047fa..4c2fbca3135 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp @@ -53,26 +53,30 @@ namespace proof_system::honk::sumcheck { @todo TODO(#390): Template only on Flavor? Is it useful to have these decoupled? */ -template class... Relations> class SumcheckRound { +template class SumcheckRound { + + using Relations = typename Flavor::Relations; + using UnivariateTuple = typename Flavor::UnivariateTuple; + using BarycentricUtils = typename Flavor::BarycentricUtils; public: using FF = typename Flavor::FF; template using ExtendedEdges = typename Flavor::template ExtendedEdges; - using PurportedEvaluations = typename Flavor::PurportedEvaluations; + using ClaimedEvaluations = typename Flavor::ClaimedEvaluations; bool round_failed = false; size_t round_size; // a power of 2 - std::tuple...> relations; - static constexpr size_t NUM_RELATIONS = sizeof...(Relations); - static constexpr size_t MAX_RELATION_LENGTH = std::max({ Relations::RELATION_LENGTH... }); + Relations relations; + static constexpr size_t NUM_RELATIONS = Flavor::NUM_RELATIONS; + static constexpr size_t MAX_RELATION_LENGTH = Flavor::MAX_RELATION_LENGTH; FF target_total_sum = 0; // TODO(#224)(Cody): this barycentric stuff should be more built-in? - std::tuple::RELATION_LENGTH, MAX_RELATION_LENGTH>...> barycentric_utils; - std::tuple::RELATION_LENGTH>...> univariate_accumulators; + BarycentricUtils barycentric_utils; + UnivariateTuple univariate_accumulators; std::array relation_evaluations; ExtendedEdges extended_edges; std::array, NUM_RELATIONS> extended_univariates; @@ -81,16 +85,12 @@ template class... Relations> class SumcheckRo BarycentricData barycentric_2_to_max = BarycentricData(); // Prover constructor - SumcheckRound(size_t initial_round_size, auto&& relations) + SumcheckRound(size_t initial_round_size) : round_size(initial_round_size) - , relations(relations) - , barycentric_utils(BarycentricData::RELATION_LENGTH, MAX_RELATION_LENGTH>()...) - , univariate_accumulators(Univariate::RELATION_LENGTH>()...) {} // Verifier constructor - explicit SumcheckRound(auto relations) - : relations(relations) + explicit SumcheckRound() { // FF's default constructor may not initialize to zero (e.g., barretenberg::fr), hence we can't rely on // aggregate initialization of the evaluations array. @@ -218,7 +218,7 @@ template class... Relations> class SumcheckRo * together, with appropriate scaling factors, produces the expected value of the full Honk relation. This value is * checked against the final value of the target total sum, defined as sigma_d. */ - FF compute_full_honk_relation_purported_value(PurportedEvaluations purported_evaluations, + FF compute_full_honk_relation_purported_value(ClaimedEvaluations purported_evaluations, const RelationParameters& relation_parameters, const PowUnivariate& pow_univariate, const FF alpha) @@ -316,7 +316,7 @@ template class... Relations> class SumcheckRo */ template // TODO(#224)(Cody): Input should be an array? - void accumulate_relation_evaluations(PurportedEvaluations purported_evaluations, + void accumulate_relation_evaluations(ClaimedEvaluations purported_evaluations, const RelationParameters& relation_parameters) { std::get(relations).add_full_relation_value_contribution( diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp index 97fefa6a48c..9efdc236779 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp @@ -1,7 +1,4 @@ #include "sumcheck_round.hpp" -#include "relations/arithmetic_relation.hpp" -#include "relations/grand_product_computation_relation.hpp" -#include "relations/grand_product_initialization_relation.hpp" #include "polynomials/univariate.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/numeric/random/engine.hpp" @@ -25,7 +22,7 @@ using namespace proof_system::honk::sumcheck; using Flavor = flavor::Standard; using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; -using PurportedEvaluations = typename Flavor::PurportedEvaluations; +using ClaimedEvaluations = typename Flavor::ClaimedEvaluations; const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; const size_t max_relation_length = 5; @@ -80,12 +77,9 @@ static Univariate compute_round_univariate( const FF alpha) { size_t round_size = 1; - auto relations = std::tuple( - ArithmeticRelation(), GrandProductComputationRelation(), GrandProductInitializationRelation()); + // Improvement(Cody): This is ugly? Maye supply some/all of this data through "flavor" class? - auto round = - SumcheckRound( - round_size, relations); + auto round = SumcheckRound(round_size); auto w_l = input_polynomials[0]; auto w_r = input_polynomials[1]; auto w_o = input_polynomials[2]; @@ -187,7 +181,7 @@ static FF compute_full_purported_value(std::array& input_va const RelationParameters& relation_parameters, const FF alpha) { - PurportedEvaluations purported_evaluations; + ClaimedEvaluations purported_evaluations; purported_evaluations.w_l = input_values[0]; purported_evaluations.w_r = input_values[1]; purported_evaluations.w_o = input_values[2]; @@ -206,11 +200,8 @@ static FF compute_full_purported_value(std::array& input_va purported_evaluations.id_3 = input_values[15]; purported_evaluations.lagrange_first = input_values[16]; purported_evaluations.lagrange_last = input_values[17]; - auto relations = std::tuple( - ArithmeticRelation(), GrandProductComputationRelation(), GrandProductInitializationRelation()); - auto round = - SumcheckRound( - relations); + + auto round = SumcheckRound(); PowUnivariate pow_univariate(1); FF full_purported_value = round.compute_full_honk_relation_purported_value( purported_evaluations, relation_parameters, pow_univariate, alpha); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp index 047102b599b..d42e3c6c9a8 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp @@ -57,7 +57,6 @@ * empty slots. This is a conscious choice to limit complexity. Note that there is very little memory cost here since * the DataType size in that case is small. * - * @todo TODO(#394): Folded polynomials should use polynomial class. * @todo TODO(#395): Getters should return arrays? * @todo TODO(#396): Access specifiers? * @todo TODO(#397): Use more handle types? @@ -68,9 +67,11 @@ #include #include #include +#include "barretenberg/honk/sumcheck/polynomials/barycentric_data.hpp" #include "barretenberg/srs/reference_string/reference_string.hpp" #include "barretenberg/polynomials/evaluation_domain.hpp" #include "barretenberg/proof_system/types/composer_type.hpp" +#include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" namespace proof_system::honk::flavor { @@ -214,6 +215,52 @@ class AllEntities_ : public Entities_ { }; }; +/** + * @brief Recursive utility function to find max RELATION_LENGTH over tuple of Relations + * + */ +template static constexpr size_t get_max_relation_length() +{ + if constexpr (Index >= std::tuple_size::value) { + return 0; // Return 0 when reach end of the tuple + } else { + constexpr size_t current_length = std::tuple_element::type::RELATION_LENGTH; + constexpr size_t next_length = get_max_relation_length(); + return (current_length > next_length) ? current_length : next_length; + } +} + +/** + * @brief Recursive utility function to construct tuple of Univariates of length RELATION_LENGTH + * + */ +template static constexpr auto create_univariate_tuple() +{ + if constexpr (Index >= std::tuple_size::value) { + return std::tuple<>{}; // Return empty when reach end of the tuple + } else { + using UnivariateType = sumcheck::Univariate::RELATION_LENGTH>; + return std::tuple_cat(std::tuple{}, create_univariate_tuple()); + } +} + +/** + * @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