Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
merge_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
7#include "merge_verifier.hpp"
11
12namespace bb {
13
14template <typename Curve>
15bool MergeVerifier_<Curve>::check_concatenation_identities(std::vector<FF>& evals, const FF& pow_kappa) const
16{
17 bool concatenation_verified = true;
18 FF concatenation_diff(0);
19 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
20 concatenation_diff = evals[idx] + (pow_kappa * evals[idx + NUM_WIRES]) - evals[idx + (2 * NUM_WIRES)];
21 if constexpr (IsRecursive) {
22 concatenation_verified &= concatenation_diff.get_value() == 0;
23 concatenation_diff.assert_equal(FF(0),
24 "assert_equal: merge concatenation identity failed in Merge Verifier");
25 } else {
26 concatenation_verified &= concatenation_diff == 0;
27 }
28 }
29 return concatenation_verified;
30}
31
32template <typename Curve>
34 const FF& pow_kappa_minus_one,
35 const std::vector<FF>& degree_check_challenges) const
36{
37 bool degree_check_verified = true;
38 FF degree_check_diff(0);
39 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
40 degree_check_diff += evals[idx] * degree_check_challenges[idx];
41 }
42 degree_check_diff -= evals.back() * pow_kappa_minus_one;
43 if constexpr (IsRecursive) {
44 degree_check_diff.assert_equal(FF(0), "assert_equal: merge degree identity failed in Merge Verifier");
45 degree_check_verified &= degree_check_diff.get_value() == 0;
46 } else {
47 degree_check_verified &= degree_check_diff == 0;
48 }
49
50 return degree_check_verified;
51}
52
53template <typename Curve>
55 const std::vector<Commitment>& table_commitments,
56 const Commitment& shplonk_batched_quotient,
57 const FF& shplonk_opening_challenge,
58 const std::vector<FF>& shplonk_batching_challenges,
59 const FF& kappa,
60 const FF& kappa_inv,
61 const std::vector<FF>& evals) const
62{
63 // Claim {Q', (z, 0)} where Q' = -Q·(z - κ) + Σᵢ βᵢLᵢ + Σᵢ βᵢRᵢ + Σᵢ βᵢMᵢ + (z - κ)/(z - κ⁻¹)·βG
64 // - Σᵢ βᵢlᵢ - Σᵢ βᵢrᵢ - Σᵢ βᵢmᵢ - (z - κ)/(z - κ⁻¹)·β·g
65 BatchOpeningClaim<Curve> batch_opening_claim;
66
67 // Commitment: [L_1], [L_2], ..., [L_n], [R_1], ..., [R_n], [M_1], ..., [M_n], [G], [1]
68 batch_opening_claim.commitments = { std::move(shplonk_batched_quotient) };
69 for (auto& commitment : table_commitments) {
70 batch_opening_claim.commitments.emplace_back(std::move(commitment));
71 }
72 if constexpr (IsRecursive) {
73 batch_opening_claim.commitments.emplace_back(Commitment::one(kappa.get_context()));
74 } else {
75 batch_opening_claim.commitments.emplace_back(Commitment::one());
76 }
77
78 // Scalars: -(z - κ), β₁...β₁₂, β₁₃·(z - κ)/(z - κ⁻¹), -(Σᵢ βᵢlᵢ + Σᵢ βᵢrᵢ + Σᵢ βᵢmᵢ + β₁₃·(z - κ)/(z - κ⁻¹)·g)
79 batch_opening_claim.scalars = { -(shplonk_opening_challenge - kappa) };
80 for (auto& scalar : shplonk_batching_challenges) {
81 batch_opening_claim.scalars.emplace_back(std::move(scalar));
82 }
83 batch_opening_claim.scalars.back() *=
84 (shplonk_opening_challenge - kappa) * (shplonk_opening_challenge - kappa_inv).invert();
85
86 batch_opening_claim.scalars.emplace_back(FF(0));
87 for (size_t idx = 0; idx < evals.size(); idx++) {
88 if (idx < evals.size() - 1) {
89 batch_opening_claim.scalars.back() -= evals[idx] * shplonk_batching_challenges[idx];
90 } else {
91 batch_opening_claim.scalars.back() -= shplonk_batching_challenges.back() * evals.back() *
92 (shplonk_opening_challenge - kappa) *
93 (shplonk_opening_challenge - kappa_inv).invert();
94 }
95 }
96
97 batch_opening_claim.evaluation_point = { shplonk_opening_challenge };
98
99 return batch_opening_claim;
100}
101
112template <typename Curve>
114 const Proof& proof, const InputCommitments& input_commitments)
115{
116 transcript->load_proof(proof);
117
118 // Receive shift size from prover
119 // For native: shift_size is uint32_t
120 // For stdlib: shift_size is FF (we'll get the value later)
121 const FF shift_size = transcript->template receive_from_prover<FF>("shift_size");
122 ;
123 if constexpr (IsRecursive) {
124 BB_ASSERT_GT(uint32_t(shift_size.get_value()), 0U, "Shift size should always be bigger than 0");
125 } else {
126
127 BB_ASSERT_GT(shift_size, 0U, "Shift size should always be bigger than 0");
128 }
129
130 // Store T_commitments of the verifier
131 TableCommitments merged_table_commitments;
132
133 // Vector of commitments
134 // The vector is composed of: [L_1], .., [L_4], [R_1], .., [R_4], [M_1], .., [M_4], [G]
135 std::vector<Commitment> table_commitments;
136 table_commitments.reserve((3 * NUM_WIRES) + 1);
137 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
138 table_commitments.emplace_back(settings == MergeSettings::PREPEND ? input_commitments.t_commitments[idx]
139 : input_commitments.T_prev_commitments[idx]);
140 }
141 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
142 table_commitments.emplace_back(settings == MergeSettings::PREPEND ? input_commitments.T_prev_commitments[idx]
143 : input_commitments.t_commitments[idx]);
144 }
145 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
146 table_commitments.emplace_back(
147 transcript->template receive_from_prover<Commitment>("MERGED_TABLE_" + std::to_string(idx)));
148 merged_table_commitments[idx] = table_commitments.back();
149 }
150
151 // Generate degree check batching challenges
152 std::vector<FF> degree_check_challenges = transcript->template get_challenges<FF>(labels_degree_check);
153
154 // Receive commitment to reversed batched left table
155 table_commitments.emplace_back(
156 transcript->template receive_from_prover<Commitment>("REVERSED_BATCHED_LEFT_TABLES"));
157
158 // Compute batching challenges
159 std::vector<FF> shplonk_batching_challenges =
160 transcript->template get_challenges<FF>(labels_shplonk_batching_challenges);
161
162 // Evaluation challenge
163 const FF kappa = transcript->template get_challenge<FF>("kappa");
164 const FF kappa_inv = kappa.invert();
165 const FF pow_kappa = kappa.pow(shift_size);
166 const FF pow_kappa_minus_one = pow_kappa * kappa_inv;
167
168 // Receive evaluations of [Lᵢ], [Rᵢ], [Mᵢ] at κ
169 std::vector<FF> evals;
170 evals.reserve((3 * NUM_WIRES) + 1);
171 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
172 evals.emplace_back(transcript->template receive_from_prover<FF>("LEFT_TABLE_EVAL_" + std::to_string(idx)));
173 }
174 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
175 evals.emplace_back(transcript->template receive_from_prover<FF>("RIGHT_TABLE_EVAL_" + std::to_string(idx)));
176 }
177 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
178 evals.emplace_back(transcript->template receive_from_prover<FF>("MERGED_TABLE_EVAL_" + std::to_string(idx)));
179 }
180
181 // Receive evaluation of G at 1/κ
182 evals.emplace_back(transcript->template receive_from_prover<FF>("REVERSED_BATCHED_LEFT_TABLES_EVAL"));
183
184 // Check concatenation identities
185 bool concatenation_verified = check_concatenation_identities(evals, pow_kappa);
186
187 // Check degree identity
188 bool degree_check_verified = check_degree_identity(evals, pow_kappa_minus_one, degree_check_challenges);
189
190 // Receive Shplonk batched quotient
191 Commitment shplonk_batched_quotient =
192 transcript->template receive_from_prover<Commitment>("SHPLONK_BATCHED_QUOTIENT");
193
194 // Generate Shplonk opening challenge
195 FF shplonk_opening_challenge = transcript->template get_challenge<FF>("shplonk_opening_challenge");
196
197 // Prepare batched opening claim to be passed to KZG
198 BatchOpeningClaim<Curve> batch_opening_claim = compute_shplonk_opening_claim(table_commitments,
199 shplonk_batched_quotient,
200 shplonk_opening_challenge,
201 shplonk_batching_challenges,
202 kappa,
203 kappa_inv,
204 evals);
205
206 BB_ASSERT(batch_opening_claim.commitments.size() == MERGE_BATCHED_CLAIM_SIZE);
207 BB_ASSERT(batch_opening_claim.scalars.size() == MERGE_BATCHED_CLAIM_SIZE);
208
209 // KZG verifier - returns PairingPoints directly
210 PairingPoints pairing_points = PCS::reduce_verify_batch_opening_claim(std::move(batch_opening_claim), transcript);
211
212 return { pairing_points, merged_table_commitments, degree_check_verified, concatenation_verified };
213}
214
215// Explicit template instantiations
216template class MergeVerifier_<curve::BN254>;
219
220} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:67
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:107
bb::field< bb::Bn254FrParams > FF
Definition field.cpp:22
Unified verifier class for the Goblin ECC op queue transcript merge protocol.
typename Curve::AffineElement Commitment
typename Curve::ScalarField FF
BatchOpeningClaim< Curve > compute_shplonk_opening_claim(const std::vector< Commitment > &table_commitments, const Commitment &shplonk_batched_quotient, const FF &shplonk_opening_challenge, const std::vector< FF > &shplonk_batching_challenges, const FF &kappa, const FF &kappa_inv, const std::vector< FF > &evals) const
std::vector< FF > Proof
bool check_concatenation_identities(std::vector< FF > &evals, const FF &pow_kappa) const
std::conditional_t< Curve::is_stdlib_type, stdlib::recursion::PairingPoints< Curve >, bb::PairingPoints< Curve > > PairingPoints
VerificationResult verify_proof(const Proof &proof, const InputCommitments &input_commitments)
Verify the merge proof.
bool check_degree_identity(std::vector< FF > &evals, const FF &pow_kappa_minus_one, const std::vector< FF > &degree_check_challenges) const
std::array< Commitment, NUM_WIRES > TableCommitments
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)
An accumulator consisting of the Shplonk evaluation challenge and vectors of commitments and scalars.
Definition claim.hpp:169
Curve::ScalarField evaluation_point
Definition claim.hpp:172
std::vector< typename Curve::AffineElement > commitments
Definition claim.hpp:170
std::vector< typename Curve::ScalarField > scalars
Definition claim.hpp:171
Result of merge verification.