Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
get_contract_instance.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <cstdint>
5
22
23namespace bb::avm2::constraining {
24namespace {
25
26using simulation::EventEmitter;
27using simulation::GetContractInstanceEvent;
28using tracegen::GetContractInstanceTraceBuilder;
29using tracegen::MemoryTraceBuilder;
30using tracegen::PrecomputedTraceBuilder;
31using tracegen::TestTraceContainer;
33using C = Column;
34using get_contract_instance = bb::avm2::get_contract_instance<FF>;
35
36TEST(GetContractInstanceConstrainingTest, EmptyRow)
37{
38 check_relation<get_contract_instance>(testing::empty_trace());
39}
40
41TEST(GetContractInstanceConstrainingTest, WriteInBoundsCheck)
42{
43 // Test constants
44 const FF dst_offset = FF(100); // Use a smaller offset for clear testing
45 const FF dst_offset_diff_max = FF(AVM_HIGHEST_MEM_ADDRESS) - dst_offset; // AVM_HIGHEST_MEM_ADDRESS - 100
46 const FF dst_offset_diff_max_inv = dst_offset_diff_max.invert(); // 1/DST_OFFSET_DIFF_MAX
47 const FF wrong_inv_value = FF(42);
48
49 TestTraceContainer trace({
50 { { C::precomputed_first_row, 1 } },
51 { { C::get_contract_instance_sel, 1 },
52 { C::get_contract_instance_dst_offset, dst_offset },
53 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
54 { C::get_contract_instance_dst_offset_diff_max_inv, dst_offset_diff_max_inv } },
55 });
56
57 check_relation<get_contract_instance>(trace, get_contract_instance::SR_WRITE_OUT_OF_BOUNDS_CHECK);
58
59 // Negative test: mutate to incorrect dst_offset_diff_max_inv
60 trace.set(C::get_contract_instance_dst_offset_diff_max_inv, 1, wrong_inv_value); // Wrong inv value
62 check_relation<get_contract_instance>(trace, get_contract_instance::SR_WRITE_OUT_OF_BOUNDS_CHECK),
63 "WRITE_OUT_OF_BOUNDS_CHECK");
64 // Reset
65 trace.set(C::get_contract_instance_dst_offset_diff_max_inv, 1, dst_offset_diff_max_inv);
66
67 // Negative test: mutate to incorrect sel_write_in_bounds
68 trace.set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 0); // Out of bounds
70 check_relation<get_contract_instance>(trace, get_contract_instance::SR_WRITE_OUT_OF_BOUNDS_CHECK),
71 "WRITE_OUT_OF_BOUNDS_CHECK");
72 // Reset
73 trace.set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 1);
74}
75
76TEST(GetContractInstanceConstrainingTest, WriteOutOfBoundsCheck)
77{
78 // Test constants
79 const FF dst_offset = FF(AVM_HIGHEST_MEM_ADDRESS); // Boundary case: dst_offset + 1 is out of bounds
80 const FF dst_offset_diff_max_inv = FF(0);
81
82 TestTraceContainer trace({
83 { { C::precomputed_first_row, 1 } },
84 { { C::get_contract_instance_sel, 1 },
85 { C::get_contract_instance_dst_offset, dst_offset },
86 { C::get_contract_instance_is_valid_writes_in_bounds, 0 },
87 { C::get_contract_instance_dst_offset_diff_max_inv, dst_offset_diff_max_inv } },
88 });
89
90 check_relation<get_contract_instance>(trace, get_contract_instance::SR_WRITE_OUT_OF_BOUNDS_CHECK);
91
92 // Negative test: mutate to incorrect sel_write_in_bounds
93 trace.set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 1);
95 check_relation<get_contract_instance>(trace, get_contract_instance::SR_WRITE_OUT_OF_BOUNDS_CHECK),
96 "WRITE_OUT_OF_BOUNDS_CHECK");
97 // Reset
98 trace.set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 0);
99}
100
101TEST(GetContractInstanceConstrainingTest, ErrorAggregationConstraint)
102{
103 // Test error aggregation subrelation
104 TestTraceContainer trace({
105 { { C::precomputed_first_row, 1 } },
106 // No error case
107 { { C::get_contract_instance_sel, 1 },
108 { C::get_contract_instance_sel_error, 0 },
109 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
110 { C::get_contract_instance_is_valid_member_enum, 1 } },
111 });
112
113 check_relation<get_contract_instance>(trace, get_contract_instance::SR_ERROR_AGGREGATION);
114
115 // Test bounds error
116 trace.set(C::get_contract_instance_sel_error, 1, 1);
117 trace.set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 0); // Out of bounds
118 check_relation<get_contract_instance>(trace, get_contract_instance::SR_ERROR_AGGREGATION);
119
120 // Test enum error
121 trace.set(C::get_contract_instance_sel_error, 1, 1);
122 trace.set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 1); // In bounds
123 trace.set(C::get_contract_instance_is_valid_member_enum, 1, 0); // Invalid enum
124 check_relation<get_contract_instance>(trace, get_contract_instance::SR_ERROR_AGGREGATION);
125
126 // Test both errors
127 trace.set(C::get_contract_instance_sel_error, 1, 1);
128 trace.set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 0); // Out of bounds
129 trace.set(C::get_contract_instance_is_valid_member_enum, 1, 0); // Invalid enum
130 check_relation<get_contract_instance>(trace, get_contract_instance::SR_ERROR_AGGREGATION);
131
132 // Negative test: wrong error value
133 trace.set(C::get_contract_instance_sel_error, 1, 0);
134 EXPECT_THROW_WITH_MESSAGE(check_relation<get_contract_instance>(trace, get_contract_instance::SR_ERROR_AGGREGATION),
135 "ERROR_AGGREGATION");
136}
137
138TEST(GetContractInstanceConstrainingTest, SelectedMemberConstraint)
139{
140 // Test constants
141 const FF deployer_addr = 0x1234;
142 const FF class_id = 0x5678;
143 const FF init_hash = 0x9ABC;
144 const FF immutables_hash = 0xCAFE;
145 const FF wrong_value = 0x1111;
146
147 // Test selected member subrelation
148 TestTraceContainer trace({
149 { { C::precomputed_first_row, 1 } },
150 // DEPLOYER selection
151 { { C::get_contract_instance_sel, 1 },
152 { C::get_contract_instance_selected_member, deployer_addr },
153 { C::get_contract_instance_is_deployer, 1 },
154 { C::get_contract_instance_is_class_id, 0 },
155 { C::get_contract_instance_is_init_hash, 0 },
156 { C::get_contract_instance_is_immutables_hash, 0 },
157 { C::get_contract_instance_retrieved_deployer_addr, deployer_addr },
158 { C::get_contract_instance_retrieved_class_id, class_id },
159 { C::get_contract_instance_retrieved_init_hash, init_hash },
160 { C::get_contract_instance_retrieved_immutables_hash, immutables_hash } },
161 });
162
163 check_relation<get_contract_instance>(trace, get_contract_instance::SR_SELECTED_MEMBER);
164
165 // Test CLASS_ID selection
166 trace.set(C::get_contract_instance_selected_member, 1, class_id);
167 trace.set(C::get_contract_instance_is_deployer, 1, 0);
168 trace.set(C::get_contract_instance_is_class_id, 1, 1);
169 check_relation<get_contract_instance>(trace, get_contract_instance::SR_SELECTED_MEMBER);
170
171 // Test INIT_HASH selection
172 trace.set(C::get_contract_instance_selected_member, 1, init_hash);
173 trace.set(C::get_contract_instance_is_class_id, 1, 0);
174 trace.set(C::get_contract_instance_is_init_hash, 1, 1);
175 check_relation<get_contract_instance>(trace, get_contract_instance::SR_SELECTED_MEMBER);
176
177 // Test IMMUTABLES_HASH selection
178 trace.set(C::get_contract_instance_selected_member, 1, immutables_hash);
179 trace.set(C::get_contract_instance_is_init_hash, 1, 0);
180 trace.set(C::get_contract_instance_is_immutables_hash, 1, 1);
181 check_relation<get_contract_instance>(trace, get_contract_instance::SR_SELECTED_MEMBER);
182
183 // Negative test: wrong selected member
184 trace.set(C::get_contract_instance_selected_member, 1, wrong_value); // Wrong value
185 EXPECT_THROW_WITH_MESSAGE(check_relation<get_contract_instance>(trace, get_contract_instance::SR_SELECTED_MEMBER),
186 "SELECTED_MEMBER");
187}
188
189TEST(GetContractInstanceConstrainingTest, ComplexMultiRowSequence)
190{
191 // Test constants
192 const uint32_t dst_offset_1 = 100;
193 const uint32_t dst_offset_2 = 200;
194 const uint32_t dst_offset_3 = 300;
195 const uint8_t deployer_enum = 0;
196 const uint8_t class_id_enum = 1;
197 const uint8_t invalid_enum = 5;
198 const FF deployer_addr_1 = 0x1234;
199 const FF class_id_1 = 0x5678;
200 const FF init_hash_1 = 0x9ABC;
201 const FF deployer_addr_2 = 0x1111;
202 const FF class_id_2 = 0x2222;
203 const FF init_hash_2 = 0x3333;
204 const FF deployer_addr_3 = 0x4444;
205 const FF class_id_3 = 0x5555;
206 const FF init_hash_3 = 0x6666;
207 const uint32_t member_write_offset_1 = 101;
208 const uint32_t member_write_offset_2 = 201;
209 const uint32_t member_write_offset_3 = 301;
210 const uint8_t u1_tag = static_cast<uint8_t>(ValueTag::U1);
211 const uint8_t ff_tag = static_cast<uint8_t>(ValueTag::FF);
212
213 // Test multiple GetContractInstance operations in sequence
214 TestTraceContainer trace({
215 { { C::precomputed_first_row, 1 } },
216 // Row 1: skippable gadget selector
217 { { C::get_contract_instance_sel, 0 } }, // Must satisfy error constraint
218 // Row 2: Valid DEPLOYER retrieval
219 { { C::get_contract_instance_sel, 1 },
220 { C::get_contract_instance_dst_offset, dst_offset_1 },
221 { C::get_contract_instance_member_enum, deployer_enum }, // DEPLOYER
222 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
223 { C::get_contract_instance_dst_offset_diff_max_inv, FF(AVM_HIGHEST_MEM_ADDRESS - dst_offset_1).invert() },
224 { C::get_contract_instance_sel_error, 0 },
225 { C::get_contract_instance_is_valid_member_enum, 1 },
226 { C::get_contract_instance_is_deployer, 1 },
227 { C::get_contract_instance_is_class_id, 0 },
228 { C::get_contract_instance_is_init_hash, 0 },
229 { C::get_contract_instance_retrieved_deployer_addr, deployer_addr_1 },
230 { C::get_contract_instance_retrieved_class_id, class_id_1 },
231 { C::get_contract_instance_retrieved_init_hash, init_hash_1 },
232 { C::get_contract_instance_selected_member, deployer_addr_1 },
233 { C::get_contract_instance_member_write_offset, member_write_offset_1 },
234 { C::get_contract_instance_exists_tag, u1_tag },
235 { C::get_contract_instance_member_tag, ff_tag } },
236 // Row 3: Valid CLASS_ID retrieval
237 { { C::get_contract_instance_sel, 1 },
238 { C::get_contract_instance_dst_offset, dst_offset_2 },
239 { C::get_contract_instance_member_enum, class_id_enum }, // CLASS_ID
240 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
241 { C::get_contract_instance_dst_offset_diff_max_inv, FF(AVM_HIGHEST_MEM_ADDRESS - dst_offset_2).invert() },
242 { C::get_contract_instance_sel_error, 0 },
243 { C::get_contract_instance_is_valid_member_enum, 1 },
244 { C::get_contract_instance_is_deployer, 0 },
245 { C::get_contract_instance_is_class_id, 1 },
246 { C::get_contract_instance_is_init_hash, 0 },
247 { C::get_contract_instance_retrieved_deployer_addr, deployer_addr_2 },
248 { C::get_contract_instance_retrieved_class_id, class_id_2 },
249 { C::get_contract_instance_retrieved_init_hash, init_hash_2 },
250 { C::get_contract_instance_selected_member, class_id_2 },
251 { C::get_contract_instance_member_write_offset, member_write_offset_2 },
252 { C::get_contract_instance_exists_tag, u1_tag },
253 { C::get_contract_instance_member_tag, ff_tag } },
254 // Row 4: Invalid member enum with error
255 { { C::get_contract_instance_sel, 1 },
256 { C::get_contract_instance_dst_offset, dst_offset_3 },
257 { C::get_contract_instance_member_enum, invalid_enum }, // Invalid
258 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
259 { C::get_contract_instance_dst_offset_diff_max_inv, FF(AVM_HIGHEST_MEM_ADDRESS - dst_offset_3).invert() },
260 { C::get_contract_instance_sel_error, 1 }, // Error due to invalid enum
261 { C::get_contract_instance_is_valid_member_enum, 0 },
262 { C::get_contract_instance_is_deployer, 0 },
263 { C::get_contract_instance_is_class_id, 0 },
264 { C::get_contract_instance_is_init_hash, 0 },
265 { C::get_contract_instance_retrieved_deployer_addr, deployer_addr_3 },
266 { C::get_contract_instance_retrieved_class_id, class_id_3 },
267 { C::get_contract_instance_retrieved_init_hash, init_hash_3 },
268 { C::get_contract_instance_selected_member, 0 }, // No selection due to invalid enum
269 { C::get_contract_instance_member_write_offset, member_write_offset_3 },
270 { C::get_contract_instance_exists_tag, u1_tag },
271 { C::get_contract_instance_member_tag, ff_tag } },
272 });
273
274 check_relation<get_contract_instance>(trace);
275}
276
277// Integration-style tests using tracegen components
278TEST(GetContractInstanceConstrainingTest, IntegrationTracegenValid)
279{
280 // Test constants
281 const uint32_t execution_clk = 42;
282 const FF contract_address = 0x1234;
283 const uint32_t dst_offset = 100;
284 const uint8_t deployer_enum = static_cast<uint8_t>(ContractInstanceMember::DEPLOYER);
285 const uint16_t space_id = 1;
286 const FF nullifier_tree_root = 0x1234;
287 const FF public_data_tree_root = 0x5678;
288 const FF deployer_addr = 0x5678;
289 const FF class_id = 0x9ABC;
290 const FF init_hash = 0xDEF0;
291
292 // Use real tracegen to generate a valid trace
293 EventEmitter<GetContractInstanceEvent> emitter;
294
295 GetContractInstanceEvent event{
296 .execution_clk = execution_clk,
297 .contract_address = contract_address,
298 .dst_offset = dst_offset,
299 .member_enum = deployer_enum,
300 .space_id = space_id,
301 .nullifier_tree_root = nullifier_tree_root,
302 .public_data_tree_root = public_data_tree_root,
303 .instance_exists = true,
304 .retrieved_deployer_addr = deployer_addr,
305 .retrieved_class_id = class_id,
306 .retrieved_init_hash = init_hash,
307 };
308
309 emitter.emit(std::move(event));
310 auto events = emitter.dump_events();
311
312 TestTraceContainer trace;
313 GetContractInstanceTraceBuilder builder;
314 builder.process(events, trace);
315
316 // Add precomputed table entries
317 PrecomputedTraceBuilder precomputed_builder;
319
320 check_relation<get_contract_instance>(trace);
321}
322
323TEST(GetContractInstanceConstrainingTest, IntegrationTracegenInvalidEnum)
324{
325 // Test constants
326 const uint32_t execution_clk = 42;
327 const FF contract_address = 0x1234;
328 const uint32_t dst_offset = 100;
329 const uint8_t invalid_enum = 200;
330 const uint16_t space_id = 1;
331 const FF nullifier_tree_root = 0x1234;
332 const FF public_data_tree_root = 0x5678;
333 const FF deployer_addr = 0x5678;
334 const FF class_id = 0x9ABC;
335 const FF init_hash = 0xDEF0;
336
337 // Test with invalid member enum
338 EventEmitter<GetContractInstanceEvent> emitter;
339
340 GetContractInstanceEvent event{
341 .execution_clk = execution_clk,
342 .contract_address = contract_address,
343 .dst_offset = dst_offset,
344 .member_enum = invalid_enum,
345 .space_id = space_id,
346 .nullifier_tree_root = nullifier_tree_root,
347 .public_data_tree_root = public_data_tree_root,
348 .instance_exists = true,
349 .retrieved_deployer_addr = deployer_addr,
350 .retrieved_class_id = class_id,
351 .retrieved_init_hash = init_hash,
352 };
353
354 emitter.emit(std::move(event));
355 auto events = emitter.dump_events();
356
357 TestTraceContainer trace;
358 GetContractInstanceTraceBuilder builder;
359 builder.process(events, trace);
360
361 // Add precomputed table entries
362 PrecomputedTraceBuilder precomputed_builder;
364
365 check_relation<get_contract_instance>(trace);
366}
367
368TEST(GetContractInstanceConstrainingTest, IntegrationTracegenOutOfBounds)
369{
370 // Test constants
371 const uint32_t execution_clk = 42;
372 const FF contract_address = 0x1234;
373 const uint32_t dst_offset = AVM_HIGHEST_MEM_ADDRESS;
374 const uint8_t class_id_enum = static_cast<uint8_t>(ContractInstanceMember::CLASS_ID);
375 const uint16_t space_id = 1;
376 const FF nullifier_tree_root = 0x1234;
377 const FF public_data_tree_root = 0x5678;
378 const FF deployer_addr = 0x5678;
379 const FF class_id = 0x9ABC;
380 const FF init_hash = 0xDEF0;
381
382 // Test with out-of-bounds destination
383 EventEmitter<GetContractInstanceEvent> emitter;
384
385 GetContractInstanceEvent event{
386 .execution_clk = execution_clk,
387 .contract_address = contract_address,
388 .dst_offset = dst_offset,
389 .member_enum = class_id_enum,
390 .space_id = space_id,
391 .nullifier_tree_root = nullifier_tree_root,
392 .public_data_tree_root = public_data_tree_root,
393 .instance_exists = true,
394 .retrieved_deployer_addr = deployer_addr,
395 .retrieved_class_id = class_id,
396 .retrieved_init_hash = init_hash,
397 };
398
399 emitter.emit(std::move(event));
400 auto events = emitter.dump_events();
401
402 TestTraceContainer trace;
403 GetContractInstanceTraceBuilder builder;
404 builder.process(events, trace);
405
406 // Add precomputed table entries
407 PrecomputedTraceBuilder precomputed_builder;
409
410 check_relation<get_contract_instance>(trace);
411}
412
413// =====================================================================
414// Ghost Row Injection Vulnerability Tests
415// =====================================================================
416// These tests verify that ghost rows (sel=0) cannot fire permutations.
417// The fix: is_valid_member_enum * (1 - sel) = 0 ensures is_valid_member_enum
418// is forced to 0 when sel=0, preventing ghost rows from firing permutations.
419//
420// Test that the fix blocks ghost row injection attacks.
421// Attack pattern:
422// 1. Create legitimate memory WRITE events (destination side)
423// 2. Build memory trace from those events
424// 3. Inject ghost get_contract_instance row with sel=0 but is_valid_member_enum=1
425// 4. The fix should cause the relation check to fail
426TEST(GetContractInstanceConstrainingTest, NegativeGhostRowInjectionBlocked)
427{
428 TestTraceContainer trace;
429 MemoryTraceBuilder memory_trace_builder;
430 PrecomputedTraceBuilder precomputed_trace_builder;
431
432 // Attacker-controlled values
433 uint32_t malicious_clk = 42;
434 uint16_t malicious_space_id = 1;
435 MemoryAddress malicious_dst_offset = 0x100;
436 uint1_t malicious_instance_exists = 1;
437 MemoryTag exists_tag = MemoryTag::U1;
438
439 // Create legitimate memory events
441 {
442 .execution_clk = malicious_clk,
444 .addr = malicious_dst_offset,
445 .value = MemoryValue::from<uint1_t>(malicious_instance_exists),
446 .space_id = malicious_space_id,
447 },
448 };
449
450 // Build memory trace (destination side)
451 precomputed_trace_builder.process_sel_range_8(trace);
452 precomputed_trace_builder.process_sel_range_16(trace);
453 precomputed_trace_builder.process_misc(trace, 1 << 16);
454 precomputed_trace_builder.process_tag_parameters(trace);
455 memory_trace_builder.process(mem_events, trace);
456
457 // Find where the memory row was placed
458 uint32_t memory_row = 0;
459 for (uint32_t row = 0; row < trace.get_num_rows(); row++) {
460 if (trace.get(C::memory_sel, row) == 1) {
461 memory_row = row;
462 break;
463 }
464 }
465
466 // Inject ghost get_contract_instance row
467 // Ghost row: sel = 0, but is_valid_member_enum = 1 (attack attempt)
468 uint32_t ghost_row = 0;
469 trace.set(ghost_row,
470 std::vector<std::pair<Column, FF>>{
471 { C::precomputed_first_row, 1 },
472 { C::execution_clk, ghost_row },
473 { C::get_contract_instance_sel, 0 },
474 { C::get_contract_instance_is_valid_member_enum, 1 },
475 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
476 { C::get_contract_instance_exists_tag, static_cast<uint8_t>(exists_tag) },
477 { C::get_contract_instance_clk, malicious_clk },
478 { C::get_contract_instance_space_id, malicious_space_id },
479 { C::get_contract_instance_dst_offset, malicious_dst_offset },
480 { C::get_contract_instance_instance_exists, static_cast<uint64_t>(malicious_instance_exists) },
481 { C::get_contract_instance_sel_error, 0 },
482 { C::get_contract_instance_is_deployer, 0 },
483 { C::get_contract_instance_is_class_id, 0 },
484 { C::get_contract_instance_is_init_hash, 0 },
485 { C::get_contract_instance_selected_member, 0 },
486 { C::get_contract_instance_member_write_offset, malicious_dst_offset + 1 },
487 { C::get_contract_instance_member_tag, static_cast<uint8_t>(MemoryTag::FF) },
488 });
489
490 trace.set(C::memory_sel_get_contract_instance_exists_write, memory_row, 1);
491
492 // The fix: is_valid_writes_in_bounds * (1 - sel) = 0 should cause the relation check to fail
493 // (in conjunction with WRITES_OUT_OF_BOUNDS * is_valid_member_enum = 0)
494 EXPECT_THROW_WITH_MESSAGE(check_relation<get_contract_instance>(trace), "IS_VALID_WRITES_IN_BOUNDS_REQUIRES_SEL");
495}
496
497// M-1: Verifies tracegen sets member_write_offset = 0 when writes are out of bounds.
498// PIL constraint: member_write_offset = is_valid_writes_in_bounds * (dst_offset + 1)
499TEST(GetContractInstanceConstrainingTest, TracegenMemberWriteOffsetOutOfBounds)
500{
501 EventEmitter<GetContractInstanceEvent> emitter;
502 emitter.emit(GetContractInstanceEvent{
503 .execution_clk = 1,
504 .contract_address = 0x1234,
505 .dst_offset = AVM_HIGHEST_MEM_ADDRESS, // Boundary case: writes out of bounds
506 .member_enum = static_cast<uint8_t>(ContractInstanceMember::DEPLOYER),
507 .space_id = 1,
508 .nullifier_tree_root = 0x5678,
509 .public_data_tree_root = 0x9ABC,
510 .instance_exists = true,
511 .retrieved_deployer_addr = 0xDEAD,
512 .retrieved_class_id = 0xBEEF,
513 .retrieved_init_hash = 0xCAFE,
514 });
515
516 TestTraceContainer trace;
517 GetContractInstanceTraceBuilder().process(emitter.dump_events(), trace);
518 PrecomputedTraceBuilder().process_get_contract_instance_table(trace);
519
520 // Row 1 has the data (row 0 is skippable setup)
521 constexpr uint32_t data_row = 1;
522 EXPECT_EQ(trace.get(C::get_contract_instance_is_valid_writes_in_bounds, data_row), FF(0));
523 EXPECT_EQ(trace.get(C::get_contract_instance_member_write_offset, data_row), FF(0));
524 check_relation<get_contract_instance>(trace);
525
526 // Negative: incorrect value fails the constraint
527 trace.set(C::get_contract_instance_member_write_offset, data_row, FF(AVM_HIGHEST_MEM_ADDRESS) + FF(1));
529 check_relation<get_contract_instance>(trace, get_contract_instance::SR_MEMBER_WRITE_OFFSET),
530 "MEMBER_WRITE_OFFSET");
531}
532
533} // namespace
534} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
#define AVM_HIGHEST_MEM_ADDRESS
static constexpr size_t SR_ERROR_AGGREGATION
static constexpr size_t SR_SELECTED_MEMBER
static constexpr size_t SR_MEMBER_WRITE_OFFSET
static constexpr size_t SR_WRITE_OUT_OF_BOUNDS_CHECK
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
Process the ALU events and populate the ALU relevant columns in the trace.
void process_get_contract_instance_table(TraceContainer &trace)
Populate the GETCONTRACTINSTANCE lookup table.
const FF & get(Column col, uint32_t row) const
void set(Column col, uint32_t row, const FF &value)
PrecomputedTraceBuilder precomputed_builder
Definition alu.test.cpp:120
AluTraceBuilder builder
Definition alu.test.cpp:124
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
AvmFlavorSettings::FF FF
Definition field.hpp:10
uint32_t MemoryAddress
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
simulation::PublicDataTreeReadWriteEvent event
constexpr field invert() const noexcept