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: Complete, auditors: [Suyash], commit: 553c5eb82901955c638b943065acd3e47fc918c0}
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
12
14
31template <typename C, class Fq, class Fr, class G>
32template <size_t num_elements>
35{
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_ct, 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_ct, 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_ct, 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_ct, 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_ct, 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_ct& 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 // ROM table points are precomputed and known to be valid, skip curve check.
98 // Use 4-arg constructor with is_infinity=false (table lookups return valid, non-infinity points).
99 const auto output = element(x_fq, y_fq, bool_ct(x_fq.get_context(), false), /*assert_on_curve=*/false);
100 return output;
101}
102
103template <typename C, class Fq, class Fr, class G>
105{
106 element d2 = input.dbl();
107
108 element_table[8] = input;
109 for (size_t i = 9; i < 16; ++i) {
110 element_table[i] = element_table[i - 1] + d2;
111 }
112 for (size_t i = 0; i < 8; ++i) {
113 element_table[i] = (-element_table[15 - i]);
114 }
115
116 coordinates = create_group_element_rom_tables<16>(element_table, limb_max);
117}
118
119template <typename C, class Fq, class Fr, class G>
121{
122 return read_group_element_rom_tables<16>(coordinates, index, limb_max);
123}
124
125template <class C, class Fq, class Fr, class G>
127{
128 const auto get_plookup_tags = [this]() {
129 switch (curve_type) {
132 use_endomorphism ? MultiTableId::SECP256K1_XLO_ENDO : MultiTableId::SECP256K1_XLO,
133 use_endomorphism ? MultiTableId::SECP256K1_XHI_ENDO : MultiTableId::SECP256K1_XHI,
134 MultiTableId::SECP256K1_YLO,
135 MultiTableId::SECP256K1_YHI,
136 use_endomorphism ? MultiTableId::SECP256K1_XYPRIME_ENDO : MultiTableId::SECP256K1_XYPRIME,
137 };
138 }
139 default: {
140 throw_or_abort("eight_bit_fixed_base_table only supports SECP256K1 curve type");
141 }
142 }
143 };
144
145 const auto tags = get_plookup_tags();
146
147 const auto xlo = plookup_read<C>::read_pair_from_table(tags[0], index);
148 const auto xhi = plookup_read<C>::read_pair_from_table(tags[1], index);
149 const auto ylo = plookup_read<C>::read_pair_from_table(tags[2], index);
150 const auto yhi = plookup_read<C>::read_pair_from_table(tags[3], index);
151 const auto xyprime = plookup_read<C>::read_pair_from_table(tags[4], index);
152
153 // All the elements are precomputed constants so they are completely reduced, so the default maximum limb values are
154 // appropriate
155 Fq x = Fq::unsafe_construct_from_limbs(xlo.first, xlo.second, xhi.first, xhi.second, xyprime.first);
156 Fq y = Fq::unsafe_construct_from_limbs(ylo.first, ylo.second, yhi.first, yhi.second, xyprime.second);
157
158 if (use_endomorphism) {
159 y = -y;
160 }
161
162 // Points from precomputed tables are known to be on the curve.
163 // Use 4-arg constructor with is_infinity=false (table lookups return valid, non-infinity points).
164 return element(x, y, bool_ct(x.get_context(), false), /*assert_on_curve=*/false);
165}
166
167template <typename C, class Fq, class Fr, class G>
172
176template <typename C, class Fq, class Fr, class G>
177template <size_t length>
179{
180 static_assert(length <= 6, "lookup_table_plookup only supports up to 6 input elements");
181
182 if constexpr (length == 2) {
183 auto [A0, A1] = inputs[1].checked_unconditional_add_sub(inputs[0]);
184 element_table[0] = A0;
185 element_table[1] = A1;
186 } else if constexpr (length == 3) {
187 auto [R0, R1] = inputs[1].checked_unconditional_add_sub(inputs[0]); // B ± A
188
189 auto [T0, T1] = inputs[2].checked_unconditional_add_sub(R0); // C ± (B + A)
190 auto [T2, T3] = inputs[2].checked_unconditional_add_sub(R1); // C ± (B - A)
191
192 element_table[0] = T0;
193 element_table[1] = T2;
194 element_table[2] = T3;
195 element_table[3] = T1;
196 } else if constexpr (length == 4) {
197 auto [T0, T1] = inputs[1].checked_unconditional_add_sub(inputs[0]); // B ± A
198 auto [T2, T3] = inputs[3].checked_unconditional_add_sub(inputs[2]); // D ± C
199
200 auto [F0, F3] = T2.checked_unconditional_add_sub(T0); // (D + C) ± (B + A)
201 auto [F1, F2] = T2.checked_unconditional_add_sub(T1); // (D + C) ± (B - A)
202 auto [F4, F7] = T3.checked_unconditional_add_sub(T0); // (D - C) ± (B + A)
203 auto [F5, F6] = T3.checked_unconditional_add_sub(T1); // (D - C) ± (B - A)
204
205 element_table[0] = F0;
206 element_table[1] = F1;
207 element_table[2] = F2;
208 element_table[3] = F3;
209 element_table[4] = F4;
210 element_table[5] = F5;
211 element_table[6] = F6;
212 element_table[7] = F7;
213 } else if constexpr (length == 5) {
214 auto [A0, A1] = inputs[1].checked_unconditional_add_sub(inputs[0]); // B ± A
215 auto [T2, T3] = inputs[3].checked_unconditional_add_sub(inputs[2]); // D ± C
216
217 auto [E0, E3] = inputs[4].checked_unconditional_add_sub(T2); // E ± (D + C)
218 auto [E1, E2] = inputs[4].checked_unconditional_add_sub(T3); // E ± (D - C)
219
220 auto [F0, F3] = E0.checked_unconditional_add_sub(A0); // E + (D + C) ± (B + A)
221 auto [F1, F2] = E0.checked_unconditional_add_sub(A1); // E + (D + C) ± (B - A)
222 auto [F4, F7] = E1.checked_unconditional_add_sub(A0); // E + (D - C) ± (B + A)
223 auto [F5, F6] = E1.checked_unconditional_add_sub(A1); // E + (D - C) ± (B - A)
224 auto [F8, F11] = E2.checked_unconditional_add_sub(A0); // E - (D - C) ± (B + A)
225 auto [F9, F10] = E2.checked_unconditional_add_sub(A1); // E - (D - C) ± (B - A)
226 auto [F12, F15] = E3.checked_unconditional_add_sub(A0); // E - (D + C) ± (B + A)
227 auto [F13, F14] = E3.checked_unconditional_add_sub(A1); // E - (D + C) ± (B - A)
228
229 element_table[0] = F0;
230 element_table[1] = F1;
231 element_table[2] = F2;
232 element_table[3] = F3;
233 element_table[4] = F4;
234 element_table[5] = F5;
235 element_table[6] = F6;
236 element_table[7] = F7;
237 element_table[8] = F8;
238 element_table[9] = F9;
239 element_table[10] = F10;
240 element_table[11] = F11;
241 element_table[12] = F12;
242 element_table[13] = F13;
243 element_table[14] = F14;
244 element_table[15] = F15;
245 } else if constexpr (length == 6) {
246 // 44 adds! Only use this if it saves us adding another table to a multi-scalar-multiplication
247
248 auto [A0, A1] = inputs[1].checked_unconditional_add_sub(inputs[0]);
249 auto [E0, E1] = inputs[4].checked_unconditional_add_sub(inputs[3]);
250 auto [C0, C3] = inputs[2].checked_unconditional_add_sub(A0);
251 auto [C1, C2] = inputs[2].checked_unconditional_add_sub(A1);
252
253 auto [F0, F3] = inputs[5].checked_unconditional_add_sub(E0);
254 auto [F1, F2] = inputs[5].checked_unconditional_add_sub(E1);
255
256 auto [R0, R7] = F0.checked_unconditional_add_sub(C0);
257 auto [R1, R6] = F0.checked_unconditional_add_sub(C1);
258 auto [R2, R5] = F0.checked_unconditional_add_sub(C2);
259 auto [R3, R4] = F0.checked_unconditional_add_sub(C3);
260
261 auto [S0, S7] = F1.checked_unconditional_add_sub(C0);
262 auto [S1, S6] = F1.checked_unconditional_add_sub(C1);
263 auto [S2, S5] = F1.checked_unconditional_add_sub(C2);
264 auto [S3, S4] = F1.checked_unconditional_add_sub(C3);
265
266 auto [U0, U7] = F2.checked_unconditional_add_sub(C0);
267 auto [U1, U6] = F2.checked_unconditional_add_sub(C1);
268 auto [U2, U5] = F2.checked_unconditional_add_sub(C2);
269 auto [U3, U4] = F2.checked_unconditional_add_sub(C3);
270
271 auto [W0, W7] = F3.checked_unconditional_add_sub(C0);
272 auto [W1, W6] = F3.checked_unconditional_add_sub(C1);
273 auto [W2, W5] = F3.checked_unconditional_add_sub(C2);
274 auto [W3, W4] = F3.checked_unconditional_add_sub(C3);
275
276 element_table[0] = R0;
277 element_table[1] = R1;
278 element_table[2] = R2;
279 element_table[3] = R3;
280 element_table[4] = R4;
281 element_table[5] = R5;
282 element_table[6] = R6;
283 element_table[7] = R7;
284
285 element_table[8] = S0;
286 element_table[9] = S1;
287 element_table[10] = S2;
288 element_table[11] = S3;
289 element_table[12] = S4;
290 element_table[13] = S5;
291 element_table[14] = S6;
292 element_table[15] = S7;
293
294 element_table[16] = U0;
295 element_table[17] = U1;
296 element_table[18] = U2;
297 element_table[19] = U3;
298 element_table[20] = U4;
299 element_table[21] = U5;
300 element_table[22] = U6;
301 element_table[23] = U7;
302
303 element_table[24] = W0;
304 element_table[25] = W1;
305 element_table[26] = W2;
306 element_table[27] = W3;
307 element_table[28] = W4;
308 element_table[29] = W5;
309 element_table[30] = W6;
310 element_table[31] = W7;
311 }
312 for (size_t i = 0; i < table_size / 2; ++i) {
313 element_table[i + (table_size / 2)] = (-element_table[(table_size / 2) - 1 - i]);
314 }
315 coordinates = create_group_element_rom_tables<table_size>(element_table, limb_max);
316}
317
318template <typename C, class Fq, class Fr, class G>
319template <size_t length>
321 const std::array<bool_ct, length>& bits) const
322{
323 std::vector<field_ct> accumulators;
324 for (size_t i = 0; i < length; ++i) {
325 accumulators.emplace_back(field_ct(bits[i]) * (1ULL << i));
326 }
327 field_ct index = field_ct::accumulate(accumulators);
328 return read_group_element_rom_tables<table_size>(coordinates, index, limb_max);
329}
330
362template <typename C, class Fq, class Fr, class G>
366{
369 element d2 = input.dbl();
370
371 P1.element_table[8] = input;
372 for (size_t i = 9; i < 16; ++i) {
373 P1.element_table[i] = P1.element_table[i - 1] + d2;
374 }
375 for (size_t i = 0; i < 8; ++i) {
376 P1.element_table[i] = (-P1.element_table[15 - i]);
377 }
378 for (size_t i = 0; i < 16; ++i) {
379 endoP1.element_table[i]._y = P1.element_table[15 - i]._y;
380 }
382 Fq beta(bb::fr(beta_val.slice(0, 136)), bb::fr(beta_val.slice(136, 256)));
383 for (size_t i = 0; i < 8; ++i) {
384 endoP1.element_table[i]._x = P1.element_table[i]._x * beta;
385 endoP1.element_table[15 - i]._x = endoP1.element_table[i]._x;
386 }
387 P1.coordinates = create_group_element_rom_tables<16>(P1.element_table, P1.limb_max);
388 endoP1.coordinates = create_group_element_rom_tables<16>(endoP1.element_table, endoP1.limb_max);
390 return result;
391}
392
393} // namespace bb::stdlib::element_default
constexpr uint256_t slice(uint64_t start, uint64_t end) const
Implements boolean logic in-circuit.
Definition bool.hpp:60
std::array< element, 2 > checked_unconditional_add_sub(const element &other) const
Compute both add and subtract (a + b, a - b) results simultaneously.
element dbl() const
Evaluates a point doubling.
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:1178
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
stdlib::field_t< Builder > field_ct
AvmProvingInputs inputs
@ SECP256K1
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:590
std::array< uint256_t, Fq::NUM_LIMBS *2 > limb_max
Definition biggroup.hpp:606
std::array< twin_rom_table< Builder >, Fq::NUM_LIMBS+1 > coordinates
Definition biggroup.hpp:605
void throw_or_abort(std::string const &err)