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: Complete, auditors: [Sergei], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#include "merge_prover.hpp"
10
11namespace bb {
12
19 std::shared_ptr<Transcript> transcript,
20 MergeSettings settings)
21 : transcript(std::move(transcript))
22 , op_queue(op_queue)
23 , settings(settings)
24{
25 // Merge the current subtable (for which a merge proof is being constructed) prior to
26 // procedeing with proving.
28 size_t last_subtable_size = op_queue->get_current_subtable_size();
29 op_queue->merge(settings, ECCOpQueue::OP_QUEUE_SIZE - last_subtable_size);
30
31 } else {
32 op_queue->merge(settings);
33 }
34
35 pcs_commitment_key = CommitmentKey(op_queue->get_ultra_ops_table_num_rows());
36};
37
39 const std::array<Polynomial, NUM_WIRES>& left_table, const std::vector<FF>& degree_check_challenges)
40{
41 Polynomial reversed_batched_left_tables(left_table[0].size());
42 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
43 reversed_batched_left_tables.add_scaled(left_table[idx], degree_check_challenges[idx]);
44 }
45 return reversed_batched_left_tables.reverse();
46}
47
49 const std::array<Polynomial, NUM_WIRES>& left_table,
50 const std::array<Polynomial, NUM_WIRES>& right_table,
51 const std::array<Polynomial, NUM_WIRES>& merged_table,
52 const std::vector<FF>& shplonk_batching_challenges,
53 const FF& kappa,
54 const FF& kappa_inv,
55 const Polynomial& reversed_batched_left_tables,
56 const std::vector<FF>& evals)
57{
58 // Q such that Q·(X - κ)·(X - κ⁻¹) =
59 // (X - κ⁻¹)·(Σᵢ βᵢ(Lᵢ - lᵢ) + Σᵢ βᵢ(Rᵢ - rᵢ) + Σᵢ βᵢ(Mᵢ - mᵢ)) + (X - κ)·β(G - g)
60 Polynomial shplonk_batched_quotient(merged_table[0].size());
61
62 // Handle polynomials opened at κ
63 for (size_t idx_table = 0; idx_table < 3; idx_table++) {
64 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
65 FF challenge = shplonk_batching_challenges[(idx_table * NUM_WIRES) + idx];
66 FF eval = evals[(idx_table * NUM_WIRES) + idx];
67 if (idx_table == 0) {
68 // Q += Lᵢ·βᵢ
69 shplonk_batched_quotient.add_scaled(left_table[idx], challenge);
70 } else if (idx_table == 1) {
71 // Q += Rᵢ·βᵢ
72 shplonk_batched_quotient.add_scaled(right_table[idx], challenge);
73 } else {
74 // Q += Mᵢ·βᵢ
75 shplonk_batched_quotient.add_scaled(merged_table[idx], challenge);
76 }
77 // Q -= eval·βᵢ
78 shplonk_batched_quotient.at(0) -= challenge * eval;
79 }
80 }
81 // Q /= (X - κ)
82 shplonk_batched_quotient.factor_roots(kappa);
83
84 // Q += (G - g)/(X - κ⁻¹)·β
85 Polynomial reversed_batched_left_tables_copy(reversed_batched_left_tables);
86 reversed_batched_left_tables_copy.at(0) -= evals.back();
87 reversed_batched_left_tables_copy.factor_roots(kappa_inv);
88 shplonk_batched_quotient.add_scaled(reversed_batched_left_tables_copy, shplonk_batching_challenges.back());
89
90 return shplonk_batched_quotient;
91}
92
94 Polynomial& shplonk_batched_quotient,
95 const FF& shplonk_opening_challenge,
96 const std::array<Polynomial, NUM_WIRES>& left_table,
97 const std::array<Polynomial, NUM_WIRES>& right_table,
98 const std::array<Polynomial, NUM_WIRES>& merged_table,
99 const std::vector<FF>& shplonk_batching_challenges,
100 const FF& kappa,
101 const FF& kappa_inv,
102 Polynomial& reversed_batched_left_tables,
103 const std::vector<FF>& evals)
104{
105 // Q' (partially evaluated batched quotient) =
106 // -Q·(z - κ) + Σᵢ βᵢ(Lᵢ - lᵢ) + Σᵢ βᵢ(Rᵢ - rᵢ) + Σᵢ βᵢ(Mᵢ - mᵢ) + (z - κ)/(z - κ⁻¹)·β(G - g)
107 Polynomial shplonk_partially_evaluated_batched_quotient(std::move(shplonk_batched_quotient));
108 shplonk_partially_evaluated_batched_quotient *= -(shplonk_opening_challenge - kappa);
109
110 // Handle polynomials opened at κ
111 for (size_t idx_table = 0; idx_table < 3; idx_table++) {
112 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
113 FF challenge = shplonk_batching_challenges[(idx_table * NUM_WIRES) + idx];
114 FF eval = evals[(idx_table * NUM_WIRES) + idx];
115 if (idx_table == 0) {
116 // Q' += Lᵢ·βᵢ
117 shplonk_partially_evaluated_batched_quotient.add_scaled(left_table[idx], challenge);
118 } else if (idx_table == 1) {
119 // Q' += Rᵢ·βᵢ
120 shplonk_partially_evaluated_batched_quotient.add_scaled(right_table[idx], challenge);
121 } else {
122 // Q' += Mᵢ·βᵢ
123 shplonk_partially_evaluated_batched_quotient.add_scaled(merged_table[idx], challenge);
124 }
125 // Q' -= eval·βᵢ
126 shplonk_partially_evaluated_batched_quotient.at(0) -= challenge * eval;
127 }
128 }
129
130 // Q' += (G - g)·(z - κ)/(z - κ⁻¹)·β
131 reversed_batched_left_tables.at(0) -= evals.back();
132 shplonk_partially_evaluated_batched_quotient.add_scaled(reversed_batched_left_tables,
133 shplonk_batching_challenges.back() *
134 (shplonk_opening_challenge - kappa) *
135 (shplonk_opening_challenge - kappa_inv).invert());
136
137 OpeningClaim shplonk_opening_claim = { .polynomial = std::move(shplonk_partially_evaluated_batched_quotient),
138 .opening_pair = { shplonk_opening_challenge, FF(0) } };
139
140 return shplonk_opening_claim;
141}
142
155{
156
159 std::array<Polynomial, NUM_WIRES> merged_table = op_queue->construct_ultra_ops_table_columns(); // T
160 std::array<Polynomial, NUM_WIRES> left_table_reversed;
161
163 left_table = op_queue->construct_current_ultra_ops_subtable_columns(); // t
164 right_table = op_queue->construct_previous_ultra_ops_table_columns(); // T_prev
165 } else {
166 left_table = op_queue->construct_previous_ultra_ops_table_columns(); // T_prev
167 right_table = op_queue->construct_current_ultra_ops_subtable_columns(); // t
168 }
169
170 // Send shift_size to the verifier
171 const size_t shift_size = left_table[0].size();
172 transcript->send_to_verifier("shift_size", static_cast<uint32_t>(shift_size));
173
174 // Compute commitments [M_j] and send to the verifier
175 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
176 transcript->send_to_verifier("MERGED_TABLE_" + std::to_string(idx),
177 pcs_commitment_key.commit(merged_table[idx]));
178 }
179
180 // Generate degree check batching challenges, batch polynomials, compute reversed polynomial, send commitment to the
181 // verifier
182 std::vector<FF> degree_check_challenges = transcript->template get_challenges<FF>(labels_degree_check);
183 Polynomial reversed_batched_left_tables = compute_degree_check_polynomial(left_table, degree_check_challenges);
184 transcript->send_to_verifier("REVERSED_BATCHED_LEFT_TABLES",
185 pcs_commitment_key.commit(reversed_batched_left_tables));
186
187 // Compute batching challenges
188 std::vector<FF> shplonk_batching_challenges =
189 transcript->template get_challenges<FF>(labels_shplonk_batching_challenges);
190
191 // Compute evaluation challenge
192 const FF kappa = transcript->template get_challenge<FF>("kappa");
193 const FF kappa_inv = kappa.invert();
194
195 // Send evaluations of [Lᵢ], [Rᵢ], [Mᵢ] at κ
196 std::vector<FF> evals;
197 evals.reserve((3 * NUM_WIRES) + 1);
198 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
199 evals.emplace_back(left_table[idx].evaluate(kappa));
200 transcript->send_to_verifier("LEFT_TABLE_EVAL_" + std::to_string(idx), evals.back());
201 }
202 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
203 evals.emplace_back(right_table[idx].evaluate(kappa));
204 transcript->send_to_verifier("RIGHT_TABLE_EVAL_" + std::to_string(idx), evals.back());
205 }
206 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
207 evals.emplace_back(merged_table[idx].evaluate(kappa));
208 transcript->send_to_verifier("MERGED_TABLE_EVAL_" + std::to_string(idx), evals.back());
209 }
210
211 // Send evaluation of G at 1/κ
212 evals.emplace_back(reversed_batched_left_tables.evaluate(kappa_inv));
213 transcript->send_to_verifier("REVERSED_BATCHED_LEFT_TABLES_EVAL", evals.back());
214
215 // Compute Shplonk batched quotient
216 Polynomial shplonk_batched_quotient = compute_shplonk_batched_quotient(left_table,
217 right_table,
218 merged_table,
219 shplonk_batching_challenges,
220 kappa,
221 kappa_inv,
222 reversed_batched_left_tables,
223 evals);
224
225 transcript->send_to_verifier("SHPLONK_BATCHED_QUOTIENT", pcs_commitment_key.commit(shplonk_batched_quotient));
226
227 // Generate Shplonk opening challenge
228 FF shplonk_opening_challenge = transcript->template get_challenge<FF>("shplonk_opening_challenge");
229
230 // Compute Shplonk opening claim
231 OpeningClaim shplonk_opening_claim = compute_shplonk_opening_claim(shplonk_batched_quotient,
232 shplonk_opening_challenge,
233 left_table,
234 right_table,
235 merged_table,
236 shplonk_batching_challenges,
237 kappa,
238 kappa_inv,
239 reversed_batched_left_tables,
240 evals);
241
242 // KZG prover
244
245 return transcript->export_proof();
246}
247} // namespace bb
Commitment commit(PolynomialSpan< const Fr > polynomial) const
Uses the ProverSRS to create a commitment to p(X)
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:42
static constexpr size_t NUM_WIRES
MergeProver(const std::shared_ptr< ECCOpQueue > &op_queue, std::shared_ptr< Transcript > transcript, MergeSettings settings=MergeSettings::PREPEND)
Create MergeProver.
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
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
void add_scaled(PolynomialSpan< const Fr > other, const Fr &scaling_factor)
adds the polynomial q(X) 'other', multiplied by a scaling factor.
Fr evaluate(const Fr &z) 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 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:36
Polynomial polynomial
Definition claim.hpp:41
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...
STL namespace.
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