-
Notifications
You must be signed in to change notification settings - Fork 327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(bb): consider polynomial end_index when constructing partially evaluated multivariates #12530
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" | ||
#include "barretenberg/sumcheck/sumcheck.hpp" | ||
|
||
#include <cstddef> | ||
#include <gtest/gtest.h> | ||
|
||
using namespace bb; | ||
|
@@ -43,6 +44,7 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsSpecial) | |
{ | ||
using Flavor = TypeParam; | ||
using FF = typename Flavor::FF; | ||
using Polynomial = typename Flavor::Polynomial; | ||
using Transcript = typename Flavor::Transcript; | ||
|
||
// values here are chosen to check another test | ||
|
@@ -54,9 +56,10 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsSpecial) | |
FF v01 = 0; | ||
FF v11 = 0; | ||
|
||
std::array<FF, 4> f0 = { v00, v10, v01, v11 }; | ||
Polynomial f0(4); | ||
f0.template copy_vector<FF>({ v00, v10, v01, v11 }); | ||
|
||
auto full_polynomials = std::array<std::span<FF>, 1>({ f0 }); | ||
auto full_polynomials = std::array<Polynomial, 1>({ f0 }); | ||
auto transcript = Transcript::prover_init_empty(); | ||
auto sumcheck = SumcheckProver<Flavor>(multivariate_n, transcript); | ||
|
||
|
@@ -65,6 +68,7 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsSpecial) | |
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.partially_evaluated_polynomials = typename Flavor::PartiallyEvaluatedMultivariates(multivariate_n); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why reassign? should probably just change the constructor in sumcheck itself There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh I see, that constructor was just removed and moved to the prove() function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah this test itself is not very nice. It tests "partially_evaluate" on itself, but that's not how the usual flow goes. |
||
sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); | ||
|
||
auto& first_polynomial = sumcheck.partially_evaluated_polynomials.get_all()[0]; | ||
|
@@ -82,6 +86,7 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsGeneric) | |
{ | ||
using Flavor = TypeParam; | ||
using FF = typename Flavor::FF; | ||
using Polynomial = typename Flavor::Polynomial; | ||
using Transcript = typename Flavor::Transcript; | ||
|
||
const size_t multivariate_d(2); | ||
|
@@ -92,16 +97,18 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsGeneric) | |
FF v01 = FF::random_element(); | ||
FF v11 = FF::random_element(); | ||
|
||
std::array<FF, 4> f0 = { v00, v10, v01, v11 }; | ||
Polynomial f0(4); | ||
f0.template copy_vector<FF>({ v00, v10, v01, v11 }); | ||
|
||
auto full_polynomials = std::array<std::span<FF>, 1>({ f0 }); | ||
auto full_polynomials = std::array<Polynomial, 1>({ f0 }); | ||
auto transcript = Transcript::prover_init_empty(); | ||
auto sumcheck = SumcheckProver<Flavor>(multivariate_n, transcript); | ||
|
||
FF round_challenge_0 = FF::random_element(); | ||
FF expected_lo = v00 * (FF(1) - round_challenge_0) + v10 * round_challenge_0; | ||
FF expected_hi = v01 * (FF(1) - round_challenge_0) + v11 * round_challenge_0; | ||
|
||
sumcheck.partially_evaluated_polynomials = typename Flavor::PartiallyEvaluatedMultivariates(multivariate_n); | ||
sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); | ||
auto& first_polynomial = sumcheck.partially_evaluated_polynomials.get_all()[0]; | ||
|
||
|
@@ -140,6 +147,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsSpecial) | |
{ | ||
using Flavor = TypeParam; | ||
using FF = typename Flavor::FF; | ||
using Polynomial = typename Flavor::Polynomial; | ||
using Transcript = typename Flavor::Transcript; | ||
|
||
const size_t multivariate_d(3); | ||
|
@@ -154,9 +162,10 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsSpecial) | |
FF v011 = 7; | ||
FF v111 = 8; | ||
|
||
std::array<FF, 8> f0 = { v000, v100, v010, v110, v001, v101, v011, v111 }; | ||
Polynomial f0(8); | ||
f0.template copy_vector<FF>({ v000, v100, v010, v110, v001, v101, v011, v111 }); | ||
|
||
auto full_polynomials = std::array<std::span<FF>, 1>({ f0 }); | ||
auto full_polynomials = std::array<Polynomial, 1>({ f0 }); | ||
auto transcript = Transcript::prover_init_empty(); | ||
auto sumcheck = SumcheckProver<Flavor>(multivariate_n, transcript); | ||
|
||
|
@@ -166,6 +175,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsSpecial) | |
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.partially_evaluated_polynomials = typename Flavor::PartiallyEvaluatedMultivariates(multivariate_n); | ||
sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); | ||
|
||
auto& first_polynomial = sumcheck.partially_evaluated_polynomials.get_all()[0]; | ||
|
@@ -192,6 +202,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGeneric) | |
{ | ||
using Flavor = TypeParam; | ||
using FF = typename Flavor::FF; | ||
using Polynomial = typename Flavor::Polynomial; | ||
using Transcript = typename Flavor::Transcript; | ||
|
||
const size_t multivariate_d(3); | ||
|
@@ -206,9 +217,10 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGeneric) | |
FF v011 = FF::random_element(); | ||
FF v111 = FF::random_element(); | ||
|
||
std::array<FF, 8> f0 = { v000, v100, v010, v110, v001, v101, v011, v111 }; | ||
Polynomial f0(8); | ||
f0.template copy_vector<FF>({ v000, v100, v010, v110, v001, v101, v011, v111 }); | ||
|
||
auto full_polynomials = std::array<std::span<FF>, 1>({ f0 }); | ||
auto full_polynomials = std::array<Polynomial, 1>({ f0 }); | ||
auto transcript = Transcript::prover_init_empty(); | ||
auto sumcheck = SumcheckProver<Flavor>(multivariate_n, transcript); | ||
|
||
|
@@ -218,6 +230,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGeneric) | |
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.partially_evaluated_polynomials = typename Flavor::PartiallyEvaluatedMultivariates(multivariate_n); | ||
auto& first_polynomial = sumcheck.partially_evaluated_polynomials.get_all()[0]; | ||
sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); | ||
|
||
|
@@ -244,6 +257,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGenericMultiplePolys) | |
{ | ||
using Flavor = TypeParam; | ||
using FF = typename Flavor::FF; | ||
using Polynomial = typename Flavor::Polynomial; | ||
using Transcript = typename Flavor::Transcript; | ||
|
||
const size_t multivariate_d(3); | ||
|
@@ -267,11 +281,12 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGenericMultiplePolys) | |
v011[i] = FF::random_element(); | ||
v111[i] = FF::random_element(); | ||
} | ||
std::array<FF, 8> f0 = { v000[0], v100[0], v010[0], v110[0], v001[0], v101[0], v011[0], v111[0] }; | ||
std::array<FF, 8> f1 = { v000[1], v100[1], v010[1], v110[1], v001[1], v101[1], v011[1], v111[1] }; | ||
std::array<FF, 8> f2 = { v000[2], v100[2], v010[2], v110[2], v001[2], v101[2], v011[2], v111[2] }; | ||
Polynomial f0(8), f1(8), f2(8); | ||
f0.template copy_vector<FF>({ v000[0], v100[0], v010[0], v110[0], v001[0], v101[0], v011[0], v111[0] }); | ||
f1.template copy_vector<FF>({ v000[1], v100[1], v010[1], v110[1], v001[1], v101[1], v011[1], v111[1] }); | ||
f2.template copy_vector<FF>({ v000[2], v100[2], v010[2], v110[2], v001[2], v101[2], v011[2], v111[2] }); | ||
|
||
auto full_polynomials = std::array<std::span<FF>, 3>{ f0, f1, f2 }; | ||
auto full_polynomials = std::array<Polynomial, 3>{ f0, f1, f2 }; | ||
auto transcript = Transcript::prover_init_empty(); | ||
auto sumcheck = SumcheckProver<Flavor>(multivariate_n, transcript); | ||
|
||
|
@@ -287,6 +302,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGenericMultiplePolys) | |
expected_q4[i] = v011[i] * (FF(1) - round_challenge_0) + v111[i] * round_challenge_0; | ||
} | ||
|
||
sumcheck.partially_evaluated_polynomials = typename Flavor::PartiallyEvaluatedMultivariates(multivariate_n); | ||
sumcheck.partially_evaluate(full_polynomials, multivariate_n, round_challenge_0); | ||
auto polynomial_get_all = sumcheck.partially_evaluated_polynomials.get_all(); | ||
for (size_t i = 0; i < 3; i++) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -171,8 +171,7 @@ template <typename Flavor> class SumcheckProver { | |
: multivariate_n(multivariate_n) | ||
, multivariate_d(numeric::get_msb(multivariate_n)) | ||
, transcript(transcript) | ||
, round(multivariate_n) | ||
, partially_evaluated_polynomials(multivariate_n){}; | ||
, round(multivariate_n){}; | ||
|
||
/** | ||
* @brief Non-ZK version: Compute round univariate, place it in transcript, compute challenge, partially evaluate. | ||
|
@@ -189,17 +188,19 @@ template <typename Flavor> class SumcheckProver { | |
const RelationSeparator alpha, | ||
const std::vector<FF>& gate_challenges) | ||
{ | ||
|
||
bb::GateSeparatorPolynomial<FF> gate_separators(gate_challenges, multivariate_d); | ||
|
||
multivariate_challenge.reserve(multivariate_d); | ||
// In the first round, we compute the first univariate polynomial and populate the book-keeping table of | ||
// #partially_evaluated_polynomials, which has \f$ n/2 \f$ rows and \f$ N \f$ columns. When the Flavor has ZK, | ||
// compute_univariate also takes into account the zk_sumcheck_data. | ||
auto round_univariate = round.compute_univariate(full_polynomials, relation_parameters, gate_separators, alpha); | ||
// Initialize the partially evaluated polynomials which will be used in the following rounds. | ||
// This will use the information in the structured full polynomials to save memory if possible. | ||
partially_evaluated_polynomials = PartiallyEvaluatedMultivariates(full_polynomials, multivariate_n); | ||
|
||
vinfo("starting sumcheck rounds..."); | ||
{ | ||
|
||
PROFILE_THIS_NAME("rest of sumcheck round 1"); | ||
|
||
// Place the evaluations of the round univariate into transcript. | ||
|
@@ -210,11 +211,10 @@ template <typename Flavor> class SumcheckProver { | |
partially_evaluate(full_polynomials, multivariate_n, round_challenge); | ||
gate_separators.partially_evaluate(round_challenge); | ||
round.round_size = round.round_size >> 1; // TODO(#224)(Cody): Maybe partially_evaluate should do this and | ||
// release memory? // All but final round | ||
// We operate on partially_evaluated_polynomials in place. | ||
// release memory? // All but final round | ||
// We operate on partially_evaluated_polynomials in place. | ||
} | ||
for (size_t round_idx = 1; round_idx < multivariate_d; round_idx++) { | ||
|
||
PROFILE_THIS_NAME("sumcheck loop"); | ||
|
||
// Write the round univariate to the transcript | ||
|
@@ -224,8 +224,8 @@ template <typename Flavor> class SumcheckProver { | |
transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate); | ||
FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(round_idx)); | ||
multivariate_challenge.emplace_back(round_challenge); | ||
// Prepare sumcheck book-keeping table for the next round | ||
partially_evaluate(partially_evaluated_polynomials, round.round_size, round_challenge); | ||
// Prepare sumcheck book-keeping table for the next round. | ||
partially_evaluate(partially_evaluated_polynomials, multivariate_n >> round_idx, round_challenge); | ||
gate_separators.partially_evaluate(round_challenge); | ||
round.round_size = round.round_size >> 1; | ||
} | ||
|
@@ -296,9 +296,12 @@ template <typename Flavor> class SumcheckProver { | |
alpha, | ||
zk_sumcheck_data, | ||
row_disabling_polynomial); | ||
// Initialize the partially evaluated polynomials which will be used in the following rounds. | ||
fcarreiro marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// This will use the information in the structured full polynomials to save memory if possible. | ||
partially_evaluated_polynomials = PartiallyEvaluatedMultivariates(full_polynomials, multivariate_n); | ||
|
||
vinfo("starting sumcheck rounds..."); | ||
{ | ||
|
||
PROFILE_THIS_NAME("rest of sumcheck round 1"); | ||
|
||
if constexpr (!IsGrumpkinFlavor<Flavor>) { | ||
|
@@ -350,8 +353,8 @@ template <typename Flavor> class SumcheckProver { | |
const FF round_challenge = | ||
transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(round_idx)); | ||
multivariate_challenge.emplace_back(round_challenge); | ||
// Prepare sumcheck book-keeping table for the next round | ||
partially_evaluate(partially_evaluated_polynomials, round.round_size, round_challenge); | ||
// Prepare sumcheck book-keeping table for the next round. | ||
partially_evaluate(partially_evaluated_polynomials, multivariate_n >> round_idx, round_challenge); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why this change? to make it more clear what this is? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, it is kind of a leftover of many changes that I had and rolled back. However now that you mention it, it is kind of nice to use |
||
// Prepare evaluation masking and libra structures for the next round (for ZK Flavors) | ||
zk_sumcheck_data.update_zk_sumcheck_data(round_challenge, round_idx); | ||
row_disabling_polynomial.update_evaluations(round_challenge, round_idx); | ||
|
@@ -450,8 +453,11 @@ template <typename Flavor> class SumcheckProver { | |
auto poly_view = polynomials.get_all(); | ||
// after the first round, operate in place on partially_evaluated_polynomials | ||
parallel_for(poly_view.size(), [&](size_t j) { | ||
for (size_t i = 0; i < round_size; i += 2) { | ||
pep_view[j].at(i >> 1) = poly_view[j][i] + round_challenge * (poly_view[j][i + 1] - poly_view[j][i]); | ||
const auto& poly = poly_view[j]; | ||
// If the polynomial is shorter than the round size, we do a little optimization. | ||
size_t limit = std::min(poly.end_index(), round_size); | ||
for (size_t i = 0; i < limit; i += 2) { | ||
pep_view[j].at(i >> 1) = poly[i] + round_challenge * (poly[i + 1] - poly[i]); | ||
} | ||
}); | ||
}; | ||
|
@@ -465,24 +471,26 @@ template <typename Flavor> class SumcheckProver { | |
auto pep_view = partially_evaluated_polynomials.get_all(); | ||
// after the first round, operate in place on partially_evaluated_polynomials | ||
parallel_for(polynomials.size(), [&](size_t j) { | ||
for (size_t i = 0; i < round_size; i += 2) { | ||
pep_view[j].at(i >> 1) = | ||
polynomials[j][i] + round_challenge * (polynomials[j][i + 1] - polynomials[j][i]); | ||
const auto& poly = polynomials[j]; | ||
// If the polynomial is shorter than the round size, we do a little optimization. | ||
size_t limit = std::min(poly.end_index(), round_size); | ||
for (size_t i = 0; i < limit; i += 2) { | ||
pep_view[j].at(i >> 1) = poly[i] + round_challenge * (poly[i + 1] - poly[i]); | ||
} | ||
}); | ||
}; | ||
|
||
/** | ||
* @brief This method takes the book-keeping table containing partially evaluated prover polynomials and creates a | ||
* vector containing the evaluations of all prover polynomials at the point \f$ (u_0, \ldots, u_{d-1} )\f$. | ||
* For ZK Flavors: this method takes the book-keeping table containing partially evaluated prover polynomials | ||
and creates a vector containing the evaluations of all witness polynomials at the point \f$ (u_0, \ldots, u_{d-1} )\f$ | ||
masked by the terms \f$ \texttt{eval_masking_scalars}_j\cdot \sum u_i(1-u_i)\f$ and the evaluations of all non-witness | ||
polynomials that are sent in clear. | ||
* | ||
* @param partially_evaluated_polynomials | ||
* @param multivariate_evaluations | ||
*/ | ||
* @brief This method takes the book-keeping table containing partially evaluated prover polynomials and creates a | ||
* vector containing the evaluations of all prover polynomials at the point \f$ (u_0, \ldots, u_{d-1} )\f$. | ||
* For ZK Flavors: this method takes the book-keeping table containing partially evaluated prover polynomials | ||
* and creates a vector containing the evaluations of all witness polynomials at the point \f$ (u_0, \ldots, u_{d-1} | ||
* )\f$ masked by the terms \f$ \texttt{eval_masking_scalars}_j\cdot \sum u_i(1-u_i)\f$ and the evaluations of all | ||
* non-witness polynomials that are sent in clear. | ||
* | ||
* @param partially_evaluated_polynomials | ||
* @param multivariate_evaluations | ||
*/ | ||
ClaimedEvaluations extract_claimed_evaluations(PartiallyEvaluatedMultivariates& partially_evaluated_polynomials) | ||
{ | ||
ClaimedEvaluations multivariate_evaluations; | ||
|
@@ -513,7 +521,6 @@ polynomials that are sent in clear. | |
std::vector<bb::Polynomial<FF>>& round_univariates, | ||
std::vector<std::array<FF, 3>>& round_univariate_evaluations) | ||
{ | ||
|
||
const std::string idx = std::to_string(round_idx); | ||
|
||
// Transform to monomial form and commit to it | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just moved because this class refers to ProverPolynomials.