1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
26using simulation::EventEmitter;
27using simulation::GetContractInstanceEvent;
28using tracegen::GetContractInstanceTraceBuilder;
29using tracegen::MemoryTraceBuilder;
30using tracegen::PrecomputedTraceBuilder;
31using tracegen::TestTraceContainer;
36TEST(GetContractInstanceConstrainingTest, EmptyRow)
41TEST(GetContractInstanceConstrainingTest, WriteInBoundsCheck)
44 const FF dst_offset =
FF(100);
45 const FF dst_offset_diff_max =
FF(AVM_HIGHEST_MEM_ADDRESS) - dst_offset;
46 const FF dst_offset_diff_max_inv = dst_offset_diff_max.
invert();
47 const FF wrong_inv_value =
FF(42);
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 } },
60 trace.
set(C::get_contract_instance_dst_offset_diff_max_inv, 1, wrong_inv_value);
65 trace.
set(C::get_contract_instance_dst_offset_diff_max_inv, 1, dst_offset_diff_max_inv);
68 trace.
set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 0);
73 trace.
set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 1);
76TEST(GetContractInstanceConstrainingTest, WriteOutOfBoundsCheck)
79 const FF dst_offset =
FF(AVM_HIGHEST_MEM_ADDRESS);
80 const FF dst_offset_diff_max_inv =
FF(0);
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 } },
93 trace.
set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 1);
98 trace.
set(C::get_contract_instance_is_valid_writes_in_bounds, 1, 0);
101TEST(GetContractInstanceConstrainingTest, ErrorAggregationConstraint)
104 TestTraceContainer
trace({
105 { { C::precomputed_first_row, 1 } },
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 } },
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);
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);
123 trace.
set(C::get_contract_instance_is_valid_member_enum, 1, 0);
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);
129 trace.
set(C::get_contract_instance_is_valid_member_enum, 1, 0);
133 trace.
set(C::get_contract_instance_sel_error, 1, 0);
139TEST(GetContractInstanceConstrainingTest, SelectedMemberConstraint)
142 const FF deployer_addr = 0x1234;
143 const FF class_id = 0x5678;
144 const FF init_hash = 0x9ABC;
145 const FF immutables_hash = 0xCAFE;
146 const FF wrong_value = 0x1111;
149 TestTraceContainer
trace({
150 { { C::precomputed_first_row, 1 } },
152 { { C::get_contract_instance_sel, 1 },
153 { C::get_contract_instance_selected_member, deployer_addr },
154 { C::get_contract_instance_is_deployer, 1 },
155 { C::get_contract_instance_is_class_id, 0 },
156 { C::get_contract_instance_is_init_hash, 0 },
157 { C::get_contract_instance_is_immutables_hash, 0 },
158 { C::get_contract_instance_retrieved_deployer_addr, deployer_addr },
159 { C::get_contract_instance_retrieved_class_id, class_id },
160 { C::get_contract_instance_retrieved_init_hash, init_hash },
161 { C::get_contract_instance_retrieved_immutables_hash, immutables_hash } },
167 trace.
set(C::get_contract_instance_selected_member, 1, class_id);
168 trace.
set(C::get_contract_instance_is_deployer, 1, 0);
169 trace.
set(C::get_contract_instance_is_class_id, 1, 1);
173 trace.
set(C::get_contract_instance_selected_member, 1, init_hash);
174 trace.
set(C::get_contract_instance_is_class_id, 1, 0);
175 trace.
set(C::get_contract_instance_is_init_hash, 1, 1);
179 trace.
set(C::get_contract_instance_selected_member, 1, immutables_hash);
180 trace.
set(C::get_contract_instance_is_init_hash, 1, 0);
181 trace.
set(C::get_contract_instance_is_immutables_hash, 1, 1);
185 trace.
set(C::get_contract_instance_selected_member, 1, wrong_value);
190TEST(GetContractInstanceConstrainingTest, ComplexMultiRowSequence)
193 const uint32_t dst_offset_1 = 100;
194 const uint32_t dst_offset_2 = 200;
195 const uint32_t dst_offset_3 = 300;
196 const uint8_t deployer_enum = 0;
197 const uint8_t class_id_enum = 1;
198 const uint8_t invalid_enum = 5;
199 const FF deployer_addr_1 = 0x1234;
200 const FF class_id_1 = 0x5678;
201 const FF init_hash_1 = 0x9ABC;
202 const FF deployer_addr_2 = 0x1111;
203 const FF class_id_2 = 0x2222;
204 const FF init_hash_2 = 0x3333;
205 const FF deployer_addr_3 = 0x4444;
206 const FF class_id_3 = 0x5555;
207 const FF init_hash_3 = 0x6666;
208 const uint32_t member_write_offset_1 = 101;
209 const uint32_t member_write_offset_2 = 201;
210 const uint32_t member_write_offset_3 = 301;
211 const uint8_t u1_tag =
static_cast<uint8_t
>(
ValueTag::U1);
212 const uint8_t ff_tag =
static_cast<uint8_t
>(
ValueTag::FF);
215 TestTraceContainer
trace({
216 { { C::precomputed_first_row, 1 } },
218 { { C::get_contract_instance_sel, 0 } },
220 { { C::get_contract_instance_sel, 1 },
221 { C::get_contract_instance_dst_offset, dst_offset_1 },
222 { C::get_contract_instance_member_enum, deployer_enum },
223 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
224 { C::get_contract_instance_dst_offset_diff_max_inv,
FF(AVM_HIGHEST_MEM_ADDRESS - dst_offset_1).invert() },
225 { C::get_contract_instance_sel_error, 0 },
226 { C::get_contract_instance_is_valid_member_enum, 1 },
227 { C::get_contract_instance_is_deployer, 1 },
228 { C::get_contract_instance_is_class_id, 0 },
229 { C::get_contract_instance_is_init_hash, 0 },
230 { C::get_contract_instance_retrieved_deployer_addr, deployer_addr_1 },
231 { C::get_contract_instance_retrieved_class_id, class_id_1 },
232 { C::get_contract_instance_retrieved_init_hash, init_hash_1 },
233 { C::get_contract_instance_selected_member, deployer_addr_1 },
234 { C::get_contract_instance_member_write_offset, member_write_offset_1 },
235 { C::get_contract_instance_exists_tag, u1_tag },
236 { C::get_contract_instance_member_tag, ff_tag } },
238 { { C::get_contract_instance_sel, 1 },
239 { C::get_contract_instance_dst_offset, dst_offset_2 },
240 { C::get_contract_instance_member_enum, class_id_enum },
241 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
242 { C::get_contract_instance_dst_offset_diff_max_inv,
FF(AVM_HIGHEST_MEM_ADDRESS - dst_offset_2).
invert() },
243 { C::get_contract_instance_sel_error, 0 },
244 { C::get_contract_instance_is_valid_member_enum, 1 },
245 { C::get_contract_instance_is_deployer, 0 },
246 { C::get_contract_instance_is_class_id, 1 },
247 { C::get_contract_instance_is_init_hash, 0 },
248 { C::get_contract_instance_retrieved_deployer_addr, deployer_addr_2 },
249 { C::get_contract_instance_retrieved_class_id, class_id_2 },
250 { C::get_contract_instance_retrieved_init_hash, init_hash_2 },
251 { C::get_contract_instance_selected_member, class_id_2 },
252 { C::get_contract_instance_member_write_offset, member_write_offset_2 },
253 { C::get_contract_instance_exists_tag, u1_tag },
254 { C::get_contract_instance_member_tag, ff_tag } },
256 { { C::get_contract_instance_sel, 1 },
257 { C::get_contract_instance_dst_offset, dst_offset_3 },
258 { C::get_contract_instance_member_enum, invalid_enum },
259 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
260 { C::get_contract_instance_dst_offset_diff_max_inv,
FF(AVM_HIGHEST_MEM_ADDRESS - dst_offset_3).
invert() },
261 { C::get_contract_instance_sel_error, 1 },
262 { C::get_contract_instance_is_valid_member_enum, 0 },
263 { C::get_contract_instance_is_deployer, 0 },
264 { C::get_contract_instance_is_class_id, 0 },
265 { C::get_contract_instance_is_init_hash, 0 },
266 { C::get_contract_instance_retrieved_deployer_addr, deployer_addr_3 },
267 { C::get_contract_instance_retrieved_class_id, class_id_3 },
268 { C::get_contract_instance_retrieved_init_hash, init_hash_3 },
269 { C::get_contract_instance_selected_member, 0 },
270 { C::get_contract_instance_member_write_offset, member_write_offset_3 },
271 { C::get_contract_instance_exists_tag, u1_tag },
272 { C::get_contract_instance_member_tag, ff_tag } },
275 check_relation<get_contract_instance>(trace);
279TEST(GetContractInstanceConstrainingTest, IntegrationTracegenValid)
282 const uint32_t execution_clk = 42;
283 const FF contract_address = 0x1234;
284 const uint32_t dst_offset = 100;
286 const uint16_t space_id = 1;
287 const FF nullifier_tree_root = 0x1234;
288 const FF public_data_tree_root = 0x5678;
289 const FF deployer_addr = 0x5678;
290 const FF class_id = 0x9ABC;
291 const FF init_hash = 0xDEF0;
294 EventEmitter<GetContractInstanceEvent> emitter;
296 GetContractInstanceEvent
event{
297 .execution_clk = execution_clk,
298 .contract_address = contract_address,
299 .dst_offset = dst_offset,
300 .member_enum = deployer_enum,
301 .space_id = space_id,
302 .nullifier_tree_root = nullifier_tree_root,
303 .public_data_tree_root = public_data_tree_root,
304 .instance_exists =
true,
305 .retrieved_deployer_addr = deployer_addr,
306 .retrieved_class_id = class_id,
307 .retrieved_init_hash = init_hash,
311 auto events = emitter.dump_events();
313 TestTraceContainer
trace;
314 GetContractInstanceTraceBuilder
builder;
321 check_relation<get_contract_instance>(trace);
324TEST(GetContractInstanceConstrainingTest, IntegrationTracegenInvalidEnum)
327 const uint32_t execution_clk = 42;
328 const FF contract_address = 0x1234;
329 const uint32_t dst_offset = 100;
330 const uint8_t invalid_enum = 200;
331 const uint16_t space_id = 1;
332 const FF nullifier_tree_root = 0x1234;
333 const FF public_data_tree_root = 0x5678;
334 const FF deployer_addr = 0x5678;
335 const FF class_id = 0x9ABC;
336 const FF init_hash = 0xDEF0;
339 EventEmitter<GetContractInstanceEvent> emitter;
341 GetContractInstanceEvent
event{
342 .execution_clk = execution_clk,
343 .contract_address = contract_address,
344 .dst_offset = dst_offset,
345 .member_enum = invalid_enum,
346 .space_id = space_id,
347 .nullifier_tree_root = nullifier_tree_root,
348 .public_data_tree_root = public_data_tree_root,
349 .instance_exists =
true,
350 .retrieved_deployer_addr = deployer_addr,
351 .retrieved_class_id = class_id,
352 .retrieved_init_hash = init_hash,
356 auto events = emitter.dump_events();
358 TestTraceContainer
trace;
359 GetContractInstanceTraceBuilder
builder;
366 check_relation<get_contract_instance>(trace);
369TEST(GetContractInstanceConstrainingTest, IntegrationTracegenOutOfBounds)
372 const uint32_t execution_clk = 42;
373 const FF contract_address = 0x1234;
374 const uint32_t dst_offset = AVM_HIGHEST_MEM_ADDRESS;
376 const uint16_t space_id = 1;
377 const FF nullifier_tree_root = 0x1234;
378 const FF public_data_tree_root = 0x5678;
379 const FF deployer_addr = 0x5678;
380 const FF class_id = 0x9ABC;
381 const FF init_hash = 0xDEF0;
384 EventEmitter<GetContractInstanceEvent> emitter;
386 GetContractInstanceEvent
event{
387 .execution_clk = execution_clk,
388 .contract_address = contract_address,
389 .dst_offset = dst_offset,
390 .member_enum = class_id_enum,
391 .space_id = space_id,
392 .nullifier_tree_root = nullifier_tree_root,
393 .public_data_tree_root = public_data_tree_root,
394 .instance_exists =
true,
395 .retrieved_deployer_addr = deployer_addr,
396 .retrieved_class_id = class_id,
397 .retrieved_init_hash = init_hash,
401 auto events = emitter.dump_events();
403 TestTraceContainer
trace;
404 GetContractInstanceTraceBuilder
builder;
411 check_relation<get_contract_instance>(trace);
427TEST(GetContractInstanceConstrainingTest, NegativeGhostRowInjectionBlocked)
429 TestTraceContainer
trace;
430 MemoryTraceBuilder memory_trace_builder;
431 PrecomputedTraceBuilder precomputed_trace_builder;
434 uint32_t malicious_clk = 42;
435 uint16_t malicious_space_id = 1;
437 uint1_t malicious_instance_exists = 1;
443 .execution_clk = malicious_clk,
445 .addr = malicious_dst_offset,
446 .value = MemoryValue::from<uint1_t>(malicious_instance_exists),
447 .space_id = malicious_space_id,
452 precomputed_trace_builder.process_sel_range_8(trace);
453 precomputed_trace_builder.process_sel_range_16(trace);
454 precomputed_trace_builder.process_misc(trace, 1 << 16);
455 precomputed_trace_builder.process_tag_parameters(trace);
456 memory_trace_builder.process(mem_events, trace);
459 uint32_t memory_row = 0;
461 if (
trace.
get(C::memory_sel, row) == 1) {
469 uint32_t ghost_row = 0;
472 { C::precomputed_first_row, 1 },
473 { C::execution_clk, ghost_row },
474 { C::get_contract_instance_sel, 0 },
475 { C::get_contract_instance_is_valid_member_enum, 1 },
476 { C::get_contract_instance_is_valid_writes_in_bounds, 1 },
477 { C::get_contract_instance_exists_tag,
static_cast<uint8_t
>(exists_tag) },
478 { C::get_contract_instance_clk, malicious_clk },
479 { C::get_contract_instance_space_id, malicious_space_id },
480 { C::get_contract_instance_dst_offset, malicious_dst_offset },
481 { C::get_contract_instance_instance_exists,
static_cast<uint64_t
>(malicious_instance_exists) },
482 { C::get_contract_instance_sel_error, 0 },
483 { C::get_contract_instance_is_deployer, 0 },
484 { C::get_contract_instance_is_class_id, 0 },
485 { C::get_contract_instance_is_init_hash, 0 },
486 { C::get_contract_instance_selected_member, 0 },
487 { C::get_contract_instance_member_write_offset, malicious_dst_offset + 1 },
488 { C::get_contract_instance_member_tag,
static_cast<uint8_t
>(
MemoryTag::FF) },
491 trace.
set(C::memory_sel_get_contract_instance_exists_write, memory_row, 1);
496 check_relation<get_contract_instance>(trace),
502TEST(GetContractInstanceConstrainingTest, TracegenMemberWriteOffsetOutOfBounds)
504 EventEmitter<GetContractInstanceEvent> emitter;
505 emitter.emit(GetContractInstanceEvent{
507 .contract_address = 0x1234,
508 .dst_offset = AVM_HIGHEST_MEM_ADDRESS,
511 .nullifier_tree_root = 0x5678,
512 .public_data_tree_root = 0x9ABC,
513 .instance_exists =
true,
514 .retrieved_deployer_addr = 0xDEAD,
515 .retrieved_class_id = 0xBEEF,
516 .retrieved_init_hash = 0xCAFE,
519 TestTraceContainer
trace;
520 GetContractInstanceTraceBuilder().process(emitter.dump_events(), trace);
521 PrecomputedTraceBuilder().process_get_contract_instance_table(trace);
524 constexpr uint32_t data_row = 1;
525 EXPECT_EQ(
trace.
get(C::get_contract_instance_is_valid_writes_in_bounds, data_row),
FF(0));
526 EXPECT_EQ(
trace.
get(C::get_contract_instance_member_write_offset, data_row),
FF(0));
527 check_relation<get_contract_instance>(trace);
530 trace.
set(C::get_contract_instance_member_write_offset, data_row,
FF(AVM_HIGHEST_MEM_ADDRESS) +
FF(1));
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
static constexpr size_t SR_ERROR_AGGREGATION
static constexpr size_t SR_IS_VALID_WRITES_IN_BOUNDS_REQUIRES_SEL
static constexpr size_t SR_SELECTED_MEMBER
static std::string get_subrelation_label(size_t index)
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
uint32_t get_num_rows() const
void set(Column col, uint32_t row, const FF &value, bool use_atomic_limbs=false)
PrecomputedTraceBuilder precomputed_builder
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
TestTraceContainer empty_trace()
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
simulation::PublicDataTreeReadWriteEvent event
constexpr field invert() const noexcept