Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
biggroup_tables.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
7#pragma once
12
14
31template <typename C, class Fq, class Fr, class G>
32template <size_t num_elements>
35{
40 std::vector<std::array<field_t<C>, 2>> prime_limbs;
41
42 for (size_t i = 0; i < num_elements; ++i) {
43 limb_max[0] = std::max(limb_max[0], rom_data[i].x.binary_basis_limbs[0].maximum_value);
44 limb_max[1] = std::max(limb_max[1], rom_data[i].x.binary_basis_limbs[1].maximum_value);
45 limb_max[2] = std::max(limb_max[2], rom_data[i].x.binary_basis_limbs[2].maximum_value);
46 limb_max[3] = std::max(limb_max[3], rom_data[i].x.binary_basis_limbs[3].maximum_value);
47 limb_max[4] = std::max(limb_max[4], rom_data[i].y.binary_basis_limbs[0].maximum_value);
48 limb_max[5] = std::max(limb_max[5], rom_data[i].y.binary_basis_limbs[1].maximum_value);
49 limb_max[6] = std::max(limb_max[6], rom_data[i].y.binary_basis_limbs[2].maximum_value);
50 limb_max[7] = std::max(limb_max[7], rom_data[i].y.binary_basis_limbs[3].maximum_value);
51
52 x_lo_limbs.emplace_back(std::array<field_t<C>, 2>{ rom_data[i].x.binary_basis_limbs[0].element,
53 rom_data[i].x.binary_basis_limbs[1].element });
54 x_hi_limbs.emplace_back(std::array<field_t<C>, 2>{ rom_data[i].x.binary_basis_limbs[2].element,
55 rom_data[i].x.binary_basis_limbs[3].element });
56 y_lo_limbs.emplace_back(std::array<field_t<C>, 2>{ rom_data[i].y.binary_basis_limbs[0].element,
57 rom_data[i].y.binary_basis_limbs[1].element });
58 y_hi_limbs.emplace_back(std::array<field_t<C>, 2>{ rom_data[i].y.binary_basis_limbs[2].element,
59 rom_data[i].y.binary_basis_limbs[3].element });
60 prime_limbs.emplace_back(
61 std::array<field_t<C>, 2>{ rom_data[i].x.prime_basis_limb, rom_data[i].y.prime_basis_limb });
62 }
63 std::array<twin_rom_table<C>, Fq::NUM_LIMBS + 1> output_tables;
64 output_tables[0] = twin_rom_table<C>(x_lo_limbs);
65 output_tables[1] = twin_rom_table<C>(x_hi_limbs);
66 output_tables[2] = twin_rom_table<C>(y_lo_limbs);
67 output_tables[3] = twin_rom_table<C>(y_hi_limbs);
68 output_tables[4] = twin_rom_table<C>(prime_limbs);
69 return output_tables;
70}
71
72template <typename C, class Fq, class Fr, class G>
73template <size_t>
75 const std::array<twin_rom_table<C>, Fq::NUM_LIMBS + 1>& tables,
76 const field_t<C>& index,
78{
79 const auto xlo = tables[0][index];
80 const auto xhi = tables[1][index];
81 const auto ylo = tables[2][index];
82 const auto yhi = tables[3][index];
83 const auto xyprime = tables[4][index];
84
85 // We assign maximum_value of each limb here, so we can use the unsafe API from element construction
86 Fq x_fq = Fq::unsafe_construct_from_limbs(xlo[0], xlo[1], xhi[0], xhi[1], xyprime[0]);
87 Fq y_fq = Fq::unsafe_construct_from_limbs(ylo[0], ylo[1], yhi[0], yhi[1], xyprime[1]);
88 x_fq.binary_basis_limbs[0].maximum_value = limb_max[0];
89 x_fq.binary_basis_limbs[1].maximum_value = limb_max[1];
90 x_fq.binary_basis_limbs[2].maximum_value = limb_max[2];
91 x_fq.binary_basis_limbs[3].maximum_value = limb_max[3];
92 y_fq.binary_basis_limbs[0].maximum_value = limb_max[4];
93 y_fq.binary_basis_limbs[1].maximum_value = limb_max[5];
94 y_fq.binary_basis_limbs[2].maximum_value = limb_max[6];
95 y_fq.binary_basis_limbs[3].maximum_value = limb_max[7];
96
97 const auto output = element(x_fq, y_fq);
98 return output;
99}
100
101template <typename C, class Fq, class Fr, class G>
103{
104 element d2 = input.dbl();
105
106 element_table[8] = input;
107 for (size_t i = 9; i < 16; ++i) {
108 element_table[i] = element_table[i - 1] + d2;
109 }
110 for (size_t i = 0; i < 8; ++i) {
111 element_table[i] = (-element_table[15 - i]);
112 }
113
114 coordinates = create_group_element_rom_tables<16>(element_table, limb_max);
115}
116
117template <typename C, class Fq, class Fr, class G>
119{
120 return read_group_element_rom_tables<16>(coordinates, index, limb_max);
121}
122
123template <class C, class Fq, class Fr, class G>
125{
126 const auto get_plookup_tags = [this]() {
127 switch (curve_type) {
130 use_endomorphism ? MultiTableId::SECP256K1_XLO_ENDO : MultiTableId::SECP256K1_XLO,
131 use_endomorphism ? MultiTableId::SECP256K1_XHI_ENDO : MultiTableId::SECP256K1_XHI,
132 MultiTableId::SECP256K1_YLO,
133 MultiTableId::SECP256K1_YHI,
134 use_endomorphism ? MultiTableId::SECP256K1_XYPRIME_ENDO : MultiTableId::SECP256K1_XYPRIME,
135 };
136 }
137 case CurveType::BN254: {
139 use_endomorphism ? MultiTableId::BN254_XLO_ENDO : MultiTableId::BN254_XLO,
140 use_endomorphism ? MultiTableId::BN254_XHI_ENDO : MultiTableId::BN254_XHI,
141 MultiTableId::BN254_YLO,
142 MultiTableId::BN254_YHI,
143 use_endomorphism ? MultiTableId::BN254_XYPRIME_ENDO : MultiTableId::BN254_XYPRIME,
144 };
145 }
146 default: {
148 use_endomorphism ? MultiTableId::BN254_XLO_ENDO : MultiTableId::BN254_XLO,
149 use_endomorphism ? MultiTableId::BN254_XHI_ENDO : MultiTableId::BN254_XHI,
150 MultiTableId::BN254_YLO,
151 MultiTableId::BN254_YHI,
152 use_endomorphism ? MultiTableId::BN254_XYPRIME_ENDO : MultiTableId::BN254_XYPRIME,
153 };
154 }
155 }
156 };
157
158 const auto tags = get_plookup_tags();
159
160 const auto xlo = plookup_read<C>::read_pair_from_table(tags[0], index);
161 const auto xhi = plookup_read<C>::read_pair_from_table(tags[1], index);
162 const auto ylo = plookup_read<C>::read_pair_from_table(tags[2], index);
163 const auto yhi = plookup_read<C>::read_pair_from_table(tags[3], index);
164 const auto xyprime = plookup_read<C>::read_pair_from_table(tags[4], index);
165
166 // All the elements are precomputed constants so they are completely reduced, so the default maximum limb values are
167 // appropriate
168 Fq x = Fq::unsafe_construct_from_limbs(xlo.first, xlo.second, xhi.first, xhi.second, xyprime.first);
169 Fq y = Fq::unsafe_construct_from_limbs(ylo.first, ylo.second, yhi.first, yhi.second, xyprime.second);
170
171 if (use_endomorphism) {
172 y = -y;
173 }
174
175 return element(x, y);
176}
177
178template <typename C, class Fq, class Fr, class G>
180{
181 return operator[](field_t<C>(index));
182}
183
187template <typename C, class Fq, class Fr, class G>
188template <size_t length>
190{
191 static_assert(length <= 6, "lookup_table_plookup only supports up to 6 input elements");
192
193 if constexpr (length == 2) {
194 auto [A0, A1] = inputs[1].checked_unconditional_add_sub(inputs[0]);
195 element_table[0] = A0;
196 element_table[1] = A1;
197 } else if constexpr (length == 3) {
198 auto [R0, R1] = inputs[1].checked_unconditional_add_sub(inputs[0]); // B ± A
199
200 auto [T0, T1] = inputs[2].checked_unconditional_add_sub(R0); // C ± (B + A)
201 auto [T2, T3] = inputs[2].checked_unconditional_add_sub(R1); // C ± (B - A)
202
203 element_table[0] = T0;
204 element_table[1] = T2;
205 element_table[2] = T3;
206 element_table[3] = T1;
207 } else if constexpr (length == 4) {
208 auto [T0, T1] = inputs[1].checked_unconditional_add_sub(inputs[0]); // B ± A
209 auto [T2, T3] = inputs[3].checked_unconditional_add_sub(inputs[2]); // D ± C
210
211 auto [F0, F3] = T2.checked_unconditional_add_sub(T0); // (D + C) ± (B + A)
212 auto [F1, F2] = T2.checked_unconditional_add_sub(T1); // (D + C) ± (B - A)
213 auto [F4, F7] = T3.checked_unconditional_add_sub(T0); // (D - C) ± (B + A)
214 auto [F5, F6] = T3.checked_unconditional_add_sub(T1); // (D - C) ± (B - A)
215
216 element_table[0] = F0;
217 element_table[1] = F1;
218 element_table[2] = F2;
219 element_table[3] = F3;
220 element_table[4] = F4;
221 element_table[5] = F5;
222 element_table[6] = F6;
223 element_table[7] = F7;
224 } else if constexpr (length == 5) {
225 auto [A0, A1] = inputs[1].checked_unconditional_add_sub(inputs[0]); // B ± A
226 auto [T2, T3] = inputs[3].checked_unconditional_add_sub(inputs[2]); // D ± C
227
228 auto [E0, E3] = inputs[4].checked_unconditional_add_sub(T2); // E ± (D + C)
229 auto [E1, E2] = inputs[4].checked_unconditional_add_sub(T3); // E ± (D - C)
230
231 auto [F0, F3] = E0.checked_unconditional_add_sub(A0); // E + (D + C) ± (B + A)
232 auto [F1, F2] = E0.checked_unconditional_add_sub(A1); // E + (D + C) ± (B - A)
233 auto [F4, F7] = E1.checked_unconditional_add_sub(A0); // E + (D - C) ± (B + A)
234 auto [F5, F6] = E1.checked_unconditional_add_sub(A1); // E + (D - C) ± (B - A)
235 auto [F8, F11] = E2.checked_unconditional_add_sub(A0); // E - (D - C) ± (B + A)
236 auto [F9, F10] = E2.checked_unconditional_add_sub(A1); // E - (D - C) ± (B - A)
237 auto [F12, F15] = E3.checked_unconditional_add_sub(A0); // E - (D + C) ± (B + A)
238 auto [F13, F14] = E3.checked_unconditional_add_sub(A1); // E - (D + C) ± (B - A)
239
240 element_table[0] = F0;
241 element_table[1] = F1;
242 element_table[2] = F2;
243 element_table[3] = F3;
244 element_table[4] = F4;
245 element_table[5] = F5;
246 element_table[6] = F6;
247 element_table[7] = F7;
248 element_table[8] = F8;
249 element_table[9] = F9;
250 element_table[10] = F10;
251 element_table[11] = F11;
252 element_table[12] = F12;
253 element_table[13] = F13;
254 element_table[14] = F14;
255 element_table[15] = F15;
256 } else if constexpr (length == 6) {
257 // 44 adds! Only use this if it saves us adding another table to a multi-scalar-multiplication
258
259 auto [A0, A1] = inputs[1].checked_unconditional_add_sub(inputs[0]);
260 auto [E0, E1] = inputs[4].checked_unconditional_add_sub(inputs[3]);
261 auto [C0, C3] = inputs[2].checked_unconditional_add_sub(A0);
262 auto [C1, C2] = inputs[2].checked_unconditional_add_sub(A1);
263
264 auto [F0, F3] = inputs[5].checked_unconditional_add_sub(E0);
265 auto [F1, F2] = inputs[5].checked_unconditional_add_sub(E1);
266
267 auto [R0, R7] = F0.checked_unconditional_add_sub(C0);
268 auto [R1, R6] = F0.checked_unconditional_add_sub(C1);
269 auto [R2, R5] = F0.checked_unconditional_add_sub(C2);
270 auto [R3, R4] = F0.checked_unconditional_add_sub(C3);
271
272 auto [S0, S7] = F1.checked_unconditional_add_sub(C0);
273 auto [S1, S6] = F1.checked_unconditional_add_sub(C1);
274 auto [S2, S5] = F1.checked_unconditional_add_sub(C2);
275 auto [S3, S4] = F1.checked_unconditional_add_sub(C3);
276
277 auto [U0, U7] = F2.checked_unconditional_add_sub(C0);
278 auto [U1, U6] = F2.checked_unconditional_add_sub(C1);
279 auto [U2, U5] = F2.checked_unconditional_add_sub(C2);
280 auto [U3, U4] = F2.checked_unconditional_add_sub(C3);
281
282 auto [W0, W7] = F3.checked_unconditional_add_sub(C0);
283 auto [W1, W6] = F3.checked_unconditional_add_sub(C1);
284 auto [W2, W5] = F3.checked_unconditional_add_sub(C2);
285 auto [W3, W4] = F3.checked_unconditional_add_sub(C3);
286
287 element_table[0] = R0;
288 element_table[1] = R1;
289 element_table[2] = R2;
290 element_table[3] = R3;
291 element_table[4] = R4;
292 element_table[5] = R5;
293 element_table[6] = R6;
294 element_table[7] = R7;
295
296 element_table[8] = S0;
297 element_table[9] = S1;
298 element_table[10] = S2;
299 element_table[11] = S3;
300 element_table[12] = S4;
301 element_table[13] = S5;
302 element_table[14] = S6;
303 element_table[15] = S7;
304
305 element_table[16] = U0;
306 element_table[17] = U1;
307 element_table[18] = U2;
308 element_table[19] = U3;
309 element_table[20] = U4;
310 element_table[21] = U5;
311 element_table[22] = U6;
312 element_table[23] = U7;
313
314 element_table[24] = W0;
315 element_table[25] = W1;
316 element_table[26] = W2;
317 element_table[27] = W3;
318 element_table[28] = W4;
319 element_table[29] = W5;
320 element_table[30] = W6;
321 element_table[31] = W7;
322 }
323 for (size_t i = 0; i < table_size / 2; ++i) {
324 element_table[i + (table_size / 2)] = (-element_table[(table_size / 2) - 1 - i]);
325 }
326 coordinates = create_group_element_rom_tables<table_size>(element_table, limb_max);
327}
328
329template <typename C, class Fq, class Fr, class G>
330template <size_t length>
332 const std::array<bool_ct, length>& bits) const
333{
334 std::vector<field_t<C>> accumulators;
335 for (size_t i = 0; i < length; ++i) {
336 accumulators.emplace_back(field_t<C>(bits[i]) * (1ULL << i));
337 }
338 field_t<C> index = field_t<C>::accumulate(accumulators);
339 return read_group_element_rom_tables<table_size>(coordinates, index, limb_max);
340}
341
373template <typename C, class Fq, class Fr, class G>
377{
380 element d2 = input.dbl();
381
382 P1.element_table[8] = input;
383 for (size_t i = 9; i < 16; ++i) {
384 P1.element_table[i] = P1.element_table[i - 1] + d2;
385 }
386 for (size_t i = 0; i < 8; ++i) {
387 P1.element_table[i] = (-P1.element_table[15 - i]);
388 }
389 for (size_t i = 0; i < 16; ++i) {
390 endoP1.element_table[i].y = P1.element_table[15 - i].y;
391 }
393 Fq beta(bb::fr(beta_val.slice(0, 136)), bb::fr(beta_val.slice(136, 256)));
394 for (size_t i = 0; i < 8; ++i) {
395 endoP1.element_table[i].x = P1.element_table[i].x * beta;
396 endoP1.element_table[15 - i].x = endoP1.element_table[i].x;
397 }
398 P1.coordinates = create_group_element_rom_tables<16>(P1.element_table, P1.limb_max);
399 endoP1.coordinates = create_group_element_rom_tables<16>(endoP1.element_table, endoP1.limb_max);
401 return result;
402}
403
404} // namespace bb::stdlib::element_default
constexpr uint256_t slice(uint64_t start, uint64_t end) const
std::array< element, 2 > checked_unconditional_add_sub(const element &other) const
Compute (*this) + other AND (*this) - other as a size-2 array.
static field_t accumulate(const std::vector< field_t > &input)
Efficiently compute the sum of vector entries. Using big_add_gate we reduce the number of gates neede...
Definition field.cpp:1157
static std::pair< field_pt, field_pt > read_pair_from_table(const plookup::MultiTableId id, const field_pt &key)
Definition plookup.cpp:70
uint8_t const size_t length
Definition data_store.hpp:9
std::conditional_t< IsGoblinBigGroup< C, Fq, Fr, G >, element_goblin::goblin_element< C, goblin_field< C >, Fr, G >, element_default::element< C, Fq, Fr, G > > element
element wraps either element_default::element or element_goblin::goblin_element depending on parametr...
@ SECP256K1
Definition types.hpp:10
@ BN254
Definition types.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field cube_root_of_unity()
Four-bit variable-base table for scalar multiplication.
Definition biggroup.hpp:600
std::array< uint256_t, Fq::NUM_LIMBS *2 > limb_max
Definition biggroup.hpp:616
std::array< twin_rom_table< Builder >, Fq::NUM_LIMBS+1 > coordinates
Definition biggroup.hpp:615