Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
merge_prover.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_prover.hpp"
10
11namespace bb {
12
19 const MergeSettings settings,
20 const CommitmentKey& commitment_key,
21 const std::shared_ptr<Transcript>& transcript)
22 : op_queue(op_queue)
23 , transcript(transcript)
24 , settings(settings)
25{
26 // Merge the current subtable (for which a merge proof is being constructed) prior to
27 // procedeing with proving.
29 size_t last_subtable_size = op_queue->get_current_subtable_size();
30 op_queue->merge(settings, ECCOpQueue::OP_QUEUE_SIZE - last_subtable_size);
31
32 } else {
33 op_queue->merge(settings);
34 }
35
37 commitment_key.initialized() ? commitment_key : CommitmentKey(op_queue->get_ultra_ops_table_num_rows());
38};
39
41 const std::array<Polynomial, NUM_WIRES>& left_table, const std::vector<FF>& degree_check_challenges)
42{
43 Polynomial reversed_batched_left_tables(left_table[0].size());
44 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
45 reversed_batched_left_tables.add_scaled(left_table[idx], degree_check_challenges[idx]);
46 }
47 return reversed_batched_left_tables.reverse();
48}
49
51 const std::array<Polynomial, NUM_WIRES>& left_table,
52 const std::array<Polynomial, NUM_WIRES>& right_table,
53 const std::array<Polynomial, NUM_WIRES>& merged_table,
54 const std::vector<FF>& shplonk_batching_challenges,
55 const FF& kappa,
56 const FF& kappa_inv,
57 const Polynomial& reversed_batched_left_tables,
58 const std::vector<FF>& evals)
59{
60 // Q such that Q·(X - κ)·(X - κ⁻¹) =
61 // (X - κ⁻¹)·(Σᵢ βᵢ(Lᵢ - lᵢ) + Σᵢ βᵢ(Rᵢ - rᵢ) + Σᵢ βᵢ(Mᵢ - mᵢ)) + (X - κ)·β(G - g)
62 Polynomial shplonk_batched_quotient(merged_table[0].size());
63
64 // Handle polynomials opened at κ
65 for (size_t idx_table = 0; idx_table < 3; idx_table++) {
66 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
67 FF challenge = shplonk_batching_challenges[(idx_table * NUM_WIRES) + idx];
68 FF eval = evals[(idx_table * NUM_WIRES) + idx];
69 if (idx_table == 0) {
70 // Q += Lᵢ·βᵢ
71 shplonk_batched_quotient.add_scaled(left_table[idx], challenge);
72 } else if (idx_table == 1) {
73 // Q += Rᵢ·βᵢ
74 shplonk_batched_quotient.add_scaled(right_table[idx], challenge);
75 } else {
76 // Q += Mᵢ·βᵢ
77 shplonk_batched_quotient.add_scaled(merged_table[idx], challenge);
78 }
79 // Q -= eval·βᵢ
80 shplonk_batched_quotient.at(0) -= challenge * eval;
81 }
82 }
83 // Q /= (X - κ)
84 shplonk_batched_quotient.factor_roots(kappa);
85
86 // Q += (G - g)/(X - κ⁻¹)·β
87 Polynomial reversed_batched_left_tables_copy(reversed_batched_left_tables);
88 reversed_batched_left_tables_copy.at(0) -= evals.back();
89 reversed_batched_left_tables_copy.factor_roots(kappa_inv);
90 shplonk_batched_quotient.add_scaled(reversed_batched_left_tables_copy, shplonk_batching_challenges.back());
91
92 return shplonk_batched_quotient;
93}
94
96 Polynomial& shplonk_batched_quotient,
97 const FF& shplonk_opening_challenge,
98 const std::array<Polynomial, NUM_WIRES>& left_table,
99 const std::array<Polynomial, NUM_WIRES>& right_table,
100 const std::array<Polynomial, NUM_WIRES>& merged_table,
101 const std::vector<FF>& shplonk_batching_challenges,
102 const FF& kappa,
103 const FF& kappa_inv,
104 Polynomial& reversed_batched_left_tables,
105 const std::vector<FF>& evals)
106{
107 // Q' (partially evaluated batched quotient) =
108 // -Q·(z - κ) + Σᵢ βᵢ(Lᵢ - lᵢ) + Σᵢ βᵢ(Rᵢ - rᵢ) + Σᵢ βᵢ(Mᵢ - mᵢ) + (z - κ)/(z - κ⁻¹)·β(G - g)
109 Polynomial shplonk_partially_evaluated_batched_quotient(std::move(shplonk_batched_quotient));
110 shplonk_partially_evaluated_batched_quotient *= -(shplonk_opening_challenge - kappa);
111
112 // Handle polynomials opened at κ
113 for (size_t idx_table = 0; idx_table < 3; idx_table++) {
114 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
115 FF challenge = shplonk_batching_challenges[(idx_table * NUM_WIRES) + idx];
116 FF eval = evals[(idx_table * NUM_WIRES) + idx];
117 if (idx_table == 0) {
118 // Q' += Lᵢ·βᵢ
119 shplonk_partially_evaluated_batched_quotient.add_scaled(left_table[idx], challenge);
120 } else if (idx_table == 1) {
121 // Q' += Rᵢ·βᵢ
122 shplonk_partially_evaluated_batched_quotient.add_scaled(right_table[idx], challenge);
123 } else {
124 // Q' += Mᵢ·βᵢ
125 shplonk_partially_evaluated_batched_quotient.add_scaled(merged_table[idx], challenge);
126 }
127 // Q' -= eval·βᵢ
128 shplonk_partially_evaluated_batched_quotient.at(0) -= challenge * eval;
129 }
130 }
131
132 // Q' += (G - g)·(z - κ)/(z - κ⁻¹)·β
133 reversed_batched_left_tables.at(0) -= evals.back();
134 shplonk_partially_evaluated_batched_quotient.add_scaled(reversed_batched_left_tables,
135 shplonk_batching_challenges.back() *
136 (shplonk_opening_challenge - kappa) *
137 (shplonk_opening_challenge - kappa_inv).invert());
138
139 OpeningClaim shplonk_opening_claim = { .polynomial = std::move(shplonk_partially_evaluated_batched_quotient),
140 .opening_pair = { shplonk_opening_challenge, FF(0) } };
141
142 return shplonk_opening_claim;
143}
144
157{
158
161 std::array<Polynomial, NUM_WIRES> merged_table = op_queue->construct_ultra_ops_table_columns(); // T
162 std::array<Polynomial, NUM_WIRES> left_table_reversed;
163
165 left_table = op_queue->construct_current_ultra_ops_subtable_columns(); // t
166 right_table = op_queue->construct_previous_ultra_ops_table_columns(); // T_prev
167 } else {
168 left_table = op_queue->construct_previous_ultra_ops_table_columns(); // T_prev
169 right_table = op_queue->construct_current_ultra_ops_subtable_columns(); // t
170 }
171
172 // Send shift_size to the verifier
173 const size_t shift_size = left_table[0].size();
174 transcript->send_to_verifier("shift_size", static_cast<uint32_t>(shift_size));
175
176 // Compute commitments [M_j] and send to the verifier
177 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
178 transcript->send_to_verifier("MERGED_TABLE_" + std::to_string(idx),
179 pcs_commitment_key.commit(merged_table[idx]));
180 }
181
182 // Generate degree check batching challenges, batch polynomials, compute reversed polynomial, send commitment to the
183 // verifier
184 std::vector<FF> degree_check_challenges = transcript->template get_challenges<FF>(labels_degree_check);
185 Polynomial reversed_batched_left_tables = compute_degree_check_polynomial(left_table, degree_check_challenges);
186 transcript->send_to_verifier("REVERSED_BATCHED_LEFT_TABLES",
187 pcs_commitment_key.commit(reversed_batched_left_tables));
188
189 // Compute batching challenges
190 std::vector<FF> shplonk_batching_challenges =
191 transcript->template get_challenges<FF>(labels_shplonk_batching_challenges);
192
193 // Compute evaluation challenge
194 const FF kappa = transcript->template get_challenge<FF>("kappa");
195 const FF kappa_inv = kappa.invert();
196
197 // Send evaluations of [Lᵢ], [Rᵢ], [Mᵢ] at κ
198 std::vector<FF> evals;
199 evals.reserve((3 * NUM_WIRES) + 1);
200 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
201 evals.emplace_back(left_table[idx].evaluate(kappa));
202 transcript->send_to_verifier("LEFT_TABLE_EVAL_" + std::to_string(idx), evals.back());
203 }
204 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
205 evals.emplace_back(right_table[idx].evaluate(kappa));
206 transcript->send_to_verifier("RIGHT_TABLE_EVAL_" + std::to_string(idx), evals.back());
207 }
208 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
209 evals.emplace_back(merged_table[idx].evaluate(kappa));
210 transcript->send_to_verifier("MERGED_TABLE_EVAL_" + std::to_string(idx), evals.back());
211 }
212
213 // Send evaluation of G at 1/κ
214 evals.emplace_back(reversed_batched_left_tables.evaluate(kappa_inv));
215 transcript->send_to_verifier("REVERSED_BATCHED_LEFT_TABLES_EVAL", evals.back());
216
217 // Compute Shplonk batched quotient
218 Polynomial shplonk_batched_quotient = compute_shplonk_batched_quotient(left_table,
219 right_table,
220 merged_table,
221 shplonk_batching_challenges,
222 kappa,
223 kappa_inv,
224 reversed_batched_left_tables,
225 evals);
226
227 transcript->send_to_verifier("SHPLONK_BATCHED_QUOTIENT", pcs_commitment_key.commit(shplonk_batched_quotient));
228
229 // Generate Shplonk opening challenge
230 FF shplonk_opening_challenge = transcript->template get_challenge<FF>("shplonk_opening_challenge");
231
232 // Compute Shplonk opening claim
233 OpeningClaim shplonk_opening_claim = compute_shplonk_opening_claim(shplonk_batched_quotient,
234 shplonk_opening_challenge,
235 left_table,
236 right_table,
237 merged_table,
238 shplonk_batching_challenges,
239 kappa,
240 kappa_inv,
241 reversed_batched_left_tables,
242 evals);
243
244 // KZG prover
246
247 return transcript->export_proof();
248}
249} // namespace bb
CommitmentKey object over a pairing group 𝔾₁.
Commitment commit(PolynomialSpan< const Fr > polynomial) const
Uses the ProverSRS to create a commitment to p(X)
bool initialized() const
Checks the commitment key is properly initialized.
static const size_t OP_QUEUE_SIZE
static void compute_opening_proof(const CK &ck, const ProverOpeningClaim< Curve > &opening_claim, const std::shared_ptr< Transcript > &prover_trancript)
Computes the KZG commitment to an opening proof polynomial at a single evaluation point.
Definition kzg.hpp:43
static constexpr size_t NUM_WIRES
Curve::ScalarField FF
std::shared_ptr< ECCOpQueue > op_queue
std::vector< FF > MergeProof
MergeSettings settings
BB_PROFILE MergeProof construct_proof()
Prove proper construction of the aggregate Goblin ECC op queue polynomials T_j.
std::vector< std::string > labels_degree_check
static OpeningClaim compute_shplonk_opening_claim(Polynomial &shplonk_batched_quotient, const FF &shplonk_opening_challenge, const std::array< Polynomial, NUM_WIRES > &left_table, const std::array< Polynomial, NUM_WIRES > &right_table, const std::array< Polynomial, NUM_WIRES > &merged_table, const std::vector< FF > &shplonk_batching_challenges, const FF &kappa, const FF &kappa_inv, Polynomial &reversed_batched_left_tables, const std::vector< FF > &evals)
Compute the partially evaluated Shplonk batched quotient and the resulting opening claim.
std::vector< std::string > labels_shplonk_batching_challenges
MergeProver(const std::shared_ptr< ECCOpQueue > &op_queue, const MergeSettings settings=MergeSettings::PREPEND, const CommitmentKey &commitment_key=CommitmentKey(), const std::shared_ptr< Transcript > &transcript=std::make_shared< Transcript >())
Create MergeProver.
std::shared_ptr< Transcript > transcript
CommitmentKey pcs_commitment_key
static Polynomial compute_shplonk_batched_quotient(const std::array< Polynomial, NUM_WIRES > &left_table, const std::array< Polynomial, NUM_WIRES > &right_table, const std::array< Polynomial, NUM_WIRES > &merged_table, const std::vector< FF > &shplonk_batching_challenges, const FF &kappa, const FF &kappa_inv, const Polynomial &reversed_batched_left_tables, const std::vector< FF > &evals)
Compute the batched Shplonk quotient polynomial.
static Polynomial compute_degree_check_polynomial(const std::array< Polynomial, NUM_WIRES > &left_table, const std::vector< FF > &degree_check_challenges)
Compute the batched polynomial for the degree check.
bb::CommitmentKey< Curve > CommitmentKey
Fr evaluate(const Fr &z, size_t target_size) const
Polynomial reverse() const
Returns the polynomial equal to the reverse of self.
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
void add_scaled(PolynomialSpan< const Fr > other, Fr scaling_factor) &
adds the polynomial q(X) 'other', multiplied by a scaling factor.
void factor_roots(const Fr &root)
Divides p(X) by (X-r) in-place. Assumes that p(rⱼ)=0 for all j.
Polynomial p and an opening pair (r,v) such that p(r) = v.
Definition claim.hpp:34
Polynomial polynomial
Definition claim.hpp:39
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
MergeSettings
The MergeSettings define whether an current subtable will be added at the beginning (PREPEND) or at t...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
constexpr field invert() const noexcept