Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
translator_verifier.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Sergei], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
17
18namespace bb {
19
20namespace {
21// Native helper: slice uint256_t values into limbs
22template <typename Flavor>
23void put_translation_data_in_relation_parameters_impl(RelationParameters<typename Flavor::FF>& relation_parameters,
24 const uint256_t& evaluation_input_x,
25 const typename Flavor::BF& batching_challenge_v,
26 const uint256_t& accumulated_result)
27 requires(!Flavor::Curve::is_stdlib_type)
28{
29 using FF = typename Flavor::FF;
30 using BF = typename Flavor::BF;
31
32 const auto compute_four_limbs = [](const auto& in) {
33 constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS;
34 return std::array<FF, 4>{ in.slice(0, NUM_LIMB_BITS),
35 in.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2),
36 in.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3),
37 in.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4) };
38 };
39
40 const auto compute_five_limbs = [](const auto& in) {
41 constexpr size_t NUM_LIMB_BITS = Flavor::NUM_LIMB_BITS;
42 return std::array<FF, 5>{ in.slice(0, NUM_LIMB_BITS),
43 in.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2),
44 in.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3),
45 in.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4),
46 in };
47 };
48
49 relation_parameters.evaluation_input_x = compute_five_limbs(evaluation_input_x);
50
51 uint256_t batching_challenge_v_power{ batching_challenge_v };
52 for (size_t i = 0; i < 4; i++) {
53 relation_parameters.batching_challenge_v[i] = compute_five_limbs(batching_challenge_v_power);
54 batching_challenge_v_power = BF(batching_challenge_v_power) * batching_challenge_v;
55 }
56
57 relation_parameters.accumulated_result = compute_four_limbs(accumulated_result);
58}
59
60// Recursive helper: extract limbs from bigfield elements
61template <typename Flavor>
62void put_translation_data_in_relation_parameters_impl(RelationParameters<typename Flavor::FF>& relation_parameters,
63 const typename Flavor::BF& evaluation_input_x,
64 const typename Flavor::BF& batching_challenge_v,
65 const typename Flavor::BF& accumulated_result)
66 requires(Flavor::Curve::is_stdlib_type)
67{
68 using FF = typename Flavor::FF;
69 using BF = typename Flavor::BF;
70
71 const auto compute_four_limbs = [](const BF& in) {
72 auto result = std::array<FF, 4>{ FF(in.binary_basis_limbs[0].element),
73 FF(in.binary_basis_limbs[1].element),
74 FF(in.binary_basis_limbs[2].element),
75 FF(in.binary_basis_limbs[3].element) };
76 // Ensure extracted limbs are witnesses, not constants
77 for (const auto& limb : result) {
78 BB_ASSERT(!limb.is_constant());
79 }
80 return result;
81 };
82
83 const auto compute_five_limbs = [](const BF& in) {
84 auto result = std::array<FF, 5>{ FF(in.binary_basis_limbs[0].element),
85 FF(in.binary_basis_limbs[1].element),
86 FF(in.binary_basis_limbs[2].element),
87 FF(in.binary_basis_limbs[3].element),
88 FF(in.prime_basis_limb) };
89 // Ensure extracted limbs are witnesses, not constants
90 for (const auto& limb : result) {
91 BB_ASSERT(!limb.is_constant());
92 }
93 return result;
94 };
95
96 relation_parameters.evaluation_input_x = compute_five_limbs(evaluation_input_x);
97
98 BF batching_challenge_v_power = batching_challenge_v;
99 for (size_t i = 0; i < 4; i++) {
100 relation_parameters.batching_challenge_v[i] = compute_five_limbs(batching_challenge_v_power);
101 batching_challenge_v_power = batching_challenge_v_power * batching_challenge_v;
102 }
103
104 relation_parameters.accumulated_result = compute_four_limbs(accumulated_result);
105
106 // OriginTag: The accumulated_result limbs originate from ECCVM verifier (different protocol phase)
107 // and are used directly in Translator relations. The fact that these values do not interact
108 // with any other value from the Translator circuit would trigger the round provenance mechanism if we didn't clear
109 // the round provenance. This cross-protocol usage is sound because:
110 // 1. ECCVM proves correctness of translation evaluations via its own sumcheck + IPA
111 // 2. ECCVM computes accumulated_result = (op + v·Px + v²·Py + v³·z1 + v⁴·z2 - masking) / x
112 // 3. Translator re-computes the same accumulator non-natively in its circuit
113 // 4. TranslatorAccumulatorTransferRelationImpl enforces exact equality at the final row:
114 // accumulators_binary_limbs_i == accumulated_result[i] for i ∈ {0,1,2,3}
115 // This binds the two protocols - Translator output must match ECCVM claim.
116 for (auto& limb : relation_parameters.accumulated_result) {
117 limb.clear_round_provenance();
118 }
119}
120} // namespace
121
123{
124 put_translation_data_in_relation_parameters_impl<Flavor>(
125 relation_parameters, evaluation_input_x, batching_challenge_v, accumulated_result);
126}
127
133template <typename Flavor>
135{
136 using PCS = typename Flavor::PCS;
138 using ClaimBatcher = ClaimBatcher_<Curve>;
139 using ClaimBatch = typename ClaimBatcher::Batch;
140 using InterleavedBatch = typename ClaimBatcher::InterleavedBatch;
141 using Sumcheck = SumcheckVerifier<Flavor>;
142
143 // Load the proof produced by the translator prover
144 transcript->load_proof(proof);
145
146 // Fiat-Shamir the vk hash
147 transcript->add_to_hash_buffer("vk_hash", vk_hash);
148 vinfo("Translator vk hash in verifier: ", vk_hash);
149
150 VerifierCommitments commitments{ key };
151 CommitmentLabels commitment_labels;
152
153 // For recursive verification, mark the accumulated result's prime basis limb as used
154 // (it can be recovered from binary basis limbs, so no need to constrain it further)
155 if constexpr (IsRecursive) {
156 mark_witness_as_used(accumulated_result.prime_basis_limb);
157 }
158
159 // Use accumulated_result from ECCVM verifier
160 put_translation_data_in_relation_parameters();
161
162 // Receive Gemini masking polynomial commitment (for ZK-PCS)
163 commitments.gemini_masking_poly = transcript->template receive_from_prover<Commitment>("Gemini:masking_poly_comm");
164
165 // Set op queue wire commitments (provided by merge protocol, not from translator proof)
166 commitments.op = op_queue_wire_commitments[0];
167 commitments.x_lo_y_hi = op_queue_wire_commitments[1];
168 commitments.x_hi_z_1 = op_queue_wire_commitments[2];
169 commitments.y_lo_z_2 = op_queue_wire_commitments[3];
170
171 // Receive commitments to non-op-queue wires and ordered range constraints
172 for (auto [comm, label] : zip_view(commitments.get_non_opqueue_wires_and_ordered_range_constraints(),
173 commitment_labels.get_non_opqueue_wires_and_ordered_range_constraints())) {
174 comm = transcript->template receive_from_prover<Commitment>(label);
175 }
176
177 // Get permutation challenges
178 FF beta = transcript->template get_challenge<FF>("beta");
179 FF gamma = transcript->template get_challenge<FF>("gamma");
180
181 relation_parameters.beta = beta;
182 relation_parameters.gamma = gamma;
183
184 // Get commitment to permutation and lookup grand products
185 commitments.z_perm = transcript->template receive_from_prover<Commitment>(commitment_labels.z_perm);
186
187 // Each linearly independent subrelation contribution is multiplied by `alpha^i`, where
188 // i = 0, ..., NUM_SUBRELATIONS- 1.
189 const FF alpha = transcript->template get_challenge<FF>("Sumcheck:alpha");
190
191 // Execute Sumcheck Verifier
192 Sumcheck sumcheck(transcript, alpha, TranslatorFlavor::CONST_TRANSLATOR_LOG_N);
193
194 std::vector<FF> gate_challenges(TranslatorFlavor::CONST_TRANSLATOR_LOG_N);
195 for (size_t idx = 0; idx < gate_challenges.size(); idx++) {
196 gate_challenges[idx] = transcript->template get_challenge<FF>("Sumcheck:gate_challenge_" + std::to_string(idx));
197 }
198
199 // Receive commitments to Libra masking polynomials
201 libra_commitments[0] = transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");
202
203 // Create padding indicator array
204 std::vector<FF> padding_indicator_array(TranslatorFlavor::CONST_TRANSLATOR_LOG_N, FF(1));
205
206 auto sumcheck_output = sumcheck.verify(relation_parameters, gate_challenges, padding_indicator_array);
207
208 libra_commitments[1] = transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
209 libra_commitments[2] = transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
210
211 // Execute Shplemini
212 ClaimBatcher claim_batcher{
213 .unshifted = ClaimBatch{ commitments.get_unshifted_without_interleaved(),
214 sumcheck_output.claimed_evaluations.get_unshifted_without_interleaved() },
215 .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() },
216 .interleaved = InterleavedBatch{ .commitments_groups = commitments.get_groups_to_be_interleaved(),
217 .evaluations = sumcheck_output.claimed_evaluations.get_interleaved() }
218 };
219
220 // Get Commitment::one() - requires builder for recursive case
221 Commitment commitment_one;
222 if constexpr (IsRecursive) {
223 commitment_one = Commitment::one(builder);
224 } else {
225 commitment_one = Commitment::one();
226 }
227
228 auto [opening_claim, consistency_checked] =
229 Shplemini::compute_batch_opening_claim(padding_indicator_array,
230 claim_batcher,
231 sumcheck_output.challenge,
232 commitment_one,
233 transcript,
235 libra_commitments,
236 sumcheck_output.claimed_libra_evaluation);
237
238 auto pairing_points = PCS::reduce_verify_batch_opening_claim(std::move(opening_claim), transcript);
239
240 vinfo("Translator Verifier: sumcheck verified: ", sumcheck_output.verified);
241 vinfo("Translator Verifier: consistency checked: ", consistency_checked);
242
243 return { pairing_points, sumcheck_output.verified && consistency_checked };
244}
245
246// Explicit instantiations
249
250} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:80
bb::field< bb::Bn254FrParams > FF
Definition field.cpp:22
typename Curve::ScalarField FF
typename Curve::BaseField BF
static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS
IPA (inner product argument) commitment scheme class.
Definition ipa.hpp:93
Implementation of the sumcheck Verifier for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:785
static constexpr size_t CONST_TRANSLATOR_LOG_N
Translator verifier class that verifies the proof of the Translator circuit.
ReductionResult reduce_to_pairing_check()
Reduce the translator proof to a pairing check.
void put_translation_data_in_relation_parameters()
Populate relation parameters with translation data from ECCVM verifier.
typename Flavor::VerifierCommitments VerifierCommitments
typename Flavor::CommitmentLabels CommitmentLabels
typename Flavor::Commitment Commitment
#define vinfo(...)
Definition log.hpp:94
AluTraceBuilder builder
Definition alu.test.cpp:124
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
This file contains part of the logic for the Origin Tag mechanism that tracks the use of in-circuit p...
Logic to support batching opening claims for unshifted, shifted and interleaved polynomials in Shplem...
Result of reducing translator proof to pairing check.