Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
multilinear_batching_prover.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
12
13namespace bb {
14
15template <size_t NumClaims>
17{
18 BB_BENCH();
19 BB_ASSERT_EQ(claims.size(), NUM_CLAIMS, "MultilinearBatchingProver: claim count must equal the batching width");
20
21 for (const auto& claim : claims) {
22 circuit_size = std::max(circuit_size, claim.dyadic_size);
23 }
24 const size_t virtual_circuit_size = 1 << MultilinearBatchingFlavor_<NumClaims>::VIRTUAL_LOG_N;
25 const size_t log_circuit_size = bb::numeric::get_msb(circuit_size);
26
27 for (size_t idx = 0; idx < NUM_CLAIMS; ++idx) {
28 auto& claim = claims[idx];
29
30 polynomials.non_shifted(idx) = std::move(claim.non_shifted_polynomial);
31 preshifted_polynomials[idx] = std::move(claim.shifted_polynomial);
32 polynomials.shifted(idx) = preshifted_polynomials[idx].shifted();
33
34 polynomials.eq(idx) = ProverEqPolynomial<FF>::construct(claim.challenge, log_circuit_size);
35 polynomials.claim_challenges[idx] = std::move(claim.challenge);
36
37 non_shifted_evaluations[idx] = claim.non_shifted_evaluation;
38 shifted_evaluations[idx] = claim.shifted_evaluation;
39 non_shifted_commitments[idx] = claim.non_shifted_commitment;
40 shifted_commitments[idx] = claim.shifted_commitment;
41 }
42
44}
45
46template <typename Flavor>
48 std::vector<MultilinearBatchingProverClaim>&& claims, std::shared_ptr<Transcript> transcript)
49 : transcript(std::move(transcript))
50 , key(std::move(claims))
51{}
52
54{
55 BB_BENCH_NAME("MultilinearBatchingProver::execute_relation_check_rounds");
56 using Sumcheck = SumcheckProver<Flavor>;
57
58 const FF alpha = transcript->template get_challenge<FF>("Sumcheck:alpha");
59 RelationParameters<FF> relation_parameters;
60 relation_parameters.compute_multilinear_batching_challenges(claim_batching_challenge, Flavor::NUM_CLAIMS);
61 Sumcheck sumcheck(key.circuit_size,
62 key.polynomials,
63 transcript,
64 alpha,
65 /*gate_challenges=*/{}, // No need for gate challenges, all the relations are linearly dependent
66 relation_parameters,
67 Flavor::VIRTUAL_LOG_N);
68 sumcheck_output = sumcheck.prove();
69
70 // Draw the merge challenge after the sumcheck's claimed evaluations are bound to the transcript, so that
71 // the single opening of the combined accumulator commitment binds each P_i(r) individually.
72 claim_merge_challenge = transcript->template get_challenge<FF>("claim_merge_challenge");
73}
74
76{
77 BB_BENCH();
78
79 // Merge the output claims using the fresh challenge ρ. ρ is drawn after the claimed evaluations are bound, so the
80 // single decider opening binds each P_i(r) individually
81 std::vector<FF> scalars(Flavor::NUM_CLAIMS);
82 scalars[0] = FF(1);
83 for (size_t idx = 1; idx < Flavor::NUM_CLAIMS; ++idx) {
84 scalars[idx] = scalars[idx - 1] * claim_merge_challenge;
85 }
86
87 bb::Polynomial<FF> new_non_shifted_polynomial;
88 bb::Polynomial<FF> new_shifted_polynomial;
89 FF new_non_shifted_evaluation(0);
90 FF new_shifted_evaluation(0);
91
92 size_t largest_non_shifted_idx = 0;
93 size_t largest_shifted_idx = 0;
94 for (size_t idx = 0; idx < Flavor::NUM_CLAIMS; ++idx) {
95 if (key.polynomials.non_shifted(idx).end_index() >
96 key.polynomials.non_shifted(largest_non_shifted_idx).end_index()) {
97 largest_non_shifted_idx = idx;
98 }
99 if (key.preshifted_polynomials[idx].end_index() > key.preshifted_polynomials[largest_shifted_idx].end_index()) {
100 largest_shifted_idx = idx;
101 }
102
103 new_non_shifted_evaluation += scalars[idx] * sumcheck_output.claimed_evaluations.non_shifted(idx);
104 new_shifted_evaluation += scalars[idx] * sumcheck_output.claimed_evaluations.shifted(idx);
105 }
106
107 new_non_shifted_polynomial = std::move(key.polynomials.non_shifted(largest_non_shifted_idx));
108 new_non_shifted_polynomial *= scalars[largest_non_shifted_idx];
109 for (size_t idx = 0; idx < Flavor::NUM_CLAIMS; ++idx) {
110 if (idx != largest_non_shifted_idx) {
111 new_non_shifted_polynomial.add_scaled(key.polynomials.non_shifted(idx), scalars[idx]);
112 }
113 }
114
115 new_shifted_polynomial = std::move(key.preshifted_polynomials[largest_shifted_idx]);
116 new_shifted_polynomial *= scalars[largest_shifted_idx];
117 for (size_t idx = 0; idx < Flavor::NUM_CLAIMS; ++idx) {
118 if (idx != largest_shifted_idx) {
119 new_shifted_polynomial.add_scaled(key.preshifted_polynomials[idx], scalars[idx]);
120 }
121 }
122
123 auto new_non_shifted_commitment = Commitment::batch_mul(key.non_shifted_commitments, scalars);
124 auto new_shifted_commitment = Commitment::batch_mul(key.shifted_commitments, scalars);
125
126 return MultilinearBatchingProverClaim{ .challenge = std::move(sumcheck_output.challenge),
127 .non_shifted_evaluation = new_non_shifted_evaluation,
128 .shifted_evaluation = new_shifted_evaluation,
129 .non_shifted_polynomial = std::move(new_non_shifted_polynomial),
130 .shifted_polynomial = std::move(new_shifted_polynomial),
131 .non_shifted_commitment = new_non_shifted_commitment,
132 .shifted_commitment = new_shifted_commitment,
133 .dyadic_size = key.circuit_size };
134}
135
137{
138 return transcript->export_proof();
139}
140
142{
143 BB_BENCH_NAME("MultilinearBatchingProver::construct_proof");
144
145 // The claims being batched are not sent in the proof: the verifier holds them in memory (it produced them via
146 // instance_to_accumulator). The batching challenge is derived from the shared transcript, whose state already
147 // commits to those claims via the group's instance sumchecks, so it binds them without any explicit hashing.
148 //
149 // γ is fed to the relation as a public per-polynomials coefficient (the i-th polynomial is weighted by γ^i)
150 claim_batching_challenge = transcript->template get_challenge<FF>("claim_batching_challenge");
151
152 execute_relation_check_rounds();
153
154 vinfo("MultilinearBatchingProver:: Computed batching proof");
155 return export_proof();
156}
157
159 std::shared_ptr<Transcript> transcript)
160 : claims(std::move(claims))
161 , transcript(std::move(transcript))
162{}
163
171
173{
174 // Dispatch the runtime claim count to the matching compile-time width. The range is derived from
175 // CHONK_MAX_CLAIMS_PER_KERNEL so every supported width is instantiated automatically and bumping the constant
176 // cannot leave a width unhandled.
178 constexpr_for<2, CHONK_MAX_CLAIMS_PER_KERNEL + 1, 1>([&]<size_t Width>() {
179 if (claims.size() == Width) {
180 proof = prove_with_width<Width>();
181 }
182 });
183 if (!proof.has_value()) {
184 throw_or_abort("MultilinearBatchingProver: incorrect number of claims supplied.");
185 }
186 return std::move(*proof);
187}
188
190{
191 BB_ASSERT(new_claim.has_value(),
192 "MultilinearBatchingProver: construct_proof must be called before compute_new_claim");
193 return std::move(*new_claim);
194}
195
196} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#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:264
#define BB_BENCH()
Definition bb_bench.hpp:268
std::array< std::vector< FF >, NUM_CLAIMS > claim_challenges
std::array< Commitment, NUM_CLAIMS > shifted_commitments
std::array< Polynomial, NUM_CLAIMS > preshifted_polynomials
std::array< Commitment, NUM_CLAIMS > non_shifted_commitments
Native flavor for multilinear batching sumcheck with NumClaims polynomials.
MultilinearBatchingProver(std::vector< ProverClaim > &&claims, std::shared_ptr< Transcript > transcript)
std::shared_ptr< Transcript > transcript
Internal prover for multilinear batching sumcheck over a fixed number of claims.
BB_PROFILE MultilinearBatchingProverClaim compute_new_claim()
MultilinearBatchingProverInternal(std::vector< MultilinearBatchingProverClaim > &&claims, std::shared_ptr< Transcript > transcript)
void add_scaled(PolynomialSpan< const Fr > other, const Fr &scaling_factor)
adds the polynomial q(X) 'other', multiplied by a scaling factor.
static Polynomial< FF > construct(std::span< const FF > challenges, size_t log_num_monomials)
Construct eq(X, r) coefficient table over Boolean hypercube {0,1}^d.
The implementation of the sumcheck Prover for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:304
#define vinfo(...)
Definition log.hpp:94
constexpr T get_msb(const T in)
Definition get_msb.hpp:50
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
std::vector< fr > HonkProof
Definition proof.hpp:15
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Prover's claim for multilinear batching - contains polynomials and their evaluation claims.
Container for parameters used by the grand product (permutation, lookup) Honk relations.
void compute_multilinear_batching_challenges(const T &batching_challenge, const size_t num_claims)
void throw_or_abort(std::string const &err)