Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
protogalaxy_prover_impl.hpp
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#pragma once
15
16namespace bb {
17template <IsUltraOrMegaHonk Flavor, size_t NUM_KEYS>
19 std::shared_ptr<DeciderVK> vk,
20 const std::string& domain_separator)
21{
22
23 PROFILE_THIS_NAME("ProtogalaxyProver::run_oink_prover_on_one_incomplete_key");
24 OinkProver<typename DeciderProvingKeys::Flavor> oink_prover(key, vk->vk, transcript, domain_separator + '_');
25 oink_prover.prove();
26}
27
28template <IsUltraOrMegaHonk Flavor, size_t NUM_KEYS>
30{
31 PROFILE_THIS_NAME("ProtogalaxyProver_::run_oink_prover_on_each_incomplete_key");
32 size_t idx = 0;
33 auto& key = keys_to_fold[0];
34 auto domain_separator = std::to_string(idx);
35 auto& verifier_accum = vks_to_fold[0];
36 if (!key->is_complete) {
37 run_oink_prover_on_one_incomplete_key(key, verifier_accum, domain_separator);
38 // Get the gate challenges for sumcheck/combiner computation
39 key->gate_challenges =
40 transcript->template get_powers_of_challenge<FF>(domain_separator + "_gate_challenge", CONST_PG_LOG_N);
41 }
42
43 idx++;
44
45 for (auto it = keys_to_fold.begin() + 1; it != keys_to_fold.end(); it++, idx++) {
46 auto key = *it;
47 auto domain_separator = std::to_string(idx);
48 run_oink_prover_on_one_incomplete_key(key, vks_to_fold[idx], domain_separator);
49 }
50
51 accumulator = keys_to_fold[0];
52};
53
54template <IsUltraOrMegaHonk Flavor, size_t NUM_KEYS>
57{
58 PROFILE_THIS_NAME("ProtogalaxyProver_::perturbator_round");
59
60 const std::vector<FF> deltas = transcript->template get_powers_of_challenge<FF>("delta", CONST_PG_LOG_N);
61 // An honest prover with valid initial key computes that the perturbator is 0 in the first round
62 const Polynomial<FF> perturbator = accumulator->from_first_instance
63 ? pg_internal.compute_perturbator(accumulator, deltas)
64 : Polynomial<FF>(CONST_PG_LOG_N + 1);
65 // Prover doesn't send the constant coefficient of F because this is supposed to be equal to the target sum of
66 // the accumulator which the folding verifier has from the previous iteration.
67 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1087): Verifier circuit for first IVC step is
68 // different
69 for (size_t idx = 1; idx <= CONST_PG_LOG_N; idx++) {
70 transcript->send_to_verifier("perturbator_" + std::to_string(idx), perturbator[idx]);
71 }
72
73 return std::make_tuple(deltas, perturbator);
74};
75
76template <IsUltraOrMegaHonk Flavor, size_t NUM_KEYS>
80 typename Flavor::FF,
83 const std::vector<FF>& deltas,
84 const DeciderProvingKeys& keys)
85{
86 PROFILE_THIS_NAME("ProtogalaxyProver_::combiner_quotient_round");
87
88 const FF perturbator_challenge = transcript->template get_challenge<FF>("perturbator_challenge");
89
90 const std::vector<FF> updated_gate_challenges =
91 update_gate_challenges(perturbator_challenge, gate_challenges, deltas);
92 const UnivariateSubrelationSeparators alphas = PGInternal::compute_and_extend_alphas(keys);
93 const GateSeparatorPolynomial<FF> gate_separators{ updated_gate_challenges, CONST_PG_LOG_N };
94 const UnivariateRelationParameters relation_parameters =
95 PGInternal::template compute_extended_relation_parameters<UnivariateRelationParameters>(keys);
96
97 // Note: {} is required to initialize the tuple contents. Otherwise the univariates contain garbage.
98 TupleOfTuplesOfUnivariates accumulators{};
99 auto combiner = pg_internal.compute_combiner(keys, gate_separators, relation_parameters, alphas, accumulators);
100
101 const FF perturbator_evaluation = perturbator.evaluate(perturbator_challenge);
102 const CombinerQuotient combiner_quotient = PGInternal::compute_combiner_quotient(perturbator_evaluation, combiner);
103
104 for (size_t idx = NUM_KEYS; idx < DeciderProvingKeys::BATCHED_EXTENDED_LENGTH; idx++) {
105 transcript->send_to_verifier("combiner_quotient_" + std::to_string(idx), combiner_quotient.value_at(idx));
106 }
107
108 return std::make_tuple(
109 updated_gate_challenges, alphas, relation_parameters, perturbator_evaluation, combiner_quotient);
110}
111
115template <IsUltraOrMegaHonk Flavor, size_t NUM_KEYS>
117 const DeciderProvingKeys& keys,
118 const CombinerQuotient& combiner_quotient,
120 const UnivariateRelationParameters& univariate_relation_parameters,
121 const FF& perturbator_evaluation)
122{
123 PROFILE_THIS_NAME("ProtogalaxyProver_::update_target_sum_and_fold");
124
125 std::shared_ptr<DeciderPK> accumulator = keys[0];
126 std::shared_ptr<DeciderPK> incoming = keys[1];
127 accumulator->from_first_instance = true;
128
129 // At this point the virtual sizes of the polynomials should already agree
130 BB_ASSERT_EQ(accumulator->polynomials.w_l.virtual_size(), incoming->polynomials.w_l.virtual_size());
131
132 const FF combiner_challenge = transcript->template get_challenge<FF>("combiner_quotient_challenge");
133
134 // Compute the next target sum (for its own use; verifier must compute its own values)
135 auto [vanishing_polynomial_at_challenge, lagranges] =
136 PGInternal::compute_vanishing_polynomial_and_lagranges(combiner_challenge);
137 accumulator->target_sum = perturbator_evaluation * lagranges[0] +
138 vanishing_polynomial_at_challenge * combiner_quotient.evaluate(combiner_challenge);
139
140 // Check whether the incoming key has a larger trace overflow than the accumulator. If so, the memory structure of
141 // the accumulator polynomials will not be sufficient to contain the contribution from the incoming polynomials. The
142 // solution is to simply reverse the order or the terms in the linear combination by swapping the polynomials and
143 // the lagrange coefficients between the accumulator and the incoming key.
144 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1417): make this swapping logic more robust.
145 if (incoming->get_overflow_size() > accumulator->get_overflow_size()) {
146 std::swap(accumulator->polynomials, incoming->polynomials); // swap the polys
147 std::swap(lagranges[0], lagranges[1]); // swap the lagrange coefficients so the sum is unchanged
148 accumulator->set_dyadic_size(incoming->dyadic_size()); // update dyadic size of accumulator
149 accumulator->set_overflow_size(incoming->get_overflow_size()); // swap overflow size
150 }
151
152 // Fold the proving key polynomials
153 for (auto& poly : accumulator->polynomials.get_unshifted()) {
154 poly *= lagranges[0];
155 }
156 for (auto [acc_poly, key_poly] :
157 zip_view(accumulator->polynomials.get_unshifted(), incoming->polynomials.get_unshifted())) {
158 acc_poly.add_scaled(key_poly, lagranges[1]);
159 }
160
161 // Evaluate the combined batching α_i univariate at challenge to obtain next α_i and send it to the
162 // verifier, where i ∈ {0,...,NUM_SUBRELATIONS - 1}
163 for (auto [folded_alpha, key_alpha] : zip_view(accumulator->alphas, alphas)) {
164 folded_alpha = key_alpha.evaluate(combiner_challenge);
165 }
166
167 // Evaluate each relation parameter univariate at challenge to obtain the folded relation parameters.
168 for (auto [univariate, value] :
169 zip_view(univariate_relation_parameters.get_to_fold(), accumulator->relation_parameters.get_to_fold())) {
170 value = univariate.evaluate(combiner_challenge);
171 }
172}
173
174template <IsUltraOrMegaHonk Flavor, size_t NUM_KEYS> FoldingResult<Flavor> ProtogalaxyProver_<Flavor, NUM_KEYS>::prove()
175{
176 PROFILE_THIS_NAME("ProtogalaxyProver::prove");
177
178 // Ensure keys are all of the same size
179 size_t max_circuit_size = 0;
180 for (size_t idx = 0; idx < NUM_KEYS; ++idx) {
181 max_circuit_size = std::max(max_circuit_size, keys_to_fold[idx]->dyadic_size());
182 }
183 for (size_t idx = 0; idx < NUM_KEYS; ++idx) {
184 if (keys_to_fold[idx]->dyadic_size() != max_circuit_size) {
185 info("ProtogalaxyProver: circuit size mismatch - increasing virtual size of key ",
186 idx,
187 " from ",
188 keys_to_fold[idx]->dyadic_size(),
189 " to ",
190 max_circuit_size);
191 keys_to_fold[idx]->polynomials.increase_polynomials_virtual_size(max_circuit_size);
192 }
193 }
194
195 run_oink_prover_on_each_incomplete_key();
196 vinfo("oink prover on each incomplete key");
197
198 std::tie(deltas, perturbator) = perturbator_round(accumulator);
199 vinfo("perturbator round");
200
201 std::tie(accumulator->gate_challenges, alphas, relation_parameters, perturbator_evaluation, combiner_quotient) =
202 combiner_quotient_round(accumulator->gate_challenges, deltas, keys_to_fold);
203 vinfo("combiner quotient round");
204
205 update_target_sum_and_fold(keys_to_fold, combiner_quotient, alphas, relation_parameters, perturbator_evaluation);
206 vinfo("folded");
207
208 return FoldingResult<Flavor>{ .accumulator = keys_to_fold[0], .proof = transcript->export_proof() };
209}
210} // namespace bb
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:59
Curve::ScalarField FF
Class for all the oink rounds, which are shared between the folding prover and ultra prover.
void prove()
Oink Prover function that runs all the rounds of the verifier.
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
BB_PROFILE FoldingResult< Flavor > prove()
Execute the folding prover.
void run_oink_prover_on_one_incomplete_key(std::shared_ptr< DeciderPK >, std::shared_ptr< DeciderVK >, const std::string &domain_separator)
For each key produced by a circuit, prior to folding, we need to complete the computation of its prov...
void update_target_sum_and_fold(const DeciderProvingKeys &keys, const CombinerQuotient &combiner_quotient, const UnivariateSubrelationSeparators &alphas, const UnivariateRelationParameters &univariate_relation_parameters, const FF &perturbator_evaluation)
Steps 12 - 13 of the paper plus the prover folding work.
std::array< Univariate< FF, DeciderProvingKeys::BATCHED_EXTENDED_LENGTH >, Flavor::NUM_SUBRELATIONS - 1 > UnivariateSubrelationSeparators
std::tuple< std::vector< FF >, UnivariateSubrelationSeparators, UnivariateRelationParameters, FF, CombinerQuotient > combiner_quotient_round(const std::vector< FF > &gate_challenges, const std::vector< FF > &deltas, const DeciderProvingKeys &keys)
Steps 6 - 11 of the paper.
typename Flavor::template ProtogalaxyTupleOfTuplesOfUnivariates< NUM_KEYS > TupleOfTuplesOfUnivariates
std::tuple< std::vector< FF >, Polynomial< FF > > perturbator_round(const std::shared_ptr< const DeciderPK > &accumulator)
Steps 2 - 5 of the paper.
void run_oink_prover_on_each_incomplete_key()
Create inputs to folding protocol (an Oink interaction).
A univariate polynomial represented by its values on {domain_start, domain_start + 1,...
Fr & value_at(size_t i)
Fr evaluate(const Fr &u) const
Evaluate a univariate at a point u not known at compile time and assumed not to be in the domain (els...
constexpr size_t NUM_KEYS
void vinfo(Args... args)
Definition log.hpp:76
void info(Args... args)
Definition log.hpp:70
Entry point for Barretenberg command-line interface.
std::vector< FF > update_gate_challenges(const FF &perturbator_challenge, const std::vector< FF > &gate_challenges, const std::vector< FF > &init_challenges)
Compute the gate challenges used in the combiner calculation.
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
#define PROFILE_THIS_NAME(name)
Definition op_count.hpp:16
The result of running the Protogalaxy prover containing a new accumulator as well as the proof data t...
std::shared_ptr< DeciderProvingKey_< Flavor > > accumulator
Implementation of the methods for the -polynomials used in Protogalaxy and -polynomials used in Sumch...
Container for parameters used by the grand product (permutation, lookup) Honk relations.
RefArray< T, NUM_TO_FOLD > get_to_fold()