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.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 .ecc_op_wires = mega_zk_verifier_instance->witness_commitments.get_ecc_op_wires().get_copy(),
59 .kernel_calldata_commitment = mega_zk_verifier_instance->witness_commitments.kernel_calldata(),
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, joint_challenge);
189
190 // Translator FRV (no row-disabling).
192 FF frv_translator = trans_frv_round.compute_full_relation_purported_value(
193 trans_evals, translator_relation_parameters, final_gate_sep, translator_alphas);
194
195 // Combine: FRV_joint = FRV_MZK + α^{K_H} · FRV_translator.
196 FF frv_joint = frv_mega_zk + alpha_power_KH * frv_translator;
197
198 // Receive and apply Libra correction.
199 libra_evaluation = transcript->template receive_from_prover<FF>("Libra:claimed_evaluation");
200
201 // Receive Libra grand-sum and quotient commitments.
202 libra_commitments[1] = transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
203 libra_commitments[2] = transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
204
205 if constexpr (IsRecursive) {
206 const auto challenge_tag = joint_challenge.back().get_origin_tag();
207 libra_evaluation.set_origin_tag(challenge_tag);
208 }
209
210 frv_joint += libra_evaluation * libra_challenge;
211
212 // Final verification via committed sumcheck round: checks first-round sum and populates Shplemini data.
213 bool verified = joint_round.perform_final_verification(frv_joint);
214 round_univariate_commitments = std::move(joint_round.round_univariate_commitments);
215 round_univariate_evaluations = std::move(joint_round.round_univariate_evaluations);
216
217 return verified;
218}
219
225template <typename Curve>
227 bool sumcheck_verified, MegaZKVerifierCommitments& mega_zk_commitments, TransVerifierCommitments& trans_commitments)
228{
230 using ClaimBatcher = ClaimBatcher_<Curve>;
231 using ClaimBatch = typename ClaimBatcher::Batch;
232
233 const Commitment one_commitment = [&]() {
234 if constexpr (IsRecursive) {
235 return Commitment::one(builder);
236 } else {
237 return Commitment::one();
238 }
239 }();
240
241 // Translator claim components (translator first: its masking poly must be at position 0 for Shplemini offset=2).
243 trans_evals.get_groups_to_be_concatenated_shifted(), std::span<const FF>(joint_challenge));
244
245 RefVector<Commitment> joint_unshifted_comms = trans_commitments.get_pcs_unshifted();
246 RefVector<FF> joint_unshifted_evals = trans_evals.get_pcs_unshifted();
247
248 // Append MegaZK unshifted (no masking poly — translator provides the joint masking poly).
249 for (auto& comm : mega_zk_commitments.get_unshifted()) {
250 joint_unshifted_comms.push_back(comm);
251 }
252 for (auto& eval : mega_zk_evals.get_unshifted()) {
253 joint_unshifted_evals.push_back(eval);
254 }
255
256 // Shifted: MegaZK first, then translator.
257 RefVector<Commitment> joint_shifted_comms = mega_zk_commitments.get_to_be_shifted();
258 RefVector<FF> joint_shifted_evals = mega_zk_evals.get_shifted();
259
260 auto trans_shifted_comms = trans_commitments.get_pcs_to_be_shifted();
261 auto trans_pcs_shifted_evals = trans_evals.get_pcs_shifted();
262 for (auto& comm : trans_shifted_comms) {
263 joint_shifted_comms.push_back(comm);
264 }
265 for (auto& eval : trans_pcs_shifted_evals) {
266 joint_shifted_evals.push_back(eval);
267 }
268 for (auto& eval : concat_shift_evals) {
269 joint_shifted_evals.push_back(eval);
270 }
271
272 ClaimBatcher joint_claim_batcher{ .unshifted = ClaimBatch{ joint_unshifted_comms, joint_unshifted_evals },
273 .shifted = ClaimBatch{ joint_shifted_comms, joint_shifted_evals } };
274
275 auto [opening_claim, consistency_checked] =
276 MegaZKShplemini::compute_batch_opening_claim(joint_claim_batcher,
277 joint_challenge,
278 one_commitment,
279 transcript,
280 REPEATED_COMMITMENTS,
281 libra_commitments,
282 libra_evaluation,
283 round_univariate_commitments,
284 round_univariate_evaluations);
285
286 auto pairing_points = MegaZKFlavorT::PCS::reduce_verify_batch_opening_claim(std::move(opening_claim), transcript);
287
288 return { pairing_points, sumcheck_verified && consistency_checked };
289}
290
291template <typename Curve>
293 const Proof& joint_proof,
294 const TransBF& evaluation_input_x,
295 const TransBF& batching_challenge_v,
296 const TransBF& accumulated_result,
297 const std::array<Commitment, TranslatorFlavor::NUM_OP_QUEUE_WIRES>& op_queue_wire_commitments)
298{
299 // Reconstruct MegaZK commitments from the stored verifier instance.
301 mega_zk_verifier_instance->get_vk(), mega_zk_verifier_instance->witness_commitments);
302 auto trans_commitments = verify_translator_oink(
303 joint_proof, evaluation_input_x, batching_challenge_v, accumulated_result, op_queue_wire_commitments);
304 bool sumcheck_verified = verify_joint_sumcheck();
305 return verify_joint_pcs(sumcheck_verified, mega_zk_commitments, trans_commitments);
306}
307
308// Explicit instantiations.
311
312} // 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 VerifierCommitmentsConstructor< MegaZKFlavorT >::Commitments MegaZKVerifierCommitments
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.
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.
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.
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, std::span< const FF > multivariate_challenge={})
Evaluate the full Honk relation at the sumcheck challenge u.
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.
static Commitments construct(const std::shared_ptr< VerificationKey > &verification_key)
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:954
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.
Computes Oink proof length from flavor traits.
void throw_or_abort(std::string const &err)