Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
fixed_base.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
7#include "./fixed_base.hpp"
8
15
25 const affine_element& offset_generator)
26{
27
28 // Construct the table in projective coordinates, then batch normalize
30 element accumulator = offset_generator;
31 for (element& raw_entry : table_raw) {
32 raw_entry = accumulator;
33 accumulator += base_point;
34 }
36
37 // Construct the final table in affine coordinates
39 table.reserve(MAX_TABLE_SIZE);
40 for (const element& raw_entry : table_raw) {
41 table.emplace_back(raw_entry.x, raw_entry.y);
42 }
43 return table;
44}
45
56{
57 constexpr size_t NUM_TABLES = numeric::ceil_div(num_bits, BITS_PER_TABLE);
58
60 tables.reserve(NUM_TABLES);
61
62 std::vector<uint8_t> input_buf;
63 write(input_buf, input);
64 const auto offset_generators = grumpkin::g1::derive_generators(input_buf, NUM_TABLES);
65
66 grumpkin::g1::element accumulator = input;
67 for (size_t i = 0; i < NUM_TABLES; ++i) {
68 tables.push_back(generate_single_lookup_table(accumulator, offset_generators[i]));
69 for (size_t j = 0; j < BITS_PER_TABLE; ++j) {
70 accumulator = accumulator.dbl();
71 }
72 }
73 return tables;
74}
75
91template <size_t num_table_bits>
93{
94 constexpr size_t NUM_TABLES = numeric::ceil_div(num_table_bits, BITS_PER_TABLE);
95
96 // Serialize the base point to use as domain separator for generator derivation
97 std::vector<uint8_t> input_buf;
98 write(input_buf, input);
99
100 // Derive NUM_TABLES unique offset generators deterministically from the base point
101 const auto offset_generators = grumpkin::g1::derive_generators(input_buf, NUM_TABLES);
102
103 // Sum all offset generators
105 for (const auto& generator : offset_generators) {
106 total_offset += generator;
107 }
108
109 return total_offset;
110}
111
120{
121 return (input == lhs_generator_point() || input == rhs_generator_point());
122}
123
132{
133 BB_ASSERT_EQ(lookup_table_exists_for_point(input), true, "No fixed-base table exists for input point");
134 if (input == lhs_generator_point()) {
136 }
137 if (input == rhs_generator_point()) {
139 }
140 return {};
141}
142
150{
151 BB_ASSERT_EQ(table_id == FIXED_BASE_LEFT_LO || table_id == FIXED_BASE_LEFT_HI || table_id == FIXED_BASE_RIGHT_LO ||
152 table_id == FIXED_BASE_RIGHT_HI,
153 true);
154 if (table_id == FIXED_BASE_LEFT_LO) {
156 }
157 if (table_id == FIXED_BASE_LEFT_HI) {
159 }
160 if (table_id == FIXED_BASE_RIGHT_LO) {
162 }
163 if (table_id == FIXED_BASE_RIGHT_HI) {
165 }
166 return {};
167}
168
180{
182 bb::constexpr_for<0, table::NUM_FIXED_BASE_MULTI_TABLES, 1>([&]<size_t i>() {
183 bb::constexpr_for<0, table::MAX_NUM_TABLES_IN_MULTITABLE, 1>(
184 [&]<size_t j>() { table[i][j] = &table::get_basic_fixed_base_table_values<i, j>; });
185 });
186 return table;
187};
188
201template <size_t multitable_index>
202BasicTable table::generate_basic_fixed_base_table(BasicTableId id, size_t basic_table_index, size_t table_index)
203{
204 static_assert(multitable_index < NUM_FIXED_BASE_MULTI_TABLES);
206
207 const size_t multitable_bits = get_num_bits_of_multi_table<multitable_index>();
208 const size_t bits_covered_by_previous_tables_in_multitable = BITS_PER_TABLE * table_index;
209 const bool is_small_table = (multitable_bits - bits_covered_by_previous_tables_in_multitable) < BITS_PER_TABLE;
210 const size_t table_bits =
211 is_small_table ? multitable_bits - bits_covered_by_previous_tables_in_multitable : BITS_PER_TABLE;
212 const auto table_size = static_cast<size_t>(1ULL << table_bits);
213
214 BasicTable table{ .id = id, .table_index = basic_table_index, .use_twin_keys = false };
215
216 const auto& basic_table = fixed_base_tables()[multitable_index][table_index];
217
218 for (size_t i = 0; i < table_size; ++i) {
219 table.column_1.emplace_back(i);
220 table.column_2.emplace_back(basic_table[i].x);
221 table.column_3.emplace_back(basic_table[i].y);
222 }
223
224 constexpr function_ptr_table get_values_from_key_table = make_function_pointer_table();
225 table.get_values_from_key = get_values_from_key_table[multitable_index][table_index];
226 ASSERT(table.get_values_from_key != nullptr);
227
228 table.column_1_step_size = table_size;
229 table.column_2_step_size = COLUMN_2_STEP_SIZE;
230 table.column_3_step_size = COLUMN_3_STEP_SIZE;
231
232 return table;
233}
234
246template <size_t multitable_index, size_t num_bits> MultiTable table::get_fixed_base_table(const MultiTableId id)
247{
248 static_assert(num_bits == BITS_PER_LO_SCALAR || num_bits == BITS_PER_HI_SCALAR);
249 constexpr size_t NUM_TABLES = numeric::ceil_div(num_bits, BITS_PER_TABLE);
255 };
256 constexpr function_ptr_table get_values_from_key_table = make_function_pointer_table();
257
258 // For fixed base scalar mul lookup tables, the special "accumulator" structure of our lookup tables (see add ref
259 // bb::plookup::get_lookup_accumulators()) is used for the scalar (first column), but not for the (x,y) coordinates
260 // (columns 2 & 3). Each table entry contains a distinct point, not an accumulated point. This is so that we can use
261 // custom ECC addition gates to perform the accumulation efficiently, e.g. in
262 // cycle_group::_fixed_base_batch_mul_internal.
263 //
264 // To achieve this, we set the step sizes of each column as follows:
265 // - Column 1 coefficient: MAX_TABLE_SIZE (512) - creates accumulator structure for scalar slices
266 // - Column 2 coefficient: 0 - results in NO accumulation for x-coordinates
267 // - Column 3 coefficient: 0 - results in NO accumulation for y-coordinates
269 table.id = id;
270 table.get_table_values.resize(NUM_TABLES);
271 table.basic_table_ids.resize(NUM_TABLES);
272 for (size_t i = 0; i < NUM_TABLES; ++i) {
273 table.slice_sizes.emplace_back(MAX_TABLE_SIZE);
274 table.get_table_values[i] = get_values_from_key_table[multitable_index][i];
275 static_assert(multitable_index < NUM_FIXED_BASE_MULTI_TABLES);
276 size_t idx = i + static_cast<size_t>(basic_table_ids[multitable_index]);
277 table.basic_table_ids[i] = static_cast<plookup::BasicTableId>(idx);
278 }
279 return table;
280}
281
282template grumpkin::g1::affine_element table::compute_generator_offset<table::BITS_PER_LO_SCALAR>(
283 const grumpkin::g1::affine_element& input);
284template grumpkin::g1::affine_element table::compute_generator_offset<table::BITS_PER_HI_SCALAR>(
285 const grumpkin::g1::affine_element& input);
286template table::fixed_base_scalar_mul_tables table::generate_tables<table::BITS_PER_LO_SCALAR>(
287 const table::affine_element& input);
288template table::fixed_base_scalar_mul_tables table::generate_tables<table::BITS_PER_HI_SCALAR>(
289 const table::affine_element& input);
290
291template BasicTable table::generate_basic_fixed_base_table<0>(BasicTableId, size_t, size_t);
292template BasicTable table::generate_basic_fixed_base_table<1>(BasicTableId, size_t, size_t);
293template BasicTable table::generate_basic_fixed_base_table<2>(BasicTableId, size_t, size_t);
294template BasicTable table::generate_basic_fixed_base_table<3>(BasicTableId, size_t, size_t);
295template MultiTable table::get_fixed_base_table<0, table::BITS_PER_LO_SCALAR>(MultiTableId);
296template MultiTable table::get_fixed_base_table<1, table::BITS_PER_HI_SCALAR>(MultiTableId);
297template MultiTable table::get_fixed_base_table<2, table::BITS_PER_LO_SCALAR>(MultiTableId);
298template MultiTable table::get_fixed_base_table<3, table::BITS_PER_HI_SCALAR>(MultiTableId);
299
306{
307 static const table::all_multi_tables tables = {
308 table::generate_tables<BITS_PER_LO_SCALAR>(lhs_base_point_lo()),
309 table::generate_tables<BITS_PER_HI_SCALAR>(lhs_base_point_hi()),
310 table::generate_tables<BITS_PER_LO_SCALAR>(rhs_base_point_lo()),
311 table::generate_tables<BITS_PER_HI_SCALAR>(rhs_base_point_hi()),
312 };
313 return tables;
314}
315
322{
324 table::compute_generator_offset<BITS_PER_LO_SCALAR>(lhs_base_point_lo()),
325 table::compute_generator_offset<BITS_PER_HI_SCALAR>(lhs_base_point_hi()),
326 table::compute_generator_offset<BITS_PER_LO_SCALAR>(rhs_base_point_lo()),
327 table::compute_generator_offset<BITS_PER_HI_SCALAR>(rhs_base_point_hi()),
328 };
329 return tables;
330}
331
332} // namespace bb::plookup::fixed_base
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:88
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:148
#define ASSERT(expression,...)
Definition assert.hpp:77
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:33
constexpr element dbl() const noexcept
static void batch_normalize(element *elements, size_t num_elements) noexcept
static constexpr element point_at_infinity
Definition group.hpp:47
static std::vector< affine_element > derive_generators(const std::vector< uint8_t > &domain_separator_bytes, const size_t num_generators, const size_t starting_index=0)
Derives generator points via hash-to-curve.
Definition group.hpp:87
Generates plookup tables required to perform fixed-base scalar multiplication over a fixed number of ...
std::vector< affine_element > single_lookup_table
static MultiTable get_fixed_base_table(MultiTableId id)
Generate a multi-table that describes the lookups required to cover a fixed-base-scalar-mul of num_bi...
static affine_element get_generator_offset_for_table_id(MultiTableId table_id)
Given a table id, return the offset generator term that will be present in the final scalar mul outpu...
std::array< fixed_base_scalar_mul_tables, NUM_FIXED_BASE_MULTI_TABLES > all_multi_tables
static bool lookup_table_exists_for_point(const affine_element &input)
Returns true iff provided point is one of the two for which we have a precomputed lookup table.
static constexpr affine_element rhs_generator_point()
static single_lookup_table generate_single_lookup_table(const affine_element &base_point, const affine_element &offset_generator)
Given a base_point [P] and an offset_generator [G], compute a lookup table of MAX_TABLE_SIZE that con...
static fixed_base_scalar_mul_tables generate_tables(const affine_element &input)
For a given base point [P], compute the set of basic tables required to traverse a num_bits sized loo...
static const all_multi_tables & fixed_base_tables()
static affine_element lhs_base_point_lo()
static affine_element rhs_base_point_lo()
static const std::array< affine_element, table::NUM_FIXED_BASE_MULTI_TABLES > & fixed_base_table_offset_generators()
offset generators!
static affine_element lhs_base_point_hi()
static affine_element compute_generator_offset(const affine_element &input)
static std::array< MultiTableId, 2 > get_lookup_table_ids_for_point(const affine_element &input)
Given a point that is one of the two for which we have a precomputed lookup table,...
static BasicTable generate_basic_fixed_base_table(BasicTableId id, size_t basic_table_index, size_t table_index)
Generate a single fixed-base-scalar-mul plookup table.
static constexpr affine_element lhs_generator_point()
std::vector< single_lookup_table > fixed_base_scalar_mul_tables
static affine_element rhs_base_point_hi()
constexpr T ceil_div(const T &numerator, const T &denominator)
Computes the ceiling of the division of two integral types.
Definition general.hpp:23
std::array< bb::fr, 2 >(*)(const std::array< uint64_t, 2 >) function_ptr
std::array< std::array< function_ptr, table::MAX_NUM_TABLES_IN_MULTITABLE >, table::NUM_FIXED_BASE_MULTI_TABLES > function_ptr_table
constexpr function_ptr_table make_function_pointer_table()
create a compile-time static 2D array of all our required get_basic_fixed_base_table_values function ...
@ FIXED_BASE_3_0
Definition types.hpp:71
@ FIXED_BASE_0_0
Definition types.hpp:68
@ FIXED_BASE_2_0
Definition types.hpp:70
@ FIXED_BASE_1_0
Definition types.hpp:69
@ FIXED_BASE_RIGHT_HI
Definition types.hpp:103
@ FIXED_BASE_LEFT_LO
Definition types.hpp:100
@ FIXED_BASE_LEFT_HI
Definition types.hpp:101
@ FIXED_BASE_RIGHT_LO
Definition types.hpp:102
void write(std::vector< uint8_t > &buf, ClientIVC::VerificationKey const &vk)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
A basic table from which we can perform lookups (for example, an xor table)
Definition types.hpp:287
static constexpr size_t NUM_FIXED_BASE_MULTI_TABLES
static const bb::fr COLUMN_3_STEP_SIZE
static const bb::fr COLUMN_2_STEP_SIZE
static constexpr size_t MAX_TABLE_SIZE
static constexpr size_t BITS_PER_TABLE
static constexpr size_t BITS_PER_HI_SCALAR
static constexpr size_t MAX_NUM_TABLES_IN_MULTITABLE
static constexpr size_t BITS_PER_LO_SCALAR
Container for managing multiple BasicTables plus the data needed to combine basic table outputs (e....
Definition types.hpp:154