Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
translator_recursive_verifier.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
16
17namespace bb {
18
21 const std::shared_ptr<NativeVerificationKey>& native_verifier_key,
22 const std::shared_ptr<Transcript>& transcript)
23 : key(std::make_shared<VerificationKey>(builder, native_verifier_key))
24 , vk_hash(stdlib::witness_t<Builder>(builder, native_verifier_key->hash()))
25 , transcript(transcript)
27{
28 key->fix_witness(); // fixed to a constant
29 vk_hash.fix_witness(); // fixed to a constant
30}
31
32// Relation params used in sumcheck which is done over FF but the received data is from BF
34 const BF& batching_challenge_v,
35 const BF& accumulated_result)
36{
37
38 const auto compute_four_limbs = [](const BF& in) {
39 return std::array<FF, 4>{ FF(in.binary_basis_limbs[0].element),
40 FF(in.binary_basis_limbs[1].element),
41 FF(in.binary_basis_limbs[2].element),
42 FF(in.binary_basis_limbs[3].element) };
43 };
44
45 const auto compute_five_limbs = [](const BF& in) {
46 return std::array<FF, 5>{ FF(in.binary_basis_limbs[0].element),
47 FF(in.binary_basis_limbs[1].element),
48 FF(in.binary_basis_limbs[2].element),
49 FF(in.binary_basis_limbs[3].element),
50 FF(in.prime_basis_limb) };
51 };
52
53 relation_parameters.evaluation_input_x = compute_five_limbs(evaluation_input_x);
54
55 BF batching_challenge_v_power = batching_challenge_v;
56 for (size_t i = 0; i < 4; i++) {
57 relation_parameters.batching_challenge_v[i] = compute_five_limbs(batching_challenge_v_power);
58 batching_challenge_v_power = batching_challenge_v_power * batching_challenge_v;
59 }
60
61 relation_parameters.accumulated_result = compute_four_limbs(accumulated_result);
62};
63
74 const BF& evaluation_input_x,
75 const BF& batching_challenge_v)
76{
77 StdlibProof stdlib_proof(*builder, proof);
78 return verify_proof(stdlib_proof, evaluation_input_x, batching_challenge_v);
79}
80
91 const BF& evaluation_input_x,
92 const BF& batching_challenge_v)
93{
94 using Sumcheck = ::bb::SumcheckVerifier<Flavor>;
95 using PCS = Flavor::PCS;
96 using Curve = Flavor::Curve;
97 using Shplemini = ::bb::ShpleminiVerifier_<Curve>;
98 using VerifierCommitments = Flavor::VerifierCommitments;
99 using CommitmentLabels = Flavor::CommitmentLabels;
100 using ClaimBatcher = ClaimBatcher_<Curve>;
101 using ClaimBatch = ClaimBatcher::Batch;
102 using InterleavedBatch = ClaimBatcher::InterleavedBatch;
103
104 transcript->load_proof(proof);
105
106 // Fiat-Shamir the vk hash
107 // We do not need to hash the vk in-circuit because both the vk and vk hash are hardcoded as constants.
108 transcript->add_to_hash_buffer("vk_hash", vk_hash);
109 vinfo("Translator vk hash in recursive verifier: ", vk_hash);
110
111 VerifierCommitments commitments{ key };
112 CommitmentLabels commitment_labels;
113
114 const BF accumulated_result = transcript->template receive_from_prover<BF>("accumulated_result");
115 // The point is prime basis limb of accumulated result can be easily recovered from binary basis limbs, so
116 // there's no meaning to use it at the circuit next and we can put it in used_witnesses
117 accumulated_result.get_context()->update_used_witnesses(accumulated_result.prime_basis_limb.witness_index);
118
119 put_translation_data_in_relation_parameters(evaluation_input_x, batching_challenge_v, accumulated_result);
120
121 // Get commitments to wires and the ordered range constraints that do not require additional challenges
122 for (auto [comm, label] : zip_view(commitments.get_wires_and_ordered_range_constraints(),
123 commitment_labels.get_wires_and_ordered_range_constraints())) {
124 comm = transcript->template receive_from_prover<Commitment>(label);
125 }
126 op_queue_commitments = { commitments.op, commitments.x_lo_y_hi, commitments.x_hi_z_1, commitments.y_lo_z_2 };
127
128 // Get permutation challenges
129 FF beta = transcript->template get_challenge<FF>("beta");
130 FF gamma = transcript->template get_challenge<FF>("gamma");
131
134
135 // Get commitment to permutation and lookup grand products
136 commitments.z_perm = transcript->template receive_from_prover<Commitment>(commitment_labels.z_perm);
137
138 // Execute Sumcheck Verifier
139 // Each linearly independent subrelation contribution is multiplied by `alpha^i`, where
140 // i = 0, ..., NUM_SUBRELATIONS- 1.
141 const FF alpha = transcript->template get_challenge<FF>("Sumcheck:alpha");
142
143 Sumcheck sumcheck(transcript, alpha, TranslatorFlavor::CONST_TRANSLATOR_LOG_N);
144
145 std::vector<FF> gate_challenges(TranslatorFlavor::CONST_TRANSLATOR_LOG_N);
146 for (size_t idx = 0; idx < gate_challenges.size(); idx++) {
147 gate_challenges[idx] = transcript->template get_challenge<FF>("Sumcheck:gate_challenge_" + std::to_string(idx));
148 }
149
151 libra_commitments[0] = transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");
152
153 FF one{ 1 };
155
156 std::vector<FF> padding_indicator_array(TranslatorFlavor::CONST_TRANSLATOR_LOG_N);
157 std::ranges::fill(padding_indicator_array, one);
158
159 auto sumcheck_output = sumcheck.verify(relation_parameters, gate_challenges, padding_indicator_array);
160
161 libra_commitments[1] = transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
162 libra_commitments[2] = transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
163
164 // Execute Shplemini
165 bool consistency_checked = true;
166 ClaimBatcher claim_batcher{
167 .unshifted = ClaimBatch{ commitments.get_unshifted_without_interleaved(),
168 sumcheck_output.claimed_evaluations.get_unshifted_without_interleaved() },
169 .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() },
170 .interleaved = InterleavedBatch{ .commitments_groups = commitments.get_groups_to_be_interleaved(),
171 .evaluations = sumcheck_output.claimed_evaluations.get_interleaved() }
172 };
173 const BatchOpeningClaim<Curve> opening_claim =
174 Shplemini::compute_batch_opening_claim(padding_indicator_array,
175 claim_batcher,
176 sumcheck_output.challenge,
177 Commitment::one(builder),
181 &consistency_checked,
182 libra_commitments,
183 sumcheck_output.claimed_libra_evaluation);
184
185 auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript);
186
187 return { pairing_points[0], pairing_points[1] };
188}
189
191 const BF& translation_masking_term_eval)
192{
193 const auto reconstruct_from_array = [&](const auto& arr) {
194 return BF::construct_from_limbs(arr[0], arr[1], arr[2], arr[3]);
195 };
196
197 const BF accumulated_result = reconstruct_from_array(relation_parameters.accumulated_result);
198 const BF x = reconstruct_from_array(relation_parameters.evaluation_input_x);
199 const BF v1 = reconstruct_from_array(relation_parameters.batching_challenge_v[0]);
200 const BF v2 = reconstruct_from_array(relation_parameters.batching_challenge_v[1]);
201 const BF v3 = reconstruct_from_array(relation_parameters.batching_challenge_v[2]);
202 const BF v4 = reconstruct_from_array(relation_parameters.batching_challenge_v[3]);
203 const BF& op = translation_evaluations.op;
204 const BF& Px = translation_evaluations.Px;
205 const BF& Py = translation_evaluations.Py;
206 const BF& z1 = translation_evaluations.z1;
207 const BF& z2 = translation_evaluations.z2;
208
209 const BF eccvm_opening = (op + (v1 * Px) + (v2 * Py) + (v3 * z1) + (v4 * z2)) - translation_masking_term_eval;
210 // multiply by x here to deal with shift
211 eccvm_opening.assert_equal(x * accumulated_result);
212}
213
215 const std::array<Commitment, TranslatorFlavor::NUM_OP_QUEUE_WIRES>& merge_commitments)
216{
217 // Check the consistency with final merge
218 for (auto [merge_commitment, translator_commitment] : zip_view(merge_commitments, op_queue_commitments)) {
219 // These are witness commitments sent as part of the proof, so their coordinates are already in reduced form.
220 // This approach is preferred over implementing assert_equal for biggroup, as it avoids the need to handle
221 // constants within biggroup logic.
222 bool consistency_check_failed = (merge_commitment.y.get_value() != translator_commitment.y.get_value()) ||
223 (merge_commitment.y.get_value() != translator_commitment.y.get_value()) ||
224 (merge_commitment.is_point_at_infinity().get_value() !=
225 translator_commitment.is_point_at_infinity().get_value());
226
227 if (consistency_check_failed) {
228 vinfo("translator commitments are inconsistent with the final merge commitments");
229 }
230
231 merge_commitment.x.assert_equal(translator_commitment.x);
232 merge_commitment.y.assert_equal(translator_commitment.y);
233 merge_commitment.is_point_at_infinity().assert_equal(translator_commitment.is_point_at_infinity());
234 }
235}
236
237} // namespace bb
An efficient verifier for the evaluation proofs of multilinear polynomials and their shifts.
Implementation of the sumcheck Verifier for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:645
static constexpr size_t CONST_TRANSLATOR_LOG_N
The verification key is responsible for storing the commitments to the precomputed (non-witnessk) pol...
stdlib::bn254< CircuitBuilder > Curve
TranslatorFlavor::CommitmentLabels CommitmentLabels
TranslatorFlavor::VerifierCommitments_< Commitment, VerificationKey > VerifierCommitments
static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS
std::array< Commitment, TranslatorFlavor::NUM_OP_QUEUE_WIRES > op_queue_commitments
std::shared_ptr< VerificationKey > key
void verify_translation(const TranslationEvaluations &translation_evaluations, const BF &translation_masking_term_eval)
void put_translation_data_in_relation_parameters(const BF &evaluation_input_x, const BF &batching_challenge_v, const BF &accumulated_result)
PairingPoints verify_proof(const HonkProof &proof, const BF &evaluation_input_x, const BF &batching_challenge_v)
Creates a circuit that executes the Translator verifier algorithm up to the final pairing check.
TranslatorRecursiveVerifier(Builder *builder, const std::shared_ptr< NativeVerificationKey > &native_verifier_key, const std::shared_ptr< Transcript > &transcript)
void verify_consistency_with_final_merge(const std::array< Commitment, TranslatorFlavor::NUM_OP_QUEUE_WIRES > &merge_commitments)
Ensure translator verifier and last round of merge verification (operating with the final table) rece...
A simple wrapper around a vector of stdlib field elements representing a proof.
Definition proof.hpp:19
void convert_constant_to_fixed_witness(Builder *ctx)
Definition field.hpp:414
void vinfo(Args... args)
Definition log.hpp:76
AluTraceBuilder builder
Definition alu.test.cpp:123
void hash(State &state) noexcept
Entry point for Barretenberg command-line interface.
std::vector< fr > HonkProof
Definition proof.hpp:15
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
An accumulator consisting of the Shplonk evaluation challenge and vectors of commitments and scalars.
Definition claim.hpp:169
Logic to support batching opening claims for unshifted and shifted polynomials in Shplemini.
std::array< std::array< T, NUM_BINARY_LIMBS_IN_GOBLIN_TRANSLATOR+NUM_NATIVE_LIMBS_IN_GOBLIN_TRANSLATOR >, NUM_CHALLENGE_POWERS_IN_GOBLIN_TRANSLATOR > batching_challenge_v
std::array< T, NUM_BINARY_LIMBS_IN_GOBLIN_TRANSLATOR > accumulated_result
std::array< T, NUM_BINARY_LIMBS_IN_GOBLIN_TRANSLATOR+NUM_NATIVE_LIMBS_IN_GOBLIN_TRANSLATOR > evaluation_input_x
Stores the evaluations of op, Px, Py, z1, and z2 computed by the ECCVM Prover. These evaluations are ...