Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
keccak_rho.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
8
9#include "../types.hpp"
12
14
60template <size_t TABLE_BITS = 0, size_t LANE_INDEX = 0> class Rho {
61
62 public:
63 static constexpr uint64_t BASE = 11;
64
65 // EFFECTIVE_BASE = maximum value each input 'quasi-bit' can reach at this stage in the Keccak algo
66 // (we use base11 as it's a bit more efficient to use a consistent base across the entire Keccak hash algorithm.
67 // The THETA round requires base-11 in order to most efficiently convert XOR operations into algebraic operations)
68 static constexpr uint64_t EFFECTIVE_BASE = 3;
69
70 // The maximum number of bits of a Rho lookup table (TABLE_BITS <= MAXIMUM_MULTITABLE_BITS).
71 // Used in get_rho_output_table
72 static constexpr size_t MAXIMUM_MULTITABLE_BITS = 8;
73
74 // Rotation offsets, y vertically, x horizontally: r[y * 5 + x]
75 static constexpr std::array<size_t, 25> ROTATIONS = {
76 0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14,
77 };
78
79 static constexpr uint64_t RHO_NORMALIZATION_TABLE[3]{
80 0,
81 1,
82 0,
83 };
84
94 {
95 uint64_t accumulator = 0;
96 uint64_t input = key[0];
97 uint64_t base_shift = 1;
98 constexpr uint64_t divisor_exponent = TABLE_BITS - 1;
99 constexpr uint64_t divisor = numeric::pow64(BASE, divisor_exponent);
100 while (input > 0) {
101 uint64_t slice = input % BASE;
102 uint64_t bit = RHO_NORMALIZATION_TABLE[static_cast<size_t>(slice)];
103 accumulator += (bit * base_shift);
104 input /= BASE;
105 base_shift *= BASE;
106 }
107
108 return { bb::fr(accumulator), bb::fr(accumulator / divisor) };
109 }
110
118 {
120 uint64_t acc = 1;
121 for (size_t i = 0; i < TABLE_BITS; ++i) {
122 result[i] = acc;
123 acc *= BASE;
124 }
125 return result;
126 }
127
142 {
143 static constexpr auto scaled_bases = get_scaled_bases();
144
145 // want the most significant bit of the 64-bit integer, when this table is used on the most significant slice
146 constexpr uint64_t divisor = numeric::pow64(static_cast<uint64_t>(BASE), TABLE_BITS - 1);
147
148 for (size_t i = 0; i < TABLE_BITS; ++i) {
149 if (counts[i] == EFFECTIVE_BASE - 1) {
150 counts[i] = 0;
151 } else {
152 counts[i] += 1;
153 break;
154 }
155 }
156
157 uint64_t value = 0;
158 uint64_t normalized_value = 0;
159 for (size_t i = 0; i < TABLE_BITS; ++i) {
160 value += counts[i] * scaled_bases[i];
161 normalized_value += (RHO_NORMALIZATION_TABLE[counts[i]]) * scaled_bases[i];
162 }
163 return { value, normalized_value, normalized_value / divisor };
164 }
165
173 static BasicTable generate_rho_renormalization_table(BasicTableId id, const size_t table_index)
174 {
175 BasicTable table;
176 table.id = id;
177 table.table_index = table_index;
178 table.use_twin_keys = false;
179 auto table_size = numeric::pow64(static_cast<uint64_t>(EFFECTIVE_BASE), TABLE_BITS);
180
182 std::array<uint64_t, 3> column_values{ 0, 0, 0 };
183
184 for (size_t i = 0; i < table_size; ++i) {
185 table.column_1.emplace_back(column_values[0]);
186 table.column_2.emplace_back(column_values[1]);
187 table.column_3.emplace_back(column_values[2]);
188 column_values = get_column_values_for_next_row(counts);
189 }
190
192
193 uint64_t step_size = numeric::pow64(static_cast<uint64_t>(BASE), TABLE_BITS);
194 table.column_1_step_size = bb::fr(step_size);
195 table.column_2_step_size = bb::fr(step_size);
196 table.column_3_step_size = bb::fr(0);
197 return table;
198 }
199
238 {
239 constexpr size_t left_bits = ROTATIONS[LANE_INDEX];
240 constexpr size_t right_bits = 64 - ROTATIONS[LANE_INDEX];
241 constexpr size_t num_left_tables =
242 left_bits / MAXIMUM_MULTITABLE_BITS + (left_bits % MAXIMUM_MULTITABLE_BITS > 0 ? 1 : 0);
243 constexpr size_t num_right_tables =
244 right_bits / MAXIMUM_MULTITABLE_BITS + (right_bits % MAXIMUM_MULTITABLE_BITS > 0 ? 1 : 0);
245
246 MultiTable table;
247 table.id = id;
248
249 table.column_1_step_sizes.push_back(1);
250 table.column_2_step_sizes.push_back(1);
251 table.column_3_step_sizes.push_back(1);
252
253 // generate table selector values for the 'right' slice
254 bb::constexpr_for<0, num_right_tables, 1>([&]<size_t i> {
255 constexpr size_t num_bits_processed = (i * MAXIMUM_MULTITABLE_BITS);
256 constexpr size_t bit_slice = (num_bits_processed + MAXIMUM_MULTITABLE_BITS > right_bits)
257 ? right_bits % MAXIMUM_MULTITABLE_BITS
259
260 constexpr uint64_t scaled_base = numeric::pow64(BASE, bit_slice);
261 if (i == num_right_tables - 1) {
262 table.column_1_step_sizes.push_back(scaled_base);
263 table.column_2_step_sizes.push_back(0);
264 table.column_3_step_sizes.push_back(0);
265 } else {
266 table.column_1_step_sizes.push_back(scaled_base);
267 table.column_2_step_sizes.push_back(scaled_base);
268 table.column_3_step_sizes.push_back(0);
269 }
270
271 table.slice_sizes.push_back(scaled_base);
272 table.get_table_values.emplace_back(&get_rho_renormalization_values);
273 table.basic_table_ids.push_back((BasicTableId)((size_t)KECCAK_RHO_1 + (bit_slice - 1)));
274 });
275
276 // generate table selector values for the 'left' slice
277 bb::constexpr_for<0, num_left_tables, 1>([&]<size_t i> {
278 constexpr size_t num_bits_processed = (i * MAXIMUM_MULTITABLE_BITS);
279
280 constexpr size_t bit_slice = (num_bits_processed + MAXIMUM_MULTITABLE_BITS > left_bits)
281 ? left_bits % MAXIMUM_MULTITABLE_BITS
283 constexpr uint64_t scaled_base = numeric::pow64(BASE, bit_slice);
284
285 if (i != num_left_tables - 1) {
286 table.column_1_step_sizes.push_back(scaled_base);
287 table.column_2_step_sizes.push_back(scaled_base);
288 table.column_3_step_sizes.push_back(0);
289 }
290
291 table.slice_sizes.push_back(scaled_base);
292 table.get_table_values.emplace_back(&get_rho_renormalization_values);
293 table.basic_table_ids.push_back((BasicTableId)((size_t)KECCAK_RHO_1 + (bit_slice - 1)));
294 });
295
296 return table;
297 }
298};
299
300} // namespace bb::plookup::keccak_tables
Generate the plookup tables used for the RHO round of the Keccak hash algorithm.
static constexpr size_t MAXIMUM_MULTITABLE_BITS
static constexpr uint64_t EFFECTIVE_BASE
static constexpr uint64_t BASE
static constexpr std::array< uint64_t, TABLE_BITS > get_scaled_bases()
Precompute an array of base multipliers (11^i for i = [0, ..., TABLE_BITS - 1]) Code is slightly fast...
static std::array< uint64_t, 3 > get_column_values_for_next_row(std::array< size_t, TABLE_BITS > &counts)
Get column values for next row of plookup table. Used to generate plookup table row values.
static MultiTable get_rho_output_table(const MultiTableId id=KECCAK_NORMALIZE_AND_ROTATE)
Create the Rho MultiTable used by plookup to generate a sequence of lookups.
static std::array< bb::fr, 2 > get_rho_renormalization_values(const std::array< uint64_t, 2 > key)
Given a table input value, return the table output value.
static constexpr std::array< size_t, 25 > ROTATIONS
static constexpr uint64_t RHO_NORMALIZATION_TABLE[3]
static BasicTable generate_rho_renormalization_table(BasicTableId id, const size_t table_index)
Generate plookup table that normalizes a TABLE_BITS-slice of a base-11 integer and extracts the msb.
constexpr uint64_t pow64(const uint64_t input, const uint64_t exponent)
Definition pow.hpp:13
@ KECCAK_RHO_1
Definition types.hpp:79
@ KECCAK_NORMALIZE_AND_ROTATE
Definition types.hpp:137
field< Bn254FrParams > fr
Definition fr.hpp:174
C slice(C const &container, size_t start)
Definition container.hpp:9
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:348
std::vector< bb::fr > column_3
Definition types.hpp:383
std::vector< bb::fr > column_2
Definition types.hpp:382
std::array< bb::fr, 2 >(* get_values_from_key)(const std::array< uint64_t, 2 >)
Definition types.hpp:391
std::vector< bb::fr > column_1
Definition types.hpp:381
Container for managing multiple BasicTables plus the data needed to combine basic table outputs (e....
Definition types.hpp:154