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: 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
9namespace bb {
28{
29 // The vector of groups of polynomials to be interleaved
30 auto interleaved = proving_key->polynomials.get_groups_to_be_interleaved();
31 // Resulting interleaved polynomials
32 auto targets = proving_key->polynomials.get_interleaved();
33
34 const size_t num_polys_in_group = interleaved[0].size();
36
37 // Targets have to be full-sized proving_key->polynomials. We can compute the mini circuit size from them by
38 // dividing by the number of polynomials in the group
39 const size_t MINI_CIRCUIT_SIZE = targets[0].size() / num_polys_in_group;
40 BB_ASSERT_EQ(MINI_CIRCUIT_SIZE * num_polys_in_group, targets[0].size());
41
42 auto ordering_function = [&](size_t index) {
43 // Get the index of the interleaved polynomial
44 size_t i = index / interleaved[0].size();
45 // Get the index of the original polynomial
46 size_t j = index % interleaved[0].size();
47 auto& group = interleaved[i];
48 auto& current_target = targets[i];
49
50 // Copy into appropriate position in the interleaved polynomial
51 // We offset by start_index() as the first 0 is not physically represented for shiftable values
52 for (size_t k = group[j].start_index(); k < group[j].end_index(); k++) {
53 current_target.at(k * num_polys_in_group + j) = group[j][k];
54 }
55 };
56 parallel_for(interleaved.size() * num_polys_in_group, ordering_function);
57}
58
82{
83 // Get constants
84 constexpr size_t num_interleaved_wires = Flavor::NUM_INTERLEAVED_WIRES;
85
86 RefArray ordered_constraint_polynomials{ proving_key->polynomials.ordered_range_constraints_0,
87 proving_key->polynomials.ordered_range_constraints_1,
88 proving_key->polynomials.ordered_range_constraints_2,
89 proving_key->polynomials.ordered_range_constraints_3 };
90 std::vector<size_t> extra_denominator_uint(dyadic_circuit_size_without_masking);
91
92 const auto sorted_elements = get_sorted_steps();
93 auto to_be_interleaved_groups = proving_key->polynomials.get_groups_to_be_interleaved();
94
95 // Given the polynomials in group_i, transfer their elements, sorted in non-descending order, into the corresponding
96 // ordered_range_constraint_i up to the given capacity and the remaining elements to the last range constraint.
97 // Sorting is done by converting the elements to uint for efficiency.
98 auto ordering_function = [&](size_t i) {
99 auto group = to_be_interleaved_groups[i];
100 std::vector<uint32_t> ordered_vectors_uint(dyadic_circuit_size_without_masking);
101
102 // Calculate how much space there is for values from the group polynomials given we also need to append the
103 // additional steps
104 auto free_space_before_runway = dyadic_circuit_size_without_masking - sorted_elements.size();
105
106 // Calculate the starting index of this group's overflowing elements in the extra denominator polynomial
107 size_t extra_denominator_offset = i * sorted_elements.size();
108
109 // Go through each polynomial in the interleaved group
110 for (size_t j = 0; j < Flavor::INTERLEAVING_GROUP_SIZE; j++) {
111
112 // Calculate the offset in the target vector
113 auto current_offset = j * dyadic_mini_circuit_size_without_masking;
114 ;
115 // For each element in the polynomial
116 for (size_t k = group[j].start_index(); k < group[j].end_index() - NUM_DISABLED_ROWS_IN_SUMCHECK; k++) {
117
118 // Put it it the target polynomial
119 if ((current_offset + k) < free_space_before_runway) {
120 ordered_vectors_uint[current_offset + k] = static_cast<uint32_t>(uint256_t(group[j][k]).data[0]);
121
122 // Or in the extra one if there is no space left
123 } else {
124 extra_denominator_uint[extra_denominator_offset] =
125 static_cast<uint32_t>(uint256_t(group[j][k]).data[0]);
126 extra_denominator_offset++;
127 }
128 }
129 }
130 // Advance the iterator past the last written element in the range constraint polynomial and complete it with
131 // sorted steps
132 auto ordered_vector_it = ordered_vectors_uint.begin();
133 std::advance(ordered_vector_it, free_space_before_runway);
134 std::copy(sorted_elements.cbegin(), sorted_elements.cend(), ordered_vector_it);
135
136 // Sort the polynomial in nondescending order. We sort using the size_t vector for 2 reasons:
137 // 1. It is faster to sort size_t
138 // 2. Comparison operators for finite fields are operating on internal form, so we'd have to convert them
139 // from Montgomery
140 std::sort(ordered_vectors_uint.begin(), ordered_vectors_uint.end());
141 BB_ASSERT_EQ(ordered_vectors_uint.size(), dyadic_circuit_size_without_masking);
142 // Copy the values into the actual polynomial
143 ordered_constraint_polynomials[i].copy_vector(ordered_vectors_uint);
144 };
145
146 // Construct the first 4 polynomials
147 parallel_for(num_interleaved_wires, ordering_function);
148
149 // Advance the iterator into the extra range constraint past the last written element
150 auto extra_denominator_it = extra_denominator_uint.begin();
151 std::advance(extra_denominator_it, num_interleaved_wires * sorted_elements.size());
152
153 // Add steps to the extra denominator polynomial to fill it
154 std::copy(sorted_elements.cbegin(), sorted_elements.cend(), extra_denominator_it);
155 // Sort it
156#ifdef NO_PAR_ALGOS
157 std::sort(extra_denominator_uint.begin(), extra_denominator_uint.end());
158#else
159 std::sort(std::execution::par_unseq, extra_denominator_uint.begin(), extra_denominator_uint.end());
160#endif
161
162 // Copy the values into the actual polynomial
163 proving_key->polynomials.ordered_range_constraints_4.copy_vector(extra_denominator_uint);
164
165 // Transfer randomness from interleaved to ordered polynomials such that the commitments and evaluations of all
166 // ordered polynomials and their shifts are hidden
168}
169
185{
186 auto interleaved = proving_key->polynomials.get_interleaved();
187 auto ordered = proving_key->polynomials.get_ordered_range_constraints();
188 const size_t num_ordered_polynomials = ordered.size();
189
190 const size_t total_num_random_values =
191 NUM_DISABLED_ROWS_IN_SUMCHECK * Flavor::NUM_INTERLEAVED_WIRES * Flavor::INTERLEAVING_GROUP_SIZE;
192 const size_t num_random_values_per_interleaved = NUM_DISABLED_ROWS_IN_SUMCHECK * Flavor::INTERLEAVING_GROUP_SIZE;
193 const size_t num_random_values_per_ordered = total_num_random_values / num_ordered_polynomials;
194 const size_t remaining_random_values = total_num_random_values % num_ordered_polynomials;
195
197 random_values = {};
198
199 // Add the random values from all interleaved polynomials to an array
201 size_t idx = i * num_random_values_per_interleaved;
202 auto current_interleaved = interleaved[i];
203 for (size_t j = dyadic_circuit_size_without_masking; j < current_interleaved.end_index(); j++) {
204 random_values[idx] = current_interleaved.at(j);
205 idx++;
206 }
207 });
208
209 // Split them across the ordered polynomials
210 size_t end = dyadic_circuit_size_without_masking + num_random_values_per_ordered;
211 parallel_for(num_ordered_polynomials, [&](size_t i) {
212 size_t index_into_random = i * num_random_values_per_ordered;
213 auto& current_ordered = ordered[i];
214 for (size_t j = dyadic_circuit_size_without_masking; j < end; j++) {
215 current_ordered.at(j) = random_values[index_into_random];
216 index_into_random++;
217 }
218 });
219
220 // As the total number of random values might not a multiple of num_ordered_polynomials (and is definitely not the
221 // current translator configurations) the remaining values are distributed across the ordered polynomials. The
222 // configurations ensure this still remain within boundaries of the polynomial size otherwise the assignment would
223 // fail.
224 size_t index_into_random = num_ordered_polynomials * num_random_values_per_ordered;
225 BB_ASSERT_LT(remaining_random_values, num_ordered_polynomials);
226 BB_ASSERT_LT(end, ordered[0].end_index());
227 for (size_t i = 0; i < remaining_random_values; i++) {
228 ordered[i].at(end) = random_values[index_into_random];
229 index_into_random++;
230 }
231}
232
238{
239
240 proving_key->polynomials.lagrange_first.at(0) = 1;
241 proving_key->polynomials.lagrange_real_last.at(dyadic_circuit_size_without_masking - 1) = 1;
242 proving_key->polynomials.lagrange_last.at(dyadic_circuit_size - 1) = 1;
243
244 // Location of randomness for the polynomials defined within the large size
246 proving_key->polynomials.lagrange_masking.at(i) = 1;
247 }
248
249 // Location of randomness for wires defined within the mini circuit
251 proving_key->polynomials.lagrange_mini_masking.at(i) = 1;
252 }
253
254 // Translator VM processes two rows of its execution trace at a time, establishing different relations between
255 // polynomials at even and odd indices, as such we need corresponding lagranges for determining whic relations
256 // should trigger at odd indices and which at even.
257 for (size_t i = 2; i < dyadic_mini_circuit_size_without_masking; i += 2) {
258 proving_key->polynomials.lagrange_even_in_minicircuit.at(i) = 1;
259 proving_key->polynomials.lagrange_odd_in_minicircuit.at(i + 1) = 1;
260 }
261
262 // Position of evaluation result
263 proving_key->polynomials.lagrange_result_row.at(Flavor::RESULT_ROW) = 1;
264 proving_key->polynomials.lagrange_last_in_minicircuit.at(dyadic_mini_circuit_size_without_masking - 1) = 1;
265}
266
283{
284
285 const auto sorted_elements = get_sorted_steps();
286 // TODO(#756): can be parallelized further. This will use at most 5 threads
287 auto fill_with_shift = [&](size_t shift) {
288 for (size_t i = 0; i < sorted_elements.size(); i++) {
289 proving_key->polynomials.ordered_extra_range_constraints_numerator.at(
290 shift + i * (Flavor::NUM_INTERLEAVED_WIRES + 1)) = sorted_elements[i];
291 }
292 };
293 // Fill polynomials with a sequence, where each element is repeated NUM_INTERLEAVED_WIRES+1 times
294 parallel_for(Flavor::NUM_INTERLEAVED_WIRES + 1, fill_with_shift);
295}
296} // namespace bb
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:59
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:115
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 NUM_INTERLEAVED_WIRES
static constexpr size_t RESULT_ROW
static constexpr size_t INTERLEAVING_GROUP_SIZE
void compute_interleaved_polynomials()
Construct a set of polynomials that are the result of interleaving 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 split_interleaved_random_coefficients_to_ordered()
Distribute the randomness from the 4 interleaved polynomials to the 5 ordered range constraints such ...
void compute_translator_range_constraint_ordered_polynomials()
Compute denominator polynomials for Translator's range constraint permutation.
static constexpr size_t dyadic_circuit_size
std::shared_ptr< ProvingKey > proving_key
static constexpr size_t dyadic_mini_circuit_size_without_masking
void compute_lagrange_polynomials()
Set all the precomputed lagrange polynomials used in 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.
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
Definition thread.cpp:72
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13