Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
secp256r1_fixed_base.cpp
Go to the documentation of this file.
2
3#include "./types.hpp"
9
11
12// Static storage for the precomputed table entries.
16
18{
20 constexpr AffineElement H =
21 bb::get_precomputed_generators<G1, "biggroup table offset generator", 1UL, 0UL>()[0];
22
23 // Step per window: 2^(8w) · G.
24 Element window_step = Element(G1::affine_one);
25
26 // Total offset accumulator: sums all 2^w · H contributions.
27 Element offset_total = Element::infinity();
28
29 for (size_t w = 0; w < NUM_WINDOWS; ++w) {
30 // Per-window offset: 2^w · H. We compute it by doubling H w times rather than scalar-mul to keep this
31 // straightforward; this code runs once per process so the cost is irrelevant.
32 const G1::Fr offset_scalar(uint256_t(1) << w);
33 const Element window_offset = Element(H) * offset_scalar;
34 offset_total += window_offset;
35
36 // Build the entries for this window: T[k] = k · window_step + window_offset. The per-window
37 // size and step are determined by table_size(w) and window_bits(w) (7-bit "big" windows
38 // plus a 3-bit lo-tail and a 1-bit hi-tail).
39 const size_t ts = table_size(w);
40 const size_t wb = window_bits(w);
42 projective[0] = window_offset;
43 for (size_t k = 1; k < ts; ++k) {
44 projective[k] = projective[k - 1] + window_step;
45 }
46 Element::batch_normalize(projective.data(), ts);
47 for (size_t k = 0; k < ts; ++k) {
48 native_table[w][k] = AffineElement(projective[k].x, projective[k].y);
49 }
50
51 // Advance the step for the next window: window_step *= 2^window_bits(w).
52 for (size_t i = 0; i < wb; ++i) {
53 window_step = window_step.dbl();
54 }
55 }
56
57 cached_total_offset = AffineElement(offset_total);
58 });
59}
60
66
68{
69 constexpr uint64_t NUM_LIMB_BITS = stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION;
70 constexpr uint256_t LIMB_MASK = (uint256_t(1) << NUM_LIMB_BITS) - uint256_t(1);
71
72 auto limb_pair = [&](const uint256_t& val, size_t low_limb_idx) {
73 return std::array<bb::fr, 2>{ bb::fr((val >> (low_limb_idx * NUM_LIMB_BITS)) & LIMB_MASK),
74 bb::fr((val >> ((low_limb_idx + 1) * NUM_LIMB_BITS)) & LIMB_MASK) };
75 };
76
77 const uint256_t x_uint(point.x);
78 const uint256_t y_uint(point.y);
79
80 switch (axis) {
81 case AXIS_XLO:
82 return limb_pair(x_uint, 0);
83 case AXIS_XHI:
84 return limb_pair(x_uint, 2);
85 case AXIS_YLO:
86 return limb_pair(y_uint, 0);
87 case AXIS_YHI:
88 return limb_pair(y_uint, 2);
89 }
90 return { bb::fr(0), bb::fr(0) }; // unreachable
91}
92
93template <table::AxisIndex axis, size_t window_idx> std::array<bb::fr, 2> table::get_values(std::array<uint64_t, 2> key)
94{
96 const size_t index = static_cast<size_t>(key[0]);
97 BB_ASSERT_LT(index, table_size(window_idx));
98 return extract_axis(native_table[window_idx][index], axis);
99}
100
101template <table::AxisIndex axis, size_t window_idx>
103{
104 init_tables();
105
106 constexpr size_t TS = table_size(window_idx);
107
108 BasicTable t;
109 t.id = id;
110 t.table_index = table_index;
111 t.use_twin_keys = false;
112 t.column_1.reserve(TS);
113 t.column_2.reserve(TS);
114 t.column_3.reserve(TS);
115 for (size_t k = 0; k < TS; ++k) {
116 const auto [val_a, val_b] = extract_axis(native_table[window_idx][k], axis);
117 t.column_1.emplace_back(k);
118 t.column_2.emplace_back(val_a);
119 t.column_3.emplace_back(val_b);
120 }
121 t.get_values_from_key = &get_values<axis, window_idx>;
125 return t;
126}
127
128namespace {
129// Returns `&table::generate_basic_table<axis, window_idx>` for a runtime window_idx. The 32-entry
130// function-pointer array is built once at compile time and shared across calls.
131using generate_fn_ptr = BasicTable (*)(BasicTableId, size_t);
132
133template <table::AxisIndex axis> generate_fn_ptr generate_fn_for_window(size_t window_idx)
134{
135 static constexpr auto fns = []() {
137 [&]<size_t... Is>(std::index_sequence<Is...>) {
138 ((arr[Is] = &table::generate_basic_table<axis, Is>), ...);
140 return arr;
141 }();
142 return fns[window_idx];
143}
144} // namespace
145
146template <table::AxisIndex axis>
147BasicTable table::generate_basic_table_runtime(BasicTableId id, size_t window_idx, size_t table_index)
148{
149 BB_ASSERT_LT(window_idx, NUM_WINDOWS);
150 return generate_fn_for_window<axis>(window_idx)(id, table_index);
151}
152
153// Explicit instantiations for the four axes.
154template BasicTable table::generate_basic_table_runtime<table::AXIS_XLO>(BasicTableId, size_t, size_t);
155template BasicTable table::generate_basic_table_runtime<table::AXIS_XHI>(BasicTableId, size_t, size_t);
156template BasicTable table::generate_basic_table_runtime<table::AXIS_YLO>(BasicTableId, size_t, size_t);
157template BasicTable table::generate_basic_table_runtime<table::AXIS_YHI>(BasicTableId, size_t, size_t);
158
159namespace {
160// Returns `&table::get_values<axis, window_idx>` for a runtime (axis, window_idx). The per-axis 32-entry
161// function-pointer array is built once at compile time and shared across calls.
162using get_values_fn_ptr = std::array<bb::fr, 2> (*)(std::array<uint64_t, 2>);
163
164template <table::AxisIndex axis> get_values_fn_ptr get_values_fn_for_window(size_t window_idx)
165{
166 static constexpr auto fns = []() {
168 [&]<size_t... Is>(std::index_sequence<Is...>) {
169 ((arr[Is] = &table::get_values<axis, Is>), ...);
171 return arr;
172 }();
173 return fns[window_idx];
174}
175
176get_values_fn_ptr lookup_get_values(table::AxisIndex axis, size_t window_idx)
177{
178 BB_ASSERT_LT(window_idx, table::NUM_WINDOWS);
179 switch (axis) {
180 case table::AXIS_XLO:
181 return get_values_fn_for_window<table::AXIS_XLO>(window_idx);
182 case table::AXIS_XHI:
183 return get_values_fn_for_window<table::AXIS_XHI>(window_idx);
184 case table::AXIS_YLO:
185 return get_values_fn_for_window<table::AXIS_YLO>(window_idx);
186 case table::AXIS_YHI:
187 return get_values_fn_for_window<table::AXIS_YHI>(window_idx);
188 }
189 return nullptr; // unreachable
190}
191} // namespace
192
194{
195 const size_t num_windows = is_lo ? NUM_WINDOWS_LO : NUM_WINDOWS_HI;
196 const size_t start_window = is_lo ? 0 : NUM_WINDOWS_LO;
197
198 // C1 step = TABLE_SIZE_BIG = 128 (uniform 7-bit slicing between consecutive windows; the tail's
199 // smaller bit-width is encoded only in `slice_sizes` below, not in the c1 step). C2/C3 step = 0
200 // (per-window values, no accumulation).
201 MultiTable mt(bb::fr(static_cast<uint64_t>(TABLE_SIZE_BIG)), bb::fr(0), bb::fr(0), num_windows);
202 mt.id = id;
203 mt.basic_table_ids.reserve(num_windows);
204 mt.get_table_values.reserve(num_windows);
205 for (size_t i = 0; i < num_windows; ++i) {
206 const size_t window_idx = start_window + i;
207 mt.slice_sizes.emplace_back(table_size(window_idx));
208 mt.basic_table_ids.emplace_back(
209 static_cast<BasicTableId>(static_cast<size_t>(axis_start_id(axis)) + window_idx));
210 mt.get_table_values.emplace_back(lookup_get_values(axis, window_idx));
211 }
212 return mt;
213}
214
215} // namespace bb::plookup::secp256r1_fixed_base
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:143
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:35
static void batch_normalize(element *elements, size_t num_elements) noexcept
static constexpr affine_element affine_one
Definition group.hpp:50
Fr_ Fr
Definition group.hpp:42
static std::array< bb::fr, 2 > get_values(std::array< uint64_t, 2 > key)
Native lookup callback used by BasicTable::get_values_from_key. axis_window_packed encodes the window...
static std::array< bb::fr, 2 > extract_axis(const AffineElement &point, AxisIndex axis)
Split an affine point into the (limb_a, limb_b) pair for the requested axis. Used by the BasicTable g...
static MultiTable get_multitable(MultiTableId id, AxisIndex axis, bool is_lo)
Construct one of the 10 MultiTables described in the file-header docstring. is_lo = true chains windo...
static void init_tables()
Precompute the 32 × 256 native points (idempotent, thread-safe). The (limb_a, limb_b) pairs for each ...
static AffineElement total_offset()
Sum of all per-window offsets (2^0 + 2^1 + ... + 2^31) · H. Subtracted from the chain-add result of t...
static BasicTable generate_basic_table_runtime(BasicTableId id, size_t window_idx, size_t table_index)
Runtime dispatch helper used by plookup_tables.cpp::create_basic_table. Selects table contents using ...
static constexpr BasicTableId axis_start_id(AxisIndex axis)
Maps a per-axis BasicTableId range start to its AxisIndex; used by the create_basic_table dispatch.
static BasicTable generate_basic_table(BasicTableId id, size_t table_index)
Construct one BasicTable instance for (axis, window_idx). id is the BasicTableId assigned by the call...
static std::array< std::array< AffineElement, TABLE_SIZE_BIG >, NUM_WINDOWS > native_table
field< Bn254FrParams > fr
Definition fr.hpp:155
constexpr std::span< const typename Group::affine_element > get_precomputed_generators()
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:305
std::vector< bb::fr > column_3
Definition types.hpp:340
std::vector< bb::fr > column_2
Definition types.hpp:339
std::array< bb::fr, 2 >(* get_values_from_key)(const std::array< uint64_t, 2 >)
Definition types.hpp:348
std::vector< bb::fr > column_1
Definition types.hpp:338
Container for managing multiple BasicTables plus the data needed to combine basic table outputs (e....
Definition types.hpp:167
std::vector< BasicTableId > basic_table_ids
Definition types.hpp:173
std::vector< uint64_t > slice_sizes
Definition types.hpp:174
std::vector< table_out(*)(table_in)> get_table_values
Definition types.hpp:183
static constexpr size_t window_bits(size_t w)