Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
sha256.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Luke], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
8
12
13#include "sparse.hpp"
14#include "types.hpp"
15
52
53// Sparse form bases used for SHA-256 operations; chosen to prevent overflow during sparse digit addition
54static constexpr uint64_t CHOOSE_BASE = 28;
55static constexpr uint64_t MAJORITY_BASE = 16;
56static constexpr uint64_t WITNESS_EXTENSION_BASE = 16;
57
58// Bits per lookup in the sparse form normalization tables
59static constexpr uint64_t CHOOSE_BITS_PER_LOOKUP = 2; // table size: 28² = 784
60static constexpr uint64_t MAJORITY_BITS_PER_LOOKUP = 3; // table size: 16³ = 4096
61static constexpr uint64_t WITNESS_EXTENSION_BITS_PER_LOOKUP = 3; // table size: 16³ = 4096
62
81static constexpr uint64_t choose_normalization_table[CHOOSE_BASE]{
82 /* σ = 0 (Σ₁ = 0): output = 0 + Ch */
83 0, // e + 2f + 3g = 0 => e=0, f=0, g=0 => Ch=0
84 0, // e + 2f + 3g = 1 => e=1, f=0, g=0 => Ch=0
85 0, // e + 2f + 3g = 2 => e=0, f=1, g=0 => Ch=0
86 1, // e + 2f + 3g = 3 => e=0, f=0, g=1 OR e=1, f=1, g=0 => Ch=1
87 0, // e + 2f + 3g = 4 => e=1, f=0, g=1 => Ch=0
88 1, // e + 2f + 3g = 5 => e=0, f=1, g=1 => Ch=1
89 1, // e + 2f + 3g = 6 => e=1, f=1, g=1 => Ch=1
90 /* σ = 1 (Σ₁ = 1): output = 1 + Ch */
91 1, // e + 2f + 3g = 0 => Ch=0
92 1, // e + 2f + 3g = 1 => Ch=0
93 1, // e + 2f + 3g = 2 => Ch=0
94 2, // e + 2f + 3g = 3 => Ch=1
95 1, // e + 2f + 3g = 4 => Ch=0
96 2, // e + 2f + 3g = 5 => Ch=1
97 2, // e + 2f + 3g = 6 => Ch=1
98 /* σ = 2 (Σ₁ = 0): output = 0 + Ch */
99 0, // e + 2f + 3g = 0 => Ch=0
100 0, // e + 2f + 3g = 1 => Ch=0
101 0, // e + 2f + 3g = 2 => Ch=0
102 1, // e + 2f + 3g = 3 => Ch=1
103 0, // e + 2f + 3g = 4 => Ch=0
104 1, // e + 2f + 3g = 5 => Ch=1
105 1, // e + 2f + 3g = 6 => Ch=1
106 /* σ = 3 (Σ₁ = 1): output = 1 + Ch */
107 1, // e + 2f + 3g = 0 => Ch=0
108 1, // e + 2f + 3g = 1 => Ch=0
109 1, // e + 2f + 3g = 2 => Ch=0
110 2, // e + 2f + 3g = 3 => Ch=1
111 1, // e + 2f + 3g = 4 => Ch=0
112 2, // e + 2f + 3g = 5 => Ch=1
113 2, // e + 2f + 3g = 6 => Ch=1
114};
115
134static constexpr uint64_t majority_normalization_table[MAJORITY_BASE]{
135 /* σ = 0 (Σ₀ = 0): output = 0 + Maj */
136 0, // a + b + c = 0 => Maj=0
137 0, // a + b + c = 1 => Maj=0
138 1, // a + b + c = 2 => Maj=1
139 1, // a + b + c = 3 => Maj=1
140 /* σ = 1 (Σ₀ = 1): output = 1 + Maj */
141 1, // a + b + c = 0 => Maj=0
142 1, // a + b + c = 1 => Maj=0
143 2, // a + b + c = 2 => Maj=1
144 2, // a + b + c = 3 => Maj=1
145 /* σ = 2 (Σ₀ = 0): output = 0 + Maj */
146 0, // a + b + c = 0 => Maj=0
147 0, // a + b + c = 1 => Maj=0
148 1, // a + b + c = 2 => Maj=1
149 1, // a + b + c = 3 => Maj=1
150 /* σ = 3 (Σ₀ = 1): output = 1 + Maj */
151 1, // a + b + c = 0 => Maj=0
152 1, // a + b + c = 1 => Maj=0
153 2, // a + b + c = 2 => Maj=1
154 2, // a + b + c = 3 => Maj=1
155};
156
175static constexpr uint64_t witness_extension_normalization_table[WITNESS_EXTENSION_BASE]{
176 /* s_0 = 0 (σ₀_bit = 0): output = 0 + (s_1 mod 2) */
177 0, // s_1 = 0 => σ₁_bit = 0
178 1, // s_1 = 1 => σ₁_bit = 1
179 0, // s_1 = 2 => σ₁_bit = 0
180 1, // s_1 = 3 => σ₁_bit = 1
181 /* s_0 = 1 (σ₀_bit = 1): output = 1 + (s_1 mod 2) */
182 1, // s_1 = 0 => σ₁_bit = 0
183 2, // s_1 = 1 => σ₁_bit = 1
184 1, // s_1 = 2 => σ₁_bit = 0
185 2, // s_1 = 3 => σ₁_bit = 1
186 /* s_0 = 2 (σ₀_bit = 0): output = 0 + (s_1 mod 2) */
187 0, // s_1 = 0 => σ₁_bit = 0
188 1, // s_1 = 1 => σ₁_bit = 1
189 0, // s_1 = 2 => σ₁_bit = 0
190 1, // s_1 = 3 => σ₁_bit = 1
191 /* s_0 = 3 (σ₀_bit = 1): output = 1 + (s_1 mod 2) */
192 1, // s_1 = 0 => σ₁_bit = 0
193 2, // s_1 = 1 => σ₁_bit = 1
194 1, // s_1 = 2 => σ₁_bit = 0
195 2, // s_1 = 3 => σ₁_bit = 1
196};
197
208static constexpr bb::fr choose_base{ CHOOSE_BASE };
209
210static constexpr bb::fr HANDLED_VIA_TABLE{ 0 }; // indicates handling via lookup table instead of scalar multiplier
211
212static constexpr std::array<bb::fr, 3> choose_rot6_coefficients{
213 HANDLED_VIA_TABLE, // splits across boundary
214 choose_base.pow(11 - 6), // lands at bit 5
215 choose_base.pow(22 - 6), // lands at bit 16
216};
217
218static constexpr std::array<bb::fr, 3> choose_rot11_coefficients{
219 choose_base.pow(32 - 11), // lands at bit 21
220 HANDLED_VIA_TABLE, // lands at bit 0 can be handled using sparse limb base table
221 choose_base.pow(22 - 11), // lands at bit 11
222};
223
224static constexpr std::array<bb::fr, 3> choose_rot25_coefficients{
225 choose_base.pow(32 - 25), // lands at bit 7
226 choose_base.pow(32 - 25 + 11), // lands at bit 18
227 HANDLED_VIA_TABLE, // splits across boundary
228};
229
230// Combined per-limb rotation coefficients
231static constexpr std::array<bb::fr, 3> choose_rotation_coefficients{
232 choose_rot6_coefficients[0] + choose_rot11_coefficients[0] + choose_rot25_coefficients[0],
233 choose_rot6_coefficients[1] + choose_rot11_coefficients[1] + choose_rot25_coefficients[1],
234 choose_rot6_coefficients[2] + choose_rot11_coefficients[2] + choose_rot25_coefficients[2],
235};
236
247static constexpr bb::fr majority_base{ MAJORITY_BASE };
248
249static constexpr std::array<bb::fr, 3> majority_rot2_coefficients{
250 HANDLED_VIA_TABLE, // splits across boundary
251 majority_base.pow(11 - 2), // lands at bit 9
252 majority_base.pow(22 - 2), // lands at bit 20
253};
254
255static constexpr std::array<bb::fr, 3> majority_rot13_coefficients{
256 majority_base.pow(32 - 13), // lands at bit 19
257 HANDLED_VIA_TABLE, // splits across boundary
258 majority_base.pow(22 - 13), // lands at bit 9
259};
260
261static constexpr std::array<bb::fr, 3> majority_rot22_coefficients{
262 majority_base.pow(32 - 22), // lands at bit 10
263 majority_base.pow(32 - 22 + 11), // lands at bit 21
264 HANDLED_VIA_TABLE, // lands at bit 0, handled via sparse limb base table
265};
266
267// Combined per-limb rotation coefficients
268static constexpr std::array<bb::fr, 3> majority_rotation_coefficients{
269 majority_rot2_coefficients[0] + majority_rot13_coefficients[0] + majority_rot22_coefficients[0],
270 majority_rot2_coefficients[1] + majority_rot13_coefficients[1] + majority_rot22_coefficients[1],
271 majority_rot2_coefficients[2] + majority_rot13_coefficients[2] + majority_rot22_coefficients[2],
272};
273
282{
283 return sparse_tables::generate_sparse_normalization_table<WITNESS_EXTENSION_BASE,
284 WITNESS_EXTENSION_BITS_PER_LOOKUP,
285 witness_extension_normalization_table>(id, table_index);
286}
287
296{
298 CHOOSE_BITS_PER_LOOKUP,
299 choose_normalization_table>(id, table_index);
300}
301
310{
312 MAJORITY_BITS_PER_LOOKUP,
313 majority_normalization_table>(id, table_index);
314}
315
322{
323 const size_t num_entries = 11; // ceil(32 bits / WITNESS_EXTENSION_BITS_PER_LOOKUP)
324 const auto slice_size = numeric::pow64(WITNESS_EXTENSION_BASE, WITNESS_EXTENSION_BITS_PER_LOOKUP);
325
326 MultiTable table(slice_size, 1ULL << WITNESS_EXTENSION_BITS_PER_LOOKUP, 0, num_entries);
327
328 table.id = id;
329 for (size_t i = 0; i < num_entries; ++i) {
330 table.slice_sizes.emplace_back(slice_size);
331 table.basic_table_ids.emplace_back(SHA256_WITNESS_NORMALIZE);
332 table.get_table_values.emplace_back(
334 witness_extension_normalization_table>);
335 }
336 return table;
337}
338
345{
346 const size_t num_entries = 16; // 32 bits / CHOOSE_BITS_PER_LOOKUP
347 const auto slice_size = numeric::pow64(CHOOSE_BASE, CHOOSE_BITS_PER_LOOKUP);
348
349 MultiTable table(slice_size, 1ULL << CHOOSE_BITS_PER_LOOKUP, 0, num_entries);
350
351 table.id = id;
352 for (size_t i = 0; i < num_entries; ++i) {
353 table.slice_sizes.emplace_back(slice_size);
354 table.basic_table_ids.emplace_back(SHA256_CH_NORMALIZE);
355 table.get_table_values.emplace_back(
356 &sparse_tables::get_sparse_normalization_values<CHOOSE_BASE, choose_normalization_table>);
357 }
358 return table;
359}
360
367{
368 const size_t num_entries = 11; // ceil(32 bits / MAJORITY_BITS_PER_LOOKUP)
369 const auto slice_size = numeric::pow64(MAJORITY_BASE, MAJORITY_BITS_PER_LOOKUP);
370
371 MultiTable table(slice_size, 1ULL << MAJORITY_BITS_PER_LOOKUP, 0, num_entries);
372
373 table.id = id;
374 for (size_t i = 0; i < num_entries; ++i) {
375 table.slice_sizes.emplace_back(slice_size);
376 table.basic_table_ids.emplace_back(SHA256_MAJ_NORMALIZE);
377 table.get_table_values.emplace_back(
378 &sparse_tables::get_sparse_normalization_values<MAJORITY_BASE, majority_normalization_table>);
379 }
380 return table;
381}
382
393{
394 bb::fr limb1_correction =
395 majority_rotation_coefficients[1] - majority_base.pow(11) * majority_rotation_coefficients[0];
396
397 return { majority_rotation_coefficients[0], limb1_correction, bb::fr(0) };
398}
399
410{
411 bb::fr limb2_correction = choose_rotation_coefficients[2] - choose_base.pow(22) * choose_rotation_coefficients[0];
412
413 return { choose_rotation_coefficients[0], bb::fr(0), limb2_correction };
414}
415
446{
447 std::vector<bb::fr> column_1_coefficients{ 1, 1 << 3, 1 << 10, 1 << 18 };
448 std::vector<bb::fr> column_2_coefficients{ 0, 0, 0, 0 }; // Not accumulated; accessed individually
449 std::vector<bb::fr> column_3_coefficients{ 0, 0, 0, 0 }; // Not accumulated; accessed individually
450 MultiTable table(column_1_coefficients, column_2_coefficients, column_3_coefficients);
451 table.id = id;
452 table.slice_sizes = { (1 << 3), (1 << 7), (1 << 8), (1 << 14) };
453
472
473 table.get_table_values = {
474 &sparse_tables::get_sparse_table_with_rotation_values<WITNESS_EXTENSION_BASE, 0>,
475 &sparse_tables::get_sparse_table_with_rotation_values<WITNESS_EXTENSION_BASE, 4>,
476 &sparse_tables::get_sparse_table_with_rotation_values<WITNESS_EXTENSION_BASE, 7>,
477 &sparse_tables::get_sparse_table_with_rotation_values<WITNESS_EXTENSION_BASE, 1>,
478 };
479 return table;
480}
481
527{
528
529 // L1 correction factor: δ = c1 - B¹¹·c0 (see block comment above)
530 bb::fr limb1_table_correction =
531 choose_rotation_coefficients[1] - choose_base.pow(11) * choose_rotation_coefficients[0];
532
533 std::vector<bb::fr> column_1_coefficients{ bb::fr(1), bb::fr(1 << 11), bb::fr(1 << 22) };
534 std::vector<bb::fr> column_2_coefficients{ bb::fr(1), choose_base.pow(11), choose_base.pow(22) };
535 std::vector<bb::fr> column_3_coefficients{ bb::fr(1), bb::fr(1) + limb1_table_correction, bb::fr(1) };
536 MultiTable table(column_1_coefficients, column_2_coefficients, column_3_coefficients);
537 table.id = id;
538 table.slice_sizes = { (1 << 11), (1 << 11), (1 << 10) };
539
553 table.get_table_values = { &sparse_tables::get_sparse_table_with_rotation_values<CHOOSE_BASE, 6>,
554 &sparse_tables::get_sparse_table_with_rotation_values<CHOOSE_BASE, 0>,
555 &sparse_tables::get_sparse_table_with_rotation_values<CHOOSE_BASE, 3> };
556
557 return table;
558}
559
605{
606 // L2 correction factor: δ = c2 - B¹¹·c1 (see block comment above)
607 bb::fr limb2_table_correction =
608 majority_rotation_coefficients[2] - majority_base.pow(11) * majority_rotation_coefficients[1];
609
610 std::vector<bb::fr> column_1_coefficients{ bb::fr(1), bb::fr(1 << 11), bb::fr(1 << 22) };
611 std::vector<bb::fr> column_2_coefficients{ bb::fr(1), majority_base.pow(11), majority_base.pow(22) };
612 std::vector<bb::fr> column_3_coefficients{ bb::fr(1), bb::fr(1), bb::fr(1) + limb2_table_correction };
613
614 MultiTable table(column_1_coefficients, column_2_coefficients, column_3_coefficients);
615 table.id = id;
616 table.slice_sizes = { (1 << 11), (1 << 11), (1 << 10) };
617
631 table.get_table_values = { &sparse_tables::get_sparse_table_with_rotation_values<MAJORITY_BASE, 2>,
632 &sparse_tables::get_sparse_table_with_rotation_values<MAJORITY_BASE, 2>,
633 &sparse_tables::get_sparse_table_with_rotation_values<MAJORITY_BASE, 0> };
634 return table;
635}
636
637} // namespace bb::plookup::sha256_tables
constexpr uint64_t pow64(const uint64_t input, const uint64_t exponent)
Definition pow.hpp:13
MultiTable get_witness_extension_input_table(const MultiTableId id=SHA256_WITNESS_INPUT)
Constructs a MultiTable for decomposing a 32-bit word for message schedule extension.
Definition sha256.hpp:445
MultiTable get_majority_input_table(const MultiTableId id=SHA256_MAJ_INPUT)
Constructs a MultiTable for decomposing a into sparse form and computing rotation components for Σ₀(a...
Definition sha256.hpp:604
BasicTable generate_choose_normalization_table(BasicTableId id, const size_t table_index)
Generates a BasicTable for normalizing choose sparse digits.
Definition sha256.hpp:295
MultiTable get_witness_extension_output_table(const MultiTableId id=SHA256_WITNESS_OUTPUT)
Constructs a MultiTable for normalizing witness extension sparse results back to normal form.
Definition sha256.hpp:321
BasicTable generate_majority_normalization_table(BasicTableId id, const size_t table_index)
Generates a BasicTable for normalizing majority sparse digits.
Definition sha256.hpp:309
MultiTable get_choose_output_table(const MultiTableId id=SHA256_CH_OUTPUT)
Constructs a MultiTable for normalizing choose sparse results back to normal form.
Definition sha256.hpp:344
std::array< bb::fr, 3 > get_choose_rotation_multipliers()
Returns multipliers for computing Σ₁(e) rotations in choose_with_sigma1.
Definition sha256.hpp:409
MultiTable get_choose_input_table(const MultiTableId id=SHA256_CH_INPUT)
Constructs a MultiTable for decomposing e into sparse form and computing rotation components for Σ₁(e...
Definition sha256.hpp:526
MultiTable get_majority_output_table(const MultiTableId id=SHA256_MAJ_OUTPUT)
Constructs a MultiTable for normalizing majority sparse results back to normal form.
Definition sha256.hpp:366
std::array< bb::fr, 3 > get_majority_rotation_multipliers()
Returns multipliers for computing Σ₀(a) rotations in majority_with_sigma0.
Definition sha256.hpp:392
BasicTable generate_witness_extension_normalization_table(BasicTableId id, const size_t table_index)
Generates a BasicTable for normalizing witness extension sparse digits.
Definition sha256.hpp:281
std::array< bb::fr, 2 > get_sparse_normalization_values(const std::array< uint64_t, 2 > key)
Computes the normalized output for a sparse value based on a provided normalization table.
Definition sparse.hpp:107
BasicTable generate_sparse_normalization_table(BasicTableId id, const size_t table_index)
Generates a BasicTable for normalizing sparse form values back to normal form.
Definition sparse.hpp:144
@ SHA256_WITNESS_SLICE_8_ROTATE_7
Definition types.hpp:41
@ SHA256_BASE28
Definition types.hpp:45
@ SHA256_BASE16_ROTATE2
Definition types.hpp:49
@ SHA256_CH_NORMALIZE
Definition types.hpp:43
@ SHA256_WITNESS_SLICE_3
Definition types.hpp:39
@ SHA256_MAJ_NORMALIZE
Definition types.hpp:44
@ SHA256_BASE28_ROTATE6
Definition types.hpp:46
@ SHA256_BASE16
Definition types.hpp:48
@ SHA256_WITNESS_SLICE_7_ROTATE_4
Definition types.hpp:40
@ SHA256_WITNESS_NORMALIZE
Definition types.hpp:38
@ SHA256_WITNESS_SLICE_14_ROTATE_1
Definition types.hpp:42
@ SHA256_BASE28_ROTATE3
Definition types.hpp:47
@ SHA256_WITNESS_INPUT
Definition types.hpp:96
@ SHA256_CH_INPUT
Definition types.hpp:92
@ SHA256_MAJ_OUTPUT
Definition types.hpp:95
@ SHA256_CH_OUTPUT
Definition types.hpp:93
@ SHA256_WITNESS_OUTPUT
Definition types.hpp:97
@ SHA256_MAJ_INPUT
Definition types.hpp:94
field< Bn254FrParams > fr
Definition fr.hpp:174
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
A basic table from which we can perform lookups (for example, an xor table)
Definition types.hpp:285
Container for managing multiple BasicTables plus the data needed to combine basic table outputs (e....
Definition types.hpp:147
std::vector< BasicTableId > basic_table_ids
Definition types.hpp:153
std::vector< uint64_t > slice_sizes
Definition types.hpp:154
std::vector< table_out(*)(table_in)> get_table_values
Definition types.hpp:163