Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
keccakf1600_trace.cpp
Go to the documentation of this file.
2
3#include <array>
4#include <cstddef>
5#include <cstdint>
6
14
15namespace bb::avm2::tracegen {
16using C = Column;
17
18namespace {
19
20// Mapping 2-dimensional array indices of state inputs to columns.
21constexpr std::array<std::array<C, 5>, 5> STATE_IN_COLS = {
22 {
23 {
24 C::keccakf1600_state_in_00,
25 C::keccakf1600_state_in_01,
26 C::keccakf1600_state_in_02,
27 C::keccakf1600_state_in_03,
28 C::keccakf1600_state_in_04,
29 },
30 {
31 C::keccakf1600_state_in_10,
32 C::keccakf1600_state_in_11,
33 C::keccakf1600_state_in_12,
34 C::keccakf1600_state_in_13,
35 C::keccakf1600_state_in_14,
36 },
37 {
38 C::keccakf1600_state_in_20,
39 C::keccakf1600_state_in_21,
40 C::keccakf1600_state_in_22,
41 C::keccakf1600_state_in_23,
42 C::keccakf1600_state_in_24,
43 },
44 {
45 C::keccakf1600_state_in_30,
46 C::keccakf1600_state_in_31,
47 C::keccakf1600_state_in_32,
48 C::keccakf1600_state_in_33,
49 C::keccakf1600_state_in_34,
50 },
51 {
52 C::keccakf1600_state_in_40,
53 C::keccakf1600_state_in_41,
54 C::keccakf1600_state_in_42,
55 C::keccakf1600_state_in_43,
56 C::keccakf1600_state_in_44,
57 },
58 },
59};
60
61// Mapping 2-dimensional array indices of theta xor intermediate value columns.
62constexpr std::array<std::array<C, 4>, 5> THETA_XOR_COLS = {
63 {
64 {
65 C::keccakf1600_theta_xor_01,
66 C::keccakf1600_theta_xor_02,
67 C::keccakf1600_theta_xor_03,
68 C::keccakf1600_theta_xor_row_0,
69 },
70 {
71 C::keccakf1600_theta_xor_11,
72 C::keccakf1600_theta_xor_12,
73 C::keccakf1600_theta_xor_13,
74 C::keccakf1600_theta_xor_row_1,
75 },
76 {
77 C::keccakf1600_theta_xor_21,
78 C::keccakf1600_theta_xor_22,
79 C::keccakf1600_theta_xor_23,
80 C::keccakf1600_theta_xor_row_2,
81 },
82 {
83 C::keccakf1600_theta_xor_31,
84 C::keccakf1600_theta_xor_32,
85 C::keccakf1600_theta_xor_33,
86 C::keccakf1600_theta_xor_row_3,
87 },
88 {
89 C::keccakf1600_theta_xor_41,
90 C::keccakf1600_theta_xor_42,
91 C::keccakf1600_theta_xor_43,
92 C::keccakf1600_theta_xor_row_4,
93 },
94 },
95};
96
97// Mapping indices of theta_xor_row_rotl1 to their columns.
98constexpr std::array<C, 5> THETA_XOR_ROW_ROTL1_COLS = {
99 {
100 C::keccakf1600_theta_xor_row_rotl1_0,
101 C::keccakf1600_theta_xor_row_rotl1_1,
102 C::keccakf1600_theta_xor_row_rotl1_2,
103 C::keccakf1600_theta_xor_row_rotl1_3,
104 C::keccakf1600_theta_xor_row_rotl1_4,
105 },
106};
107
108// Mapping indices of theta_xor_row_msb to their columns.
109constexpr std::array<C, 5> THETA_XOR_ROW_MSB_COLS = {
110 {
111 C::keccakf1600_theta_xor_row_msb_0,
112 C::keccakf1600_theta_xor_row_msb_1,
113 C::keccakf1600_theta_xor_row_msb_2,
114 C::keccakf1600_theta_xor_row_msb_3,
115 C::keccakf1600_theta_xor_row_msb_4,
116 },
117};
118
119// Mapping indices of theta_combined_xor to their columns.
120constexpr std::array<C, 5> THETA_COMBINED_XOR_COLS = {
121 {
122 C::keccakf1600_theta_combined_xor_0,
123 C::keccakf1600_theta_combined_xor_1,
124 C::keccakf1600_theta_combined_xor_2,
125 C::keccakf1600_theta_combined_xor_3,
126 C::keccakf1600_theta_combined_xor_4,
127 },
128};
129
130// Mapping indices of state_theta to their columns.
131constexpr std::array<std::array<C, 5>, 5> STATE_THETA_COLS = {
132 {
133 {
134 C::keccakf1600_state_theta_00,
135 C::keccakf1600_state_theta_01,
136 C::keccakf1600_state_theta_02,
137 C::keccakf1600_state_theta_03,
138 C::keccakf1600_state_theta_04,
139 },
140 {
141 C::keccakf1600_state_theta_10,
142 C::keccakf1600_state_theta_11,
143 C::keccakf1600_state_theta_12,
144 C::keccakf1600_state_theta_13,
145 C::keccakf1600_state_theta_14,
146 },
147 {
148 C::keccakf1600_state_theta_20,
149 C::keccakf1600_state_theta_21,
150 C::keccakf1600_state_theta_22,
151 C::keccakf1600_state_theta_23,
152 C::keccakf1600_state_theta_24,
153 },
154 {
155 C::keccakf1600_state_theta_30,
156 C::keccakf1600_state_theta_31,
157 C::keccakf1600_state_theta_32,
158 C::keccakf1600_state_theta_33,
159 C::keccakf1600_state_theta_34,
160 },
161 {
162 C::keccakf1600_state_theta_40,
163 C::keccakf1600_state_theta_41,
164 C::keccakf1600_state_theta_42,
165 C::keccakf1600_state_theta_43,
166 C::keccakf1600_state_theta_44,
167 },
168 },
169};
170
171// Mapping flattened indices to the range-checked limb column for each rotation.
172// For rot <= 32: hi is range-checked. For rot > 32: low is range-checked.
173// As index 00 is not used here, we flatten the list and start with 01.
174constexpr std::array<C, 24> STATE_THETA_LIMB_COLS = {
175 {
176 C::keccakf1600_state_theta_low_01, // [0,1] rot=36 >32
177 C::keccakf1600_state_theta_hi_02, // [0,2] rot=3 <=32
178 C::keccakf1600_state_theta_low_03, // [0,3] rot=41 >32
179 C::keccakf1600_state_theta_hi_04, // [0,4] rot=18 <=32
180 C::keccakf1600_state_theta_hi_10, // [1,0] rot=1 <=32
181 C::keccakf1600_state_theta_low_11, // [1,1] rot=44 >32
182 C::keccakf1600_state_theta_hi_12, // [1,2] rot=10 <=32
183 C::keccakf1600_state_theta_low_13, // [1,3] rot=45 >32
184 C::keccakf1600_state_theta_hi_14, // [1,4] rot=2 <=32
185 C::keccakf1600_state_theta_low_20, // [2,0] rot=62 >32
186 C::keccakf1600_state_theta_hi_21, // [2,1] rot=6 <=32
187 C::keccakf1600_state_theta_low_22, // [2,2] rot=43 >32
188 C::keccakf1600_state_theta_hi_23, // [2,3] rot=15 <=32
189 C::keccakf1600_state_theta_low_24, // [2,4] rot=61 >32
190 C::keccakf1600_state_theta_hi_30, // [3,0] rot=28 <=32
191 C::keccakf1600_state_theta_low_31, // [3,1] rot=55 >32
192 C::keccakf1600_state_theta_hi_32, // [3,2] rot=25 <=32
193 C::keccakf1600_state_theta_hi_33, // [3,3] rot=21 <=32
194 C::keccakf1600_state_theta_low_34, // [3,4] rot=56 >32
195 C::keccakf1600_state_theta_hi_40, // [4,0] rot=27 <=32
196 C::keccakf1600_state_theta_hi_41, // [4,1] rot=20 <=32
197 C::keccakf1600_state_theta_low_42, // [4,2] rot=39 >32
198 C::keccakf1600_state_theta_hi_43, // [4,3] rot=8 <=32
199 C::keccakf1600_state_theta_hi_44, // [4,4] rot=14 <=32
200 },
201};
202
203// Mapping indices of state_rho to their columns.
204// As index 00 is not used here, we flatten the list and start with 01.
205constexpr std::array<C, 24> STATE_RHO_COLS = {
206 {
207 C::keccakf1600_state_rho_01, C::keccakf1600_state_rho_02, C::keccakf1600_state_rho_03,
208 C::keccakf1600_state_rho_04, C::keccakf1600_state_rho_10, C::keccakf1600_state_rho_11,
209 C::keccakf1600_state_rho_12, C::keccakf1600_state_rho_13, C::keccakf1600_state_rho_14,
210 C::keccakf1600_state_rho_20, C::keccakf1600_state_rho_21, C::keccakf1600_state_rho_22,
211 C::keccakf1600_state_rho_23, C::keccakf1600_state_rho_24, C::keccakf1600_state_rho_30,
212 C::keccakf1600_state_rho_31, C::keccakf1600_state_rho_32, C::keccakf1600_state_rho_33,
213 C::keccakf1600_state_rho_34, C::keccakf1600_state_rho_40, C::keccakf1600_state_rho_41,
214 C::keccakf1600_state_rho_42, C::keccakf1600_state_rho_43, C::keccakf1600_state_rho_44,
215 },
216};
217
218// Mapping indices of rho rotation constants and the corresponding constant columns.
219// As index 00 is not used here, we flatten the list and start with 01.
220constexpr std::array<C, 24> RHO_ROTATION_LEN_COLS = {
221 {
222 C::keccakf1600_rot_64_min_len_01, C::keccakf1600_rot_len_02, C::keccakf1600_rot_64_min_len_03,
223 C::keccakf1600_rot_len_04, C::keccakf1600_rot_len_10, C::keccakf1600_rot_64_min_len_11,
224 C::keccakf1600_rot_len_12, C::keccakf1600_rot_64_min_len_13, C::keccakf1600_rot_len_14,
225 C::keccakf1600_rot_64_min_len_20, C::keccakf1600_rot_len_21, C::keccakf1600_rot_64_min_len_22,
226 C::keccakf1600_rot_len_23, C::keccakf1600_rot_64_min_len_24, C::keccakf1600_rot_len_30,
227 C::keccakf1600_rot_64_min_len_31, C::keccakf1600_rot_len_32, C::keccakf1600_rot_len_33,
228 C::keccakf1600_rot_64_min_len_34, C::keccakf1600_rot_len_40, C::keccakf1600_rot_len_41,
229 C::keccakf1600_rot_64_min_len_42, C::keccakf1600_rot_len_43, C::keccakf1600_rot_len_44,
230 },
231};
232
233// Mapping indices of "pi not" values to their columns
234constexpr std::array<std::array<C, 5>, 5> STATE_PI_NOT_COLS = {
235 {
236 {
237 C::keccakf1600_state_pi_not_00,
238 C::keccakf1600_state_pi_not_01,
239 C::keccakf1600_state_pi_not_02,
240 C::keccakf1600_state_pi_not_03,
241 C::keccakf1600_state_pi_not_04,
242 },
243 {
244 C::keccakf1600_state_pi_not_10,
245 C::keccakf1600_state_pi_not_11,
246 C::keccakf1600_state_pi_not_12,
247 C::keccakf1600_state_pi_not_13,
248 C::keccakf1600_state_pi_not_14,
249 },
250 {
251 C::keccakf1600_state_pi_not_20,
252 C::keccakf1600_state_pi_not_21,
253 C::keccakf1600_state_pi_not_22,
254 C::keccakf1600_state_pi_not_23,
255 C::keccakf1600_state_pi_not_24,
256 },
257 {
258 C::keccakf1600_state_pi_not_30,
259 C::keccakf1600_state_pi_not_31,
260 C::keccakf1600_state_pi_not_32,
261 C::keccakf1600_state_pi_not_33,
262 C::keccakf1600_state_pi_not_34,
263 },
264 {
265 C::keccakf1600_state_pi_not_40,
266 C::keccakf1600_state_pi_not_41,
267 C::keccakf1600_state_pi_not_42,
268 C::keccakf1600_state_pi_not_43,
269 C::keccakf1600_state_pi_not_44,
270 },
271 },
272};
273
274// Mapping indices of "pi and" values to their columns
275constexpr std::array<std::array<C, 5>, 5> STATE_PI_AND_COLS = {
276 {
277 {
278 C::keccakf1600_state_pi_and_00,
279 C::keccakf1600_state_pi_and_01,
280 C::keccakf1600_state_pi_and_02,
281 C::keccakf1600_state_pi_and_03,
282 C::keccakf1600_state_pi_and_04,
283 },
284 {
285 C::keccakf1600_state_pi_and_10,
286 C::keccakf1600_state_pi_and_11,
287 C::keccakf1600_state_pi_and_12,
288 C::keccakf1600_state_pi_and_13,
289 C::keccakf1600_state_pi_and_14,
290 },
291 {
292 C::keccakf1600_state_pi_and_20,
293 C::keccakf1600_state_pi_and_21,
294 C::keccakf1600_state_pi_and_22,
295 C::keccakf1600_state_pi_and_23,
296 C::keccakf1600_state_pi_and_24,
297 },
298 {
299 C::keccakf1600_state_pi_and_30,
300 C::keccakf1600_state_pi_and_31,
301 C::keccakf1600_state_pi_and_32,
302 C::keccakf1600_state_pi_and_33,
303 C::keccakf1600_state_pi_and_34,
304 },
305 {
306 C::keccakf1600_state_pi_and_40,
307 C::keccakf1600_state_pi_and_41,
308 C::keccakf1600_state_pi_and_42,
309 C::keccakf1600_state_pi_and_43,
310 C::keccakf1600_state_pi_and_44,
311 },
312 },
313};
314
315// Mapping indices of chi values to their columns
316constexpr std::array<std::array<C, 5>, 5> STATE_CHI_COLS = {
317 {
318 {
319 C::keccakf1600_state_chi_00,
320 C::keccakf1600_state_chi_01,
321 C::keccakf1600_state_chi_02,
322 C::keccakf1600_state_chi_03,
323 C::keccakf1600_state_chi_04,
324 },
325 {
326 C::keccakf1600_state_chi_10,
327 C::keccakf1600_state_chi_11,
328 C::keccakf1600_state_chi_12,
329 C::keccakf1600_state_chi_13,
330 C::keccakf1600_state_chi_14,
331 },
332 {
333 C::keccakf1600_state_chi_20,
334 C::keccakf1600_state_chi_21,
335 C::keccakf1600_state_chi_22,
336 C::keccakf1600_state_chi_23,
337 C::keccakf1600_state_chi_24,
338 },
339 {
340 C::keccakf1600_state_chi_30,
341 C::keccakf1600_state_chi_31,
342 C::keccakf1600_state_chi_32,
343 C::keccakf1600_state_chi_33,
344 C::keccakf1600_state_chi_34,
345 },
346 {
347 C::keccakf1600_state_chi_40,
348 C::keccakf1600_state_chi_41,
349 C::keccakf1600_state_chi_42,
350 C::keccakf1600_state_chi_43,
351 C::keccakf1600_state_chi_44,
352 },
353 },
354};
355
356// Mapping 1-dimensional array indices of read/write memory slice values to columns.
357constexpr std::array<C, AVM_KECCAKF1600_STATE_SIZE> MEM_VAL_COLS = {
358 {
359 C::keccak_memory_val_0_, C::keccak_memory_val_1_, C::keccak_memory_val_2_, C::keccak_memory_val_3_,
360 C::keccak_memory_val_4_, C::keccak_memory_val_5_, C::keccak_memory_val_6_, C::keccak_memory_val_7_,
361 C::keccak_memory_val_8_, C::keccak_memory_val_9_, C::keccak_memory_val_10_, C::keccak_memory_val_11_,
362 C::keccak_memory_val_12_, C::keccak_memory_val_13_, C::keccak_memory_val_14_, C::keccak_memory_val_15_,
363 C::keccak_memory_val_16_, C::keccak_memory_val_17_, C::keccak_memory_val_18_, C::keccak_memory_val_19_,
364 C::keccak_memory_val_20_, C::keccak_memory_val_21_, C::keccak_memory_val_22_, C::keccak_memory_val_23_,
365 C::keccak_memory_val_24_,
366 },
367};
368
375const FF& get_precomputed_inverse(size_t index)
376{
377 static const std::array<FF, AVM_KECCAKF1600_STATE_SIZE + 1> precomputed_inverses = []() {
379 for (size_t i = 0; i < AVM_KECCAKF1600_STATE_SIZE + 1; i++) {
380 inverses.at(i) = FF(i);
381 }
382 FF::batch_invert(inverses);
383 return inverses;
384 }();
385
386 return precomputed_inverses.at(index);
387}
388
389} // namespace
390
404 bool write,
405 uint32_t& row,
406 TraceContainer& trace)
407{
409 single_tag_errors.fill(false);
411 tags.fill(MemoryTag::U64);
412
413 // The effective number of rows to populate. In case of a tag error, we only populate
414 // the rows up to where the tag error occurred.
415 size_t num_rows = AVM_KECCAKF1600_STATE_SIZE;
416
417 // The relevant state and read/write memory values depending on read/write boolean.
419 if (write) {
420 for (size_t i = 0; i < 5; i++) {
421 for (size_t j = 0; j < 5; j++) {
422 // Standard Keccak layout: memory[(5 * j) + i] = A[i][j].
423 slice_ff[(5 * j) + i] = event.rounds[AVM_KECCAKF1600_NUM_ROUNDS - 1].state_chi[i][j];
424 }
425 }
426 slice_ff[0] = event.rounds[AVM_KECCAKF1600_NUM_ROUNDS - 1].state_iota_00;
427 } else {
428 // While reading we need to check the tag for each slice value.
429 for (size_t k = 0; k < AVM_KECCAKF1600_STATE_SIZE; k++) {
430 const auto& mem_val = event.src_mem_values[k];
431 slice_ff[k] = mem_val.as_ff();
432 tags[k] = mem_val.get_tag();
433 if (tags[k] != MemoryTag::U64) {
434 single_tag_errors.at(k) = true;
435 num_rows = k + 1;
436 break;
437 }
438 }
439 }
440
442 tag_errors.fill(single_tag_errors.at(num_rows - 1));
443
444 MemoryAddress addr = write ? event.dst_addr : event.src_addr;
445
446 for (size_t i = 0; i < num_rows; i++) {
447
448 trace.set(
449 row,
450 { {
451 { C::keccak_memory_sel, 1 },
452 { C::keccak_memory_clk, event.execution_clk },
453 { C::keccak_memory_ctr, i + 1 },
454 { C::keccak_memory_state_size_min_ctr_inv,
455 get_precomputed_inverse(AVM_KECCAKF1600_STATE_SIZE - i - 1) },
456 { C::keccak_memory_start_read, (i == 0 && !write) ? 1 : 0 },
457 { C::keccak_memory_start_write, (i == 0 && write) ? 1 : 0 },
458 { C::keccak_memory_ctr_end, i == AVM_KECCAKF1600_STATE_SIZE - 1 ? 1 : 0 },
459 { C::keccak_memory_end, (i == AVM_KECCAKF1600_STATE_SIZE - 1) || single_tag_errors.at(i) ? 1 : 0 },
460 { C::keccak_memory_rw, write ? 1 : 0 },
461 { C::keccak_memory_addr, addr + i },
462 { C::keccak_memory_space_id, event.space_id },
463 { C::keccak_memory_tag, static_cast<uint8_t>(tags[i]) },
464 { C::keccak_memory_tag_min_u64_inv, // No need to batch invert for an exception case.
465 single_tag_errors.at(i)
466 ? (FF(static_cast<uint8_t>(tags[i])) - FF(static_cast<uint8_t>(MemoryTag::U64))).invert()
467 : 0 },
468 { C::keccak_memory_single_tag_error, single_tag_errors.at(i) ? 1 : 0 },
469 { C::keccak_memory_tag_error, tag_errors.at(i) ? 1 : 0 },
470 } });
471
472 // We get a "triangle" when shifting values to their columns from val_0_ bottom-up.
473 for (size_t j = i; j < num_rows; j++) {
474 trace.set(MEM_VAL_COLS.at(j - i), row, slice_ff[j]);
475 }
476
477 row++;
478 }
479}
480
492{
493 constexpr MemoryAddress HIGHEST_SLICE_ADDRESS = AVM_HIGHEST_MEM_ADDRESS - AVM_KECCAKF1600_STATE_SIZE + 1;
494
495 uint32_t row = 1;
496 for (const auto& event : events) {
497 const bool out_of_range = event.src_out_of_range || event.dst_out_of_range;
498 const bool error = out_of_range || event.tag_error;
499
500 for (size_t round_idx = 0; round_idx == 0 || (!error && round_idx < AVM_KECCAKF1600_NUM_ROUNDS); round_idx++) {
501 const auto& round_data = event.rounds[round_idx];
502
503 // Setting the selector, xor operation id, and operation id, round, round cst
504 trace.set(row,
505 { {
506 { C::keccakf1600_sel, 1 },
507 { C::keccakf1600_clk, event.execution_clk },
508 { C::keccakf1600_bitwise_xor_op_id, static_cast<uint8_t>(BitwiseOperation::XOR) },
509 { C::keccakf1600_bitwise_and_op_id, static_cast<uint8_t>(BitwiseOperation::AND) },
510 { C::keccakf1600_tag_u64, static_cast<uint8_t>(MemoryTag::U64) },
511 { C::keccakf1600_round, round_idx + 1 }, // round is 1-indexed
512 { C::keccakf1600_round_cst, simulation::keccak_round_constants[round_idx] },
513 } });
514
515 // Setting the rotation length constants
516 // If the constant is <= 32, we set it in the column.
517 // Otherwise, we set 64 - constant.
518 for (size_t k = 1; k < 25; k++) {
519 const size_t i = k / 5;
520 const size_t j = k % 5;
521 const auto rotation_len = simulation::keccak_rotation_len[i][j];
522 const auto value = rotation_len <= 32 ? rotation_len : 64 - rotation_len;
523 trace.set(RHO_ROTATION_LEN_COLS.at(k - 1), row, value);
524 }
525
526 // Selectors start and last.
527 // src_address required on first row
528 if (round_idx == 0) {
529 trace.set(
530 row,
531 { {
532 { C::keccakf1600_start, 1 },
533 { C::keccakf1600_highest_slice_address, HIGHEST_SLICE_ADDRESS },
534 { C::keccakf1600_src_addr, event.src_addr },
535 { C::keccakf1600_src_out_of_range_error, event.src_out_of_range ? 1 : 0 },
536 { C::keccakf1600_dst_out_of_range_error, event.dst_out_of_range ? 1 : 0 },
537 { C::keccakf1600_tag_error, event.tag_error ? 1 : 0 },
538 { C::keccakf1600_sel_slice_read, out_of_range ? 0 : 1 },
539 { C::keccakf1600_error, error ? 1 : 0 },
540 { C::keccakf1600_end, error ? 1 : 0 }, // We set end at the initial row when there is an error.
541 // Note that the loop will stop after the initial round.
542 } });
543
544 } else if (round_idx == AVM_KECCAKF1600_NUM_ROUNDS - 1) {
545 trace.set(row,
546 { {
547 { C::keccakf1600_end, 1 },
548 { C::keccakf1600_sel_slice_write, error ? 0 : 1 },
549 } });
550 };
551
552 // dst_address, sel_no_error, space_id are required at every row as we propagate
553 // for the slice memory write lookup.
554 trace.set(row,
555 { {
556 { C::keccakf1600_dst_addr, event.dst_addr },
557 { C::keccakf1600_sel_no_error, error ? 0 : 1 },
558 { C::keccakf1600_space_id, event.space_id },
559 } });
560
561 // When no out-of-range value occured but a tag value error, we
562 // need to set the initial state values in the first round.
563 if (!out_of_range && event.tag_error && round_idx == 0) {
564 for (size_t k = 0; k < AVM_KECCAKF1600_STATE_SIZE; k++) {
565 const size_t i = k % 5; // Keccak layout: memory[k] = A[k%5][k/5]
566 const size_t j = k / 5;
567 // In simulation we set src_mem_values[i][j] to be the memory value when
568 // tag is U64, otherwise we set it to zero.
569 trace.set(STATE_IN_COLS[i][j], row, event.src_mem_values[k]);
570 }
571 }
572
573 // When there is no error we set state values completely.
574 if (!error) {
575 // Setting state inputs in their corresponding colums
576 for (size_t i = 0; i < 5; i++) {
577 for (size_t j = 0; j < 5; j++) {
578 trace.set(STATE_IN_COLS[i][j], row, round_data.state[i][j]);
579 }
580 }
581
582 // Setting theta xor values to their corresponding columns
583 for (size_t i = 0; i < 5; i++) {
584 for (size_t j = 0; j < 4; j++) {
585 trace.set(THETA_XOR_COLS[i][j], row, round_data.theta_xor[i][j]);
586 }
587 }
588
589 // Setting theta xor final values left rotated by 1 and the msb values.
590 // Setting theta_combined_xor values
591 for (size_t i = 0; i < 5; i++) {
592 const auto theta_xor_row_rotl1 = round_data.theta_xor_row_rotl1[i];
593 const auto theta_xor_row_msb = theta_xor_row_rotl1 & 1; // lsb of the rotated value
594
595 trace.set(row,
596 { {
597 { THETA_XOR_ROW_ROTL1_COLS[i], theta_xor_row_rotl1 },
598 { THETA_XOR_ROW_MSB_COLS[i], theta_xor_row_msb },
599 { THETA_COMBINED_XOR_COLS[i], round_data.theta_combined_xor[i] },
600 } });
601 }
602
603 // Setting state_theta values
604 for (size_t i = 0; i < 5; i++) {
605 for (size_t j = 0; j < 5; j++) {
606 trace.set(STATE_THETA_COLS[i][j], row, round_data.state_theta[i][j]);
607 }
608 }
609
610 // Setting the range-checked limb and state_rho values.
611 // For rot <= 32: keep hi = state_theta >> (64 - rot).
612 // For rot > 32: keep low = state_theta & ((1 << (64 - rot)) - 1).
613 for (size_t k = 1; k < 25; k++) {
614 const size_t i = k / 5;
615 const size_t j = k % 5;
616 const auto rotation_len = simulation::keccak_rotation_len[i][j];
617 const size_t low_num_bits = 64 - rotation_len;
618 const auto state_theta_val = round_data.state_theta[i][j];
619 const auto range_checked_limb = rotation_len <= 32
620 ? state_theta_val >> low_num_bits // hi
621 : state_theta_val & ((1ULL << low_num_bits) - 1); // low
622
623 trace.set(row,
624 { {
625 { STATE_THETA_LIMB_COLS[k - 1], range_checked_limb },
626 { STATE_RHO_COLS[k - 1], round_data.state_rho[i][j] },
627 } });
628 }
629
630 // Setting "pi not", "pi and", and "chi" values
631 for (size_t i = 0; i < 5; i++) {
632 for (size_t j = 0; j < 5; j++) {
633 trace.set(row,
634 { {
635 { STATE_PI_NOT_COLS[i][j], round_data.state_pi_not[i][j] },
636 { STATE_PI_AND_COLS[i][j], round_data.state_pi_and[i][j] },
637 { STATE_CHI_COLS[i][j], round_data.state_chi[i][j] },
638 } });
639 }
640 }
641
642 // Setting iota_00
643 trace.set(C::keccakf1600_state_iota_00, row, round_data.state_iota_00);
644 }
645 row++;
646 }
647 }
648}
649
662{
663 uint32_t row = 1;
664 for (const auto& event : events) {
665 // Skip the event if there is an out of range error.
666 // Namely, in this case the lookups to the memory slice are inactive.
667 if (!event.src_out_of_range && !event.dst_out_of_range) {
668 process_single_slice(event, /* write */ false, row, trace);
669
670 // Write to memory slice is only active if there is no tag error.
671 if (!event.tag_error) {
672 process_single_slice(event, /* write */ true, row, trace);
673 }
674 }
675 }
676}
677
680 // Theta XOR values
682 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_02_settings>(Column::bitwise_start)
684 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_row_0_settings>(Column::bitwise_start)
686 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_12_settings>(Column::bitwise_start)
688 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_row_1_settings>(Column::bitwise_start)
690 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_22_settings>(Column::bitwise_start)
692 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_row_2_settings>(Column::bitwise_start)
694 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_32_settings>(Column::bitwise_start)
696 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_row_3_settings>(Column::bitwise_start)
698 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_42_settings>(Column::bitwise_start)
700 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_xor_row_4_settings>(Column::bitwise_start)
701 // Theta XOR combined values
703 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_combined_xor_1_settings>(Column::bitwise_start)
705 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_combined_xor_3_settings>(Column::bitwise_start)
707 // State Theta final values
708 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_00_settings>(Column::bitwise_start)
710 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_02_settings>(Column::bitwise_start)
712 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_04_settings>(Column::bitwise_start)
714 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_11_settings>(Column::bitwise_start)
716 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_13_settings>(Column::bitwise_start)
718 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_20_settings>(Column::bitwise_start)
720 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_22_settings>(Column::bitwise_start)
722 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_24_settings>(Column::bitwise_start)
724 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_31_settings>(Column::bitwise_start)
726 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_33_settings>(Column::bitwise_start)
728 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_40_settings>(Column::bitwise_start)
730 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_42_settings>(Column::bitwise_start)
732 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_theta_44_settings>(Column::bitwise_start)
733 // Range check on some state theta limbs
735 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_02_range_settings>(Column::range_check_sel)
737 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_04_range_settings>(Column::range_check_sel)
739 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_11_range_settings>(Column::range_check_sel)
741 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_13_range_settings>(Column::range_check_sel)
743 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_20_range_settings>(Column::range_check_sel)
745 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_22_range_settings>(Column::range_check_sel)
747 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_24_range_settings>(Column::range_check_sel)
749 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_31_range_settings>(Column::range_check_sel)
751 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_33_range_settings>(Column::range_check_sel)
753 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_40_range_settings>(Column::range_check_sel)
755 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_42_range_settings>(Column::range_check_sel)
757 .add<InteractionType::LookupGeneric, lookup_keccakf1600_theta_limb_44_range_settings>(Column::range_check_sel)
758 // "pi and" values
760 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_01_settings>(Column::bitwise_start)
762 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_03_settings>(Column::bitwise_start)
764 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_10_settings>(Column::bitwise_start)
766 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_12_settings>(Column::bitwise_start)
768 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_14_settings>(Column::bitwise_start)
770 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_21_settings>(Column::bitwise_start)
772 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_23_settings>(Column::bitwise_start)
774 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_30_settings>(Column::bitwise_start)
776 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_32_settings>(Column::bitwise_start)
778 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_34_settings>(Column::bitwise_start)
780 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_41_settings>(Column::bitwise_start)
782 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_pi_and_43_settings>(Column::bitwise_start)
784 // chi values
785 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_00_settings>(Column::bitwise_start)
787 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_02_settings>(Column::bitwise_start)
789 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_04_settings>(Column::bitwise_start)
791 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_11_settings>(Column::bitwise_start)
793 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_13_settings>(Column::bitwise_start)
795 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_20_settings>(Column::bitwise_start)
797 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_22_settings>(Column::bitwise_start)
799 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_24_settings>(Column::bitwise_start)
801 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_31_settings>(Column::bitwise_start)
803 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_33_settings>(Column::bitwise_start)
805 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_40_settings>(Column::bitwise_start)
807 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_42_settings>(Column::bitwise_start)
809 .add<InteractionType::LookupGeneric, lookup_keccakf1600_state_chi_44_settings>(Column::bitwise_start)
810 // iota_00
812 // round constants lookup
813 .add<InteractionType::LookupIntoIndexedByRow, lookup_keccakf1600_round_cst_settings>()
814 // Memory slices permutations
816 .add<InteractionType::Permutation, perm_keccakf1600_write_to_slice_settings>()
817 // GT checks for slice memory ranges.
818 // GT checks are de-duplicated and therefore we can't use the interaction builder
819 // LookupIntoDynamicTableSequential.
821 .add<InteractionType::LookupGeneric, lookup_keccakf1600_dst_out_of_range_toggle_settings>(Column::gt_sel);
822
823} // namespace bb::avm2::tracegen
#define AVM_KECCAKF1600_STATE_SIZE
#define AVM_HIGHEST_MEM_ADDRESS
#define AVM_KECCAKF1600_NUM_ROUNDS
InteractionDefinition & add(auto &&... args)
void process_memory_slices(const simulation::EventEmitterInterface< simulation::KeccakF1600Event >::Container &events, TraceContainer &trace)
Populate the keccak_memory sub-trace for read/write memory slices.
static const InteractionDefinition interactions
void process_single_slice(const simulation::KeccakF1600Event &event, bool write, uint32_t &row, TraceContainer &trace)
Populate a single memory-slice (read or write) for one event.
void process_permutation(const simulation::EventEmitterInterface< simulation::KeccakF1600Event >::Container &events, TraceContainer &trace)
Populate the keccakf1600 sub-trace from permutation events.
TestTraceContainer trace
constexpr std::array< uint64_t, 24 > keccak_round_constants
constexpr std::array< std::array< uint8_t, 5 >, 5 > keccak_rotation_len
AvmFlavorSettings::FF FF
Definition field.hpp:10
uint32_t MemoryAddress
void write(B &buf, field2< base_field, Params > const &value)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
simulation::PublicDataTreeReadWriteEvent event
Settings to be passed ot GenericLookupRelationImpl.
Event emitted by the Keccak-f[1600] simulation for trace generation.
static void batch_invert(C &coeffs) noexcept
Batch invert a collection of field elements using Montgomery's trick.