Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
eccvm_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
13
14namespace bb {
15
20template <typename Flavor>
22{
23 BB_BENCH_NAME("ECCVMVerifier::reduce");
24 using Curve = typename Flavor::Curve;
26 using Shplonk = ShplonkVerifier_<Curve>;
28 using ClaimBatcher = ClaimBatcher_<Curve>;
29 using ClaimBatch = typename ClaimBatcher::Batch;
30
31 RelationParameters<FF> relation_parameters;
32
33 // Load proof into transcript
34 transcript->load_proof(proof);
35
36 // Fiat-Shamir the vk hash (computed in constructor)
37 transcript->add_to_hash_buffer("vk_hash", vk_hash);
38 vinfo("ECCVM vk hash: ", vk_hash);
39
40 VerifierCommitments commitments{ key };
41 CommitmentLabels commitment_labels;
42
43 // Receive Gemini masking polynomial commitment (for ZK-PCS)
44 commitments.gemini_masking_poly = transcript->template receive_from_prover<Commitment>("Gemini:masking_poly_comm");
45 for (auto [comm, label] : zip_view(commitments.get_wires(), commitment_labels.get_wires())) {
46 comm = transcript->template receive_from_prover<Commitment>(label);
47 }
48
49 // Get challenge for sorted list batching and wire four memory records
50 auto [beta, gamma] = transcript->template get_challenges<FF>(std::array<std::string, 2>{ "beta", "gamma" });
51
52 auto beta_sqr = beta * beta;
53 auto beta_quartic = beta_sqr * beta_sqr;
54 relation_parameters.gamma = gamma;
55 relation_parameters.beta = beta;
56 relation_parameters.beta_sqr = beta_sqr;
57 relation_parameters.beta_cube = beta_sqr * beta;
58 relation_parameters.beta_quartic = beta_quartic;
59 auto first_term_tag = beta_quartic; // FIRST_TERM_TAG (= 1) * beta_quartic
60 relation_parameters.eccvm_set_permutation_delta = (gamma + first_term_tag) * (gamma + beta_sqr + first_term_tag) *
61 (gamma + beta_sqr + beta_sqr + first_term_tag) *
62 (gamma + beta_sqr + beta_sqr + beta_sqr + first_term_tag);
63 relation_parameters.eccvm_set_permutation_delta = relation_parameters.eccvm_set_permutation_delta.invert();
64
65 // Get commitment to permutation and lookup grand products
66 commitments.lookup_inverses =
67 transcript->template receive_from_prover<Commitment>(commitment_labels.lookup_inverses);
68 commitments.z_perm = transcript->template receive_from_prover<Commitment>(commitment_labels.z_perm);
69
70 // Each linearly independent subrelation contribution is multiplied by `alpha^i`, where
71 // i = 0, ..., NUM_SUBRELATIONS- 1.
72 const FF alpha = transcript->template get_challenge<FF>("Sumcheck:alpha");
73
74 // Execute Sumcheck Verifier
75 SumcheckVerifier<Flavor> sumcheck(transcript, alpha, CONST_ECCVM_LOG_N);
76
77 std::vector<FF> gate_challenges(CONST_ECCVM_LOG_N);
78 for (size_t idx = 0; idx < gate_challenges.size(); idx++) {
79 gate_challenges[idx] = transcript->template get_challenge<FF>("Sumcheck:gate_challenge_" + std::to_string(idx));
80 }
81
82 // Receive commitments to Libra masking polynomials
83 std::array<Commitment, NUM_LIBRA_COMMITMENTS> libra_commitments = {};
84
85 libra_commitments[0] = transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");
86 std::vector<FF> padding_indicator_array(CONST_ECCVM_LOG_N, FF(1));
87
88 auto sumcheck_output = sumcheck.verify(relation_parameters, gate_challenges, padding_indicator_array);
89
90 libra_commitments[1] = transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
91 libra_commitments[2] = transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
92
93 // Compute the Shplemini accumulator consisting of the Shplonk evaluation and the commitments and scalars vector
94 // produced by the unified protocol
95
96 ClaimBatcher claim_batcher{
97 .unshifted = ClaimBatch{ commitments.get_unshifted(), sumcheck_output.claimed_evaluations.get_unshifted() },
98 .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() }
99 };
100
101 auto [sumcheck_batch_opening_claims, consistency_checked] =
102 Shplemini::compute_batch_opening_claim(padding_indicator_array,
103 claim_batcher,
104 sumcheck_output.challenge,
105 pcs_g1_identity,
106 transcript,
108 libra_commitments,
109 sumcheck_output.claimed_libra_evaluation,
110 sumcheck_output.round_univariate_commitments,
111 sumcheck_output.round_univariate_evaluations);
112
113 // Reduce the accumulator to a single opening claim
114 OpeningClaim multivariate_to_univariate_opening_claim =
115 PCS::reduce_batch_opening_claim(sumcheck_batch_opening_claims);
116
117 // Produce the opening claim for batch opening of `op`, `Px`, `Py`, `z1`, and `z2` wires as univariate
118 // polynomials
119
120 std::vector<Commitment> translation_commitments = { commitments.transcript_op,
121 commitments.transcript_Px,
122 commitments.transcript_Py,
123 commitments.transcript_z1,
124 commitments.transcript_z2 };
125 compute_translation_opening_claims(translation_commitments);
126
127 opening_claims.back() = multivariate_to_univariate_opening_claim;
128
129 // Construct the combined opening claim
130 const OpeningClaim batch_opening_claim = Shplonk::reduce_verification(pcs_g1_identity, opening_claims, transcript);
131
132 bool sumcheck_verified = sumcheck_output.verified;
133 vinfo("ECCVM Verifier: sumcheck verified: ", sumcheck_verified);
134 vinfo("ECCVM Verifier: consistency checked: ", consistency_checked);
135 vinfo("ECCVM Verifier: translation masking consistency checked: ", translation_masking_consistency_checked);
136
137 compute_accumulated_result();
138
139 return { batch_opening_claim, sumcheck_verified && consistency_checked && translation_masking_consistency_checked };
140}
141
151template <typename Flavor>
152void ECCVMVerifier_<Flavor>::compute_translation_opening_claims(const std::vector<Commitment>& translation_commitments)
153{
154 // Used to capture the batched evaluation of unmasked `translation_polynomials` while preserving ZK
155 using SmallIPA = SmallSubgroupIPAVerifier<Curve>;
156
157 // Initialize SmallSubgroupIPA structures
158 SmallSubgroupIPACommitments<Commitment> small_ipa_commitments;
159 std::array<FF, NUM_SMALL_IPA_EVALUATIONS> small_ipa_evaluations;
160 const auto labels = SmallIPA::evaluation_labels("Translation:");
161
162 // Get a commitment to M + Z_H * R, where M is a concatenation of the masking terms of
163 // `translation_polynomials`, Z_H = X^{|H|} - 1, and R is a random degree 2 polynomial
164 small_ipa_commitments.concatenated =
165 transcript->template receive_from_prover<Commitment>("Translation:concatenated_masking_term_commitment");
166
167 // Get a challenge to evaluate `translation_polynomials` as univariates
168 evaluation_challenge_x = transcript->template get_challenge<FF>("Translation:evaluation_challenge_x");
169
170 // Populate the translation evaluations {`op(x)`, `Px(x)`, `Py(x)`, `z1(x)`, `z2(x)`} to be batched
171 for (auto [eval, label] : zip_view(translation_evaluations.get_all(), translation_evaluations.labels)) {
172 eval = transcript->template receive_from_prover<FF>(label);
173 }
174
175 // Get the batching challenge for commitments and evaluations
176 batching_challenge_v = transcript->template get_challenge<FF>("Translation:batching_challenge_v");
177
178 // Get the value ∑ mᵢ(x) ⋅ vⁱ
179 translation_masking_term_eval = transcript->template receive_from_prover<FF>("Translation:masking_term_eval");
180
181 // Receive commitments to the SmallSubgroupIPA witnesses that are computed once x and v are available
182 small_ipa_commitments.grand_sum =
183 transcript->template receive_from_prover<Commitment>("Translation:grand_sum_commitment");
184 small_ipa_commitments.quotient =
185 transcript->template receive_from_prover<Commitment>("Translation:quotient_commitment");
186
187 // Get a challenge for the evaluations of the concatenated masking term G, grand sum A, its shift, and grand sum
188 // identity quotient Q
189 const FF small_ipa_evaluation_challenge =
190 transcript->template get_challenge<FF>("Translation:small_ipa_evaluation_challenge");
191
192 // Compute {r, r * g, r, r}, where r = `small_ipa_evaluation_challenge`
194 SmallIPA::evaluation_points(small_ipa_evaluation_challenge);
195
196 // Get the evaluations G(r), A(g * r), A(r), Q(r)
197 for (size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
198 small_ipa_evaluations[idx] = transcript->template receive_from_prover<FF>(labels[idx]);
199 opening_claims[idx] = { { evaluation_points[idx], small_ipa_evaluations[idx] },
200 small_ipa_commitments.get_all()[idx] };
201 }
202
203 // OriginTag false positive: Small IPA evaluations need to satisfy an identity where they are mixing without
204 // challenges, it is safe because these evaluations are opened in Shplonk.
205 if constexpr (IsRecursive) {
206 for (auto& eval : small_ipa_evaluations) {
207 eval.clear_round_provenance();
208 }
209 }
210
211 // Check Grand Sum Identity at r
212
213 translation_masking_consistency_checked =
214 SmallIPA::check_eccvm_evaluations_consistency(small_ipa_evaluations,
215 small_ipa_evaluation_challenge,
216 evaluation_challenge_x,
217 batching_challenge_v,
218 translation_masking_term_eval);
219
220 // Compute the batched commitment and batched evaluation for the univariate opening claim
221 FF batched_translation_evaluation = translation_evaluations.get_all()[0];
222 FF batching_scalar = batching_challenge_v;
223
224 std::vector<FF> batching_challenges = { FF::one() };
225 for (size_t idx = 1; idx < NUM_TRANSLATION_EVALUATIONS; ++idx) {
226 batched_translation_evaluation += batching_scalar * translation_evaluations.get_all()[idx];
227 batching_challenges.push_back(batching_scalar);
228 batching_scalar *= batching_challenge_v;
229 }
230 Commitment batched_commitment = Commitment::batch_mul(translation_commitments, batching_challenges);
231
232 // Place the claim to the array containing the SmallSubgroupIPA opening claims
233 opening_claims[NUM_SMALL_IPA_EVALUATIONS] = { { evaluation_challenge_x, batched_translation_evaluation },
234 batched_commitment };
235
236 // Compute `translation_masking_term_eval` * `evaluation_challenge_x`^{circuit_size -
237 // NUM_DISABLED_ROWS_IN_SUMCHECK}
238 shift_translation_masking_term_eval(evaluation_challenge_x, translation_masking_term_eval);
239}
240
241// Compute the accumulated result from translation evaluations
242// This is the value that Translator will use in its relations
243// Formula: accumulated_result = (op + v*Px + v²*Py + v³*z1 + v⁴*z2 - masking_term) / x
245{
246 FF v = batching_challenge_v;
247 FF v_squared = v * v;
248 FF v_cubed = v_squared * v;
249 FF v_fourth = v_cubed * v;
250
251 // OriginTag false positive: translation_masking_term_eval is bound by the masking term
252 // commitments (fixed before batching_challenge_v) and batching_challenge_v itself.
253 if constexpr (IsRecursive) {
254 translation_masking_term_eval.set_origin_tag(batching_challenge_v.get_origin_tag());
255 }
256
257 FF batched_eval_minus_masking = translation_evaluations.op + v * translation_evaluations.Px +
258 v_squared * translation_evaluations.Py + v_cubed * translation_evaluations.z1 +
259 v_fourth * translation_evaluations.z2 - translation_masking_term_eval;
260
261 accumulated_result = batched_eval_minus_masking / evaluation_challenge_x;
262}
263
264// Explicit template instantiations
265template class ECCVMVerifier_<ECCVMFlavor>;
267
268} // namespace bb
bb::field< bb::Bn254FrParams > FF
Definition field.cpp:24
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:225
A container for commitment labels.
curve::Grumpkin Curve
static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS
Unified ECCVM verifier class for both native and recursive verification.
void compute_translation_opening_claims(const std::vector< Commitment > &translation_commitments)
To link the ECCVM Transcript wires op, Px, Py, z1, and z2 to the accumulator computed by the translat...
Flavor::Commitment Commitment
ReductionResult reduce_to_ipa_opening()
Reduce the ECCVM proof to an IPA opening claim.
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition claim.hpp:55
Shplonk Verifier.
Definition shplonk.hpp:338
Verifies the consistency of polynomial evaluations provided by the the prover.
Implementation of the sumcheck Verifier for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:747
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, const std::vector< FF > &gate_challenges, const std::vector< FF > &padding_indicator_array)
The Sumcheck verification method. First it extracts round univariate, checks sum (the sumcheck univar...
Definition sumcheck.hpp:803
#define vinfo(...)
Definition log.hpp:94
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 and shifted polynomials in Shplemini.
Result of reducing ECCVM proof to IPA opening claim.
Container for parameters used by the grand product (permutation, lookup) Honk relations.
Contains commitments to polynomials [G], [A], and [Q]. See SmallSubgroupIPAProver docs.
RefArray< Commitment, NUM_SMALL_IPA_EVALUATIONS > get_all()