Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
execution.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <cstdint>
5
18
19namespace bb::avm2::constraining {
20namespace {
21
22using tracegen::TestTraceContainer;
24using C = Column;
26using addressing = bb::avm2::addressing<FF>;
27using gas = bb::avm2::gas<FF>;
28using registers = bb::avm2::registers<FF>;
29
30TEST(ExecutionConstrainingTest, EmptyRow)
31{
32 check_relation<execution>(testing::empty_trace());
33}
34
35// DO NOT SUBMIT: add full flow tests
36// TEST(ExecutionConstrainingTest, Basic)
37// {
38// // clang-format off
39// TestTraceContainer trace({
40// {{ C::execution_sel, 1 }, { C::execution_pc, 0 }},
41// {{ C::execution_sel, 1 }, { C::execution_pc, 20 }, { C::execution_last, 1 }}
42// });
43// // clang-format on
44
45// check_relation<execution>(trace);
46// }
47
48TEST(ExecutionConstrainingTest, Continuity)
49{
50 // clang-format off
51 TestTraceContainer trace({
52 {{ C::precomputed_first_row, 1 }},
53 {{ C::execution_sel, 1 }},
54 {{ C::execution_sel, 1 }},
55 {{ C::execution_sel, 1 }, { C::execution_enqueued_call_end, 1 }},
56 });
57 // clang-format on
58
59 check_relation<execution>(trace, execution::SR_TRACE_CONTINUITY);
60
61 // Negative test: remove enqueued call end
62 trace.set(C::execution_enqueued_call_end, 3, 0);
63 EXPECT_THROW_WITH_MESSAGE(check_relation<execution>(trace, execution::SR_TRACE_CONTINUITY), "TRACE_CONTINUITY");
64}
65
66TEST(ExecutionConstrainingTest, ContinuityBrokenFirstRow)
67{
68 // clang-format off
69 TestTraceContainer trace({
70 {{ C::execution_sel, 0 }}, // End of trace!
71 {{ C::execution_sel, 1 }},
72 {{ C::execution_sel, 1 }},
73 {{ C::execution_sel, 1 }, { C::execution_enqueued_call_end, 1 }},
74 });
75 // clang-format on
76
77 EXPECT_THROW_WITH_MESSAGE(check_relation<execution>(trace, execution::SR_TRACE_CONTINUITY), "TRACE_CONTINUITY");
78}
79
80TEST(ExecutionConstrainingTest, ContinuityBrokenInMiddle)
81{
82 // clang-format off
83 TestTraceContainer trace({
84 {{ C::execution_sel, 1 }},
85 {{ C::execution_sel, 0 }}, // End of trace!
86 {{ C::execution_sel, 1 }},
87 {{ C::execution_sel, 1 }, { C::execution_enqueued_call_end, 1 }},
88 });
89 // clang-format on
90
91 EXPECT_THROW_WITH_MESSAGE(check_relation<execution>(trace, execution::SR_TRACE_CONTINUITY), "TRACE_CONTINUITY");
92}
93
94TEST(ExecutionConstrainingTest, TreeStateNotChanged)
95{
96 TestTraceContainer trace({
97 {
98 { C::precomputed_first_row, 1 },
99 },
100 {
101 { C::execution_sel, 1 },
102 { C::execution_prev_note_hash_tree_root, 10 },
103 { C::execution_prev_note_hash_tree_size, 9 },
104 { C::execution_prev_num_note_hashes_emitted, 8 },
105 { C::execution_prev_nullifier_tree_root, 7 },
106 { C::execution_prev_nullifier_tree_size, 6 },
107 { C::execution_prev_num_nullifiers_emitted, 5 },
108 { C::execution_prev_public_data_tree_root, 4 },
109 { C::execution_prev_public_data_tree_size, 3 },
110 { C::execution_prev_written_public_data_slots_tree_root, 2 },
111 { C::execution_prev_written_public_data_slots_tree_size, 1 },
112 { C::execution_prev_retrieved_bytecodes_tree_root, 12 },
113 { C::execution_prev_retrieved_bytecodes_tree_size, 13 },
114 { C::execution_note_hash_tree_root, 10 },
115 { C::execution_note_hash_tree_size, 9 },
116 { C::execution_num_note_hashes_emitted, 8 },
117 { C::execution_nullifier_tree_root, 7 },
118 { C::execution_nullifier_tree_size, 6 },
119 { C::execution_num_nullifiers_emitted, 5 },
120 { C::execution_public_data_tree_root, 4 },
121 { C::execution_public_data_tree_size, 3 },
122 { C::execution_written_public_data_slots_tree_root, 2 },
123 { C::execution_written_public_data_slots_tree_size, 1 },
124 { C::execution_retrieved_bytecodes_tree_root, 12 },
125 { C::execution_retrieved_bytecodes_tree_size, 13 },
126 },
127 });
128
129 check_relation<execution>(trace,
142
143 // Negative test: change note hash tree root
144 trace.set(C::execution_note_hash_tree_root, 1, 100);
146 "NOTE_HASH_TREE_ROOT_NOT_CHANGED");
147
148 // Negative test: change note hash tree size
149 trace.set(C::execution_note_hash_tree_size, 1, 100);
151 "NOTE_HASH_TREE_SIZE_NOT_CHANGED");
152
153 // Negative test: change num note hashes emitted
154 trace.set(C::execution_num_note_hashes_emitted, 1, 100);
156 "NUM_NOTE_HASHES_EMITTED_NOT_CHANGED");
157
158 // Negative test: change nullifier tree root
159 trace.set(C::execution_nullifier_tree_root, 1, 100);
161 "NULLIFIER_TREE_ROOT_NOT_CHANGED");
162
163 // Negative test: change nullifier tree size
164 trace.set(C::execution_nullifier_tree_size, 1, 100);
166 "NULLIFIER_TREE_SIZE_NOT_CHANGED");
167
168 // Negative test: change num nullifiers emitted
169 trace.set(C::execution_prev_num_nullifiers_emitted, 1, 100);
171 "NUM_NULLIFIERS_EMITTED_NOT_CHANGED");
172
173 // Negative test: change public data tree root
174 trace.set(C::execution_public_data_tree_root, 1, 100);
176 "PUBLIC_DATA_TREE_ROOT_NOT_CHANGED");
177
178 // Negative test: change public data tree size
179 trace.set(C::execution_public_data_tree_size, 1, 100);
181 "PUBLIC_DATA_TREE_SIZE_NOT_CHANGED");
182
183 // Negative test: change written public data slots tree root
184 trace.set(C::execution_written_public_data_slots_tree_root, 1, 100);
187 "WRITTEN_PUBLIC_DATA_SLOTS_TREE_ROOT_NOT_CHANGED");
188
189 // Negative test: change written public data slots tree size
190 trace.set(C::execution_written_public_data_slots_tree_size, 1, 100);
193 "WRITTEN_PUBLIC_DATA_SLOTS_TREE_SIZE_NOT_CHANGED");
194
195 // Negative test: change retrieved bytecodes tree root
196 trace.set(C::execution_retrieved_bytecodes_tree_root, 1, 100);
198 "RETRIEVED_BYTECODES_TREE_ROOT_NOT_CHANGED");
199
200 // Negative test: change retrieved bytecodes tree size
201 trace.set(C::execution_retrieved_bytecodes_tree_size, 1, 100);
203 "RETRIEVED_BYTECODES_TREE_SIZE_NOT_CHANGED");
204}
205
206TEST(ExecutionConstrainingTest, SideEffectStateNotChanged)
207{
208 TestTraceContainer trace({
209 {
210 { C::precomputed_first_row, 1 },
211 },
212 {
213 { C::execution_sel, 1 },
214 { C::execution_prev_num_public_log_fields, 10 },
215 { C::execution_prev_num_l2_to_l1_messages, 11 },
216 { C::execution_num_public_log_fields, 10 },
217 { C::execution_num_l2_to_l1_messages, 11 },
218 },
219 });
220
221 check_relation<execution>(
223
224 // Negative test: change num public logs
225 trace.set(C::execution_num_public_log_fields, 1, 100);
227 "NUM_PUBLIC_LOGS_NOT_CHANGED");
228
229 // Negative test: change num l2 to l1 messages
230 trace.set(C::execution_num_l2_to_l1_messages, 1, 100);
232 "NUM_L2_TO_L1_MESSAGES_NOT_CHANGED");
233}
234
235TEST(ExecutionConstrainingTest, NoFetchingNoInstrFetchError)
236{
237 // sel_bytecode_retrieval_success == 0 => sel_instruction_fetching_failure == 0
238 TestTraceContainer trace({
239 { { C::execution_sel_bytecode_retrieval_success, 0 }, { C::execution_sel_instruction_fetching_failure, 0 } },
240 });
241
242 check_relation<execution>(trace, execution::SR_NO_FETCHING_NO_INSTR_FETCH_ERROR);
243
244 // Negative test: sel_bytecode_retrieval_success == 0 but sel_instruction_fetching_failure == 1
245 trace.set(C::execution_sel_instruction_fetching_failure, 0, 1);
247 "NO_FETCHING_NO_INSTR_FETCH_ERROR");
248
249 // Positive test: sel_bytecode_retrieval_success == 1 allows sel_instruction_fetching_failure == 1
250 trace.set(C::execution_sel_bytecode_retrieval_success, 0, 1);
251 check_relation<execution>(trace, execution::SR_NO_FETCHING_NO_INSTR_FETCH_ERROR);
252}
253
254TEST(ExecutionConstrainingTest, NoAddressingErrorIfNotResolving)
255{
256 // sel_instruction_fetching_success == 0 => sel_addressing_error == 0
257 // (SEL_RESOLVE_ADDRESS is an alias for sel_instruction_fetching_success)
258 TestTraceContainer trace({
259 { { C::execution_sel_instruction_fetching_success, 0 }, { C::execution_sel_addressing_error, 0 } },
260 });
261
262 check_relation<addressing>(trace, addressing::SR_NO_ADDRESSING_ERROR_IF_NOT_RESOLVING);
263
264 // Negative test: sel_instruction_fetching_success == 0 but sel_addressing_error == 1
265 trace.set(C::execution_sel_addressing_error, 0, 1);
267 "NO_ADDRESSING_ERROR_IF_NOT_RESOLVING");
268
269 // Positive test: sel_instruction_fetching_success == 1 allows sel_addressing_error == 1
270 trace.set(C::execution_sel_instruction_fetching_success, 0, 1);
271 check_relation<addressing>(trace, addressing::SR_NO_ADDRESSING_ERROR_IF_NOT_RESOLVING);
272}
273
274TEST(ExecutionConstrainingTest, NoRegisterReadErrorIfNotReading)
275{
276 // sel_read_registers == 0 => sel_register_read_error == 0
277 // Via #[REGISTER_READ_TAG_CHECK]: when sel_read_registers == 0, BATCHED_TAGS_DIFF_X_REG == 0,
278 // which forces sel_register_read_error == 0.
279 TestTraceContainer trace({
280 { { C::execution_sel_read_registers, 0 }, { C::execution_sel_register_read_error, 0 } },
281 });
282
283 check_relation<registers>(trace, registers::SR_REGISTER_READ_TAG_CHECK);
284
285 // Negative test: sel_read_registers == 0 but sel_register_read_error == 1
286 trace.set(C::execution_sel_register_read_error, 0, 1);
288 "REGISTER_READ_TAG_CHECK");
289}
290
291TEST(ExecutionConstrainingTest, NoOogIfNoGasCheck)
292{
293 // sel_check_gas == 0 => sel_out_of_gas == 0
294 TestTraceContainer trace({
295 { { C::execution_sel_check_gas, 0 }, { C::execution_sel_out_of_gas, 0 } },
296 });
297
298 check_relation<gas>(trace, gas::SR_NO_OOG_IF_NO_GAS_CHECK);
299
300 // Negative test: sel_check_gas == 0 but sel_out_of_gas == 1
301 trace.set(C::execution_sel_out_of_gas, 0, 1);
302 EXPECT_THROW_WITH_MESSAGE(check_relation<gas>(trace, gas::SR_NO_OOG_IF_NO_GAS_CHECK), "NO_OOG_IF_NO_GAS_CHECK");
303
304 // Positive test: sel_check_gas == 1 allows sel_out_of_gas == 1
305 trace.set(C::execution_sel_check_gas, 0, 1);
306 check_relation<gas>(trace, gas::SR_NO_OOG_IF_NO_GAS_CHECK);
307}
308
309TEST(ExecutionConstrainingTest, NoOpcodeErrorIfNotExecuting)
310{
311 // sel_execute_opcode == 0 => sel_opcode_error == 0
312 TestTraceContainer trace({
313 { { C::execution_sel_execute_opcode, 0 }, { C::execution_sel_opcode_error, 0 } },
314 });
315
316 check_relation<execution>(trace, execution::SR_NO_OPCODE_ERROR_IF_NOT_EXECUTING);
317
318 // Negative test: sel_execute_opcode == 0 but sel_opcode_error == 1
319 trace.set(C::execution_sel_opcode_error, 0, 1);
321 "NO_OPCODE_ERROR_IF_NOT_EXECUTING");
322
323 // Positive test: sel_execute_opcode == 1 allows sel_opcode_error == 1
324 trace.set(C::execution_sel_execute_opcode, 0, 1);
325 check_relation<execution>(trace, execution::SR_NO_OPCODE_ERROR_IF_NOT_EXECUTING);
326}
327
328TEST(ExecutionConstrainingTest, SubtraceIdDecomposition)
329{
333
334 TestTraceContainer trace;
335 const uint8_t enum_length = static_cast<uint8_t>(SubtraceSel::MAX) + 1;
336
337 for (uint8_t i = 0; i < enum_length; i++) {
338 SubtraceSel subtrace_sel = static_cast<SubtraceSel>(i);
339 const auto subtrace_id = get_subtrace_id(subtrace_sel);
340 const auto subtrace_selector = get_subtrace_selector(subtrace_sel);
341
342 trace.set(i,
343 { {
344 { subtrace_selector, 1 },
345 { C::execution_subtrace_id, subtrace_id },
346 { C::execution_sel_execute_opcode, 1 },
347 } });
348 }
349
350 check_relation<execution>(trace, execution::SR_SUBTRACE_ID_DECOMPOSITION);
351
352 for (uint8_t i = 0; i < enum_length; i++) {
353 const auto subtrace_selector = get_subtrace_selector(static_cast<SubtraceSel>(i));
354
355 // Negative test: de-activate the selector
356 trace.set(subtrace_selector, i, 0);
358 "SUBTRACE_ID_DECOMPOSITION");
359
360 // Negative test: activate the wrong selector
361 const auto wrong_selector = get_subtrace_selector(static_cast<SubtraceSel>((i + 1) % enum_length));
362 trace.set(wrong_selector, i, 1);
364 "SUBTRACE_ID_DECOMPOSITION");
365 // De-activate the wrong selector
366 trace.set(wrong_selector, i, 0);
367
368 // Re-activate the correct selector
369 trace.set(subtrace_selector, i, 1);
370
371 // Ensure we have a correct trace for the next iteration
372 check_relation<execution>(trace, execution::SR_SUBTRACE_ID_DECOMPOSITION);
373 }
374}
375
376} // namespace
377} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
static constexpr size_t SR_NO_ADDRESSING_ERROR_IF_NOT_RESOLVING
static constexpr size_t SR_NUM_L2_TO_L1_MESSAGES_NOT_CHANGED
Definition execution.hpp:75
static constexpr size_t SR_RETRIEVED_BYTECODES_TREE_ROOT_NOT_CHANGED
Definition execution.hpp:76
static constexpr size_t SR_WRITTEN_PUBLIC_DATA_SLOTS_TREE_SIZE_NOT_CHANGED
Definition execution.hpp:67
static constexpr size_t SR_NULLIFIER_TREE_SIZE_NOT_CHANGED
Definition execution.hpp:72
static constexpr size_t SR_NO_OPCODE_ERROR_IF_NOT_EXECUTING
Definition execution.hpp:79
static constexpr size_t SR_NUM_NULLIFIERS_EMITTED_NOT_CHANGED
Definition execution.hpp:73
static constexpr size_t SR_PUBLIC_DATA_TREE_SIZE_NOT_CHANGED
Definition execution.hpp:65
static constexpr size_t SR_NOTE_HASH_TREE_ROOT_NOT_CHANGED
Definition execution.hpp:68
static constexpr size_t SR_TRACE_CONTINUITY
Definition execution.hpp:44
static constexpr size_t SR_NO_FETCHING_NO_INSTR_FETCH_ERROR
Definition execution.hpp:48
static constexpr size_t SR_SUBTRACE_ID_DECOMPOSITION
Definition execution.hpp:54
static constexpr size_t SR_NULLIFIER_TREE_ROOT_NOT_CHANGED
Definition execution.hpp:71
static constexpr size_t SR_NUM_PUBLIC_LOGS_NOT_CHANGED
Definition execution.hpp:74
static constexpr size_t SR_PUBLIC_DATA_TREE_ROOT_NOT_CHANGED
Definition execution.hpp:64
static constexpr size_t SR_WRITTEN_PUBLIC_DATA_SLOTS_TREE_ROOT_NOT_CHANGED
Definition execution.hpp:66
static constexpr size_t SR_NOTE_HASH_TREE_SIZE_NOT_CHANGED
Definition execution.hpp:69
static constexpr size_t SR_RETRIEVED_BYTECODES_TREE_SIZE_NOT_CHANGED
Definition execution.hpp:77
static constexpr size_t SR_NUM_NOTE_HASHES_EMITTED_NOT_CHANGED
Definition execution.hpp:70
static constexpr size_t SR_NO_OOG_IF_NO_GAS_CHECK
Definition gas.hpp:38
static constexpr size_t SR_REGISTER_READ_TAG_CHECK
Definition registers.hpp:44
void set(Column col, uint32_t row, const FF &value)
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:153
Column get_subtrace_selector(SubtraceSel subtrace_sel)
Get the column selector for a given subtrace selector.
FF get_subtrace_id(SubtraceSel subtrace_sel)
Get the subtrace ID for a given subtrace enum.
NiceMock< MockExecution > execution