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_tree_height, NULLIFIER_TREE_HEIGHT },
98 { C::contract_instance_retrieval_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
99 { C::contract_instance_retrieval_nullifier_key_x, nullifier_key_x },
100 { C::contract_instance_retrieval_nullifier_key_y, nullifier_key_y },
101 { C::contract_instance_retrieval_incoming_viewing_key_x, incoming_viewing_key_x },
102 { C::contract_instance_retrieval_incoming_viewing_key_y, incoming_viewing_key_y },
103 { C::contract_instance_retrieval_outgoing_viewing_key_x, outgoing_viewing_key_x },
104 { C::contract_instance_retrieval_outgoing_viewing_key_y, outgoing_viewing_key_y },
105 { C::contract_instance_retrieval_tagging_key_x, tagging_key_x },
106 { C::contract_instance_retrieval_tagging_key_y, tagging_key_y },
107 { C::contract_instance_retrieval_deployer_protocol_contract_address,
109 // Protocol Contract conditionals
110 { C::contract_instance_retrieval_address_sub_one, contract_address - 1 },
111 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
112 { C::contract_instance_retrieval_derived_address, contract_address },
113 { C::contract_instance_retrieval_is_protocol_contract, 0 },
114 { C::contract_instance_retrieval_should_check_nullifier, 1 },
115 { C::contract_instance_retrieval_should_check_for_update, 1 } },
116 });
117
118 check_relation<contract_instance_retrieval>(trace);
119}
120
121TEST(ContractInstanceRetrievalConstrainingTest, MultipleInstancesTrace)
122{
123 // Test constants
124 const auto num_instances = 3;
125 const auto base_address = 0x1000;
126 const auto base_nullifier_tree_root = 0x2000;
127 const auto base_public_data_tree_root = 0x3000;
128 const auto base_salt = 100;
129
130 // Test multiple contract instances in sequence
132
133 // First row
134 trace_data.push_back({ { C::precomputed_first_row, 1 } });
135
136 // Create multiple instance rows
137 for (uint32_t i = 0; i < num_instances; i++) {
138 auto contract_instance = create_test_contract_instance(base_salt + i);
139
140 trace_data.push_back({
141 { C::contract_instance_retrieval_sel, 1 },
142 { C::contract_instance_retrieval_address, FF(base_address + i) },
143 { C::contract_instance_retrieval_exists, 1 },
144 { C::contract_instance_retrieval_salt, contract_instance.salt },
145 { C::contract_instance_retrieval_deployer_addr, contract_instance.deployer },
146 { C::contract_instance_retrieval_current_class_id, contract_instance.current_contract_class_id },
147 { C::contract_instance_retrieval_original_class_id, contract_instance.original_contract_class_id },
148 { C::contract_instance_retrieval_init_hash, contract_instance.initialization_hash },
149 { C::contract_instance_retrieval_public_data_tree_root, FF(base_public_data_tree_root + i) },
150 { C::contract_instance_retrieval_nullifier_tree_root, FF(base_nullifier_tree_root + i) },
151 { C::contract_instance_retrieval_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
152 { C::contract_instance_retrieval_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
153 { C::contract_instance_retrieval_nullifier_key_x, contract_instance.public_keys.nullifier_key.x },
154 { C::contract_instance_retrieval_nullifier_key_y, contract_instance.public_keys.nullifier_key.y },
155 { C::contract_instance_retrieval_incoming_viewing_key_x,
156 contract_instance.public_keys.incoming_viewing_key.x },
157 { C::contract_instance_retrieval_incoming_viewing_key_y,
158 contract_instance.public_keys.incoming_viewing_key.y },
159 { C::contract_instance_retrieval_outgoing_viewing_key_x,
160 contract_instance.public_keys.outgoing_viewing_key.x },
161 { C::contract_instance_retrieval_outgoing_viewing_key_y,
162 contract_instance.public_keys.outgoing_viewing_key.y },
163 { C::contract_instance_retrieval_tagging_key_x, contract_instance.public_keys.tagging_key.x },
164 { C::contract_instance_retrieval_tagging_key_y, contract_instance.public_keys.tagging_key.y },
165 { C::contract_instance_retrieval_deployer_protocol_contract_address,
167 // Protocol Contract conditionals
168 { C::contract_instance_retrieval_address_sub_one, (base_address + i) - 1 },
169 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
170 { C::contract_instance_retrieval_derived_address, base_address + i },
171 { C::contract_instance_retrieval_is_protocol_contract, 0 },
172 { C::contract_instance_retrieval_should_check_nullifier, 1 },
173 { C::contract_instance_retrieval_should_check_for_update, 1 },
174 });
175 }
176
177 TestTraceContainer trace(trace_data);
178 check_relation<contract_instance_retrieval>(trace);
179}
180
181TEST(ContractInstanceRetrievalConstrainingTest, NonExistentInstanceTrace)
182{
183 // Test constants
184 const auto contract_address = FF(0x99999999);
185 const auto nullifier_tree_root = FF(0xffffff);
186 const auto public_data_tree_root = FF(0xeeeeee);
187 const auto exists = false;
188
189 // Test trace for non-existent contract instance
190 TestTraceContainer trace({
191 { { C::precomputed_first_row, 1 } },
192 { { C::contract_instance_retrieval_sel, 1 },
193 { C::contract_instance_retrieval_address, contract_address },
194 { C::contract_instance_retrieval_exists, exists ? 1 : 0 },
195 { C::contract_instance_retrieval_salt, 0 },
196 { C::contract_instance_retrieval_deployer_addr, 0 },
197 { C::contract_instance_retrieval_current_class_id, 0 },
198 { C::contract_instance_retrieval_original_class_id, 0 },
199 { C::contract_instance_retrieval_init_hash, 0 },
200 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
201 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
202 { C::contract_instance_retrieval_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
203 { C::contract_instance_retrieval_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
204 { C::contract_instance_retrieval_deployer_protocol_contract_address,
206 // Protocol Contract conditionals
207 { C::contract_instance_retrieval_address_sub_one, contract_address - 1 },
208 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
209 { C::contract_instance_retrieval_derived_address, contract_address },
210 { C::contract_instance_retrieval_is_protocol_contract, 0 },
211 { C::contract_instance_retrieval_should_check_nullifier, 1 },
212 { C::contract_instance_retrieval_should_check_for_update, 0 /*since exists = false*/ } },
213 });
214
215 check_relation<contract_instance_retrieval>(trace);
216
217 // mutate instance members to be nonzero and confirm that relation fails
218 // mutate deployer_addr
219 trace.set(C::contract_instance_retrieval_deployer_addr, 1, 1);
220 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
221 "INSTANCE_MEMBER_DEPLOYER_IS_ZERO_IF_DNE");
222 // reset
223 trace.set(C::contract_instance_retrieval_deployer_addr, 1, 0);
224 // mutate current_class_id
225 trace.set(C::contract_instance_retrieval_current_class_id, 1, 1);
226 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
227 "INSTANCE_MEMBER_CLASS_ID_IS_ZERO_IF_DNE");
228 // reset
229 trace.set(C::contract_instance_retrieval_current_class_id, 1, 0);
230 // mutate original_class_id
231 trace.set(C::contract_instance_retrieval_original_class_id, 1, 1);
232 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
233 "INSTANCE_MEMBER_ORIGINAL_CLASS_ID_IS_ZERO_IF_DNE");
234 // reset
235 trace.set(C::contract_instance_retrieval_original_class_id, 1, 0);
236 // mutate init_hash
237 trace.set(C::contract_instance_retrieval_init_hash, 1, 1);
238 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
239 "INSTANCE_MEMBER_INIT_HASH_IS_ZERO_IF_DNE");
240 // reset
241 trace.set(C::contract_instance_retrieval_init_hash, 1, 0);
242}
243
244TEST(ContractInstanceRetrievalConstrainingTest, MaximumFieldValuesTrace)
245{
246 // Test constants
247 const auto max_field = FF(-1); // Maximum field value
248
249 // Test trace with maximum field values
250 TestTraceContainer trace({
251 { { C::precomputed_first_row, 1 } },
252 { { C::contract_instance_retrieval_sel, 1 },
253 { C::contract_instance_retrieval_address, max_field },
254 { C::contract_instance_retrieval_exists, 1 },
255 { C::contract_instance_retrieval_salt, max_field },
256 { C::contract_instance_retrieval_deployer_addr, max_field },
257 { C::contract_instance_retrieval_current_class_id, max_field },
258 { C::contract_instance_retrieval_original_class_id, max_field },
259 { C::contract_instance_retrieval_init_hash, max_field },
260 { C::contract_instance_retrieval_public_data_tree_root, max_field },
261 { C::contract_instance_retrieval_nullifier_tree_root, max_field },
262 { C::contract_instance_retrieval_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
263 { C::contract_instance_retrieval_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
264 { C::contract_instance_retrieval_nullifier_key_x, max_field },
265 { C::contract_instance_retrieval_nullifier_key_y, max_field },
266 { C::contract_instance_retrieval_incoming_viewing_key_x, max_field },
267 { C::contract_instance_retrieval_incoming_viewing_key_y, max_field },
268 { C::contract_instance_retrieval_outgoing_viewing_key_x, max_field },
269 { C::contract_instance_retrieval_outgoing_viewing_key_y, max_field },
270 { C::contract_instance_retrieval_tagging_key_x, max_field },
271 { C::contract_instance_retrieval_tagging_key_y, max_field },
272 { C::contract_instance_retrieval_deployer_protocol_contract_address,
274 // Protocol Contract conditionals
275 { C::contract_instance_retrieval_address_sub_one, max_field - 1 },
276 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
277 { C::contract_instance_retrieval_derived_address, max_field },
278 { C::contract_instance_retrieval_is_protocol_contract, 0 },
279 { C::contract_instance_retrieval_should_check_nullifier, 1 },
280 { C::contract_instance_retrieval_should_check_for_update, 1 } },
281 });
282
283 check_relation<contract_instance_retrieval>(trace);
284}
285
286TEST(ContractInstanceRetrievalConstrainingTest, ProtocolContractInstanceExists)
287{
288 // Test constants
289 const AztecAddress contract_address = FEE_JUICE_ADDRESS;
290 const AztecAddress derived_address = FF(0xabcdef1234567890ULL);
291 const auto nullifier_tree_root = FF(0xbadc0ffeeULL);
292 const auto public_data_tree_root = FF(0xfacefeedUL);
293 ProtocolContracts protocol_contracts = {};
294 uint32_t protocol_contract_index = static_cast<uint32_t>(contract_address - 1);
295 protocol_contracts.derived_addresses[protocol_contract_index] = derived_address;
296
297 auto public_inputs = PublicInputsBuilder().set_protocol_contracts(protocol_contracts).build();
298
299 // Test complete valid trace with all constraints
300 TestTraceContainer trace({
301 {
302 { C::precomputed_first_row, 1 },
303 // Field Greater-Than Trace for Protocol Contract Address Check
304 { C::ff_gt_sel, 1 },
305 { C::ff_gt_sel_gt, 1 },
306 { C::ff_gt_a, MAX_PROTOCOL_CONTRACTS },
307 { C::ff_gt_b, contract_address - FF(1) },
308 { C::ff_gt_result, 1 },
309 },
310 {
311 // Contract Retrieval Instance Trace
312 { C::contract_instance_retrieval_sel, 1 },
313 { C::contract_instance_retrieval_address, contract_address },
314 { C::contract_instance_retrieval_exists, 1 },
315 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
316 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
317 { C::contract_instance_retrieval_deployer_protocol_contract_address,
319 // Protocol Contract conditionals
320 { C::contract_instance_retrieval_derived_address_pi_index,
321 AVM_PUBLIC_INPUTS_PROTOCOL_CONTRACTS_ROW_IDX + protocol_contract_index },
322 { C::contract_instance_retrieval_protocol_contract_derived_address_inv, derived_address.invert() },
323 { C::contract_instance_retrieval_address_sub_one, contract_address - FF(1) },
324 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
325 { C::contract_instance_retrieval_derived_address, derived_address },
326 { C::contract_instance_retrieval_is_protocol_contract, 1 },
327 { C::contract_instance_retrieval_should_check_nullifier, 0 },
328 { C::contract_instance_retrieval_should_check_for_update, 0 },
329 },
330 });
331
332 PublicInputsTraceBuilder public_inputs_builder;
333 public_inputs_builder.process_public_inputs(trace, public_inputs);
334 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
335
336 tracegen::PrecomputedTraceBuilder precomputed_builder;
338
339 check_relation<contract_instance_retrieval>(trace);
340 check_interaction<ContractInstanceRetrievalTraceBuilder,
343}
344
345TEST(ContractInstanceRetrievalConstrainingTest, ProtocolContractInstanceNotExists)
346{
347 // Test constants
348 const AztecAddress contract_address = FEE_JUICE_ADDRESS;
349 const AztecAddress derived_address = FF(0);
350 const auto nullifier_tree_root = FF(0xbadc0ffeeULL);
351 const auto public_data_tree_root = FF(0xfacefeedUL);
352 uint32_t protocol_contract_index = static_cast<uint32_t>(contract_address - 1);
353 // Default protocol contracts: empty
354 auto public_inputs = PublicInputsBuilder().build();
355
356 // Test complete valid trace with all constraints
357 TestTraceContainer trace({
358 {
359 { C::precomputed_first_row, 1 },
360 // Field Greater-Than Trace for Protocol Contract Address Check
361 { C::ff_gt_sel, 1 },
362 { C::ff_gt_sel_gt, 1 },
363 { C::ff_gt_a, MAX_PROTOCOL_CONTRACTS },
364 { C::ff_gt_b, contract_address - FF(1) },
365 { C::ff_gt_result, 1 },
366 },
367 {
368 // Contract Retrieval Instance Trace
369 { C::contract_instance_retrieval_sel, 1 },
370 { C::contract_instance_retrieval_address, contract_address },
371 { C::contract_instance_retrieval_exists, 0 },
372 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
373 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
374 { C::contract_instance_retrieval_deployer_protocol_contract_address,
376 // Protocol Contract conditionals
377 { C::contract_instance_retrieval_derived_address_pi_index,
378 AVM_PUBLIC_INPUTS_PROTOCOL_CONTRACTS_ROW_IDX + protocol_contract_index },
379 { C::contract_instance_retrieval_protocol_contract_derived_address_inv, 0 },
380 { C::contract_instance_retrieval_address_sub_one, contract_address - FF(1) },
381 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
382 { C::contract_instance_retrieval_derived_address, derived_address },
383 { C::contract_instance_retrieval_is_protocol_contract, 1 },
384 { C::contract_instance_retrieval_should_check_nullifier, 0 },
385 { C::contract_instance_retrieval_should_check_for_update, 0 },
386 },
387 });
388
389 PublicInputsTraceBuilder public_inputs_builder;
390 public_inputs_builder.process_public_inputs(trace, public_inputs);
391 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
392
393 tracegen::PrecomputedTraceBuilder precomputed_builder;
395
396 check_relation<contract_instance_retrieval>(trace);
397 check_interaction<ContractInstanceRetrievalTraceBuilder,
400}
401
402// Integration-style tests using tracegen components
403TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenValidInstance)
404{
405 // Test constants
406 const auto contract_address = FF(0x1234567890abcdefULL);
407 const auto timestamp = 12345;
408 const auto nullifier_tree_root = FF(0xaabbccdd);
409 const auto public_data_tree_root = FF(0xeeff1122);
410 const auto deployment_nullifier = FF(0x7777);
411
412 // Use real tracegen to generate a valid trace
413 EventEmitter<ContractInstanceRetrievalEvent> emitter;
414 auto contract_instance = create_test_contract_instance();
415
416 ContractInstanceRetrievalEvent event = { .address = contract_address,
417 .contract_instance = contract_instance,
418 .nullifier_tree_root = nullifier_tree_root,
419 .public_data_tree_root = public_data_tree_root,
420 .deployment_nullifier = deployment_nullifier,
421 .exists = true,
422 .is_protocol_contract = false };
423
424 emitter.emit(std::move(event));
425 auto events = emitter.dump_events();
426
427 TestTraceContainer trace;
428 ContractInstanceRetrievalTraceBuilder builder;
429 builder.process(events, trace);
430
431 // Add precomputed table entries
432 PrecomputedTraceBuilder precomputed_builder;
436
437 // Manually populate destination tables for lookup interactions
438 auto contract_instance_data = create_test_contract_instance();
439
440 trace.set(
441 1,
442 { { // For deployment nullifier lookup
443 { C::indexed_tree_check_sel, 1 },
444 { C::indexed_tree_check_exists, 1 },
445 { C::indexed_tree_check_value, contract_address },
446 { C::indexed_tree_check_root, nullifier_tree_root },
447 { C::indexed_tree_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
448 { C::indexed_tree_check_sel_silo, 1 },
449 { C::indexed_tree_check_tree_height, NULLIFIER_TREE_HEIGHT },
450 { C::indexed_tree_check_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
451 // For address derivation lookup
452 { C::address_derivation_sel, 1 },
453 { C::address_derivation_address, contract_address },
454 { C::address_derivation_salt, contract_instance_data.salt },
455 { C::address_derivation_deployer_addr, contract_instance_data.deployer },
456 { C::address_derivation_class_id, contract_instance_data.original_contract_class_id },
457 { C::address_derivation_init_hash, contract_instance_data.initialization_hash },
458 { C::address_derivation_nullifier_key_x, contract_instance_data.public_keys.nullifier_key.x },
459 { C::address_derivation_nullifier_key_y, contract_instance_data.public_keys.nullifier_key.y },
460 { C::address_derivation_incoming_viewing_key_x, contract_instance_data.public_keys.incoming_viewing_key.x },
461 { C::address_derivation_incoming_viewing_key_y, contract_instance_data.public_keys.incoming_viewing_key.y },
462 { C::address_derivation_outgoing_viewing_key_x, contract_instance_data.public_keys.outgoing_viewing_key.x },
463 { C::address_derivation_outgoing_viewing_key_y, contract_instance_data.public_keys.outgoing_viewing_key.y },
464 { C::address_derivation_tagging_key_x, contract_instance_data.public_keys.tagging_key.x },
465 { C::address_derivation_tagging_key_y, contract_instance_data.public_keys.tagging_key.y },
466 // For update check lookup
467 { C::update_check_sel, 1 },
468 { C::update_check_address, contract_address },
469 { C::update_check_current_class_id, contract_instance_data.current_contract_class_id },
470 { C::update_check_original_class_id, contract_instance_data.original_contract_class_id },
471 { C::update_check_public_data_tree_root, public_data_tree_root },
472 { C::update_check_timestamp, timestamp },
473 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
474
475 check_relation<contract_instance_retrieval>(trace);
476
477 // Test lookup interactions
478 check_interaction<ContractInstanceRetrievalTraceBuilder,
480 check_interaction<ContractInstanceRetrievalTraceBuilder,
482 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
483 trace);
484}
485
486TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenNonExistentInstance)
487{
488 // Test constants
489 const auto contract_address = FF(0x999999999ULL);
490 const auto timestamp = 99999;
491 const auto nullifier_tree_root = FF(0xffffff);
492 const auto public_data_tree_root = FF(0xeeeeee);
493 const auto deployment_nullifier = FF(0x8888);
494
495 // Use real tracegen to generate a valid trace for non-existent instance
496 EventEmitter<ContractInstanceRetrievalEvent> emitter;
497
498 ContractInstanceRetrievalEvent event{ .address = contract_address,
499 .contract_instance = {}, // no instance, DNE
500 .nullifier_tree_root = nullifier_tree_root,
501 .public_data_tree_root = public_data_tree_root,
502 .deployment_nullifier = deployment_nullifier,
503 .exists = false, // Non-existent
504 .is_protocol_contract = false };
505
506 emitter.emit(std::move(event));
507 auto events = emitter.dump_events();
508
509 TestTraceContainer trace;
510 ContractInstanceRetrievalTraceBuilder builder;
511 builder.process(events, trace);
512
513 // Add precomputed table entries
514 PrecomputedTraceBuilder precomputed_builder;
518
519 trace.set(1,
520 { { // For deployment nullifier read lookup
521 { C::indexed_tree_check_sel, 1 },
522 { C::indexed_tree_check_exists, 0 }, // Non-existent
523 { C::indexed_tree_check_value, contract_address },
524 { C::indexed_tree_check_root, nullifier_tree_root },
525 { C::indexed_tree_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
526 { C::indexed_tree_check_sel_silo, 1 },
527 { C::indexed_tree_check_tree_height, NULLIFIER_TREE_HEIGHT },
528 { C::indexed_tree_check_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
529 // For address derivation lookup
530 { C::address_derivation_sel, 0 }, // Not selected since nullifier doesn't exist
531 { C::address_derivation_address, contract_address },
532 { C::address_derivation_salt, 0 }, // zero since nullifier doesn't exist
533 { C::address_derivation_deployer_addr, 0 }, // zero since nullifier doesn't exist
534 { C::address_derivation_class_id, 0 }, // zero since nullifier doesn't exist
535 { C::address_derivation_init_hash, 0 }, // zero since nullifier doesn't exist
536 { C::address_derivation_nullifier_key_x, 0 },
537 { C::address_derivation_nullifier_key_y, 0 },
538 { C::address_derivation_incoming_viewing_key_x, 0 },
539 { C::address_derivation_incoming_viewing_key_y, 0 },
540 { C::address_derivation_outgoing_viewing_key_x, 0 },
541 { C::address_derivation_outgoing_viewing_key_y, 0 },
542 { C::address_derivation_tagging_key_x, 0 },
543 { C::address_derivation_tagging_key_y, 0 },
544 // For update check lookup (only populated when nullifier exists)
545 { C::update_check_sel, 0 }, // Not selected since nullifier doesn't exist
546 { C::update_check_address, contract_address },
547 { C::update_check_current_class_id, 0 },
548 { C::update_check_original_class_id, 0 },
549 { C::update_check_public_data_tree_root, public_data_tree_root },
550 { C::update_check_timestamp, timestamp },
551 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
552
553 check_relation<contract_instance_retrieval>(trace);
554
555 // Test lookup interactions
556 check_interaction<ContractInstanceRetrievalTraceBuilder,
558 check_interaction<ContractInstanceRetrievalTraceBuilder,
560 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
561 trace);
562}
563
564TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenAddressZero)
565{
566 // Test constants
567 const auto contract_address = FF(0);
568 const auto timestamp = 99999;
569 const auto nullifier_tree_root = FF(0xffffff);
570 const auto public_data_tree_root = FF(0xeeeeee);
571 const auto deployment_nullifier = FF(0x8888);
572
573 // Use real tracegen to generate a valid trace for non-existent instance
574 EventEmitter<ContractInstanceRetrievalEvent> emitter;
575
576 ContractInstanceRetrievalEvent event{
577 .address = contract_address,
578 .contract_instance = {}, // no instance, DNE
579 .nullifier_tree_root = nullifier_tree_root,
580 .public_data_tree_root = public_data_tree_root,
581 .deployment_nullifier = deployment_nullifier,
582 .exists = false, // Non-existent
583 .is_protocol_contract = false, // Not a protocol contract, since MAX_PROTOCOL_CONTRACTS < (0 - 1)
584 };
585
586 emitter.emit(std::move(event));
587 auto events = emitter.dump_events();
588
589 TestTraceContainer trace;
590 ContractInstanceRetrievalTraceBuilder builder;
591 builder.process(events, trace);
592
593 // Add precomputed table entries
594 PrecomputedTraceBuilder precomputed_builder;
598
599 trace.set(1,
600 { { // For deployment nullifier read lookup
601 { C::indexed_tree_check_sel, 1 },
602 { C::indexed_tree_check_exists, 0 }, // Non-existent
603 { C::indexed_tree_check_value, contract_address },
604 { C::indexed_tree_check_root, nullifier_tree_root },
605 { C::indexed_tree_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
606 { C::indexed_tree_check_sel_silo, 1 },
607 { C::indexed_tree_check_tree_height, NULLIFIER_TREE_HEIGHT },
608 { C::indexed_tree_check_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
609 // For address derivation lookup
610 { C::address_derivation_sel, 0 }, // Not selected since nullifier doesn't exist
611 { C::address_derivation_address, contract_address },
612 { C::address_derivation_salt, 0 }, // zero since nullifier doesn't exist
613 { C::address_derivation_deployer_addr, 0 }, // zero since nullifier doesn't exist
614 { C::address_derivation_class_id, 0 }, // zero since nullifier doesn't exist
615 { C::address_derivation_init_hash, 0 }, // zero since nullifier doesn't exist
616 { C::address_derivation_nullifier_key_x, 0 },
617 { C::address_derivation_nullifier_key_y, 0 },
618 { C::address_derivation_incoming_viewing_key_x, 0 },
619 { C::address_derivation_incoming_viewing_key_y, 0 },
620 { C::address_derivation_outgoing_viewing_key_x, 0 },
621 { C::address_derivation_outgoing_viewing_key_y, 0 },
622 { C::address_derivation_tagging_key_x, 0 },
623 { C::address_derivation_tagging_key_y, 0 },
624 // For update check lookup (only populated when nullifier exists)
625 { C::update_check_sel, 0 }, // Not selected since nullifier doesn't exist
626 { C::update_check_address, contract_address },
627 { C::update_check_current_class_id, 0 },
628 { C::update_check_original_class_id, 0 },
629 { C::update_check_public_data_tree_root, public_data_tree_root },
630 { C::update_check_timestamp, timestamp },
631 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
632
633 check_relation<contract_instance_retrieval>(trace);
634
635 // Test lookup interactions
636 check_interaction<ContractInstanceRetrievalTraceBuilder,
638 check_interaction<ContractInstanceRetrievalTraceBuilder,
640 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
641 trace);
642}
643
644TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenMultipleInstances)
645{
646 // Test constants
647 const auto num_instances = 3;
648 const auto base_address = 0x1000;
649 const auto base_timestamp = 1000;
650 const auto base_nullifier_tree_root = 0x2000;
651 const auto base_public_data_tree_root = 0x3000;
652 const auto base_salt = 100;
653
654 // Use real tracegen to generate multiple instances
655 EventEmitter<ContractInstanceRetrievalEvent> emitter;
656
657 for (uint32_t i = 0; i < num_instances; i++) {
658 auto contract_instance = create_test_contract_instance(base_salt + i);
659
660 ContractInstanceRetrievalEvent event = { .address = FF(base_address + i),
661 .contract_instance = contract_instance,
662 .nullifier_tree_root = FF(base_nullifier_tree_root + i),
663 .public_data_tree_root = FF(base_public_data_tree_root + i),
664 .deployment_nullifier = FF(base_address + i),
665 .exists = true,
666 .is_protocol_contract = false };
667
668 emitter.emit(std::move(event));
669 }
670
671 auto events = emitter.dump_events();
672
673 TestTraceContainer trace;
674 ContractInstanceRetrievalTraceBuilder builder;
675 builder.process(events, trace);
676
677 // Add precomputed table entries
678 PrecomputedTraceBuilder precomputed_builder;
682
683 // Manually populate destination tables for lookup interactions
684 for (uint32_t i = 0; i < num_instances; i++) {
685 auto contract_instance_data = create_test_contract_instance(base_salt + i);
686 uint32_t row = i + 1; // Skip row 0 (skippable gadget)
687
688 trace.set(
689 row, // For deployment nullifier read lookup
690 { { { C::indexed_tree_check_sel, 1 },
691 { C::indexed_tree_check_exists, true },
692 { C::indexed_tree_check_value, FF(base_address + i) },
693 { C::indexed_tree_check_root, FF(base_nullifier_tree_root + i) },
694 { C::indexed_tree_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
695 { C::indexed_tree_check_sel_silo, 1 },
696 { C::indexed_tree_check_tree_height, NULLIFIER_TREE_HEIGHT },
697 { C::indexed_tree_check_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
698 // For address derivation lookup (only when nullifier exists)
699 { C::address_derivation_sel, 1 },
700 { C::address_derivation_address, FF(base_address + i) },
701 { C::address_derivation_salt, contract_instance_data.salt },
702 { C::address_derivation_deployer_addr, contract_instance_data.deployer },
703 { C::address_derivation_class_id, contract_instance_data.original_contract_class_id },
704 { C::address_derivation_init_hash, contract_instance_data.initialization_hash },
705 { C::address_derivation_nullifier_key_x, contract_instance_data.public_keys.nullifier_key.x },
706 { C::address_derivation_nullifier_key_y, contract_instance_data.public_keys.nullifier_key.y },
707 { C::address_derivation_incoming_viewing_key_x,
708 contract_instance_data.public_keys.incoming_viewing_key.x },
709 { C::address_derivation_incoming_viewing_key_y,
710 contract_instance_data.public_keys.incoming_viewing_key.y },
711 { C::address_derivation_outgoing_viewing_key_x,
712 contract_instance_data.public_keys.outgoing_viewing_key.x },
713 { C::address_derivation_outgoing_viewing_key_y,
714 contract_instance_data.public_keys.outgoing_viewing_key.y },
715 { C::address_derivation_tagging_key_x, contract_instance_data.public_keys.tagging_key.x },
716 { C::address_derivation_tagging_key_y, contract_instance_data.public_keys.tagging_key.y },
717 // For update check lookup (only when nullifier exists)
718 { C::update_check_sel, 1 },
719 { C::update_check_address, FF(base_address + i) },
720 { C::update_check_current_class_id, contract_instance_data.current_contract_class_id },
721 { C::update_check_original_class_id, contract_instance_data.original_contract_class_id },
722 { C::update_check_public_data_tree_root, FF(base_public_data_tree_root + i) },
723 { C::update_check_timestamp, base_timestamp + i },
724 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
725 }
726
727 check_relation<contract_instance_retrieval>(trace);
728
729 // Test lookup interactions
730 check_interaction<ContractInstanceRetrievalTraceBuilder,
732 check_interaction<ContractInstanceRetrievalTraceBuilder,
734 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
735 trace);
736}
737
738} // namespace
739} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
#define AVM_PUBLIC_INPUTS_PROTOCOL_CONTRACTS_ROW_IDX
#define FEE_JUICE_ADDRESS
#define DOM_SEP__SILOED_NULLIFIER
#define NULLIFIER_TREE_HEIGHT
#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=PRECOMPUTED_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
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:153
lookup_settings< lookup_contract_instance_retrieval_check_protocol_address_range_settings_ > lookup_contract_instance_retrieval_check_protocol_address_range_settings
AvmFlavorSettings::FF FF
Definition field.hpp:10
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
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