Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
batched_honk_translator_verifier.cpp
Go to the documentation of this file.
2
17
18namespace bb {
19
20template <typename Curve>
22 std::shared_ptr<MegaZKVKAndHash> mega_zk_vk_and_hash, std::shared_ptr<Transcript> transcript)
23 : mega_zk_vk_and_hash(std::move(mega_zk_vk_and_hash))
24 , transcript(std::move(transcript))
25{}
26
33template <typename Curve>
35 const Proof& mega_zk_proof)
36{
37 transcript->load_proof(mega_zk_proof);
38
39 if constexpr (IsRecursive) {
40 builder = mega_zk_proof.back().get_context();
41 }
42
43 mega_zk_verifier_instance = std::make_shared<MegaZKVerifierInstance>(mega_zk_vk_and_hash);
44
45 // Derive num_public_inputs from the Oink-only MegaZK proof.
47 throw_or_abort("MegaZK Oink proof too short to derive num_public_inputs");
48 }
49 const size_t num_public_inputs = mega_zk_proof.size() - ProofLength::Oink<MegaZKFlavorT>::LENGTH_WITHOUT_PUB_INPUTS;
50
51 OinkVerifier<MegaZKFlavorT> oink_verifier{ mega_zk_verifier_instance, transcript, num_public_inputs };
52 oink_verifier.verify(/*emit_alpha=*/false);
53
54 mega_zk_relation_parameters = mega_zk_verifier_instance->relation_parameters;
55
56 return OinkResult{
57 .public_inputs = mega_zk_verifier_instance->public_inputs,
58 .kernel_calldata_commitment = mega_zk_verifier_instance->witness_commitments.kernel_calldata,
59 .ecc_op_wires = mega_zk_verifier_instance->witness_commitments.get_ecc_op_wires().get_copy(),
60 };
61}
62
69template <typename Curve>
71 Curve>::verify_translator_oink(const Proof& joint_proof,
72 const TransBF& evaluation_input_x,
73 const TransBF& batching_challenge_v,
74 const TransBF& accumulated_result,
75 const std::array<Commitment, TranslatorFlavor::NUM_OP_QUEUE_WIRES>&
76 op_queue_wire_commitments)
77{
78 // Pass the full joint_proof to TranslatorVerifier. It calls
79 // transcript->load_proof(proof) in receive_pre_sumcheck(), loading everything
80 // (translator oink + joint sumcheck + joint PCS data) into the transcript buffer.
81 // The joint phases that follow will read the remaining data in order.
82 TranslatorVerifier_<TransFlavor> trans_verifier(transcript,
83 joint_proof,
84 evaluation_input_x,
85 batching_challenge_v,
86 accumulated_result,
87 op_queue_wire_commitments);
88 auto trans_commitments = trans_verifier.receive_pre_sumcheck();
89 translator_relation_parameters = trans_verifier.relation_parameters;
90 return trans_commitments;
91}
92
101{
102 static constexpr size_t JOINT_LOG_N = TranslatorFlavor::CONST_TRANSLATOR_LOG_N; // 17
103
104 // Draw joint alpha after all pre-sumcheck commitments from both circuits.
105 const FF alpha = transcript->template get_challenge<FF>("Sumcheck:alpha");
106
107 // Compute α^{K_H}.
108 FF alpha_power_KH = FF(1);
109 for (size_t i = 0; i < MegaZKFlavorT::NUM_SUBRELATIONS; i++) {
110 alpha_power_KH *= alpha;
111 }
112
113 // Subrelation separators.
114 auto mega_zk_alphas = initialize_relation_separator<FF, MegaZKFlavorT::NUM_SUBRELATIONS - 1>(alpha);
115 auto translator_alphas = initialize_relation_separator<FF, TransFlavor::NUM_SUBRELATIONS - 1>(alpha);
116
117 // Draw gate challenges.
118 std::vector<FF> gate_challenges =
119 transcript->template get_dyadic_powers_of_challenge<FF>("Sumcheck:gate_challenge", JOINT_LOG_N);
120
121 // Receive Libra masking commitments.
122 libra_commitments = {};
123 libra_commitments[0] = transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");
124
125 // ZK correction: receive Libra:Sum and Libra:Challenge to set initial target sum.
126 FF libra_total_sum = transcript->template receive_from_prover<FF>("Libra:Sum");
127 libra_challenge = transcript->template get_challenge<FF>("Libra:Challenge");
128
129 // Use committed sumcheck infrastructure: defers per-round checks to Shplemini.
130 static constexpr bool UseCommittedSumcheck = true;
131 SumcheckVerifierRound<MegaZKFlavorT, UseCommittedSumcheck> joint_round(libra_total_sum * libra_challenge);
132
133 GateSeparatorPolynomial<FF> gate_sep(gate_challenges);
134
135 joint_challenge.clear();
136 joint_challenge.reserve(JOINT_LOG_N);
137
138 for (size_t round_idx = 0; round_idx < JOINT_LOG_N; round_idx++) {
139 joint_round.process_round(transcript, joint_challenge, gate_sep, round_idx);
140
141 if (round_idx == TranslatorFlavor::LOG_MINI_CIRCUIT_SIZE - 1) {
142 TransFlavor::set_minicircuit_evaluations(
143 trans_evals,
144 transcript->template receive_from_prover<std::array<FF, TransFlavor::NUM_MINICIRCUIT_EVALUATIONS>>(
145 "Sumcheck:minicircuit_evaluations"));
146 }
147 }
148
149 // Receive MegaZK evaluations after all rounds — full N-variable multilinear evaluations.
150 {
151 auto transcript_evals =
152 transcript->template receive_from_prover<std::array<FF, MegaZKFlavorT::NUM_ALL_ENTITIES>>(
153 "Sumcheck:evaluations");
154 for (auto [eval, te] : zip_view(mega_zk_evals.get_all(), transcript_evals)) {
155 eval = te;
156 }
157 }
158
159 // Receive translator evaluations (full-circuit subset, then complete from minicircuit + precomputed).
160 {
161 auto get_full_circuit_evals =
162 transcript->template receive_from_prover<std::array<FF, TransFlavor::NUM_FULL_CIRCUIT_EVALUATIONS>>(
163 "Sumcheck:evaluations_translator");
164 TransFlavor::complete_full_circuit_evaluations(
165 trans_evals, get_full_circuit_evals, std::span<const FF>(joint_challenge));
166 }
167
168 // Set OriginTag for recursive mode.
169 if constexpr (IsRecursive) {
170 const auto challenge_tag = joint_challenge.back().get_origin_tag();
171 for (auto& eval : mega_zk_evals.get_all()) {
172 eval.set_origin_tag(challenge_tag);
173 }
174 for (auto& eval : trans_evals.get_all()) {
175 eval.set_origin_tag(challenge_tag);
176 }
177 }
178
179 // -------------------------------------------------------------------------
180 // Compute joint full-relation purported value.
181 // -------------------------------------------------------------------------
182
183 GateSeparatorPolynomial<FF> final_gate_sep(gate_challenges, joint_challenge);
184
185 // MegaZK circuit FRV: evaluations are full N-variable multilinear evaluations.
186 SumcheckVerifierRound<MegaZKFlavorT> mega_zk_frv_round;
187 FF frv_mega_zk = mega_zk_frv_round.compute_full_relation_purported_value(
188 mega_zk_evals, mega_zk_relation_parameters, final_gate_sep, mega_zk_alphas);
189
190 // Apply row-disabling polynomial: RDP = 1 - ∏_{i≥2}(1-u_i) over ALL challenges (circuit-size independent).
191 FF rdp = RowDisablingPolynomial<FF>::evaluate_at_challenge(joint_challenge, joint_challenge.size());
192 frv_mega_zk *= rdp;
193
194 // Translator FRV (no row-disabling).
196 FF frv_translator = trans_frv_round.compute_full_relation_purported_value(
197 trans_evals, translator_relation_parameters, final_gate_sep, translator_alphas);
198
199 // Combine: FRV_joint = FRV_MZK + α^{K_H} · FRV_translator.
200 FF frv_joint = frv_mega_zk + alpha_power_KH * frv_translator;
201
202 // Receive and apply Libra correction.
203 libra_evaluation = transcript->template receive_from_prover<FF>("Libra:claimed_evaluation");
204
205 // Receive Libra grand-sum and quotient commitments.
206 libra_commitments[1] = transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
207 libra_commitments[2] = transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
208
209 if constexpr (IsRecursive) {
210 const auto challenge_tag = joint_challenge.back().get_origin_tag();
211 libra_evaluation.set_origin_tag(challenge_tag);
212 }
213
214 frv_joint += libra_evaluation * libra_challenge;
215
216 // Final verification via committed sumcheck round: checks first-round sum and populates Shplemini data.
217 bool verified = joint_round.perform_final_verification(frv_joint);
218 round_univariate_commitments = std::move(joint_round.round_univariate_commitments);
219 round_univariate_evaluations = std::move(joint_round.round_univariate_evaluations);
220
221 return verified;
222}
223
229template <typename Curve>
231 bool sumcheck_verified, MegaZKVerifierCommitments& mega_zk_commitments, TransVerifierCommitments& trans_commitments)
232{
234 using ClaimBatcher = ClaimBatcher_<Curve>;
235 using ClaimBatch = typename ClaimBatcher::Batch;
236
237 const Commitment one_commitment = [&]() {
238 if constexpr (IsRecursive) {
239 return Commitment::one(builder);
240 } else {
241 return Commitment::one();
242 }
243 }();
244
245 // Translator claim components (translator first: its masking poly must be at position 0 for Shplemini offset=2).
247 trans_evals.get_groups_to_be_concatenated_shifted(), std::span<const FF>(joint_challenge));
248
249 RefVector<Commitment> joint_unshifted_comms = trans_commitments.get_pcs_unshifted();
250 RefVector<FF> joint_unshifted_evals = trans_evals.get_pcs_unshifted();
251
252 // Append MegaZK unshifted (no masking poly — translator provides the joint masking poly).
253 for (auto& comm : mega_zk_commitments.get_unshifted()) {
254 joint_unshifted_comms.push_back(comm);
255 }
256 for (auto& eval : mega_zk_evals.get_unshifted()) {
257 joint_unshifted_evals.push_back(eval);
258 }
259
260 // Shifted: MegaZK first, then translator.
261 RefVector<Commitment> joint_shifted_comms = mega_zk_commitments.get_to_be_shifted();
262 RefVector<FF> joint_shifted_evals = mega_zk_evals.get_shifted();
263
264 auto trans_shifted_comms = trans_commitments.get_pcs_to_be_shifted();
265 auto trans_pcs_shifted_evals = trans_evals.get_pcs_shifted();
266 for (auto& comm : trans_shifted_comms) {
267 joint_shifted_comms.push_back(comm);
268 }
269 for (auto& eval : trans_pcs_shifted_evals) {
270 joint_shifted_evals.push_back(eval);
271 }
272 for (auto& eval : concat_shift_evals) {
273 joint_shifted_evals.push_back(eval);
274 }
275
276 ClaimBatcher joint_claim_batcher{ .unshifted = ClaimBatch{ joint_unshifted_comms, joint_unshifted_evals },
277 .shifted = ClaimBatch{ joint_shifted_comms, joint_shifted_evals } };
278
279 auto [opening_claim, consistency_checked] =
280 MegaZKShplemini::compute_batch_opening_claim(joint_claim_batcher,
281 joint_challenge,
282 one_commitment,
283 transcript,
284 REPEATED_COMMITMENTS,
285 libra_commitments,
286 libra_evaluation,
287 round_univariate_commitments,
288 round_univariate_evaluations);
289
290 auto pairing_points = MegaZKFlavorT::PCS::reduce_verify_batch_opening_claim(std::move(opening_claim), transcript);
291
292 return { pairing_points, sumcheck_verified && consistency_checked };
293}
294
295template <typename Curve>
297 const Proof& joint_proof,
298 const TransBF& evaluation_input_x,
299 const TransBF& batching_challenge_v,
300 const TransBF& accumulated_result,
301 const std::array<Commitment, TranslatorFlavor::NUM_OP_QUEUE_WIRES>& op_queue_wire_commitments)
302{
303 // Reconstruct MegaZK commitments from the stored verifier instance.
304 MegaZKVerifierCommitments mega_zk_commitments{ mega_zk_verifier_instance->get_vk(),
305 mega_zk_verifier_instance->witness_commitments };
306 auto trans_commitments = verify_translator_oink(
307 joint_proof, evaluation_input_x, batching_challenge_v, accumulated_result, op_queue_wire_commitments);
308 bool sumcheck_verified = verify_joint_sumcheck();
309 return verify_joint_pcs(sumcheck_verified, mega_zk_commitments, trans_commitments);
310}
311
312// Explicit instantiations.
315
316} // namespace bb
bb::field< bb::Bn254FrParams > FF
Definition field.cpp:24
Verifier for the batched MegaZK circuit + translator sumcheck and PCS.
std::conditional_t< IsRecursive, stdlib::Proof< UltraCircuitBuilder >, HonkProof > Proof
BatchedHonkTranslatorVerifier_(std::shared_ptr< MegaZKVKAndHash > mega_zk_vk_and_hash, std::shared_ptr< Transcript > transcript)
Construct the batched verifier with minimal state.
typename TransFlavor::VerifierCommitments TransVerifierCommitments
ReductionResult verify_joint_pcs(bool sumcheck_verified, MegaZKVerifierCommitments &mega_zk_commitments, TransVerifierCommitments &trans_commitments)
Execute the joint Shplemini / KZG PCS reduction.
ReductionResult verify(const Proof &joint_proof, const TransBF &evaluation_input_x, const TransBF &batching_challenge_v, const TransBF &accumulated_result, const std::array< Commitment, TranslatorFlavor::NUM_OP_QUEUE_WIRES > &op_queue_wire_commitments)
Phase 2: Verify translator Oink + joint sumcheck + joint PCS.
bool verify_joint_sumcheck()
Verify the joint 17-round sumcheck.
OinkResult verify_mega_zk_oink(const Proof &mega_zk_proof)
Phase 1: Verify the MegaZK Oink phase on the shared transcript.
typename MegaZKFlavorT::VerifierCommitments MegaZKVerifierCommitments
Verifier counterpart to OinkProver: receives witness commitments, computes relation parameters,...
void verify(bool emit_alpha=true)
Receive witness commitments, compute relation parameters, and prepare for Sumcheck.
A template class for a reference vector. Behaves as if std::vector<T&> was possible.
void push_back(T &element)
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)
Compute the full relation purported value.
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.
bool perform_final_verification(const FF &full_honk_purported_value)
Perform final verification: check that the computed target sum matches the full relation evaluation....
static constexpr size_t CONST_TRANSLATOR_LOG_N
static constexpr size_t LOG_MINI_CIRCUIT_SIZE
static std::array< FFType, NUM_CONCATENATED_POLYS > reconstruct_concatenated_evaluations(const std::vector< RefVector< FFType > > &groups, std::span< const FFType > challenge)
Reconstruct concatenated polynomial evaluations from individual wire evaluations using the Lagrange b...
Translator verifier class that verifies the proof of the Translator circuit.
VerifierCommitments receive_pre_sumcheck()
Load translator proof and run the pre-sumcheck (Oink-like) phase on the shared transcript.
AluTraceBuilder builder
Definition alu.test.cpp:124
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
std::array< FF, N > initialize_relation_separator(const FF &alpha)
Definition sumcheck.hpp:949
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Logic to support batching opening claims for unshifted and shifted polynomials in Shplemini.
Implementation of the methods for the -polynomials used in in Sumcheck.
Computes Oink proof length from flavor traits.
static FF evaluate_at_challenge(std::span< const FF > multivariate_challenge, const size_t log_circuit_size)
Compute the evaluation of at the sumcheck challenge.
void throw_or_abort(std::string const &err)