Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
sumcheck.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
13#include "sumcheck_round.hpp"
14
15namespace bb {
16
123template <typename Flavor> class SumcheckProver {
124 public:
125 using FF = typename Flavor::FF;
126 // PartiallyEvaluatedMultivariates OR ProverPolynomials
127 // both inherit from AllEntities
135
141
142 // this constant specifies the number of coefficients of libra polynomials, and evaluations of round univariate
144
146
147 // The size of the hypercube, i.e. \f$ 2^d\f$.
148 const size_t multivariate_n;
149 // The number of variables
150 const size_t multivariate_d;
151 // A reference to all prover multilinear polynomials.
153
154 std::shared_ptr<Transcript> transcript;
155 // Contains the core sumcheck methods such as `compute_univariate`.
157 // An array of size NUM_SUBRELATIONS-1 containing challenges or consecutive powers of a single challenge that
158 // separate linearly independent subrelation.
160 // pow_β(X₀, ..., X_{d−1}) = ∏ₖ₌₀^{d−1} (1 − Xₖ + Xₖ ⋅ βₖ)
161 std::vector<FF> gate_challenges;
162 // Contains various challenges, such as `beta` and `gamma` used in the Grand Product argument.
164
165 // Determines the number of rounds in the sumcheck (may include padding rounds, i.e. >= multivariate_d).
167
168 std::vector<FF> multivariate_challenge;
169
170 std::vector<typename Flavor::Commitment> round_univariate_commitments = {};
173 std::vector<FF> eval_domain = {};
175
177
188
189 // SumcheckProver constructor for the Flavors that generate NUM_SUBRELATIONS - 1 subrelation separator challenges.
191 ProverPolynomials& prover_polynomials,
192 std::shared_ptr<Transcript> transcript,
193 const SubrelationSeparators& relation_separator,
194 const std::vector<FF>& gate_challenges,
196 const size_t virtual_log_n)
199 , full_polynomials(prover_polynomials)
200 , transcript(std::move(transcript))
202 , alphas(relation_separator)
206
207 // SumcheckProver constructor for the Flavors that generate a single challeng `alpha` and use its powers as
208 // subrelation seperator challenges.
210 ProverPolynomials& prover_polynomials,
211 std::shared_ptr<Transcript> transcript,
212 const FF& alpha,
213 const std::vector<FF>& gate_challenges,
215 const size_t virtual_log_n)
218 , full_polynomials(prover_polynomials)
219 , transcript(std::move(transcript))
221 , alphas(initialize_relation_separator<FF, Flavor::NUM_SUBRELATIONS - 1>(alpha))
232 {
233 // Given gate challenges β = (β₀, ..., β_{d−1}) and d = `multivariate_d`, compute the evaluations of
234 // GateSeparator_β (X₀, ..., X_{d−1}) = ∏ₖ₌₀^{d−1} (1 − Xₖ + Xₖ · βₖ)
235 // on the boolean hypercube.
237
239 // In the first round, we compute the first univariate polynomial and populate the book-keeping table of
240 // #partially_evaluated_polynomials, which has \f$ n/2 \f$ rows and \f$ N \f$ columns.
241 auto round_univariate =
242 round.compute_univariate(full_polynomials, relation_parameters, gate_separators, alphas);
243 // Initialize the partially evaluated polynomials which will be used in the following rounds.
244 // This will use the information in the structured full polynomials to save memory if possible.
246
247 vinfo("starting sumcheck rounds...");
248 {
249 PROFILE_THIS_NAME("rest of sumcheck round 1");
250
251 // Place the evaluations of the round univariate into transcript.
252 transcript->send_to_verifier("Sumcheck:univariate_0", round_univariate);
253 FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_0");
254 multivariate_challenge.emplace_back(round_challenge);
255 // Prepare sumcheck book-keeping table for the next round
256 partially_evaluate(full_polynomials, round_challenge);
257 gate_separators.partially_evaluate(round_challenge);
258 round.round_size = round.round_size >> 1; // TODO(#224)(Cody): Maybe partially_evaluate should do this and
259 // release memory? // All but final round
260 // We operate on partially_evaluated_polynomials in place.
261 }
262 for (size_t round_idx = 1; round_idx < multivariate_d; round_idx++) {
263 PROFILE_THIS_NAME("sumcheck loop");
264
265 // Write the round univariate to the transcript
266 round_univariate =
267 round.compute_univariate(partially_evaluated_polynomials, relation_parameters, gate_separators, alphas);
268 // Place evaluations of Sumcheck Round Univariate in the transcript
269 transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate);
270 FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(round_idx));
271 multivariate_challenge.emplace_back(round_challenge);
272 // Prepare sumcheck book-keeping table for the next round.
274 gate_separators.partially_evaluate(round_challenge);
275 round.round_size = round.round_size >> 1;
276 }
277 vinfo("completed ", multivariate_d, " rounds of sumcheck");
278
280 // If required, extend prover's multilinear polynomials in `multivariate_d` variables by zero to get multilinear
281 // polynomials in `virtual_log_n` variables.
282 for (size_t k = multivariate_d; k < virtual_log_n; ++k) {
283 // Compute the contribution from the extensions by zero. It is sufficient to evaluate the main constraint at
284 // `MAX_PARTIAL_RELATION_LENGTH` points.
285 const auto virtual_round_univariate = round.compute_virtual_contribution(
287
288 transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(k), virtual_round_univariate);
289
290 const FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(k));
291 multivariate_challenge.emplace_back(round_challenge);
292
293 // Update the book-keeping table of partial evaluations of the prover polynomials extended by zero.
294 for (auto& poly : partially_evaluated_polynomials.get_all()) {
295 // Avoid bad access if polynomials are set to be of size 0, which can happen in AVM.
296 if (poly.size() > 0) {
297 poly.at(0) *= (FF(1) - round_challenge);
298 }
299 }
300 virtual_gate_separator.partially_evaluate(round_challenge);
301 }
302
304 transcript->send_to_verifier("Sumcheck:evaluations", multivariate_evaluations.get_all());
305 // For ZK Flavors: the evaluations of Libra univariates are included in the Sumcheck Output
306
308 .claimed_evaluations = multivariate_evaluations };
309 vinfo("finished sumcheck");
310 };
311
319 SumcheckOutput<Flavor> prove(ZKData& zk_sumcheck_data)
320 requires Flavor::HasZK
321 {
323
324 if constexpr (IsGrumpkinFlavor<Flavor>) {
326 // Compute the vector {0, 1, \ldots, BATCHED_RELATION_PARTIAL_LENGTH-1} needed to transform the round
327 // univariates from Lagrange to monomial basis
328 for (size_t idx = 0; idx < BATCHED_RELATION_PARTIAL_LENGTH; idx++) {
329 eval_domain.push_back(FF(idx));
330 }
331 }
332
333 vinfo("starting sumcheck rounds...");
334 // Given gate challenges β = (β₀, ..., β_{d−1}) and d = `multivariate_d`, compute the evaluations of
335 // GateSeparator_β (X₀, ..., X_{d−1}) = ∏ₖ₌₀^{d−1} (1 − Xₖ + Xₖ · βₖ)
336 // on the boolean hypercube.
337 GateSeparatorPolynomial<FF> gate_separators(gate_challenges, multivariate_d);
338
340 size_t round_idx = 0;
341 // In the first round, we compute the first univariate polynomial and populate the book-keeping table of
342 // #partially_evaluated_polynomials, which has \f$ n/2 \f$ rows and \f$ N \f$ columns.
343 auto hiding_univariate = round.compute_hiding_univariate(round_idx,
346 gate_separators,
347 alphas,
348 zk_sumcheck_data,
350 auto round_univariate =
351 round.compute_univariate(full_polynomials, relation_parameters, gate_separators, alphas);
352 round_univariate += hiding_univariate;
353
354 // Initialize the partially evaluated polynomials which will be used in the following rounds.
355 // This will use the information in the structured full polynomials to save memory if possible.
357
358 {
359 PROFILE_THIS_NAME("rest of sumcheck round 1");
360
361 if constexpr (!IsGrumpkinFlavor<Flavor>) {
362 // Place the evaluations of the round univariate into transcript.
363 transcript->send_to_verifier("Sumcheck:univariate_0", round_univariate);
364 } else {
365
366 // Compute monomial coefficients of the round univariate, commit to it, populate an auxiliary structure
367 // needed in the PCS round
368 commit_to_round_univariate(round_idx, round_univariate, ck);
369 }
370
371 const FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_0");
372
373 multivariate_challenge.emplace_back(round_challenge);
374 // Prepare sumcheck book-keeping table for the next round
375 partially_evaluate(full_polynomials, round_challenge);
376 // Prepare ZK Sumcheck data for the next round
377 zk_sumcheck_data.update_zk_sumcheck_data(round_challenge, round_idx);
378 row_disabling_polynomial.update_evaluations(round_challenge, round_idx);
379 gate_separators.partially_evaluate(round_challenge);
380 round.round_size = round.round_size >> 1; // TODO(#224)(Cody): Maybe partially_evaluate should do this and
381 // release memory? // All but final round
382 // We operate on partially_evaluated_polynomials in place.
383 }
384 for (size_t round_idx = 1; round_idx < multivariate_d; round_idx++) {
385 PROFILE_THIS_NAME("sumcheck loop");
386
387 // Computes the round univariate in two parts: first the contribution necessary to hide the polynomial and
388 // account for having randomness at the end of the trace and then the contribution from the full
389 // relation. Note: we compute the hiding univariate first as the `compute_univariate` method prepares
390 // relevant data structures for the next round
391 hiding_univariate = round.compute_hiding_univariate(round_idx,
394 gate_separators,
395 alphas,
396 zk_sumcheck_data,
398 round_univariate =
399 round.compute_univariate(partially_evaluated_polynomials, relation_parameters, gate_separators, alphas);
400 round_univariate += hiding_univariate;
401
402 if constexpr (!IsGrumpkinFlavor<Flavor>) {
403 // Place evaluations of Sumcheck Round Univariate in the transcript
404 transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate);
405 } else {
406
407 // Compute monomial coefficients of the round univariate, commit to it, populate an auxiliary structure
408 // needed in the PCS round
409 commit_to_round_univariate(round_idx, round_univariate, ck);
410 }
411 const FF round_challenge =
412 transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(round_idx));
413 multivariate_challenge.emplace_back(round_challenge);
414 // Prepare sumcheck book-keeping table for the next round.
416 // Prepare evaluation masking and libra structures for the next round (for ZK Flavors)
417 zk_sumcheck_data.update_zk_sumcheck_data(round_challenge, round_idx);
418 row_disabling_polynomial.update_evaluations(round_challenge, round_idx);
419
420 gate_separators.partially_evaluate(round_challenge);
421 round.round_size = round.round_size >> 1;
422 }
423
424 if constexpr (IsGrumpkinFlavor<Flavor>) {
426 round_univariate.evaluate(multivariate_challenge[multivariate_d - 1]);
427 }
428 vinfo("completed ", multivariate_d, " rounds of sumcheck");
429
430 // Zero univariates are used to pad the proof to the fixed size virtual_log_n.
432 for (size_t idx = multivariate_d; idx < virtual_log_n; idx++) {
433 transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(idx), zero_univariate);
434
435 FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(idx));
436 multivariate_challenge.emplace_back(round_challenge);
437 }
438
439 // Claimed evaluations of Prover polynomials are extracted and added to the transcript. When Flavor has ZK, the
440 // evaluations of all witnesses are masked.
442 transcript->send_to_verifier("Sumcheck:evaluations", multivariate_evaluations.get_all());
443
444 // The evaluations of Libra uninvariates at \f$ g_0(u_0), \ldots, g_{d-1} (u_{d-1}) \f$ are added to the
445 // transcript.
446 FF libra_evaluation = zk_sumcheck_data.constant_term;
447 for (const auto& libra_eval : zk_sumcheck_data.libra_evaluations) {
448 libra_evaluation += libra_eval;
449 }
450 transcript->send_to_verifier("Libra:claimed_evaluation", libra_evaluation);
451
452 // The sum of the Libra constant term and the evaluations of Libra univariates at corresponding sumcheck
453 // challenges is included in the Sumcheck Output
454 if constexpr (!IsGrumpkinFlavor<Flavor>) {
455 return SumcheckOutput<Flavor>{ .challenge = multivariate_challenge,
456 .claimed_evaluations = multivariate_evaluations,
457 .claimed_libra_evaluation = libra_evaluation };
458 } else {
459 return SumcheckOutput<Flavor>{ .challenge = multivariate_challenge,
460 .claimed_evaluations = multivariate_evaluations,
461 .claimed_libra_evaluation = libra_evaluation,
462 .round_univariates = round_univariates,
463 .round_univariate_evaluations = round_evaluations };
464 }
465 vinfo("finished sumcheck");
466 };
467
503 void partially_evaluate(auto& polynomials, const FF& round_challenge)
504 {
505 auto pep_view = partially_evaluated_polynomials.get_all();
506 auto poly_view = polynomials.get_all();
507 // after the first round, operate in place on partially_evaluated_polynomials
508 parallel_for(poly_view.size(), [&](size_t j) {
509 const auto& poly = poly_view[j];
510 // The polynomial is shorter than the round size.
511 size_t limit = poly.end_index();
512 for (size_t i = 0; i < limit; i += 2) {
513 pep_view[j].at(i >> 1) = poly[i] + round_challenge * (poly[i + 1] - poly[i]);
514 }
515
516 // We resize pep_view[j] to have the exact size required for the next round which is
517 // CEIL(limit/2). This has the effect to reduce the limit in next round and also to
518 // virtually zeroize any leftover values beyond the limit (in-place computation).
519 // This is important to zeroize leftover values to not mess up with compute_univariate().
520 // Note that the virtual size of pep_view[j] remains unchanged.
521 pep_view[j].shrink_end_index(limit / 2 + limit % 2);
522 });
523 };
528 template <typename PolynomialT, std::size_t N>
529 void partially_evaluate(std::array<PolynomialT, N>& polynomials, const FF& round_challenge)
530 {
531 auto pep_view = partially_evaluated_polynomials.get_all();
532 // after the first round, operate in place on partially_evaluated_polynomials
533 parallel_for(polynomials.size(), [&](size_t j) {
534 const auto& poly = polynomials[j];
535 // The polynomial is shorter than the round size.
536 size_t limit = poly.end_index();
537 for (size_t i = 0; i < limit; i += 2) {
538 pep_view[j].at(i >> 1) = poly[i] + round_challenge * (poly[i + 1] - poly[i]);
539 }
540
541 // We resize pep_view[j] to have the exact size required for the next round which is
542 // CEIL(limit/2). This has the effect to reduce the limit in next round and also to
543 // virtually zeroize any leftover values beyond the limit (in-place computation).
544 // This is important to zeroize leftover values to not mess up with compute_univariate().
545 // Note that the virtual size of pep_view[j] remains unchanged.
546 pep_view[j].shrink_end_index(limit / 2 + limit % 2);
547 });
548 };
549
562 {
563 ClaimedEvaluations multivariate_evaluations;
564 for (auto [eval, poly] :
565 zip_view(multivariate_evaluations.get_all(), partially_evaluated_polynomials.get_all())) {
566 eval = poly[0];
567 };
568 return multivariate_evaluations;
569 };
570
583 void commit_to_round_univariate(const size_t round_idx,
585 const CommitmentKey& ck)
586
587 {
588 const std::string idx = std::to_string(round_idx);
589
590 // Transform to monomial form and commit to it
591 Polynomial<FF> round_poly_monomial(
592 eval_domain, std::span<FF>(round_univariate.evaluations), BATCHED_RELATION_PARTIAL_LENGTH);
593 transcript->send_to_verifier("Sumcheck:univariate_comm_" + idx, ck.commit(round_poly_monomial));
594
595 // Store round univariate in monomial, as it is required by Shplemini
596 round_univariates.push_back(std::move(round_poly_monomial));
597
598 // Send the evaluations of the round univariate at 0 and 1
599 transcript->send_to_verifier("Sumcheck:univariate_" + idx + "_eval_0", round_univariate.value_at(0));
600 transcript->send_to_verifier("Sumcheck:univariate_" + idx + "_eval_1", round_univariate.value_at(1));
601
602 // Store the evaluations to be used by ShpleminiProver.
603 round_evaluations.push_back({ round_univariate.value_at(0), round_univariate.value_at(1), FF(0) });
604 if (round_idx > 0) {
605 round_evaluations[round_idx - 1][2] = round_univariate.value_at(0) + round_univariate.value_at(1);
606 };
607 }
608};
645template <typename Flavor> class SumcheckVerifier {
646
647 public:
649 using FF = typename Flavor::FF;
656 // For ZK Flavors: the verifier obtains a vector of evaluations of \f$ d \f$ univariate polynomials and uses them to
657 // compute full_honk_relation_purported_value
658 using ClaimedLibraEvaluations = typename std::vector<FF>;
662
667 static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH;
672 static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES;
673
674 std::shared_ptr<Transcript> transcript;
676
677 // Determines number of rounds in the sumcheck (may include padding rounds)
679
680 // An array of size NUM_SUBRELATIONS-1 containing challenges or consecutive powers of a single challenge that
681 // separate linearly independent subrelation.
683 FF libra_evaluation{ 0 };
686
688
689 std::vector<Commitment> round_univariate_commitments = {};
690 std::vector<std::array<FF, 3>> round_univariate_evaluations = {};
691
692 explicit SumcheckVerifier(std::shared_ptr<Transcript> transcript,
693 SubrelationSeparators& relation_separator,
694 size_t virtual_log_n,
695 FF target_sum = 0)
696 : transcript(std::move(transcript))
697 , round(target_sum)
698 , virtual_log_n(virtual_log_n)
699 , alphas(relation_separator) {};
700
701 explicit SumcheckVerifier(std::shared_ptr<Transcript> transcript,
702 const FF& alpha,
703 size_t virtual_log_n,
704 FF target_sum = 0)
705 : transcript(std::move(transcript))
706 , round(target_sum)
707 , virtual_log_n(virtual_log_n)
708 , alphas(initialize_relation_separator<FF, Flavor::NUM_SUBRELATIONS - 1>(alpha)) {};
719 std::vector<FF>& gate_challenges,
720 const std::vector<FF>& padding_indicator_array)
721 requires(!IsGrumpkinFlavor<Flavor>)
722 {
723 bool verified(true);
724
725 bb::GateSeparatorPolynomial<FF> gate_separators(gate_challenges);
726 // All but final round.
727 // target_total_sum is initialized to zero then mutated in place.
728
730
731 if constexpr (Flavor::HasZK) {
732 // If running zero-knowledge sumcheck the target total sum is corrected by the claimed sum of libra masking
733 // multivariate over the hypercube
734 libra_total_sum = transcript->template receive_from_prover<FF>("Libra:Sum");
735 libra_challenge = transcript->template get_challenge<FF>("Libra:Challenge");
736 round.target_total_sum = libra_total_sum * libra_challenge;
737 }
738
739 std::vector<FF> multivariate_challenge;
740 multivariate_challenge.reserve(virtual_log_n);
741 for (size_t round_idx = 0; round_idx < virtual_log_n; round_idx++) {
742 // Obtain the round univariate from the transcript
743 std::string round_univariate_label = "Sumcheck:univariate_" + std::to_string(round_idx);
744 round_univariate =
745 transcript->template receive_from_prover<bb::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>>(
746 round_univariate_label);
747 FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(round_idx));
748 multivariate_challenge.emplace_back(round_challenge);
749
750 const bool checked = round.check_sum(round_univariate, padding_indicator_array[round_idx]);
751 round.compute_next_target_sum(round_univariate, round_challenge, padding_indicator_array[round_idx]);
752 gate_separators.partially_evaluate(round_challenge, padding_indicator_array[round_idx]);
753
754 verified = verified && checked;
755 }
756 // Extract claimed evaluations of Libra univariates and compute their sum multiplied by the Libra challenge
757 // Final round
758 ClaimedEvaluations purported_evaluations;
759 auto transcript_evaluations =
760 transcript->template receive_from_prover<std::array<FF, NUM_POLYNOMIALS>>("Sumcheck:evaluations");
761 for (auto [eval, transcript_eval] : zip_view(purported_evaluations.get_all(), transcript_evaluations)) {
762 eval = transcript_eval;
763 }
764
765 // Evaluate the Honk relation at the point (u_0, ..., u_{d-1}) using claimed evaluations of prover polynomials.
766 // In ZK Flavors, the evaluation is corrected by full_libra_purported_value
767 FF full_honk_purported_value = round.compute_full_relation_purported_value(
768 purported_evaluations, relation_parameters, gate_separators, alphas);
769
770 // For ZK Flavors: compute the evaluation of the Row Disabling Polynomial at the sumcheck challenge and of the
771 // libra univariate used to hide the contribution from the actual Honk relation
772 if constexpr (Flavor::HasZK) {
773 if constexpr (UseRowDisablingPolynomial<Flavor>) {
774 // Compute the evaluations of the polynomial (1 - \sum L_i) where the sum is for i corresponding to the
775 // rows where all sumcheck relations are disabled
776 full_honk_purported_value *=
777 RowDisablingPolynomial<FF>::evaluate_at_challenge(multivariate_challenge, padding_indicator_array);
778 }
779
780 libra_evaluation = transcript->template receive_from_prover<FF>("Libra:claimed_evaluation");
781 full_honk_purported_value += libra_evaluation * libra_challenge;
782 }
783
785 bool final_check(false);
786 if constexpr (IsRecursiveFlavor<Flavor>) {
787 // These booleans are only needed for debugging
788 final_check = (full_honk_purported_value.get_value() == round.target_total_sum.get_value());
789 verified = verified && final_check;
790
791 full_honk_purported_value.assert_equal(round.target_total_sum);
792 } else {
793 final_check = (full_honk_purported_value == round.target_total_sum);
794 verified = verified && final_check;
795 }
796
797 return SumcheckOutput<Flavor>{ .challenge = multivariate_challenge,
798 .claimed_evaluations = purported_evaluations,
799 .verified = verified,
800 .claimed_libra_evaluation = libra_evaluation };
801 };
802
819 const std::vector<FF>& gate_challenges)
821 {
822 bool verified(false);
823
824 bb::GateSeparatorPolynomial<FF> gate_separators(gate_challenges);
825
826 // get the claimed sum of libra masking multivariate over the hypercube
827 libra_total_sum = transcript->template receive_from_prover<FF>("Libra:Sum");
828 // get the challenge for the ZK Sumcheck claim
829 const FF libra_challenge = transcript->template get_challenge<FF>("Libra:Challenge");
830
831 std::vector<FF> multivariate_challenge;
832 multivariate_challenge.reserve(virtual_log_n);
833 // if Flavor has ZK, the target total sum is corrected by Libra total sum multiplied by the Libra
834 // challenge
835 round.target_total_sum = libra_total_sum * libra_challenge;
836
837 for (size_t round_idx = 0; round_idx < virtual_log_n; round_idx++) {
838 // Obtain the round univariate from the transcript
839 const std::string round_univariate_comm_label = "Sumcheck:univariate_comm_" + std::to_string(round_idx);
840 const std::string univariate_eval_label_0 = "Sumcheck:univariate_" + std::to_string(round_idx) + "_eval_0";
841 const std::string univariate_eval_label_1 = "Sumcheck:univariate_" + std::to_string(round_idx) + "_eval_1";
842
843 // Receive the commitment to the round univariate
844 round_univariate_commitments.push_back(
845 transcript->template receive_from_prover<Commitment>(round_univariate_comm_label));
846 // Receive evals at 0 and 1
847 round_univariate_evaluations.push_back(
848 { transcript->template receive_from_prover<FF>(univariate_eval_label_0),
849 transcript->template receive_from_prover<FF>(univariate_eval_label_1) });
850
851 const FF round_challenge =
852 transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(round_idx));
853 multivariate_challenge.emplace_back(round_challenge);
854
855 gate_separators.partially_evaluate(round_challenge);
856 }
857
858 FF first_sumcheck_round_evaluations_sum =
859 round_univariate_evaluations[0][0] + round_univariate_evaluations[0][1];
860
861 // Populate claimed evaluations at the challenge
862 ClaimedEvaluations purported_evaluations;
863 auto transcript_evaluations =
864 transcript->template receive_from_prover<std::array<FF, NUM_POLYNOMIALS>>("Sumcheck:evaluations");
865 for (auto [eval, transcript_eval] : zip_view(purported_evaluations.get_all(), transcript_evaluations)) {
866 eval = transcript_eval;
867 }
868 // For ZK Flavors: the evaluation of the Row Disabling Polynomial at the sumcheck challenge
869 // Evaluate the Honk relation at the point (u_0, ..., u_{d-1}) using claimed evaluations of prover polynomials.
870 // In ZK Flavors, the evaluation is corrected by full_libra_purported_value
871 FF full_honk_purported_value = round.compute_full_relation_purported_value(
872 purported_evaluations, relation_parameters, gate_separators, alphas);
873
874 // Compute the evaluations of the polynomial (1 - \sum L_i) where the sum is for i corresponding to the rows
875 // where all sumcheck relations are disabled
876 full_honk_purported_value *=
877 RowDisablingPolynomial<FF>::evaluate_at_challenge(multivariate_challenge, virtual_log_n);
878
879 // Extract claimed evaluations of Libra univariates and compute their sum multiplied by the Libra challenge
880 const FF libra_evaluation = transcript->template receive_from_prover<FF>("Libra:claimed_evaluation");
881 // Verifier computes full ZK Honk value, taking into account the contribution from the disabled row and the
882 // Libra polynomials
883 full_honk_purported_value += libra_evaluation * libra_challenge;
884
885 // Populate claimed evaluations of Sumcheck Round Unviariates at the round challenges. These will be checked as
886 // a part of Shplemini.
887 for (size_t round_idx = 1; round_idx < virtual_log_n; round_idx++) {
888 round_univariate_evaluations[round_idx - 1][2] =
889 round_univariate_evaluations[round_idx][0] + round_univariate_evaluations[round_idx][1];
890 };
891
892 if constexpr (IsRecursiveFlavor<Flavor>) {
893
894 first_sumcheck_round_evaluations_sum.self_reduce();
895 round.target_total_sum.self_reduce();
896
897 // This bool is only needed for debugging
898 verified = (first_sumcheck_round_evaluations_sum.get_value() == round.target_total_sum.get_value());
899 // Ensure that the sum of the evaluations of the first Sumcheck Round Univariate is equal to the claimed
900 // target total sum
901 first_sumcheck_round_evaluations_sum.assert_equal(round.target_total_sum);
902
903 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1197)
904 full_honk_purported_value.self_reduce();
905
906 } else {
907 // Ensure that the sum of the evaluations of the first Sumcheck Round Univariate is equal to the claimed
908 // target total sum
909 verified = (first_sumcheck_round_evaluations_sum == round.target_total_sum);
910 }
911
912 round_univariate_evaluations[virtual_log_n - 1][2] = full_honk_purported_value;
913
915 // For ZK Flavors: the evaluations of Libra univariates are included in the Sumcheck Output
916 return SumcheckOutput<Flavor>{ .challenge = multivariate_challenge,
917 .claimed_evaluations = purported_evaluations,
918 .verified = verified,
919 .claimed_libra_evaluation = libra_evaluation,
920 .round_univariate_commitments = round_univariate_commitments,
921 .round_univariate_evaluations = round_univariate_evaluations };
922 };
923};
924
925template <typename FF, size_t N> std::array<FF, N> initialize_relation_separator(const FF& alpha)
926{
927 std::array<FF, N> alphas;
928 alphas[0] = alpha;
929 for (size_t i = 1; i < N; ++i) {
930 alphas[i] = alphas[i - 1] * alpha;
931 }
932 return alphas;
933}
934} // namespace bb
CommitmentKey object over a pairing group 𝔾₁.
static constexpr bool HasZK
typename Curve::ScalarField FF
static constexpr size_t NUM_ALL_ENTITIES
typename G1::affine_element Commitment
NativeTranscript Transcript
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH
std::array< FF, NUM_SUBRELATIONS - 1 > SubrelationSeparators
A field element for each entity of the flavor. These entities represent the prover polynomials evalua...
A container for storing the partially evaluated multivariates produced by sumcheck.
A container for the prover polynomials handles.
Curve::ScalarField FF
bb::CommitmentKey< Curve > CommitmentKey
std::array< FF, NUM_SUBRELATIONS - 1 > SubrelationSeparators
NativeTranscript Transcript
static constexpr bool HasZK
static constexpr size_t MAX_PARTIAL_RELATION_LENGTH
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
The implementation of the sumcheck Prover for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:123
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH
Definition sumcheck.hpp:143
std::vector< Polynomial< FF > > round_univariates
Definition sumcheck.hpp:172
typename Flavor::FF FF
Definition sumcheck.hpp:125
ProverPolynomials & full_polynomials
Definition sumcheck.hpp:152
const size_t multivariate_n
Definition sumcheck.hpp:148
bb::RelationParameters< FF > relation_parameters
Definition sumcheck.hpp:163
typename Flavor::Transcript Transcript
Definition sumcheck.hpp:132
std::vector< std::array< FF, 3 > > round_evaluations
Definition sumcheck.hpp:171
std::vector< typename Flavor::Commitment > round_univariate_commitments
Definition sumcheck.hpp:170
void partially_evaluate(std::array< PolynomialT, N > &polynomials, const FF &round_challenge)
Evaluate at the round challenge and prepare class for next round. Specialization for array,...
Definition sumcheck.hpp:529
typename Flavor::ProverPolynomials ProverPolynomials
Definition sumcheck.hpp:128
static constexpr size_t MAX_PARTIAL_RELATION_LENGTH
The total algebraic degree of the Sumcheck relation as a polynomial in Prover Polynomials .
Definition sumcheck.hpp:140
void commit_to_round_univariate(const size_t round_idx, bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &round_univariate, const CommitmentKey &ck)
Compute monomial coefficients of the round univariate, commit to it, populate an auxiliary structure ...
Definition sumcheck.hpp:583
const size_t multivariate_d
Definition sumcheck.hpp:150
ClaimedEvaluations extract_claimed_evaluations(PartiallyEvaluatedMultivariates &partially_evaluated_polynomials)
This method takes the book-keeping table containing partially evaluated prover polynomials and create...
Definition sumcheck.hpp:561
typename Flavor::AllValues ClaimedEvaluations
Definition sumcheck.hpp:130
typename bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > SumcheckRoundUnivariate
Definition sumcheck.hpp:145
std::vector< FF > eval_domain
Definition sumcheck.hpp:173
std::vector< FF > multivariate_challenge
Definition sumcheck.hpp:168
SumcheckOutput< Flavor > prove(ZKData &zk_sumcheck_data) void partially_evaluate(auto &polynomials, const FF &round_challenge)
ZK-version of prove that runs Sumcheck with disabled rows and masking of Round Univariates....
Definition sumcheck.hpp:503
typename Flavor::PartiallyEvaluatedMultivariates PartiallyEvaluatedMultivariates
Definition sumcheck.hpp:129
SumcheckProver(size_t multivariate_n, ProverPolynomials &prover_polynomials, std::shared_ptr< Transcript > transcript, const FF &alpha, const std::vector< FF > &gate_challenges, const RelationParameters< FF > &relation_parameters, const size_t virtual_log_n)
Definition sumcheck.hpp:209
RowDisablingPolynomial< FF > row_disabling_polynomial
Definition sumcheck.hpp:176
typename Flavor::CommitmentKey CommitmentKey
Definition sumcheck.hpp:134
SumcheckProver(size_t multivariate_n, ProverPolynomials &prover_polynomials, std::shared_ptr< Transcript > transcript, const SubrelationSeparators &relation_separator, const std::vector< FF > &gate_challenges, const RelationParameters< FF > &relation_parameters, const size_t virtual_log_n)
Definition sumcheck.hpp:190
std::vector< FF > gate_challenges
Definition sumcheck.hpp:161
SumcheckProverRound< Flavor > round
Definition sumcheck.hpp:156
typename Flavor::SubrelationSeparators SubrelationSeparators
Definition sumcheck.hpp:133
PartiallyEvaluatedMultivariates partially_evaluated_polynomials
Container for partially evaluated Prover Polynomials at a current challenge. Upon computing challenge...
Definition sumcheck.hpp:187
std::shared_ptr< Transcript > transcript
Definition sumcheck.hpp:154
SumcheckOutput< Flavor > prove()
Non-ZK version: Compute round univariate, place it in transcript, compute challenge,...
Definition sumcheck.hpp:231
ZKSumcheckData< Flavor > ZKData
Definition sumcheck.hpp:131
SubrelationSeparators alphas
Definition sumcheck.hpp:159
Imlementation of the Sumcheck prover round.
Implementation of the sumcheck Verifier for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:645
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, std::vector< FF > &gate_challenges, const std::vector< FF > &padding_indicator_array)
Extract round univariate, check sum, generate challenge, compute next target sum.....
Definition sumcheck.hpp:718
typename std::vector< FF > ClaimedLibraEvaluations
Definition sumcheck.hpp:658
SumcheckVerifier(std::shared_ptr< Transcript > transcript, SubrelationSeparators &relation_separator, size_t virtual_log_n, FF target_sum=0)
Definition sumcheck.hpp:692
typename Flavor::FF FF
Definition sumcheck.hpp:649
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, const std::vector< FF > &gate_challenges)
Sumcheck Verifier for ECCVM and ECCVMRecursive.
Definition sumcheck.hpp:818
typename Flavor::Commitment Commitment
Definition sumcheck.hpp:661
SumcheckVerifierRound< Flavor > round
Definition sumcheck.hpp:675
typename Flavor::SubrelationSeparators SubrelationSeparators
Definition sumcheck.hpp:660
SumcheckVerifier(std::shared_ptr< Transcript > transcript, const FF &alpha, size_t virtual_log_n, FF target_sum=0)
Definition sumcheck.hpp:701
std::shared_ptr< Transcript > transcript
Definition sumcheck.hpp:674
typename Flavor::AllValues ClaimedEvaluations
Container type for the evaluations of Prover Polynomials at the challenge point .
Definition sumcheck.hpp:655
SubrelationSeparators alphas
Definition sumcheck.hpp:682
typename Flavor::Transcript Transcript
Definition sumcheck.hpp:659
Implementation of the Sumcheck Verifier Round.
FF compute_full_relation_purported_value(const ClaimedEvaluations &purported_evaluations, const bb::RelationParameters< FF > &relation_parameters, const bb::GateSeparatorPolynomial< FF > &gate_separators, const SubrelationSeparators &alphas)
Given the evaluations of the ProverPolynomials at the challenge point stored in purported_evaluatio...
void compute_next_target_sum(bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &univariate, FF &round_challenge, const FF &indicator)
After checking that the univariate is good for this round, compute the next target sum given by the e...
bool check_sum(bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &univariate, const FF &indicator)
Check that the round target sum is correct.
A univariate polynomial represented by its values on {domain_start, domain_start + 1,...
Fr & value_at(size_t i)
static Univariate zero()
std::array< Fr, LENGTH > evaluations
void vinfo(Args... args)
Definition log.hpp:76
constexpr T get_msb(const T in)
Definition get_msb.hpp:47
Entry point for Barretenberg command-line interface.
typename Flavor::FF FF
CommitmentKey< Curve > ck
std::array< FF, N > initialize_relation_separator(const FF &alpha)
Definition sumcheck.hpp:925
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
Definition thread.cpp:72
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
#define PROFILE_THIS_NAME(name)
Definition op_count.hpp:16
Implementation of the methods for the -polynomials used in Protogalaxy and -polynomials used in Sumch...
void partially_evaluate(FF challenge)
Partially evaluate the -polynomial at the new challenge and update .
Container for parameters used by the grand product (permutation, lookup) Honk relations.
Polynomial for Sumcheck with disabled Rows.
Contains the evaluations of multilinear polynomials at the challenge point . These are computed by S...
std::vector< FF > challenge
This structure is created to contain various polynomials and constants required by ZK Sumcheck.