22template <
typename Flavor>
54 typename Flavor::template ProverUnivariates<2>,
107 template <
typename ProverPolynomialsOrPartiallyEvaluatedMultivariates>
110 size_t max_end_index = 0;
111 if constexpr (
requires { multivariates.get_witness(); }) {
112 for (
auto& witness_poly : multivariates.get_witness()) {
113 max_end_index =
std::max(max_end_index, witness_poly.end_index());
119 size_t effective = max_end_index + (max_end_index % 2);
157 template <
typename ProverPolynomialsOrPartiallyEvaluatedMultivariates>
159 const ProverPolynomialsOrPartiallyEvaluatedMultivariates& multivariates,
160 const size_t edge_idx)
162 for (
auto [extended_edge, multivariate] :
zip_view(extended_edges.get_all(), multivariates.get_all())) {
166 if (multivariate.end_index() < edge_idx) {
168 extended_edge = zero_univariate;
171 .
template extend_to<MAX_PARTIAL_RELATION_LENGTH>();
181 template <
typename ProverPolynomialsOrPartiallyEvaluatedMultivariates>
212 ,
total_chunks(((end - start) / rpc) + ((end - start) % rpc > 0 ? 1 : 0))
214 BB_ASSERT(start % 2 == 0,
"start_edge_idx must be even");
215 BB_ASSERT(end % 2 == 0,
"end_edge_idx must be even");
216 BB_ASSERT(rpc >= 2 && rpc % 2 == 0,
"rows_per_chunk must be at least 2 and even");
217 BB_ASSERT(start <= end,
"start_edge_idx must not exceed end_edge_idx");
240 template <
typename ProverPolynomialsOrPartiallyEvaluatedMultivariates>
252 constexpr size_t rows_per_chunk = 16;
261 ExtendedEdges lazy_extended_edges(polynomials);
262 auto& accum = thread_univariate_accumulators[slot_id];
263 while (auto range = chunks.pop()) {
264 const auto [start, end] = *range;
265 for (size_t edge_idx = start; edge_idx < end; edge_idx += 2) {
266 lazy_extended_edges.set_current_edge(edge_idx);
272 accumulate_relation_univariates(
273 accum, lazy_extended_edges, relation_parameters, gate_separators[edge_idx]);
279 for (
auto& accumulators : thread_univariate_accumulators) {
308 template <
typename ProverPolynomialsOrPartiallyEvaluatedMultivariates>
310 ProverPolynomialsOrPartiallyEvaluatedMultivariates& polynomials)
313 const size_t effective_round_size = compute_effective_round_size(polynomials);
316 const size_t start_edge_idx = excluded_head_size;
321 if constexpr (can_skip_rows) {
323 const size_t num_edge_pairs = (effective_round_size - start_edge_idx) / 2;
331 auto range = chunk.
range(num_edge_pairs);
338 size_t current_block_start = 0;
339 size_t current_block_size = 0;
341 for (
size_t pair_idx : range) {
342 size_t edge_idx = start_edge_idx + pair_idx * 2;
345 if (current_block_size == 0) {
346 current_block_start = edge_idx;
348 current_block_size += 2;
351 if (current_block_size > 0) {
353 .size = current_block_size });
354 current_block_size = 0;
359 if (current_block_size > 0) {
361 .size = current_block_size });
367 for (
const auto& thread_blocks : all_thread_blocks) {
368 for (
const auto block : thread_blocks) {
369 result.push_back(block);
374 .size = effective_round_size - start_edge_idx });
400 template <
typename ProverPolynomialsOrPartiallyEvaluatedMultivariates>
402 ProverPolynomialsOrPartiallyEvaluatedMultivariates& polynomials,
411 if constexpr (!can_skip_rows) {
415 const size_t effective_round_size = compute_effective_round_size(polynomials);
416 constexpr size_t rows_per_chunk = 64;
417 ChunkStealer chunks{ excluded_head_size, effective_round_size, rows_per_chunk };
426 ExtendedEdges extended_edges;
427 auto& accum = thread_univariate_accumulators[slot_id];
428 while (auto range = chunks.pop()) {
429 const auto [start, end] = *range;
430 for (size_t edge_idx = start; edge_idx < end; edge_idx += 2) {
431 extend_edges(extended_edges, polynomials, edge_idx);
438 FF scaling_factor{ 1 };
439 if constexpr (!isMultilinearBatchingFlavor<Flavor>) {
440 scaling_factor = gate_separators[edge_idx];
442 accumulate_relation_univariates(accum, extended_edges, relation_parameters, scaling_factor);
448 for (
auto& accumulators : thread_univariate_accumulators) {
449 Utils::add_nested_tuples(univariate_accumulators, accumulators);
453 return batch_over_relations<SumcheckRoundUnivariate>(univariate_accumulators, alphas, gate_separators);
467 ExtendedEdges extended_edges;
470 for (
const BlockOfContiguousRows& block : round_manifest) {
471 size_t block_iterations = block.size / 2;
474 auto iteration_range = chunk.
range(block_iterations);
476 for (
size_t i : iteration_range) {
477 size_t edge_idx = block.starting_edge_idx + (i * 2);
478 extend_edges(extended_edges, polynomials, edge_idx);
487 FF scaling_factor{ 1 };
488 if constexpr (!isMultilinearBatchingFlavor<Flavor>) {
489 scaling_factor = gate_separators[edge_idx];
491 accumulate_relation_univariates(thread_univariate_accumulators[chunk.
thread_index],
500 for (
auto& accumulators : thread_univariate_accumulators) {
501 Utils::add_nested_tuples(univariate_accumulators, accumulators);
505 return batch_over_relations<SumcheckRoundUnivariate>(univariate_accumulators, alphas, gate_separators);
517 template <
typename ProverPolynomialsOrPartiallyEvaluatedMultivariates>
519 ProverPolynomialsOrPartiallyEvaluatedMultivariates& polynomials,
530 for (
size_t edge_idx = 0; edge_idx < excluded_head_size; edge_idx += 2) {
531 extend_edges(extended_edges, polynomials, edge_idx);
532 accumulate_relation_univariates(
533 univariate_accumulator, extended_edges, relation_parameters, gate_separators[edge_idx]);
536 result = batch_over_relations<SumcheckRoundUnivariate>(univariate_accumulator, alphas, gate_separators);
540 {
FF::one() - row_disabling_polynomial.eval_at_0,
FF::one() - row_disabling_polynomial.eval_at_1 });
542 one_minus_L.template extend_to<SumcheckRoundUnivariate::LENGTH>();
543 result *= one_minus_L_extended;
548 template <
typename ProverPolynomialsOrPartiallyEvaluatedMultivariates>
550 ProverPolynomialsOrPartiallyEvaluatedMultivariates& polynomials,
562 const size_t virtual_contribution_edge_idx = 0;
566 auto extended_edges = [&]() {
569 lazy_extended_edges.set_current_edge(virtual_contribution_edge_idx);
570 return lazy_extended_edges;
573 extend_edges(extended_edges, polynomials, virtual_contribution_edge_idx);
574 return extended_edges;
579 const FF gate_separator_tail{ 1 };
580 accumulate_relation_univariates(
581 univariate_accumulator, extended_edges, relation_parameters, gate_separator_tail);
583 return batch_over_relations<SumcheckRoundUnivariate>(univariate_accumulator, alphas, gate_separator);
601 template <
typename ExtendedUnivariate,
typename ContainerOverSubrelations>
606 Utils::scale_univariates(univariate_accumulators, challenge);
608 auto result = ExtendedUnivariate(0);
609 extend_and_batch_univariates(univariate_accumulators, result, gate_separators);
612 Utils::zero_univariates(univariate_accumulators);
629 template <
typename ExtendedUnivariate,
typename TupleOfTuplesOfUnivariates>
631 ExtendedUnivariate& result,
636 ExtendedUnivariate extended_random_polynomial =
637 random_polynomial.template extend_to<ExtendedUnivariate::LENGTH>();
639 constexpr_for<0, std::tuple_size_v<TupleOfTuplesOfUnivariates>, 1>([&]<
size_t relation_idx>() {
642 [&]<
size_t subrelation_idx>() {
644 auto extended = element.template extend_to<ExtendedUnivariate::LENGTH>();
647 constexpr bool is_subrelation_linearly_independent =
648 bb::subrelation_is_linearly_independent<Relation, subrelation_idx>();
653 if constexpr (!is_subrelation_linearly_independent) {
684 for (
size_t idx = 0; idx < LIBRA_UNIVARIATES_LENGTH; ++idx) {
685 libra_round_univariate.
value_at(idx) =
688 if constexpr (BATCHED_RELATION_PARTIAL_LENGTH == LIBRA_UNIVARIATES_LENGTH) {
689 return libra_round_univariate;
691 return libra_round_univariate.template extend_to<SumcheckRoundUnivariate::LENGTH>();
697 const auto& extended_edges,
699 const FF& scaling_factor)
701 accumulate_relation_univariates(univariate_accumulators, extended_edges, relation_parameters, scaling_factor);
733 const auto& extended_edges,
735 const FF& scaling_factor)
737 constexpr_for<0, NUM_RELATIONS, 1>([&]<
size_t relation_idx>() {
748 if (!Relation::skip(extended_edges)) {
784 bool round_failed =
false;
789 FF target_total_sum = 0;
793 : target_total_sum(target_total_sum)
795 Utils::zero_elements(relation_evaluations);
806 const auto bound_tag = target_total_sum.get_origin_tag();
808 eval.set_origin_tag(bound_tag);
813 bool sumcheck_round_failed(
false);
815 sumcheck_round_failed = (target_total_sum.get_value() != total_sum.get_value());
816 target_total_sum.assert_equal(total_sum);
818 sumcheck_round_failed = (target_total_sum != total_sum);
820 round_failed = round_failed || sumcheck_round_failed;
828 target_total_sum = univariate.
evaluate(round_challenge);
839 Utils::template accumulate_relation_evaluations_without_skipping<>(purported_evaluations,
840 relation_evaluations,
843 return Utils::scale_and_batch_elements(relation_evaluations, alphas);
853 std::vector<FF>& multivariate_challenge,
858 std::string round_univariate_label =
"Sumcheck:univariate_" +
std::to_string(round_idx);
859 auto round_univariate =
860 transcript->template receive_from_prover<bb::Univariate<FF, BATCHED_RELATION_PARTIAL_LENGTH>>(
861 round_univariate_label);
862 FF round_challenge = transcript->template get_challenge<FF>(
"Sumcheck:u_" +
std::to_string(round_idx));
863 multivariate_challenge.emplace_back(round_challenge);
866 check_sum(round_univariate);
868 compute_next_target_sum(round_univariate, round_challenge);
878 bool verified =
false;
880 verified = (full_honk_purported_value.get_value() == target_total_sum.get_value());
881 full_honk_purported_value.assert_equal(target_total_sum);
883 verified = (full_honk_purported_value == target_total_sum);
916 bool round_failed =
false;
921 FF target_total_sum = 0;
929 : target_total_sum(target_total_sum)
931 Utils::zero_elements(relation_evaluations);
942 Utils::template accumulate_relation_evaluations_without_skipping<>(purported_evaluations,
943 relation_evaluations,
946 return Utils::scale_and_batch_elements(relation_evaluations, alphas);
954 std::vector<FF>& multivariate_challenge,
958 const std::string round_univariate_comm_label =
"Sumcheck:univariate_comm_" +
std::to_string(round_idx);
959 const std::string univariate_eval_label_0 =
"Sumcheck:univariate_" +
std::to_string(round_idx) +
"_eval_0";
960 const std::string univariate_eval_label_1 =
"Sumcheck:univariate_" +
std::to_string(round_idx) +
"_eval_1";
963 round_univariate_commitments.push_back(
964 transcript->template receive_from_prover<Commitment>(round_univariate_comm_label));
966 round_univariate_evaluations.push_back(
967 { transcript->template receive_from_prover<FF>(univariate_eval_label_0),
968 transcript->template receive_from_prover<FF>(univariate_eval_label_1),
971 const FF round_challenge = transcript->template get_challenge<FF>(
"Sumcheck:u_" +
std::to_string(round_idx));
972 multivariate_challenge.emplace_back(round_challenge);
987 FF first_sumcheck_round_evaluations_sum =
988 round_univariate_evaluations[0][0] + round_univariate_evaluations[0][1];
990 bool verified =
false;
993 first_sumcheck_round_evaluations_sum.self_reduce();
994 target_total_sum.self_reduce();
995 full_honk_purported_value.self_reduce();
997 verified = (first_sumcheck_round_evaluations_sum.get_value() == target_total_sum.get_value());
998 first_sumcheck_round_evaluations_sum.assert_equal(target_total_sum);
1000 verified = (first_sumcheck_round_evaluations_sum == target_total_sum);
1005 for (
size_t round_idx = 1; round_idx < round_univariate_evaluations.size(); round_idx++) {
1006 round_univariate_evaluations[round_idx - 1][2] =
1007 round_univariate_evaluations[round_idx][0] + round_univariate_evaluations[round_idx][1];
1011 round_univariate_evaluations[round_univariate_evaluations.size() - 1][2] = full_honk_purported_value;
#define BB_ASSERT(expression,...)
bb::field< bb::Bn254FrParams > FF
#define BB_BENCH_NAME(name)
A base class labelling all entities (for instance, all of the polynomials used by the prover during s...
A field element for each entity of the flavor. These entities represent the prover polynomials evalua...
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
static bool skip_entire_row(const ProverPolynomialsOrPartiallyEvaluatedMultivariates &polynomials, const EdgeType edge_idx)
When evaluating the sumcheck protocol - can we skip evaluation of all relations for a given row?...
static constexpr bool USE_SHORT_MONOMIALS
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH
static constexpr size_t NUM_RELATIONS
BaseTranscript< Codec, HashFunction > Transcript
Relations_< FF > Relations
static constexpr size_t TRACE_OFFSET
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
static void zero_univariates(auto &tuple)
Set all coefficients of Univariates to zero.
static constexpr void add_nested_tuples(Tuple &tuple_1, const Tuple &tuple_2)
Componentwise addition of nested tuples (tuples of tuples)
Imlementation of the Sumcheck prover round.
decltype(create_sumcheck_tuple_of_tuples_of_univariates< Relations >()) SumcheckTupleOfTuplesOfUnivariates
static constexpr size_t LIBRA_UNIVARIATES_LENGTH
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH
The total algebraic degree of the Sumcheck relation as a polynomial in Prover Polynomials incremen...
std::conditional_t< Flavor::USE_SHORT_MONOMIALS, typename Flavor::template ProverUnivariates< 2 >, typename Flavor::ExtendedEdges > ExtendedEdges
static constexpr size_t MAX_PARTIAL_RELATION_LENGTH
The total algebraic degree of the Sumcheck relation as a polynomial in Prover Polynomials .
static void extend_and_batch_univariates(const TupleOfTuplesOfUnivariates &tuple, ExtendedUnivariate &result, const bb::GateSeparatorPolynomial< FF > &gate_separators)
Extend Univariates then sum them multiplying by the current -contributions.
static ExtendedUnivariate batch_over_relations(ContainerOverSubrelations &univariate_accumulators, const SubrelationSeparators &challenge, const bb::GateSeparatorPolynomial< FF > &gate_separators)
Given a tuple of tuples of extended per-relation contributions, and a challenge ,...
SumcheckRoundUnivariate compute_virtual_contribution(ProverPolynomialsOrPartiallyEvaluatedMultivariates &polynomials, const bb::RelationParameters< FF > &relation_parameters, const GateSeparatorPolynomial< FF > &gate_separator, const SubrelationSeparators &alphas)
size_t compute_effective_round_size(const ProverPolynomialsOrPartiallyEvaluatedMultivariates &multivariates) const
Compute the effective round size by finding the maximum end_index() across witness polynomials.
SumcheckRoundUnivariate compute_univariate_with_row_skipping(ProverPolynomialsOrPartiallyEvaluatedMultivariates &polynomials, const bb::RelationParameters< FF > &relation_parameters, const bb::GateSeparatorPolynomial< FF > &gate_separators, const SubrelationSeparators alphas)
Return the evaluations of the univariate round polynomials at . Most likely, is around ....
SumcheckProverRound(size_t initial_round_size)
SumcheckRoundUnivariate compute_univariate_avm(ProverPolynomialsOrPartiallyEvaluatedMultivariates &polynomials, const bb::RelationParameters< FF > &relation_parameters, const bb::GateSeparatorPolynomial< FF > &gate_separators, const SubrelationSeparators &alphas)
A version of compute_univariate that is better optimized for the AVM.
SumcheckTupleOfTuplesOfUnivariates univariate_accumulators
SumcheckRoundUnivariate compute_univariate(ProverPolynomialsOrPartiallyEvaluatedMultivariates &polynomials, const bb::RelationParameters< FF > &relation_parameters, const bb::GateSeparatorPolynomial< FF > &gate_separators, const SubrelationSeparators &alphas)
Return the evaluations of the univariate round polynomials. Toggles between chunked computation (desi...
void extend_edges(ExtendedEdges &extended_edges, const ProverPolynomialsOrPartiallyEvaluatedMultivariates &multivariates, const size_t edge_idx)
To compute the round univariate in Round , the prover first computes the values of Honk polynomials ...
std::array< FF, Flavor::NUM_SUBRELATIONS - 1 > SubrelationSeparators
void accumulate_relation_univariates(SumcheckTupleOfTuplesOfUnivariates &univariate_accumulators, const auto &extended_edges, const bb::RelationParameters< FF > &relation_parameters, const FF &scaling_factor)
In Round , for a given point , calculate the contribution of each sub-relation to .
static SumcheckRoundUnivariate compute_libra_univariate(const ZKData &zk_sumcheck_data, size_t round_idx)
Compute Libra round univariate expressed given by the formula.
size_t excluded_head_size
static constexpr size_t NUM_RELATIONS
Number of batched sub-relations in specified by Flavor.
SumcheckRoundUnivariate compute_disabled_contribution(ProverPolynomialsOrPartiallyEvaluatedMultivariates &polynomials, const bb::RelationParameters< FF > &relation_parameters, const bb::GateSeparatorPolynomial< FF > &gate_separators, const SubrelationSeparators &alphas, const RowDisablingPolynomial< FF > row_disabling_polynomial)
Compute the disabled rows' contribution to the round univariate.
std::vector< BlockOfContiguousRows > compute_contiguous_round_size(ProverPolynomialsOrPartiallyEvaluatedMultivariates &polynomials)
Compute the number of unskippable rows we must iterate over.
typename Flavor::Relations Relations
size_t round_size
In Round , equals .
void accumulate_relation_univariates_public(SumcheckTupleOfTuplesOfUnivariates &univariate_accumulators, const auto &extended_edges, const bb::RelationParameters< FF > &relation_parameters, const FF &scaling_factor)
TupleOfArraysOfValues relation_evaluations
std::vector< std::array< FF, 3 > > round_univariate_evaluations
typename Flavor::Commitment Commitment
typename std::vector< FF > ClaimedLibraEvaluations
std::vector< Commitment > round_univariate_commitments
void process_round(const std::shared_ptr< Transcript > &transcript, std::vector< FF > &multivariate_challenge, bb::GateSeparatorPolynomial< FF > &gate_separators, size_t round_idx)
Process a single sumcheck round for Grumpkin: receive commitment and evaluations, defer per-round ver...
typename Flavor::Relations Relations
decltype(create_tuple_of_arrays_of_values< typename Flavor::Relations >()) TupleOfArraysOfValues
bool perform_final_verification(const FF &full_honk_purported_value)
Perform final verification for Grumpkin: check first round sum, populate Shplemini data,...
std::array< FF, Flavor::NUM_SUBRELATIONS - 1 > SubrelationSeparators
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.
std::vector< std::array< FF, 3 > > get_round_univariate_evaluations()
Get round univariate evaluations for Shplemini.
std::vector< Commitment > get_round_univariate_commitments()
Get round univariate commitments for Shplemini.
typename Flavor::Transcript Transcript
SumcheckVerifierRound(FF target_total_sum=0)
typename Flavor::AllValues ClaimedEvaluations
Implementation of the Sumcheck Verifier Round.
typename Flavor::Commitment Commitment
typename Flavor::Relations Relations
typename std::vector< FF > ClaimedLibraEvaluations
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.
void check_sum(bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &univariate)
Check that the round target sum is correct.
void process_round(const std::shared_ptr< Transcript > &transcript, std::vector< FF > &multivariate_challenge, bb::GateSeparatorPolynomial< FF > &gate_separators, size_t round_idx)
Process a single sumcheck round: receive univariate from transcript, verify sum, generate challenge.
decltype(create_tuple_of_arrays_of_values< typename Flavor::Relations >()) TupleOfArraysOfValues
std::array< FF, Flavor::NUM_SUBRELATIONS - 1 > SubrelationSeparators
typename Flavor::AllValues ClaimedEvaluations
TupleOfArraysOfValues relation_evaluations
std::vector< Commitment > get_round_univariate_commitments()
Get round univariate commitments (only used for Grumpkin flavors).
bool perform_final_verification(const FF &full_honk_purported_value)
Perform final verification: check that the computed target sum matches the full relation evaluation....
typename Flavor::Transcript Transcript
void compute_next_target_sum(bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &univariate, FF &round_challenge)
Compute the next target sum.
SumcheckVerifierRound(FF target_total_sum=0)
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...
Check if the flavor has a static skip method to determine if accumulation of all relations can be ski...
The templates defined herein facilitate sharing the relation arithmetic between the prover and the ve...
Base class templates shared across Honk flavors.
constexpr size_t FF_COPY_COST
Entry point for Barretenberg command-line interface.
constexpr void constexpr_for(F &&f)
Implements a loop using a compile-time iterator. Requires c++20. Implementation (and description) fro...
void parallel_for_heuristic(size_t num_points, const std::function< void(size_t, size_t, size_t)> &func, size_t heuristic_cost)
Split a loop into several loops running in parallel based on operations in 1 iteration.
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
Implementation of the methods for the -polynomials used in in Sumcheck.
FF current_element() const
Computes the component at index current_element_idx in betas.
void partially_evaluate(FF challenge)
Partially evaluate the -polynomial at the new challenge and update .
FF partial_evaluation_result
The value obtained by partially evaluating one variable in the power polynomial at each round....
Container for parameters used by the grand product (permutation, lookup) Honk relations.
Polynomial for Sumcheck with disabled Rows.
Helper struct that describes a block of non-zero unskippable rows.
Shared chunk scheduler for dynamic work-stealing in the sumcheck prover's main loop.
const size_t rows_per_chunk
const size_t start_edge_idx
const size_t total_chunks
const size_t end_edge_idx
std::atomic< size_t > next_chunk
std::optional< std::pair< size_t, size_t > > pop()
ChunkStealer(size_t start, size_t end, size_t rpc)
auto range(size_t size, size_t offset=0) const
This structure is created to contain various polynomials and constants required by ZK Sumcheck.
std::vector< Polynomial< FF > > libra_univariates
static constexpr field one()