barretenberg
Loading...
Searching...
No Matches
transition_widget.hpp
1#pragma once
2
3#include <array>
4#include <cstddef>
5#include <set>
6#include <unordered_map>
7#include <vector>
8
9#include "../../types/prover_settings.hpp"
10#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp"
11#include "barretenberg/plonk/work_queue/work_queue.hpp"
12#include "barretenberg/polynomials/iterate_over_domain.hpp"
13
14using namespace proof_system;
15namespace proof_system::plonk {
16
17namespace widget {
18enum ChallengeIndex {
19 ALPHA,
20 BETA,
21 GAMMA,
22 ETA,
23 ZETA,
24 MAX_NUM_CHALLENGES,
25};
26
31#define CHALLENGE_BIT_ALPHA (1 << widget::ChallengeIndex::ALPHA)
32#define CHALLENGE_BIT_BETA (1 << widget::ChallengeIndex::BETA)
33#define CHALLENGE_BIT_GAMMA (1 << widget::ChallengeIndex::GAMMA)
34#define CHALLENGE_BIT_ETA (1 << widget::ChallengeIndex::ETA)
35#define CHALLENGE_BIT_ZETA (1 << widget::ChallengeIndex::ZETA)
36
37namespace containers {
38template <class Field, size_t num_widget_relations> struct challenge_array {
39 std::array<Field, ChallengeIndex::MAX_NUM_CHALLENGES> elements;
40 std::array<Field, num_widget_relations> alpha_powers;
41};
42
43template <class Field> using poly_array = std::array<std::pair<Field, Field>, PolynomialIndex::MAX_NUM_POLYNOMIALS>;
44
45template <class Field> struct poly_ptr_map {
46 std::unordered_map<PolynomialIndex, polynomial::pointer> coefficients;
47 size_t block_mask;
48 size_t index_shift;
49};
50
51} // namespace containers
52
63namespace getters {
72template <class Field, class Transcript, class Settings, size_t num_widget_relations> class BaseGetter {
73 protected:
75
76 public:
87 static challenge_array get_challenges(const Transcript& transcript,
88 const Field& alpha_base,
89 uint8_t required_challenges)
90
91 {
92 challenge_array result{};
112 auto add_challenge = [transcript,
113 &result](const auto label, const auto tag, const bool required, const size_t index = 0) {
114 ASSERT(!required || transcript.has_challenge(label));
115 if (transcript.has_challenge(label)) {
116 ASSERT(index < transcript.get_num_challenges(label));
117 result.elements[tag] = transcript.get_challenge_field_element(label, index);
118 } else {
119 result.elements[tag] = barretenberg::fr::random_element();
120 }
121 };
122 add_challenge("alpha", ALPHA, required_challenges & CHALLENGE_BIT_ALPHA);
123 add_challenge("beta", BETA, required_challenges & CHALLENGE_BIT_BETA);
124 add_challenge("beta", GAMMA, required_challenges & CHALLENGE_BIT_GAMMA, 1);
125 add_challenge("eta", ETA, required_challenges & CHALLENGE_BIT_ETA);
126 add_challenge("z", ZETA, required_challenges & CHALLENGE_BIT_ZETA);
127 result.alpha_powers[0] = alpha_base;
128 for (size_t i = 1; i < num_widget_relations; ++i) {
129 result.alpha_powers[i] = result.alpha_powers[i - 1] * result.elements[ALPHA];
130 }
131 return result;
132 }
133
134 static Field update_alpha(const challenge_array& challenges, const size_t num_independent_relations)
135 {
136 if (num_independent_relations == 0) {
137 return challenges.alpha_powers[0];
138 }
139 return challenges.alpha_powers[num_independent_relations - 1] * challenges.elements[ALPHA];
140 }
141};
142
152template <class Field, class Transcript, class Settings, size_t num_widget_relations>
153class EvaluationGetter : public BaseGetter<Field, Transcript, Settings, num_widget_relations> {
154 protected:
155 typedef containers::poly_array<Field> poly_array;
157
158 public:
170 template <bool use_shifted_evaluation, PolynomialIndex id>
171 inline static const Field& get_value(const poly_array& polynomials, const size_t = 0)
172 {
173 if constexpr (use_shifted_evaluation) {
174 return polynomials[id].second;
175 }
176 return polynomials[id].first;
177 }
186 const Transcript& transcript)
187 {
188 poly_array result{};
189 for (size_t i = 0; i < polynomial_manifest.size(); ++i) {
190 auto info = polynomial_manifest[i];
191 const std::string label(info.polynomial_label);
192 result[info.index].first = transcript.get_field_element(label);
193
194 if (info.requires_shifted_evaluation) {
195 result[info.index].second = transcript.get_field_element(label + "_omega");
196 } else {
197 result[info.index].second = 0;
198 }
199 }
200 return result;
201 }
202};
203
214template <typename Field, class Transcript, class Settings, size_t num_widget_relations>
215class FFTGetter : public BaseGetter<Field, Transcript, Settings, num_widget_relations> {
216 protected:
218
219 public:
220 static poly_ptr_map get_polynomials(proving_key* key, std::set<PolynomialIndex> required_polynomial_ids)
221 {
222 poly_ptr_map result;
223 std::string label_suffix;
224
225 // Set block_mask and index_shift
226 label_suffix = "_fft"; // coset evaluation form has suffix "_fft"
227 result.block_mask = key->large_domain.size - 1;
228 result.index_shift = 4; // for coset fft, x->ω*x corresponds to shift by 4
229
230 // Construct the container of pointers to the required polynomials
231 for (size_t i = 0; i < key->polynomial_manifest.size(); ++i) {
232 auto info_ = key->polynomial_manifest[i];
233 if (required_polynomial_ids.contains(info_.index)) {
234 std::string label = std::string(info_.polynomial_label) + label_suffix;
235 result.coefficients[info_.index] = key->polynomial_store.get(label).data();
236 }
237 }
238 return result;
239 }
240
241 template <EvaluationType evaluation_type, PolynomialIndex id>
242 inline static const Field& get_value(poly_ptr_map& polynomials, const size_t index = 0)
243 {
244 if constexpr (EvaluationType::SHIFTED == evaluation_type) {
245 return polynomials
246 .coefficients[id][(ptrdiff_t)((index + polynomials.index_shift) & polynomials.block_mask)];
247 }
248 // This ID should exist
249 ASSERT(polynomials.coefficients.count(id) > 0);
250 return polynomials.coefficients[id][(ptrdiff_t)index];
251 }
252};
253} // namespace getters
254
255template <class Field> class TransitionWidgetBase {
256 public:
257 TransitionWidgetBase(proving_key* _key = nullptr)
258 : key(_key){};
260 : key(other.key){};
262 : key(other.key){};
263 TransitionWidgetBase& operator=(const TransitionWidgetBase& other)
264 {
265 key = other.key;
266 return *this;
267 };
269 {
270 key = other.key;
271 return *this;
272 };
273 virtual ~TransitionWidgetBase() {}
274
275 virtual Field compute_quotient_contribution(const Field&, const transcript::StandardTranscript&) = 0;
276
277 public:
278 proving_key* key;
279};
280
281template <class Field, class Settings, template <typename, typename, typename> typename KernelBase>
283 protected:
284 static constexpr size_t num_independent_relations = KernelBase<int, int, int>::num_independent_relations;
286 typedef containers::poly_array<Field> poly_array;
288
289 public:
293
294 typedef KernelBase<Field, FFTGetter, poly_ptr_map> FFTKernel;
295 typedef KernelBase<Field, EvaluationGetter, poly_array> EvaluationKernel;
296
297 TransitionWidget(proving_key* _key = nullptr)
303 TransitionWidget& operator=(const TransitionWidget& other)
304 {
306 return *this;
307 };
308 TransitionWidget& operator=(TransitionWidget&& other)
309 {
311 return *this;
312 };
313
314 Field compute_quotient_contribution(const Field& alpha_base,
315 const transcript::StandardTranscript& transcript) override
316 {
318 ASSERT(key != nullptr);
319
320 // Get the set IDs for the polynomials required by the widget
321 auto& required_polynomial_ids = FFTKernel::get_required_polynomial_ids();
322
323 // Construct the map of pointers to the required polynomials
324 poly_ptr_map polynomials = FFTGetter::get_polynomials(key, required_polynomial_ids);
325
326 challenge_array challenges =
327 FFTGetter::get_challenges(transcript, alpha_base, FFTKernel::quotient_required_challenges);
328
329 ITERATE_OVER_DOMAIN_START(key->large_domain);
330 // populate split quotient components
331 Field& quotient_term =
332 key->quotient_polynomial_parts[i >> key->small_domain.log2_size][i & (key->circuit_size - 1)];
333 FFTKernel::accumulate_contribution(polynomials, challenges, quotient_term, i);
334 ITERATE_OVER_DOMAIN_END;
335
336 return FFTGetter::update_alpha(challenges, FFTKernel::num_independent_relations);
337 }
338};
339
340template <class Field, class Transcript, class Settings, template <typename, typename, typename> typename KernelBase>
342 protected:
343 static constexpr size_t num_independent_relations = KernelBase<int, int, int>::num_independent_relations;
345 typedef containers::poly_array<Field> poly_array;
347
348 public:
350 typedef KernelBase<Field, EvaluationGetter, poly_array> EvaluationKernel;
351
352 static Field compute_quotient_evaluation_contribution(typename Transcript::Key* key,
353 const Field& alpha_base,
354 const Transcript& transcript,
355 Field& quotient_numerator_eval)
356 {
357 poly_array polynomial_evaluations =
358 EvaluationGetter::get_polynomial_evaluations(key->polynomial_manifest, transcript);
359 challenge_array challenges =
360 EvaluationGetter::get_challenges(transcript, alpha_base, EvaluationKernel::quotient_required_challenges);
361
362 // Accumulate the contribution from the widget into the quotient
363 EvaluationKernel::accumulate_contribution(polynomial_evaluations, challenges, quotient_numerator_eval);
364
365 return EvaluationGetter::update_alpha(challenges, num_independent_relations);
366 }
367
368 static Field append_scalar_multiplication_inputs(typename Transcript::Key*,
369 const Field& alpha_base,
370 const Transcript& transcript,
371 std::map<std::string, Field>&)
372 {
374 alpha_base,
375 EvaluationKernel::quotient_required_challenges |
376 EvaluationKernel::update_required_challenges);
377 return EvaluationGetter::update_alpha(challenges, num_independent_relations);
378 }
379};
380} // namespace widget
381} // namespace proof_system::plonk
Definition: polynomial_manifest.hpp:142
Definition: transition_widget.hpp:341
Definition: transition_widget.hpp:255
Definition: transition_widget.hpp:282
Implements loading challenges from the transcript and computing powers of α, which is later used in w...
Definition: transition_widget.hpp:72
static challenge_array get_challenges(const Transcript &transcript, const Field &alpha_base, uint8_t required_challenges)
Definition: transition_widget.hpp:87
Implements loading polynomial openings from transcript in addition to BaseGetter's loading challenges...
Definition: transition_widget.hpp:153
static poly_array get_polynomial_evaluations(const polynomial_manifest &polynomial_manifest, const Transcript &transcript)
Return an array with poly.
Definition: transition_widget.hpp:185
static const Field & get_value(const poly_array &polynomials, const size_t=0)
Definition: transition_widget.hpp:171
Provides access to polynomials (monomial or coset FFT) for use in widgets.
Definition: transition_widget.hpp:215
Definition: transcript_wrappers.hpp:13
Definition: widget.bench.cpp:13
Definition: proving_key.hpp:38
Definition: transition_widget.hpp:45