Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
precomputed_trace.cpp
Go to the documentation of this file.
2
3#include <array>
4#include <cstddef>
5#include <cstdint>
6
19
20namespace bb::avm2::tracegen {
21
23{
24 using C = Column;
25
26 // First row.
27 trace.set(C::precomputed_first_row, 0, 1);
28
29 // Clk
30 // TODO: What a waste of 64MB. Can we elegantly have a flag for this?
31 trace.reserve_column(C::precomputed_clk, num_rows);
32 for (uint32_t i = 0; i < num_rows; i++) {
33 trace.set(C::precomputed_clk, i, i);
34 }
35}
36
38{
39 using C = Column;
40
41 // 256 per input (a and b), and 3 different bitwise ops
42 constexpr auto num_rows = 256 * 256 * 3;
43 trace.reserve_column(C::precomputed_sel_bitwise, num_rows);
44 trace.reserve_column(C::precomputed_bitwise_input_a, num_rows);
45 trace.reserve_column(C::precomputed_bitwise_input_b, num_rows);
46 trace.reserve_column(C::precomputed_bitwise_output, num_rows);
47
48 // row # is derived as:
49 // - input_b: bits 0...7 (0 being LSB)
50 // - input_a: bits 8...15
51 // - op_id: bits 16...
52 // In other words, the first 256*256 rows are for op_id 0. Next are for op_id 1, followed by op_id 2.
53 auto row_from_inputs = [](BitwiseOperation op_id, uint32_t input_a, uint32_t input_b) -> uint32_t {
54 return (static_cast<uint32_t>(op_id) << 16) | (input_a << 8) | input_b;
55 };
56 auto compute_operation = [](BitwiseOperation op_id, uint32_t a, uint32_t b) -> uint32_t {
57 switch (op_id) {
59 return a & b;
61 return a | b;
63 return a ^ b;
64 }
65
66 assert(false && "This should not happen");
67 return 0; // Should never happen. To please the compiler.
68 };
69
71 for (uint32_t a = 0; a < 256; a++) {
72 for (uint32_t b = 0; b < 256; b++) {
73 trace.set(row_from_inputs(op_id, a, b),
74 { {
75 { C::precomputed_sel_bitwise, 1 },
76 { C::precomputed_bitwise_op_id, static_cast<uint8_t>(op_id) },
77 { C::precomputed_bitwise_input_a, FF(a) },
78 { C::precomputed_bitwise_input_b, FF(b) },
79 { C::precomputed_bitwise_output, FF(compute_operation(op_id, a, b)) },
80 } });
81 }
82 }
83 }
84}
85
93{
94 using C = Column;
95
96 constexpr auto num_rows = 1 << 8; // 256
97 // Set this selector high for the first 2^8 rows
98 // For these rows, clk will be 0...255
99 trace.reserve_column(C::precomputed_sel_range_8, num_rows);
100 for (uint32_t i = 0; i < num_rows; i++) {
101 trace.set(C::precomputed_sel_range_8, i, 1);
102 }
103}
104
112{
113 using C = Column;
114
115 constexpr auto num_rows = 1 << 16; // 2^16
116 // Set this selector high for the first 2^16 rows
117 // For these rows, clk will be 0...2^16-1
118 trace.reserve_column(C::precomputed_sel_range_16, num_rows);
119 for (uint32_t i = 0; i < num_rows; i++) {
120 trace.set(C::precomputed_sel_range_16, i, 1);
121 }
122}
123
129{
130 using C = Column;
131
132 constexpr auto num_rows = 1 << 8; // 2^8 = 256
133 trace.reserve_column(C::precomputed_power_of_2, num_rows);
134 for (uint32_t i = 0; i < num_rows; i++) {
135 trace.set(C::precomputed_power_of_2, i, uint256_t(1) << uint256_t(i));
136 }
137}
138
140{
141 using C = Column;
142
143 constexpr std::array<uint32_t, 64> round_constants{
144 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
145 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
146 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
147 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
148 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
149 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
150 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
151 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
152 };
153 constexpr auto num_rows = round_constants.size();
154 trace.reserve_column(C::precomputed_sha256_compression_round_constant, num_rows);
155 trace.reserve_column(C::precomputed_sel_sha256_compression, num_rows);
156 for (uint32_t i = 0; i < num_rows; i++) {
157 trace.set(i,
158 { { { C::precomputed_sel_sha256_compression, 1 },
159 { C::precomputed_sha256_compression_round_constant, round_constants[i] } } });
160 }
161}
162
164{
165 using C = Column;
167
168 // Column number corresponds to MemoryTag enum value.
169 // TODO(MW): Q: is there a better way to iterate over all values in an enum?
172
173 for (const auto& tag : tags) {
174 trace.set(static_cast<uint32_t>(tag),
175 { { { C::precomputed_sel_tag_parameters, 1 },
176 { C::precomputed_tag_byte_length, get_tag_bytes(tag) },
177 { C::precomputed_tag_max_bits, get_tag_bits(tag) },
178 { C::precomputed_tag_max_value, get_tag_max_value(tag) } } });
179 }
180}
181
183{
184 using C = Column;
185 const std::array<Column, NUM_OP_DC_SELECTORS> sel_op_dc_columns = {
186 C::precomputed_sel_op_dc_0, C::precomputed_sel_op_dc_1, C::precomputed_sel_op_dc_2,
187 C::precomputed_sel_op_dc_3, C::precomputed_sel_op_dc_4, C::precomputed_sel_op_dc_5,
188 C::precomputed_sel_op_dc_6, C::precomputed_sel_op_dc_7, C::precomputed_sel_op_dc_8,
189 C::precomputed_sel_op_dc_9, C::precomputed_sel_op_dc_10, C::precomputed_sel_op_dc_11,
190 C::precomputed_sel_op_dc_12, C::precomputed_sel_op_dc_13, C::precomputed_sel_op_dc_14,
191 C::precomputed_sel_op_dc_15, C::precomputed_sel_op_dc_16, C::precomputed_sel_op_dc_17,
192 };
193
194 // First set the selector for this table lookup.
195 constexpr uint32_t num_rows = 1 << 8; // 256
196 constexpr uint32_t num_opcodes = static_cast<uint32_t>(WireOpCode::LAST_OPCODE_SENTINEL);
197 trace.reserve_column(C::precomputed_opcode_out_of_range, num_rows - num_opcodes);
198 for (uint32_t i = num_opcodes; i < num_rows; i++) {
199 trace.set(C::precomputed_opcode_out_of_range, i, 1);
200 }
201
202 for (size_t i = 0; i < NUM_OP_DC_SELECTORS; i++) {
203 trace.reserve_column(sel_op_dc_columns.at(i), num_opcodes);
204 }
205 trace.reserve_column(C::precomputed_exec_opcode, num_opcodes);
206 trace.reserve_column(C::precomputed_instr_size, num_opcodes);
207
208 // Fill the lookup tables with the operand decomposition selectors.
209 for (const auto& [wire_opcode, wire_instruction_spec] : WIRE_INSTRUCTION_SPEC) {
210 for (size_t i = 0; i < NUM_OP_DC_SELECTORS; i++) {
211 trace.set(sel_op_dc_columns.at(i),
212 static_cast<uint32_t>(wire_opcode),
213 wire_instruction_spec.op_dc_selectors.at(i));
214 }
215 trace.set(C::precomputed_exec_opcode,
216 static_cast<uint32_t>(wire_opcode),
217 static_cast<uint32_t>(wire_instruction_spec.exec_opcode));
218 trace.set(C::precomputed_instr_size, static_cast<uint32_t>(wire_opcode), wire_instruction_spec.size_in_bytes);
219
220 if (wire_instruction_spec.tag_operand_idx.has_value()) {
221 trace.set(C::precomputed_sel_has_tag, static_cast<uint32_t>(wire_opcode), 1);
222
223 if (wire_instruction_spec.tag_operand_idx.value() == 2) {
224 trace.set(C::precomputed_sel_tag_is_op2, static_cast<uint32_t>(wire_opcode), 1);
225 }
226 }
227 }
228}
229
231{
232 using C = Column;
233
234 constexpr size_t NUM_REGISTERS = 7;
235 constexpr std::array<Column, NUM_REGISTERS> MEM_OP_REG_COLUMNS = {
236 Column::precomputed_sel_mem_op_reg_0_, Column::precomputed_sel_mem_op_reg_1_,
237 Column::precomputed_sel_mem_op_reg_2_, Column::precomputed_sel_mem_op_reg_3_,
238 Column::precomputed_sel_mem_op_reg_4_, Column::precomputed_sel_mem_op_reg_5_,
239 Column::precomputed_sel_mem_op_reg_6_,
240 };
241 constexpr std::array<Column, NUM_REGISTERS> RW_COLUMNS = {
242 Column::precomputed_rw_reg_0_, Column::precomputed_rw_reg_1_, Column::precomputed_rw_reg_2_,
243 Column::precomputed_rw_reg_3_, Column::precomputed_rw_reg_4_, Column::precomputed_rw_reg_5_,
244 Column::precomputed_rw_reg_6_,
245 };
246 constexpr std::array<Column, NUM_REGISTERS> DO_TAG_CHECK_COLUMNS = {
247 Column::precomputed_sel_tag_check_reg_0_, Column::precomputed_sel_tag_check_reg_1_,
248 Column::precomputed_sel_tag_check_reg_2_, Column::precomputed_sel_tag_check_reg_3_,
249 Column::precomputed_sel_tag_check_reg_4_, Column::precomputed_sel_tag_check_reg_5_,
250 Column::precomputed_sel_tag_check_reg_6_,
251 };
252 constexpr std::array<Column, NUM_REGISTERS> EXPECTED_TAG_COLUMNS = {
253 Column::precomputed_expected_tag_reg_0_, Column::precomputed_expected_tag_reg_1_,
254 Column::precomputed_expected_tag_reg_2_, Column::precomputed_expected_tag_reg_3_,
255 Column::precomputed_expected_tag_reg_4_, Column::precomputed_expected_tag_reg_5_,
256 Column::precomputed_expected_tag_reg_6_,
257 };
258
259 constexpr size_t NUM_OPERANDS = 7;
260 constexpr std::array<Column, NUM_OPERANDS> SEL_OP_IS_ADDRESS_COLUMNS = {
261 Column::precomputed_sel_op_is_address_0_, Column::precomputed_sel_op_is_address_1_,
262 Column::precomputed_sel_op_is_address_2_, Column::precomputed_sel_op_is_address_3_,
263 Column::precomputed_sel_op_is_address_4_, Column::precomputed_sel_op_is_address_5_,
264 Column::precomputed_sel_op_is_address_6_,
265 };
266
267 for (const auto& [exec_opcode, exec_instruction_spec] : EXEC_INSTRUCTION_SPEC) {
268 // Basic information.
269 trace.set(static_cast<uint32_t>(exec_opcode),
270 { {
271 { C::precomputed_sel_exec_spec, 1 },
272 { C::precomputed_exec_opcode_opcode_gas, exec_instruction_spec.gas_cost.opcode_gas },
273 { C::precomputed_exec_opcode_base_da_gas, exec_instruction_spec.gas_cost.base_da },
274 { C::precomputed_exec_opcode_dynamic_l2_gas, exec_instruction_spec.gas_cost.dyn_l2 },
275 { C::precomputed_exec_opcode_dynamic_da_gas, exec_instruction_spec.gas_cost.dyn_da },
276 } });
277
278 // Register information.
279 const auto& register_info = EXEC_INSTRUCTION_SPEC.at(exec_opcode).register_info;
280 for (size_t i = 0; i < NUM_REGISTERS; i++) {
281 trace.set(MEM_OP_REG_COLUMNS.at(i), static_cast<uint32_t>(exec_opcode), register_info.is_active(i) ? 1 : 0);
282 trace.set(RW_COLUMNS.at(i), static_cast<uint32_t>(exec_opcode), register_info.is_write(i) ? 1 : 0);
283 trace.set(DO_TAG_CHECK_COLUMNS.at(i),
284 static_cast<uint32_t>(exec_opcode),
285 register_info.need_tag_check(i) ? 1 : 0);
286 trace.set(EXPECTED_TAG_COLUMNS.at(i),
287 static_cast<uint32_t>(exec_opcode),
288 static_cast<uint32_t>(register_info.expected_tag(i).value_or(static_cast<ValueTag>(0))));
289 }
290
291 // Whether an operand is an address
292 for (size_t i = 0; i < NUM_OPERANDS; i++) {
293 trace.set(SEL_OP_IS_ADDRESS_COLUMNS.at(i),
294 static_cast<uint32_t>(exec_opcode),
295 i < exec_instruction_spec.num_addresses ? 1 : 0);
296 }
297
298 // Gadget / Subtrace Selectors / Decomposable selectors
299 auto dispatch_to_subtrace = SUBTRACE_INFO_MAP.at(exec_opcode);
300 trace.set(static_cast<uint32_t>(exec_opcode),
301 { { { C::precomputed_subtrace_id, get_subtrace_id(dispatch_to_subtrace.subtrace_selector) },
302 { C::precomputed_subtrace_operation_id, dispatch_to_subtrace.subtrace_operation_id },
303 { C::precomputed_dyn_gas_id, exec_instruction_spec.dyn_gas_id } } });
304 }
305}
306
308{
309 using C = Column;
310
311 auto p_limbs_per_radix = get_p_limbs_per_radix();
312
313 trace.reserve_column(C::precomputed_sel_to_radix_p_limb_counts, p_limbs_per_radix.size());
314 trace.reserve_column(C::precomputed_to_radix_safe_limbs, p_limbs_per_radix.size());
315
316 for (size_t i = 0; i < p_limbs_per_radix.size(); ++i) {
317 size_t decomposition_len = p_limbs_per_radix[i].size();
318 if (decomposition_len > 0) {
319 trace.set(C::precomputed_sel_to_radix_p_limb_counts, static_cast<uint32_t>(i), 1);
320 trace.set(C::precomputed_to_radix_safe_limbs, static_cast<uint32_t>(i), decomposition_len - 1);
321 trace.set(C::precomputed_to_radix_num_limbs_for_p, static_cast<uint32_t>(i), decomposition_len);
322 }
323 }
324}
325
327{
328 using C = Column;
329
330 auto p_limbs_per_radix = get_p_limbs_per_radix();
331
332 uint32_t row = 0;
333 for (size_t i = 0; i < p_limbs_per_radix.size(); ++i) {
334 size_t decomposition_len = p_limbs_per_radix[i].size();
335 for (size_t j = 0; j < decomposition_len; ++j) {
336 trace.set(C::precomputed_sel_p_decomposition, row, 1);
337 trace.set(C::precomputed_p_decomposition_radix, row, i);
338 trace.set(C::precomputed_p_decomposition_limb_index, row, j);
339 trace.set(C::precomputed_p_decomposition_limb, row, p_limbs_per_radix[i][j]);
340 row++;
341 }
342 }
343}
344
346{
347 using C = Column;
348
349 constexpr uint32_t num_rows = 1 << 8; // 256
350
351 for (uint32_t i = static_cast<uint32_t>(MemoryTag::MAX) + 1; i < num_rows; i++) {
352 trace.set(C::precomputed_sel_mem_tag_out_of_range, i, 1);
353 }
354}
355
357{
358 using C = Column;
359
360 constexpr uint32_t num_rows = 1 << 16; // 65536
361 trace.reserve_column(C::precomputed_sel_addressing_gas, num_rows);
362 trace.reserve_column(C::precomputed_addressing_gas, num_rows);
363
364 for (uint32_t i = 0; i < num_rows; i++) {
365 trace.set(C::precomputed_sel_addressing_gas, i, 1);
366 trace.set(C::precomputed_addressing_gas, i, compute_addressing_gas(static_cast<uint16_t>(i)));
367 }
368}
369
371{
372 using C = Column;
373
374 // Non Revertible Nullifiers
376 trace.set(0,
377 {
378 {
379 { C::precomputed_sel_phase, 1 },
380 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::NR_NULLIFIER_INSERTION) },
381 { C::precomputed_sel_non_revertible_append_nullifier, 1 },
382
383 { C::precomputed_read_public_input_offset, nr_nullifiers.read_pi_offset },
384 { C::precomputed_read_public_input_length_offset, nr_nullifiers.read_pi_length_offset },
385 { C::precomputed_sel_can_emit_nullifier, 1 },
386 },
387 });
388 // Non Revertible Note Hash
390 trace.set(1,
391 {
392 {
393 { C::precomputed_sel_phase, 1 },
394 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::NR_NOTE_INSERTION) },
395 { C::precomputed_sel_non_revertible_append_note_hash, 1 },
396
397 { C::precomputed_read_public_input_offset, nr_note_hash.read_pi_offset },
398 { C::precomputed_read_public_input_length_offset, nr_note_hash.read_pi_length_offset },
399 { C::precomputed_sel_can_emit_note_hash, 1 },
400 },
401 });
402 // Non Revertible L2 to L1 Messages
404 trace.set(2,
405 {
406 {
407 { C::precomputed_sel_phase, 1 },
408 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::NR_L2_TO_L1_MESSAGE) },
409 { C::precomputed_sel_non_revertible_append_l2_l1_msg, 1 },
410
411 { C::precomputed_read_public_input_offset, nr_l2_to_l1_msgs.read_pi_offset },
412 { C::precomputed_read_public_input_length_offset, nr_l2_to_l1_msgs.read_pi_length_offset },
413 { C::precomputed_sel_can_emit_l2_l1_msg, 1 },
414 },
415 });
416 // Setup
418 trace.set(3,
419 {
420 {
421 { C::precomputed_sel_phase, 1 },
422 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::SETUP) },
423 { C::precomputed_is_public_call_request_phase, 1 },
424
425 { C::precomputed_read_public_input_offset, setup.read_pi_offset },
426 { C::precomputed_read_public_input_length_offset, setup.read_pi_length_offset },
427 { C::precomputed_sel_can_emit_note_hash, 1 },
428 { C::precomputed_sel_can_emit_nullifier, 1 },
429 { C::precomputed_sel_can_write_public_data, 1 },
430 { C::precomputed_sel_can_emit_unencrypted_log, 1 },
431 { C::precomputed_sel_can_emit_l2_l1_msg, 1 },
432 },
433 });
434 // Revertible Nullifiers
436 trace.set(4,
437 {
438 {
439 { C::precomputed_sel_phase, 1 },
440 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::R_NULLIFIER_INSERTION) },
441 { C::precomputed_sel_revertible_append_nullifier, 1 },
442 { C::precomputed_is_revertible, 1 },
443 { C::precomputed_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
444
445 { C::precomputed_read_public_input_offset, r_nullifiers.read_pi_offset },
446 { C::precomputed_read_public_input_length_offset, r_nullifiers.read_pi_length_offset },
447 { C::precomputed_sel_can_emit_nullifier, 1 },
448 },
449 });
450 // Revertible Note Hash
452 trace.set(5,
453 {
454 {
455 { C::precomputed_sel_phase, 1 },
456 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::R_NOTE_INSERTION) },
457 { C::precomputed_sel_revertible_append_note_hash, 1 },
458 { C::precomputed_is_revertible, 1 },
459 { C::precomputed_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
460
461 { C::precomputed_read_public_input_offset, r_note_hash.read_pi_offset },
462 { C::precomputed_read_public_input_length_offset, r_note_hash.read_pi_length_offset },
463 { C::precomputed_sel_can_emit_note_hash, 1 },
464 },
465 });
466 // Revertible L2 to L1 Messages
468 trace.set(6,
469 {
470 {
471 { C::precomputed_sel_phase, 1 },
472 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::R_L2_TO_L1_MESSAGE) },
473 { C::precomputed_sel_revertible_append_l2_l1_msg, 1 },
474 { C::precomputed_is_revertible, 1 },
475 { C::precomputed_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
476
477 { C::precomputed_read_public_input_offset, r_l2_to_l1_msgs.read_pi_offset },
478 { C::precomputed_read_public_input_length_offset, r_l2_to_l1_msgs.read_pi_length_offset },
479 { C::precomputed_sel_can_emit_l2_l1_msg, 1 },
480 },
481 });
482 // App Logic
484 trace.set(7,
485 {
486 {
487 { C::precomputed_sel_phase, 1 },
488 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::APP_LOGIC) },
489 { C::precomputed_is_public_call_request_phase, 1 },
490 { C::precomputed_is_revertible, 1 },
491 { C::precomputed_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
492
493 { C::precomputed_read_public_input_offset, app_logic.read_pi_offset },
494 { C::precomputed_read_public_input_length_offset, app_logic.read_pi_length_offset },
495 { C::precomputed_sel_can_emit_note_hash, 1 },
496 { C::precomputed_sel_can_emit_nullifier, 1 },
497 { C::precomputed_sel_can_write_public_data, 1 },
498 { C::precomputed_sel_can_emit_unencrypted_log, 1 },
499 { C::precomputed_sel_can_emit_l2_l1_msg, 1 },
500 },
501 });
502 // Teardown
504 trace.set(8,
505 {
506 {
507 { C::precomputed_sel_phase, 1 },
508 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
509 { C::precomputed_is_public_call_request_phase, 1 },
510 { C::precomputed_is_revertible, 1 },
511 { C::precomputed_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::COLLECT_GAS_FEES) },
512
513 { C::precomputed_read_public_input_offset, teardown.read_pi_offset },
514 { C::precomputed_read_public_input_length_offset, teardown.read_pi_length_offset },
515 { C::precomputed_sel_can_emit_note_hash, 1 },
516 { C::precomputed_sel_can_emit_nullifier, 1 },
517 { C::precomputed_sel_can_write_public_data, 1 },
518 { C::precomputed_sel_can_emit_unencrypted_log, 1 },
519 { C::precomputed_sel_can_emit_l2_l1_msg, 1 },
520 },
521 });
522 // TODO: Complete Collect Gas Fee and Pad Tree phases
524 trace.set(9,
525 {
526 {
527 { C::precomputed_sel_phase, 1 },
528 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::COLLECT_GAS_FEES) },
529 { C::precomputed_sel_collect_fee, 1 },
530 { C::precomputed_is_revertible, 0 },
531
532 { C::precomputed_read_public_input_offset, pay_gas.read_pi_offset },
533 { C::precomputed_read_public_input_length_offset, pay_gas.read_pi_length_offset },
534 { C::precomputed_sel_can_write_public_data, 1 },
535 },
536 });
537
538 trace.set(10,
539 {
540 {
541 { C::precomputed_sel_phase, 1 },
542 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::TREE_PADDING) },
543 { C::precomputed_sel_tree_padding, 1 },
544 { C::precomputed_is_revertible, 0 },
545 { C::precomputed_sel_can_emit_note_hash, 1 },
546 { C::precomputed_sel_can_emit_nullifier, 1 },
547 },
548 });
549
550 trace.set(11,
551 {
552 {
553 { C::precomputed_sel_phase, 1 },
554 { C::precomputed_phase_value, static_cast<uint8_t>(TransactionPhase::CLEANUP) },
555 { C::precomputed_sel_cleanup, 1 },
556 { C::precomputed_is_revertible, 0 },
557 },
558 });
559}
560
562{
563 using C = Column;
564
565 uint32_t row = 1;
566 for (const auto& round_constant : simulation::keccak_round_constants) {
567 trace.set(row,
568 { {
569 { C::precomputed_sel_keccak, 1 },
570 { C::precomputed_keccak_round_constant, round_constant },
571 } });
572 row++;
573 }
574}
575
580{
581 using C = Column;
582
583 constexpr uint32_t NUM_ROWS = 1 << 8;
584
585 // Start by flagging `invalid_envvar_enum` as 1 for all rows.
586 // "valid" rows will be reset manually to 0 below.
587 for (uint32_t i = 0; i < NUM_ROWS; i++) {
588 trace.set(C::precomputed_invalid_envvar_enum, i, 1);
589 }
590
591 for (uint8_t enum_value = 0; enum_value <= static_cast<uint8_t>(EnvironmentVariable::MAX); enum_value++) {
592 const auto& envvar_spec = GetEnvVarSpec::get_table(enum_value);
593 trace.set(static_cast<uint32_t>(enum_value),
594 { {
595 { C::precomputed_invalid_envvar_enum, 0 }, // Reset the invalid enum flag for valid rows
596 { C::precomputed_sel_envvar_pi_lookup_col0, envvar_spec.envvar_pi_lookup_col0 },
597 { C::precomputed_sel_envvar_pi_lookup_col1, envvar_spec.envvar_pi_lookup_col1 },
598 { C::precomputed_envvar_pi_row_idx, envvar_spec.envvar_pi_row_idx },
599 { C::precomputed_is_address, envvar_spec.is_address ? 1 : 0 },
600 { C::precomputed_is_sender, envvar_spec.is_sender ? 1 : 0 },
601 { C::precomputed_is_transactionfee, envvar_spec.is_transactionfee ? 1 : 0 },
602 { C::precomputed_is_isstaticcall, envvar_spec.is_isstaticcall ? 1 : 0 },
603 { C::precomputed_is_l2gasleft, envvar_spec.is_l2gasleft ? 1 : 0 },
604 { C::precomputed_is_dagasleft, envvar_spec.is_dagasleft ? 1 : 0 },
605 { C::precomputed_out_tag, envvar_spec.out_tag },
606 } });
607 }
608}
609
614{
615 using C = Column;
616
617 // Set valid rows based on the precomputed table
618 for (uint8_t enum_value = 0; enum_value <= static_cast<uint8_t>(ContractInstanceMember::MAX); enum_value++) {
619 const auto& spec = GetContractInstanceSpec::get_table(enum_value);
620
621 trace.set(static_cast<uint32_t>(enum_value),
622 { {
623 { C::precomputed_is_valid_member_enum, spec.is_valid_member_enum ? 1 : 0 },
624 { C::precomputed_is_deployer, spec.is_deployer ? 1 : 0 },
625 { C::precomputed_is_class_id, spec.is_class_id ? 1 : 0 },
626 { C::precomputed_is_init_hash, spec.is_init_hash ? 1 : 0 },
627 } });
628 }
629}
630
631} // namespace bb::avm2::tracegen
static Table get_table(uint8_t envvar)
void process_sha256_round_constants(TraceContainer &trace)
void process_to_radix_p_decompositions(TraceContainer &trace)
void process_wire_instruction_spec(TraceContainer &trace)
void process_keccak_round_constants(TraceContainer &trace)
void process_to_radix_safe_limbs(TraceContainer &trace)
void process_memory_tag_range(TraceContainer &trace)
void process_exec_instruction_spec(TraceContainer &trace)
void process_misc(TraceContainer &trace, const uint32_t num_rows=MAX_AVM_TRACE_SIZE)
void process_get_env_var_table(TraceContainer &trace)
void process_get_contract_instance_table(TraceContainer &trace)
static const Offsets & get_offsets(TransactionPhase phase)
TestTraceContainer trace
FF a
FF b
constexpr std::array< uint64_t, 24 > keccak_round_constants
constexpr uint32_t round_constants[64]
const std::unordered_map< ExecutionOpCode, SubtraceInfo > SUBTRACE_INFO_MAP
FF get_subtrace_id(SubtraceSel subtrace_sel)
Get the subtrace ID for a given subtrace enum.
const std::array< std::vector< uint8_t >, 257 > & get_p_limbs_per_radix()
Definition to_radix.cpp:33
@ NR_NOTE_INSERTION
@ R_NULLIFIER_INSERTION
@ NR_L2_TO_L1_MESSAGE
@ R_L2_TO_L1_MESSAGE
@ NR_NULLIFIER_INSERTION
uint32_t compute_addressing_gas(uint16_t indirect_flag)
Definition gas.cpp:10
uint8_t get_tag_bits(ValueTag tag)
uint256_t get_tag_max_value(ValueTag tag)
constexpr size_t NUM_OP_DC_SELECTORS
const std::unordered_map< WireOpCode, WireInstructionSpec > WIRE_INSTRUCTION_SPEC
AvmFlavorSettings::FF FF
Definition field.hpp:10
const std::unordered_map< ExecutionOpCode, ExecInstructionSpec > EXEC_INSTRUCTION_SPEC
uint8_t get_tag_bytes(ValueTag tag)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13