Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
batched_honk_translator_prover.cpp
Go to the documentation of this file.
2
10
11// Short-monomial translator relation definitions: the joint sumcheck round (TransProverRound) is templated on
12// TranslatorShortMonomialFlavor, so this TU instantiates the short relations' prover-side accumulate. The short
13// relations are otherwise header-only (no explicit instantiation into librelations), so include the _impl here.
19
20namespace bb {
21
23 std::shared_ptr<MegaZKVK> mega_zk_vk,
24 std::shared_ptr<Transcript> transcript)
25 : mega_zk_inst(std::move(mega_zk_instance))
26 , mega_zk_vk(std::move(mega_zk_vk))
27 , transcript(std::move(transcript))
28{}
29
37{
38 BB_BENCH_NAME("BatchedHonkTranslatorProver::execute_mega_zk_oink");
40 oink_prover.prove(/*emit_alpha=*/false);
41}
42
59
78{
79 BB_BENCH_NAME("BatchedHonkTranslatorProver::execute_joint_sumcheck_rounds");
80 // Draw joint alpha after all pre-sumcheck commitments from both circuits.
81 const FF alpha = transcript->template get_challenge<FF>("Sumcheck:alpha");
82
83 // Draw joint gate challenges (17 total).
84 std::vector<FF> gate_challenges =
85 transcript->template get_dyadic_powers_of_challenge<FF>("Sumcheck:gate_challenge", JOINT_LOG_N);
86
87 // Compute α^{K_H}: offset for translator subrelation separators.
88 FF alpha_power_KH = FF(1);
89 for (size_t i = 0; i < MegaZKFlavor::NUM_SUBRELATIONS; i++) {
90 alpha_power_KH *= alpha;
91 }
92
93 // Subrelation separator arrays (powers of alpha starting at alpha^1).
94 const MegaZKSubrelationSeparators mega_zk_alphas =
96 const TransSubrelationSeparators translator_alphas =
98
99 // Derive MegaZK circuit log_circuit_size from the proving instance.
100 const size_t mega_zk_log_n = mega_zk_inst->log_dyadic_size();
101 BB_ASSERT(mega_zk_log_n <= JOINT_LOG_N);
102
103 // Joint ZK data: single Libra masking for all 17 rounds.
104 constexpr size_t log_subgroup_size = static_cast<size_t>(numeric::get_msb(Curve::SUBGROUP_SIZE));
105 MegaZKCommitmentKey small_ck(1 << (log_subgroup_size + 1));
107
108 // Single gate separator for both circuits: beta_products has size 2^JOINT_LOG_N which covers
109 // both the MegaZK real rounds (2^mega_zk_log_n) and translator rounds (2^JOINT_LOG_N).
110 GateSeparatorPolynomial<FF> gate_sep(gate_challenges, JOINT_LOG_N);
111
112 // Round helper objects.
113 MegaZKProverRound mega_zk_round(static_cast<size_t>(1) << mega_zk_log_n);
114 TransProverRound translator_round(static_cast<size_t>(1) << JOINT_LOG_N);
115
116 // Row disabling polynomial for the MegaZK circuit.
117 // (TranslatorFlavor does not use UseRowDisablingPolynomial.)
119
120 auto& mega_zk_polys = mega_zk_inst->polynomials;
121 auto& mega_zk_params = mega_zk_inst->relation_parameters;
122 auto& translator_polys = translator_key->proving_key->polynomials;
123
124 // Allocate partially evaluated polynomial tables (populated by the first partially_evaluate call).
125 MegaZKPartialEvals mega_zk_partial(mega_zk_polys, static_cast<size_t>(1) << mega_zk_log_n);
126 TransPartialEvals translator_partial(translator_polys, static_cast<size_t>(1) << JOINT_LOG_N);
127
128 // Type aliases for static partial-evaluation helpers from SumcheckProver.
129 using MegaZKSumcheck = SumcheckProver<MegaZKFlavor>;
130 using TransSumcheck = SumcheckProver<TranslatorFlavor>;
131
133
135
136 // Use committed sumcheck infrastructure: commits to round univariates and stores them for Shplemini.
137 static constexpr bool UseCommittedSumcheck = true;
139
140 auto send_round = [&](size_t round_idx) -> FF {
142 handler.process_round_univariate(round_idx, U_joint);
143 FF u = transcript->template get_challenge<FF>("Sumcheck:u_" + std::to_string(round_idx));
144 joint_challenge.emplace_back(u);
145 return u;
146 };
147
148 // Per-round helper: update ZK data, gate separators, translator round size, and optionally send
149 // translator minicircuit evaluations.
150 auto update_round_state = [&](size_t round_idx, const FF& u) {
151 if (round_idx == TranslatorFlavor::LOG_MINI_CIRCUIT_SIZE - 1) {
152 transcript->send_to_verifier("Sumcheck:minicircuit_evaluations",
154 }
156 gate_sep.partially_evaluate(u);
157 translator_round.round_size >>= 1;
158 };
159
160 // Per-round helper: compute U_joint = U_MZK + α^{K_H}·U_translator from given polynomial
161 // sources, add Libra masking, send to verifier, and return the round challenge.
162 // hpolys/tpolys are the full tables on round 0, the partial-eval tables on subsequent rounds.
163 auto do_round = [&](auto& hpolys, auto& tpolys, size_t round_idx) -> FF {
165
166 {
167 BB_BENCH_NAME("joint_sumcheck/hiding_kernel");
169 {
170 BB_BENCH_NAME("joint_sumcheck/hiding_kernel/compute_univariate");
171 U_H = mega_zk_round.compute_univariate(hpolys, mega_zk_params, gate_sep, mega_zk_alphas);
172 }
173 {
174 BB_BENCH_NAME("joint_sumcheck/hiding_kernel/disabled_contribution");
175 U_H +=
176 mega_zk_round.compute_disabled_contribution(hpolys, mega_zk_params, gate_sep, mega_zk_alphas, rdp);
177 }
178 U_joint += U_H;
179 }
180
181 {
182 BB_BENCH_NAME("joint_sumcheck/translator");
184 {
185 BB_BENCH_NAME("joint_sumcheck/translator/compute_univariate");
186 U_T = translator_round.compute_univariate(
187 tpolys, translator_relation_parameters, gate_sep, translator_alphas);
188 }
189 for (auto& eval : U_T.evaluations) {
190 eval *= alpha_power_KH;
191 }
192 U_joint += U_T;
193 }
194
195 return send_round(round_idx);
196 };
197
198 // ==================== Round 0: bootstraps mega_zk_partial and translator_partial ====================
199 // PartiallyEvaluatedMultivariates only allocates output buffers; values are populated here.
200 {
201 const FF u = do_round(mega_zk_polys, translator_polys, 0);
202 {
203 BB_BENCH_NAME("joint_sumcheck/hiding_kernel");
204 {
205 BB_BENCH_NAME("joint_sumcheck/hiding_kernel/partially_evaluate");
206 MegaZKSumcheck::partially_evaluate(mega_zk_polys, mega_zk_partial, u);
207 }
208 }
209 {
210 BB_BENCH_NAME("joint_sumcheck/translator");
211 {
212 BB_BENCH_NAME("joint_sumcheck/translator/partially_evaluate");
213 TransSumcheck::partially_evaluate(translator_polys, translator_partial, u);
214 }
215 }
216 rdp.update_evaluations(u, 0);
217 mega_zk_round.round_size >>= 1;
218 mega_zk_round.excluded_head_size = 2; // After round 0, disabled zone collapses to 1 edge pair
219 update_round_state(0, u);
220 }
221
222 // ==================== Real rounds 1..mega_zk_log_n-1 ====================
223 for (size_t round_idx = 1; round_idx < mega_zk_log_n; round_idx++) {
224 const FF u = do_round(mega_zk_partial, translator_partial, round_idx);
225 {
226 BB_BENCH_NAME("joint_sumcheck/hiding_kernel");
227 {
228 BB_BENCH_NAME("joint_sumcheck/hiding_kernel/partially_evaluate_in_place");
229 MegaZKSumcheck::partially_evaluate_in_place(mega_zk_partial, u);
230 }
231 }
232 {
233 BB_BENCH_NAME("joint_sumcheck/translator");
234 {
235 BB_BENCH_NAME("joint_sumcheck/translator/partially_evaluate_in_place");
236 TransSumcheck::partially_evaluate_in_place(translator_partial, u);
237 }
238 }
239 rdp.update_evaluations(u, round_idx);
240 mega_zk_round.round_size >>= 1;
241 update_round_state(round_idx, u);
242 }
243
244 // ==================== Virtual rounds mega_zk_log_n..JOINT_LOG_N-1 ====================
245 // MegaZK contributes a virtual (zero-extended) univariate with RDP factor; translator contributes a real round.
246 for (size_t round_idx = mega_zk_log_n; round_idx < JOINT_LOG_N; round_idx++) {
248
249 {
250 BB_BENCH_NAME("joint_sumcheck/hiding_kernel");
251 {
252 BB_BENCH_NAME("joint_sumcheck/hiding_kernel/virtual_univariate");
253 U_joint += MegaZKSumcheck::compute_virtual_round_univariate(
254 mega_zk_round, mega_zk_partial, mega_zk_params, gate_sep, mega_zk_alphas, rdp);
255 }
256 }
257
258 {
259 BB_BENCH_NAME("joint_sumcheck/translator");
261 {
262 BB_BENCH_NAME("joint_sumcheck/translator/compute_univariate");
263 U_T = translator_round.compute_univariate(
264 translator_partial, translator_relation_parameters, gate_sep, translator_alphas);
265 }
266 for (auto& eval : U_T.evaluations) {
267 eval *= alpha_power_KH;
268 }
269 U_joint += U_T;
270 }
271
272 // send_round adds libra masking, sends univariate, and returns the challenge
273 const FF u = send_round(round_idx);
274
275 {
276 BB_BENCH_NAME("joint_sumcheck/hiding_kernel");
277 {
278 BB_BENCH_NAME("joint_sumcheck/hiding_kernel/fold_for_zero_extension");
279 MegaZKSumcheck::fold_for_zero_extension(mega_zk_partial, u);
280 }
281 }
282 {
283 BB_BENCH_NAME("joint_sumcheck/translator");
284 {
285 BB_BENCH_NAME("joint_sumcheck/translator/partially_evaluate_in_place");
286 TransSumcheck::partially_evaluate_in_place(translator_partial, u);
287 }
288 }
289 rdp.update_evaluations(u, round_idx);
290 update_round_state(round_idx, u);
291 }
292
293 handler.finalize_last_round(JOINT_LOG_N, U_joint, joint_challenge.back());
294 round_univariates_list = std::move(handler.round_univariates);
295 round_evaluations_list = std::move(handler.round_evaluations);
296
297 // Extract and send MegaZK evaluations after all rounds — full N-variable evaluations.
298 for (auto [eval, poly] : zip_view(mega_zk_claimed_evals.get_all(), mega_zk_partial.get_all())) {
299 eval = poly[0];
300 }
301 transcript->send_to_verifier("Sumcheck:evaluations", mega_zk_claimed_evals.get_all());
302
303 // Extract and send translator evaluations after all rounds.
304 for (auto [eval, poly] : zip_view(trans_claimed_evals.get_all(), translator_partial.get_all())) {
305 eval = poly[0];
306 }
307 transcript->send_to_verifier("Sumcheck:evaluations_translator",
309
310 // Compute and send the claimed Libra evaluation (covers all JOINT_LOG_N rounds).
312 for (const auto& libra_eval : zk_sumcheck_data.libra_evaluations) {
313 claimed_libra_evaluation += libra_eval;
314 }
315 transcript->send_to_verifier("Libra:claimed_evaluation", claimed_libra_evaluation);
316}
317
327{
328 BB_BENCH_NAME("BatchedHonkTranslatorProver::execute_joint_pcs");
330 using PolynomialBatcher = GeminiProver_<Curve>::PolynomialBatcher;
331 using SmallSubgroupIPA = SmallSubgroupIPAProver<MegaZKFlavor>;
332
333 // Use the translator's commitment key (sized to 2^17 = joint_circuit_size) for all PCS work.
334 // The translator key is initialised by TranslatorProver in execute_translator_oink().
335 auto& ck = translator_key->proving_key->commitment_key;
336
337 // Prove the small-subgroup IPA opening for the joint Libra polynomial.
338 SmallSubgroupIPA small_subgroup_ipa(zk_sumcheck_data, joint_challenge, claimed_libra_evaluation, transcript, ck);
339 small_subgroup_ipa.prove();
340
341 // Build joint PolynomialBatcher at joint_circuit_size = 2^17.
342 // max_end_index covers hiding (2^16) and translator (2^17) polynomials; use the larger.
343 const size_t joint_circuit_size = static_cast<size_t>(1) << JOINT_LOG_N;
344 const size_t mega_zk_max_end = mega_zk_inst->polynomials.max_end_index();
345 const size_t trans_max_end = translator_key->proving_key->circuit_size; // translator polys fill 2^17
346 const size_t max_end_index = std::max(mega_zk_max_end, trans_max_end);
347
348 PolynomialBatcher polynomial_batcher(joint_circuit_size, max_end_index);
349
350 // Combine unshifted polynomials: translator first (its masking poly at position 0 for Shplemini offset=2),
351 // then MegaZK (no masking poly — translator provides the joint masking poly).
352 auto trans_unshifted = translator_key->proving_key->polynomials.get_pcs_unshifted();
353 auto mega_zk_unshifted = mega_zk_inst->polynomials.get_unshifted();
354 auto joint_unshifted = concatenate(trans_unshifted, mega_zk_unshifted);
355 polynomial_batcher.set_unshifted(joint_unshifted);
356
357 // Combine shifted polynomials: MegaZK first, then translator.
358 auto mega_zk_shifted = mega_zk_inst->polynomials.get_to_be_shifted();
359 auto trans_shifted = translator_key->proving_key->polynomials.get_pcs_to_be_shifted();
360 auto joint_shifted = concatenate(mega_zk_shifted, trans_shifted);
361 polynomial_batcher.set_to_be_shifted_by_one(joint_shifted);
362
363 const OpeningClaim prover_opening_claim =
364 ShpleminiProver_<Curve>::prove(joint_circuit_size,
365 polynomial_batcher,
367 ck,
369 small_subgroup_ipa.get_witness_polynomials(),
372
374}
375
377{
378 BB_BENCH_NAME("BatchedHonkTranslatorProver::prove_mega_zk_oink");
380 return transcript->export_proof();
381}
382
384{
385 BB_BENCH_NAME("BatchedHonkTranslatorProver::prove");
386 translator_key = std::move(translator_proving_key);
390 return transcript->export_proof();
391}
392
393} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:264
std::shared_ptr< MegaZKProverInstance > mega_zk_inst
BatchedHonkTranslatorProver(std::shared_ptr< MegaZKProverInstance > mega_zk_instance, std::shared_ptr< MegaZKVK > mega_zk_vk, std::shared_ptr< Transcript > transcript)
std::vector< Polynomial< FF > > round_univariates_list
std::shared_ptr< TranslatorProvingKey > translator_key
void execute_joint_sumcheck_rounds()
Execute the joint 17-round sumcheck.
bb::RelationParameters< FF > translator_relation_parameters
void execute_joint_pcs()
Execute the joint Shplemini / KZG PCS over both circuits' polynomials.
std::array< FF, MegaZKFlavor::NUM_SUBRELATIONS - 1 > MegaZKSubrelationSeparators
HonkProof prove(std::shared_ptr< TranslatorProvingKey > translator_proving_key)
std::vector< std::array< FF, 3 > > round_evaluations_list
std::array< FF, TranslatorFlavor::NUM_SUBRELATIONS - 1 > TransSubrelationSeparators
void execute_mega_zk_oink()
Run the MegaZK circuit's Oink phase.
void execute_translator_oink()
Run the translator's Oink phase on the shared transcript.
CommitmentKey object over a pairing group 𝔾₁.
Class responsible for computation of the batched multilinear polynomials required by the Gemini proto...
Definition gemini.hpp:128
static void compute_opening_proof(const CK &ck, const ProverOpeningClaim< Curve > &opening_claim, const std::shared_ptr< Transcript > &prover_trancript)
Computes the KZG commitment to an opening proof polynomial at a single evaluation point.
Definition kzg.hpp:43
static constexpr size_t NUM_SUBRELATIONS
Executes the "Oink" phase of the Honk proving protocol: the initial rounds that commit to witness dat...
void prove(bool emit_alpha=true)
Commit to witnesses, compute relation parameters, and prepare for Sumcheck.
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition claim.hpp:55
A container for storing the partially evaluated multivariates produced by sumcheck.
Polynomial p and an opening pair (r,v) such that p(r) = v.
Definition claim.hpp:36
static OpeningClaim prove(size_t circuit_size, PolynomialBatcher &polynomial_batcher, std::span< FF > multilinear_challenge, const CommitmentKey< Curve > &commitment_key, const std::shared_ptr< Transcript > &transcript, const std::array< Polynomial, NUM_SMALL_IPA_EVALUATIONS > &libra_polynomials={}, const std::vector< Polynomial > &sumcheck_round_univariates={}, const std::vector< std::array< FF, 3 > > &sumcheck_round_evaluations={})
Definition shplemini.hpp:37
A Curve-agnostic ZK protocol to prove inner products of small vectors.
Flavor::CommitmentKey commitment_key
The implementation of the sumcheck Prover for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:294
Imlementation of the Sumcheck prover round.
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...
static SumcheckRoundUnivariate compute_libra_univariate(const ZKData &zk_sumcheck_data, size_t round_idx)
Compute Libra round univariate expressed given by the formula.
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.
size_t round_size
In Round , equals .
static std::array< FFType, NUM_FULL_CIRCUIT_EVALUATIONS > get_full_circuit_evaluations(AllEntities< FFType > &evals)
Prover: extract the full-circuit evaluations via get_full_circuit_entities().
static constexpr size_t LOG_MINI_CIRCUIT_SIZE
static constexpr size_t NUM_SUBRELATIONS
static std::array< FF, NUM_MINICIRCUIT_EVALUATIONS > get_minicircuit_evaluations(PolyContainer &polys)
Prover: read the 154 minicircuit wire evaluations from partially-evaluated polynomials.
BB_PROFILE void execute_preamble_round()
Add circuit size and values used in the relations to the transcript.
BB_PROFILE void execute_grand_product_computation_round()
Compute permutation product polynomial and commitments.
bb::RelationParameters< FF > relation_parameters
BB_PROFILE void execute_wire_and_sorted_constraints_commitments_round()
Compute commitments to wires and ordered range constraints.
A univariate polynomial represented by its values on {0, 1,..., domain_end - 1}.
static Univariate zero()
std::array< Fr, LENGTH > evaluations
static constexpr size_t SUBGROUP_SIZE
Definition bn254.hpp:34
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
RefArray< T,(Ns+...)> constexpr concatenate(const RefArray< T, Ns > &... ref_arrays)
Concatenates multiple RefArray objects into a single RefArray.
CommitmentKey< Curve > ck
std::array< FF, N > initialize_relation_separator(const FF &alpha)
Definition sumcheck.hpp:958
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 .
Handler for processing round univariates in sumcheck. Default implementation: send evaluations direct...
Definition sumcheck.hpp:27
void finalize_last_round(size_t, const bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &, const FF &)
Definition sumcheck.hpp:45
void process_round_univariate(size_t round_idx, bb::Univariate< FF, BATCHED_RELATION_PARTIAL_LENGTH > &round_univariate)
Definition sumcheck.hpp:39
Polynomial for Sumcheck with disabled Rows.
void update_evaluations(FF round_challenge, size_t round_idx)
Compute the evaluations of L^{(i)} at 0 and 1.
ClaimedLibraEvaluations libra_evaluations
void update_zk_sumcheck_data(const FF &round_challenge, const size_t round_idx)
Upon receiving the challenge , the prover updates Libra data. If .