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