Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
tx.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <cstdint>
5#include <vector>
6
7#include "barretenberg/aztec/aztec_constants.hpp"
28
29namespace bb::avm2::constraining {
30namespace {
31
32using tracegen::TestTraceContainer;
33using tracegen::TxTraceBuilder;
35using C = Column;
36using tx = bb::avm2::tx<FF>;
37using tx_context = bb::avm2::tx_context<FF>;
38
39TEST(TxExecutionConstrainingTest, NegativeEmptyTrace)
40{
43}
44
45TEST(TxExecutionConstrainingTest, NegativeEarlyEnd)
46{
47 TestTraceContainer trace({
48 {
49 // Row 0
50 { C::precomputed_first_row, 1 },
51 },
52 {
53 // Row 1
54 { C::tx_sel, 1 },
55 },
56 });
57 EXPECT_THROW_WITH_MESSAGE(check_relation<tx>(trace, tx::SR_NO_EARLY_END),
59}
60
61TEST(TxExecutionConstrainingTest, NegativeNoExtraneousRows)
62{
63 TestTraceContainer trace({
64 {
65 // Row 0
66 { C::precomputed_first_row, 1 },
67 },
68 {
69 // Row 1
70 { C::tx_sel, 0 },
71 },
72 {
73 // Row 2
74 { C::tx_sel, 1 },
75 },
76 });
77 EXPECT_THROW_WITH_MESSAGE(check_relation<tx>(trace, tx::SR_TRACE_CONTINUITY),
79}
80
81class TxExecutionConstrainingTestHelper : public ::testing::Test {
82 public:
83 tracegen::PrecomputedTraceBuilder precomputed_builder;
84 tracegen::PublicInputsTraceBuilder public_inputs_builder;
85 static void set_initial_columns(TestTraceContainer& trace,
86 const std::vector<PublicCallRequest>& setup_call_requests,
87 const std::vector<PublicCallRequest>& app_logic_call_requests)
88 {
89 uint32_t row = 0;
90 // Prepended first row:
91 trace.set(row++, { { { C::execution_clk, 0 }, { C::precomputed_first_row, 1 } } });
92 // Nullifer, note, and message insertion:
93 trace.set(
94 row++,
95 { {
96 { C::tx_sel, 1 },
97 { C::tx_start_tx, 1 },
98 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::NR_NULLIFIER_INSERTION) },
99 { C::tx_is_padded, 1 },
100 { C::tx_is_tree_insert_phase, 1 },
101 { C::tx_sel_append_nullifier, 1 },
102
103 { C::tx_read_pi_start_offset,
104 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_NULLIFIERS_ROW_IDX },
105 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_NULLIFIERS_ROW_IDX },
106 { C::tx_sel_read_phase_length, 1 },
107 { C::tx_read_pi_length_offset,
108 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_NULLIFIERS_ROW_IDX },
109
110 { C::tx_start_phase, 1 },
111 { C::tx_end_phase, 1 },
112 { C::tx_next_context_id, 1 },
113 } });
114 trace.set(row++,
115 { {
116 { C::tx_sel, 1 },
117 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::NR_NOTE_INSERTION) },
118 { C::tx_is_padded, 1 },
119 { C::tx_is_tree_insert_phase, 1 },
120 { C::tx_sel_append_note_hash, 1 },
121 { C::tx_read_pi_start_offset,
122 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_NOTE_HASHES_ROW_IDX },
123 { C::tx_read_pi_offset,
124 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_NOTE_HASHES_ROW_IDX },
125 { C::tx_sel_read_phase_length, 1 },
126 { C::tx_read_pi_length_offset,
127 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_NOTE_HASHES_ROW_IDX },
128 { C::tx_start_phase, 1 },
129 { C::tx_end_phase, 1 },
130 { C::tx_next_context_id, 1 },
131 } });
132 trace.set(
133 row++,
134 { {
135 { C::tx_sel, 1 },
136 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::NR_L2_TO_L1_MESSAGE) },
137 { C::tx_is_padded, 1 },
138 { C::tx_sel_append_l2_l1_msg, 1 },
139
140 { C::tx_read_pi_start_offset,
141 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX },
142 { C::tx_read_pi_offset,
143 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX },
144 { C::tx_sel_read_phase_length, 1 },
145 { C::tx_read_pi_length_offset,
146 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_L2_TO_L1_MSGS_ROW_IDX },
147 { C::tx_write_pi_offset, AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX },
148
149 { C::tx_start_phase, 1 },
150 { C::tx_end_phase, 1 },
151 { C::tx_next_context_id, 1 },
152 } });
153 // Setup calls:
154 auto calls_remaining = setup_call_requests.size();
155 auto read_pi_offset = AVM_PUBLIC_INPUTS_PUBLIC_SETUP_CALL_REQUESTS_ROW_IDX;
156 for (auto setup_call : setup_call_requests) {
157 bool is_first_call = calls_remaining == setup_call_requests.size();
158 trace.set(row++,
159 { {
160 { C::tx_sel, 1 },
161 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::SETUP) },
162 { C::tx_start_phase, is_first_call ? 1 : 0 },
163 { C::tx_end_phase, calls_remaining == 1 ? 1 : 0 },
164 { C::tx_sel_read_phase_length, is_first_call ? 1 : 0 },
165 // Lookup Precomputed Table Values
166 { C::tx_is_public_call_request, 1 },
167 { C::tx_sel_process_call_request, 1 },
168 { C::tx_read_pi_start_offset, AVM_PUBLIC_INPUTS_PUBLIC_SETUP_CALL_REQUESTS_ROW_IDX },
169 { C::tx_read_pi_offset, read_pi_offset },
170 { C::tx_read_pi_length_offset,
171 AVM_PUBLIC_INPUTS_PUBLIC_CALL_REQUEST_ARRAY_LENGTHS_SETUP_CALLS_ROW_IDX },
172 { C::tx_remaining_phase_counter, calls_remaining },
173 { C::tx_remaining_phase_inv, FF(calls_remaining).invert() },
174 { C::tx_remaining_phase_minus_one_inv,
175 calls_remaining == 1 ? 0 : FF(calls_remaining - 1).invert() },
176 // Public Input Loaded Values
177 { C::tx_msg_sender, setup_call.msg_sender },
178 { C::tx_contract_addr, setup_call.contract_address },
179 { C::tx_is_static, setup_call.is_static_call },
180 { C::tx_calldata_hash, setup_call.calldata_hash },
181 } });
182 calls_remaining--;
183 read_pi_offset++;
184 }
185 // Nullifer, note, and message insertion:
186 trace.set(
187 row++,
188 { {
189 { C::tx_sel, 1 },
190 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::R_NULLIFIER_INSERTION) },
191 { C::tx_is_padded, 1 },
192 { C::tx_is_tree_insert_phase, 1 },
193 { C::tx_sel_append_nullifier, 1 },
194 { C::tx_is_revertible, 1 },
195 { C::tx_read_pi_start_offset,
196 AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_NULLIFIERS_ROW_IDX },
197 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_NULLIFIERS_ROW_IDX },
198 { C::tx_sel_read_phase_length, 1 },
199 { C::tx_read_pi_length_offset,
200 AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_NULLIFIERS_ROW_IDX },
201 { C::tx_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
202 { C::tx_start_phase, 1 },
203 { C::tx_end_phase, 1 },
204 } });
205 trace.set(
206 row++,
207 { {
208 { C::tx_sel, 1 },
209 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::R_NOTE_INSERTION) },
210 { C::tx_is_padded, 1 },
211 { C::tx_is_tree_insert_phase, 1 },
212 { C::tx_sel_append_note_hash, 1 },
213 { C::tx_is_revertible, 1 },
214 { C::tx_read_pi_start_offset,
215 AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_NOTE_HASHES_ROW_IDX },
216 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_NOTE_HASHES_ROW_IDX },
217 { C::tx_sel_read_phase_length, 1 },
218 { C::tx_read_pi_length_offset,
219 AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_NOTE_HASHES_ROW_IDX },
220 { C::tx_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
221 { C::tx_start_phase, 1 },
222 { C::tx_end_phase, 1 },
223 } });
224 trace.set(
225 row++,
226 { {
227 { C::tx_sel, 1 },
228 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::R_L2_TO_L1_MESSAGE) },
229 { C::tx_is_padded, 1 },
230 { C::tx_sel_append_l2_l1_msg, 1 },
231 { C::tx_is_revertible, 1 },
232 { C::tx_read_pi_start_offset,
233 AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX },
234 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX },
235 { C::tx_sel_read_phase_length, 1 },
236 { C::tx_read_pi_length_offset,
237 AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_L2_TO_L1_MSGS_ROW_IDX },
238 { C::tx_write_pi_offset, AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX },
239 { C::tx_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
240 { C::tx_start_phase, 1 },
241 { C::tx_end_phase, 1 },
242 } });
243 // App logic calls:
244 calls_remaining = app_logic_call_requests.size();
245 read_pi_offset = AVM_PUBLIC_INPUTS_PUBLIC_APP_LOGIC_CALL_REQUESTS_ROW_IDX;
246 for (auto app_logic_call : app_logic_call_requests) {
247 bool is_first_call = calls_remaining == app_logic_call_requests.size();
248 trace.set(row++,
249 { {
250 { C::tx_sel, 1 },
251 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::APP_LOGIC) },
252 { C::tx_start_phase, is_first_call ? 1 : 0 },
253 { C::tx_end_phase, calls_remaining == 1 ? 1 : 0 },
254 { C::tx_sel_read_phase_length, is_first_call ? 1 : 0 },
255 // Lookup Precomputed Table Values
256 { C::tx_is_public_call_request, 1 },
257 { C::tx_sel_process_call_request, 1 },
258 { C::tx_read_pi_start_offset, AVM_PUBLIC_INPUTS_PUBLIC_APP_LOGIC_CALL_REQUESTS_ROW_IDX },
259 { C::tx_read_pi_offset, read_pi_offset },
260 { C::tx_read_pi_length_offset,
261 AVM_PUBLIC_INPUTS_PUBLIC_CALL_REQUEST_ARRAY_LENGTHS_APP_LOGIC_CALLS_ROW_IDX },
262 { C::tx_remaining_phase_counter, calls_remaining },
263 { C::tx_remaining_phase_inv, FF(calls_remaining).invert() },
264 { C::tx_remaining_phase_minus_one_inv,
265 calls_remaining == 1 ? 0 : FF(calls_remaining - 1).invert() },
266 { C::tx_is_revertible, 1 },
267 { C::tx_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
268 // Public Input Loaded Values
269 { C::tx_msg_sender, app_logic_call.msg_sender },
270 { C::tx_contract_addr, app_logic_call.contract_address },
271 { C::tx_is_static, app_logic_call.is_static_call },
272 { C::tx_calldata_hash, app_logic_call.calldata_hash },
273 } });
274 calls_remaining--;
275 read_pi_offset++;
276 }
277 // Teardown:
278 trace.set(row++,
279 { {
280 { C::tx_sel, 1 },
281 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
282 { C::tx_is_teardown, 1 },
283 { C::tx_sel_read_phase_length, 1 },
284 { C::tx_read_pi_start_offset, AVM_PUBLIC_INPUTS_PUBLIC_TEARDOWN_CALL_REQUEST_ROW_IDX },
285 { C::tx_read_pi_length_offset,
286 AVM_PUBLIC_INPUTS_PUBLIC_CALL_REQUEST_ARRAY_LENGTHS_TEARDOWN_CALL_ROW_IDX },
287 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PUBLIC_TEARDOWN_CALL_REQUEST_ROW_IDX },
288 { C::tx_is_public_call_request, 1 },
289 { C::tx_is_revertible, 1 },
290 { C::tx_next_phase_on_revert, static_cast<uint8_t>(TransactionPhase::COLLECT_GAS_FEES) },
291 { C::tx_start_phase, 1 },
292 { C::tx_end_phase, 1 },
293 } });
294 // Collect fees
295 trace.set(row++,
296 { {
297 { C::tx_sel, 1 },
298 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::COLLECT_GAS_FEES) },
299 { C::tx_remaining_phase_counter, 1 },
300 { C::tx_remaining_phase_inv, 1 },
301 { C::tx_is_collect_fee, 1 },
302 { C::tx_read_pi_start_offset, AVM_PUBLIC_INPUTS_EFFECTIVE_GAS_FEES_ROW_IDX },
303 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_EFFECTIVE_GAS_FEES_ROW_IDX },
304 { C::tx_write_pi_offset, AVM_PUBLIC_INPUTS_TRANSACTION_FEE_ROW_IDX },
305 { C::tx_fee_juice_contract_address, FEE_JUICE_ADDRESS },
306 { C::tx_fee_juice_balances_slot_constant, FEE_JUICE_BALANCES_SLOT },
307 { C::tx_dom_sep_public_storage_map_slot, DOM_SEP__PUBLIC_STORAGE_MAP_SLOT },
308 { C::tx_fee_payer_pi_offset, AVM_PUBLIC_INPUTS_FEE_PAYER_ROW_IDX },
309 { C::tx_const_three, 3 },
310 { C::tx_start_phase, 1 },
311 { C::tx_end_phase, 1 },
312 { C::tx_uint32_max, 0xffffffff },
313 } });
314 // Tree Padding
315 trace.set(row++,
316 { {
317 { C::tx_sel, 1 },
318 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::TREE_PADDING) },
319 { C::tx_start_phase, 1 },
320 { C::tx_end_phase, 1 },
321 { C::tx_is_tree_padding, 1 },
322 { C::tx_remaining_phase_counter, 1 },
323 { C::tx_remaining_phase_inv, 1 },
324 { C::tx_next_note_hash_tree_size, MAX_NOTE_HASHES_PER_TX },
325 { C::tx_next_nullifier_tree_size, MAX_NULLIFIERS_PER_TX },
326 } });
327 // Cleanup
328 trace.set(row++,
329 { {
330 { C::tx_sel, 1 },
331 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::CLEANUP) },
332 { C::tx_start_phase, 1 },
333 { C::tx_end_phase, 1 },
334 { C::tx_is_cleanup, 1 },
335 { C::tx_remaining_phase_counter, 1 },
336 { C::tx_remaining_phase_inv, 1 },
337 } });
338 }
339};
340
341TEST_F(TxExecutionConstrainingTestHelper, SimpleControlFlowRead)
342{
343 auto test_public_inputs = testing::PublicInputsBuilder()
344 .rand_public_setup_call_requests(2)
345 .rand_public_app_logic_call_requests(1)
346 .build();
347
348 auto first_setup_call_request = test_public_inputs.public_setup_call_requests[0];
349 auto second_setup_call_request = test_public_inputs.public_setup_call_requests[1];
350 auto app_logic_call_request = test_public_inputs.public_app_logic_call_requests[0];
351
352 TestTraceContainer trace;
353 set_initial_columns(trace, { first_setup_call_request, second_setup_call_request }, { app_logic_call_request });
354
355 // Set is_padded at teardown:
356 trace.set(10,
357 { {
358 { C::tx_is_padded, 1 },
359 } });
360
361 public_inputs_builder.process_public_inputs(trace, test_public_inputs);
362 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
363
365 precomputed_builder.process_misc(trace, AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH);
366
367 check_relation<tx>(trace);
368 check_interaction<TxTraceBuilder,
372}
373
374TEST_F(TxExecutionConstrainingTestHelper, SimpleHandleRevert)
375{
376 auto test_public_inputs = testing::PublicInputsBuilder()
377 .rand_public_setup_call_requests(2)
378 .rand_public_app_logic_call_requests(2)
379 .set_reverted(true)
380 .build();
381
382 auto first_setup_call_request = test_public_inputs.public_setup_call_requests[0];
383 auto second_setup_call_request = test_public_inputs.public_setup_call_requests[1];
384 auto first_app_logic_call_request = test_public_inputs.public_app_logic_call_requests[0];
385 auto second_app_logic_call_request = test_public_inputs.public_app_logic_call_requests[1];
386
387 TestTraceContainer trace;
388 set_initial_columns(trace,
389 { first_setup_call_request, second_setup_call_request },
390 { first_app_logic_call_request, second_app_logic_call_request });
391
392 // Set teardown as padded:
393 trace.set(11, { { { C::tx_is_padded, 1 } } });
394
395 // Set the second app logic call to have reverted:
396 trace.set(10, { { { C::tx_reverted, 1 } } });
397
398 // Set some tx_context values:
399 trace.set(1, { { { C::tx_start_tx, 1 } } });
400 for (uint32_t i = 10; i < 15; i++) {
401 trace.set(i, { { { C::tx_tx_reverted, 1 } } });
402 }
403 trace.set(14, { { { C::tx_reverted_pi_offset, AVM_PUBLIC_INPUTS_REVERTED_ROW_IDX } } });
404
405 public_inputs_builder.process_public_inputs(trace, test_public_inputs);
406 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
407
409 precomputed_builder.process_misc(trace, AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH);
410
411 check_relation<tx>(trace);
412 check_relation<tx_context>(
414 check_interaction<TxTraceBuilder, lookup_tx_context_public_inputs_read_reverted_settings>(trace);
415}
416
417TEST_F(TxExecutionConstrainingTestHelper, JumpOnRevert)
418{
419 TestTraceContainer trace;
420 set_initial_columns(
421 trace,
422 { PublicCallRequest{ .msg_sender = 0, .contract_address = 0, .is_static_call = false, .calldata_hash = 0 } },
423 {});
424
425 // Set reverted at row 7, message phase:
426 trace.set(7,
427 { {
428 { C::tx_is_padded, 0 },
429 { C::tx_sel_append_l2_l1_msg, 0 }, // switch off for testing
430 { C::tx_remaining_phase_counter, 1 },
431 { C::tx_remaining_phase_inv, 1 },
432 { C::tx_is_revertible, 1 },
433 { C::tx_reverted, 1 },
434 } });
435 // Set teardown as padded:
436 trace.set(8, { { { C::tx_is_padded, 1 } } });
437
439 precomputed_builder.process_misc(trace, AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH);
440
441 check_relation<tx>(trace);
442}
443
444} // namespace
445
446TEST(TxExecutionConstrainingTest, WriteTreeValue)
447{
449
450 auto pub_inputs_col = test_public_inputs.to_columns();
452 // Row 0
453 { { C::execution_clk, 0 }, { C::precomputed_first_row, 1 } },
454
455 // Row 1
456 { { C::tx_sel, 1 },
457 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::NR_NULLIFIER_INSERTION) },
458 { C::tx_start_phase, 1 },
459
460 { C::tx_read_pi_length_offset,
461 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_NULLIFIERS_ROW_IDX },
462 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_NULLIFIERS_ROW_IDX },
463
464 { C::tx_is_tree_insert_phase, 1 },
465 { C::tx_leaf_value, test_public_inputs.previous_non_revertible_accumulated_data.nullifiers[0] },
466 { C::tx_prev_num_nullifiers_emitted, 0 },
467 { C::tx_next_num_nullifiers_emitted, 1 },
468 { C::tx_end_phase, 1 } },
469
470 // Row 2
471 { { C::tx_sel, 1 },
472 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::NR_NOTE_INSERTION) },
473 { C::tx_start_phase, 1 },
474
475 { C::tx_read_pi_length_offset,
476 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_NOTE_HASHES_ROW_IDX },
477 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_NOTE_HASHES_ROW_IDX },
478
479 { C::tx_is_tree_insert_phase, 1 },
480 { C::tx_leaf_value, test_public_inputs.previous_non_revertible_accumulated_data.note_hashes[0] },
481 { C::tx_prev_num_note_hashes_emitted, 0 },
482 { C::tx_next_num_note_hashes_emitted, 1 },
483 { C::tx_end_phase, 1 } },
484
485 // Row 3
486 { { C::tx_sel, 1 },
487 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::NR_L2_TO_L1_MESSAGE) },
488 { C::tx_start_phase, 1 },
489 { C::tx_read_pi_length_offset,
490 AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_L2_TO_L1_MSGS_ROW_IDX },
491 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_NON_REVERTIBLE_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX },
492 { C::tx_write_pi_offset, AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX },
493
494 { C::tx_sel_append_l2_l1_msg, 1 },
495 { C::tx_l2_l1_msg_content,
496 test_public_inputs.previous_non_revertible_accumulated_data.l2_to_l1_msgs[0].message.content },
497 { C::tx_l2_l1_msg_recipient,
498 test_public_inputs.previous_non_revertible_accumulated_data.l2_to_l1_msgs[0].message.recipient },
499 { C::tx_l2_l1_msg_contract_address,
500 test_public_inputs.previous_non_revertible_accumulated_data.l2_to_l1_msgs[0].contract_address },
501 { C::tx_end_phase, 1 } },
502
503 // Row 4
504 // Setup
505 { { C::tx_sel, 1 },
506 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::SETUP) },
507 { C::tx_start_phase, 1 },
508 { C::tx_is_padded, 1 },
509 { C::tx_read_pi_length_offset, AVM_PUBLIC_INPUTS_PUBLIC_CALL_REQUEST_ARRAY_LENGTHS_SETUP_CALLS_ROW_IDX },
510 { C::tx_end_phase, 1 } },
511
512 // Row 5
513 { { C::tx_sel, 1 },
514 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::R_NULLIFIER_INSERTION) },
515 { C::tx_start_phase, 1 },
516
517 { C::tx_read_pi_length_offset,
518 AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_NULLIFIERS_ROW_IDX },
519 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_NULLIFIERS_ROW_IDX },
520
521 { C::tx_is_tree_insert_phase, 1 },
522 { C::tx_leaf_value, test_public_inputs.previous_revertible_accumulated_data.nullifiers[0] },
523 { C::tx_prev_num_nullifiers_emitted, 1 },
524 { C::tx_next_num_nullifiers_emitted, 2 },
525 { C::tx_end_phase, 1 } },
526
527 // Row 6
528 { { C::tx_sel, 1 },
529 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::R_NOTE_INSERTION) },
530 { C::tx_start_phase, 1 },
531
532 { C::tx_read_pi_length_offset,
533 AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_NOTE_HASHES_ROW_IDX },
534 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_NOTE_HASHES_ROW_IDX },
535
536 { C::tx_is_tree_insert_phase, 1 },
537 { C::tx_leaf_value, test_public_inputs.previous_revertible_accumulated_data.note_hashes[0] },
538 { C::tx_prev_num_note_hashes_emitted, 1 },
539 { C::tx_next_num_note_hashes_emitted, 2 },
540 { C::tx_end_phase, 1 } },
541
542 // Row 7
543 { { C::tx_sel, 1 },
544 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::R_L2_TO_L1_MESSAGE) },
545 { C::tx_start_phase, 1 },
546
547 { C::tx_read_pi_length_offset,
548 AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_ARRAY_LENGTHS_L2_TO_L1_MSGS_ROW_IDX },
549 { C::tx_read_pi_offset, AVM_PUBLIC_INPUTS_PREVIOUS_REVERTIBLE_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX },
550 { C::tx_write_pi_offset, AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX + 1 },
551
552 { C::tx_sel_append_l2_l1_msg, 1 },
553 { C::tx_l2_l1_msg_content,
554 test_public_inputs.previous_revertible_accumulated_data.l2_to_l1_msgs[0].message.content },
555 { C::tx_l2_l1_msg_recipient,
556 test_public_inputs.previous_revertible_accumulated_data.l2_to_l1_msgs[0].message.recipient },
557 { C::tx_l2_l1_msg_contract_address,
558 test_public_inputs.previous_revertible_accumulated_data.l2_to_l1_msgs[0].contract_address },
559 { C::tx_end_phase, 1 } },
560
561 // App Logic
562 // Row 8
563 { { C::tx_sel, 1 },
564 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::APP_LOGIC) },
565 { C::tx_start_phase, 1 },
566 { C::tx_is_padded, 1 },
567 { C::tx_read_pi_length_offset, AVM_PUBLIC_INPUTS_PUBLIC_CALL_REQUEST_ARRAY_LENGTHS_APP_LOGIC_CALLS_ROW_IDX },
568 { C::tx_end_phase, 1 } },
569
570 // Row 9
571 { { C::tx_sel, 1 },
572 { C::tx_phase_value, static_cast<uint8_t>(TransactionPhase::TEARDOWN) },
573 { C::tx_read_pi_length_offset, AVM_PUBLIC_INPUTS_PUBLIC_CALL_REQUEST_ARRAY_LENGTHS_TEARDOWN_CALL_ROW_IDX },
574 { C::tx_is_padded, 1 },
575 { C::tx_start_phase, 1 },
576 { C::tx_end_phase, 1 } },
577 });
578
581 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
582
584 precomputed_builder.process_misc(trace, AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH);
585
586 check_interaction<TxTraceBuilder, lookup_tx_read_tree_insert_value_settings>(trace);
587 check_interaction<TxTraceBuilder, lookup_tx_read_l2_l1_msg_settings>(trace);
588 check_interaction<TxTraceBuilder, lookup_tx_write_l2_l1_msg_settings>(trace);
589}
590
591TEST_F(TxExecutionConstrainingTestHelper, CollectFees)
592{
593 auto test_public_inputs = testing::PublicInputsBuilder()
595 .rand_public_app_logic_call_requests(1)
596 .rand_public_teardown_call_request()
597 .build();
598
599 auto first_setup_call_request = test_public_inputs.public_setup_call_requests[0];
600 auto second_setup_call_request = test_public_inputs.public_setup_call_requests[1];
601 auto app_logic_call_request = test_public_inputs.public_app_logic_call_requests[0];
602 auto teardown_call_request = test_public_inputs.public_teardown_call_request;
603
605 set_initial_columns(trace, { first_setup_call_request, second_setup_call_request }, { app_logic_call_request });
606
607 // Set gas used values:
608 for (uint32_t i = 1; i < 4; i++) {
609 trace.set(i,
610 { {
611 { C::tx_prev_da_gas_used, 1 },
612 { C::tx_prev_l2_gas_used, 100 },
613 { C::tx_next_da_gas_used, 1 },
614 { C::tx_next_l2_gas_used, 100 },
615 } });
616 }
617
618 trace.set(4,
619 { {
620 { C::tx_prev_da_gas_used, 1 },
621 { C::tx_prev_l2_gas_used, 100 },
622 { C::tx_prev_da_gas_used_sent_to_enqueued_call, 1 },
623 { C::tx_prev_l2_gas_used_sent_to_enqueued_call, 100 },
624 { C::tx_next_da_gas_used, 2 },
625 { C::tx_next_l2_gas_used, 200 },
626 { C::tx_next_da_gas_used_sent_to_enqueued_call, 2 },
627 { C::tx_next_l2_gas_used_sent_to_enqueued_call, 200 },
628 } });
629
630 trace.set(5,
631 { {
632 { C::tx_prev_da_gas_used, 2 },
633 { C::tx_prev_l2_gas_used, 200 },
634 { C::tx_prev_da_gas_used_sent_to_enqueued_call, 2 },
635 { C::tx_prev_l2_gas_used_sent_to_enqueued_call, 200 },
636 { C::tx_next_da_gas_used, 3 },
637 { C::tx_next_l2_gas_used, 300 },
638 { C::tx_next_da_gas_used_sent_to_enqueued_call, 3 },
639 { C::tx_next_l2_gas_used_sent_to_enqueued_call, 300 },
640 } });
641
642 for (uint32_t i = 6; i < 9; i++) {
643 trace.set(i,
644 { {
645 { C::tx_prev_da_gas_used, 3 },
646 { C::tx_prev_l2_gas_used, 300 },
647 { C::tx_next_da_gas_used, 3 },
648 { C::tx_next_l2_gas_used, 300 },
649 } });
650 }
651
652 trace.set(9,
653 { {
654 { C::tx_prev_da_gas_used, 3 },
655 { C::tx_prev_l2_gas_used, 300 },
656 { C::tx_prev_da_gas_used_sent_to_enqueued_call, 3 },
657 { C::tx_prev_l2_gas_used_sent_to_enqueued_call, 300 },
658 { C::tx_next_da_gas_used, 4 },
659 { C::tx_next_l2_gas_used, 400 },
660 { C::tx_next_da_gas_used_sent_to_enqueued_call, 4 },
661 { C::tx_next_l2_gas_used_sent_to_enqueued_call, 400 },
662 } });
663
664 trace.set(10,
665 { {
666 { C::tx_sel_process_call_request, 1 },
667 { C::tx_remaining_phase_counter, 1 },
668 { C::tx_remaining_phase_inv, 1 },
669 // Public Input Loaded Values
670 { C::tx_msg_sender, teardown_call_request.msg_sender },
671 { C::tx_contract_addr, teardown_call_request.contract_address },
672 { C::tx_is_static, teardown_call_request.is_static_call },
673 { C::tx_calldata_hash, teardown_call_request.calldata_hash },
674 { C::tx_prev_da_gas_used, 4 },
675 { C::tx_prev_l2_gas_used, 400 },
676 { C::tx_prev_da_gas_used_sent_to_enqueued_call, 0 },
677 { C::tx_prev_l2_gas_used_sent_to_enqueued_call, 0 },
678 { C::tx_next_da_gas_used, 4 },
679 { C::tx_next_l2_gas_used, 400 },
680 { C::tx_next_da_gas_used_sent_to_enqueued_call, 13213 },
681 { C::tx_next_l2_gas_used_sent_to_enqueued_call, 456789 },
682 } });
683
684 trace.set(11,
685 { {
686 { C::tx_prev_da_gas_used, 4 },
687 { C::tx_prev_l2_gas_used, 400 },
688 { C::tx_next_da_gas_used, 4 },
689 { C::tx_next_l2_gas_used, 400 },
690 } });
691
692 public_inputs_builder.process_public_inputs(trace, test_public_inputs);
693 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
694
696 precomputed_builder.process_misc(trace, AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH);
697
698 check_relation<tx>(trace);
699 check_interaction<TxTraceBuilder, lookup_tx_read_phase_spec_settings>(trace);
700 check_interaction<TxTraceBuilder, lookup_tx_read_phase_length_settings>(trace);
701 check_interaction<TxTraceBuilder, lookup_tx_read_public_call_request_phase_settings>(trace);
702 check_interaction<TxTraceBuilder, lookup_tx_read_effective_fee_public_inputs_settings>(trace);
703 check_interaction<TxTraceBuilder, lookup_tx_read_fee_payer_public_inputs_settings>(trace);
704}
705
706TEST(TxExecutionConstrainingTest, NegativeTreePaddingChecks)
707{
709 {
710 // Row 0
711 { C::precomputed_first_row, 1 },
712 },
713 {
714 // Row 1
715 { C::tx_sel, 1 },
716 { C::tx_is_tree_padding, 1 },
717 { C::tx_prev_note_hash_tree_root, 42 },
718 { C::tx_next_note_hash_tree_root, 42 },
719 { C::tx_prev_note_hash_tree_size, 5 },
720 { C::tx_next_note_hash_tree_size, MAX_NOTE_HASHES_PER_TX },
721 { C::tx_prev_num_note_hashes_emitted, 5 },
722 { C::tx_next_num_note_hashes_emitted, 5 },
723 { C::tx_prev_nullifier_tree_root, 43 },
724 { C::tx_next_nullifier_tree_root, 43 },
725 { C::tx_prev_nullifier_tree_size, 7 },
726 { C::tx_next_nullifier_tree_size, MAX_NULLIFIERS_PER_TX },
727 { C::tx_prev_num_nullifiers_emitted, 7 },
728 { C::tx_next_num_nullifiers_emitted, 7 },
729 },
730 });
732
733 check_relation<tx_context>(trace,
740
741 // Negative test: change note hash root in tree padding
742 trace.set(C::tx_next_note_hash_tree_root, 1, 999);
745
746 // Negative test: change num emitted note hashes in tree padding
747 trace.set(C::tx_next_num_note_hashes_emitted, 1, 999);
750
751 // Negative test: change nullifier tree root in tree padding
752 trace.set(C::tx_next_nullifier_tree_root, 1, 999);
755
756 // Negative test: change num emitted nullifiers in tree padding
757 trace.set(C::tx_next_num_nullifiers_emitted, 1, 999);
760
761 // Negative test: wrong note hash padding check
762 trace.set(C::tx_next_note_hash_tree_size, 1, MAX_NOTE_HASHES_PER_TX - 1);
765
766 // Negative test: wrong nullifier padding check
767 trace.set(C::tx_next_nullifier_tree_size, 1, MAX_NULLIFIERS_PER_TX - 1);
770}
771
784
786{
789 auto test_public_inputs = testing::PublicInputsBuilder()
791 .rand_public_app_logic_call_requests(2)
792 .build();
793
794 std::vector<FF> dummy_setup_calldata = { 1, 2 };
795 std::vector<FF> dummy_setup_calldata_preimage = dummy_setup_calldata;
796 dummy_setup_calldata_preimage.insert(dummy_setup_calldata_preimage.begin(), DOM_SEP__PUBLIC_CALLDATA);
797 FF dummy_setup_calldata_hash = poseidon2.hash(dummy_setup_calldata_preimage);
798 test_public_inputs.public_setup_call_requests[0].calldata_hash = dummy_setup_calldata_hash;
799
800 std::vector<FF> non_empty_calldata = { 2, 3, 4 };
801 std::vector<FF> non_empty_calldata_preimage = non_empty_calldata;
802 non_empty_calldata_preimage.insert(non_empty_calldata_preimage.begin(), DOM_SEP__PUBLIC_CALLDATA);
803 FF non_empty_calldata_hash = poseidon2.hash(non_empty_calldata_preimage);
804 test_public_inputs.public_app_logic_call_requests[0].calldata_hash = non_empty_calldata_hash;
805
806 FF empty_calldata_hash = poseidon2.hash({ DOM_SEP__PUBLIC_CALLDATA });
807 test_public_inputs.public_app_logic_call_requests[1].calldata_hash = empty_calldata_hash;
808
810 { .context_id = 1, .calldata = dummy_setup_calldata, .calldata_hash = dummy_setup_calldata_hash },
811 { .context_id = 5, .calldata = non_empty_calldata, .calldata_hash = non_empty_calldata_hash },
812 { .context_id = 6, .calldata = {}, .calldata_hash = empty_calldata_hash },
813 };
814
815 auto setup_call_request = test_public_inputs.public_setup_call_requests[0];
816 auto non_empty_calldata_app_logic_call_request = test_public_inputs.public_app_logic_call_requests[0];
817 auto empty_calldata_app_logic_call_request = test_public_inputs.public_app_logic_call_requests[1];
818
820
821 set_initial_columns(trace,
822 { setup_call_request },
823 { non_empty_calldata_app_logic_call_request, empty_calldata_app_logic_call_request });
824
825 // Set calldata specific values for setup:
826 trace.set(4, { { { C::tx_calldata_size, 2 }, { C::tx_next_context_id, 1 } } });
827
828 // Set calldata specific values for non empty calldata call:
829 trace.set(8, { { { C::tx_calldata_size, 3 }, { C::tx_next_context_id, 5 } } });
830
831 // Set calldata specific values for empty calldata call:
832 trace.set(9, { { { C::tx_calldata_size, 0 }, { C::tx_next_context_id, 6 } } });
833
834 // Set teardown as padded:
835 trace.set(10, { { { C::tx_is_padded, 1 } } });
836
837 public_inputs_builder.process_public_inputs(trace, test_public_inputs);
838 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
839
841 precomputed_builder.process_misc(trace, AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH);
842
844
845 calldata_builder.process_retrieval(calldata_events, trace);
846 calldata_builder.process_hashing(calldata_events, trace);
847
848 check_relation<tx>(trace);
854 check_relation<bb::avm2::calldata_hashing<FF>>(trace);
855 check_all_interactions<tracegen::CalldataTraceBuilder>(trace);
856}
857
858// Verify that the nullifier state increment is unconditional when sel_nullifier_append = 1.
859// A malicious prover cannot set reverted = 1 to skip the state increment.
860TEST(TxExecutionConstrainingTest, NegativeNullifierStateIncrementIsUnconditional)
861{
862 // #[NULLIFIER_TREE_SIZE_INCREMENT]: sel_nullifier_append * (prev_nullifier_tree_size + 1 -
863 // next_nullifier_tree_size) =
864 // 0
865 // #[NUM_NULLIFIERS_EMITTED_INCREMENT]: sel_nullifier_append * (prev_num_nullifiers_emitted + 1 -
866 // next_num_nullifiers_emitted) = 0
868 {
869 // Row 0
870 { C::precomputed_first_row, 1 },
871 },
872 {
873 // Row 1: Nullifier append with sel_nullifier_append = 1 but state not incremented.
874 { C::tx_sel, 1 },
875 { C::tx_sel_nullifier_append, 1 },
876 { C::tx_reverted, 1 }, // Prover tries to cheat by setting reverted = 1.
877 { C::tx_prev_nullifier_tree_size, 5 },
878 { C::tx_next_nullifier_tree_size, 5 }, // Should be 6.
879 { C::tx_prev_num_nullifiers_emitted, 3 },
880 { C::tx_next_num_nullifiers_emitted, 3 }, // Should be 4.
881 },
882 });
883
884 // Tree size must increment unconditionally.
887 // Fix tree size, break emitted count.
888 trace.set(C::tx_next_nullifier_tree_size, 1, 6);
891 // Fix emitted count — both should pass now.
892 trace.set(C::tx_next_num_nullifiers_emitted, 1, 4);
894}
895
896// When the maximum number of nullifier writes has been reached (REMAINING_NULLIFIER_WRITES == 0),
897// the prover must set `reverted = 1`; setting `reverted = 0` is rejected.
898TEST(TxExecutionConstrainingTest, MaxNullifierWritesReachedForcesReverted)
899{
900 // #[MAX_NULLIFIER_WRITES_REACHED]:
901 // sel_try_nullifier_append * (REMAINING_NULLIFIER_WRITES *
902 // (reverted * (1 - remaining_side_effects_inv) + remaining_side_effects_inv) - 1 + reverted) = 0
903 // With REMAINING_NULLIFIER_WRITES = MAX_NULLIFIERS_PER_TX - prev_num_nullifiers_emitted = 0,
904 // the constraint reduces to (reverted - 1) = 0, forcing reverted = 1.
906 {
907 // Row 0
908 { C::precomputed_first_row, 1 },
909 },
910 {
911 // Row 1: the nullifier write limit has been reached and the prover honestly reverts.
912 { C::tx_sel_try_nullifier_append, 1 },
913 { C::tx_prev_num_nullifiers_emitted, MAX_NULLIFIERS_PER_TX },
914 { C::tx_reverted, 1 },
915 },
916 });
917
918 // Honest trace satisfies the relation.
919 check_relation<tx>(trace, tx::SR_MAX_NULLIFIER_WRITES_REACHED);
920
921 // Mutate: prover tries to skip the revert despite being at the limit.
922 trace.set(C::tx_reverted, 1, 0);
925}
926
927// A malicious prover cannot toggle `reverted = 1` when REMAINING_NULLIFIER_WRITES > 0:
928// no value of `remaining_side_effects_inv` can satisfy the constraint in that case.
929TEST(TxExecutionConstrainingTest, NegativeCannotRevertWhenNullifierWritesAvailable)
930{
931 // With REMAINING_NULLIFIER_WRITES > 0 and reverted = 1, the inner factor reduces to 1 (independently
932 // of remaining_side_effects_inv), so the constraint evaluates to REMAINING_NULLIFIER_WRITES != 0.
933 constexpr uint32_t prev_emitted = 3;
934 constexpr uint32_t remaining = MAX_NULLIFIERS_PER_TX - prev_emitted;
935 static_assert(remaining > 0);
936
938 {
939 // Row 0
940 { C::precomputed_first_row, 1 },
941 },
942 {
943 // Row 1: nullifier write slots are still available; honest prover does not revert.
944 { C::tx_sel_try_nullifier_append, 1 },
945 { C::tx_prev_num_nullifiers_emitted, prev_emitted },
946 { C::tx_reverted, 0 },
947 { C::tx_remaining_side_effects_inv, FF(remaining).invert() },
948 },
949 });
950
951 // Honest trace satisfies the relation.
952 check_relation<tx>(trace, tx::SR_MAX_NULLIFIER_WRITES_REACHED);
953
954 // Mutate: prover maliciously toggles reverted = 1 despite slots remaining.
955 trace.set(C::tx_reverted, 1, 1);
958}
959
960} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:224
StrictMock< MockGreaterThan > mock_gt
EventEmitter< Poseidon2PermutationMemoryEvent > perm_mem_event_emitter
EventEmitter< Poseidon2PermutationEvent > perm_event_emitter
EventEmitter< Poseidon2HashEvent > hash_event_emitter
Poseidon2TraceBuilder poseidon2_builder
StrictMock< MockExecutionIdManager > mock_execution_id_manager
simulation::EventEmitter< simulation::Poseidon2HashEvent > hash_event_emitter
Definition tx.test.cpp:774
::testing::StrictMock< simulation::MockGreaterThan > mock_gt
Definition tx.test.cpp:778
simulation::EventEmitter< simulation::Poseidon2PermutationEvent > perm_event_emitter
Definition tx.test.cpp:775
::testing::StrictMock< simulation::MockExecutionIdManager > mock_execution_id_manager
Definition tx.test.cpp:779
simulation::EventEmitter< simulation::Poseidon2PermutationMemoryEvent > perm_mem_event_emitter
Definition tx.test.cpp:776
PublicInputsBuilder & rand_public_setup_call_requests(size_t n)
PublicInputsBuilder & rand_previous_non_revertible_accumulated_data(size_t n)
void process_hash(const simulation::EventEmitterInterface< simulation::Poseidon2HashEvent >::Container &hash_events, TraceContainer &trace)
Processes the hash events for the Poseidon2 hash function. It populates the columns for the poseidon2...
void process_misc(TraceContainer &trace, const uint32_t num_rows=PRECOMPUTED_TRACE_SIZE)
Populate miscellaneous precomputed columns: first_row selector and idx (row index).
void process_phase_table(TraceContainer &trace)
Populate the transaction phase specification table.
void process_public_inputs(TraceContainer &trace, const PublicInputs &public_inputs)
Populate the public inputs trace columns from the given public inputs.
void set(Column col, uint32_t row, const FF &value, bool use_atomic_limbs=false)
static constexpr size_t SR_NULLIFIER_SIZE_IMMUTABILITY
static constexpr size_t SR_INIT_TX_REVERTED
static constexpr size_t SR_NULLIFIER_COUNT_IMMUTABILITY
static std::string get_subrelation_label(size_t index)
static constexpr size_t SR_NOTE_HASH_ROOT_IMMUTABILITY
static constexpr size_t SR_NOTE_HASH_SIZE_IMMUTABILITY
static constexpr size_t SR_NULLIFIER_ROOT_IMMUTABILITY
static constexpr size_t SR_NOTE_HASH_COUNT_IMMUTABILITY
static constexpr size_t SR_TX_REVERTED_CONTINUITY
static constexpr size_t SR_SET_TX_REVERTED
static constexpr size_t SR_NO_EARLY_END
Definition tx.hpp:47
static std::string get_subrelation_label(size_t index)
Definition tx.hpp:73
static constexpr size_t SR_NULLIFIER_EMITTED_COUNT_INCREMENT
Definition tx.hpp:62
static constexpr size_t SR_MAX_NULLIFIER_WRITES_REACHED
Definition tx.hpp:60
static constexpr size_t SR_PAD_NOTE_HASH_TREE
Definition tx.hpp:69
static constexpr size_t SR_NULLIFIER_TREE_SIZE_INCREMENT
Definition tx.hpp:61
static constexpr size_t SR_TRACE_CONTINUITY
Definition tx.hpp:41
static constexpr size_t SR_PAD_NULLIFIER_TREE
Definition tx.hpp:70
static constexpr size_t SR_START_WITH_SEL
Definition tx.hpp:43
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
PrecomputedTraceBuilder precomputed_builder
Definition alu.test.cpp:120
TestTraceContainer trace
TEST_F(AvmRecursiveTests, TwoLayerAvmRecursion)
A test of the Two Layer AVM recursive verifier.
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
TestTraceContainer empty_trace()
Definition fixtures.cpp:156
lookup_settings< lookup_tx_read_phase_spec_settings_ > lookup_tx_read_phase_spec_settings
AvmFlavorSettings::FF FF
Definition field.hpp:10
permutation_settings< perm_tx_read_calldata_hash_settings_ > perm_tx_read_calldata_hash_settings
Definition perms_tx.hpp:33
lookup_settings< lookup_tx_read_public_call_request_phase_settings_ > lookup_tx_read_public_call_request_phase_settings
lookup_settings< lookup_tx_read_phase_length_settings_ > lookup_tx_read_phase_length_settings
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
EventEmitter< CalldataEvent > calldata_events
std::vector< std::vector< FF > > to_columns() const
Serialization to columns.
Definition avm_io.cpp:142
std::array< PublicCallRequest, MAX_ENQUEUED_CALLS_PER_TX > public_setup_call_requests
Definition avm_io.hpp:39
Settings to be passed ot GenericLookupRelationImpl.
tracegen::PublicInputsTraceBuilder public_inputs_builder
Definition tx.test.cpp:84