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 =
78 transcript->template get_dyadic_powers_of_challenge<FF>("Sumcheck:gate_challenge", CONST_ECCVM_LOG_N);
79
80 // Receive commitments to Libra masking polynomials
81 std::array<Commitment, NUM_LIBRA_COMMITMENTS> libra_commitments = {};
82
83 libra_commitments[0] = transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");
84 auto sumcheck_output = sumcheck.verify(relation_parameters, gate_challenges);
85
86 libra_commitments[1] = transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
87 libra_commitments[2] = transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
88
89 // Compute the Shplemini accumulator consisting of the Shplonk evaluation and the commitments and scalars vector
90 // produced by the unified protocol
91
92 ClaimBatcher claim_batcher{
93 .unshifted = ClaimBatch{ commitments.get_unshifted(), sumcheck_output.claimed_evaluations.get_unshifted() },
94 .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() }
95 };
96
97 auto [sumcheck_batch_opening_claims, consistency_checked] =
98 Shplemini::compute_batch_opening_claim(claim_batcher,
99 sumcheck_output.challenge,
100 pcs_g1_identity,
101 transcript,
103 libra_commitments,
104 sumcheck_output.claimed_libra_evaluation,
105 sumcheck_output.round_univariate_commitments,
106 sumcheck_output.round_univariate_evaluations);
107
108 // Reduce the accumulator to a single opening claim
109 OpeningClaim multivariate_to_univariate_opening_claim =
110 PCS::reduce_batch_opening_claim(sumcheck_batch_opening_claims);
111
112 // Produce the opening claim for batch opening of `op`, `Px`, `Py`, `z1`, and `z2` wires as univariate
113 // polynomials
114
115 std::vector<Commitment> translation_commitments = { commitments.transcript_op,
116 commitments.transcript_Px,
117 commitments.transcript_Py,
118 commitments.transcript_z1,
119 commitments.transcript_z2 };
120 compute_translation_opening_claims(translation_commitments);
121
122 opening_claims.back() = multivariate_to_univariate_opening_claim;
123
124 // Construct the combined opening claim
125 const OpeningClaim batch_opening_claim = Shplonk::reduce_verification(pcs_g1_identity, opening_claims, transcript);
126
127 bool sumcheck_verified = sumcheck_output.verified;
128 vinfo("ECCVM Verifier: sumcheck verified: ", sumcheck_verified);
129 vinfo("ECCVM Verifier: consistency checked: ", consistency_checked);
130 vinfo("ECCVM Verifier: translation masking consistency checked: ", translation_masking_consistency_checked);
131
132 compute_accumulated_result();
133
134 return { batch_opening_claim, sumcheck_verified && consistency_checked && translation_masking_consistency_checked };
135}
136
146template <typename Flavor>
147void ECCVMVerifier_<Flavor>::compute_translation_opening_claims(const std::vector<Commitment>& translation_commitments)
148{
149 // Used to capture the batched evaluation of unmasked `translation_polynomials` while preserving ZK
150 using SmallIPA = SmallSubgroupIPAVerifier<Curve>;
151
152 // Initialize SmallSubgroupIPA structures
153 SmallSubgroupIPACommitments<Commitment> small_ipa_commitments;
154 std::array<FF, NUM_SMALL_IPA_EVALUATIONS> small_ipa_evaluations;
155 const auto labels = SmallIPA::evaluation_labels("Translation:");
156
157 // Get a commitment to M + Z_H * R, where M is a concatenation of the masking terms of
158 // `translation_polynomials`, Z_H = X^{|H|} - 1, and R is a random degree 2 polynomial
159 small_ipa_commitments.concatenated =
160 transcript->template receive_from_prover<Commitment>("Translation:concatenated_masking_term_commitment");
161
162 // Get a challenge to evaluate `translation_polynomials` as univariates
163 evaluation_challenge_x = transcript->template get_challenge<FF>("Translation:evaluation_challenge_x");
164
165 // Populate the translation evaluations {`op(x)`, `Px(x)`, `Py(x)`, `z1(x)`, `z2(x)`} to be batched
166 for (auto [eval, label] : zip_view(translation_evaluations.get_all(), translation_evaluations.labels)) {
167 eval = transcript->template receive_from_prover<FF>(label);
168 }
169
170 // Get the batching challenge for commitments and evaluations
171 batching_challenge_v = transcript->template get_challenge<FF>("Translation:batching_challenge_v");
172
173 // Get the value ∑ mᵢ(x) ⋅ vⁱ
174 translation_masking_term_eval = transcript->template receive_from_prover<FF>("Translation:masking_term_eval");
175
176 // Receive commitments to the SmallSubgroupIPA witnesses that are computed once x and v are available
177 small_ipa_commitments.grand_sum =
178 transcript->template receive_from_prover<Commitment>("Translation:grand_sum_commitment");
179 small_ipa_commitments.quotient =
180 transcript->template receive_from_prover<Commitment>("Translation:quotient_commitment");
181
182 // Get a challenge for the evaluations of the concatenated masking term G, grand sum A, its shift, and grand sum
183 // identity quotient Q
184 const FF small_ipa_evaluation_challenge =
185 transcript->template get_challenge<FF>("Translation:small_ipa_evaluation_challenge");
186
187 // Compute {r, r * g, r, r}, where r = `small_ipa_evaluation_challenge`
189 SmallIPA::evaluation_points(small_ipa_evaluation_challenge);
190
191 // Get the evaluations G(r), A(g * r), A(r), Q(r)
192 for (size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
193 small_ipa_evaluations[idx] = transcript->template receive_from_prover<FF>(labels[idx]);
194 opening_claims[idx] = { { evaluation_points[idx], small_ipa_evaluations[idx] },
195 small_ipa_commitments.get_all()[idx] };
196 }
197
198 // OriginTag false positive: Small IPA evaluations need to satisfy an identity where they are mixing without
199 // challenges, it is safe because these evaluations are opened in Shplonk.
200 if constexpr (IsRecursive) {
201 for (auto& eval : small_ipa_evaluations) {
202 eval.clear_round_provenance();
203 }
204 }
205
206 // Check Grand Sum Identity at r
207
208 translation_masking_consistency_checked =
209 SmallIPA::check_eccvm_evaluations_consistency(small_ipa_evaluations,
210 small_ipa_evaluation_challenge,
211 evaluation_challenge_x,
212 batching_challenge_v,
213 translation_masking_term_eval);
214
215 // Compute the batched commitment and batched evaluation for the univariate opening claim
216 FF batched_translation_evaluation = translation_evaluations.get_all()[0];
217 FF batching_scalar = batching_challenge_v;
218
219 std::vector<FF> batching_challenges = { FF::one() };
220 for (size_t idx = 1; idx < NUM_TRANSLATION_EVALUATIONS; ++idx) {
221 batched_translation_evaluation += batching_scalar * translation_evaluations.get_all()[idx];
222 batching_challenges.push_back(batching_scalar);
223 batching_scalar *= batching_challenge_v;
224 }
225 Commitment batched_commitment = Commitment::batch_mul(translation_commitments, batching_challenges);
226
227 // Place the claim to the array containing the SmallSubgroupIPA opening claims
228 opening_claims[NUM_SMALL_IPA_EVALUATIONS] = { { evaluation_challenge_x, batched_translation_evaluation },
229 batched_commitment };
230}
231
232// Compute the accumulated result from translation evaluations
233// This is the value that Translator will use in its relations
234// Formula: accumulated_result = (op + v*Px + v²*Py + v³*z1 + v⁴*z2 - masking_term) / x^5
235// Translation poly data starts at coefficient TRACE_OFFSET,
236// introducing an x^TRACE_OFFSET factor. The division by x^(1+TRACE_OFFSET) accounts for both the
237// shiftable offset (x) and the trace offset.
239{
240 FF v = batching_challenge_v;
241 FF v_squared = v * v;
242 FF v_cubed = v_squared * v;
243 FF v_fourth = v_cubed * v;
244
245 // OriginTag false positive: translation_masking_term_eval is bound by the masking term
246 // commitments (fixed before batching_challenge_v) and batching_challenge_v itself.
247 if constexpr (IsRecursive) {
248 translation_masking_term_eval.set_origin_tag(batching_challenge_v.get_origin_tag());
249 }
250
251 FF batched_eval_minus_masking = translation_evaluations.op + v * translation_evaluations.Px +
252 v_squared * translation_evaluations.Py + v_cubed * translation_evaluations.z1 +
253 v_fourth * translation_evaluations.z2 - translation_masking_term_eval;
254
255 // x^(1 + TRACE_OFFSET) accounts for the shiftable offset (x) and trace data offset (x^TRACE_OFFSET)
256 FF x_power = evaluation_challenge_x;
257 for (size_t i = 0; i < Flavor::TRACE_OFFSET; i++) {
258 x_power *= evaluation_challenge_x;
259 }
260 accumulated_result = batched_eval_minus_masking / x_power;
261}
262
263// Explicit template instantiations
264template class ECCVMVerifier_<ECCVMFlavor>;
266
267} // namespace bb
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:264
A container for commitment labels.
curve::Grumpkin Curve
static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS
static constexpr size_t TRACE_OFFSET
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:331
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:804
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, const std::vector< FF > &gate_challenges)
The Sumcheck verification method. First it extracts round univariate, checks sum (the sumcheck univar...
Definition sumcheck.hpp:859
#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
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()