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: 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
23#pragma once
24#include <array>
25#include <tuple>
26
31
32namespace bb {
38template <typename Settings, typename FF_> class GenericLookupRelationImpl {
39 public:
40 using FF = FF_;
41
42 // Read terms specified how many maximum lookups can be performed in 1 row
43 static constexpr size_t READ_TERMS = Settings::READ_TERMS;
44
45 // Looked up entries can be a basic tuple, a scaled tuple or completely arbitrary
47
48 // Write terms specifies how many insertions into the lookup table can be performed in 1 row
49 static constexpr size_t WRITE_TERMS = Settings::WRITE_TERMS;
50
51 // Entries put into the table are ever defined as a tuple or constructed arbitrarily
53
54 // Lookup tuple size specifies how many values are bundled together to represent a single entry in the lookup table.
55 // For example, it would be 1 for a range constraint lookup, or 3 for XOR lookup
56 static constexpr size_t LOOKUP_TUPLE_SIZE = Settings::LOOKUP_TUPLE_SIZE;
57
64 static constexpr size_t compute_maximum_read_term_degree()
65 {
66 size_t maximum_degree = 0;
67 for (size_t i = 0; i < READ_TERMS; i++) {
68 size_t current_degree = 0;
69 if (Settings::READ_TERM_TYPES[i] == READ_BASIC_TUPLE) {
70 current_degree = 1;
71 } else if (Settings::READ_TERM_TYPES[i] == READ_SCALED_TUPLE) {
72 current_degree = 2;
73 } else {
74 current_degree = Settings::READ_TERM_DEGREE;
75 }
76 maximum_degree = std::max(current_degree, maximum_degree);
77 }
78 return maximum_degree;
79 }
80
87 static constexpr size_t compute_maximum_write_term_degree()
88 {
89 size_t maximum_degree = 0;
90 for (size_t i = 0; i < WRITE_TERMS; i++) {
91 size_t current_degree = 0;
92 if (Settings::WRITE_TERM_TYPES[i] == WRITE_BASIC_TUPLE) {
93 current_degree = 1;
94 } else {
95 current_degree = Settings::WRITE_TERM_DEGREE;
96 }
97 maximum_degree = std::max(current_degree, maximum_degree);
98 }
99 return maximum_degree;
100 }
101
109 static constexpr size_t compute_read_term_product_degree()
110 {
111 size_t accumulated_degree = 0;
112 for (size_t i = 0; i < READ_TERMS; i++) {
113 size_t current_degree = 0;
114 if (Settings::READ_TERM_TYPES[i] == READ_BASIC_TUPLE) {
115 current_degree = 1;
116 } else if (Settings::READ_TERM_TYPES[i] == READ_SCALED_TUPLE) {
117 current_degree = 2;
118 } else {
119 current_degree = Settings::READ_TERM_DEGREE;
120 }
121 accumulated_degree += current_degree;
122 }
123 return accumulated_degree;
124 }
125
133 static constexpr size_t compute_write_term_product_degree()
134 {
135 size_t accumulated_degree = 0;
136 for (size_t i = 0; i < WRITE_TERMS; i++) {
137 size_t current_degree = 0;
138 if (Settings::WRITE_TERM_TYPES[i] == WRITE_BASIC_TUPLE) {
139 current_degree = 1;
140 } else {
141 current_degree = Settings::WRITE_TERM_DEGREE;
142 }
143 accumulated_degree += current_degree;
144 }
145 return accumulated_degree;
146 }
147
148 // Read term degree is dependent on what type of read term we use
150 static_assert(READ_TERM_DEGREE != 0);
151
152 // Write term degree is dependent on what type of write term we use
154
155 static_assert(WRITE_TERM_DEGREE != 0);
156
157 // Compute the length of the inverse polynomial correctness sub-relation MAX(product of terms * inverse, inverse
158 // exists polynomial) + 1;
159 static constexpr size_t FIRST_SUBRELATION_LENGTH =
161 Settings::INVERSE_EXISTS_POLYNOMIAL_DEGREE) +
162 1;
163
164 // Compute the length of the log-derived term subrelation MAX(read term * enable read, write term * write count *
165 // enable write)
167 // 1 + polynomial degree of this relation
169
170 // The structure of polynomial tuple returned from Settings' functions get_const_entities and get_nonconst_entities
171 // is the following:
172 // 1) 1 Polynomial used to contain the inverse product from which we reconstruct individual inverses
173 // used in the sum
174 // 2) WRITE_TERMS number of polynomials representing how much each write term has been read
175 // 3) READ_TERMS number of polynomials enabling the addition of a particular read term in this row (should we lookup
176 // or not)
177 // 4) WRITE_TERMS number of polynomials enabling a particular write term in this row (should we add it to
178 // the lookup table or not)
179 // 5) For each read term depending on its type (READ_BASIC_TUPLE, READ_SCALED_TUPLE or READ_ARBITRARY):
180 // 1. In case of basic tuple LOOKUP_TUPLE_SIZE polynomials the combination of whose values in a row is supposed to
181 // represent the looked up entry
182 // 2. In case of scaled tuple there are LOOKUP_TUPLE_SIZE previous accumulator polynomials, LOOKUP_TUPLE_SIZE
183 // scaling polynomials and LOOKUP_TUPLE_SIZE current accumulator polynomials. The tuple is comprised of values
184 // (current_accumulator-scale*previous_accumulator)
185 // 3. In the arbitrary case the are no additional
186 // polynomials, because the logic is completely decided in the settings
187 // 6) For each write term depending on its type (READ_BASIC_TUPLE or READ_ARBITRARY):
188 // 1. In case of basic tuple LOOKUP_TUPLE_SIZE polynomials the combination of whose values in a row is supposed to
189 // represent the entry written into the lookup table
190 // 2. In the arbitrary case the are no additional write term polynomials,
191 // because the logic is completely decided in the settings
192 static constexpr size_t INVERSE_POLYNOMIAL_INDEX = 0;
193 static constexpr size_t LOOKUP_READ_COUNT_START_POLYNOMIAL_INDEX = 1;
200
201 static constexpr std::array<size_t, 2> SUBRELATION_PARTIAL_LENGTHS{
202 LENGTH, // inverse polynomial correctness sub-relation
203 LENGTH // log-derived terms subrelation
204 };
212 static constexpr std::array<bool, 2> SUBRELATION_LINEARLY_INDEPENDENT = { true, false };
213
220 template <typename AllValues> static bool operation_exists_at_row(const AllValues& row)
221
222 {
223 return Settings::inverse_polynomial_is_computed_at_row(row);
224 }
225
230 template <typename AllEntities> static auto& get_inverse_polynomial(AllEntities& in)
231 {
232 // WIRE containing the inverse of the product of terms at this row. Used to reconstruct individual inversed
233 // terms
234 return std::get<INVERSE_POLYNOMIAL_INDEX>(Settings::get_nonconst_entities(in));
235 }
236
241 template <typename Accumulator, typename AllEntities>
242 static Accumulator compute_inverse_exists(const AllEntities& in)
243 {
244
245 // A lookup could be enabled by one of several selectors or witnesses, so we want to give as much freedom as
246 // possible to the implementor
247 return Settings::template compute_inverse_exists<Accumulator>(in);
248 }
249
261 template <typename Accumulator, size_t index, typename AllEntities>
262 static Accumulator lookup_read_counts(const AllEntities& in)
263 {
264
265 static_assert(index < WRITE_TERMS);
266 using View = typename Accumulator::View;
267
268 return Accumulator(
269 View(std::get<LOOKUP_READ_COUNT_START_POLYNOMIAL_INDEX + index>(Settings::get_const_entities(in))));
270 }
276 template <typename Accumulator, size_t read_index, typename AllEntities>
277 static Accumulator compute_read_term_predicate(const AllEntities& in)
278
279 {
280 static_assert(read_index < READ_TERMS);
281 using View = typename Accumulator::View;
282
283 // The selector/wire value that determines that an element from the first set needs to be included. Can be
284 // different from the wire used in the write part.
286 Settings::get_const_entities(in))));
287 }
288
294 template <typename Accumulator, size_t write_index, typename AllEntities>
295 static Accumulator compute_write_term_predicate(const AllEntities& in)
296 {
297
298 static_assert(write_index < WRITE_TERMS);
299 using View = typename Accumulator::View;
300
301 // The selector/wire value that determines that an element from the first set needs to be included. Can be
302 // different from the wire used in the write part.
304 Settings::get_const_entities(in))));
305 }
306
317 static constexpr size_t compute_read_term_polynomial_offset(size_t read_index)
318 {
319 // If it's the starting index, then there is nothing to compute, just get the starting index
320 if (read_index == 0) {
322 }
323
324 // If the previous term used basic tuple lookup, add lookup tuple size (it was using just a linear combination
325 // of polynomials)
326 if (Settings::READ_TERM_TYPES[read_index - 1] == READ_BASIC_TUPLE) {
328 }
329
330 // If the previous term used scaled tuple lookup, add lookup tuple size x 3 (it was using just a linear
331 // combination of differences (current - previousâ‹…scale))
332
333 if (Settings::READ_TERM_TYPES[read_index - 1] == READ_SCALED_TUPLE) {
334 return compute_read_term_polynomial_offset(read_index - 1) + 3 * LOOKUP_TUPLE_SIZE;
335 }
336 // In case of arbitrary read term, no polynomials from the tuple are being used
337 if (Settings::READ_TERM_TYPES[read_index - 1] == READ_ARBITRARY) {
338 return compute_read_term_polynomial_offset(read_index - 1);
339 }
340 return SIZE_MAX;
341 }
342
353 static constexpr size_t compute_write_term_polynomial_offset(size_t write_index)
354 {
355 // If it's the starting index, then we need to find out how many polynomials were taken by read terms
356 if (write_index == 0) {
358 }
359
360 // If the previous term used basic tuple lookup, add lookup tuple size (it was using just a linear combination
361 // of polynomials)
362 if (Settings::WRITE_TERM_TYPES[write_index - 1] == WRITE_BASIC_TUPLE) {
364 }
365
366 // In case of arbitrary write term, no polynomials from the tuple are being used
367 if (Settings::WRITE_TERM_TYPES[write_index - 1] == WRITE_ARBITRARY) {
368 return compute_write_term_polynomial_offset(write_index - 1);
369 }
370 return SIZE_MAX;
371 }
372
383 template <typename Accumulator, size_t read_index, typename AllEntities, typename Parameters>
384 static Accumulator compute_read_term(const AllEntities& in, const Parameters& params)
385 {
386 using View = typename Accumulator::View;
387
388 static_assert(read_index < READ_TERMS);
389 constexpr size_t start_polynomial_index = compute_read_term_polynomial_offset(read_index);
390 if constexpr (Settings::READ_TERM_TYPES[read_index] == READ_BASIC_TUPLE) {
391 // Retrieve all polynomials used
392 const auto all_polynomials = Settings::get_const_entities(in);
393
394 auto result = Accumulator(0);
395
396 // Iterate over tuple and sum as a polynomial over beta
397 bb::constexpr_for<start_polynomial_index, start_polynomial_index + LOOKUP_TUPLE_SIZE, 1>(
398 [&]<size_t i>() { result = (result * params.beta) + View(std::get<i>(all_polynomials)); });
399 const auto& gamma = params.gamma;
400 return result + gamma;
401 } else if constexpr (Settings::READ_TERM_TYPES[read_index] == READ_SCALED_TUPLE) {
402 // Retrieve all polynomials used
403 const auto all_polynomials = Settings::get_const_entities(in);
404
405 auto result = Accumulator(0);
406 // Iterate over tuple and sum as a polynomial over beta
407 bb::constexpr_for<start_polynomial_index, start_polynomial_index + LOOKUP_TUPLE_SIZE, 1>([&]<size_t i>() {
408 result = (result * params.beta) + View(std::get<i + 2 * LOOKUP_TUPLE_SIZE>(all_polynomials)) -
409 View(std::get<i + LOOKUP_TUPLE_SIZE>(all_polynomials)) * View(std::get<i>(all_polynomials));
410 });
411 const auto& gamma = params.gamma;
412 return result + gamma;
413 } else {
414
415 return Settings::template compute_read_term<Accumulator, read_index>(in, params);
416 }
417 }
418
429 template <typename Accumulator, size_t write_index, typename AllEntities, typename Parameters>
430 static Accumulator compute_write_term(const AllEntities& in, const Parameters& params)
431 {
432
433 static_assert(write_index < WRITE_TERMS);
434
435 using View = typename Accumulator::View;
436 constexpr size_t start_polynomial_index = compute_write_term_polynomial_offset(write_index);
437
438 if constexpr (Settings::WRITE_TERM_TYPES[write_index] == WRITE_BASIC_TUPLE) {
439 // Retrieve all polynomials used
440 const auto all_polynomials = Settings::get_const_entities(in);
441
442 auto result = Accumulator(0);
443
444 // Iterate over tuple and sum as a polynomial over beta
445 bb::constexpr_for<start_polynomial_index, start_polynomial_index + LOOKUP_TUPLE_SIZE, 1>(
446 [&]<size_t i>() { result = (result * params.beta) + View(std::get<i>(all_polynomials)); });
447 const auto& gamma = params.gamma;
448 return result + gamma;
449 } else {
450 // Sometimes we construct lookup tables on the fly from intermediate
451
452 return Settings::template compute_write_term<Accumulator, write_index>(in, params);
453 }
454 }
455
463 template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
464 static void accumulate(ContainerOverSubrelations& accumulator,
465 const AllEntities& in,
466 const Parameters& params,
467 const FF& scaling_factor)
468 {
469 accumulate_logderivative_lookup_subrelation_contributions<FF, GenericLookupRelationImpl<Settings, FF>>(
470 accumulator, in, params, scaling_factor);
471 }
472};
473
474template <typename Settings, typename FF>
476
477template <typename Settings, typename FF> using GenericLookup = GenericLookupRelationImpl<Settings, FF>;
478
479} // namespace bb
Specifies positions of elements in the tuple of entities received from methods in the Settings class.
static constexpr size_t compute_read_term_polynomial_offset(size_t read_index)
Compute where the polynomials defining a particular read term are located.
static constexpr size_t LOOKUP_READ_COUNT_START_POLYNOMIAL_INDEX
static Accumulator compute_inverse_exists(const AllEntities &in)
Get selector/wire switching on(1) or off(0) inverse computation.
static Accumulator compute_write_term(const AllEntities &in, const Parameters &params)
Compute the value of a single item in the set.
static constexpr size_t compute_maximum_read_term_degree()
Compute the maximum degree of read terms.
static constexpr size_t INVERSE_POLYNOMIAL_INDEX
static constexpr std::array< bool, 2 > SUBRELATION_LINEARLY_INDEPENDENT
We apply the power polynomial only to the first subrelation.
static constexpr size_t FIRST_SUBRELATION_LENGTH
static void accumulate(ContainerOverSubrelations &accumulator, const AllEntities &in, const Parameters &params, const FF &scaling_factor)
Expression for generic log-derivative-based set permutation.
static constexpr size_t LOOKUP_READ_PREDICATE_START_POLYNOMIAL_INDEX
static Accumulator compute_write_term_predicate(const AllEntities &in)
Compute if the value from the second set exists in this row.
static constexpr size_t LOOKUP_TUPLE_SIZE
static bool operation_exists_at_row(const AllValues &row)
Check if we need to compute the inverse polynomial element value for this row.
static constexpr size_t compute_read_term_product_degree()
Compute the degree of of the product of read terms.
static constexpr size_t SECOND_SUBRELATION_LENGTH
static Accumulator compute_read_term(const AllEntities &in, const Parameters &params)
Compute the value of a single item in the set.
static constexpr size_t compute_write_term_product_degree()
Compute the degree of of the product of write terms.
static auto & get_inverse_polynomial(AllEntities &in)
Get the inverse permutation polynomial (needed to compute its value)
static constexpr size_t compute_maximum_write_term_degree()
Compute the maximum degree of write terms.
static constexpr size_t LOOKUP_READ_TERM_PREDICATE_START_POLYNOMIAL_INDEX
static Accumulator compute_read_term_predicate(const AllEntities &in)
Compute if the value from the first set exists in this row.
static constexpr size_t compute_write_term_polynomial_offset(size_t write_index)
Compute where the polynomials defining a particular write term are located.
static constexpr std::array< size_t, 2 > SUBRELATION_PARTIAL_LENGTHS
static Accumulator lookup_read_counts(const AllEntities &in)
Returns the number of times a particular value is written (how many times it is being looked up)
static constexpr size_t LOOKUP_WRITE_TERM_PREDICATE_START_POLYNOMIAL_INDEX
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13