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
8#include "barretenberg/aztec/aztec_constants.hpp"
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 .immutables_hash = FF(0x22222222ULL),
49 .public_keys =
50 PublicKeys{
51 .nullifier_key_hash = FF(0x100),
52 .incoming_viewing_key = { FF(0x200), FF(0x201) },
53 .outgoing_viewing_key_hash = FF(0x300),
54 .tagging_key_hash = FF(0x400),
55 .message_signing_key_hash = FF(0x500),
56 .fallback_key_hash = FF(0x600),
57 },
58 };
59}
60
61TEST(ContractInstanceRetrievalConstrainingTest, EmptyRow)
62{
63 check_relation<contract_instance_retrieval>(testing::empty_trace());
64}
65
66TEST(ContractInstanceRetrievalConstrainingTest, CompleteValidTrace)
67{
68 // Test constants
69 const auto contract_address = FF(0x1234567890abcdefULL);
70 const auto nullifier_tree_root = FF(0xaabbccdd);
71 const auto public_data_tree_root = FF(0xeeff1122);
72 const auto exists = true;
73 const auto salt = FF(0x555);
74 const auto deployer_addr = FF(0x123456789ULL);
75 const auto current_class_id = FF(0xdeadbeefULL);
76 const auto original_class_id = FF(0xcafebabeULL);
77 const auto init_hash = FF(0x11111111ULL);
78 const auto immutables_hash = FF(0x22222222ULL);
79 const auto nullifier_key_hash = FF(0x100);
80 const auto incoming_viewing_key_x = FF(0x200);
81 const auto incoming_viewing_key_y = FF(0x201);
82 const auto outgoing_viewing_key_hash = FF(0x300);
83 const auto tagging_key_hash = FF(0x400);
84 const auto message_signing_key_hash = FF(0x500);
85 const auto fallback_key_hash = FF(0x600);
86
87 // Test complete valid trace with all constraints
88 TestTraceContainer trace({
89 { { C::precomputed_first_row, 1 } },
90 { { C::contract_instance_retrieval_sel, 1 },
91 { C::contract_instance_retrieval_address, contract_address },
92 { C::contract_instance_retrieval_exists, exists ? 1 : 0 },
93 { C::contract_instance_retrieval_salt, salt },
94 { C::contract_instance_retrieval_deployer_addr, deployer_addr },
95 { C::contract_instance_retrieval_current_class_id, current_class_id },
96 { C::contract_instance_retrieval_original_class_id, original_class_id },
97 { C::contract_instance_retrieval_init_hash, init_hash },
98 { C::contract_instance_retrieval_immutables_hash, immutables_hash },
99 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
100 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
101 { C::contract_instance_retrieval_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
102 { C::contract_instance_retrieval_nullifier_merkle_separator, DOM_SEP__NULLIFIER_MERKLE },
103 { C::contract_instance_retrieval_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
104 { C::contract_instance_retrieval_nullifier_key_hash, nullifier_key_hash },
105 { C::contract_instance_retrieval_incoming_viewing_key_x, incoming_viewing_key_x },
106 { C::contract_instance_retrieval_incoming_viewing_key_y, incoming_viewing_key_y },
107 { C::contract_instance_retrieval_outgoing_viewing_key_hash, outgoing_viewing_key_hash },
108 { C::contract_instance_retrieval_tagging_key_hash, tagging_key_hash },
109 { C::contract_instance_retrieval_message_signing_key_hash, message_signing_key_hash },
110 { C::contract_instance_retrieval_fallback_key_hash, fallback_key_hash },
111 { C::contract_instance_retrieval_deployer_protocol_contract_address,
112 CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
113 // Protocol Contract conditionals
114 { C::contract_instance_retrieval_address_sub_one, contract_address - 1 },
115 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
116 { C::contract_instance_retrieval_derived_address, contract_address },
117 { C::contract_instance_retrieval_is_protocol_contract, 0 },
118 { C::contract_instance_retrieval_should_check_nullifier, 1 },
119 { C::contract_instance_retrieval_should_check_for_update, 1 } },
120 });
121
122 check_relation<contract_instance_retrieval>(trace);
123}
124
125TEST(ContractInstanceRetrievalConstrainingTest, MultipleInstancesTrace)
126{
127 // Test constants
128 const auto num_instances = 3;
129 const auto base_address = 0x1000;
130 const auto base_nullifier_tree_root = 0x2000;
131 const auto base_public_data_tree_root = 0x3000;
132 const auto base_salt = 100;
133
134 // Test multiple contract instances in sequence
136
137 // First row
138 trace_data.push_back({ { C::precomputed_first_row, 1 } });
139
140 // Create multiple instance rows
141 for (uint32_t i = 0; i < num_instances; i++) {
142 auto contract_instance = create_test_contract_instance(base_salt + i);
143
144 trace_data.push_back({
145 { C::contract_instance_retrieval_sel, 1 },
146 { C::contract_instance_retrieval_address, FF(base_address + i) },
147 { C::contract_instance_retrieval_exists, 1 },
148 { C::contract_instance_retrieval_salt, contract_instance.salt },
149 { C::contract_instance_retrieval_deployer_addr, contract_instance.deployer },
150 { C::contract_instance_retrieval_current_class_id, contract_instance.current_contract_class_id },
151 { C::contract_instance_retrieval_original_class_id, contract_instance.original_contract_class_id },
152 { C::contract_instance_retrieval_init_hash, contract_instance.initialization_hash },
153 { C::contract_instance_retrieval_immutables_hash, contract_instance.immutables_hash },
154 { C::contract_instance_retrieval_public_data_tree_root, FF(base_public_data_tree_root + i) },
155 { C::contract_instance_retrieval_nullifier_tree_root, FF(base_nullifier_tree_root + i) },
156 { C::contract_instance_retrieval_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
157 { C::contract_instance_retrieval_nullifier_merkle_separator, DOM_SEP__NULLIFIER_MERKLE },
158 { C::contract_instance_retrieval_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
159 { C::contract_instance_retrieval_nullifier_key_hash, contract_instance.public_keys.nullifier_key_hash },
160 { C::contract_instance_retrieval_incoming_viewing_key_x,
161 contract_instance.public_keys.incoming_viewing_key.x },
162 { C::contract_instance_retrieval_incoming_viewing_key_y,
163 contract_instance.public_keys.incoming_viewing_key.y },
164 { C::contract_instance_retrieval_outgoing_viewing_key_hash,
165 contract_instance.public_keys.outgoing_viewing_key_hash },
166 { C::contract_instance_retrieval_tagging_key_hash, contract_instance.public_keys.tagging_key_hash },
167 { C::contract_instance_retrieval_message_signing_key_hash,
168 contract_instance.public_keys.message_signing_key_hash },
169 { C::contract_instance_retrieval_fallback_key_hash, contract_instance.public_keys.fallback_key_hash },
170 { C::contract_instance_retrieval_deployer_protocol_contract_address,
171 CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
172 // Protocol Contract conditionals
173 { C::contract_instance_retrieval_address_sub_one, (base_address + i) - 1 },
174 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
175 { C::contract_instance_retrieval_derived_address, base_address + i },
176 { C::contract_instance_retrieval_is_protocol_contract, 0 },
177 { C::contract_instance_retrieval_should_check_nullifier, 1 },
178 { C::contract_instance_retrieval_should_check_for_update, 1 },
179 });
180 }
181
182 TestTraceContainer trace(trace_data);
183 check_relation<contract_instance_retrieval>(trace);
184}
185
186TEST(ContractInstanceRetrievalConstrainingTest, NonExistentInstanceTrace)
187{
188 // Test constants
189 const auto contract_address = FF(0x99999999);
190 const auto nullifier_tree_root = FF(0xffffff);
191 const auto public_data_tree_root = FF(0xeeeeee);
192 const auto exists = false;
193
194 // Test trace for non-existent contract instance
195 TestTraceContainer trace({
196 { { C::precomputed_first_row, 1 } },
197 { { C::contract_instance_retrieval_sel, 1 },
198 { C::contract_instance_retrieval_address, contract_address },
199 { C::contract_instance_retrieval_exists, exists ? 1 : 0 },
200 { C::contract_instance_retrieval_salt, 0 },
201 { C::contract_instance_retrieval_deployer_addr, 0 },
202 { C::contract_instance_retrieval_current_class_id, 0 },
203 { C::contract_instance_retrieval_original_class_id, 0 },
204 { C::contract_instance_retrieval_init_hash, 0 },
205 { C::contract_instance_retrieval_immutables_hash, 0 },
206 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
207 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
208 { C::contract_instance_retrieval_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
209 { C::contract_instance_retrieval_nullifier_merkle_separator, DOM_SEP__NULLIFIER_MERKLE },
210 { C::contract_instance_retrieval_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
211 { C::contract_instance_retrieval_deployer_protocol_contract_address,
212 CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
213 // Protocol Contract conditionals
214 { C::contract_instance_retrieval_address_sub_one, contract_address - 1 },
215 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
216 { C::contract_instance_retrieval_derived_address, contract_address },
217 { C::contract_instance_retrieval_is_protocol_contract, 0 },
218 { C::contract_instance_retrieval_should_check_nullifier, 1 },
219 { C::contract_instance_retrieval_should_check_for_update, 0 /*since exists = false*/ } },
220 });
221
222 check_relation<contract_instance_retrieval>(trace);
223
224 // mutate instance members to be nonzero and confirm that relation fails
225 // mutate deployer_addr
226 trace.set(C::contract_instance_retrieval_deployer_addr, 1, 1);
227 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
230 // reset
231 trace.set(C::contract_instance_retrieval_deployer_addr, 1, 0);
232 // mutate current_class_id
233 trace.set(C::contract_instance_retrieval_current_class_id, 1, 1);
234 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
237 // reset
238 trace.set(C::contract_instance_retrieval_current_class_id, 1, 0);
239 // mutate original_class_id
240 trace.set(C::contract_instance_retrieval_original_class_id, 1, 1);
241 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
244 // reset
245 trace.set(C::contract_instance_retrieval_original_class_id, 1, 0);
246 // mutate init_hash
247 trace.set(C::contract_instance_retrieval_init_hash, 1, 1);
248 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
251 // reset
252 trace.set(C::contract_instance_retrieval_init_hash, 1, 0);
253 // mutate immutables_hash
254 trace.set(C::contract_instance_retrieval_immutables_hash, 1, 1);
255 EXPECT_THROW_WITH_MESSAGE(check_relation<contract_instance_retrieval>(trace),
258 // reset
259 trace.set(C::contract_instance_retrieval_immutables_hash, 1, 0);
260}
261
262TEST(ContractInstanceRetrievalConstrainingTest, MaximumFieldValuesTrace)
263{
264 // Test constants
265 const auto max_field = FF(-1); // Maximum field value
266
267 // Test trace with maximum field values
268 TestTraceContainer trace({
269 { { C::precomputed_first_row, 1 } },
270 { { C::contract_instance_retrieval_sel, 1 },
271 { C::contract_instance_retrieval_address, max_field },
272 { C::contract_instance_retrieval_exists, 1 },
273 { C::contract_instance_retrieval_salt, max_field },
274 { C::contract_instance_retrieval_deployer_addr, max_field },
275 { C::contract_instance_retrieval_current_class_id, max_field },
276 { C::contract_instance_retrieval_original_class_id, max_field },
277 { C::contract_instance_retrieval_init_hash, max_field },
278 { C::contract_instance_retrieval_immutables_hash, max_field },
279 { C::contract_instance_retrieval_public_data_tree_root, max_field },
280 { C::contract_instance_retrieval_nullifier_tree_root, max_field },
281 { C::contract_instance_retrieval_nullifier_tree_height, NULLIFIER_TREE_HEIGHT },
282 { C::contract_instance_retrieval_nullifier_merkle_separator, DOM_SEP__NULLIFIER_MERKLE },
283 { C::contract_instance_retrieval_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
284 { C::contract_instance_retrieval_nullifier_key_hash, max_field },
285 { C::contract_instance_retrieval_incoming_viewing_key_x, max_field },
286 { C::contract_instance_retrieval_incoming_viewing_key_y, max_field },
287 { C::contract_instance_retrieval_outgoing_viewing_key_hash, max_field },
288 { C::contract_instance_retrieval_tagging_key_hash, max_field },
289 { C::contract_instance_retrieval_message_signing_key_hash, max_field },
290 { C::contract_instance_retrieval_fallback_key_hash, max_field },
291 { C::contract_instance_retrieval_deployer_protocol_contract_address,
292 CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
293 // Protocol Contract conditionals
294 { C::contract_instance_retrieval_address_sub_one, max_field - 1 },
295 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
296 { C::contract_instance_retrieval_derived_address, max_field },
297 { C::contract_instance_retrieval_is_protocol_contract, 0 },
298 { C::contract_instance_retrieval_should_check_nullifier, 1 },
299 { C::contract_instance_retrieval_should_check_for_update, 1 } },
300 });
301
302 check_relation<contract_instance_retrieval>(trace);
303}
304
305TEST(ContractInstanceRetrievalConstrainingTest, ProtocolContractInstanceExists)
306{
307 // Test constants
308 const AztecAddress contract_address = FEE_JUICE_ADDRESS;
309 const AztecAddress derived_address = FF(0xabcdef1234567890ULL);
310 const auto nullifier_tree_root = FF(0xbadc0ffeeULL);
311 const auto public_data_tree_root = FF(0xfacefeedUL);
312 ProtocolContracts protocol_contracts = {};
313 uint32_t protocol_contract_index = static_cast<uint32_t>(contract_address - 1);
314 protocol_contracts.derived_addresses[protocol_contract_index] = derived_address;
315
316 auto public_inputs = PublicInputsBuilder().set_protocol_contracts(protocol_contracts).build();
317
318 // Test complete valid trace with all constraints
319 TestTraceContainer trace({
320 {
321 { C::precomputed_first_row, 1 },
322 // Field Greater-Than Trace for Protocol Contract Address Check
323 { C::ff_gt_sel, 1 },
324 { C::ff_gt_sel_gt, 1 },
325 { C::ff_gt_a, MAX_PROTOCOL_CONTRACTS },
326 { C::ff_gt_b, contract_address - FF(1) },
327 { C::ff_gt_result, 1 },
328 },
329 {
330 // Contract Retrieval Instance Trace
331 { C::contract_instance_retrieval_sel, 1 },
332 { C::contract_instance_retrieval_address, contract_address },
333 { C::contract_instance_retrieval_exists, 1 },
334 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
335 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
336 { C::contract_instance_retrieval_deployer_protocol_contract_address,
337 CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
338 // Protocol Contract conditionals
339 { C::contract_instance_retrieval_derived_address_pi_index,
340 AVM_PUBLIC_INPUTS_PROTOCOL_CONTRACTS_ROW_IDX + protocol_contract_index },
341 { C::contract_instance_retrieval_protocol_contract_derived_address_inv, derived_address.invert() },
342 { C::contract_instance_retrieval_address_sub_one, contract_address - FF(1) },
343 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
344 { C::contract_instance_retrieval_derived_address, derived_address },
345 { C::contract_instance_retrieval_is_protocol_contract, 1 },
346 { C::contract_instance_retrieval_should_check_nullifier, 0 },
347 { C::contract_instance_retrieval_should_check_for_update, 0 },
348 },
349 });
350
351 PublicInputsTraceBuilder public_inputs_builder;
352 public_inputs_builder.process_public_inputs(trace, public_inputs);
353 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
354
355 tracegen::PrecomputedTraceBuilder precomputed_builder;
357
358 check_relation<contract_instance_retrieval>(trace);
359 check_interaction<ContractInstanceRetrievalTraceBuilder,
362}
363
364TEST(ContractInstanceRetrievalConstrainingTest, ProtocolContractInstanceNotExists)
365{
366 // Test constants
367 const AztecAddress contract_address = FEE_JUICE_ADDRESS;
368 const AztecAddress derived_address = FF(0);
369 const auto nullifier_tree_root = FF(0xbadc0ffeeULL);
370 const auto public_data_tree_root = FF(0xfacefeedUL);
371 uint32_t protocol_contract_index = static_cast<uint32_t>(contract_address - 1);
372 // Default protocol contracts: empty
373 auto public_inputs = PublicInputsBuilder().build();
374
375 // Test complete valid trace with all constraints
376 TestTraceContainer trace({
377 {
378 { C::precomputed_first_row, 1 },
379 // Field Greater-Than Trace for Protocol Contract Address Check
380 { C::ff_gt_sel, 1 },
381 { C::ff_gt_sel_gt, 1 },
382 { C::ff_gt_a, MAX_PROTOCOL_CONTRACTS },
383 { C::ff_gt_b, contract_address - FF(1) },
384 { C::ff_gt_result, 1 },
385 },
386 {
387 // Contract Retrieval Instance Trace
388 { C::contract_instance_retrieval_sel, 1 },
389 { C::contract_instance_retrieval_address, contract_address },
390 { C::contract_instance_retrieval_exists, 0 },
391 { C::contract_instance_retrieval_public_data_tree_root, public_data_tree_root },
392 { C::contract_instance_retrieval_nullifier_tree_root, nullifier_tree_root },
393 { C::contract_instance_retrieval_deployer_protocol_contract_address,
394 CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
395 // Protocol Contract conditionals
396 { C::contract_instance_retrieval_derived_address_pi_index,
397 AVM_PUBLIC_INPUTS_PROTOCOL_CONTRACTS_ROW_IDX + protocol_contract_index },
398 { C::contract_instance_retrieval_protocol_contract_derived_address_inv, 0 },
399 { C::contract_instance_retrieval_address_sub_one, contract_address - FF(1) },
400 { C::contract_instance_retrieval_max_protocol_contracts, MAX_PROTOCOL_CONTRACTS },
401 { C::contract_instance_retrieval_derived_address, derived_address },
402 { C::contract_instance_retrieval_is_protocol_contract, 1 },
403 { C::contract_instance_retrieval_should_check_nullifier, 0 },
404 { C::contract_instance_retrieval_should_check_for_update, 0 },
405 },
406 });
407
408 PublicInputsTraceBuilder public_inputs_builder;
409 public_inputs_builder.process_public_inputs(trace, public_inputs);
410 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
411
412 tracegen::PrecomputedTraceBuilder precomputed_builder;
414
415 check_relation<contract_instance_retrieval>(trace);
416 check_interaction<ContractInstanceRetrievalTraceBuilder,
419}
420
421// Integration-style tests using tracegen components
422TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenValidInstance)
423{
424 // Test constants
425 const auto contract_address = FF(0x1234567890abcdefULL);
426 const auto timestamp = 12345;
427 const auto nullifier_tree_root = FF(0xaabbccdd);
428 const auto public_data_tree_root = FF(0xeeff1122);
429 const auto deployment_nullifier = FF(0x7777);
430
431 // Use real tracegen to generate a valid trace
432 EventEmitter<ContractInstanceRetrievalEvent> emitter;
433 auto contract_instance = create_test_contract_instance();
434
435 ContractInstanceRetrievalEvent event = { .address = contract_address,
436 .contract_instance = contract_instance,
437 .nullifier_tree_root = nullifier_tree_root,
438 .public_data_tree_root = public_data_tree_root,
439 .deployment_nullifier = deployment_nullifier,
440 .exists = true,
441 .is_protocol_contract = false };
442
443 emitter.emit(std::move(event));
444 auto events = emitter.dump_events();
445
446 TestTraceContainer trace;
447 ContractInstanceRetrievalTraceBuilder builder;
448 builder.process(events, trace);
449
450 // Add precomputed table entries
451 PrecomputedTraceBuilder precomputed_builder;
455
456 // Manually populate destination tables for lookup interactions
457 auto contract_instance_data = create_test_contract_instance();
458
459 trace.set(
460 1,
461 { { // For deployment nullifier lookup
462 { C::indexed_tree_check_sel, 1 },
463 { C::indexed_tree_check_exists, 1 },
464 { C::indexed_tree_check_value, contract_address },
465 { C::indexed_tree_check_root, nullifier_tree_root },
466 { C::indexed_tree_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
467 { C::indexed_tree_check_sel_silo, 1 },
468 { C::indexed_tree_check_tree_height, NULLIFIER_TREE_HEIGHT },
469 { C::indexed_tree_check_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
470 { C::indexed_tree_check_merkle_hash_separator, DOM_SEP__NULLIFIER_MERKLE },
471 // For address derivation lookup
472 { C::address_derivation_sel, 1 },
473 { C::address_derivation_address, contract_address },
474 { C::address_derivation_salt, contract_instance_data.salt },
475 { C::address_derivation_deployer_addr, contract_instance_data.deployer },
476 { C::address_derivation_class_id, contract_instance_data.original_contract_class_id },
477 { C::address_derivation_init_hash, contract_instance_data.initialization_hash },
478 { C::address_derivation_immutables_hash, contract_instance_data.immutables_hash },
479 { C::address_derivation_nullifier_key_hash, contract_instance_data.public_keys.nullifier_key_hash },
480 { C::address_derivation_incoming_viewing_key_x, contract_instance_data.public_keys.incoming_viewing_key.x },
481 { C::address_derivation_incoming_viewing_key_y, contract_instance_data.public_keys.incoming_viewing_key.y },
482 { C::address_derivation_outgoing_viewing_key_hash,
483 contract_instance_data.public_keys.outgoing_viewing_key_hash },
484 { C::address_derivation_tagging_key_hash, contract_instance_data.public_keys.tagging_key_hash },
485 { C::address_derivation_message_signing_key_hash,
486 contract_instance_data.public_keys.message_signing_key_hash },
487 { C::address_derivation_fallback_key_hash, contract_instance_data.public_keys.fallback_key_hash },
488 // For update check lookup
489 { C::update_check_sel, 1 },
490 { C::update_check_address, contract_address },
491 { C::update_check_current_class_id, contract_instance_data.current_contract_class_id },
492 { C::update_check_original_class_id, contract_instance_data.original_contract_class_id },
493 { C::update_check_public_data_tree_root, public_data_tree_root },
494 { C::update_check_timestamp, timestamp },
495 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
496
497 check_relation<contract_instance_retrieval>(trace);
498
499 // Test lookup interactions
500 check_interaction<ContractInstanceRetrievalTraceBuilder,
502 check_interaction<ContractInstanceRetrievalTraceBuilder,
504 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
505 trace);
506}
507
508TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenNonExistentInstance)
509{
510 // Test constants
511 const auto contract_address = FF(0x999999999ULL);
512 const auto timestamp = 99999;
513 const auto nullifier_tree_root = FF(0xffffff);
514 const auto public_data_tree_root = FF(0xeeeeee);
515 const auto deployment_nullifier = FF(0x8888);
516
517 // Use real tracegen to generate a valid trace for non-existent instance
518 EventEmitter<ContractInstanceRetrievalEvent> emitter;
519
520 ContractInstanceRetrievalEvent event{ .address = contract_address,
521 .contract_instance = {}, // no instance, DNE
522 .nullifier_tree_root = nullifier_tree_root,
523 .public_data_tree_root = public_data_tree_root,
524 .deployment_nullifier = deployment_nullifier,
525 .exists = false, // Non-existent
526 .is_protocol_contract = false };
527
528 emitter.emit(std::move(event));
529 auto events = emitter.dump_events();
530
531 TestTraceContainer trace;
532 ContractInstanceRetrievalTraceBuilder builder;
533 builder.process(events, trace);
534
535 // Add precomputed table entries
536 PrecomputedTraceBuilder precomputed_builder;
540
541 trace.set(1,
542 { { // For deployment nullifier read lookup
543 { C::indexed_tree_check_sel, 1 },
544 { C::indexed_tree_check_exists, 0 }, // Non-existent
545 { C::indexed_tree_check_value, contract_address },
546 { C::indexed_tree_check_root, nullifier_tree_root },
547 { C::indexed_tree_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
548 { C::indexed_tree_check_sel_silo, 1 },
549 { C::indexed_tree_check_tree_height, NULLIFIER_TREE_HEIGHT },
550 { C::indexed_tree_check_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
551 { C::indexed_tree_check_merkle_hash_separator, DOM_SEP__NULLIFIER_MERKLE },
552 // For address derivation lookup
553 { C::address_derivation_sel, 0 }, // Not selected since nullifier doesn't exist
554 { C::address_derivation_address, contract_address },
555 { C::address_derivation_salt, 0 }, // zero since nullifier doesn't exist
556 { C::address_derivation_deployer_addr, 0 }, // zero since nullifier doesn't exist
557 { C::address_derivation_class_id, 0 }, // zero since nullifier doesn't exist
558 { C::address_derivation_init_hash, 0 }, // zero since nullifier doesn't exist
559 { C::address_derivation_immutables_hash, 0 }, // zero since nullifier doesn't exist
560 { C::address_derivation_nullifier_key_hash, 0 },
561 { C::address_derivation_incoming_viewing_key_x, 0 },
562 { C::address_derivation_incoming_viewing_key_y, 0 },
563 { C::address_derivation_outgoing_viewing_key_hash, 0 },
564 { C::address_derivation_tagging_key_hash, 0 },
565 { C::address_derivation_message_signing_key_hash, 0 },
566 { C::address_derivation_fallback_key_hash, 0 },
567 // For update check lookup (only populated when nullifier exists)
568 { C::update_check_sel, 0 }, // Not selected since nullifier doesn't exist
569 { C::update_check_address, contract_address },
570 { C::update_check_current_class_id, 0 },
571 { C::update_check_original_class_id, 0 },
572 { C::update_check_public_data_tree_root, public_data_tree_root },
573 { C::update_check_timestamp, timestamp },
574 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
575
576 check_relation<contract_instance_retrieval>(trace);
577
578 // Test lookup interactions
579 check_interaction<ContractInstanceRetrievalTraceBuilder,
581 check_interaction<ContractInstanceRetrievalTraceBuilder,
583 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
584 trace);
585}
586
587TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenAddressZero)
588{
589 // Test constants
590 const auto contract_address = FF(0);
591 const auto timestamp = 99999;
592 const auto nullifier_tree_root = FF(0xffffff);
593 const auto public_data_tree_root = FF(0xeeeeee);
594 const auto deployment_nullifier = FF(0x8888);
595
596 // Use real tracegen to generate a valid trace for non-existent instance
597 EventEmitter<ContractInstanceRetrievalEvent> emitter;
598
599 ContractInstanceRetrievalEvent event{
600 .address = contract_address,
601 .contract_instance = {}, // no instance, DNE
602 .nullifier_tree_root = nullifier_tree_root,
603 .public_data_tree_root = public_data_tree_root,
604 .deployment_nullifier = deployment_nullifier,
605 .exists = false, // Non-existent
606 .is_protocol_contract = false, // Not a protocol contract, since MAX_PROTOCOL_CONTRACTS < (0 - 1)
607 };
608
609 emitter.emit(std::move(event));
610 auto events = emitter.dump_events();
611
612 TestTraceContainer trace;
613 ContractInstanceRetrievalTraceBuilder builder;
614 builder.process(events, trace);
615
616 // Add precomputed table entries
617 PrecomputedTraceBuilder precomputed_builder;
621
622 trace.set(1,
623 { { // For deployment nullifier read lookup
624 { C::indexed_tree_check_sel, 1 },
625 { C::indexed_tree_check_exists, 0 }, // Non-existent
626 { C::indexed_tree_check_value, contract_address },
627 { C::indexed_tree_check_root, nullifier_tree_root },
628 { C::indexed_tree_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
629 { C::indexed_tree_check_sel_silo, 1 },
630 { C::indexed_tree_check_tree_height, NULLIFIER_TREE_HEIGHT },
631 { C::indexed_tree_check_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
632 { C::indexed_tree_check_merkle_hash_separator, DOM_SEP__NULLIFIER_MERKLE },
633 // For address derivation lookup
634 { C::address_derivation_sel, 0 }, // Not selected since nullifier doesn't exist
635 { C::address_derivation_address, contract_address },
636 { C::address_derivation_salt, 0 }, // zero since nullifier doesn't exist
637 { C::address_derivation_deployer_addr, 0 }, // zero since nullifier doesn't exist
638 { C::address_derivation_class_id, 0 }, // zero since nullifier doesn't exist
639 { C::address_derivation_init_hash, 0 }, // zero since nullifier doesn't exist
640 { C::address_derivation_immutables_hash, 0 }, // zero since nullifier doesn't exist
641 { C::address_derivation_nullifier_key_hash, 0 },
642 { C::address_derivation_incoming_viewing_key_x, 0 },
643 { C::address_derivation_incoming_viewing_key_y, 0 },
644 { C::address_derivation_outgoing_viewing_key_hash, 0 },
645 { C::address_derivation_tagging_key_hash, 0 },
646 { C::address_derivation_message_signing_key_hash, 0 },
647 { C::address_derivation_fallback_key_hash, 0 },
648 // For update check lookup (only populated when nullifier exists)
649 { C::update_check_sel, 0 }, // Not selected since nullifier doesn't exist
650 { C::update_check_address, contract_address },
651 { C::update_check_current_class_id, 0 },
652 { C::update_check_original_class_id, 0 },
653 { C::update_check_public_data_tree_root, public_data_tree_root },
654 { C::update_check_timestamp, timestamp },
655 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
656
657 check_relation<contract_instance_retrieval>(trace);
658
659 // Test lookup interactions
660 check_interaction<ContractInstanceRetrievalTraceBuilder,
662 check_interaction<ContractInstanceRetrievalTraceBuilder,
664 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
665 trace);
666}
667
668TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenMultipleInstances)
669{
670 // Test constants
671 const auto num_instances = 3;
672 const auto base_address = 0x1000;
673 const auto base_timestamp = 1000;
674 const auto base_nullifier_tree_root = 0x2000;
675 const auto base_public_data_tree_root = 0x3000;
676 const auto base_salt = 100;
677
678 // Use real tracegen to generate multiple instances
679 EventEmitter<ContractInstanceRetrievalEvent> emitter;
680
681 for (uint32_t i = 0; i < num_instances; i++) {
682 auto contract_instance = create_test_contract_instance(base_salt + i);
683
684 ContractInstanceRetrievalEvent event = { .address = FF(base_address + i),
685 .contract_instance = contract_instance,
686 .nullifier_tree_root = FF(base_nullifier_tree_root + i),
687 .public_data_tree_root = FF(base_public_data_tree_root + i),
688 .deployment_nullifier = FF(base_address + i),
689 .exists = true,
690 .is_protocol_contract = false };
691
692 emitter.emit(std::move(event));
693 }
694
695 auto events = emitter.dump_events();
696
697 TestTraceContainer trace;
698 ContractInstanceRetrievalTraceBuilder builder;
699 builder.process(events, trace);
700
701 // Add precomputed table entries
702 PrecomputedTraceBuilder precomputed_builder;
706
707 // Manually populate destination tables for lookup interactions
708 for (uint32_t i = 0; i < num_instances; i++) {
709 auto contract_instance_data = create_test_contract_instance(base_salt + i);
710 uint32_t row = i + 1; // Skip row 0 (skippable gadget)
711
712 trace.set(
713 row, // For deployment nullifier read lookup
714 { { { C::indexed_tree_check_sel, 1 },
715 { C::indexed_tree_check_exists, true },
716 { C::indexed_tree_check_value, FF(base_address + i) },
717 { C::indexed_tree_check_root, FF(base_nullifier_tree_root + i) },
718 { C::indexed_tree_check_address, CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
719 { C::indexed_tree_check_sel_silo, 1 },
720 { C::indexed_tree_check_tree_height, NULLIFIER_TREE_HEIGHT },
721 { C::indexed_tree_check_siloing_separator, DOM_SEP__SILOED_NULLIFIER },
722 { C::indexed_tree_check_merkle_hash_separator, DOM_SEP__NULLIFIER_MERKLE },
723 // For address derivation lookup (only when nullifier exists)
724 { C::address_derivation_sel, 1 },
725 { C::address_derivation_address, FF(base_address + i) },
726 { C::address_derivation_salt, contract_instance_data.salt },
727 { C::address_derivation_deployer_addr, contract_instance_data.deployer },
728 { C::address_derivation_class_id, contract_instance_data.original_contract_class_id },
729 { C::address_derivation_init_hash, contract_instance_data.initialization_hash },
730 { C::address_derivation_immutables_hash, contract_instance_data.immutables_hash },
731 { C::address_derivation_nullifier_key_hash, contract_instance_data.public_keys.nullifier_key_hash },
732 { C::address_derivation_incoming_viewing_key_x,
733 contract_instance_data.public_keys.incoming_viewing_key.x },
734 { C::address_derivation_incoming_viewing_key_y,
735 contract_instance_data.public_keys.incoming_viewing_key.y },
736 { C::address_derivation_outgoing_viewing_key_hash,
737 contract_instance_data.public_keys.outgoing_viewing_key_hash },
738 { C::address_derivation_tagging_key_hash, contract_instance_data.public_keys.tagging_key_hash },
739 { C::address_derivation_message_signing_key_hash,
740 contract_instance_data.public_keys.message_signing_key_hash },
741 { C::address_derivation_fallback_key_hash, contract_instance_data.public_keys.fallback_key_hash },
742 // For update check lookup (only when nullifier exists)
743 { C::update_check_sel, 1 },
744 { C::update_check_address, FF(base_address + i) },
745 { C::update_check_current_class_id, contract_instance_data.current_contract_class_id },
746 { C::update_check_original_class_id, contract_instance_data.original_contract_class_id },
747 { C::update_check_public_data_tree_root, FF(base_public_data_tree_root + i) },
748 { C::update_check_timestamp, base_timestamp + i },
749 { C::update_check_timestamp_pi_offset, AVM_PUBLIC_INPUTS_GLOBAL_VARIABLES_TIMESTAMP_ROW_IDX } } });
750 }
751
752 check_relation<contract_instance_retrieval>(trace);
753
754 // Test lookup interactions
755 check_interaction<ContractInstanceRetrievalTraceBuilder,
757 check_interaction<ContractInstanceRetrievalTraceBuilder,
759 check_interaction<ContractInstanceRetrievalTraceBuilder, lookup_contract_instance_retrieval_update_check_settings>(
760 trace);
761}
762
763} // namespace
764} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:224
static constexpr size_t SR_INSTANCE_MEMBER_IMMUTABLES_HASH_IS_ZERO_IF_DNE
static constexpr size_t SR_INSTANCE_MEMBER_CLASS_ID_IS_ZERO_IF_DNE
static std::string get_subrelation_label(size_t index)
static constexpr size_t SR_INSTANCE_MEMBER_INIT_HASH_IS_ZERO_IF_DNE
static constexpr size_t SR_INSTANCE_MEMBER_DEPLOYER_IS_ZERO_IF_DNE
static constexpr size_t SR_INSTANCE_MEMBER_ORIGINAL_CLASS_ID_IS_ZERO_IF_DNE
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, bool use_atomic_limbs=false)
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:156
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:84