From bba1601b0b6cd98e94ed9a2b029a3262df5cc65c Mon Sep 17 00:00:00 2001 From: adr1anh Date: Wed, 15 Mar 2023 16:07:17 +0000 Subject: [PATCH 1/2] - Remove zeta,alpha from relation_params - make sumcheck methods static - add public inputs and rel_param to prover key - sumcheck returns an output - sumcheck verifier does not depend on sumcheck round --- .../composer/standard_honk_composer.test.cpp | 23 +- .../barretenberg/honk/proof_system/prover.cpp | 75 ++-- .../barretenberg/honk/proof_system/prover.hpp | 42 +- .../honk/proof_system/verifier.cpp | 147 ++++--- .../polynomials/multivariates.test.cpp | 177 ++------ .../honk/sumcheck/polynomials/univariate.hpp | 12 + .../relations/arithmetic_relation.hpp | 14 +- .../grand_product_computation_relation.hpp | 8 +- .../grand_product_initialization_relation.hpp | 9 +- .../honk/sumcheck/relations/relation.hpp | 3 - .../honk/sumcheck/relations/relation.test.cpp | 8 +- .../barretenberg/honk/sumcheck/sumcheck.hpp | 400 ++++++++++-------- .../honk/sumcheck/sumcheck.test.cpp | 93 ++-- .../honk/sumcheck/sumcheck_round.hpp | 220 +++------- .../honk/sumcheck/sumcheck_round.test.cpp | 103 +++-- 15 files changed, 581 insertions(+), 753 deletions(-) diff --git a/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp b/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp index ea544cde58..285eccbc33 100644 --- a/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp +++ b/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp @@ -1,15 +1,15 @@ #include "standard_honk_composer.hpp" -#include "barretenberg/honk/sumcheck/relations/relation.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/proof_system/flavor/flavor.hpp" -#include #include "barretenberg/honk/proof_system/prover.hpp" -#include "barretenberg/honk/sumcheck/sumcheck_round.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/arithmetic_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/relation.hpp" #include "barretenberg/honk/utils/public_inputs.hpp" #include +#include using namespace honk; @@ -335,7 +335,6 @@ TEST(StandardHonkComposer, SumcheckRelationCorrectness) // Generate beta and gamma fr beta = fr::random_element(); fr gamma = fr::random_element(); - fr zeta = fr::random_element(); // Compute public input delta const auto public_inputs = composer.circuit_constructor.get_public_inputs(); @@ -343,8 +342,6 @@ TEST(StandardHonkComposer, SumcheckRelationCorrectness) honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); sumcheck::RelationParameters params{ - .zeta = zeta, - .alpha = fr::one(), .beta = beta, .gamma = gamma, .public_input_delta = public_input_delta, @@ -380,11 +377,6 @@ TEST(StandardHonkComposer, SumcheckRelationCorrectness) evaluations_array[POLYNOMIAL::LAGRANGE_FIRST] = prover.key->polynomial_store.get("L_first_lagrange"); evaluations_array[POLYNOMIAL::LAGRANGE_LAST] = prover.key->polynomial_store.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()); - 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 @@ -397,13 +389,16 @@ TEST(StandardHonkComposer, SumcheckRelationCorrectness) // 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); + result = honk::sumcheck::ArithmeticRelation::evaluate_full_relation_value_contribution( + evaluations_at_index_i, params); ASSERT_EQ(result, 0); - std::get<1>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + result = honk::sumcheck::GrandProductComputationRelation::evaluate_full_relation_value_contribution( + evaluations_at_index_i, params); ASSERT_EQ(result, 0); - std::get<2>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + result = honk::sumcheck::GrandProductInitializationRelation::evaluate_full_relation_value_contribution( + evaluations_at_index_i, params); ASSERT_EQ(result, 0); } } diff --git a/cpp/src/barretenberg/honk/proof_system/prover.cpp b/cpp/src/barretenberg/honk/proof_system/prover.cpp index 15cef9aa23..d1f4605b22 100644 --- a/cpp/src/barretenberg/honk/proof_system/prover.cpp +++ b/cpp/src/barretenberg/honk/proof_system/prover.cpp @@ -1,33 +1,26 @@ #include "prover.hpp" -#include -#include -#include "barretenberg/honk/sumcheck/sumcheck.hpp" // will need -#include -#include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" // will go away -#include "barretenberg/honk/utils/power_polynomial.hpp" +#include "barretenberg/honk/sumcheck/sumcheck.hpp" #include "barretenberg/honk/pcs/commitment_key.hpp" -#include -#include -#include -#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/utils/public_inputs.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/proof_system/flavor/flavor.hpp" #include "barretenberg/transcript/transcript_wrappers.hpp" + #include -#include "barretenberg/honk/pcs/claim.hpp" +#include +#include +#include +#include +#include +#include +#include namespace honk { -using Fr = barretenberg::fr; -using Commitment = barretenberg::g1::affine_element; -using Polynomial = barretenberg::Polynomial; -using POLYNOMIAL = bonk::StandardArithmetization::POLYNOMIAL; - /** * Create Prover from proving key, witness and manifest. * @@ -37,7 +30,7 @@ using POLYNOMIAL = bonk::StandardArithmetization::POLYNOMIAL; * @tparam settings Settings class. * */ template -Prover::Prover(std::vector&& wire_polys, +Prover::Prover(std::vector&& wire_polys, std::shared_ptr input_key, const transcript::Manifest& input_manifest) : transcript(input_manifest, settings::hash_type, settings::num_challenge_bytes) @@ -66,6 +59,13 @@ Prover::Prover(std::vector&& wire_polys, prover_polynomials[POLYNOMIAL::W_L] = wire_polynomials[0]; prover_polynomials[POLYNOMIAL::W_R] = wire_polynomials[1]; prover_polynomials[POLYNOMIAL::W_O] = wire_polynomials[2]; + + // Add public inputs to transcript from the second wire polynomial + std::span public_wires_source = prover_polynomials[POLYNOMIAL::W_R]; + + for (size_t i = 0; i < key->num_public_inputs; ++i) { + public_inputs.emplace_back(public_wires_source[i]); + } } /** @@ -109,10 +109,11 @@ template void Prover::compute_wire_commitments() * one batch inversion (at the expense of more multiplications) */ // TODO(#222)(luke): Parallelize -template Polynomial Prover::compute_grand_product_polynomial(Fr beta, Fr gamma) +template +barretenberg::Polynomial Prover::compute_grand_product_polynomial(Fr beta, Fr gamma) { using barretenberg::polynomial_arithmetic::copy_polynomial; - static const size_t program_width = settings::program_width; + constexpr size_t program_width = settings::program_width; // Allocate scratch space for accumulators std::array numerator_accumulator; @@ -224,14 +225,8 @@ template void Prover::execute_wire_commitments_rou // queue.flush_queue(); // NOTE: Don't remove; we may reinstate the queue compute_wire_commitments(); - // Add public inputs to transcript from the second wire polynomial - const Polynomial& public_wires_source = wire_polynomials[1]; - - std::vector public_wires; - for (size_t i = 0; i < key->num_public_inputs; ++i) { - public_wires.push_back(public_wires_source[i]); - } - transcript.add_element("public_inputs", ::to_buffer(public_wires)); + // Add public inputs to transcript + transcript.add_element("public_inputs", ::to_buffer(public_inputs)); } /** @@ -257,6 +252,15 @@ template void Prover::execute_grand_product_comput auto beta = transcript.get_challenge_field_element("beta", 0); auto gamma = transcript.get_challenge_field_element("beta", 1); + + auto public_input_delta = compute_public_input_delta(public_inputs, beta, gamma, key->circuit_size); + + relation_parameters = sumcheck::RelationParameters{ + .beta = beta, + .gamma = gamma, + .public_input_delta = public_input_delta, + }; + z_permutation = compute_grand_product_polynomial(beta, gamma); // The actual polynomial is of length n+1, but commitment key is just n, so we need to limit it auto commitment = commitment_key->commit(z_permutation); @@ -276,16 +280,14 @@ template void Prover::execute_relation_check_round // queue.flush_queue(); // NOTE: Don't remove; we may reinstate the queue using Sumcheck = sumcheck::Sumcheck; transcript.apply_fiat_shamir("alpha"); - auto sumcheck = Sumcheck(key->circuit_size, transcript); - - sumcheck.execute_prover(prover_polynomials); + sumcheck_output = + Sumcheck::execute_prover(key->log_circuit_size, relation_parameters, prover_polynomials, transcript); } /** @@ -298,20 +300,13 @@ template void Prover::execute_univariatization_rou const size_t NUM_POLYNOMIALS = bonk::StandardArithmetization::NUM_POLYNOMIALS; const size_t NUM_UNSHIFTED_POLYS = bonk::StandardArithmetization::NUM_UNSHIFTED_POLYNOMIALS; - // Construct MLE opening point u = (u_0, ..., u_{d-1}) - std::vector opening_point; // u - for (size_t round_idx = 0; round_idx < key->log_circuit_size; round_idx++) { - std::string label = "u_" + std::to_string(round_idx); - opening_point.emplace_back(transcript.get_challenge_field_element(label)); - } - // Generate batching challenge ρ and powers 1,ρ,…,ρᵐ⁻¹ transcript.apply_fiat_shamir("rho"); Fr rho = Fr::serialize_from_buffer(transcript.get_challenge("rho").begin()); std::vector rhos = Gemini::powers_of_rho(rho, NUM_POLYNOMIALS); // Get vector of multivariate evaluations produced by Sumcheck - auto multivariate_evaluations = transcript.get_field_element_vector("multivariate_evaluations"); + auto [opening_point, multivariate_evaluations] = sumcheck_output; // Batch the unshifted polynomials and the to-be-shifted polynomials using ρ Polynomial batched_poly_unshifted(key->circuit_size); // batched unshifted polynomials diff --git a/cpp/src/barretenberg/honk/proof_system/prover.hpp b/cpp/src/barretenberg/honk/proof_system/prover.hpp index ffe58f41c0..2af99db0b5 100644 --- a/cpp/src/barretenberg/honk/proof_system/prover.hpp +++ b/cpp/src/barretenberg/honk/proof_system/prover.hpp @@ -1,34 +1,33 @@ #pragma once -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/honk/pcs/shplonk/shplonk.hpp" #include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/proof_system/flavor/flavor.hpp" -#include -#include "barretenberg/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/honk/sumcheck/sumcheck.hpp" +#include "barretenberg/honk/sumcheck/relations/relation.hpp" #include "barretenberg/honk/pcs/commitment_key.hpp" -#include "barretenberg/plonk/proof_system/types/proof.hpp" -#include "barretenberg/plonk/proof_system/types/program_settings.hpp" #include "barretenberg/honk/pcs/gemini/gemini.hpp" #include "barretenberg/honk/pcs/shplonk/shplonk_single.hpp" +#include "barretenberg/honk/pcs/shplonk/shplonk.hpp" #include "barretenberg/honk/pcs/kzg/kzg.hpp" +#include "barretenberg/transcript/transcript_wrappers.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" +#include "barretenberg/plonk/proof_system/types/prover_settings.hpp" + +#include #include -#include #include -#include -#include #include -#include -#include -#include "barretenberg/honk/pcs/claim.hpp" namespace honk { -using Fr = barretenberg::fr; - template class Prover { + using Fr = barretenberg::fr; + using Polynomial = barretenberg::Polynomial; + using POLYNOMIAL = bonk::StandardArithmetization::POLYNOMIAL; + public: - Prover(std::vector&& wire_polys, + Prover(std::vector&& wire_polys, std::shared_ptr input_key = nullptr, const transcript::Manifest& manifest = transcript::Manifest()); @@ -44,7 +43,7 @@ template class Prover { void compute_wire_commitments(); - barretenberg::polynomial compute_grand_product_polynomial(Fr beta, Fr gamma); + Polynomial compute_grand_product_polynomial(Fr beta, Fr gamma); void construct_prover_polynomials(); @@ -53,8 +52,12 @@ template class Prover { transcript::StandardTranscript transcript; - std::vector wire_polynomials; - barretenberg::polynomial z_permutation; + std::vector public_inputs; + + std::vector wire_polynomials; + Polynomial z_permutation; + + sumcheck::RelationParameters relation_parameters; std::shared_ptr key; @@ -79,6 +82,7 @@ template class Prover { // This makes 'settings' accesible from Prover using settings_ = settings; + sumcheck::SumcheckOutput sumcheck_output; pcs::gemini::ProverOutput gemini_output; pcs::shplonk::ProverOutput shplonk_output; diff --git a/cpp/src/barretenberg/honk/proof_system/verifier.cpp b/cpp/src/barretenberg/honk/proof_system/verifier.cpp index 7d54319ecf..7716e0aeee 100644 --- a/cpp/src/barretenberg/honk/proof_system/verifier.cpp +++ b/cpp/src/barretenberg/honk/proof_system/verifier.cpp @@ -1,30 +1,24 @@ -#include -#include "barretenberg/common/throw_or_abort.hpp" -#include -#include -#include "barretenberg/plonk/proof_system/constants.hpp" + #include "./verifier.hpp" -#include "barretenberg/plonk/proof_system/public_inputs/public_inputs.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/honk/pcs/commitment_key.hpp" #include "barretenberg/honk/pcs/gemini/gemini.hpp" #include "barretenberg/honk/pcs/kzg/kzg.hpp" +#include "barretenberg/honk/pcs/shplonk/shplonk_single.hpp" +#include "barretenberg/honk/sumcheck/sumcheck.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/utils/public_inputs.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/proof_system/flavor/flavor.hpp" -#include "barretenberg/proof_system/polynomial_store/polynomial_store.hpp" -#include "barretenberg/ecc/curves/bn254/fq12.hpp" -#include "barretenberg/ecc/curves/bn254/pairing.hpp" #include "barretenberg/ecc/curves/bn254/scalar_multiplication/scalar_multiplication.hpp" -#include "barretenberg/polynomials/polynomial_arithmetic.hpp" -#include "barretenberg/honk/composer/composer_helper/permutation_helper.hpp" -#include -#include -#include "barretenberg/honk/utils/power_polynomial.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" -using namespace barretenberg; -using namespace honk::sumcheck; +#include +#include +#include +#include +#include namespace honk { template @@ -81,18 +75,25 @@ template bool Verifier::verify_pro { using FF = typename program_settings::fr; using Commitment = barretenberg::g1::element; - using Transcript = typename program_settings::Transcript; + using CommitmentAffine = barretenberg::g1::affine_element; + + using Sumcheck = sumcheck::Sumcheck; using Gemini = pcs::gemini::MultilinearReductionScheme; using Shplonk = pcs::shplonk::SingleBatchOpeningScheme; using KZG = pcs::kzg::UnivariateOpeningScheme; + const size_t NUM_POLYNOMIALS = bonk::StandardArithmetization::NUM_POLYNOMIALS; const size_t NUM_UNSHIFTED = bonk::StandardArithmetization::NUM_UNSHIFTED_POLYNOMIALS; const size_t NUM_PRECOMPUTED = bonk::StandardArithmetization::NUM_PRECOMPUTED_POLYNOMIALS; - key->program_width = program_settings::program_width; - - size_t log_n(numeric::get_msb(key->circuit_size)); + constexpr auto width = program_settings::program_width; + const auto circuit_size = static_cast(key->circuit_size); + const auto num_public_inputs = static_cast(key->num_public_inputs); + const size_t log_n(numeric::get_msb(circuit_size)); // Add the proof data to the transcript, according to the manifest. Also initialise the transcript's hash type // and challenge bytes. auto transcript = transcript::StandardTranscript( @@ -100,16 +101,16 @@ template bool Verifier::verify_pro // Add the circuit size and the number of public inputs) to the transcript. transcript.add_element("circuit_size", - { static_cast(key->circuit_size >> 24), - static_cast(key->circuit_size >> 16), - static_cast(key->circuit_size >> 8), - static_cast(key->circuit_size) }); + { static_cast(circuit_size >> 24), + static_cast(circuit_size >> 16), + static_cast(circuit_size >> 8), + static_cast(circuit_size) }); transcript.add_element("public_input_size", - { static_cast(key->num_public_inputs >> 24), - static_cast(key->num_public_inputs >> 16), - static_cast(key->num_public_inputs >> 8), - static_cast(key->num_public_inputs) }); + { static_cast(num_public_inputs >> 24), + static_cast(num_public_inputs >> 16), + static_cast(num_public_inputs >> 8), + static_cast(num_public_inputs) }); // Compute challenges from the proof data, based on the manifest, using the Fiat-Shamir heuristic transcript.apply_fiat_shamir("init"); @@ -125,60 +126,80 @@ template bool Verifier::verify_pro transcript.apply_fiat_shamir("z"); transcript.apply_fiat_shamir("separator"); - // // TODO(Cody): Compute some basic public polys like id(X), pow(X), and any required Lagrange polys + std::vector public_inputs = many_from_buffer(transcript.get_element("public_inputs")); + ASSERT(public_inputs.size() == num_public_inputs); + + // Get commitments to the wires + std::array wire_commitments; + for (size_t i = 0; i < width; ++i) { + wire_commitments[i] = + transcript.get_group_element(bonk::StandardArithmetization::ENUM_TO_COMM[NUM_PRECOMPUTED + i]); + } + + // Get commitment to Z_PERM + auto z_permutation_commitment = transcript.get_group_element("Z_PERM"); + + // Get permutation challenges + const FF beta = FF::serialize_from_buffer(transcript.get_challenge("beta").begin()); + const FF gamma = FF::serialize_from_buffer(transcript.get_challenge("beta", 1).begin()); + const FF public_input_delta = compute_public_input_delta(public_inputs, beta, gamma, circuit_size); + + sumcheck::RelationParameters relation_parameters{ + .beta = beta, + .gamma = gamma, + .public_input_delta = public_input_delta, + }; + + // TODO(Cody): Compute some basic public polys like id(X), pow(X), and any required Lagrange polys // Execute Sumcheck Verifier - auto sumcheck = Sumcheck(transcript); - bool sumcheck_result = sumcheck.execute_verifier(); + std::optional sumcheck_result = Sumcheck::execute_verifier(log_n, relation_parameters, transcript); + // Abort if sumcheck failed and returned nothing + if (!sumcheck_result.has_value()) { + return false; + } + + // Get opening point and vector of multivariate evaluations produced by Sumcheck + // - Multivariate opening point u = (u_0, ..., u_{d-1}) + auto [opening_point, multivariate_evaluations] = *sumcheck_result; // Execute Gemini/Shplonk verification: // Construct inputs for Gemini verifier: // - Multivariate opening point u = (u_0, ..., u_{d-1}) // - batched unshifted and to-be-shifted polynomial commitments - std::vector opening_point; // u = (u_0,...,u_{d-1}) - auto batched_commitment_unshifted = Commitment::zero(); - auto batched_commitment_to_be_shifted = Commitment::zero(); - - // Construct MLE opening point - for (size_t round_idx = 0; round_idx < key->log_circuit_size; round_idx++) { - std::string label = "u_" + std::to_string(round_idx); - opening_point.emplace_back(transcript.get_challenge_field_element(label)); - } // Compute powers of batching challenge rho - Fr rho = Fr::serialize_from_buffer(transcript.get_challenge("rho").begin()); - std::vector rhos = Gemini::powers_of_rho(rho, NUM_POLYNOMIALS); - - // Get vector of multivariate evaluations produced by Sumcheck - auto multivariate_evaluations = transcript.get_field_element_vector("multivariate_evaluations"); + FF rho = FF::serialize_from_buffer(transcript.get_challenge("rho").begin()); + std::vector rhos = Gemini::powers_of_rho(rho, NUM_POLYNOMIALS); // Compute batched multivariate evaluation - Fr batched_evaluation = Fr::zero(); + FF batched_evaluation = FF::zero(); for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { batched_evaluation += multivariate_evaluations[i] * rhos[i]; } // Construct batched commitment for NON-shifted polynomials - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - Commitment commitment; - if (i < NUM_PRECOMPUTED) { // if precomputed, commitment comes from verification key - commitment = key->commitments[bonk::StandardArithmetization::ENUM_TO_COMM[i]]; - } else { // if witness, commitment comes from prover (via transcript) - commitment = transcript.get_group_element(bonk::StandardArithmetization::ENUM_TO_COMM[i]); + Commitment batched_commitment_unshifted = Commitment::zero(); + { + // add precomputed commitments + for (size_t i = 0; i < NUM_PRECOMPUTED; ++i) { + // if precomputed, commitment comes from verification key + Commitment commitment = key->commitments[bonk::StandardArithmetization::ENUM_TO_COMM[i]]; + batched_commitment_unshifted += commitment * rhos[i]; + } + // add wire commitment + for (size_t i = 0; i < width; ++i) { + batched_commitment_unshifted += wire_commitments[i] * rhos[NUM_PRECOMPUTED + i]; } - batched_commitment_unshifted += commitment * rhos[i]; + // add z_perm + batched_commitment_unshifted += z_permutation_commitment * rhos[NUM_PRECOMPUTED + width]; } - - // Construct batched commitment for to-be-shifted polynomials - batched_commitment_to_be_shifted = transcript.get_group_element("Z_PERM") * rhos[NUM_UNSHIFTED]; + // Construct batched commitment for to-be-shifted polynomials (for now only Z_PERM) + Commitment batched_commitment_to_be_shifted = z_permutation_commitment * rhos[NUM_UNSHIFTED]; // Reconstruct the Gemini Proof from the transcript - auto gemini_proof = Gemini::reconstruct_proof_from_transcript(&transcript, key->log_circuit_size); + auto gemini_proof = Gemini::reconstruct_proof_from_transcript(&transcript, log_n); // Produce a Gemini claim consisting of: // - d+1 commitments [Fold_{r}^(0)], [Fold_{-r}^(0)], and [Fold^(l)], l = 1:d-1 diff --git a/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp b/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp index aca89f9319..23989e300c 100644 --- a/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp +++ b/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp @@ -1,17 +1,15 @@ #include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" #include "barretenberg/honk/sumcheck/sumcheck.hpp" #include -#include "barretenberg/numeric/random/engine.hpp" -using namespace honk::sumcheck; namespace test_sumcheck_polynomials { +using namespace honk::sumcheck; + template class MultivariatesTests : public testing::Test {}; using FieldTypes = testing::Types; -using Transcript = transcript::StandardTranscript; TYPED_TEST_SUITE(MultivariatesTests, FieldTypes); #define MULTIVARIATES_TESTS_TYPE_ALIASES using FF = TypeParam; @@ -46,69 +44,56 @@ TYPED_TEST(MultivariatesTests, FoldTwoRoundsSpecial) { MULTIVARIATES_TESTS_TYPE_ALIASES - // values here are chosen to check another test - const size_t multivariate_d(2); - const size_t multivariate_n(1 << multivariate_d); - FF v00 = 0; FF v10 = 1; FF v01 = 0; FF v11 = 0; - std::array f0 = { v00, v10, v01, v11 }; - - auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = Transcript(transcript::Manifest()); - auto sumcheck = Sumcheck(multivariate_n, transcript); + const std::array f0 = { v00, v10, v01, v11 }; + std::vector f0_evaluated; 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); + partially_evaluate(f0_evaluated, std::span{ f0 }, round_challenge_0); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], round_challenge_0); - EXPECT_EQ(sumcheck.folded_polynomials[0][1], FF(0)); + EXPECT_EQ(f0_evaluated[0], round_challenge_0); + EXPECT_EQ(f0_evaluated[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); + partially_evaluate(f0_evaluated, std::span{ f0_evaluated }, round_challenge_1); + EXPECT_EQ(f0_evaluated[0], expected_val); } TYPED_TEST(MultivariatesTests, FoldTwoRoundsGeneric) { MULTIVARIATES_TESTS_TYPE_ALIASES - const size_t multivariate_d(2); - const size_t multivariate_n(1 << multivariate_d); - FF v00 = FF::random_element(); FF v10 = FF::random_element(); FF v01 = FF::random_element(); FF v11 = FF::random_element(); std::array f0 = { v00, v10, v01, v11 }; - - auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = Transcript(transcript::Manifest()); - auto sumcheck = Sumcheck(multivariate_n, transcript); + std::vector f0_evaluated; 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); + partially_evaluate(f0_evaluated, std::span{ f0 }, round_challenge_0); - EXPECT_EQ(sumcheck.folded_polynomials[0][0], expected_lo); - EXPECT_EQ(sumcheck.folded_polynomials[0][1], expected_hi); + EXPECT_EQ(f0_evaluated[0], expected_lo); + EXPECT_EQ(f0_evaluated[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); + partially_evaluate(f0_evaluated, std::span{ f0_evaluated }, round_challenge_1); + EXPECT_EQ(f0_evaluated[0], expected_val); } /* @@ -137,9 +122,6 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsSpecial) { MULTIVARIATES_TESTS_TYPE_ALIASES - const size_t multivariate_d(3); - const size_t multivariate_n(1 << multivariate_d); - FF v000 = 1; FF v100 = 2; FF v010 = 3; @@ -150,10 +132,7 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsSpecial) FF v111 = 8; std::array f0 = { v000, v100, v010, v110, v001, v101, v011, v111 }; - - auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = Transcript(transcript::Manifest()); - auto sumcheck = Sumcheck(multivariate_n, transcript); + std::vector f0_evaluated; FF round_challenge_0 = 1; FF expected_q1 = v000 * (FF(1) - round_challenge_0) + v100 * round_challenge_0; // 2 @@ -161,34 +140,31 @@ 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); + partially_evaluate(f0_evaluated, std::span{ f0 }, 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(f0_evaluated[0], expected_q1); + EXPECT_EQ(f0_evaluated[1], expected_q2); + EXPECT_EQ(f0_evaluated[2], expected_q3); + EXPECT_EQ(f0_evaluated[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); + partially_evaluate(f0_evaluated, std::span{ f0_evaluated }, round_challenge_1); + EXPECT_EQ(f0_evaluated[0], expected_lo); + EXPECT_EQ(f0_evaluated[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); + partially_evaluate(f0_evaluated, std::span{ f0_evaluated }, round_challenge_2); + EXPECT_EQ(f0_evaluated[0], expected_val); } TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) { MULTIVARIATES_TESTS_TYPE_ALIASES - const size_t multivariate_d(3); - const size_t multivariate_n(1 << multivariate_d); - FF v000 = FF::random_element(); FF v100 = FF::random_element(); FF v010 = FF::random_element(); @@ -199,10 +175,7 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) FF v111 = FF::random_element(); std::array f0 = { v000, v100, v010, v110, v001, v101, v011, v111 }; - - auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = Transcript(transcript::Manifest()); - auto sumcheck = Sumcheck(multivariate_n, transcript); + std::vector f0_evaluated; FF round_challenge_0 = FF::random_element(); FF expected_q1 = v000 * (FF(1) - round_challenge_0) + v100 * round_challenge_0; @@ -210,100 +183,24 @@ 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); + partially_evaluate(f0_evaluated, std::span{ f0 }, 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(f0_evaluated[0], expected_q1); + EXPECT_EQ(f0_evaluated[1], expected_q2); + EXPECT_EQ(f0_evaluated[2], expected_q3); + EXPECT_EQ(f0_evaluated[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); + partially_evaluate(f0_evaluated, std::span{ f0_evaluated }, round_challenge_1); + EXPECT_EQ(f0_evaluated[0], expected_lo); + EXPECT_EQ(f0_evaluated[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); -} - -TYPED_TEST(MultivariatesTests, FoldThreeRoundsGenericMultiplePolys) -{ - MULTIVARIATES_TESTS_TYPE_ALIASES - const size_t multivariate_d(3); - const size_t multivariate_n(1 << multivariate_d); - std::array v000; - std::array v100; - std::array v010; - std::array v110; - std::array v001; - std::array v101; - std::array v011; - std::array v111; - - for (size_t i = 0; i < 3; i++) { - v000[i] = FF::random_element(); - v100[i] = FF::random_element(); - v010[i] = FF::random_element(); - v110[i] = FF::random_element(); - v001[i] = FF::random_element(); - v101[i] = FF::random_element(); - v011[i] = FF::random_element(); - v111[i] = FF::random_element(); - } - std::array f0 = { v000[0], v100[0], v010[0], v110[0], v001[0], v101[0], v011[0], v111[0] }; - std::array f1 = { v000[1], v100[1], v010[1], v110[1], v001[1], v101[1], v011[1], v111[1] }; - std::array f2 = { v000[2], v100[2], v010[2], v110[2], v001[2], v101[2], v011[2], v111[2] }; - - auto full_polynomials = std::array, 3>{ f0, f1, f2 }; - auto transcript = Transcript(transcript::Manifest()); - auto sumcheck = Sumcheck(multivariate_n, transcript); - - std::array expected_q1; - std::array expected_q2; - std::array expected_q3; - std::array expected_q4; - FF round_challenge_0 = FF::random_element(); - for (size_t i = 0; i < 3; i++) { - expected_q1[i] = v000[i] * (FF(1) - round_challenge_0) + v100[i] * round_challenge_0; - expected_q2[i] = v010[i] * (FF(1) - round_challenge_0) + v110[i] * round_challenge_0; - expected_q3[i] = v001[i] * (FF(1) - round_challenge_0) + v101[i] * round_challenge_0; - expected_q4[i] = v011[i] * (FF(1) - round_challenge_0) + v111[i] * round_challenge_0; - } - - sumcheck.fold(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]); - } - - FF round_challenge_1 = FF::random_element(); - std::array expected_lo; - std::array expected_hi; - for (size_t i = 0; i < 3; i++) { - 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); - 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]); - } - 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); - for (size_t i = 0; i < 3; i++) { - EXPECT_EQ(sumcheck.folded_polynomials[i][0], expected_val[i]); - } + partially_evaluate(f0_evaluated, std::span{ f0_evaluated }, round_challenge_2); + EXPECT_EQ(f0_evaluated[0], expected_val); } - } // namespace test_sumcheck_polynomials diff --git a/cpp/src/barretenberg/honk/sumcheck/polynomials/univariate.hpp b/cpp/src/barretenberg/honk/sumcheck/polynomials/univariate.hpp index 0ae49c5f10..89804ebc8f 100644 --- a/cpp/src/barretenberg/honk/sumcheck/polynomials/univariate.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/polynomials/univariate.hpp @@ -211,6 +211,18 @@ template class Univariate { } }; +template inline void read(B& it, Univariate& univariate) +{ + using serialize::read; + read(it, univariate.evaluations); +} + +template inline void write(B& it, Univariate const& univariate) +{ + using serialize::write; + write(it, univariate.evaluations); +} + template class UnivariateView { public: std::span evaluations; diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp b/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp index 8aaed7922e..fde214a715 100644 --- a/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp @@ -49,9 +49,8 @@ template class ArithmeticRelation { evals += tmp; }; - void add_full_relation_value_contribution(FF& full_honk_relation_value, - const auto& purported_evaluations, - const RelationParameters&) const + static FF evaluate_full_relation_value_contribution(const auto& purported_evaluations, + const RelationParameters&) { auto w_l = purported_evaluations[MULTIVARIATE::W_L]; auto w_r = purported_evaluations[MULTIVARIATE::W_R]; @@ -62,10 +61,11 @@ template class ArithmeticRelation { auto q_o = purported_evaluations[MULTIVARIATE::Q_O]; auto q_c = purported_evaluations[MULTIVARIATE::Q_C]; - full_honk_relation_value += w_l * (q_m * w_r + q_l); - full_honk_relation_value += q_r * w_r; - full_honk_relation_value += q_o * w_o; - full_honk_relation_value += q_c; + FF eval = w_l * (q_m * w_r + q_l); + eval += q_r * w_r; + eval += q_o * w_o; + eval += q_c; + return eval; }; }; } // namespace honk::sumcheck diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp b/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp index 9ba477f5c3..9909768284 100644 --- a/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp @@ -59,9 +59,8 @@ template class GrandProductComputationRelation { scaling_factor; }; - void add_full_relation_value_contribution(FF& full_honk_relation_value, - auto& purported_evaluations, - const RelationParameters& relation_parameters) const + static FF evaluate_full_relation_value_contribution(const auto& purported_evaluations, + const RelationParameters& relation_parameters) { const auto& beta = relation_parameters.beta; const auto& gamma = relation_parameters.gamma; @@ -82,8 +81,7 @@ template class GrandProductComputationRelation { auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; // Contribution (1) - full_honk_relation_value += - ((z_perm + lagrange_first) * (w_1 + beta * id_1 + gamma) * (w_2 + beta * id_2 + gamma) * + return ((z_perm + lagrange_first) * (w_1 + beta * id_1 + gamma) * (w_2 + beta * id_2 + gamma) * (w_3 + beta * id_3 + gamma) - (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + beta * sigma_1 + gamma) * (w_2 + beta * sigma_2 + gamma) * (w_3 + beta * sigma_3 + gamma)); diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp b/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp index 9620cc3d37..bb97cf8454 100644 --- a/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp @@ -35,14 +35,13 @@ template class GrandProductInitializationRelation { evals += (lagrange_last * z_perm_shift) * scaling_factor; }; - void add_full_relation_value_contribution(FF& full_honk_relation_value, - auto& purported_evaluations, - const RelationParameters&) const + static FF evaluate_full_relation_value_contribution(const auto& purported_evaluations, + const RelationParameters&) { auto z_perm_shift = purported_evaluations[MULTIVARIATE::Z_PERM_SHIFT]; auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; - full_honk_relation_value += lagrange_last * z_perm_shift; - }; + return lagrange_last * z_perm_shift; + } }; } // namespace honk::sumcheck diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/relation.hpp b/cpp/src/barretenberg/honk/sumcheck/relations/relation.hpp index 143246544a..0fb1c999d8 100644 --- a/cpp/src/barretenberg/honk/sumcheck/relations/relation.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/relations/relation.hpp @@ -2,10 +2,7 @@ namespace honk::sumcheck { -// TODO(#226)(Adrian): Remove zeta, alpha as they are not used by the relations. template struct RelationParameters { - FF zeta; - FF alpha; FF beta; FF gamma; FF public_input_delta; diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/relation.test.cpp b/cpp/src/barretenberg/honk/sumcheck/relations/relation.test.cpp index b169924f08..61196520bc 100644 --- a/cpp/src/barretenberg/honk/sumcheck/relations/relation.test.cpp +++ b/cpp/src/barretenberg/honk/sumcheck/relations/relation.test.cpp @@ -93,9 +93,7 @@ template class SumcheckRelation : public testing::Test { */ RelationParameters compute_mock_relation_parameters() { - return { .zeta = FF::random_element(), - .alpha = FF::random_element(), - .beta = FF::random_element(), + return { .beta = FF::random_element(), .gamma = FF::random_element(), .public_input_delta = FF::random_element() }; } @@ -151,8 +149,8 @@ template class SumcheckRelation : public testing::Test { // 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); + expected_evals_index.value_at(i) = + relation.evaluate_full_relation_value_contribution(evals_i, relation_parameters); } EXPECT_EQ(expected_evals, expected_evals_index); diff --git a/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp b/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp index f918747be0..a63aec3d56 100644 --- a/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp @@ -1,116 +1,84 @@ #pragma once -#include "barretenberg/common/serialize.hpp" -#include -#include "barretenberg/honk/utils/public_inputs.hpp" -#include "barretenberg/common/throw_or_abort.hpp" #include "sumcheck_round.hpp" +#include "relations/relation.hpp" +#include "polynomials/pow.hpp" #include "polynomials/univariate.hpp" +#include "barretenberg/common/serialize.hpp" #include "barretenberg/proof_system/flavor/flavor.hpp" +#include "barretenberg/numeric/bitop/get_msb.hpp" + #include +#include #include #include #include #include -#include "barretenberg/honk/proof_system/prover.hpp" + namespace honk::sumcheck { -template class... Relations> class Sumcheck { - public: - static constexpr size_t MAX_RELATION_LENGTH = std::max({ Relations::RELATION_LENGTH... }); +/** + * @brief Contains the multi-linear `evaluations` of the polynomials at the `evaluation_point`. + * These are computed by the prover and need to be checked using a multi-linear PCS like Gemini. + */ +template struct SumcheckOutput { + // u = (u_0, ..., u_{d-1}) + std::vector evaluation_point; + // Evaluations in `u` of the polynomials used in Sumcheck + std::array evaluations; - std::array purported_evaluations; - Transcript& transcript; - const size_t multivariate_n; - const size_t multivariate_d; - SumcheckRound round; + bool operator==(const SumcheckOutput& other) const = default; +}; - /** - * - * @brief (folded_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 - * 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.: - - 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 - |-----------------------------------| - group 0 --| * | * | * | * | ... | * | vertex 0 - \-| * | * | * | * | ... | * | vertex 1 - group 1 --| * | * | * | * | ... | * | vertex 2 - \-| * | * | * | * | ... | * | vertex 3 - | * | * | * | * | ... | * | - group m-1 --| * | * | * | * | ... | * | vertex n-2 - \-| * | * | * | * | ... | * | vertex n-1 - m = n/2 - * - Each group consists of N edges |, and our construction of univariates and folding - * - operations naturally operate on these groups of edges - - * - * 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? - */ - std::array, bonk::StandardArithmetization::NUM_POLYNOMIALS> folded_polynomials; - - // prover instantiates sumcheck with circuit size and transcript - Sumcheck(size_t multivariate_n, Transcript& 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); - } - }; +/** + * @brief Partially evaluate the multi-linear polynomial contained in `source`, at the point `round_challenge`, + * storing the result in `destination`. + * + * @param destination vector to store the resulting evaluations. It is resized to half the size of `source`. + * P'(X_1, ..., X_{d-1}) = P(u_0, X_1, ..., X_{d-1}), with n/2 cofficients [v'_0, ..., v'_{2^{d-1}-1}], where + * v'_i = v_{2i} * (1 - u_0) + v_{2i+1} * u_0. + * @param source coefficients of the polynomial we want to evaluate. + * P(X_0, X_1, ..., X_{d-1}) with n=2^d coefficients [v_0, ..., v_{2^{d}-1}]. + * @param round_challenge partial evaluation point `u_0` + * + * @details Illustration of layout in example of first round when d==3: + * + * 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 + * \- v3 X0 X1 (1-X2) --/ / - (v6(1-u0) + v7 u0) X1 X2 + * g2 -- v4 (1-X0)(1-X1) X2 --- (v4(1-X0) + v5 X0) (1-X1) X2 -/ / + * \- v5 X0 (1-X1) X2 --/ / + * g3 -- v6 (1-X0) X1 X2 --- (v6(1-X0) + v7 X0) X1 X2 -/ + * \- v7 X0 X1 X2 --/ + */ +template +static void partially_evaluate(std::vector& destination, std::span source, FF round_challenge) +{ + const size_t source_size = source.size(); // = 2^{d} + const size_t destination_size = source_size >> 1; // = 2^{d-1} + if (destination.size() < destination_size) { + // resizing may invalidate `source` + ASSERT(destination.data() != source.data()); + destination.resize(destination_size); + } + for (size_t i = 0; i < destination_size; ++i) { + const FF coefficient_even = source[i << 1]; // v_{ 2i } + const FF coefficient_odd = source[(i << 1) + 1]; // v_{2i+1} + // v'_i = (1-u_0) * v_{ 2i } + u_0 * v_{2i+1} = v_{ 2i } + u_0 * (v_{2i+1} - v_{ 2i }) + destination[i] = coefficient_even + round_challenge * (coefficient_odd - coefficient_even); + } + destination.resize(destination_size); +} - // verifier instantiates with transcript alone - explicit Sumcheck(Transcript& transcript) - : transcript(transcript) - , multivariate_n([](std::vector buffer) { - return static_cast(buffer[3]) + (static_cast(buffer[2]) << 8) + - (static_cast(buffer[1]) << 16) + (static_cast(buffer[0]) << 24); - }(transcript.get_element("circuit_size"))) - , multivariate_d(numeric::get_msb(multivariate_n)) - , round(std::tuple(Relations()...)) - { - for (auto& polynomial : folded_polynomials) { - polynomial.resize(multivariate_n >> 1); - } - }; +template class... Relations> class Sumcheck { - /** - * @brief Get all the challenges and computed parameters used in sumcheck in a convenient format - * - * @return RelationParameters - */ - RelationParameters retrieve_proof_parameters() - { - const FF alpha = FF::serialize_from_buffer(transcript.get_challenge("alpha").begin()); - const FF zeta = FF::serialize_from_buffer(transcript.get_challenge("alpha", 1).begin()); - const FF beta = FF::serialize_from_buffer(transcript.get_challenge("beta").begin()); - const FF gamma = FF::serialize_from_buffer(transcript.get_challenge("beta", 1).begin()); - const auto public_input_size_vector = transcript.get_element("public_input_size"); - const size_t public_input_size = (static_cast(public_input_size_vector[0]) << 24) | - (static_cast(public_input_size_vector[1]) << 16) | - (static_cast(public_input_size_vector[2]) << 8) | - - static_cast(public_input_size_vector[3]); - const auto circut_size_vector = transcript.get_element("circuit_size"); - const size_t n = (static_cast(circut_size_vector[0]) << 24) | - (static_cast(circut_size_vector[1]) << 16) | - (static_cast(circut_size_vector[2]) << 8) | static_cast(circut_size_vector[3]); - std::vector public_inputs = many_from_buffer(transcript.get_element("public_inputs")); - ASSERT(public_inputs.size() == public_input_size); - FF public_input_delta = honk::compute_public_input_delta(public_inputs, beta, gamma, n); - const RelationParameters relation_parameters = RelationParameters{ - .zeta = zeta, .alpha = alpha, .beta = beta, .gamma = gamma, .public_input_delta = public_input_delta - }; - return relation_parameters; - } + public: + static constexpr size_t MAX_RELATION_LENGTH = std::max({ Relations::RELATION_LENGTH... }); + static constexpr size_t NUM_POLYNOMIALS = bonk::StandardArithmetization::NUM_POLYNOMIALS; + + using RoundUnivariate = Univariate; + using SumcheckRound = SumcheckRound; /** * @brief Compute univariate restriction place in transcript, generate challenge, fold,... repeat until final round, @@ -118,43 +86,98 @@ template class... Relations> cl * * @details */ - void execute_prover(auto full_polynomials) // pass by value, not by reference + static SumcheckOutput execute_prover(const size_t multivariate_d, + const RelationParameters& relation_parameters, + auto full_polynomials, // pass by value, not by reference + auto& transcript) { - // First round - // This populates folded_polynomials. - - const auto relation_parameters = retrieve_proof_parameters(); - PowUnivariate pow_univariate(relation_parameters.zeta); - - auto round_univariate = round.compute_univariate(full_polynomials, relation_parameters, pow_univariate); - transcript.add_element("univariate_0", round_univariate.to_buffer()); - std::string challenge_label = "u_0"; - transcript.apply_fiat_shamir(challenge_label); - FF round_challenge = FF::serialize_from_buffer(transcript.get_challenge(challenge_label).begin()); - fold(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? - - // All but final round - // We operate on folded_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); + const FF alpha = FF::serialize_from_buffer(transcript.get_challenge("alpha").begin()); + const FF zeta = FF::serialize_from_buffer(transcript.get_challenge("alpha", 1).begin()); + + /** + * Suppose the Honk `full_polynomials` (multilinear in d variables) are called P_1, ..., P_{NUM_POLYNOMIALS}. + * 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 ('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}. + * + * We imagine all of the defining polynomial data in a matrix like this: + * | P_1 | P_2 | P_3 | P_4 | ... | P_N | N = NUM_POLYNOMIALS + * |-----------------------------------| + * group 0 --| * | * | * | * | ... | * | vertex 0 + * \-| * | * | * | * | ... | * | vertex 1 + * group 1 --| * | * | * | * | ... | * | vertex 2 + * \-| * | * | * | * | ... | * | vertex 3 + * | * | * | * | * | ... | * | + * group m-1 --| * | * | * | * | ... | * | vertex n-2 + * \-| * | * | * | * | ... | * | vertex n-1 + * m = n/2 + * + * At the start of round l>0, the array contains the n/2^l evaluation of + * P_i(u0, ..., u_{l-1}, X_l, ..., X_{d-1}), and at the end of the round it is evaluated in X_l = u_l, + * where u_l is the challenge point sent by the verifier. + * + * Since the Honk prover requires the full description of the `full_polynomials` for the PCS opening, we store + * the partial evaluations in `partially_evaluated_polynomials`, an array of temporary buffers. + * To make the rounds uniform, we perform the Sumcheck rounds over `round_polynomials` which represents the + * matrix of partially evaluated polynomials for the given round. + * + * + * 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? + */ + std::array, NUM_POLYNOMIALS> round_polynomials; + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + round_polynomials[i] = full_polynomials[i]; + } + + /** + * Array of temporary buffers containing the partial evaluations of the `full_polynomials` + * The function `partially_evaluate` takes care of resizing the vectors after each partial evaluation. + */ + std::array, NUM_POLYNOMIALS> partially_evaluated_polynomials; + + // Store the multi-variate evaluation point u = (u_0, ..., u_{d-1}) + std::vector evaluation_points; + evaluation_points.reserve(multivariate_d); + + // The pow polynomial and its partial evaluations can be efficiently computed by the PowUnivariate class. + PowUnivariate pow_univariate(zeta); + + // Perform the d Sumcheck rounds + for (size_t round_idx = 0; round_idx < multivariate_d; round_idx++) { + const size_t round_size = 1 << (multivariate_d - round_idx); + // Write the round univariate T_l(X) to the transcript + // Multiply by [(1-X) + ζ^{ 2^{l} } X] to obtain the full round univariate S_l(X). + RoundUnivariate round_univariate = SumcheckRound::compute_univariate( + round_polynomials, round_size, relation_parameters, pow_univariate, alpha); transcript.add_element("univariate_" + std::to_string(round_idx), round_univariate.to_buffer()); - challenge_label = "u_" + std::to_string(round_idx); + + // Get the challenge + auto challenge_label = "u_" + std::to_string(round_idx); transcript.apply_fiat_shamir(challenge_label); FF round_challenge = FF::serialize_from_buffer(transcript.get_challenge(challenge_label).begin()); - fold(folded_polynomials, round.round_size, round_challenge); + evaluation_points.emplace_back(round_challenge); + + // Perform partial evaluation of the round polynomials, in the evaluation point u_l + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + // The polynomials in `partially_evaluated_polynomials` are resized appropriately. + partially_evaluate(partially_evaluated_polynomials[i], round_polynomials[i], round_challenge); + // Sets the polynomials for the next round. + round_polynomials[i] = partially_evaluated_polynomials[i]; + } 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 - std::array multivariate_evaluations; - for (size_t i = 0; i < bonk::StandardArithmetization::NUM_POLYNOMIALS; ++i) { - multivariate_evaluations[i] = folded_polynomials[i][0]; + std::array multivariate_evaluations; + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + ASSERT(partially_evaluated_polynomials[i].size() == 1); + multivariate_evaluations[i] = partially_evaluated_polynomials[i][0]; } transcript.add_element("multivariate_evaluations", to_buffer(multivariate_evaluations)); + + return SumcheckOutput{ .evaluation_point = evaluation_points, .evaluations = multivariate_evaluations }; }; /** @@ -162,73 +185,100 @@ template class... Relations> cl * round, then use purported evaluations to generate purported full Honk relation value and check against final * target sum. */ - bool execute_verifier() + static std::optional> execute_verifier(const size_t multivariate_d, + const RelationParameters& relation_parameters, + auto& transcript) { - bool verified(true); + const FF alpha = FF::serialize_from_buffer(transcript.get_challenge("alpha").begin()); + const FF zeta = FF::serialize_from_buffer(transcript.get_challenge("alpha", 1).begin()); - const auto relation_parameters = retrieve_proof_parameters(); - PowUnivariate pow_univariate(relation_parameters.zeta); - // All but final round. - // target_total_sum is initialized to zero then mutated in place. + PowUnivariate pow_univariate(zeta); - if (multivariate_d == 0) { - throw_or_abort("Number of variables in multivariate is 0."); - } + // Used to evaluate T_l in each round. + auto barycentric = BarycentricData(); - for (size_t round_idx = 0; round_idx < multivariate_d; round_idx++) { + // Keep track of the evaluation points and so we can return them upon successful verification. + std::vector evaluation_points; + evaluation_points.reserve(multivariate_d); + + // initialize sigma_0 = 0 + FF target_sum{ 0 }; + for (size_t round_idx = 0; round_idx < multivariate_d; ++round_idx) { // Obtain the round univariate from the transcript - auto round_univariate = Univariate::serialize_from_buffer( + auto T_l = RoundUnivariate::serialize_from_buffer( &transcript.get_element("univariate_" + std::to_string(round_idx))[0]); - bool checked = round.check_sum(round_univariate, pow_univariate); - verified = verified && checked; - FF round_challenge = - FF::serialize_from_buffer(transcript.get_challenge("u_" + std::to_string(round_idx)).begin()); - round.compute_next_target_sum(round_univariate, round_challenge, pow_univariate); - pow_univariate.partially_evaluate(round_challenge); + // The "real" round polynomial S_l(X) is ( (1−X) + X⋅ζ^{ 2^{l} } ) ⋅ T_l(X) + // S_l(0) + S_l(1) = T^{l}(0) + ζ^{ 2^{l} } ⋅ T^{l}(1), since + // S^{l}(0) = ( (1−0) + 0⋅ζ^{ 2^{l} } ) ⋅ T^{l}(0) = T^{l}(0) + // S^{l}(1) = ( (1−1) + 1⋅ζ^{ 2^{l} } ) ⋅ T^{l}(1) = ζ^{ 2^{l} } ⋅ T^{l}(1) + FF claimed_sum = T_l.value_at(0) + (pow_univariate.zeta_pow * T_l.value_at(1)); - if (!verified) { - return false; + // If the evaluation is wrong, abort and return nothing to indicate failure. + if (claimed_sum != target_sum) { + return std::nullopt; } + + // Get the next challenge point and store it. + FF u_l = FF::serialize_from_buffer(transcript.get_challenge("u_" + std::to_string(round_idx)).begin()); + evaluation_points.emplace_back(u_l); + + // Compute next target_sum + // sigma_{l+1} = S^l(u_l) + // = T^l(u_l) * [ (1−u_l) + u_l⋅ζ^{ 2^l } ] + target_sum = barycentric.evaluate(T_l, u_l) * pow_univariate.univariate_eval(u_l); + + // Partially evaluate the pow_zeta polynomial + pow_univariate.partially_evaluate(u_l); } // Final round - auto purported_evaluations = transcript.get_field_element_vector("multivariate_evaluations"); - FF full_honk_relation_purported_value = round.compute_full_honk_relation_purported_value( - purported_evaluations, relation_parameters, pow_univariate); - verified = verified && (full_honk_relation_purported_value == round.target_total_sum); - return verified; - }; + auto purported_evaluations_vec = transcript.get_field_element_vector("multivariate_evaluations"); + std::array purported_evaluations{}; + std::copy_n(purported_evaluations_vec.begin(), NUM_POLYNOMIALS, purported_evaluations.begin()); + + // The full Honk identity evaluated in the opening point u. + FF full_eval = compute_full_evaluation( + purported_evaluations, pow_univariate.partial_evaluation_constant, relation_parameters, alpha); + + // Check against sigma_d + if (full_eval != target_sum) { + return std::nullopt; + } + + return SumcheckOutput{ .evaluation_point = evaluation_points, .evaluations = 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): + * @brief Given the multi-linear evaluations of the Sumcheck polynomials, + * computes the evaluation of the full Honk identity. * - * groups vertex terms collected vertex terms groups after folding - * 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 - * \- v3 X0 X1 (1-X2) --/ / - (v6(1-u0) + v7 u0) X1 X2 - * g2 -- v4 (1-X0)(1-X1) X2 --- (v4(1-X0) + v5 X0) (1-X1) X2 -/ / - * \- v5 X0 (1-X1) X2 --/ / - * g3 -- v6 (1-X0) X1 X2 --- (v6(1-X0) + v7 X0) X1 X2 -/ - * \- v7 X0 X1 X2 --/ - * - * @param challenge + * @param multivariate_evaluations container with polynomial + * @param pow_zeta_eval Evaluation of pow, computed by the verifier which multiplies the full identity. + * @param relation_parameters required by certain relations. + * @param alpha relation separation challenge. + * @return */ - void fold(auto& polynomials, size_t round_size, FF round_challenge) + static FF compute_full_evaluation(std::span multivariate_evaluations, + const FF pow_zeta_eval, + const RelationParameters& relation_parameters, + const FF alpha) { - // after the first round, operate in place on folded_polynomials - for (size_t j = 0; j < polynomials.size(); ++j) { - // for (size_t j = 0; j < bonk::StandardArithmetization::NUM_POLYNOMIALS; ++j) { - for (size_t i = 0; i < round_size; i += 2) { - folded_polynomials[j][i >> 1] = - polynomials[j][i] + round_challenge * (polynomials[j][i + 1] - polynomials[j][i]); - } + constexpr size_t NUM_RELATIONS = sizeof...(Relations); + // Compute the evaluations of each relation by unpacking the type `Relations` + std::array relation_evals = { Relations::evaluate_full_relation_value_contribution( + multivariate_evaluations, relation_parameters)... }; + + // Do the alpha-linear combination + FF alpha_pow{ alpha }; + FF full_eval{ relation_evals[0] }; + for (size_t i = 1; i < NUM_RELATIONS; ++i) { + full_eval += relation_evals[i] * alpha_pow; + alpha_pow *= alpha; } - }; + // Multiply by the evaluation of pow + full_eval *= pow_zeta_eval; + return full_eval; + } }; } // namespace honk::sumcheck diff --git a/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp b/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp index e8b6830233..276b65473e 100644 --- a/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp +++ b/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp @@ -1,22 +1,21 @@ #include "sumcheck.hpp" -#include "barretenberg/proof_system/flavor/flavor.hpp" -#include "barretenberg/transcript/transcript_wrappers.hpp" #include "relations/arithmetic_relation.hpp" #include "relations/grand_product_computation_relation.hpp" #include "relations/grand_product_initialization_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/relation.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" +#include "barretenberg/transcript/transcript_wrappers.hpp" #include "barretenberg/transcript/manifest.hpp" -#include -#include -#include #include "barretenberg/ecc/curves/bn254/fr.hpp" -#include #include "barretenberg/numeric/random/engine.hpp" #include #include #include -#include #include +#include +#include +#include using namespace honk; using namespace honk::sumcheck; @@ -196,19 +195,15 @@ TEST(Sumcheck, PolynomialNormalization) lagrange_first, lagrange_last); + using Sumcheck = + Sumcheck; auto transcript = produce_mocked_transcript(multivariate_d, num_public_inputs); - auto sumcheck = Sumcheck(multivariate_n, transcript); - - sumcheck.execute_prover(full_polynomials); + auto [evaluation_points, evals] = Sumcheck::execute_prover(multivariate_d, {}, full_polynomials, transcript); - FF u_0 = transcript.get_challenge_field_element("u_0"); - FF u_1 = transcript.get_challenge_field_element("u_1"); - FF u_2 = transcript.get_challenge_field_element("u_2"); + FF u_0 = evaluation_points[0]; + FF u_1 = evaluation_points[1]; + FF u_2 = evaluation_points[2]; /* sumcheck.execute_prover() terminates with sumcheck.multivariates.folded_polynoimals as an array such that * sumcheck.multivariates.folded_polynoimals[i][0] is the evaluatioin of the i'th multivariate at the vector of @@ -238,7 +233,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, evals[i]); } } @@ -298,15 +293,12 @@ TEST(Sumcheck, Prover) lagrange_last); auto transcript = produce_mocked_transcript(multivariate_d, num_public_inputs); - auto sumcheck = Sumcheck(multivariate_n, transcript); - - sumcheck.execute_prover(full_polynomials); - FF u_0 = transcript.get_challenge_field_element("u_0"); - FF u_1 = transcript.get_challenge_field_element("u_1"); + using Sumcheck = + Sumcheck; + + auto [evaluation_points, evals] = Sumcheck::execute_prover(multivariate_d, {}, full_polynomials, transcript); + FF u_0 = evaluation_points[0]; + FF u_1 = evaluation_points[1]; std::vector expected_values; for (auto& polynomial : full_polynomials) { // using knowledge of inputs here to derive the evaluation @@ -316,10 +308,8 @@ TEST(Sumcheck, Prover) expected_hi *= u_1; expected_values.emplace_back(expected_lo + expected_hi); } - // pull the sumcheck-produced multivariate evals out of the transcript - auto sumcheck_evaluations = transcript.get_field_element_vector("multivariate_evaluations"); for (size_t poly_idx = 0; poly_idx < NUM_POLYNOMIALS; poly_idx++) { - EXPECT_EQ(sumcheck_evaluations[poly_idx], expected_values[poly_idx]); + EXPECT_EQ(evals[poly_idx], expected_values[poly_idx]); } }; run_test(/* is_random_input=*/false); @@ -330,7 +320,6 @@ TEST(Sumcheck, Prover) TEST(Sumcheck, ProverAndVerifier) { const size_t multivariate_d(1); - const size_t multivariate_n(1 << multivariate_d); const size_t num_public_inputs(1); std::array w_l = { 0, 1 }; @@ -371,24 +360,16 @@ TEST(Sumcheck, ProverAndVerifier) lagrange_first, lagrange_last); - auto transcript = produce_mocked_transcript(multivariate_d, num_public_inputs); + using Sumcheck = + Sumcheck; - auto sumcheck_prover = Sumcheck(multivariate_n, transcript); - - sumcheck_prover.execute_prover(full_polynomials); + auto transcript = produce_mocked_transcript(multivariate_d, num_public_inputs); - auto sumcheck_verifier = Sumcheck(transcript); + auto prover_output = Sumcheck::execute_prover(multivariate_d, {}, full_polynomials, transcript); - bool verified = sumcheck_verifier.execute_verifier(); - ASSERT_TRUE(verified); + auto verifier_output = Sumcheck::execute_verifier(multivariate_d, {}, transcript); + ASSERT_TRUE(verifier_output.has_value()); + ASSERT_EQ(prover_output, *verifier_output); } // TODO(#225): make the inputs to this test more interesting, e.g. num_public_inputs > 0 and non-trivial permutations @@ -443,24 +424,16 @@ TEST(Sumcheck, ProverAndVerifierLonger) lagrange_first, lagrange_last); - auto transcript = produce_mocked_transcript(multivariate_d, num_public_inputs); + using Sumcheck = + Sumcheck; - auto sumcheck_prover = Sumcheck(multivariate_n, transcript); + auto transcript = produce_mocked_transcript(multivariate_d, num_public_inputs); - sumcheck_prover.execute_prover(full_polynomials); + auto prover_output = Sumcheck::execute_prover(multivariate_d, {}, full_polynomials, transcript); - auto sumcheck_verifier = Sumcheck(transcript); + auto verifier_output = Sumcheck::execute_verifier(multivariate_d, {}, transcript); - bool verified = sumcheck_verifier.execute_verifier(); - EXPECT_EQ(verified, expect_verified); + EXPECT_EQ(verifier_output.has_value(), expect_verified); }; run_test(/* expect_verified=*/true); diff --git a/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp b/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp index fa1d5750e0..76433c4b1a 100644 --- a/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp @@ -1,12 +1,11 @@ #pragma once -#include "barretenberg/common/log.hpp" -#include -#include -#include #include "polynomials/barycentric_data.hpp" #include "polynomials/univariate.hpp" #include "polynomials/pow.hpp" #include "relations/relation.hpp" +#include +#include +#include namespace honk::sumcheck { @@ -52,63 +51,17 @@ namespace honk::sumcheck { template class... Relations> class SumcheckRound { - public: - 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 std::array RELATION_LENGTHS = { Relations::RELATION_LENGTH... }; static constexpr size_t MAX_RELATION_LENGTH = std::max({ Relations::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; - std::array evaluations; - std::array, num_multivariates> extended_edges; - std::array, NUM_RELATIONS> extended_univariates; - - // TODO(#224)(Cody): this should go away and we should use constexpr method to extend - BarycentricData barycentric_2_to_max = BarycentricData(); - - // Prover constructor - SumcheckRound(size_t initial_round_size, auto&& relations) - : 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) - { - // 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. - std::fill(evaluations.begin(), evaluations.end(), FF(0)); - }; - - /** - * @brief After computing the round univariate, it is necessary to zero-out the accumulators used to compute it. - */ - template void reset_accumulators() - { - auto& univariate = std::get(univariate_accumulators); - std::fill(univariate.evaluations.begin(), univariate.evaluations.end(), FF(0)); - - if constexpr (idx + 1 < NUM_RELATIONS) { - reset_accumulators(); - } - }; - // IMPROVEMENT(Cody): This is kind of ugly. There should be a one-liner with folding - // or std::apply or something. + static constexpr std::tuple...> relations = std::tuple{ Relations()... }; /** * @brief Given a tuple t = (t_0, t_1, ..., t_{NUM_RELATIONS-1}) and a challenge α, * modify the tuple in place to (t_0, αt_1, ..., α^{NUM_RELATIONS-1}t_{NUM_RELATIONS-1}). */ - template void scale_tuple(auto& tuple, FF challenge, FF running_challenge) + template static void scale_tuple(auto& tuple, FF challenge, FF running_challenge) { std::get(tuple) *= running_challenge; running_challenge *= challenge; @@ -122,12 +75,17 @@ template class... Relation * return t_0 + αt_1 + ... + α^{NUM_RELATIONS-1}t_{NUM_RELATIONS-1}). * * @tparam T : In practice, this is an FF or a Univariate. + * @param univariate_accumulators tuple of Univariates for each relation. Each one is of size of the relation's + * length + * @param challenge the relation separation challenge + * @return T */ - template T batch_over_relations(FF challenge) + template static T batch_over_relations(auto& univariate_accumulators, FF challenge) { + std::array, NUM_RELATIONS> extended_univariates; FF running_challenge = 1; scale_tuple<>(univariate_accumulators, challenge, running_challenge); - extend_univariate_accumulators<>(); + extend_univariate_accumulators<>(extended_univariates, univariate_accumulators); auto result = T(); for (size_t i = 0; i < NUM_RELATIONS; ++i) { result += extended_univariates[i]; @@ -142,9 +100,15 @@ template class... Relation * * @details Should only be called externally with relation_idx equal to 0. * + * @param extended_edges array of univariates we store the extended edges into + * @param multivariates array of multivariate polynomials + * @param edge_idx index in the hypercube of the edges we are extending */ - void extend_edges(auto& multivariates, size_t edge_idx) + static void extend_edges(auto& extended_edges, const auto& multivariates, size_t edge_idx) { + // TODO(#224)(Cody): this should go away and we should use constexpr method to extend + static BarycentricData barycentric_2_to_max = + BarycentricData(); for (size_t idx = 0; idx < num_multivariates; idx++) { auto edge = Univariate({ multivariates[idx][edge_idx], multivariates[idx][edge_idx + 1] }); extended_edges[idx] = barycentric_2_to_max.extend(edge); @@ -156,115 +120,64 @@ template class... Relation * extend all univariates to the max of the lenghths required by the largest relation. * * @tparam relation_idx + * @param extended_univariates array of Univariate of size MAX_RELATION_LENGTHS in which we store the result + * @param univariate_accumulators tuple of Univariates we want to extend. */ - template void extend_univariate_accumulators() + template + static void extend_univariate_accumulators(auto& extended_univariates, const auto& univariate_accumulators) { - extended_univariates[relation_idx] = - std::get(barycentric_utils).extend(std::get(univariate_accumulators)); + // TODO(#224)(Cody): this barycentric stuff should be more built-in? + static auto barycentric_utils = BarycentricData(); + + extended_univariates[relation_idx] = barycentric_utils.extend(std::get(univariate_accumulators)); // Repeat for the next relation. if constexpr (relation_idx + 1 < NUM_RELATIONS) { - extend_univariate_accumulators(); + extend_univariate_accumulators(extended_univariates, univariate_accumulators); } } + public: /** * @brief Return the evaluations of the univariate restriction (S_l(X_l) in the thesis) at num_multivariates-many - * values. Most likely this will end up being S_l(0), ... , S_l(t-1) where t is around 12. At the end, reset all - * univariate accumulators to be zero. + * values. Most likely this will end up being S_l(0), ... , S_l(t-1) where t is around 12. + * + * @param polynomials container of spans with the coefficients of + * @param round_size number of evaluations in each polynomial + * @param relation_parameters parameters for the relations + * @param pow_univariate container for the pow polynomial + * @param alpha relation separation challenge + * @return Univariate S_l(X), as evaluations over {0,1,...,t-1} */ - Univariate compute_univariate(auto& polynomials, - const RelationParameters& relation_parameters, - const PowUnivariate& pow_univariate) + static Univariate compute_univariate(auto& polynomials, + const size_t round_size, + const RelationParameters& relation_parameters, + const PowUnivariate& pow_univariate, + const FF alpha) { + auto univariate_accumulators = std::tuple{ Univariate::RELATION_LENGTH>()... }; + std::array, num_multivariates> extended_edges; + // For each edge_idx = 2i, we need to multiply the whole contribution by zeta^{2^{2i}} // This means that each univariate for each relation needs an extra multiplication. FF pow_challenge = pow_univariate.partial_evaluation_constant; for (size_t edge_idx = 0; edge_idx < round_size; edge_idx += 2) { - extend_edges(polynomials, edge_idx); + extend_edges(extended_edges, polynomials, edge_idx); // Compute the i-th edge's univariate contribution, // scale it by the pow polynomial's constant and zeta power "c_l ⋅ ζ_{l+1}ⁱ" // and add it to the accumulators for Sˡ(Xₗ) - accumulate_relation_univariates<>(relation_parameters, pow_challenge); + accumulate_relation_univariates<>( + univariate_accumulators, extended_edges, relation_parameters, pow_challenge); // Update the pow polynomial's contribution c_l ⋅ ζ_{l+1}ⁱ for the next edge. pow_challenge *= pow_univariate.zeta_pow_sqr; } - auto result = batch_over_relations>(relation_parameters.alpha); - - reset_accumulators<>(); + auto result = batch_over_relations>(univariate_accumulators, alpha); return result; } - /** - * @brief Calculate the contribution of each relation to the expected value of the full Honk relation. - * - * @details For each relation, use the purported values (supplied by the prover) of the multivariates to calculate - * a contribution to the purported value of the full Honk relation. These are stored in `evaluations`. Adding these - * 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. - */ - // TODO(#224)(Cody): Input should be an array? - FF compute_full_honk_relation_purported_value(std::vector& purported_evaluations, - const RelationParameters& relation_parameters, - const PowUnivariate& pow_univariate) - { - accumulate_relation_evaluations<>(purported_evaluations, relation_parameters); - - // IMPROVEMENT(Cody): Reuse functions from univariate_accumulators batching? - FF running_challenge = 1; - FF output = 0; - for (auto& evals : evaluations) { - output += evals * running_challenge; - running_challenge *= relation_parameters.alpha; - } - output *= pow_univariate.partial_evaluation_constant; - - return output; - } - - /** - * @brief check if S^{l}(0) + S^{l}(1) = S^{l-1}(u_{l-1}) = sigma_{l} (or 0 if l=0) - * - * @param univariate T^{l}(X), the round univariate that is equal to S^{l}(X)/( (1−X) + X⋅ζ^{ 2^l } ) - */ - bool check_sum(Univariate& univariate, const PowUnivariate& pow_univariate) - { - // S^{l}(0) = ( (1−0) + 0⋅ζ^{ 2^l } ) ⋅ T^{l}(0) = T^{l}(0) - // S^{l}(1) = ( (1−1) + 1⋅ζ^{ 2^l } ) ⋅ T^{l}(1) = ζ^{ 2^l } ⋅ T^{l}(1) - FF total_sum = univariate.value_at(0) + (pow_univariate.zeta_pow * univariate.value_at(1)); - // target_total_sum = sigma_{l} = - bool sumcheck_round_failed = (target_total_sum != total_sum); - round_failed = round_failed || sumcheck_round_failed; - return !sumcheck_round_failed; - }; - - /** - * @brief After checking that the univariate is good for this round, compute the next target sum. - * - * @param univariate T^l(X), given by its evaluations over {0,1,2,...}, - * equal to S^{l}(X)/( (1−X) + X⋅ζ^{ 2^l } ) - * @param round_challenge u_l - * @return FF sigma_{l+1} = S^l(u_l) - */ - FF compute_next_target_sum(Univariate& univariate, - FF& round_challenge, - const PowUnivariate& pow_univariate) - { - // IMPROVEMENT(Cody): Use barycentric static method, maybe implement evaluation as member - // function on Univariate. - auto barycentric = BarycentricData(); - // Evaluate T^{l}(u_{l}) - target_total_sum = barycentric.evaluate(univariate, round_challenge); - // Evaluate (1−u_l) + u_l ⋅ ζ^{2^l} ) - FF pow_monomial_eval = pow_univariate.univariate_eval(round_challenge); - // sigma_{l+1} = S^l(u_l) = (1−u_l) + u_l⋅ζ^{2^l} ) ⋅ T^{l}(u_l) - target_total_sum *= pow_monomial_eval; - return target_total_sum; - } - private: /** * @brief For a given edge, calculate the contribution of each relation to the prover round univariate (S_l in the @@ -280,39 +193,22 @@ template class... Relation * Result: for each relation, a univariate of some degree is computed by accumulating the contributions of each * group of edges. These are stored in `univariate_accumulators`. Adding these univariates together, with * appropriate scaling factors, produces S_l. + * @param univariate_accumulators tuple containing the accumulated evaluations for each relation + * @param extended_edges array of Univariates, extended to MAX_RELATION_LENGTH */ template - void accumulate_relation_univariates(const RelationParameters& relation_parameters, const FF& scaling_factor) + static void accumulate_relation_univariates(auto& univariate_accumulators, + const auto& extended_edges, + const RelationParameters& relation_parameters, + const FF& scaling_factor) { std::get(relations).add_edge_contribution( std::get(univariate_accumulators), extended_edges, relation_parameters, scaling_factor); // Repeat for the next relation. if constexpr (relation_idx + 1 < NUM_RELATIONS) { - accumulate_relation_univariates(relation_parameters, scaling_factor); - } - } - - // TODO(#224)(Cody): make uniform with accumulate_relation_univariates - /** - * @brief Calculate the contribution of each relation to the expected value of the full Honk relation. - * - * @details For each relation, use the purported values (supplied by the prover) of the multivariates to calculate - * a contribution to the purported value of the full Honk relation. These are stored in `evaluations`. Adding these - * 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 (called sigma_0 in the thesis). - */ - template - // TODO(#224)(Cody): Input should be an array? - void accumulate_relation_evaluations(std::vector& purported_evaluations, - const RelationParameters& relation_parameters) - { - std::get(relations).add_full_relation_value_contribution( - evaluations[relation_idx], purported_evaluations, relation_parameters); - - // Repeat for the next relation. - if constexpr (relation_idx + 1 < NUM_RELATIONS) { - accumulate_relation_evaluations(purported_evaluations, relation_parameters); + accumulate_relation_univariates( + univariate_accumulators, extended_edges, relation_parameters, scaling_factor); } } }; diff --git a/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp b/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp index 95f2677239..a42fec5185 100644 --- a/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp +++ b/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp @@ -1,15 +1,15 @@ -#include "barretenberg/proof_system/flavor/flavor.hpp" #include "sumcheck_round.hpp" +#include "sumcheck.hpp" +#include "polynomials/univariate.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/proof_system/flavor/flavor.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/numeric/random/engine.hpp" #include -#include "barretenberg/common/mem.hpp" #include /** * We want to test if the univariate (S_l in the thesis) computed by the prover in a particular round is correct. We @@ -78,17 +78,16 @@ std::array, NUM_POLYNOMIALS> construct_full_polynomials(std::array // The below two methods are used in the test ComputeUnivariateProver static Univariate compute_round_univariate( std::array, NUM_POLYNOMIALS>& input_polynomials, - const RelationParameters& relation_parameters) + const RelationParameters& relation_parameters, + 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); + using SumcheckRound = SumcheckRound; auto w_l = input_polynomials[0]; auto w_r = input_polynomials[1]; auto w_o = input_polynomials[2]; @@ -126,15 +125,16 @@ static Univariate compute_round_univariate( id_3, lagrange_first, lagrange_last); - PowUnivariate pow_zeta(relation_parameters.zeta); + PowUnivariate pow_zeta(1); Univariate round_univariate = - round.compute_univariate(full_polynomials, relation_parameters, pow_zeta); + SumcheckRound::compute_univariate(full_polynomials, round_size, relation_parameters, pow_zeta, alpha); return round_univariate; } static Univariate compute_expected_round_univariate( std::array, NUM_POLYNOMIALS>& input_univariates, - const RelationParameters& relation_parameters) + const RelationParameters& relation_parameters, + const FF alpha) { BarycentricData barycentric_2_to_max = BarycentricData(); @@ -177,17 +177,17 @@ static Univariate compute_expected_round_univariate( (w_o_univariate + sigma_3_univariate * relation_parameters.beta + relation_parameters.gamma)); auto expected_grand_product_initialization_relation = (z_perm_shift_univariate * lagrange_last_univariate); Univariate expected_round_univariate = - expected_arithmetic_relation + expected_grand_product_computation_relation * relation_parameters.alpha + - expected_grand_product_initialization_relation * relation_parameters.alpha * relation_parameters.alpha; + expected_arithmetic_relation + expected_grand_product_computation_relation * alpha + + expected_grand_product_initialization_relation * alpha.sqr(); return expected_round_univariate; } // The below two methods are used in the test ComputeUnivariateVerifier static FF compute_full_purported_value(std::array& input_values, - const RelationParameters& relation_parameters) + const RelationParameters& relation_parameters, + const FF alpha) { - std::vector purported_evaluations; - purported_evaluations.resize(NUM_POLYNOMIALS); + std::array purported_evaluations; purported_evaluations[POLYNOMIAL::W_L] = input_values[0]; purported_evaluations[POLYNOMIAL::W_R] = input_values[1]; purported_evaluations[POLYNOMIAL::W_O] = input_values[2]; @@ -206,21 +206,16 @@ static FF compute_full_purported_value(std::array& input_va purported_evaluations[POLYNOMIAL::ID_3] = input_values[15]; purported_evaluations[POLYNOMIAL::LAGRANGE_FIRST] = input_values[16]; purported_evaluations[POLYNOMIAL::LAGRANGE_LAST] = input_values[17]; - auto relations = std::tuple( - ArithmeticRelation(), GrandProductComputationRelation(), GrandProductInitializationRelation()); - auto round = SumcheckRound(relations); - PowUnivariate pow_univariate(relation_parameters.zeta); - FF full_purported_value = - round.compute_full_honk_relation_purported_value(purported_evaluations, relation_parameters, pow_univariate); + using Sumcheck = + Sumcheck; + PowUnivariate pow_univariate(1); + FF full_purported_value = Sumcheck::compute_full_evaluation(purported_evaluations, 1, relation_parameters, alpha); return full_purported_value; } static FF compute_full_purported_value_expected(std::array& input_values, - const RelationParameters& relation_parameters) + const RelationParameters& relation_parameters, + const FF alpha) { FF w_l = input_values[0]; FF w_r = input_values[1]; @@ -251,9 +246,9 @@ static FF compute_full_purported_value_expected(std::array& (w_r + sigma_2 * relation_parameters.beta + relation_parameters.gamma) * (w_o + sigma_3 * relation_parameters.beta + relation_parameters.gamma); auto expected_grand_product_initialization_relation = z_perm_shift * lagrange_last; - auto expected_full_purported_value = - expected_arithmetic_relation + expected_grand_product_computation_relation * relation_parameters.alpha + - expected_grand_product_initialization_relation * relation_parameters.alpha * relation_parameters.alpha; + auto expected_full_purported_value = expected_arithmetic_relation + + expected_grand_product_computation_relation * alpha + + expected_grand_product_initialization_relation * alpha.sqr(); return expected_full_purported_value; } @@ -265,19 +260,18 @@ TEST(SumcheckRound, ComputeUnivariateProver) for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = { FF::random_element(), FF::random_element() }; } - const RelationParameters relation_parameters = - RelationParameters{ .zeta = FF::random_element(), - .alpha = FF::random_element(), - .beta = FF::random_element(), - .gamma = FF::random_element(), - .public_input_delta = FF::random_element() }; - auto round_univariate = compute_round_univariate(input_polynomials, relation_parameters); + const FF alpha = FF::random_element(); + const RelationParameters relation_parameters = RelationParameters{ + .beta = FF::random_element(), .gamma = FF::random_element(), .public_input_delta = FF::random_element() + }; + auto round_univariate = compute_round_univariate(input_polynomials, relation_parameters, alpha); // Compute round_univariate manually std::array, NUM_POLYNOMIALS> input_univariates; for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_univariates[i] = Univariate(input_polynomials[i]); } - auto expected_round_univariate = compute_expected_round_univariate(input_univariates, relation_parameters); + auto expected_round_univariate = + compute_expected_round_univariate(input_univariates, relation_parameters, alpha); EXPECT_EQ(round_univariate, expected_round_univariate); } else { std::array, NUM_POLYNOMIALS> input_polynomials; @@ -285,15 +279,16 @@ TEST(SumcheckRound, ComputeUnivariateProver) input_polynomials[i] = { 1, 2 }; } const RelationParameters relation_parameters = - RelationParameters{ .zeta = 1, .alpha = 1, .beta = 1, .gamma = 1, .public_input_delta = 1 }; - auto round_univariate = compute_round_univariate(input_polynomials, relation_parameters); + RelationParameters{ .beta = 1, .gamma = 1, .public_input_delta = 1 }; + auto round_univariate = compute_round_univariate(input_polynomials, relation_parameters, 1); // Compute round_univariate manually std::array, NUM_POLYNOMIALS> input_univariates; for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_univariates[i] = Univariate(input_polynomials[i]); } // expected_round_univariate = { 6, 26, 66, 132, 230, 366 } - auto expected_round_univariate = compute_expected_round_univariate(input_univariates, relation_parameters); + auto expected_round_univariate = + compute_expected_round_univariate(input_univariates, relation_parameters, 1); EXPECT_EQ(round_univariate, expected_round_univariate); }; }; @@ -309,16 +304,14 @@ TEST(SumcheckRound, ComputeUnivariateVerifier) for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_values[i] = FF::random_element(); } - const RelationParameters relation_parameters = - RelationParameters{ .zeta = FF::random_element(), - .alpha = FF::random_element(), - .beta = FF::random_element(), - .gamma = FF::random_element(), - .public_input_delta = FF::random_element() }; - auto full_purported_value = compute_full_purported_value(input_values, relation_parameters); + const FF alpha = FF::random_element(); + const RelationParameters relation_parameters = RelationParameters{ + .beta = FF::random_element(), .gamma = FF::random_element(), .public_input_delta = FF::random_element() + }; + auto full_purported_value = compute_full_purported_value(input_values, relation_parameters, alpha); // Compute round_univariate manually auto expected_full_purported_value = - compute_full_purported_value_expected(input_values, relation_parameters); + compute_full_purported_value_expected(input_values, relation_parameters, alpha); EXPECT_EQ(full_purported_value, expected_full_purported_value); } else { std::array input_values; @@ -326,11 +319,11 @@ TEST(SumcheckRound, ComputeUnivariateVerifier) input_values[i] = FF(2); } const RelationParameters relation_parameters = - RelationParameters{ .zeta = 2, .alpha = 1, .beta = 1, .gamma = 1, .public_input_delta = 1 }; - auto full_purported_value = compute_full_purported_value(input_values, relation_parameters); + RelationParameters{ .beta = 1, .gamma = 1, .public_input_delta = 1 }; + auto full_purported_value = compute_full_purported_value(input_values, relation_parameters, 1); // Compute round_univariate manually auto expected_full_purported_value = - compute_full_purported_value_expected(input_values, relation_parameters); + compute_full_purported_value_expected(input_values, relation_parameters, 1); EXPECT_EQ(full_purported_value, expected_full_purported_value); }; }; From f45669bb2e49921b44c00c6bce6d93e9d9dc0217 Mon Sep 17 00:00:00 2001 From: adr1anh Date: Wed, 15 Mar 2023 16:23:48 +0000 Subject: [PATCH 2/2] fix build --- cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp | 4 ++-- .../honk/sumcheck/sumcheck_round.test.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp b/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp index a63aec3d56..cfe968bbd0 100644 --- a/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp @@ -8,6 +8,7 @@ #include "barretenberg/numeric/bitop/get_msb.hpp" #include +#include #include #include #include @@ -78,7 +79,6 @@ template class... Relations> class Sumcheck { static constexpr size_t NUM_POLYNOMIALS = bonk::StandardArithmetization::NUM_POLYNOMIALS; using RoundUnivariate = Univariate; - using SumcheckRound = SumcheckRound; /** * @brief Compute univariate restriction place in transcript, generate challenge, fold,... repeat until final round, @@ -149,7 +149,7 @@ template class... Relations> class Sumcheck { const size_t round_size = 1 << (multivariate_d - round_idx); // Write the round univariate T_l(X) to the transcript // Multiply by [(1-X) + ζ^{ 2^{l} } X] to obtain the full round univariate S_l(X). - RoundUnivariate round_univariate = SumcheckRound::compute_univariate( + RoundUnivariate round_univariate = SumcheckRound::compute_univariate( round_polynomials, round_size, relation_parameters, pow_univariate, alpha); transcript.add_element("univariate_" + std::to_string(round_idx), round_univariate.to_buffer()); diff --git a/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp b/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp index a42fec5185..4f7396ddc5 100644 --- a/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp +++ b/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp @@ -83,11 +83,11 @@ static Univariate compute_round_univariate( { size_t round_size = 1; // Improvement(Cody): This is ugly? Maye supply some/all of this data through "flavor" class? - using SumcheckRound = SumcheckRound; + using Round = SumcheckRound; auto w_l = input_polynomials[0]; auto w_r = input_polynomials[1]; auto w_o = input_polynomials[2]; @@ -127,7 +127,7 @@ static Univariate compute_round_univariate( lagrange_last); PowUnivariate pow_zeta(1); Univariate round_univariate = - SumcheckRound::compute_univariate(full_polynomials, round_size, relation_parameters, pow_zeta, alpha); + Round::compute_univariate(full_polynomials, round_size, relation_parameters, pow_zeta, alpha); return round_univariate; }