Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
contract_instance_retrieval.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 <memory>
6#include <vector>
7
24
25namespace bb::avm2::constraining {
26namespace {
27
28using simulation::ContractInstanceRetrievalEvent;
29using simulation::EventEmitter;
30using testing::PublicInputsBuilder;
31using tracegen::ContractInstanceRetrievalTraceBuilder;
32using tracegen::PrecomputedTraceBuilder;
33using tracegen::PublicInputsTraceBuilder;
34using tracegen::TestTraceContainer;
36using C = Column;
37using contract_instance_retrieval = bb::avm2::contract_instance_retrieval<FF>;
38
39// Helper to create a test contract instance
40ContractInstance create_test_contract_instance(uint32_t salt_value = 123)
41{
42 return ContractInstance{
43 .salt = FF(salt_value),
44 .deployer = FF(0x123456789ULL),
45 .current_contract_class_id = FF(0xdeadbeefULL),
46 .original_contract_class_id = FF(0xcafebabeULL),
47 .initialization_hash = FF(0x11111111ULL),
48 .public_keys =
49 PublicKeys{
50 .nullifier_key = { FF(0x100), FF(0x101) },
51 .incoming_viewing_key = { FF(0x200), FF(0x201) },
52 .outgoing_viewing_key = { FF(0x300), FF(0x301) },
53 .tagging_key = { FF(0x400), FF(0x401) },
54 },
55 };
56}
57
58TEST(ContractInstanceRetrievalConstrainingTest, EmptyRow)
59{
60 check_relation<contract_instance_retrieval>(testing::empty_trace());
61}
62
63TEST(ContractInstanceRetrievalConstrainingTest, CompleteValidTrace)
64{
65 // Test constants
66 const auto contract_address = FF(0x1234567890abcdefULL);
67 const auto nullifier_tree_root = FF(0xaabbccdd);
68 const auto public_data_tree_root = FF(0xeeff1122);
69 const auto exists = true;
70 const auto salt = FF(0x555);
71 const auto deployer_addr = FF(0x123456789ULL);
72 const auto current_class_id = FF(0xdeadbeefULL);
73 const auto original_class_id = FF(0xcafebabeULL);
74 const auto init_hash = FF(0x11111111ULL);
75 const auto nullifier_key_x = FF(0x100);
76 const auto nullifier_key_y = FF(0x101);
77 const auto incoming_viewing_key_x = FF(0x200);
78 const auto incoming_viewing_key_y = FF(0x201);
79 const auto outgoing_viewing_key_x = FF(0x300);
80 const auto outgoing_viewing_key_y = FF(0x301);
81 const auto tagging_key_x = FF(0x400);
82 const auto tagging_key_y = FF(0x401);
83
84 // Test complete valid trace with all constraints
85 TestTraceContainer trace({
86 { { C::precomputed_first_row, 1 } },
87 { { C::contract_instance_retrieval_sel, 1 },
88 { C::contract_instance_retrieval_address, contract_address },
89 { C::contract_instance_retrieval_exists, exists ? 1 : 0 },
90 { C::contract_instance_retrieval_salt, salt },
91 { C::contract_instance_retrieval_deployer_addr, deployer_addr },
92 { C::contract_instance_retrieval_current_class_id, current_class_id },
93 { C::contract_instance_retrieval_original_class_id, original_class_id },
94 { C::contract_instance_retrieval_init_hash, init_hash },
95 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
96 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
97 { C::contract_instance_retrieval_nullifier_key_x, nullifier_key_x },
98 { C::contract_instance_retrieval_nullifier_key_y, nullifier_key_y },
99 { C::contract_instance_retrieval_incoming_viewing_key_x, incoming_viewing_key_x },
100 { C::contract_instance_retrieval_incoming_viewing_key_y, incoming_viewing_key_y },
101 { C::contract_instance_retrieval_outgoing_viewing_key_x, outgoing_viewing_key_x },
102 { C::contract_instance_retrieval_outgoing_viewing_key_y, outgoing_viewing_key_y },
103 { C::contract_instance_retrieval_tagging_key_x, tagging_key_x },
104 { C::contract_instance_retrieval_tagging_key_y, tagging_key_y },
105 { C::contract_instance_retrieval_deployer_protocol_contract_address,
107 // Protocol Contract conditionals
108 { C::contract_instance_retrieval_address_sub_one, contract_address - 1 },
109 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
110 { C::contract_instance_retrieval_derived_address, contract_address },
111 { C::contract_instance_retrieval_is_protocol_contract, 0 },
112 { C::contract_instance_retrieval_should_check_nullifier, 1 },
113 { C::contract_instance_retrieval_should_check_for_update, 1 } },
114 });
115
116 check_relation<contract_instance_retrieval>(trace);
117}
118
119TEST(ContractInstanceRetrievalConstrainingTest, MultipleInstancesTrace)
120{
121 // Test constants
122 const auto num_instances = 3;
123 const auto base_address = 0x1000;
124 const auto base_nullifier_tree_root = 0x2000;
125 const auto base_public_data_tree_root = 0x3000;
126 const auto base_salt = 100;
127
128 // Test multiple contract instances in sequence
130
131 // First row
132 trace_data.push_back({ { C::precomputed_first_row, 1 } });
133
134 // Create multiple instance rows
135 for (uint32_t i = 0; i < num_instances; i++) {
136 auto contract_instance = create_test_contract_instance(base_salt + i);
137
138 trace_data.push_back({
139 { C::contract_instance_retrieval_sel, 1 },
140 { C::contract_instance_retrieval_address, FF(base_address + i) },
141 { C::contract_instance_retrieval_exists, 1 },
142 { C::contract_instance_retrieval_salt, contract_instance.salt },
143 { C::contract_instance_retrieval_deployer_addr, contract_instance.deployer },
144 { C::contract_instance_retrieval_current_class_id, contract_instance.current_contract_class_id },
145 { C::contract_instance_retrieval_original_class_id, contract_instance.original_contract_class_id },
146 { C::contract_instance_retrieval_init_hash, contract_instance.initialization_hash },
147 { C::contract_instance_retrieval_public_data_tree_root, FF(base_public_data_tree_root + i) },
148 { C::contract_instance_retrieval_nullifier_tree_root, FF(base_nullifier_tree_root + i) },
149 { C::contract_instance_retrieval_nullifier_key_x, contract_instance.public_keys.nullifier_key.x },
150 { C::contract_instance_retrieval_nullifier_key_y, contract_instance.public_keys.nullifier_key.y },
151 { C::contract_instance_retrieval_incoming_viewing_key_x,
152 contract_instance.public_keys.incoming_viewing_key.x },
153 { C::contract_instance_retrieval_incoming_viewing_key_y,
154 contract_instance.public_keys.incoming_viewing_key.y },
155 { C::contract_instance_retrieval_outgoing_viewing_key_x,
156 contract_instance.public_keys.outgoing_viewing_key.x },
157 { C::contract_instance_retrieval_outgoing_viewing_key_y,
158 contract_instance.public_keys.outgoing_viewing_key.y },
159 { C::contract_instance_retrieval_tagging_key_x, contract_instance.public_keys.tagging_key.x },
160 { C::contract_instance_retrieval_tagging_key_y, contract_instance.public_keys.tagging_key.y },
161 { C::contract_instance_retrieval_deployer_protocol_contract_address,
163 // Protocol Contract conditionals
164 { C::contract_instance_retrieval_address_sub_one, (base_address + i) - 1 },
165 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
166 { C::contract_instance_retrieval_derived_address, base_address + i },
167 { C::contract_instance_retrieval_is_protocol_contract, 0 },
168 { C::contract_instance_retrieval_should_check_nullifier, 1 },
169 { C::contract_instance_retrieval_should_check_for_update, 1 },
170 });
171 }
172
173 TestTraceContainer trace(trace_data);
174 check_relation<contract_instance_retrieval>(trace);
175}
176
177TEST(ContractInstanceRetrievalConstrainingTest, NonExistentInstanceTrace)
178{
179 // Test constants
180 const auto contract_address = FF(0x99999999);
181 const auto nullifier_tree_root = FF(0xffffff);
182 const auto public_data_tree_root = FF(0xeeeeee);
183 const auto exists = false;
184
185 // Test trace for non-existent contract instance
186 TestTraceContainer trace({
187 { { C::precomputed_first_row, 1 } },
188 { { C::contract_instance_retrieval_sel, 1 },
189 { C::contract_instance_retrieval_address, contract_address },
190 { C::contract_instance_retrieval_exists, exists ? 1 : 0 },
191 { C::contract_instance_retrieval_salt, 0 },
192 { C::contract_instance_retrieval_deployer_addr, 0 },
193 { C::contract_instance_retrieval_current_class_id, 0 },
194 { C::contract_instance_retrieval_original_class_id, 0 },
195 { C::contract_instance_retrieval_init_hash, 0 },
196 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
197 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
198 { C::contract_instance_retrieval_deployer_protocol_contract_address,
200 // Protocol Contract conditionals
201 { C::contract_instance_retrieval_address_sub_one, contract_address - 1 },
202 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
203 { C::contract_instance_retrieval_derived_address, contract_address },
204 { C::contract_instance_retrieval_is_protocol_contract, 0 },
205 { C::contract_instance_retrieval_should_check_nullifier, 1 },
206 { C::contract_instance_retrieval_should_check_for_update, 0 /*since exists = false*/ } },
207 });
208
209 check_relation<contract_instance_retrieval>(trace);
210
211 // mutate instance members to be nonzero and confirm that relation fails
212 // mutate deployer_addr
213 trace.set(C::contract_instance_retrieval_deployer_addr, 1, 1);
214 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
215 "INSTANCE_MEMBER_DEPLOYER_IS_ZERO_IF_DNE");
216 // reset
217 trace.set(C::contract_instance_retrieval_deployer_addr, 1, 0);
218 // mutate current_class_id
219 trace.set(C::contract_instance_retrieval_current_class_id, 1, 1);
220 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
221 "INSTANCE_MEMBER_CLASS_ID_IS_ZERO_IF_DNE");
222 // reset
223 trace.set(C::contract_instance_retrieval_current_class_id, 1, 0);
224 // mutate original_class_id
225 trace.set(C::contract_instance_retrieval_original_class_id, 1, 1);
226 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
227 "INSTANCE_MEMBER_ORIGINAL_CLASS_ID_IS_ZERO_IF_DNE");
228 // reset
229 trace.set(C::contract_instance_retrieval_original_class_id, 1, 0);
230 // mutate init_hash
231 trace.set(C::contract_instance_retrieval_init_hash, 1, 1);
232 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
233 "INSTANCE_MEMBER_INIT_HASH_IS_ZERO_IF_DNE");
234 // reset
235 trace.set(C::contract_instance_retrieval_init_hash, 1, 0);
236}
237
238TEST(ContractInstanceRetrievalConstrainingTest, MaximumFieldValuesTrace)
239{
240 // Test constants
241 const auto max_field = FF(-1); // Maximum field value
242
243 // Test trace with maximum field values
244 TestTraceContainer trace({
245 { { C::precomputed_first_row, 1 } },
246 { { C::contract_instance_retrieval_sel, 1 },
247 { C::contract_instance_retrieval_address, max_field },
248 { C::contract_instance_retrieval_exists, 1 },
249 { C::contract_instance_retrieval_salt, max_field },
250 { C::contract_instance_retrieval_deployer_addr, max_field },
251 { C::contract_instance_retrieval_current_class_id, max_field },
252 { C::contract_instance_retrieval_original_class_id, max_field },
253 { C::contract_instance_retrieval_init_hash, max_field },
254 { C::contract_instance_retrieval_public_data_tree_root, max_field },
255 { C::contract_instance_retrieval_nullifier_tree_root, max_field },
256 { C::contract_instance_retrieval_nullifier_key_x, max_field },
257 { C::contract_instance_retrieval_nullifier_key_y, max_field },
258 { C::contract_instance_retrieval_incoming_viewing_key_x, max_field },
259 { C::contract_instance_retrieval_incoming_viewing_key_y, max_field },
260 { C::contract_instance_retrieval_outgoing_viewing_key_x, max_field },
261 { C::contract_instance_retrieval_outgoing_viewing_key_y, max_field },
262 { C::contract_instance_retrieval_tagging_key_x, max_field },
263 { C::contract_instance_retrieval_tagging_key_y, max_field },
264 { C::contract_instance_retrieval_deployer_protocol_contract_address,
266 // Protocol Contract conditionals
267 { C::contract_instance_retrieval_address_sub_one, max_field - 1 },
268 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
269 { C::contract_instance_retrieval_derived_address, max_field },
270 { C::contract_instance_retrieval_is_protocol_contract, 0 },
271 { C::contract_instance_retrieval_should_check_nullifier, 1 },
272 { C::contract_instance_retrieval_should_check_for_update, 1 } },
273 });
274
275 check_relation<contract_instance_retrieval>(trace);
276}
277
278TEST(ContractInstanceRetrievalConstrainingTest, ProtocolContractInstanceExists)
279{
280 // Test constants
282 const AztecAddress derived_address = FF(0xabcdef1234567890ULL);
283 const auto nullifier_tree_root = FF(0xbadc0ffeeULL);
284 const auto public_data_tree_root = FF(0xfacefeedUL);
285 ProtocolContracts protocol_contracts = {};
286 uint32_t protocol_contract_index = static_cast<uint32_t>(contract_address - 1);
287 protocol_contracts.derived_addresses[protocol_contract_index] = derived_address;
288
289 auto public_inputs = PublicInputsBuilder().set_protocol_contracts(protocol_contracts).build();
290
291 // Test complete valid trace with all constraints
292 TestTraceContainer trace({
293 {
294 { C::precomputed_first_row, 1 },
295 // Field Greater-Than Trace for Protocol Contract Address Check
296 { C::ff_gt_sel, 1 },
297 { C::ff_gt_sel_gt, 1 },
298 { C::ff_gt_a, MAX_PROTOCOL_CONTRACTS },
299 { C::ff_gt_b, contract_address - FF(1) },
300 { C::ff_gt_result, 1 },
301 },
302 {
303 // Contract Retrieval Instance Trace
304 { C::contract_instance_retrieval_sel, 1 },
305 { C::contract_instance_retrieval_address, contract_address },
306 { C::contract_instance_retrieval_exists, 1 },
307 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
308 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
309 { C::contract_instance_retrieval_deployer_protocol_contract_address,
311 // Protocol Contract conditionals
312 { C::contract_instance_retrieval_derived_address_pi_index,
313 AVM_PUBLIC_INPUTS_PROTOCOL_CONTRACTS_ROW_IDX + protocol_contract_index },
314 { C::contract_instance_retrieval_protocol_contract_derived_address_inv, derived_address.invert() },
315 { C::contract_instance_retrieval_address_sub_one, contract_address - FF(1) },
316 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
317 { C::contract_instance_retrieval_derived_address, derived_address },
318 { C::contract_instance_retrieval_is_protocol_contract, 1 },
319 { C::contract_instance_retrieval_should_check_nullifier, 0 },
320 { C::contract_instance_retrieval_should_check_for_update, 0 },
321 },
322 });
323
324 PublicInputsTraceBuilder public_inputs_builder;
325 public_inputs_builder.process_public_inputs(trace, public_inputs);
326 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
327
328 tracegen::PrecomputedTraceBuilder precomputed_builder;
330
331 check_relation<contract_instance_retrieval>(trace);
332 check_interaction<ContractInstanceRetrievalTraceBuilder,
335}
336
337TEST(ContractInstanceRetrievalConstrainingTest, ProtocolContractInstanceNotExists)
338{
339 // Test constants
341 const AztecAddress derived_address = FF(0);
342 const auto nullifier_tree_root = FF(0xbadc0ffeeULL);
343 const auto public_data_tree_root = FF(0xfacefeedUL);
344 uint32_t protocol_contract_index = static_cast<uint32_t>(contract_address - 1);
345 // Default protocol contracts: empty
346 auto public_inputs = PublicInputsBuilder().build();
347
348 // Test complete valid trace with all constraints
349 TestTraceContainer trace({
350 {
351 { C::precomputed_first_row, 1 },
352 // Field Greater-Than Trace for Protocol Contract Address Check
353 { C::ff_gt_sel, 1 },
354 { C::ff_gt_sel_gt, 1 },
355 { C::ff_gt_a, MAX_PROTOCOL_CONTRACTS },
356 { C::ff_gt_b, contract_address - FF(1) },
357 { C::ff_gt_result, 1 },
358 },
359 {
360 // Contract Retrieval Instance Trace
361 { C::contract_instance_retrieval_sel, 1 },
362 { C::contract_instance_retrieval_address, contract_address },
363 { C::contract_instance_retrieval_exists, 0 },
364 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
365 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
366 { C::contract_instance_retrieval_deployer_protocol_contract_address,
368 // Protocol Contract conditionals
369 { C::contract_instance_retrieval_derived_address_pi_index,
370 AVM_PUBLIC_INPUTS_PROTOCOL_CONTRACTS_ROW_IDX + protocol_contract_index },
371 { C::contract_instance_retrieval_protocol_contract_derived_address_inv, 0 },
372 { C::contract_instance_retrieval_address_sub_one, contract_address - FF(1) },
373 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
374 { C::contract_instance_retrieval_derived_address, derived_address },
375 { C::contract_instance_retrieval_is_protocol_contract, 1 },
376 { C::contract_instance_retrieval_should_check_nullifier, 0 },
377 { C::contract_instance_retrieval_should_check_for_update, 0 },
378 },
379 });
380
381 PublicInputsTraceBuilder public_inputs_builder;
382 public_inputs_builder.process_public_inputs(trace, public_inputs);
383 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
384
385 tracegen::PrecomputedTraceBuilder precomputed_builder;
387
388 check_relation<contract_instance_retrieval>(trace);
389 check_interaction<ContractInstanceRetrievalTraceBuilder,
392}
393
394// Integration-style tests using tracegen components
395TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenValidInstance)
396{
397 // Test constants
398 const auto contract_address = FF(0x1234567890abcdefULL);
399 const auto timestamp = 12345;
400 const auto nullifier_tree_root = FF(0xaabbccdd);
401 const auto public_data_tree_root = FF(0xeeff1122);
402 const auto deployment_nullifier = FF(0x7777);
403
404 // Use real tracegen to generate a valid trace
405 EventEmitter<ContractInstanceRetrievalEvent> emitter;
406 auto contract_instance = create_test_contract_instance();
407
408 ContractInstanceRetrievalEvent event = { .address = contract_address,
409 .contract_instance = contract_instance,
410 .nullifier_tree_root = nullifier_tree_root,
411 .public_data_tree_root = public_data_tree_root,
412 .deployment_nullifier = deployment_nullifier,
413 .exists = true,
414 .is_protocol_contract = false };
415
416 emitter.emit(std::move(event));
417 auto events = emitter.dump_events();
418
419 TestTraceContainer trace;
420 ContractInstanceRetrievalTraceBuilder builder;
421 builder.process(events, trace);
422
423 // Add precomputed table entries
424 PrecomputedTraceBuilder precomputed_builder;
428
429 // Manually populate destination tables for lookup interactions
430 auto contract_instance_data = create_test_contract_instance();
431
432 trace.set(
433 1,
434 { { // For deployment nullifier lookup
435 { C::nullifier_check_sel, 1 },
436 { C::nullifier_check_exists, 1 },
437 { C::nullifier_check_nullifier, contract_address },
438 { C::nullifier_check_root, nullifier_tree_root },
439 { C::nullifier_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
440 { C::nullifier_check_should_silo, 1 },
441 // For address derivation lookup
442 { C::address_derivation_sel, 1 },
443 { C::address_derivation_address, contract_address },
444 { C::address_derivation_salt, contract_instance_data.salt },
445 { C::address_derivation_deployer_addr, contract_instance_data.deployer },
446 { C::address_derivation_class_id, contract_instance_data.original_contract_class_id },
447 { C::address_derivation_init_hash, contract_instance_data.initialization_hash },
448 { C::address_derivation_nullifier_key_x, contract_instance_data.public_keys.nullifier_key.x },
449 { C::address_derivation_nullifier_key_y, contract_instance_data.public_keys.nullifier_key.y },
450 { C::address_derivation_incoming_viewing_key_x, contract_instance_data.public_keys.incoming_viewing_key.x },
451 { C::address_derivation_incoming_viewing_key_y, contract_instance_data.public_keys.incoming_viewing_key.y },
452 { C::address_derivation_outgoing_viewing_key_x, contract_instance_data.public_keys.outgoing_viewing_key.x },
453 { C::address_derivation_outgoing_viewing_key_y, contract_instance_data.public_keys.outgoing_viewing_key.y },
454 { C::address_derivation_tagging_key_x, contract_instance_data.public_keys.tagging_key.x },
455 { C::address_derivation_tagging_key_y, contract_instance_data.public_keys.tagging_key.y },
456 // For update check lookup
457 { C::update_check_sel, 1 },
458 { C::update_check_address, contract_address },
459 { C::update_check_current_class_id, contract_instance_data.current_contract_class_id },
460 { C::update_check_original_class_id, contract_instance_data.original_contract_class_id },
461 { C::update_check_public_data_tree_root, public_data_tree_root },
462 { C::update_check_timestamp, timestamp },
463 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
464
465 check_relation<contract_instance_retrieval>(trace);
466
467 // Test lookup interactions
468 check_interaction<ContractInstanceRetrievalTraceBuilder,
470 check_interaction<ContractInstanceRetrievalTraceBuilder,
472 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
473 trace);
474}
475
476TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenNonExistentInstance)
477{
478 // Test constants
479 const auto contract_address = FF(0x999999999ULL);
480 const auto timestamp = 99999;
481 const auto nullifier_tree_root = FF(0xffffff);
482 const auto public_data_tree_root = FF(0xeeeeee);
483 const auto deployment_nullifier = FF(0x8888);
484
485 // Use real tracegen to generate a valid trace for non-existent instance
486 EventEmitter<ContractInstanceRetrievalEvent> emitter;
487
488 ContractInstanceRetrievalEvent event{ .address = contract_address,
489 .contract_instance = {}, // no instance, DNE
490 .nullifier_tree_root = nullifier_tree_root,
491 .public_data_tree_root = public_data_tree_root,
492 .deployment_nullifier = deployment_nullifier,
493 .exists = false, // Non-existent
494 .is_protocol_contract = false };
495
496 emitter.emit(std::move(event));
497 auto events = emitter.dump_events();
498
499 TestTraceContainer trace;
500 ContractInstanceRetrievalTraceBuilder builder;
501 builder.process(events, trace);
502
503 // Add precomputed table entries
504 PrecomputedTraceBuilder precomputed_builder;
508
509 trace.set(1,
510 { { // For deployment nullifier read lookup
511 { C::nullifier_check_sel, 1 },
512 { C::nullifier_check_exists, 0 }, // Non-existent
513 { C::nullifier_check_nullifier, contract_address },
514 { C::nullifier_check_root, nullifier_tree_root },
515 { C::nullifier_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
516 { C::nullifier_check_should_silo, 1 },
517 // For address derivation lookup
518 { C::address_derivation_sel, 0 }, // Not selected since nullifier doesn't exist
519 { C::address_derivation_address, contract_address },
520 { C::address_derivation_salt, 0 }, // zero since nullifier doesn't exist
521 { C::address_derivation_deployer_addr, 0 }, // zero since nullifier doesn't exist
522 { C::address_derivation_class_id, 0 }, // zero since nullifier doesn't exist
523 { C::address_derivation_init_hash, 0 }, // zero since nullifier doesn't exist
524 { C::address_derivation_nullifier_key_x, 0 },
525 { C::address_derivation_nullifier_key_y, 0 },
526 { C::address_derivation_incoming_viewing_key_x, 0 },
527 { C::address_derivation_incoming_viewing_key_y, 0 },
528 { C::address_derivation_outgoing_viewing_key_x, 0 },
529 { C::address_derivation_outgoing_viewing_key_y, 0 },
530 { C::address_derivation_tagging_key_x, 0 },
531 { C::address_derivation_tagging_key_y, 0 },
532 // For update check lookup (only populated when nullifier exists)
533 { C::update_check_sel, 0 }, // Not selected since nullifier doesn't exist
534 { C::update_check_address, contract_address },
535 { C::update_check_current_class_id, 0 },
536 { C::update_check_original_class_id, 0 },
537 { C::update_check_public_data_tree_root, public_data_tree_root },
538 { C::update_check_timestamp, timestamp },
539 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
540
541 check_relation<contract_instance_retrieval>(trace);
542
543 // Test lookup interactions
544 check_interaction<ContractInstanceRetrievalTraceBuilder,
546 check_interaction<ContractInstanceRetrievalTraceBuilder,
548 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
549 trace);
550}
551
552TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenAddressZero)
553{
554 // Test constants
555 const auto contract_address = FF(0);
556 const auto timestamp = 99999;
557 const auto nullifier_tree_root = FF(0xffffff);
558 const auto public_data_tree_root = FF(0xeeeeee);
559 const auto deployment_nullifier = FF(0x8888);
560
561 // Use real tracegen to generate a valid trace for non-existent instance
562 EventEmitter<ContractInstanceRetrievalEvent> emitter;
563
564 ContractInstanceRetrievalEvent event{
565 .address = contract_address,
566 .contract_instance = {}, // no instance, DNE
567 .nullifier_tree_root = nullifier_tree_root,
568 .public_data_tree_root = public_data_tree_root,
569 .deployment_nullifier = deployment_nullifier,
570 .exists = false, // Non-existent
571 .is_protocol_contract = false, // Not a protocol contract, since MAX_PROTOCOL_CONTRACTS < (0 - 1)
572 };
573
574 emitter.emit(std::move(event));
575 auto events = emitter.dump_events();
576
577 TestTraceContainer trace;
578 ContractInstanceRetrievalTraceBuilder builder;
579 builder.process(events, trace);
580
581 // Add precomputed table entries
582 PrecomputedTraceBuilder precomputed_builder;
586
587 trace.set(1,
588 { { // For deployment nullifier read lookup
589 { C::nullifier_check_sel, 1 },
590 { C::nullifier_check_exists, 0 }, // Non-existent
591 { C::nullifier_check_nullifier, contract_address },
592 { C::nullifier_check_root, nullifier_tree_root },
593 { C::nullifier_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
594 { C::nullifier_check_should_silo, 1 },
595 // For address derivation lookup
596 { C::address_derivation_sel, 0 }, // Not selected since nullifier doesn't exist
597 { C::address_derivation_address, contract_address },
598 { C::address_derivation_salt, 0 }, // zero since nullifier doesn't exist
599 { C::address_derivation_deployer_addr, 0 }, // zero since nullifier doesn't exist
600 { C::address_derivation_class_id, 0 }, // zero since nullifier doesn't exist
601 { C::address_derivation_init_hash, 0 }, // zero since nullifier doesn't exist
602 { C::address_derivation_nullifier_key_x, 0 },
603 { C::address_derivation_nullifier_key_y, 0 },
604 { C::address_derivation_incoming_viewing_key_x, 0 },
605 { C::address_derivation_incoming_viewing_key_y, 0 },
606 { C::address_derivation_outgoing_viewing_key_x, 0 },
607 { C::address_derivation_outgoing_viewing_key_y, 0 },
608 { C::address_derivation_tagging_key_x, 0 },
609 { C::address_derivation_tagging_key_y, 0 },
610 // For update check lookup (only populated when nullifier exists)
611 { C::update_check_sel, 0 }, // Not selected since nullifier doesn't exist
612 { C::update_check_address, contract_address },
613 { C::update_check_current_class_id, 0 },
614 { C::update_check_original_class_id, 0 },
615 { C::update_check_public_data_tree_root, public_data_tree_root },
616 { C::update_check_timestamp, timestamp },
617 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
618
619 check_relation<contract_instance_retrieval>(trace);
620
621 // Test lookup interactions
622 check_interaction<ContractInstanceRetrievalTraceBuilder,
624 check_interaction<ContractInstanceRetrievalTraceBuilder,
626 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
627 trace);
628}
629
630TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenMultipleInstances)
631{
632 // Test constants
633 const auto num_instances = 3;
634 const auto base_address = 0x1000;
635 const auto base_timestamp = 1000;
636 const auto base_nullifier_tree_root = 0x2000;
637 const auto base_public_data_tree_root = 0x3000;
638 const auto base_salt = 100;
639
640 // Use real tracegen to generate multiple instances
641 EventEmitter<ContractInstanceRetrievalEvent> emitter;
642
643 for (uint32_t i = 0; i < num_instances; i++) {
644 auto contract_instance = create_test_contract_instance(base_salt + i);
645
646 ContractInstanceRetrievalEvent event = { .address = FF(base_address + i),
647 .contract_instance = contract_instance,
648 .nullifier_tree_root = FF(base_nullifier_tree_root + i),
649 .public_data_tree_root = FF(base_public_data_tree_root + i),
650 .deployment_nullifier = FF(base_address + i),
651 .exists = true,
652 .is_protocol_contract = false };
653
654 emitter.emit(std::move(event));
655 }
656
657 auto events = emitter.dump_events();
658
659 TestTraceContainer trace;
660 ContractInstanceRetrievalTraceBuilder builder;
661 builder.process(events, trace);
662
663 // Add precomputed table entries
664 PrecomputedTraceBuilder precomputed_builder;
668
669 // Manually populate destination tables for lookup interactions
670 for (uint32_t i = 0; i < num_instances; i++) {
671 auto contract_instance_data = create_test_contract_instance(base_salt + i);
672 uint32_t row = i + 1; // Skip row 0 (skippable gadget)
673
674 trace.set(
675 row, // For deployment nullifier read lookup
676 { { { C::nullifier_check_sel, 1 },
677 { C::nullifier_check_exists, true },
678 { C::nullifier_check_nullifier, FF(base_address + i) },
679 { C::nullifier_check_root, FF(base_nullifier_tree_root + i) },
680 { C::nullifier_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
681 { C::nullifier_check_should_silo, 1 },
682 // For address derivation lookup (only when nullifier exists)
683 { C::address_derivation_sel, 1 },
684 { C::address_derivation_address, FF(base_address + i) },
685 { C::address_derivation_salt, contract_instance_data.salt },
686 { C::address_derivation_deployer_addr, contract_instance_data.deployer },
687 { C::address_derivation_class_id, contract_instance_data.original_contract_class_id },
688 { C::address_derivation_init_hash, contract_instance_data.initialization_hash },
689 { C::address_derivation_nullifier_key_x, contract_instance_data.public_keys.nullifier_key.x },
690 { C::address_derivation_nullifier_key_y, contract_instance_data.public_keys.nullifier_key.y },
691 { C::address_derivation_incoming_viewing_key_x,
692 contract_instance_data.public_keys.incoming_viewing_key.x },
693 { C::address_derivation_incoming_viewing_key_y,
694 contract_instance_data.public_keys.incoming_viewing_key.y },
695 { C::address_derivation_outgoing_viewing_key_x,
696 contract_instance_data.public_keys.outgoing_viewing_key.x },
697 { C::address_derivation_outgoing_viewing_key_y,
698 contract_instance_data.public_keys.outgoing_viewing_key.y },
699 { C::address_derivation_tagging_key_x, contract_instance_data.public_keys.tagging_key.x },
700 { C::address_derivation_tagging_key_y, contract_instance_data.public_keys.tagging_key.y },
701 // For update check lookup (only when nullifier exists)
702 { C::update_check_sel, 1 },
703 { C::update_check_address, FF(base_address + i) },
704 { C::update_check_current_class_id, contract_instance_data.current_contract_class_id },
705 { C::update_check_original_class_id, contract_instance_data.original_contract_class_id },
706 { C::update_check_public_data_tree_root, FF(base_public_data_tree_root + i) },
707 { C::update_check_timestamp, base_timestamp + i },
708 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
709 }
710
711 check_relation<contract_instance_retrieval>(trace);
712
713 // Test lookup interactions
714 check_interaction<ContractInstanceRetrievalTraceBuilder,
716 check_interaction<ContractInstanceRetrievalTraceBuilder,
718 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
719 trace);
720}
721
722} // namespace
723} // namespace bb::avm2::constraining
#define AVM_PUBLIC_INPUTS_PROTOCOL_CONTRACTS_ROW_IDX
#define FEE_JUICE_ADDRESS
#define MAX_PROTOCOL_CONTRACTS
#define AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX
#define CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS
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_misc(TraceContainer &trace, const uint32_t num_rows=MAX_AVM_TRACE_SIZE)
void process_get_contract_instance_table(TraceContainer &trace)
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
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
Definition macros.hpp:7
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(TxExecutionConstrainingTest, WriteTreeValue)
Definition tx.test.cpp:441
TestTraceContainer empty_trace()
Definition fixtures.cpp:153
lookup_settings< lookup_contract_instance_retrieval_check_protocol_address_range_settings_ > lookup_contract_instance_retrieval_check_protocol_address_range_settings
lookup_settings< lookup_contract_instance_retrieval_address_derivation_settings_ > lookup_contract_instance_retrieval_address_derivation_settings
lookup_settings< lookup_contract_instance_retrieval_read_derived_address_from_public_inputs_settings_ > lookup_contract_instance_retrieval_read_derived_address_from_public_inputs_settings
lookup_settings< lookup_contract_instance_retrieval_deployment_nullifier_read_settings_ > lookup_contract_instance_retrieval_deployment_nullifier_read_settings
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
simulation::PublicDataTreeReadWriteEvent event
FF original_class_id
FF current_class_id
constexpr field invert() const noexcept
tracegen::PublicInputsTraceBuilder public_inputs_builder
Definition tx.test.cpp:81