Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
translator_proving_key.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Planned, auditors: [], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
9namespace bb {
21{
22 // The vector of groups of polynomials to be concatenated
23 auto groups = proving_key->polynomials.get_groups_to_be_concatenated();
24 // Resulting concatenated polynomials
25 auto targets = proving_key->polynomials.get_concatenated();
26
27 const size_t num_polys_in_group = groups[0].size();
29
30 const size_t MINI_CIRCUIT_SIZE = Flavor::MINI_CIRCUIT_SIZE;
31
32 auto ordering_function = [&](size_t index) {
33 // Get the index of the concatenated polynomial (group index)
34 size_t i = index / num_polys_in_group;
35 // Get the index of the polynomial within the group
36 size_t j = index % num_polys_in_group;
37 auto& group = groups[i];
38 auto& current_target = targets[i];
39
40 // Copy into appropriate position in the concatenated polynomial: j * MINI + k
41 // Note: null padding slots in group 4 are zero-sized polynomials, so this loop is a no-op for them.
42 for (size_t k = group[j].start_index(); k < group[j].end_index(); k++) {
43 current_target.at(j * MINI_CIRCUIT_SIZE + k) = group[j][k];
44 }
45 };
46 parallel_for(groups.size() * num_polys_in_group, ordering_function);
47}
48
73{
74 RefArray ordered_constraint_polynomials{ proving_key->polynomials.ordered_range_constraints_0,
75 proving_key->polynomials.ordered_range_constraints_1,
76 proving_key->polynomials.ordered_range_constraints_2,
77 proving_key->polynomials.ordered_range_constraints_3 };
78 std::vector<size_t> extra_denominator_uint(dyadic_circuit_size_without_masking);
79
80 const auto sorted_elements = get_sorted_steps();
81 auto to_be_concatenated_groups = proving_key->polynomials.get_groups_to_be_concatenated();
82 const size_t circuit_size = proving_key->polynomials.get_polynomial_size();
83
84 // Given the polynomials in group_i, transfer their elements, sorted in non-descending order, into the corresponding
85 // ordered_range_constraint_i up to the given capacity and the remaining elements to the last range constraint.
86 // Sorting is done by converting the elements to uint for efficiency.
87 auto ordering_function = [&](size_t i) {
88 const auto& group = to_be_concatenated_groups[i];
89 std::vector<uint32_t> ordered_vectors_uint(dyadic_circuit_size_without_masking);
90
91 // Calculate how much space there is for values from the group polynomials given we also need to append the
92 // additional steps
93 auto free_space_before_runway = dyadic_circuit_size_without_masking - sorted_elements.size();
94
95 // Calculate the starting index of this group's overflowing elements in the extra denominator polynomial
96 size_t extra_denominator_offset = i * sorted_elements.size();
97
98 // Number of real values per lane: MINI_CIRCUIT_SIZE positions minus the virtual zero at index 0
99 // minus NUM_MASKED_ROWS_END masking rows at the end of each block
100 static constexpr size_t values_per_lane = Flavor::MINI_CIRCUIT_SIZE - 1 - Flavor::NUM_MASKED_ROWS_END;
101
102 // Go through each polynomial in the concatenated group
103 for (size_t j = 0; j < Flavor::CONCATENATION_GROUP_SIZE; j++) {
104
105 // Dense offset: avoid phantom zeros by packing values tightly
106 auto current_offset = j * values_per_lane;
107
108 // For each element in the polynomial (excluding masking rows at the end)
109 for (size_t k = group[j].start_index(); k < group[j].end_index() - Flavor::NUM_MASKED_ROWS_END; k++) {
110
111 auto vec_idx = current_offset + (k - group[j].start_index());
112
113 // Put it in the target polynomial
114 if (vec_idx < free_space_before_runway) {
115 ordered_vectors_uint[vec_idx] = static_cast<uint32_t>(uint256_t(group[j][k]).data[0]);
116
117 // Or in the extra one if there is no space left
118 } else {
119 extra_denominator_uint[extra_denominator_offset] =
120 static_cast<uint32_t>(uint256_t(group[j][k]).data[0]);
121 extra_denominator_offset++;
122 }
123 }
124 }
125 // Advance the iterator past the last written element in the range constraint polynomial and complete it with
126 // sorted steps
127 auto ordered_vector_it = ordered_vectors_uint.begin();
128 std::advance(ordered_vector_it, free_space_before_runway);
129 std::copy(sorted_elements.cbegin(), sorted_elements.cend(), ordered_vector_it);
130
131 // Sort the polynomial in nondescending order. We sort using the uint32_t vector for 2 reasons:
132 // 1. It is faster to sort integers
133 // 2. Comparison operators for finite fields are operating on internal form, so we'd have to convert them
134 // from Montgomery
135 std::sort(ordered_vectors_uint.begin(), ordered_vectors_uint.end());
136 BB_ASSERT_EQ(ordered_vectors_uint.size(), dyadic_circuit_size_without_masking);
137
138 // All polynomials reserve the same amount of space at the end (max across all polynomials)
139 // so that lagrange_real_last marks the same position for all polynomials
140 // Place sorted values contiguously from position 1 to circuit_size - MAX_RANDOM_VALUES_PER_ORDERED
141 // Position 0 remains 0 (virtual zero). Last MAX_RANDOM_VALUES_PER_ORDERED positions reserved for random values.
142 size_t sorted_idx = 1; // Skip vec[0] (virtual zero at position 0)
143 for (size_t pos = 1; pos < circuit_size - Flavor::MAX_RANDOM_VALUES_PER_ORDERED; pos++) {
144 ordered_constraint_polynomials[i].at(pos) = FF(ordered_vectors_uint[sorted_idx]);
145 sorted_idx++;
146 }
147 };
148
149 // Construct the first NUM_CONCATENATED_POLYS - 1 polynomials (range constraint groups only)
150 constexpr size_t NUM_RANGE_CONSTRAINT_GROUPS = Flavor::NUM_CONCATENATED_POLYS - 1;
151 parallel_for(NUM_RANGE_CONSTRAINT_GROUPS, ordering_function);
152
153 // Advance the iterator into the extra range constraint past the last written element
154 auto extra_denominator_it = extra_denominator_uint.begin();
155 std::advance(extra_denominator_it, NUM_RANGE_CONSTRAINT_GROUPS * sorted_elements.size());
156
157 // Add steps to the extra denominator polynomial to fill it
158 std::copy(sorted_elements.cbegin(), sorted_elements.cend(), extra_denominator_it);
159 // Sort it
160#ifdef NO_PAR_ALGOS
161 std::sort(extra_denominator_uint.begin(), extra_denominator_uint.end());
162#else
163 std::sort(std::execution::par_unseq, extra_denominator_uint.begin(), extra_denominator_uint.end());
164#endif
165
166 // Place sorted values for the 5th polynomial
167 // All polynomials reserve the same amount of space at the end
168 {
169 size_t sorted_idx = 1; // Skip vec[0] (virtual zero at position 0)
170 for (size_t pos = 1; pos < circuit_size - Flavor::MAX_RANDOM_VALUES_PER_ORDERED; pos++) {
171 proving_key->polynomials.ordered_range_constraints_4.at(pos) = FF(extra_denominator_uint[sorted_idx]);
172 sorted_idx++;
173 }
174 }
175
176 // Transfer randomness from concatenated to ordered polynomials such that the commitments and evaluations of all
177 // ordered polynomials and their shifts are hidden
179}
180
191{
192 auto concatenated = proving_key->polynomials.get_concatenated();
193 auto ordered = proving_key->polynomials.get_ordered_range_constraints();
194 const size_t num_ordered_polynomials = ordered.size();
195 const size_t MINI = Flavor::MINI_CIRCUIT_SIZE;
196
197 // Collect all random values from masking positions in concatenated range constraint polynomials
198 // NOTE: Only extract from the first NUM_CONCATENATED_POLYS - 1 concatenated polys
199 // (concatenated_range_constraints_0..3) which appear in the permutation numerator.
200 // The last (concatenated_non_range) is not in the numerator.
201 // Masking positions are at the end of each block: [j*MINI + (MINI - NUM_MASKED_ROWS_END), j*MINI + MINI)
202 constexpr size_t NUM_RANGE_CONSTRAINT_GROUPS = Flavor::NUM_CONCATENATED_POLYS - 1;
203 const size_t num_random_values_per_concat = Flavor::NUM_MASKED_ROWS_END * Flavor::CONCATENATION_GROUP_SIZE;
204 const size_t total_num_random_values = num_random_values_per_concat * NUM_RANGE_CONSTRAINT_GROUPS;
205 const size_t num_random_values_per_ordered = total_num_random_values / num_ordered_polynomials;
206 const size_t remaining_random_values = total_num_random_values % num_ordered_polynomials;
207
208 std::vector<FF> random_values(total_num_random_values);
209
210 // Extract random values from scattered masking positions in the first NUM_RANGE_CONSTRAINT_GROUPS concatenated
211 // polynomials. Each thread handles one concatenated polynomial, writing to a disjoint slice of random_values.
212 parallel_for(NUM_RANGE_CONSTRAINT_GROUPS, [&](size_t i) {
213 const auto& current_concat = concatenated[i];
214 size_t idx = i * num_random_values_per_concat;
215 for (size_t j = 0; j < Flavor::CONCATENATION_GROUP_SIZE; j++) {
216 size_t block_masking_start = j * MINI + (MINI - Flavor::NUM_MASKED_ROWS_END);
217 for (size_t k = 0; k < Flavor::NUM_MASKED_ROWS_END; k++) {
218 random_values[idx] = current_concat[block_masking_start + k];
219 idx++;
220 }
221 }
222 });
223
224 // Distribute random values to ordered polynomials at the END (contiguous).
225 // Each ordered polynomial gets values at the last positions.
226 const size_t circuit_size = proving_key->polynomials.get_polynomial_size();
227 parallel_for(num_ordered_polynomials, [&](size_t i) {
228 auto& current_ordered = ordered[i];
229 size_t values_for_this_poly = num_random_values_per_ordered + (i < remaining_random_values ? 1 : 0);
230 // Compute offset into random_values for this ordered polynomial
231 size_t random_idx = i * num_random_values_per_ordered + std::min(i, remaining_random_values);
232 // Place random values at the END: [circuit_size - values_for_this_poly, circuit_size)
233 for (size_t k = 0; k < values_for_this_poly; k++) {
234 current_ordered.at(circuit_size - values_for_this_poly + k) = random_values[random_idx];
235 random_idx++;
236 }
237 });
238}
239
277{
278 const size_t MINI = Flavor::MINI_CIRCUIT_SIZE;
279 const size_t circuit_size = proving_key->polynomials.get_polynomial_size();
280
281 proving_key->polynomials.lagrange_first.at(0) = 1;
282 // lagrange_real_last marks the last position with sorted values in ordered polynomials
283 // (where we check maximum value = 2^14 - 1)
284 proving_key->polynomials.lagrange_real_last.at(circuit_size - Flavor::MAX_RANDOM_VALUES_PER_ORDERED - 1) = 1;
285 proving_key->polynomials.lagrange_last.at(circuit_size - 1) = 1;
286
287 // Scattered masking: last NUM_MASKED_ROWS_END rows of each of the 16 blocks
288 for (size_t j = 0; j < Flavor::CONCATENATION_GROUP_SIZE; j++) {
289 for (size_t k = MINI - Flavor::NUM_MASKED_ROWS_END; k < MINI; k++) {
290 proving_key->polynomials.lagrange_masking.at(j * MINI + k) = 1;
291 }
292 }
293
294 // lagrange_ordered_masking: marks the last MAX_RANDOM_VALUES_PER_ORDERED positions (contiguous at end)
295 // where random values are placed in ordered polynomials
296 for (size_t i = circuit_size - Flavor::MAX_RANDOM_VALUES_PER_ORDERED; i < circuit_size; i++) {
297 proving_key->polynomials.lagrange_ordered_masking.at(i) = 1;
298 }
299
300 for (size_t i = Flavor::RANDOMNESS_START; i < Flavor::RESULT_ROW; i++) {
301 proving_key->polynomials.lagrange_mini_masking.at(i) = 1;
302 }
303
304 // Location of randomness for wires defined within the mini circuit
306 proving_key->polynomials.lagrange_mini_masking.at(i) = 1;
307 }
308
309 // Translator VM processes two rows of its execution trace at a time, establishing different relations between
310 // polynomials at even and odd indices
312 proving_key->polynomials.lagrange_even_in_minicircuit.at(i) = 1;
313 proving_key->polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1;
314 }
315
316 // Position of evaluation result
317 proving_key->polynomials.lagrange_result_row.at(Flavor::RESULT_ROW) = 1;
318 proving_key->polynomials.lagrange_last_in_minicircuit.at(dyadic_mini_circuit_size_without_masking - 1) = 1;
319}
320
336{
337
338 const auto sorted_elements = get_sorted_steps();
339 // The numerator has NUM_CONCATENATED_POLYS factors: (NUM_CONCATENATED_POLYS - 1) concatenated range constraint
340 // polynomials + 1 extra_numerator, matching NUM_CONCATENATED_POLYS ordered polynomials in the denominator.
341 // Each sorted element appears NUM_CONCATENATED_POLYS times.
342 constexpr size_t NUM_FACTORS_IN_NUMERATOR = Flavor::NUM_CONCATENATED_POLYS;
343 auto fill_with_shift = [&](size_t shift) {
344 for (size_t i = 0; i < sorted_elements.size(); i++) {
345 proving_key->polynomials.ordered_extra_range_constraints_numerator.at(
346 shift + i * NUM_FACTORS_IN_NUMERATOR) = sorted_elements[i];
347 }
348 };
349 // Fill polynomials with a sequence, where each element is repeated NUM_FACTORS_IN_NUMERATOR times
350 parallel_for(NUM_FACTORS_IN_NUMERATOR, fill_with_shift);
351}
352} // namespace bb
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
A template class for a reference array. Behaves as if std::array<T&, N> was possible.
Definition ref_array.hpp:22
static constexpr size_t MINI_CIRCUIT_SIZE
static constexpr size_t MAX_RANDOM_VALUES_PER_ORDERED
static constexpr size_t NUM_CONCATENATED_POLYS
static constexpr size_t RANDOMNESS_START
static constexpr size_t CONCATENATION_GROUP_SIZE
static constexpr size_t RESULT_ROW
static constexpr size_t NUM_MASKED_ROWS_END
void split_concatenated_random_coefficients_to_ordered()
Distribute the randomness from the 4 concatenated range constraint polynomials to the 5 ordered range...
void compute_concatenated_polynomials()
Construct a set of polynomials that are the result of concatenating a group of polynomials into one....
static std::array< size_t, Flavor::SORTED_STEPS_COUNT > get_sorted_steps()
Create the array of steps inserted in each ordered range constraint to ensure they respect the approp...
static constexpr size_t mini_circuit_dyadic_size
void compute_extra_range_constraint_numerator()
Compute the extra numerator for the grand product polynomial.
static constexpr size_t dyadic_circuit_size_without_masking
void compute_translator_range_constraint_ordered_polynomials()
Compute denominator polynomials for Translator's range constraint permutation.
std::shared_ptr< ProvingKey > proving_key
static constexpr size_t dyadic_mini_circuit_size_without_masking
void compute_lagrange_polynomials()
Constructs all Lagrange precomputed polynomials required for Translator relations....
group class. Represents an elliptic curve group element. Group is parametrised by Fq and Fr
Definition group.hpp:36
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
Definition thread.cpp:111
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13