Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
generic_lookup_relation.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Completed, auditors: [Federico], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
8#include <array>
9#include <tuple>
10
15
16namespace bb {
17
30
56template <typename Settings_> class LookupPolynomialStructure {
57 private:
58 static constexpr size_t NUM_LOOKUP_TERMS = Settings_::NUM_LOOKUP_TERMS;
59 static constexpr size_t NUM_TABLE_TERMS = Settings_::NUM_TABLE_TERMS;
60
61 static constexpr size_t INVERSE_POLYNOMIAL_INDEX = 0;
62 static constexpr size_t LOOKUP_READ_COUNT_START_POLYNOMIAL_INDEX = 1;
67 static constexpr size_t LOOKUP_TERM_START_POLYNOMIAL_INDEX =
69
70 public:
71 static constexpr size_t get_inverse_polynomial_index() { return INVERSE_POLYNOMIAL_INDEX; }
72
73 static constexpr size_t get_read_count_polynomial_index(const size_t index)
74 {
76 }
77
78 static constexpr size_t get_lookup_term_predicate_index(const size_t lookup_index)
79 {
81 }
82
83 static constexpr size_t get_table_term_predicate_index(const size_t table_index)
84 {
86 }
87
94 static constexpr size_t compute_lookup_term_polynomial_offset(size_t lookup_index)
95 {
96 // If it's the starting index, then there is nothing to compute, just get the starting index
97 if (lookup_index == 0) {
99 }
100
101 switch (Settings_::LOOKUP_TYPES[lookup_index - 1]) {
102 case BASIC_LOOKUP:
103 // If the previous lookup was a basic lookup, add lookup tuple size (it was using just a linear combination
104 // of polynomials)
105 return compute_lookup_term_polynomial_offset(lookup_index - 1) + Settings_::LOOKUP_TUPLE_SIZE;
107 // In case of customized lookup, no polynomials from the tuple are being used
108 return compute_lookup_term_polynomial_offset(lookup_index - 1);
109 default:
110 bb::assert_failure("Invalid lookup type");
111 return SIZE_MAX;
112 }
113 }
114
121 static constexpr size_t compute_table_term_polynomial_offset(size_t table_index)
122 {
123 // If it's the starting index, then we need to find out how many polynomials were taken by lookup terms
124 if (table_index == 0) {
126 }
127
128 switch (Settings_::TABLE_TYPES[table_index - 1]) {
129 case BASIC_TABLE:
130 // If the previous lookup was a basic table, add lookup tuple size (it was using just a linear combination
131 // of polynomials)
132 return compute_table_term_polynomial_offset(table_index - 1) + Settings_::LOOKUP_TUPLE_SIZE;
133 case CUSTOMIZED_TABLE:
134 // In case of customized table, no polynomials from the tuple are being used
135 return compute_table_term_polynomial_offset(table_index - 1);
136 default:
137 bb::assert_failure("Invalid lookup type");
138 return SIZE_MAX;
139 }
140 }
141};
142
143// clang-format off
150template <typename S>
151concept GenericLookupSettings = requires {
152 // We allow looking up multiple items per row from a variable number of table columns. These values are not
153 // bound to the real number of columns the lookup operates on. We allow looking up virtual columns (i.e.,
154 // combinations of columns) from virtual table columns (i.e., combinations of table columns).
155 requires std::is_same_v<decltype(S::NUM_LOOKUP_TERMS), const size_t>;
156 requires std::is_same_v<decltype(S::NUM_TABLE_TERMS), const size_t>;
157
158 // An array defining the types of the lookups performed. They can be BASIC_LOOKUP or CUSTOMIZED_LOOKUP
159 requires std::is_same_v<decltype(S::LOOKUP_TYPES), const std::array<uint8_t, S::NUM_LOOKUP_TERMS>>;
160 // An array defining the types of the tables used. They can be BASIC_TABLE or CUSTOMIZED_TABLE
161 requires std::is_same_v<decltype(S::TABLE_TYPES), const std::array<uint8_t, S::NUM_TABLE_TERMS>>;
162 // An array specifying the degree of the lookup terms
163 requires std::is_same_v<decltype(S::LOOKUP_TERM_DEGREES), const std::array<size_t, S::NUM_LOOKUP_TERMS>>;
164 // An array specifying the degree of the table terms
165 requires std::is_same_v<decltype(S::TABLE_TERM_DEGREES), const std::array<size_t, S::NUM_TABLE_TERMS>>;
166
167 requires std::is_same_v<decltype(S::LOOKUP_TUPLE_SIZE), const size_t>; // Number of columns to batch for basic lookups
168
169 // Degree of the polynomial expression indicating whether the inverse polynomial exists at a given row
170 requires std::is_same_v<decltype(S::INVERSE_EXISTS_POLYNOMIAL_DEGREE), const size_t>;
171
172 // Settings also require the following methods, but some of them are templated, so we can't check them here.
173 // 1) Settings::inverse_polynomial_is_computed_at_row(const AllValues& row), method to compute whether the inverse polynomial should be computed at a given row
174 // 2) Settings::compute_inverse_exists<Accumulator>(const AllEntities& in), method to compute the value of the inverse_exists polynomial at a given row
175 // 3) Settings::template compute_lookup_term<Accumulator, size_t>(const AllEntities&, const Parameters&), method to compute the lookup term at a given index
176 // 4) Settings::template compute_table_term<Accumulator, size_t>(const AllEntities&, const Parameters&), method to compute the table term at a given index
177 // 5) Settings::get_nonconst_entities(AllEntities&), method to extract non constant references to the columns used in the relation
178 // 6) Settings::get_const_entities(const AllEntities&), method to extract constant references to the columns used in the relation
179};
180
241// clang-format on
242template <typename Settings, typename FF_> class GenericLookupRelationImpl {
243 public:
244 using FF = FF_;
246
247 static constexpr size_t NUM_LOOKUP_TERMS = Settings::NUM_LOOKUP_TERMS;
248 static constexpr size_t NUM_TABLE_TERMS = Settings::NUM_TABLE_TERMS;
249
256 static constexpr size_t LOOKUP_TUPLE_SIZE = Settings::LOOKUP_TUPLE_SIZE;
257
263 static constexpr size_t compute_lookup_term_product_degree()
264 {
265 size_t accumulated_degree = 0;
266 for (size_t i = 0; i < NUM_LOOKUP_TERMS; i++) {
267 size_t current_degree = 0;
268 switch (Settings::LOOKUP_TYPES[i]) {
269 case BASIC_LOOKUP:
270 current_degree = 1;
271 break;
273 current_degree = Settings::LOOKUP_TERM_DEGREES[i];
274 break;
275 default:
276 bb::assert_failure("Invalid lookup type");
277 }
278 accumulated_degree += current_degree;
279 }
280 return accumulated_degree;
281 }
282
288 static constexpr size_t compute_table_term_product_degree()
289 {
290 size_t accumulated_degree = 0;
291 for (size_t i = 0; i < NUM_TABLE_TERMS; i++) {
292 size_t current_degree = 0;
293 switch (Settings::TABLE_TYPES[i]) {
294 case BASIC_TABLE:
295 current_degree = 1;
296 break;
297 case CUSTOMIZED_TABLE:
298 current_degree = Settings::TABLE_TERM_DEGREES[i];
299 break;
300 default:
301 bb::assert_failure("Invalid table type");
302 break;
303 }
304 accumulated_degree += current_degree;
305 }
306 return accumulated_degree;
307 }
308
317 static constexpr size_t compute_second_subrelation_degree()
318 {
319 // Account for inverse polynomial, read count, and table term predicate
320 constexpr size_t ADDITIONAL_DEGREE = 3;
321 constexpr size_t TOTAL_TERM_PRODUCT_DEGREE =
323
324 size_t max_degree = 0;
325 for (size_t i = 0; i < NUM_LOOKUP_TERMS; i++) {
326 size_t current_degree = 0;
327 switch (Settings::LOOKUP_TYPES[i]) {
328 case BASIC_LOOKUP:
329 current_degree = 1;
330 break;
332 current_degree = Settings::LOOKUP_TERM_DEGREES[i];
333 break;
334 default:
335 bb::assert_failure("Invalid lookup type");
336 }
337 size_t adjusted_degree = TOTAL_TERM_PRODUCT_DEGREE - current_degree;
338 max_degree = std::max(max_degree, adjusted_degree);
339 }
340 for (size_t i = 0; i < NUM_TABLE_TERMS; i++) {
341 size_t current_degree = 0;
342 switch (Settings::TABLE_TYPES[i]) {
343 case BASIC_TABLE:
344 current_degree = 1;
345 break;
346 case CUSTOMIZED_TABLE:
347 current_degree = Settings::TABLE_TERM_DEGREES[i];
348 break;
349 default:
350 bb::assert_failure("Invalid table type");
351 break;
352 }
353 size_t adjusted_degree = TOTAL_TERM_PRODUCT_DEGREE - current_degree;
354 max_degree = std::max(max_degree, adjusted_degree);
355 }
356 return max_degree + ADDITIONAL_DEGREE;
357 }
358
359 // (Sub)relation lengths: equal to 1 + relation degree
362 static_assert(LOOKUP_TERM_ACCUMULATED_DEGREE > 0);
363 static_assert(TABLE_TERM_ACCUMULATED_DEGREE > 0);
364
365 static constexpr size_t FIRST_RELATION_PARTIAL_LENGTH =
367 Settings::INVERSE_EXISTS_POLYNOMIAL_DEGREE) +
368 1; // inverse polynomial correctness sub-relation
369 static constexpr size_t SECOND_RELATION_PARTIAL_LENGTH =
370 compute_second_subrelation_degree() + 1; // log-derived terms sub-relation
372
373 // We use the max of the subrelation lengths because the inverses of lookup/table terms must be used in both
374 // subrelations
375 static constexpr std::array<size_t, 2> SUBRELATION_PARTIAL_LENGTHS{ LENGTH, LENGTH };
376
377 // The first subrelation must be satisfied at every row.
378 // The second subrelation must be satisfied when summed across the entire trace
379 static constexpr std::array<bool, 2> SUBRELATION_LINEARLY_INDEPENDENT = { true, false };
380
388 template <typename AllValues> static bool operation_exists_at_row(const AllValues& row)
389 {
390 return Settings::inverse_polynomial_is_computed_at_row(row);
391 }
392
403 template <typename AllEntities> static auto& get_inverse_polynomial(AllEntities& in)
404 {
405 return std::get<PolynomialStructure::get_inverse_polynomial_index()>(Settings::get_nonconst_entities(in));
406 }
407
416 template <typename Accumulator, typename AllEntities>
417 static Accumulator compute_inverse_exists(const AllEntities& in)
418 {
419 // A lookup could be enabled by one of several selectors or witnesses, so we want to give as much freedom as
420 // possible to the implementor
421 return Settings::template compute_inverse_exists<Accumulator>(in);
422 }
423
436 template <typename Accumulator, size_t index, typename AllEntities>
437 static Accumulator lookup_read_counts(const AllEntities& in)
438 {
439
440 static_assert(index < NUM_TABLE_TERMS);
441 using View = typename Accumulator::View;
442
443 return Accumulator(View(
444 std::get<PolynomialStructure::get_read_count_polynomial_index(index)>(Settings::get_const_entities(in))));
445 }
446
456 template <typename Accumulator, size_t lookup_index, typename AllEntities>
457 static Accumulator get_lookup_term_predicate(const AllEntities& in)
458
459 {
460 static_assert(lookup_index < NUM_LOOKUP_TERMS);
461 using View = typename Accumulator::View;
462
463 return Accumulator(View(std::get<PolynomialStructure::get_lookup_term_predicate_index(lookup_index)>(
464 Settings::get_const_entities(in))));
465 }
466
476 template <typename Accumulator, size_t table_index, typename AllEntities>
477 static Accumulator get_table_term_predicate(const AllEntities& in)
478 {
479
480 static_assert(table_index < NUM_TABLE_TERMS);
481 using View = typename Accumulator::View;
482
483 return Accumulator(View(std::get<PolynomialStructure::get_table_term_predicate_index(table_index)>(
484 Settings::get_const_entities(in))));
485 }
486
498 template <typename Accumulator, size_t lookup_index, typename AllEntities, typename Parameters>
499 static Accumulator compute_lookup_term(const AllEntities& in, const Parameters& params)
500 {
501 using View = typename Accumulator::View;
502
503 static_assert(lookup_index < NUM_LOOKUP_TERMS);
504 constexpr size_t start_polynomial_index =
506 const FF beta = params.beta;
507 const FF gamma = params.gamma;
508
509 if constexpr (Settings::LOOKUP_TYPES[lookup_index] == BASIC_LOOKUP) {
510 // In this case we batch all the lookup columns pertaining to this lookup term using the randomness beta
511 Accumulator result = Accumulator(0);
512
513 const auto all_polynomials = Settings::get_const_entities(in);
514 bb::constexpr_for<start_polynomial_index, start_polynomial_index + LOOKUP_TUPLE_SIZE, 1>(
515 [&]<size_t i>() { result = (result * beta) + View(std::get<i>(all_polynomials)); });
516
517 return result + gamma;
518 } else if constexpr (Settings::LOOKUP_TYPES[lookup_index] == CUSTOMIZED_LOOKUP) {
519 return Settings::template compute_lookup_term<Accumulator, lookup_index>(in, params);
520 } else {
521 bb::assert_failure("Invalid lookup type");
522 return Accumulator(0);
523 }
524 }
525
537 template <typename Accumulator, size_t table_index, typename AllEntities, typename Parameters>
538 static Accumulator compute_table_term(const AllEntities& in, const Parameters& params)
539 {
540 using View = typename Accumulator::View;
541
542 static_assert(table_index < NUM_TABLE_TERMS);
543 constexpr size_t start_polynomial_index =
545 const FF beta = params.beta;
546 const FF gamma = params.gamma;
547
548 if constexpr (Settings::TABLE_TYPES[table_index] == BASIC_TABLE) {
549 // In this case we batch all the lookup columns pertaining to this lookup term using the randomness beta
550 Accumulator result = Accumulator(0);
551
552 const auto all_polynomials = Settings::get_const_entities(in);
553
554 bb::constexpr_for<start_polynomial_index, start_polynomial_index + LOOKUP_TUPLE_SIZE, 1>(
555 [&]<size_t i>() { result = (result * beta) + View(std::get<i>(all_polynomials)); });
556
557 return result + gamma;
558 } else if constexpr (Settings::TABLE_TYPES[table_index] == CUSTOMIZED_TABLE) {
559 return Settings::template compute_table_term<Accumulator, table_index>(in, params);
560 } else {
561 bb::assert_failure("Invalid table type");
562 return Accumulator(0);
563 }
564 }
565
584 template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
585 static void accumulate(ContainerOverSubrelations& accumulator,
586 const AllEntities& in,
587 const Parameters& params,
588 const FF& scaling_factor)
589 {
592 ContainerOverSubrelations,
593 AllEntities,
594 Parameters,
595 false>(accumulator, in, params, scaling_factor);
596 }
597};
598
599template <typename Settings, typename FF>
601
602} // namespace bb
Generic implementation of a log-derivative based lookup relation.
static constexpr size_t compute_lookup_term_product_degree()
Compute the degree of the product of lookup terms.
static Accumulator compute_inverse_exists(const AllEntities &in)
Get selector/wire switching on (1) or off (0) inverse computation.
static constexpr size_t TABLE_TERM_ACCUMULATED_DEGREE
static constexpr std::array< bool, 2 > SUBRELATION_LINEARLY_INDEPENDENT
static void accumulate(ContainerOverSubrelations &accumulator, const AllEntities &in, const Parameters &params, const FF &scaling_factor)
Compute generic log-derivative lookup subrelation accumulation.
static constexpr size_t compute_table_term_product_degree()
Compute the degree of the product of table terms.
static constexpr size_t FIRST_RELATION_PARTIAL_LENGTH
static bool operation_exists_at_row(const AllValues &row)
Check if we need to compute the inverse polynomial element value for this row.
static auto & get_inverse_polynomial(AllEntities &in)
Get the inverse permutation polynomial.
static Accumulator compute_lookup_term(const AllEntities &in, const Parameters &params)
Compute the value of the lookup term at a given index.
static Accumulator compute_table_term(const AllEntities &in, const Parameters &params)
Compute the value of a table term at a given index.
static constexpr size_t compute_second_subrelation_degree()
Compute the degree of the second subrelation.
static constexpr size_t SECOND_RELATION_PARTIAL_LENGTH
static constexpr size_t LOOKUP_TERM_ACCUMULATED_DEGREE
static Accumulator get_table_term_predicate(const AllEntities &in)
Extract predicate enabling looking up a given table term at this row.
static constexpr std::array< size_t, 2 > SUBRELATION_PARTIAL_LENGTHS
static Accumulator get_lookup_term_predicate(const AllEntities &in)
Extract predicate enabling looking up a given lookup term at this row.
static Accumulator lookup_read_counts(const AllEntities &in)
Get the number of times a particular table value has been looked up.
Polynomial structure required for the lookup argument.
static constexpr size_t compute_table_term_polynomial_offset(size_t table_index)
Compute where the polynomials defining a particular table term are located.
static constexpr size_t get_table_term_predicate_index(const size_t table_index)
static constexpr size_t compute_lookup_term_polynomial_offset(size_t lookup_index)
Compute where the polynomials defining a particular lookup term are located.
static constexpr size_t LOOKUP_TERM_START_POLYNOMIAL_INDEX
static constexpr size_t LOOKUP_TERM_PREDICATE_START_POLYNOMIAL_INDEX
static constexpr size_t get_inverse_polynomial_index()
static constexpr size_t get_read_count_polynomial_index(const size_t index)
static constexpr size_t INVERSE_POLYNOMIAL_INDEX
static constexpr size_t LOOKUP_READ_COUNT_START_POLYNOMIAL_INDEX
static constexpr size_t TABLE_TERM_PREDICATE_START_POLYNOMIAL_INDEX
static constexpr size_t get_lookup_term_predicate_index(const size_t lookup_index)
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
Concept defining the requirements for the Settings struct used to configure the GenericLookupRelation...
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
void _accumulate_logderivative_subrelation_contributions(ContainerOverSubrelations &accumulator, const AllEntities &in, const Parameters &params, const FF &scaling_factor)
Unified implementation of log-derivative subrelation accumulation.
void assert_failure(std::string const &err)
Definition assert.cpp:11
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13