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: Complete, auditors: [Khashayar], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
17#include "sumcheck_round.hpp"
18
19namespace bb {
20
25template <typename Flavor, bool IsGrumpkin = IsGrumpkinFlavor<Flavor>> struct RoundUnivariateHandler {
26 using FF = typename Flavor::FF;
30
31 std::shared_ptr<Transcript> transcript;
32
33 RoundUnivariateHandler(std::shared_ptr<Transcript> transcript)
34 : transcript(std::move(transcript))
35 {}
36
37 void process_round_univariate(size_t round_idx,
39 {
40 transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate);
41 }
42
43 void finalize_last_round(size_t /*multivariate_d*/,
45 const FF& /*last_challenge*/)
46 {}
47
50};
51
55template <typename Flavor> struct RoundUnivariateHandler<Flavor, true> {
56 using FF = typename Flavor::FF;
60
61 std::shared_ptr<Transcript> transcript;
63 std::vector<FF> eval_domain;
66
67 RoundUnivariateHandler(std::shared_ptr<Transcript> transcript)
68 : transcript(std::move(transcript))
70 {
71 // Compute the vector {0, 1, \ldots, BATCHED_RELATION_PARTIAL_LENGTH-1} needed to transform
72 // the round univariates from Lagrange to monomial basis
73 for (size_t idx = 0; idx < BATCHED_RELATION_PARTIAL_LENGTH; idx++) {
74 eval_domain.push_back(FF(idx));
75 }
76 }
77
78 void process_round_univariate(size_t round_idx,
80 {
81 const std::string idx = std::to_string(round_idx);
82
83 // Transform to monomial form and commit to it
84 Polynomial<FF> round_poly_monomial(
85 eval_domain, std::span<FF>(round_univariate.evaluations), BATCHED_RELATION_PARTIAL_LENGTH);
86 transcript->send_to_verifier("Sumcheck:univariate_comm_" + idx, ck.commit(round_poly_monomial));
87
88 // Store round univariate in monomial, as it is required by Shplemini
89 round_univariates.push_back(std::move(round_poly_monomial));
90
91 // Send the evaluations of the round univariate at 0 and 1
92 transcript->send_to_verifier("Sumcheck:univariate_" + idx + "_eval_0", round_univariate.value_at(0));
93 transcript->send_to_verifier("Sumcheck:univariate_" + idx + "_eval_1", round_univariate.value_at(1));
94
95 // Store the evaluations to be used by ShpleminiProver.
96 round_evaluations.push_back({ round_univariate.value_at(0), round_univariate.value_at(1), FF(0) });
97 if (round_idx > 0) {
98 round_evaluations[round_idx - 1][2] = round_univariate.value_at(0) + round_univariate.value_at(1);
99 }
100 }
101
102 void finalize_last_round(size_t multivariate_d,
104 const FF& last_challenge)
105 {
106 round_evaluations[multivariate_d - 1][2] = round_univariate.evaluate(last_challenge);
107 }
108
109 std::vector<std::array<FF, 3>> get_evaluations() { return round_evaluations; }
110 std::vector<Polynomial<FF>> get_univariates() { return round_univariates; }
111};
112
117template <typename Flavor, bool HasZK = Flavor::HasZK> struct VerifierZKCorrectionHandler {
118 using FF = typename Flavor::FF;
121
122 std::shared_ptr<Transcript> transcript;
125
126 // Construct a handler which will handle all the evaluations/
127 VerifierZKCorrectionHandler(std::shared_ptr<Transcript> transcript)
128 : transcript(std::move(transcript))
129 {}
130
132
133 void apply_zk_corrections(FF& /*full_honk_purported_value*/,
134 const std::vector<FF>& /*multivariate_challenge*/,
135 const std::vector<FF>& /*padding_indicator_array*/)
136 {}
137
139};
140
144template <typename Flavor> struct VerifierZKCorrectionHandler<Flavor, true> {
145 using FF = typename Flavor::FF;
148
149 std::shared_ptr<Transcript> transcript;
150 FF libra_total_sum = FF{ 0 };
153
154 // If running zero-knowledge sumcheck the target total sum is corrected by the claimed sum of libra masking
155 // multivariate over the hypercube
156 VerifierZKCorrectionHandler(std::shared_ptr<Transcript> transcript)
157 : transcript(std::move(transcript))
158 , libra_total_sum(this->transcript->template receive_from_prover<FF>("Libra:Sum"))
159 , libra_challenge(this->transcript->template get_challenge<FF>("Libra:Challenge"))
160 {}
161
162 void initialize_target_sum(SumcheckRound& round) { round.target_total_sum = libra_total_sum * libra_challenge; }
163
164 void apply_zk_corrections(FF& full_honk_purported_value,
165 std::vector<FF>& multivariate_challenge,
166 const std::vector<FF>& padding_indicator_array)
167 {
168 if constexpr (UseRowDisablingPolynomial<Flavor>) {
169 // Compute the evaluations of the polynomial (1 - \sum L_i) where the sum is for i corresponding to the
170 // rows where all sumcheck relations are disabled
171 // i.e. compute the term $1 - \prod_{i=2}^{d-1} u_i$
172 full_honk_purported_value *=
173 RowDisablingPolynomial<FF>::evaluate_at_challenge(multivariate_challenge, padding_indicator_array);
174 }
175
176 // Get the claimed evaluation of the Libra multivariate evaluated at the sumcheck challenge
177 libra_evaluation = transcript->template receive_from_prover<FF>("Libra:claimed_evaluation");
178
179 // OriginTag false positive: libra_evaluation is PCS-bound (verified by Shplemini opening).
180 // Once commitments are fixed and sumcheck challenges derived, the correct evaluation is determined.
181 if constexpr (IsRecursiveFlavor<Flavor>) {
182 const auto challenge_tag = multivariate_challenge.back().get_origin_tag();
183 libra_evaluation.set_origin_tag(challenge_tag);
184 }
185
186 full_honk_purported_value += libra_evaluation * libra_challenge;
187 }
188
190};
191
298template <typename Flavor> class SumcheckProver {
299 public:
300 using FF = typename Flavor::FF;
301 // PartiallyEvaluatedMultivariates OR ProverPolynomials
302 // both inherit from AllEntities
310
317
318 // this constant specifies the number of coefficients of libra polynomials, and evaluations of round univariate
320
322
323 // The size of the hypercube, i.e. \f$ 2^d\f$.
324 const size_t multivariate_n;
325 // The number of variables
326 const size_t multivariate_d;
327 // A reference to all prover multilinear polynomials.
329
330 std::shared_ptr<Transcript> transcript;
331 // Contains the core sumcheck methods such as `compute_univariate`.
333 // An array of size NUM_SUBRELATIONS-1 containing challenges or consecutive powers of a single challenge that
334 // separate linearly independent subrelation.
336 // pow_β(X₀, ..., X_{d−1}) = ∏ₖ₌₀^{d−1} (1 − Xₖ + Xₖ ⋅ βₖ)
337 std::vector<FF> gate_challenges;
338 // Contains various challenges, such as `beta` and `gamma` used in the Grand Product argument.
340
341 // Determines the number of rounds in the sumcheck (may include padding rounds, i.e. >= multivariate_d).
343
344 std::vector<FF> multivariate_challenge;
345
346 // For computing eq polymomials in Multilinear Batching Flavor
347 std::vector<FF> accumulator_challenge = {};
348 std::vector<FF> instance_challenge = {};
350
352
353 // SumcheckProver constructor for MultilinearBatchingFlavor.
355 ProverPolynomials& prover_polynomials,
356 std::shared_ptr<Transcript> transcript,
357 const FF& relation_separator,
358 const size_t virtual_log_n,
359 const std::vector<FF>& accumulator_challenge,
360 const std::vector<FF>& instance_challenge)
363 , full_polynomials(prover_polynomials)
364 , transcript(std::move(transcript))
366 , alphas(initialize_relation_separator<FF, Flavor::NUM_SUBRELATIONS - 1>(relation_separator))
367 , gate_challenges({})
371
372 // SumcheckProver constructor for the Flavors that generate a single challenge `alpha` and use its powers as
373 // subrelation seperator challenges.
375 ProverPolynomials& prover_polynomials,
376 std::shared_ptr<Transcript> transcript,
377 const FF& alpha,
378 const std::vector<FF>& gate_challenges,
380 const size_t virtual_log_n)
383 , full_polynomials(prover_polynomials)
384 , transcript(std::move(transcript))
386 , alphas(initialize_relation_separator<FF, Flavor::NUM_SUBRELATIONS - 1>(alpha))
397 {
398 vinfo("starting sumcheck rounds...");
399
400 // Given gate challenges β = (β₀, ..., β_{d−1}) and d = `multivariate_d`, compute the evaluations of
401 // GateSeparator_β (X₀, ..., X_{d−1}) = ∏ₖ₌₀^{d−1} (1 − Xₖ + Xₖ · βₖ)
402 // on the boolean hypercube.
404
406 // In the first round, we compute the first univariate polynomial and populate the book-keeping table of
407 // #partially_evaluated_polynomials, which has \f$ n/2 \f$ rows and \f$ N \f$ columns.
408 auto round_univariate =
409 round.compute_univariate(full_polynomials, relation_parameters, gate_separators, alphas);
410
411 // Place the evaluations of the round univariate into transcript.
412 transcript->send_to_verifier("Sumcheck:univariate_0", round_univariate);
413 FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_0");
414 multivariate_challenge.emplace_back(round_challenge);
415
416 // Populate the book-keeping table
417 PartiallyEvaluatedMultivariates partially_evaluated_polynomials =
419
420 gate_separators.partially_evaluate(round_challenge);
421 round.round_size = round.round_size >> 1;
422 for (size_t round_idx = 1; round_idx < multivariate_d; round_idx++) {
423 BB_BENCH_NAME("sumcheck loop");
424
425 // Write the round univariate to the transcript
426 round_univariate =
427 round.compute_univariate(partially_evaluated_polynomials, relation_parameters, gate_separators, alphas);
428 // Place evaluations of Sumcheck Round Univariate in the transcript
429 transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(round_idx), round_univariate);
430 FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(round_idx));
431 multivariate_challenge.emplace_back(round_challenge);
432 // Prepare sumcheck book-keeping table for the next round.
433 partially_evaluate_in_place(partially_evaluated_polynomials, round_challenge);
434 gate_separators.partially_evaluate(round_challenge);
435 round.round_size = round.round_size >> 1;
436 }
437 vinfo("completed ", multivariate_d, " rounds of sumcheck");
438
440 // If required, extend prover's multilinear polynomials in `multivariate_d` variables by zero to get multilinear
441 // polynomials in `virtual_log_n` variables.
442 for (size_t k = multivariate_d; k < virtual_log_n; ++k) {
443 if constexpr (isMultilinearBatchingFlavor) {
444 // We need to specify the evaluation at index 1 for eq polynomials
445 std::vector<FF> index_1_challenge(virtual_log_n);
446 for (size_t i = 0; i < k; i++) {
447 index_1_challenge[i] = multivariate_challenge[i];
448 }
449 index_1_challenge[k] = FF(1);
450 if (partially_evaluated_polynomials.eq_accumulator.size() == 1) {
451
452 // We need to reallocate the polynomials
453 auto new_polynomial =
454 Polynomial<FF>(2, partially_evaluated_polynomials.eq_accumulator.virtual_size());
455 new_polynomial.at(0) = partially_evaluated_polynomials.eq_accumulator.at(0);
456 partially_evaluated_polynomials.eq_accumulator = new_polynomial;
457 }
458 if (partially_evaluated_polynomials.eq_instance.size() == 1) {
459 // We need to reallocate the polynomials
460 auto new_polynomial = Polynomial<FF>(2, partially_evaluated_polynomials.eq_instance.virtual_size());
461 new_polynomial.at(0) = partially_evaluated_polynomials.eq_instance.at(0);
462 partially_evaluated_polynomials.eq_instance = new_polynomial;
463 }
464 partially_evaluated_polynomials.eq_accumulator.at(1) =
466 partially_evaluated_polynomials.eq_instance.at(1) =
468 index_1_challenge[k] = FF(0);
469 }
470 // Compute the contribution from the extensions by zero. It is sufficient to evaluate the main constraint at
471 // `MAX_PARTIAL_RELATION_LENGTH` points.
472 const auto virtual_round_univariate = round.compute_virtual_contribution(
473 partially_evaluated_polynomials, relation_parameters, virtual_gate_separator, alphas);
474
475 transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(k), virtual_round_univariate);
476
477 const FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(k));
478 multivariate_challenge.emplace_back(round_challenge);
479
480 // Update the book-keeping table of partial evaluations of the prover polynomials extended by zero.
481 for (auto& poly : partially_evaluated_polynomials.get_all()) {
482 // Avoid bad access if polynomials are set to be of size 0, which can happen in AVM.
483 if (poly.size() > 0) {
484 if (poly.size() == 1) {
485 poly.at(0) *= (FF(1) - round_challenge);
486 } else if (poly.size() == 2) {
487 // Here we handle the eq polynomial case
488 poly.at(0) = poly.at(0) * (FF(1) - round_challenge) + poly.at(1) * round_challenge;
489 poly.at(1) = 0;
490 } else {
491 BB_ASSERT_EQ(true, false, "Polynomial size is not 1 or 2");
492 }
493 }
494 }
495 virtual_gate_separator.partially_evaluate(round_challenge);
496 }
497
498 ClaimedEvaluations multivariate_evaluations = extract_claimed_evaluations(partially_evaluated_polynomials);
499 transcript->send_to_verifier("Sumcheck:evaluations", multivariate_evaluations.get_all());
500 // For ZK Flavors: the evaluations of Libra univariates are included in the Sumcheck Output
501
503 .claimed_evaluations = multivariate_evaluations };
504 vinfo("finished sumcheck");
505 };
506
514 SumcheckOutput<Flavor> prove(ZKData& zk_sumcheck_data)
515 requires Flavor::HasZK
516 {
518 vinfo("starting sumcheck rounds...");
519 // Given gate challenges β = (β₀, ..., β_{d−1}) and d = `multivariate_d`, compute the evaluations of
520 // GateSeparator_β (X₀, ..., X_{d−1}) = ∏ₖ₌₀^{d−1} (1 − Xₖ + Xₖ · βₖ)
521 // on the boolean hypercube.
523
525 size_t round_idx = 0;
526 // In the first round, we compute the first univariate polynomial and populate the book-keeping table of
527 // #partially_evaluated_polynomials, which has \f$ n/2 \f$ rows and \f$ N \f$ columns.
528
529 // Compute the round univariate
530 auto round_univariate =
531 round.compute_univariate(full_polynomials, relation_parameters, gate_separators, alphas);
532
533 // Add the contribution from the Libra univariates
534 auto hiding_univariate = round.compute_libra_univariate(zk_sumcheck_data, round_idx);
535 round_univariate += hiding_univariate;
536
537 // Subtract the contribution from the disabled rows
538 if constexpr (UseRowDisablingPolynomial<Flavor>) {
539 round_univariate -= round.compute_disabled_contribution(
541 }
542
543 handler.process_round_univariate(round_idx, round_univariate);
544 const FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_0");
545 multivariate_challenge.emplace_back(round_challenge);
546
547 // Populate the book-keeping table
548 PartiallyEvaluatedMultivariates partially_evaluated_polynomials =
550
551 // Prepare ZK Sumcheck data for the next round
552 zk_sumcheck_data.update_zk_sumcheck_data(round_challenge, round_idx);
553 row_disabling_polynomial.update_evaluations(round_challenge, round_idx);
554 gate_separators.partially_evaluate(round_challenge);
555 round.round_size = round.round_size >> 1;
556 for (size_t round_idx = 1; round_idx < multivariate_d; round_idx++) {
557 BB_BENCH_NAME("sumcheck loop");
558
559 // Computes the round univariate in two parts: first the contribution necessary to hide the polynomial and
560 // account for having randomness at the end of the trace and then the contribution from the full
561 // relation. Note: we compute the hiding univariate first as the `compute_univariate` method prepares
562 // relevant data structures for the next round
563 round_univariate =
564 round.compute_univariate(partially_evaluated_polynomials, relation_parameters, gate_separators, alphas);
565 hiding_univariate = round.compute_libra_univariate(zk_sumcheck_data, round_idx);
566 // Add the contribution from the Libra univariates
567 round_univariate += hiding_univariate;
568 // Subtract the contribution from the disabled rows
569 if constexpr (UseRowDisablingPolynomial<Flavor>) {
570 round_univariate -= round.compute_disabled_contribution(partially_evaluated_polynomials,
572 gate_separators,
573 alphas,
574 round_idx,
576 }
577
578 handler.process_round_univariate(round_idx, round_univariate);
579
580 const FF round_challenge =
581 transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(round_idx));
582 multivariate_challenge.emplace_back(round_challenge);
583 // Prepare sumcheck book-keeping table for the next round.
584 partially_evaluate_in_place(partially_evaluated_polynomials, round_challenge);
585
586 if constexpr (IsTranslatorFlavor<Flavor>) {
587 if (round_idx == Flavor::LOG_MINI_CIRCUIT_SIZE - 1) {
588 // Send mini-circuit evaluations mid-sumcheck so that they get hashed into the transcript,
589 // ensuring the remaining LOG_N - LOG_MINI_CIRCUIT_SIZE round challenges depend on them.
590 transcript->send_to_verifier("Sumcheck:minicircuit_evaluations",
591 Flavor::get_minicircuit_evaluations(partially_evaluated_polynomials));
592 }
593 }
594
595 // Prepare evaluation masking and libra structures for the next round (for ZK Flavors)
596 zk_sumcheck_data.update_zk_sumcheck_data(round_challenge, round_idx);
597 row_disabling_polynomial.update_evaluations(round_challenge, round_idx);
598
599 gate_separators.partially_evaluate(round_challenge);
600 round.round_size = round.round_size >> 1;
601 }
602
603 handler.finalize_last_round(multivariate_d, round_univariate, multivariate_challenge[multivariate_d - 1]);
604
605 vinfo("completed ", multivariate_d, " rounds of sumcheck");
606
607 // Zero univariates are used to pad the proof to the fixed size virtual_log_n.
609 for (size_t idx = multivariate_d; idx < virtual_log_n; idx++) {
610 transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(idx), zero_univariate);
611
612 FF round_challenge = transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(idx));
613 multivariate_challenge.emplace_back(round_challenge);
614 }
615
616 // Claimed evaluations of Prover polynomials are extracted and added to the transcript. When Flavor has ZK, the
617 // evaluations of all witnesses are masked.
618 ClaimedEvaluations multivariate_evaluations = extract_claimed_evaluations(partially_evaluated_polynomials);
619 // For Translator: send only the full-circuit evaluations (computable precomputed and minicircuit wires
620 // excluded)
621 if constexpr (IsTranslatorFlavor<Flavor>) {
622 transcript->send_to_verifier("Sumcheck:evaluations",
623 Flavor::get_full_circuit_evaluations(multivariate_evaluations));
624 } else {
625 transcript->send_to_verifier("Sumcheck:evaluations", multivariate_evaluations.get_all());
626 }
627
628 // The evaluations of Libra uninvariates at \f$ g_0(u_0), \ldots, g_{d-1} (u_{d-1}) \f$ are added to the
629 // transcript.
630 FF libra_evaluation = zk_sumcheck_data.constant_term;
631 for (const auto& libra_eval : zk_sumcheck_data.libra_evaluations) {
632 libra_evaluation += libra_eval;
633 }
634 transcript->send_to_verifier("Libra:claimed_evaluation", libra_evaluation);
635
636 // The sum of the Libra constant term and the evaluations of Libra univariates at corresponding sumcheck
637 // challenges is included in the Sumcheck Output
638 return SumcheckOutput<Flavor>{ .challenge = multivariate_challenge,
639 .claimed_evaluations = multivariate_evaluations,
640 .claimed_libra_evaluation = libra_evaluation,
641 .round_univariates = handler.get_univariates(),
642 .round_univariate_evaluations = handler.get_evaluations() };
643 vinfo("finished sumcheck");
644 };
645
651 static void partially_evaluate(auto& source_polynomials,
652 PartiallyEvaluatedMultivariates& dest_polynomials,
653 const FF& round_challenge)
654 {
655 auto source_view = source_polynomials.get_all();
656 auto dest_view = dest_polynomials.get_all();
657 parallel_for(source_view.size(), [&](size_t j) {
658 const auto& poly = source_view[j];
659 size_t limit = poly.end_index();
660 for (size_t i = 0; i < limit; i += 2) {
661 dest_view[j].at(i >> 1) = poly[i] + round_challenge * (poly[i + 1] - poly[i]);
662 }
663 dest_view[j].shrink_end_index((limit / 2) + (limit % 2));
664 });
665 };
666
674 const FF& round_challenge)
675 {
676 PartiallyEvaluatedMultivariates partially_evaluated_polynomials(full_polynomials, multivariate_n);
677 partially_evaluate(full_polynomials, partially_evaluated_polynomials, round_challenge);
678 return partially_evaluated_polynomials;
679 }
680
684 static void partially_evaluate_in_place(PartiallyEvaluatedMultivariates& polynomials, const FF& round_challenge)
685 {
686 partially_evaluate(polynomials, polynomials, round_challenge);
687 };
688
701 {
702 ClaimedEvaluations multivariate_evaluations;
703 for (auto [eval, poly] :
704 zip_view(multivariate_evaluations.get_all(), partially_evaluated_polynomials.get_all())) {
705 eval = poly[0];
706 };
707 return multivariate_evaluations;
708 };
709};
710
747template <typename Flavor> class SumcheckVerifier {
748
749 public:
751 using FF = typename Flavor::FF;
757 // For ZK Flavors: the verifier obtains a vector of evaluations of \f$ d \f$ univariate polynomials and uses them to
758 // compute full_honk_relation_purported_value
759 using ClaimedLibraEvaluations = typename std::vector<FF>;
763
768 static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = Flavor::BATCHED_RELATION_PARTIAL_LENGTH;
772 static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES;
773
774 std::shared_ptr<Transcript> transcript;
776
777 // Determines number of rounds in the sumcheck (may include padding rounds)
779
780 // An array of size NUM_SUBRELATIONS-1 containing challenges or consecutive powers of a single challenge that
781 // separate linearly independent subrelation.
783
784 explicit SumcheckVerifier(std::shared_ptr<Transcript> transcript,
785 const FF& alpha,
786 size_t virtual_log_n,
787 FF target_sum = 0)
788 : transcript(std::move(transcript))
789 , round(target_sum)
790 , virtual_log_n(virtual_log_n)
791 , alphas(initialize_relation_separator<FF, Flavor::NUM_SUBRELATIONS - 1>(alpha)) {};
804 const std::vector<FF>& gate_challenges,
805 const std::vector<FF>& padding_indicator_array)
806 {
807 bb::GateSeparatorPolynomial<FF> gate_separators(gate_challenges);
808 // Construct a ZKHandler to handle all the libra related information in the transcript
809 VerifierZKCorrectionHandler<Flavor> zk_correction_handler(transcript);
810
811 // Correct the target sum in the round in the ZK case
812 zk_correction_handler.initialize_target_sum(round);
813
814 std::vector<FF> multivariate_challenge;
815 multivariate_challenge.reserve(virtual_log_n);
816
817 // Process univariate consistancy check rounds
818 // For ECCVM we ensure the consistencies by populating an vector of claimed evaluations that will be checked in
819 // the PCS rounds
820 // For other flavors, we perform the sumcheck univariate consistency check
821
822 bool verified = true;
823 ClaimedEvaluations purported_evaluations;
824 for (size_t round_idx = 0; round_idx < virtual_log_n; round_idx++) {
825 round.process_round(
826 transcript, multivariate_challenge, gate_separators, padding_indicator_array[round_idx], round_idx);
827 verified = verified && !round.round_failed;
828
829 if constexpr (IsTranslatorFlavor<Flavor>) {
830 if (round_idx == Flavor::LOG_MINI_CIRCUIT_SIZE - 1) {
831 // Receive mini-circuit evaluations mid-sumcheck so that they get hashed into the transcript,
832 // ensuring the remaining LOG_N - LOG_MINI_CIRCUIT_SIZE round challenges depend on them.
833 Flavor::set_minicircuit_evaluations(
834 purported_evaluations,
835 transcript->template receive_from_prover<std::array<FF, Flavor::NUM_MINICIRCUIT_EVALUATIONS>>(
836 "Sumcheck:minicircuit_evaluations"));
837 }
838 }
839 }
840
841 // Populate claimed evaluations at the challenge
842 if constexpr (IsTranslatorFlavor<Flavor>) {
843 // Translator path: receive full-circuit evaluations, set them, and complete
844 // (computable precomputed selectors + L_0 scaling of minicircuit wires already placed above)
845 auto get_full_circuit_evaluations =
846 transcript->template receive_from_prover<std::array<FF, Flavor::NUM_FULL_CIRCUIT_EVALUATIONS>>(
847 "Sumcheck:evaluations");
848 Flavor::complete_full_circuit_evaluations(
849 purported_evaluations, get_full_circuit_evaluations, std::span<const FF>(multivariate_challenge));
850 } else {
851 auto transcript_evaluations =
852 transcript->template receive_from_prover<std::array<FF, NUM_POLYNOMIALS>>("Sumcheck:evaluations");
853 for (auto [eval, transcript_eval] : zip_view(purported_evaluations.get_all(), transcript_evaluations)) {
854 eval = transcript_eval;
855 }
856 }
857
858 // OriginTag false positive: The evaluations are PCS-bound - the prover committed to the
859 // polynomials before challenges were known, and the PCS opening verifies consistency.
860 if constexpr (IsRecursiveFlavor<Flavor>) {
861 const auto challenge_tag = multivariate_challenge.back().get_origin_tag();
862 for (auto& eval : purported_evaluations.get_all()) {
863 eval.set_origin_tag(challenge_tag);
864 }
865 }
866
867 // Evaluate the Honk relation at the point (u_0, ..., u_{d-1}) using claimed evaluations of prover polynomials.
868 // In ZK Flavors, the evaluation is corrected by full_libra_purported_value
869 FF full_honk_purported_value = round.compute_full_relation_purported_value(
870 purported_evaluations, relation_parameters, gate_separators, alphas);
871
872 // For ZK Flavors: compute the evaluation of the Row Disabling Polynomial at the sumcheck challenge and of the
873 // libra univariate used to hide the contribution from the actual Honk relation
874 zk_correction_handler.apply_zk_corrections(
875 full_honk_purported_value, multivariate_challenge, padding_indicator_array);
876
878 verified = round.perform_final_verification(full_honk_purported_value) && verified;
879
880 // For ZK Flavors: the evaluations of Libra univariates are included in the Sumcheck Output
881 return SumcheckOutput<Flavor>{ .challenge = multivariate_challenge,
882 .claimed_evaluations = purported_evaluations,
883 .verified = verified,
884 .claimed_libra_evaluation = zk_correction_handler.get_libra_evaluation(),
885 .round_univariate_commitments = round.get_round_univariate_commitments(),
886 .round_univariate_evaluations = round.get_round_univariate_evaluations() };
887 };
888};
889
890template <typename FF, size_t N> std::array<FF, N> initialize_relation_separator(const FF& alpha)
891{
892 std::array<FF, N> alphas;
893 alphas[0] = alpha;
894 for (size_t i = 1; i < N; ++i) {
895 alphas[i] = alphas[i - 1] * alpha;
896 }
897 return alphas;
898}
899} // namespace bb
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
bb::field< bb::Bn254FrParams > FF
Definition field.cpp:24
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:225
A field element for each entity of the flavor. These entities represent the prover polynomials evalua...
A container for the prover polynomials.
static constexpr bool HasZK
typename Curve::ScalarField FF
static constexpr size_t NUM_SUBRELATIONS
static constexpr size_t NUM_ALL_ENTITIES
static constexpr size_t MAX_PARTIAL_RELATION_LENGTH
typename G1::affine_element Commitment
PartiallyEvaluatedMultivariatesBase< AllEntities< Polynomial >, ProverPolynomials, Polynomial > PartiallyEvaluatedMultivariates
A container for storing the partially evaluated multivariates produced by sumcheck.
bb::CommitmentKey< Curve > CommitmentKey
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH
BaseTranscript< Codec, HashFunction > Transcript
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:298
SumcheckOutput< Flavor > static prove(ZKData &zk_sumcheck_data) void partially_evaluate(auto &source_polynomials, PartiallyEvaluatedMultivariates &dest_polynomials, const FF &round_challenge)
ZK-version of prove that runs Sumcheck with disabled rows and masking of Round Univariates....
Definition sumcheck.hpp:651
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH
Definition sumcheck.hpp:319
typename Flavor::FF FF
Definition sumcheck.hpp:300
ProverPolynomials & full_polynomials
Definition sumcheck.hpp:328
const size_t multivariate_n
Definition sumcheck.hpp:324
bb::RelationParameters< FF > relation_parameters
Definition sumcheck.hpp:339
typename Flavor::Transcript Transcript
Definition sumcheck.hpp:307
std::vector< FF > accumulator_challenge
Definition sumcheck.hpp:347
std::vector< FF > instance_challenge
Definition sumcheck.hpp:348
PartiallyEvaluatedMultivariates partially_evaluate_first_round(ProverPolynomials &full_polynomials, const FF &round_challenge)
Initialize partially evaluated polynomials and perform first round of partial evaluation.
Definition sumcheck.hpp:673
static constexpr bool isMultilinearBatchingFlavor
Definition sumcheck.hpp:311
typename Flavor::ProverPolynomials ProverPolynomials
Definition sumcheck.hpp:303
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:316
std::array< FF, Flavor::NUM_SUBRELATIONS - 1 > SubrelationSeparators
Definition sumcheck.hpp:308
const size_t multivariate_d
Definition sumcheck.hpp:326
static void partially_evaluate_in_place(PartiallyEvaluatedMultivariates &polynomials, const FF &round_challenge)
Evaluate at the round challenge in-place.
Definition sumcheck.hpp:684
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:700
typename Flavor::AllValues ClaimedEvaluations
Definition sumcheck.hpp:305
typename bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > SumcheckRoundUnivariate
Definition sumcheck.hpp:321
std::vector< FF > multivariate_challenge
Definition sumcheck.hpp:344
typename Flavor::PartiallyEvaluatedMultivariates PartiallyEvaluatedMultivariates
Definition sumcheck.hpp:304
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:374
RowDisablingPolynomial< FF > row_disabling_polynomial
Definition sumcheck.hpp:351
typename Flavor::CommitmentKey CommitmentKey
Definition sumcheck.hpp:309
SumcheckProver(size_t multivariate_n, ProverPolynomials &prover_polynomials, std::shared_ptr< Transcript > transcript, const FF &relation_separator, const size_t virtual_log_n, const std::vector< FF > &accumulator_challenge, const std::vector< FF > &instance_challenge)
Definition sumcheck.hpp:354
std::vector< FF > gate_challenges
Definition sumcheck.hpp:337
SumcheckProverRound< Flavor > round
Definition sumcheck.hpp:332
std::shared_ptr< Transcript > transcript
Definition sumcheck.hpp:330
SumcheckOutput< Flavor > prove()
Non-ZK version: Compute round univariate, place it in transcript, compute challenge,...
Definition sumcheck.hpp:396
ZKSumcheckData< Flavor > ZKData
Definition sumcheck.hpp:306
SubrelationSeparators alphas
Definition sumcheck.hpp:335
Imlementation of the Sumcheck prover round.
Implementation of the sumcheck Verifier for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:747
typename std::vector< FF > ClaimedLibraEvaluations
Definition sumcheck.hpp:759
std::array< FF, Flavor::NUM_SUBRELATIONS - 1 > SubrelationSeparators
Definition sumcheck.hpp:761
typename Flavor::FF FF
Definition sumcheck.hpp:751
typename Flavor::Commitment Commitment
Definition sumcheck.hpp:762
SumcheckVerifierRound< Flavor > round
Definition sumcheck.hpp:775
SumcheckVerifier(std::shared_ptr< Transcript > transcript, const FF &alpha, size_t virtual_log_n, FF target_sum=0)
Definition sumcheck.hpp:784
std::shared_ptr< Transcript > transcript
Definition sumcheck.hpp:774
typename Flavor::AllValues ClaimedEvaluations
Container type for the evaluations of Prover Polynomials at the challenge point .
Definition sumcheck.hpp:756
SubrelationSeparators alphas
Definition sumcheck.hpp:782
typename Flavor::Transcript Transcript
Definition sumcheck.hpp:760
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, const std::vector< FF > &gate_challenges, const std::vector< FF > &padding_indicator_array)
The Sumcheck verification method. First it extracts round univariate, checks sum (the sumcheck univar...
Definition sumcheck.hpp:803
Implementation of the Sumcheck Verifier Round.
std::vector< Commitment > get_round_univariate_commitments()
Get round univariate commitments (only used for Grumpkin flavors).
void process_round(const std::shared_ptr< Transcript > &transcript, std::vector< FF > &multivariate_challenge, bb::GateSeparatorPolynomial< FF > &gate_separators, const FF &padding_indicator, size_t round_idx)
Process a single sumcheck round: receive univariate from transcript, verify sum, generate challenge.
bool perform_final_verification(const FF &full_honk_purported_value)
Perform final verification: check that the computed target sum matches the full relation evaluation....
std::vector< std::array< FF, 3 > > get_round_univariate_evaluations()
Get round univariate evaluations (only used for Grumpkin flavors).
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)
Compute the full relation purported value.
A univariate polynomial represented by its values on {0, 1,..., domain_end - 1}.
Fr & value_at(size_t i)
static Univariate zero()
std::array< Fr, LENGTH > evaluations
Fr evaluate(const Fr &u) const
Evaluate a univariate at a point u not known at compile time and assumed not to be in the domain (els...
#define vinfo(...)
Definition log.hpp:94
constexpr T get_msb(const T in)
Definition get_msb.hpp:49
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
CommitmentKey< Curve > ck
std::array< FF, N > initialize_relation_separator(const FF &alpha)
Definition sumcheck.hpp:890
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
Definition thread.cpp:111
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
Implementation of the methods for the -polynomials used in in Sumcheck.
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.
std::vector< std::array< FF, 3 > > round_evaluations
Definition sumcheck.hpp:64
void process_round_univariate(size_t round_idx, bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &round_univariate)
Definition sumcheck.hpp:78
typename Flavor::CommitmentKey CommitmentKey
Definition sumcheck.hpp:58
std::vector< Polynomial< FF > > round_univariates
Definition sumcheck.hpp:65
void finalize_last_round(size_t multivariate_d, const bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &round_univariate, const FF &last_challenge)
Definition sumcheck.hpp:102
std::vector< Polynomial< FF > > get_univariates()
Definition sumcheck.hpp:110
std::shared_ptr< Transcript > transcript
Definition sumcheck.hpp:61
typename Flavor::Transcript Transcript
Definition sumcheck.hpp:57
std::vector< std::array< FF, 3 > > get_evaluations()
Definition sumcheck.hpp:109
RoundUnivariateHandler(std::shared_ptr< Transcript > transcript)
Definition sumcheck.hpp:67
Handler for processing round univariates in sumcheck. Default implementation: send evaluations direct...
Definition sumcheck.hpp:25
std::vector< Polynomial< FF > > get_univariates()
Definition sumcheck.hpp:49
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH
Definition sumcheck.hpp:29
typename Flavor::CommitmentKey CommitmentKey
Definition sumcheck.hpp:28
void process_round_univariate(size_t round_idx, bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &round_univariate)
Definition sumcheck.hpp:37
RoundUnivariateHandler(std::shared_ptr< Transcript > transcript)
Definition sumcheck.hpp:33
std::shared_ptr< Transcript > transcript
Definition sumcheck.hpp:31
std::vector< std::array< FF, 3 > > get_evaluations()
Definition sumcheck.hpp:48
typename Flavor::FF FF
Definition sumcheck.hpp:26
void finalize_last_round(size_t, const bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &, const FF &)
Definition sumcheck.hpp:43
typename Flavor::Transcript Transcript
Definition sumcheck.hpp:27
Polynomial for Sumcheck with disabled Rows.
static FF evaluate_at_challenge(std::vector< FF > multivariate_challenge, const size_t log_circuit_size)
Compute the evaluation of at the sumcheck challenge.
Contains the evaluations of multilinear polynomials at the challenge point . These are computed by S...
std::vector< FF > challenge
static FF eval(std::span< const FF > r_in, std::span< const FF > u)
VerifierZKCorrectionHandler(std::shared_ptr< Transcript > transcript)
Definition sumcheck.hpp:156
void initialize_target_sum(SumcheckRound &round)
Definition sumcheck.hpp:162
std::shared_ptr< Transcript > transcript
Definition sumcheck.hpp:149
void apply_zk_corrections(FF &full_honk_purported_value, std::vector< FF > &multivariate_challenge, const std::vector< FF > &padding_indicator_array)
Definition sumcheck.hpp:164
Handler for ZK-related verification adjustments in sumcheck. Default implementation: no ZK adjustment...
Definition sumcheck.hpp:117
void apply_zk_corrections(FF &, const std::vector< FF > &, const std::vector< FF > &)
Definition sumcheck.hpp:133
typename Flavor::Transcript Transcript
Definition sumcheck.hpp:119
void initialize_target_sum(SumcheckRound &)
Definition sumcheck.hpp:131
std::shared_ptr< Transcript > transcript
Definition sumcheck.hpp:122
VerifierZKCorrectionHandler(std::shared_ptr< Transcript > transcript)
Definition sumcheck.hpp:127
This structure is created to contain various polynomials and constants required by ZK Sumcheck.