barretenberg
Loading...
Searching...
No Matches
keccak_theta.hpp
1#pragma once
2
3#include "../types.hpp"
4#include "barretenberg/common/constexpr_utils.hpp"
5#include "barretenberg/numeric/bitop/pow.hpp"
6
7namespace plookup {
8namespace keccak_tables {
9
53class Theta {
54 public:
55 static constexpr size_t TABLE_BITS = 4;
56 static constexpr uint64_t BASE = 11;
57
58 static constexpr uint64_t THETA_NORMALIZATION_TABLE[11]{
59 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
60 };
61
62 // template <size_t i> static std::pair<uint64_t, uint64_t> update_counts(std::array<size_t, TABLE_BITS>& counts)
63 // {
64 // ASSERT(i <= TABLE_BITS);
65 // if constexpr (i >= TABLE_BITS) {
66 // // TODO use concepts or template metaprogramming to put this condition in method declaration
67 // return std::make_pair(0, 0);
68 // } else {
69 // if (counts[i] == BASE - 1) {
70 // counts[i] = 0;
71 // return update_counts<i + 1>(counts);
72 // } else {
73 // counts[i] += 1;
74 // }
75
76 // uint64_t value = 0;
77 // uint64_t normalized_value = 0;
78 // uint64_t cumulative_base = 1;
79 // for (size_t j = 0; j < TABLE_BITS; ++j) {
80 // value += counts[j] * cumulative_base;
81 // normalized_value += (THETA_NORMALIZATION_TABLE[counts[j]]) * cumulative_base;
82 // cumulative_base *= BASE;
83 // }
84 // return std::make_pair(value, normalized_value);
85 // }
86 // }
87
96 static std::array<barretenberg::fr, 2> get_theta_renormalization_values(const std::array<uint64_t, 2> key)
97 {
98 uint64_t accumulator = 0;
99 uint64_t input = key[0];
100 uint64_t base_shift = 1;
101 while (input > 0) {
102 uint64_t slice = input % BASE;
103 uint64_t bit = THETA_NORMALIZATION_TABLE[static_cast<size_t>(slice)];
104 accumulator += (bit * base_shift);
105 input /= BASE;
106 base_shift *= BASE;
107 }
108 return { barretenberg::fr(accumulator), barretenberg::fr(0) };
109 }
110
117 static constexpr std::array<uint64_t, TABLE_BITS> get_scaled_bases()
118 {
119 std::array<uint64_t, TABLE_BITS> result;
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
137 static std::array<uint64_t, 2> get_column_values_for_next_row(std::array<size_t, TABLE_BITS>& counts)
138 {
139 static constexpr auto scaled_bases = get_scaled_bases();
140
141 for (size_t i = 0; i < TABLE_BITS; ++i) {
142 if (counts[i] == BASE - 1) {
143 counts[i] = 0;
144 } else {
145 counts[i] += 1;
146 break;
147 }
148 }
149
150 uint64_t value = 0;
151 uint64_t normalized_value = 0;
152 for (size_t i = 0; i < TABLE_BITS; ++i) {
153 value += counts[i] * scaled_bases[i];
154 normalized_value += (THETA_NORMALIZATION_TABLE[counts[i]]) * scaled_bases[i];
155 }
156 return { value, normalized_value };
157 }
158
166 static BasicTable generate_theta_renormalization_table(BasicTableId id, const size_t table_index)
167 {
168 // max_base_value_plus_one sometimes may not equal base iff this is an intermediate lookup table
169 // (e.g. keccak, we have base11 values that need to be normalized where the actual values-per-base only range
170 // from [0, 1, 2])
171 BasicTable table;
172 table.id = id;
173 table.table_index = table_index;
174 table.use_twin_keys = false;
175 table.size = numeric::pow64(static_cast<uint64_t>(BASE), TABLE_BITS);
176
177 std::array<size_t, TABLE_BITS> counts{};
178 std::array<uint64_t, 2> column_values{ 0, 0 };
179
180 for (size_t i = 0; i < table.size; ++i) {
181 table.column_1.emplace_back(column_values[0]);
182 table.column_2.emplace_back(column_values[1]);
183 table.column_3.emplace_back(0);
184 column_values = get_column_values_for_next_row(counts);
185 }
186
187 table.get_values_from_key = &get_theta_renormalization_values;
188
189 constexpr uint64_t step_size = numeric::pow64(static_cast<uint64_t>(BASE), TABLE_BITS);
190 table.column_1_step_size = barretenberg::fr(step_size);
191 table.column_2_step_size = barretenberg::fr(step_size);
192 table.column_3_step_size = barretenberg::fr(0);
193 return table;
194 }
195
237 static MultiTable get_theta_output_table(const MultiTableId id = KECCAK_THETA_OUTPUT)
238 {
239 constexpr size_t num_tables_per_multitable =
240 (64 / TABLE_BITS) + (64 % TABLE_BITS == 0 ? 0 : 1); // 64 bits, 5 bits per entry
241
242 uint64_t column_multiplier = numeric::pow64(BASE, TABLE_BITS);
243 MultiTable table(column_multiplier, column_multiplier, 0, num_tables_per_multitable);
244
245 table.id = id;
246 for (size_t i = 0; i < num_tables_per_multitable; ++i) {
247 table.slice_sizes.emplace_back(numeric::pow64(BASE, TABLE_BITS));
248 table.lookup_ids.emplace_back(KECCAK_THETA);
249 table.get_table_values.emplace_back(&get_theta_renormalization_values);
250 }
251 return table;
252 }
253};
254} // namespace keccak_tables
255} // namespace plookup
Generates plookup tables required for THETA round of Keccak hash function.
Definition: keccak_theta.hpp:53
static std::array< barretenberg::fr, 2 > get_theta_renormalization_values(const std::array< uint64_t, 2 > key)
Given a table input value, return the table output value.
Definition: keccak_theta.hpp:96
static MultiTable get_theta_output_table(const MultiTableId id=KECCAK_THETA_OUTPUT)
Create the THETA MultiTable used by plookup to generate a sequence of lookups.
Definition: keccak_theta.hpp:237
static std::array< uint64_t, 2 > 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.
Definition: keccak_theta.hpp:137
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...
Definition: keccak_theta.hpp:117
static BasicTable generate_theta_renormalization_table(BasicTableId id, const size_t table_index)
Generate plookup table that normalizes a TABLE_BITS-slice of a base-11 integer.
Definition: keccak_theta.hpp:166
The structure contains the most basic table serving one function (for, example an xor table)
Definition: types.hpp:263
Definition: types.hpp:124