Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
program_block.cpp
Go to the documentation of this file.
11
13{
14 if (resolved_address.base_pointer.has_value()) {
16 .operand(static_cast<uint16_t>(0))
18 .operand(resolved_address.base_pointer.value())
19 .build();
20 instructions.push_back(set_base_offset_instruction);
22 }
23 if (resolved_address.pointer_address.has_value()) {
24 if (resolved_address.base_pointer.has_value()) {
25 // Indirect relative: Write the pointer in a relative manner
27 .operand(static_cast<uint16_t>(resolved_address.pointer_address.value() -
28 resolved_address.base_pointer.value()))
29 .relative()
31 .operand(resolved_address.absolute_address)
32 .build();
33 instructions.push_back(set_pointer_instruction);
34 } else {
35 // Indirect: Write the pointer directly
37 .operand(static_cast<uint16_t>(resolved_address.pointer_address.value()))
39 .operand(resolved_address.absolute_address)
40 .build();
41 instructions.push_back(set_pointer_instruction);
42 }
43
45 }
46}
47
50{
51 for (const auto& param : params) {
52 auto tag =
53 std::visit(overloaded{ [](const VariableRef& var) -> std::optional<MemoryTag> { return var.tag.value; },
54 [](const AddressRef&) -> std::optional<MemoryTag> { return std::nullopt; } },
55 param);
56 if (tag.has_value()) {
57 memory_manager.set_memory_address(tag.value(), result_address.absolute_address);
58 return;
59 }
60 }
61}
62
64{
65#ifdef DISABLE_ADD_8_INSTRUCTION
66 return;
67#endif
71 if (!a.has_value() || !b.has_value() || !result.has_value()) {
72 return;
73 }
74 preprocess_memory_addresses(a.value().first);
75 preprocess_memory_addresses(b.value().first);
76 preprocess_memory_addresses(result.value().first);
77
79 .operand(a.value().second)
80 .operand(b.value().second)
81 .operand(result.value().second)
82 .build();
83 instructions.push_back(add_8_instruction);
84 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
85}
86
88{
89#ifdef DISABLE_SUB_8_INSTRUCTION
90 return;
91#endif
95 if (!a.has_value() || !b.has_value() || !result.has_value()) {
96 return;
97 }
98 preprocess_memory_addresses(a.value().first);
99 preprocess_memory_addresses(b.value().first);
100 preprocess_memory_addresses(result.value().first);
102 .operand(a.value().second)
103 .operand(b.value().second)
104 .operand(result.value().second)
105 .build();
106 instructions.push_back(sub_8_instruction);
107 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
108}
109
111{
112#ifdef DISABLE_MUL_8_INSTRUCTION
113 return;
114#endif
118 if (!a.has_value() || !b.has_value() || !result.has_value()) {
119 return;
120 }
121 preprocess_memory_addresses(a.value().first);
122 preprocess_memory_addresses(b.value().first);
123 preprocess_memory_addresses(result.value().first);
125 .operand(a.value().second)
126 .operand(b.value().second)
127 .operand(result.value().second)
128 .build();
129 instructions.push_back(mul_8_instruction);
130 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
131}
132
134{
135#ifdef DISABLE_DIV_8_INSTRUCTION
136 return;
137#endif
141 if (!a.has_value() || !b.has_value() || !result.has_value()) {
142 return;
143 }
144 preprocess_memory_addresses(a.value().first);
145 preprocess_memory_addresses(b.value().first);
146 preprocess_memory_addresses(result.value().first);
148 .operand(a.value().second)
149 .operand(b.value().second)
150 .operand(result.value().second)
151 .build();
152 instructions.push_back(div_8_instruction);
153 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
154}
155
157{
158#ifdef DISABLE_EQ_8_INSTRUCTION
159 return;
160#endif
164 if (!a.has_value() || !b.has_value() || !result.has_value()) {
165 return;
166 }
167 preprocess_memory_addresses(a.value().first);
168 preprocess_memory_addresses(b.value().first);
169 preprocess_memory_addresses(result.value().first);
171 .operand(a.value().second)
172 .operand(b.value().second)
173 .operand(result.value().second)
174 .build();
175 instructions.push_back(eq_8_instruction);
176 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address);
177}
178
180{
181#ifdef DISABLE_LT_8_INSTRUCTION
182 return;
183#endif
187 if (!a.has_value() || !b.has_value() || !result.has_value()) {
188 return;
189 }
190 preprocess_memory_addresses(a.value().first);
191 preprocess_memory_addresses(b.value().first);
192 preprocess_memory_addresses(result.value().first);
194 .operand(a.value().second)
195 .operand(b.value().second)
196 .operand(result.value().second)
197 .build();
198 instructions.push_back(lt_8_instruction);
199 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address);
200}
201
203{
204#ifdef DISABLE_LTE_8_INSTRUCTION
205 return;
206#endif
210 if (!a.has_value() || !b.has_value() || !result.has_value()) {
211 return;
212 }
213 preprocess_memory_addresses(a.value().first);
214 preprocess_memory_addresses(b.value().first);
215 preprocess_memory_addresses(result.value().first);
217 .operand(a.value().second)
218 .operand(b.value().second)
219 .operand(result.value().second)
220 .build();
221 instructions.push_back(lte_8_instruction);
222 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address);
223}
224
226{
227#ifdef DISABLE_AND_8_INSTRUCTION
228 return;
229#endif
233 if (!a.has_value() || !b.has_value() || !result.has_value()) {
234 return;
235 }
236
237 preprocess_memory_addresses(a.value().first);
238 preprocess_memory_addresses(b.value().first);
239 preprocess_memory_addresses(result.value().first);
241 .operand(a.value().second)
242 .operand(b.value().second)
243 .operand(result.value().second)
244 .build();
245 instructions.push_back(and_8_instruction);
246 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
247}
248
250{
251#ifdef DISABLE_OR_8_INSTRUCTION
252 return;
253#endif
257 if (!a.has_value() || !b.has_value() || !result.has_value()) {
258 return;
259 }
260
261 preprocess_memory_addresses(a.value().first);
262 preprocess_memory_addresses(b.value().first);
263 preprocess_memory_addresses(result.value().first);
265 .operand(a.value().second)
266 .operand(b.value().second)
267 .operand(result.value().second)
268 .build();
269 instructions.push_back(or_8_instruction);
270 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
271}
272
274{
275#ifdef DISABLE_XOR_8_INSTRUCTION
276 return;
277#endif
281 if (!a.has_value() || !b.has_value() || !result.has_value()) {
282 return;
283 }
284
285 preprocess_memory_addresses(a.value().first);
286 preprocess_memory_addresses(b.value().first);
287 preprocess_memory_addresses(result.value().first);
289 .operand(a.value().second)
290 .operand(b.value().second)
291 .operand(result.value().second)
292 .build();
293 instructions.push_back(xor_8_instruction);
294 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
295}
296
298{
299#ifdef DISABLE_SHL_8_INSTRUCTION
300 return;
301#endif
305 if (!a.has_value() || !b.has_value() || !result.has_value()) {
306 return;
307 }
308
309 preprocess_memory_addresses(a.value().first);
310 preprocess_memory_addresses(b.value().first);
311 preprocess_memory_addresses(result.value().first);
313 .operand(a.value().second)
314 .operand(b.value().second)
315 .operand(result.value().second)
316 .build();
317 instructions.push_back(shl_8_instruction);
318 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
319}
320
322{
323#ifdef DISABLE_SHR_8_INSTRUCTION
324 return;
325#endif
329 if (!a.has_value() || !b.has_value() || !result.has_value()) {
330 return;
331 }
332
333 preprocess_memory_addresses(a.value().first);
334 preprocess_memory_addresses(b.value().first);
335 preprocess_memory_addresses(result.value().first);
337 .operand(a.value().second)
338 .operand(b.value().second)
339 .operand(result.value().second)
340 .build();
341 instructions.push_back(shr_8_instruction);
342 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
343}
344
346{
347#ifdef DISABLE_SET_8_INSTRUCTION
348 return;
349#endif
350 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
351 if (!effective_address_operand.has_value()) {
352 return;
353 }
354 preprocess_memory_addresses(effective_address_operand.value().first);
356 .operand(effective_address_operand.value().second)
357 .operand(instruction.value_tag.value)
358 .operand(instruction.value)
359 .build());
361 effective_address_operand.value().first.absolute_address);
362}
363
365{
366#ifdef DISABLE_SET_16_INSTRUCTION
367 return;
368#endif
369 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
370 if (!effective_address_operand.has_value()) {
371 return;
372 }
373 preprocess_memory_addresses(effective_address_operand.value().first);
375 .operand(effective_address_operand.value().second)
376 .operand(instruction.value_tag.value)
377 .operand(instruction.value)
378 .build());
380 effective_address_operand.value().first.absolute_address);
381}
382
384{
385#ifdef DISABLE_SET_32_INSTRUCTION
386 return;
387#endif
388 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
389 if (!effective_address_operand.has_value()) {
390 return;
391 }
392 preprocess_memory_addresses(effective_address_operand.value().first);
394 .operand(effective_address_operand.value().second)
395 .operand(instruction.value_tag.value)
396 .operand(instruction.value)
397 .build());
399 effective_address_operand.value().first.absolute_address);
400}
401
403{
404#ifdef DISABLE_SET_64_INSTRUCTION
405 return;
406#endif
407 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
408 if (!effective_address_operand.has_value()) {
409 return;
410 }
411 preprocess_memory_addresses(effective_address_operand.value().first);
413 .operand(effective_address_operand.value().second)
414 .operand(instruction.value_tag.value)
415 .operand(instruction.value)
416 .build());
418 effective_address_operand.value().first.absolute_address);
419}
420
422{
423#ifdef DISABLE_SET_128_INSTRUCTION
424 return;
425#endif
426 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
427 if (!effective_address_operand.has_value()) {
428 return;
429 }
431 (static_cast<uint128_t>(instruction.value_high) << 64) | static_cast<uint128_t>(instruction.value_low);
432 preprocess_memory_addresses(effective_address_operand.value().first);
434 .operand(effective_address_operand.value().second)
435 .operand(instruction.value_tag.value)
436 .operand(value)
437 .build());
439 effective_address_operand.value().first.absolute_address);
440}
441
443{
444#ifdef DISABLE_SET_FF_INSTRUCTION
445 return;
446#endif
447 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
448 if (!effective_address_operand.has_value()) {
449 return;
450 }
451 preprocess_memory_addresses(effective_address_operand.value().first);
453 .operand(effective_address_operand.value().second)
454 .operand(instruction.value_tag.value)
455 .operand(instruction.value)
456 .build());
458 effective_address_operand.value().first.absolute_address);
459}
460
462{
463#ifdef DISABLE_MOV_8_INSTRUCTION
464 return;
465#endif
466 auto src_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.src_address);
467 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
468 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
469 return;
470 }
471 preprocess_memory_addresses(src_address_operand.value().first);
472 preprocess_memory_addresses(result_address_operand.value().first);
474 .operand(src_address_operand.value().second)
475 .operand(result_address_operand.value().second)
476 .build();
477 instructions.push_back(mov_8_instruction);
478 record_result_tag_from_param_tags({ instruction.src_address }, result_address_operand.value().first);
479}
480
482{
483#ifdef DISABLE_MOV_16_INSTRUCTION
484 return;
485#endif
486 auto src_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.src_address);
487 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
488 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
489 return;
490 }
491
492 preprocess_memory_addresses(src_address_operand.value().first);
493 preprocess_memory_addresses(result_address_operand.value().first);
495 .operand(src_address_operand.value().second)
496 .operand(result_address_operand.value().second)
497 .build();
498 instructions.push_back(mov_16_instruction);
499 record_result_tag_from_param_tags({ instruction.src_address }, result_address_operand.value().first);
500}
501
503{
504#ifdef DISABLE_FDIV_8_INSTRUCTION
505 return;
506#endif
507 auto a_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.a_address);
508 auto b_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.b_address);
509 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
510 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
511 return;
512 }
513
514 preprocess_memory_addresses(a_address_operand.value().first);
515 preprocess_memory_addresses(b_address_operand.value().first);
516 preprocess_memory_addresses(result_address_operand.value().first);
518 .operand(a_address_operand.value().second)
519 .operand(b_address_operand.value().second)
520 .operand(result_address_operand.value().second)
521 .build();
522 instructions.push_back(fdiv_8_instruction);
524 result_address_operand.value().first);
525}
526
528{
529#ifdef DISABLE_NOT_8_INSTRUCTION
530 return;
531#endif
532 auto a_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.a_address);
533 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
534 if (!a_address_operand.has_value() || !result_address_operand.has_value()) {
535 return;
536 }
537
538 preprocess_memory_addresses(a_address_operand.value().first);
539 preprocess_memory_addresses(result_address_operand.value().first);
541 .operand(a_address_operand.value().second)
542 .operand(result_address_operand.value().second)
543 .build();
544 instructions.push_back(not_8_instruction);
545 record_result_tag_from_param_tags({ instruction.a_address }, result_address_operand.value().first);
546}
547
549{
550#ifdef DISABLE_ADD_16_INSTRUCTION
551 return;
552#endif
553 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
554 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
555 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
556 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
557 return;
558 }
559
560 preprocess_memory_addresses(a_address_operand.value().first);
561 preprocess_memory_addresses(b_address_operand.value().first);
562 preprocess_memory_addresses(result_address_operand.value().first);
564 .operand(a_address_operand.value().second)
565 .operand(b_address_operand.value().second)
566 .operand(result_address_operand.value().second)
567 .build();
568 instructions.push_back(add_16_instruction);
570 result_address_operand.value().first);
571}
572
574{
575#ifdef DISABLE_SUB_16_INSTRUCTION
576 return;
577#endif
578 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
579 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
580 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
581 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
582 return;
583 }
584
585 preprocess_memory_addresses(a_address_operand.value().first);
586 preprocess_memory_addresses(b_address_operand.value().first);
587 preprocess_memory_addresses(result_address_operand.value().first);
589 .operand(a_address_operand.value().second)
590 .operand(b_address_operand.value().second)
591 .operand(result_address_operand.value().second)
592 .build();
593 instructions.push_back(sub_16_instruction);
595 result_address_operand.value().first);
596}
597
599{
600#ifdef DISABLE_MUL_16_INSTRUCTION
601 return;
602#endif
603 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
604 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
605 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
606 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
607 return;
608 }
609
610 preprocess_memory_addresses(a_address_operand.value().first);
611 preprocess_memory_addresses(b_address_operand.value().first);
612 preprocess_memory_addresses(result_address_operand.value().first);
614 .operand(a_address_operand.value().second)
615 .operand(b_address_operand.value().second)
616 .operand(result_address_operand.value().second)
617 .build();
618 instructions.push_back(mul_16_instruction);
620 result_address_operand.value().first);
621}
622
624{
625#ifdef DISABLE_DIV_16_INSTRUCTION
626 return;
627#endif
628 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
629 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
630 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
631 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
632 return;
633 }
634
635 preprocess_memory_addresses(a_address_operand.value().first);
636 preprocess_memory_addresses(b_address_operand.value().first);
637 preprocess_memory_addresses(result_address_operand.value().first);
639 .operand(a_address_operand.value().second)
640 .operand(b_address_operand.value().second)
641 .operand(result_address_operand.value().second)
642 .build();
643 instructions.push_back(div_16_instruction);
645 result_address_operand.value().first);
646}
647
649{
650#ifdef DISABLE_FDIV_16_INSTRUCTION
651 return;
652#endif
653 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
654 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
655 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
656 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
657 return;
658 }
659
660 preprocess_memory_addresses(a_address_operand.value().first);
661 preprocess_memory_addresses(b_address_operand.value().first);
662 preprocess_memory_addresses(result_address_operand.value().first);
664 .operand(a_address_operand.value().second)
665 .operand(b_address_operand.value().second)
666 .operand(result_address_operand.value().second)
667 .build();
668 instructions.push_back(fdiv_16_instruction);
670 result_address_operand.value().first);
671}
672
674{
675#ifdef DISABLE_EQ_16_INSTRUCTION
676 return;
677#endif
678 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
679 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
680 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
681 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
682 return;
683 }
684
685 preprocess_memory_addresses(a_address_operand.value().first);
686 preprocess_memory_addresses(b_address_operand.value().first);
687 preprocess_memory_addresses(result_address_operand.value().first);
689 .operand(a_address_operand.value().second)
690 .operand(b_address_operand.value().second)
691 .operand(result_address_operand.value().second)
692 .build();
693 instructions.push_back(eq_16_instruction);
694 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
695}
696
698{
699#ifdef DISABLE_LT_16_INSTRUCTION
700 return;
701#endif
702 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
703 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
704 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
705 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
706 return;
707 }
708
709 preprocess_memory_addresses(a_address_operand.value().first);
710 preprocess_memory_addresses(b_address_operand.value().first);
711 preprocess_memory_addresses(result_address_operand.value().first);
713 .operand(a_address_operand.value().second)
714 .operand(b_address_operand.value().second)
715 .operand(result_address_operand.value().second)
716 .build();
717 instructions.push_back(lt_16_instruction);
718 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
719}
720
722{
723#ifdef DISABLE_LTE_16_INSTRUCTION
724 return;
725#endif
726 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
727 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
728 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
729 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
730 return;
731 }
732
733 preprocess_memory_addresses(a_address_operand.value().first);
734 preprocess_memory_addresses(b_address_operand.value().first);
735 preprocess_memory_addresses(result_address_operand.value().first);
737 .operand(a_address_operand.value().second)
738 .operand(b_address_operand.value().second)
739 .operand(result_address_operand.value().second)
740 .build();
741 instructions.push_back(lte_16_instruction);
742 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
743}
744
746{
747#ifdef DISABLE_AND_16_INSTRUCTION
748 return;
749#endif
750 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
751 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
752 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
753 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
754 return;
755 }
756
757 preprocess_memory_addresses(a_address_operand.value().first);
758 preprocess_memory_addresses(b_address_operand.value().first);
759 preprocess_memory_addresses(result_address_operand.value().first);
761 .operand(a_address_operand.value().second)
762 .operand(b_address_operand.value().second)
763 .operand(result_address_operand.value().second)
764 .build();
765 instructions.push_back(and_16_instruction);
767 result_address_operand.value().first);
768}
769
771{
772#ifdef DISABLE_OR_16_INSTRUCTION
773 return;
774#endif
775 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
776 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
777 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
778 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
779 return;
780 }
781
782 preprocess_memory_addresses(a_address_operand.value().first);
783 preprocess_memory_addresses(b_address_operand.value().first);
784 preprocess_memory_addresses(result_address_operand.value().first);
786 .operand(a_address_operand.value().second)
787 .operand(b_address_operand.value().second)
788 .operand(result_address_operand.value().second)
789 .build();
790 instructions.push_back(or_16_instruction);
792 result_address_operand.value().first);
793}
794
796{
797#ifdef DISABLE_XOR_16_INSTRUCTION
798 return;
799#endif
800 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
801 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
802 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
803 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
804 return;
805 }
806
807 preprocess_memory_addresses(a_address_operand.value().first);
808 preprocess_memory_addresses(b_address_operand.value().first);
809 preprocess_memory_addresses(result_address_operand.value().first);
811 .operand(a_address_operand.value().second)
812 .operand(b_address_operand.value().second)
813 .operand(result_address_operand.value().second)
814 .build();
815 instructions.push_back(xor_16_instruction);
817 result_address_operand.value().first);
818}
819
821{
822#ifdef DISABLE_NOT_16_INSTRUCTION
823 return;
824#endif
825 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
826 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
827 if (!a_address_operand.has_value() || !result_address_operand.has_value()) {
828 return;
829 }
830
831 preprocess_memory_addresses(a_address_operand.value().first);
832 preprocess_memory_addresses(result_address_operand.value().first);
834 .operand(a_address_operand.value().second)
835 .operand(result_address_operand.value().second)
836 .build();
837 instructions.push_back(not_16_instruction);
838 record_result_tag_from_param_tags({ instruction.a_address }, result_address_operand.value().first);
839}
840
842{
843#ifdef DISABLE_SHL_16_INSTRUCTION
844 return;
845#endif
846 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
847 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
848 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
849 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
850 return;
851 }
852 preprocess_memory_addresses(a_address_operand.value().first);
853 preprocess_memory_addresses(b_address_operand.value().first);
854 preprocess_memory_addresses(result_address_operand.value().first);
855
857 .operand(a_address_operand.value().second)
858 .operand(b_address_operand.value().second)
859 .operand(result_address_operand.value().second)
860 .build();
861 instructions.push_back(shl_16_instruction);
863 result_address_operand.value().first);
864}
865
867{
868#ifdef DISABLE_SHR_16_INSTRUCTION
869 return;
870#endif
871 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
872 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
873 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
874 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
875 return;
876 }
877
878 preprocess_memory_addresses(a_address_operand.value().first);
879 preprocess_memory_addresses(b_address_operand.value().first);
880 preprocess_memory_addresses(result_address_operand.value().first);
882 .operand(a_address_operand.value().second)
883 .operand(b_address_operand.value().second)
884 .operand(result_address_operand.value().second)
885 .build();
886 instructions.push_back(shr_16_instruction);
888 result_address_operand.value().first);
889}
890
892{
893#ifdef DISABLE_CAST_8_INSTRUCTION
894 return;
895#endif
896 auto src_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.src_address);
897 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
898 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
899 return;
900 }
901
902 preprocess_memory_addresses(src_address_operand.value().first);
903 preprocess_memory_addresses(result_address_operand.value().first);
905 .operand(src_address_operand.value().second)
906 .operand(result_address_operand.value().second)
907 .operand(instruction.target_tag.value)
908 .build();
909 instructions.push_back(cast_8_instruction);
911 result_address_operand.value().first.absolute_address);
912}
913
915{
916#ifdef DISABLE_CAST_16_INSTRUCTION
917 return;
918#endif
919 auto src_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.src_address);
920 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
921 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
922 return;
923 }
924
925 preprocess_memory_addresses(src_address_operand.value().first);
926 preprocess_memory_addresses(result_address_operand.value().first);
928 .operand(src_address_operand.value().second)
929 .operand(result_address_operand.value().second)
930 .operand(instruction.target_tag.value)
931 .build();
932 instructions.push_back(cast_16_instruction);
934 result_address_operand.value().first.absolute_address);
935}
936
938{
939#ifdef DISABLE_SSTORE_INSTRUCTION
940 return;
941#endif
942 auto src_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.src_address);
943 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
944 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
945 return;
946 }
947 preprocess_memory_addresses(src_address_operand.value().first);
948 preprocess_memory_addresses(result_address_operand.value().first);
949 auto set_slot_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
950 .result_address = instruction.result_address,
951 .value = instruction.slot };
952 this->process_set_ff_instruction(set_slot_instruction);
954 .operand(src_address_operand.value().second)
955 .operand(result_address_operand.value().second)
956 .build();
957 instructions.push_back(sstore_instruction);
959}
960
962{
963#ifdef DISABLE_SLOAD_INSTRUCTION
964 return;
965#endif
966 auto slot_addr = memory_manager.get_slot(instruction.slot_index);
967 if (!slot_addr.has_value()) {
968 return;
969 }
970
971 auto set_slot_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
972 .result_address = instruction.slot_address,
973 .value = *slot_addr };
974 this->process_set_ff_instruction(set_slot_instruction);
975 auto slot_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.slot_address);
976 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
977 if (!slot_address_operand.has_value() || !result_address_operand.has_value()) {
978 return;
979 }
980 preprocess_memory_addresses(slot_address_operand.value().first);
981 preprocess_memory_addresses(result_address_operand.value().first);
982
984 .operand(slot_address_operand.value().second)
985 .operand(result_address_operand.value().second)
986 .build();
987 instructions.push_back(sload_instruction);
988 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, result_address_operand.value().first.absolute_address);
989}
990
992{
993#ifdef DISABLE_GETENVVAR_INSTRUCTION
994 return;
995#endif
996 auto instruction_type = static_cast<uint8_t>(instruction.type % 12);
997 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
998 if (!result_address_operand.has_value()) {
999 return;
1000 }
1001 preprocess_memory_addresses(result_address_operand.value().first);
1003 .operand(result_address_operand.value().second)
1004 .operand(instruction_type)
1005 .build();
1006 instructions.push_back(getenvvar_instruction);
1007 // special case for timestamp, it returns a 64-bit value
1008 if (instruction_type == 6) {
1010 result_address_operand.value().first.absolute_address);
1011 } else {
1013 result_address_operand.value().first.absolute_address);
1014 }
1015}
1016
1018{
1019#ifdef DISABLE_EMITNULLIFIER_INSTRUCTION
1020 return;
1021#endif
1022 auto nullifier_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.nullifier_address);
1023 if (!nullifier_address_operand.has_value()) {
1024 return;
1025 }
1026 preprocess_memory_addresses(nullifier_address_operand.value().first);
1028 .operand(nullifier_address_operand.value().second)
1029 .build();
1030 instructions.push_back(emitnulifier_instruction);
1031}
1032
1034{
1035#ifdef DISABLE_NULLIFIEREXISTS_INSTRUCTION
1036 return;
1037#endif
1038 auto nullifier_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.nullifier_address);
1039 auto contract_address_operand =
1041 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1042 if (!nullifier_address_operand.has_value() || !contract_address_operand.has_value() ||
1043 !result_address_operand.has_value()) {
1044 return;
1045 }
1046
1047 preprocess_memory_addresses(nullifier_address_operand.value().first);
1048 preprocess_memory_addresses(contract_address_operand.value().first);
1049 preprocess_memory_addresses(result_address_operand.value().first);
1050 auto get_contract_address_instruction =
1051 GETENVVAR_Instruction{ .result_address = instruction.contract_address_address, .type = 0 };
1052 this->process_getenvvar_instruction(get_contract_address_instruction);
1053
1055 .operand(nullifier_address_operand.value().second)
1056 .operand(contract_address_operand.value().second)
1057 .operand(result_address_operand.value().second)
1058 .build();
1059 instructions.push_back(nullifierexists_instruction);
1060 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
1061}
1062
1064{
1065#ifdef DISABLE_EMITNOTEHASH_INSTRUCTION
1066 return;
1067#endif
1068 auto set_note_hash_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1069 .result_address = instruction.note_hash_address,
1070 .value = instruction.note_hash };
1071 this->process_set_ff_instruction(set_note_hash_instruction);
1072
1073 // EMITNOTEHASH expects UINT16 operand
1074 auto note_hash_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.note_hash_address);
1075 if (!note_hash_address_operand.has_value()) {
1076 return;
1077 }
1078 preprocess_memory_addresses(note_hash_address_operand.value().first);
1079
1081 .operand(note_hash_address_operand.value().second)
1082 .build();
1083 instructions.push_back(emitnotehash_instruction);
1085}
1086
1088{
1089#ifdef DISABLE_NOTEHASHEXISTS_INSTRUCTION
1090 return;
1091#endif
1093 if (!note_hash.has_value()) {
1094 return;
1095 }
1096 auto leaf_index = memory_manager.get_leaf_index(instruction.notehash_index);
1097 if (!leaf_index.has_value()) {
1098 return;
1099 }
1101 auto note_hash_counter = static_cast<uint64_t>(*leaf_index);
1103 auto unique_note_computed_hash = bb::avm2::simulation::unconstrained_make_unique_note_hash(
1104 siloed_note_computed_hash, FIRST_NULLIFIER, note_hash_counter);
1105
1106 auto set_note_hash_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1107 .result_address = instruction.notehash_address,
1108 .value = unique_note_computed_hash };
1109 this->process_set_ff_instruction(set_note_hash_instruction);
1110 auto set_leaf_index_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::U64,
1111 .result_address = instruction.leaf_index_address,
1112 .value = *leaf_index };
1113 this->process_set_ff_instruction(set_leaf_index_instruction);
1114
1115 auto notehash_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.notehash_address);
1116 auto leaf_index_address_operand =
1118 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1119 if (!notehash_address_operand.has_value() || !leaf_index_address_operand.has_value() ||
1120 !result_address_operand.has_value()) {
1121 return;
1122 }
1123 preprocess_memory_addresses(notehash_address_operand.value().first);
1124 preprocess_memory_addresses(leaf_index_address_operand.value().first);
1125 preprocess_memory_addresses(result_address_operand.value().first);
1126
1128 .operand(notehash_address_operand.value().second)
1129 .operand(leaf_index_address_operand.value().second)
1130 .operand(result_address_operand.value().second)
1131 .build();
1132 instructions.push_back(notehashexists_instruction);
1133 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
1134}
1135
1137{
1138#ifdef DISABLE_CALLDATACOPY_INSTRUCTION
1139 return;
1140#endif
1141 auto copy_size_set_instruction = SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1142 .result_address = instruction.copy_size_address,
1143 .value = instruction.copy_size };
1144 this->process_set_32_instruction(copy_size_set_instruction);
1145 auto cd_start_set_instruction = SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1146 .result_address = instruction.cd_start_address,
1147 .value = instruction.cd_start };
1148 this->process_set_32_instruction(cd_start_set_instruction);
1149 // CALLDATACOPY expects UINT16 operands for all three addresses
1150 auto copy_size_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.copy_size_address);
1151 auto cd_start_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.cd_start_address);
1152 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1153 if (!copy_size_address_operand.has_value() || !cd_start_address_operand.has_value() ||
1154 !dst_address_operand.has_value()) {
1155 return;
1156 }
1157
1158 preprocess_memory_addresses(copy_size_address_operand.value().first);
1159 preprocess_memory_addresses(cd_start_address_operand.value().first);
1160 preprocess_memory_addresses(dst_address_operand.value().first);
1162 .operand(copy_size_address_operand.value().second)
1163 .operand(cd_start_address_operand.value().second)
1164 .operand(dst_address_operand.value().second)
1165 .build();
1166 instructions.push_back(calldatacopy_instruction);
1167
1168 // setting calldata_addr to u32 to avoid overflows
1169 uint32_t calldata_base_offset = dst_address_operand.value().first.absolute_address;
1170 auto loop_upper_bound = static_cast<uint32_t>(std::min((calldata_base_offset) + instruction.copy_size, 65535U));
1171 for (uint32_t calldata_addr = calldata_base_offset; calldata_addr < loop_upper_bound; calldata_addr++) {
1173 }
1174}
1175
1177{
1178#ifdef DISABLE_SENDL2TOL1MSG_INSTRUCTION
1179 return;
1180#endif
1181 auto set_recipient_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1182 .result_address = instruction.recipient_address,
1183 .value = instruction.recipient };
1184 this->process_set_ff_instruction(set_recipient_instruction);
1185 auto set_content_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1186 .result_address = instruction.content_address,
1187 .value = instruction.content };
1188 this->process_set_ff_instruction(set_content_instruction);
1189
1190 auto recipient_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.recipient_address);
1191 auto content_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.content_address);
1192 if (!recipient_address_operand.has_value() || !content_address_operand.has_value()) {
1193 return;
1194 }
1195 preprocess_memory_addresses(recipient_address_operand.value().first);
1196 preprocess_memory_addresses(content_address_operand.value().first);
1198 .operand(recipient_address_operand.value().second)
1199 .operand(content_address_operand.value().second)
1200 .build();
1201 instructions.push_back(sendl2tol1msg_instruction);
1202}
1203
1205{
1206#ifdef DISABLE_EMITUNENCRYPTEDLOG_INSTRUCTION
1207 return;
1208#endif
1209 auto log_size_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.log_size_address);
1210 auto log_values_address_operand =
1212 if (!log_size_address_operand.has_value() || !log_values_address_operand.has_value()) {
1213 return;
1214 }
1215 preprocess_memory_addresses(log_size_address_operand.value().first);
1216 preprocess_memory_addresses(log_values_address_operand.value().first);
1217 auto emitunencryptedlog_instruction =
1219 .operand(log_size_address_operand.value().second)
1220 .operand(log_values_address_operand.value().second)
1221 .build();
1222 instructions.push_back(emitunencryptedlog_instruction);
1223}
1224
1226{
1227#ifdef DISABLE_CALL_INSTRUCTION
1228 return;
1229#endif
1236 if (!l2_gas.has_value() || !da_gas.has_value() || !contract_address_address.has_value() ||
1237 !calldata_size_address.has_value() || !calldata_address.has_value()) {
1238 return;
1239 }
1240 preprocess_memory_addresses(l2_gas.value().first);
1241 preprocess_memory_addresses(da_gas.value().first);
1245
1247 .result_address = instruction.calldata_size_address,
1248 .value = static_cast<uint32_t>(instruction.calldata_size) });
1249
1250 auto call_instruction_builder = instruction.is_static_call
1253 auto call_instruction = call_instruction_builder.operand(l2_gas.value().second)
1254 .operand(da_gas.value().second)
1255 .operand(contract_address_address.value().second)
1256 .operand(calldata_size_address.value().second)
1257 .operand(calldata_address.value().second)
1258 .build();
1259 instructions.push_back(call_instruction);
1260}
1261
1264{
1265#ifdef DISABLE_RETURNDATASIZE_WITH_RETURNDATACOPY_INSTRUCTION
1266 return;
1267#endif
1269 .operand(instruction.copy_size_offset)
1270 .build();
1271 instructions.push_back(returndatasize_instruction);
1272 auto rd_start_set_instruction =
1274 .result_address =
1275 AddressRef{ .address = instruction.rd_start_offset, .mode = AddressingMode::Direct },
1276 .value = instruction.rd_start };
1277 this->process_set_32_instruction(rd_start_set_instruction);
1279 .operand(instruction.copy_size_offset)
1280 .operand(instruction.rd_start_offset)
1281 .operand(instruction.dst_address)
1282 .build();
1283 // TODO(defkit): function can return more than one value :D
1285 instructions.push_back(returndatacopy_instruction);
1286}
1287
1289{
1290#ifdef DISABLE_GETCONTRACTINSTANCE_INSTRUCTION
1291 return;
1292#endif
1295
1297 if (!contract_address_address.has_value() || !dst_address.has_value()) {
1298 return;
1299 }
1302
1303 auto get_contract_instance_instruction =
1305 .operand(contract_address_address.value().second)
1306 .operand(dst_address.value().second)
1307 .operand(instruction.member_enum)
1308 .build();
1309 instructions.push_back(get_contract_instance_instruction);
1311 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, dst_address.value().first.absolute_address + 1);
1312}
1313
1315{
1316#ifdef DISABLE_SUCCESSCOPY_INSTRUCTION
1317 return;
1318#endif
1319 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1320 if (!dst_address_operand.has_value()) {
1321 return;
1322 }
1323 preprocess_memory_addresses(dst_address_operand.value().first);
1325 .operand(dst_address_operand.value().second)
1326 .build();
1327 instructions.push_back(successcopy_instruction);
1328 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, dst_address_operand.value().first.absolute_address);
1329}
1330
1332{
1333#ifdef DISABLE_ECADD_INSTRUCTION
1334 return;
1335#endif
1343
1344 if (!p1_x.has_value() || !p1_y.has_value() || !p1_inf.has_value() || !p2_x.has_value() || !p2_y.has_value() ||
1345 !p2_inf.has_value() || !result.has_value()) {
1346 return;
1347 }
1348
1349 preprocess_memory_addresses(p1_x.value().first);
1350 preprocess_memory_addresses(p1_y.value().first);
1351 preprocess_memory_addresses(p1_inf.value().first);
1352 preprocess_memory_addresses(p2_x.value().first);
1353 preprocess_memory_addresses(p2_y.value().first);
1354 preprocess_memory_addresses(p2_inf.value().first);
1355 preprocess_memory_addresses(result.value().first);
1356
1358 .operand(p1_x.value().second)
1359 .operand(p1_y.value().second)
1360 .operand(p1_inf.value().second)
1361 .operand(p2_x.value().second)
1362 .operand(p2_y.value().second)
1363 .operand(p2_inf.value().second)
1364 .operand(result.value().second)
1365 .build();
1366 instructions.push_back(ecadd_instruction);
1367
1368 // ECADD writes 3 consecutive memory locations: result_x (FF), result_y (FF), result_is_inf (U1)
1369 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, result.value().first.absolute_address);
1370 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, result.value().first.absolute_address + 1);
1371 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address + 2);
1372}
1373
1375{
1376#ifdef DISABLE_POSEIDON2PERM_INSTRUCTION
1377 return;
1378#endif
1381
1382 if (!src.has_value() || !dst.has_value()) {
1383 return;
1384 }
1385
1386 preprocess_memory_addresses(src.value().first);
1387 preprocess_memory_addresses(dst.value().first);
1388
1390 .operand(src.value().second)
1391 .operand(dst.value().second)
1392 .build();
1393 instructions.push_back(poseidon2perm_instruction);
1394
1395 // Poseidon2 permutation writes 4 consecutive FF values to dst
1396 for (uint32_t i = 0; i < 4; i++) {
1397 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, dst.value().first.absolute_address + i);
1398 }
1399}
1400
1402{
1403#ifdef DISABLE_KECCAKF1600_INSTRUCTION
1404 return;
1405#endif
1408
1409 if (!src.has_value() || !dst.has_value()) {
1410 return;
1411 }
1412
1413 preprocess_memory_addresses(src.value().first);
1414 preprocess_memory_addresses(dst.value().first);
1415
1417 .operand(dst.value().second)
1418 .operand(src.value().second)
1419 .build();
1420 instructions.push_back(keccakf1600_instruction);
1421
1422 // Keccak-f[1600] permutation writes 25 consecutive U64 values to dst
1423 for (uint32_t i = 0; i < 25; i++) {
1424 memory_manager.set_memory_address(bb::avm2::MemoryTag::U64, dst.value().first.absolute_address + i);
1425 }
1426}
1427
1429{
1430#ifdef DISABLE_SHA256COMPRESSION_INSTRUCTION
1431 return;
1432#endif
1436
1437 if (!state.has_value() || !input.has_value() || !dst.has_value()) {
1438 return;
1439 }
1440
1441 preprocess_memory_addresses(state.value().first);
1442 preprocess_memory_addresses(input.value().first);
1443 preprocess_memory_addresses(dst.value().first);
1444
1446 .operand(dst.value().second)
1447 .operand(state.value().second)
1448 .operand(input.value().second)
1449 .build();
1450 instructions.push_back(sha256compression_instruction);
1451
1452 // SHA256 compression writes 8 consecutive U32 values to dst
1453 for (uint32_t i = 0; i < 8; i++) {
1454 memory_manager.set_memory_address(bb::avm2::MemoryTag::U32, dst.value().first.absolute_address + i);
1455 }
1456}
1457
1459{
1460 auto msg_hash_operand = memory_manager.get_resolved_address_and_operand_16(instruction.msg_hash_address);
1461 auto leaf_index_operand = memory_manager.get_resolved_address_and_operand_16(instruction.leaf_index_address);
1462 auto result_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1463
1464 if (!msg_hash_operand.has_value() || !leaf_index_operand.has_value() || !result_operand.has_value()) {
1465 return;
1466 }
1467
1468 preprocess_memory_addresses(msg_hash_operand.value().first);
1469 preprocess_memory_addresses(leaf_index_operand.value().first);
1470 preprocess_memory_addresses(result_operand.value().first);
1471
1473 .operand(msg_hash_operand.value().second)
1474 .operand(leaf_index_operand.value().second)
1475 .operand(result_operand.value().second)
1476 .build();
1477 instructions.push_back(l1tol2msgexists_instruction);
1478 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_operand.value().first.absolute_address);
1479}
1480
1482{
1483 auto value_operand = memory_manager.get_resolved_address_and_operand_16(instruction.value_address);
1484 auto radix_operand = memory_manager.get_resolved_address_and_operand_16(instruction.radix_address);
1485 auto num_limbs_operand = memory_manager.get_resolved_address_and_operand_16(instruction.num_limbs_address);
1486 auto output_bits_operand = memory_manager.get_resolved_address_and_operand_16(instruction.output_bits_address);
1487 auto dst_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1488
1489 if (!value_operand.has_value() || !radix_operand.has_value() || !num_limbs_operand.has_value() ||
1490 !output_bits_operand.has_value() || !dst_operand.has_value()) {
1491 return;
1492 }
1493
1494 preprocess_memory_addresses(value_operand.value().first);
1495 preprocess_memory_addresses(radix_operand.value().first);
1496 preprocess_memory_addresses(num_limbs_operand.value().first);
1497 preprocess_memory_addresses(output_bits_operand.value().first);
1498 preprocess_memory_addresses(dst_operand.value().first);
1499
1501 .operand(dst_operand.value().second)
1502 .operand(value_operand.value().second)
1503 .operand(radix_operand.value().second)
1504 .operand(num_limbs_operand.value().second)
1505 .operand(output_bits_operand.value().second)
1506 .build();
1507 instructions.push_back(toradixbe_instruction);
1508
1509 // Use is_output_bits to determine the output memory tag
1510 auto output_tag = instruction.is_output_bits ? bb::avm2::MemoryTag::U1 : bb::avm2::MemoryTag::U8;
1511 memory_manager.set_memory_address(output_tag, dst_operand.value().first.absolute_address);
1512}
1513
1517{
1519 // if the block is called by INTERNALCALL, just insert INTERNALRETURN
1520 if (caller != nullptr) {
1521 auto internalreturn_instruction =
1523 instructions.push_back(internalreturn_instruction);
1524 return;
1525 }
1526
1528 if (!return_addr.has_value()) {
1529 return_addr = std::optional<uint32_t>(0);
1530 }
1531
1532 // TODO(defkit): return_size_offset should be const and defined by fuzzer
1533
1534 uint16_t return_size_offset = 5U;
1535 // Ensure operands are created as U16 to match wire format (UINT16)
1537 .operand(return_size_offset)
1539 .operand(static_cast<uint16_t>(return_size))
1540 .build();
1541 instructions.push_back(set_size_instruction);
1542 // RETURN expects UINT16 operands, ensure we cast to uint16_t explicitly
1544 .operand(static_cast<uint16_t>(return_size_offset))
1545 .operand(return_addr.value())
1546 .build();
1547 instructions.push_back(return_instruction);
1548}
1549
1550void ProgramBlock::finalize_with_revert(uint8_t revert_size,
1551 MemoryTagWrapper revert_value_tag,
1552 uint16_t revert_value_offset_index)
1553{
1555
1556 auto revert_addr = memory_manager.get_memory_offset_16(revert_value_tag.value, revert_value_offset_index);
1557 if (!revert_addr.has_value()) {
1558 revert_addr = std::optional<uint32_t>(0);
1559 }
1560
1561 // Once we do more of the randomness in Instruction selection, revert_size_offset we shouldnt need to hardcode
1562 uint16_t revert_size_offset = 5U;
1563 // Ensure operands are created as U16 to match wire format (UINT16)
1565 .operand(revert_size_offset)
1567 .operand(static_cast<uint16_t>(revert_size))
1568 .build();
1569 instructions.push_back(set_size_instruction);
1570 // REVERT_16 expects UINT16 operands, ensure we cast to uint16_t explicitly
1572 .operand(static_cast<uint16_t>(revert_size_offset))
1573 .operand(revert_addr.value())
1574 .build();
1575 instructions.push_back(revert_instruction);
1576}
1577
1578void ProgramBlock::finalize_with_jump(ProgramBlock* target_block, bool copy_memory_manager)
1579{
1581 successors.push_back(target_block);
1582 target_block->predecessors.push_back(this);
1583 target_block->caller = this->caller;
1584 if (copy_memory_manager) {
1585 target_block->memory_manager = memory_manager;
1586 }
1587}
1588
1590 ProgramBlock* target_else_block,
1591 uint16_t condition_offset,
1592 bool copy_memory_manager)
1593{
1595 successors.push_back(target_then_block);
1596 successors.push_back(target_else_block);
1598 target_then_block->predecessors.push_back(this);
1599 target_else_block->predecessors.push_back(this);
1600 target_then_block->caller = this->caller;
1601 target_else_block->caller = this->caller;
1602 if (copy_memory_manager) {
1603 target_then_block->memory_manager = memory_manager;
1604 target_else_block->memory_manager = memory_manager;
1605 }
1606}
1607
1609{
1610 auto internalcall_instruction =
1612 instructions.push_back(internalcall_instruction);
1614 this->successors.push_back(target_block);
1615 target_block->predecessors.push_back(this);
1616 target_block->caller = this->caller;
1617}
1618
1620{
1621 for (auto [instruction_index, target_block] : internal_call_instruction_indicies_to_patch) {
1622 auto internalcall_instruction = instructions.at(instruction_index);
1623 if (target_block->offset == -1) {
1624 throw std::runtime_error("Target block offset is not set, should not happen");
1625 }
1626 auto internalcall_instruction_builder =
1628 .operand(static_cast<uint32_t>(target_block->offset));
1629 instructions.at(instruction_index) = internalcall_instruction_builder.build();
1630 }
1632}
1633
1635{
1637 if (!condition_addr.has_value()) {
1638 return std::nullopt;
1639 }
1640 return condition_addr;
1641}
1642
1647
1649{
1650 std::visit(
1651 overloaded{
1652 [this](ADD_8_Instruction instruction) { return this->process_add_8_instruction(instruction); },
1653 [this](SUB_8_Instruction instruction) { return this->process_sub_8_instruction(instruction); },
1654 [this](MUL_8_Instruction instruction) { return this->process_mul_8_instruction(instruction); },
1655 [this](DIV_8_Instruction instruction) { return this->process_div_8_instruction(instruction); },
1656 [this](EQ_8_Instruction instruction) { return this->process_eq_8_instruction(instruction); },
1657 [this](LT_8_Instruction instruction) { return this->process_lt_8_instruction(instruction); },
1658 [this](LTE_8_Instruction instruction) { return this->process_lte_8_instruction(instruction); },
1659 [this](AND_8_Instruction instruction) { return this->process_and_8_instruction(instruction); },
1660 [this](OR_8_Instruction instruction) { return this->process_or_8_instruction(instruction); },
1661 [this](XOR_8_Instruction instruction) { return this->process_xor_8_instruction(instruction); },
1662 [this](SHL_8_Instruction instruction) { return this->process_shl_8_instruction(instruction); },
1663 [this](SHR_8_Instruction instruction) { return this->process_shr_8_instruction(instruction); },
1664 [this](SET_8_Instruction instruction) { return this->process_set_8_instruction(instruction); },
1665 [this](SET_16_Instruction instruction) { return this->process_set_16_instruction(instruction); },
1666 [this](SET_32_Instruction instruction) { return this->process_set_32_instruction(instruction); },
1667 [this](SET_64_Instruction instruction) { return this->process_set_64_instruction(instruction); },
1668 [this](SET_128_Instruction instruction) { return this->process_set_128_instruction(instruction); },
1669 [this](SET_FF_Instruction instruction) { return this->process_set_ff_instruction(instruction); },
1670 [this](MOV_8_Instruction instruction) { return this->process_mov_8_instruction(instruction); },
1671 [this](MOV_16_Instruction instruction) { return this->process_mov_16_instruction(instruction); },
1672 [this](FDIV_8_Instruction instruction) { return this->process_fdiv_8_instruction(instruction); },
1673 [this](NOT_8_Instruction instruction) { return this->process_not_8_instruction(instruction); },
1674 [this](ADD_16_Instruction instruction) { return this->process_add_16_instruction(instruction); },
1675 [this](SUB_16_Instruction instruction) { return this->process_sub_16_instruction(instruction); },
1676 [this](MUL_16_Instruction instruction) { return this->process_mul_16_instruction(instruction); },
1677 [this](DIV_16_Instruction instruction) { return this->process_div_16_instruction(instruction); },
1678 [this](FDIV_16_Instruction instruction) { return this->process_fdiv_16_instruction(instruction); },
1679 [this](EQ_16_Instruction instruction) { return this->process_eq_16_instruction(instruction); },
1680 [this](LT_16_Instruction instruction) { return this->process_lt_16_instruction(instruction); },
1681 [this](LTE_16_Instruction instruction) { return this->process_lte_16_instruction(instruction); },
1682 [this](AND_16_Instruction instruction) { return this->process_and_16_instruction(instruction); },
1683 [this](OR_16_Instruction instruction) { return this->process_or_16_instruction(instruction); },
1684 [this](XOR_16_Instruction instruction) { return this->process_xor_16_instruction(instruction); },
1685 [this](NOT_16_Instruction instruction) { return this->process_not_16_instruction(instruction); },
1686 [this](SHL_16_Instruction instruction) { return this->process_shl_16_instruction(instruction); },
1687 [this](SHR_16_Instruction instruction) { return this->process_shr_16_instruction(instruction); },
1688 [this](CAST_8_Instruction instruction) { return this->process_cast_8_instruction(instruction); },
1689 [this](CAST_16_Instruction instruction) { return this->process_cast_16_instruction(instruction); },
1690 [this](SSTORE_Instruction instruction) { return this->process_sstore_instruction(instruction); },
1691 [this](SLOAD_Instruction instruction) { return this->process_sload_instruction(instruction); },
1692 [this](GETENVVAR_Instruction instruction) { return this->process_getenvvar_instruction(instruction); },
1694 return this->process_emitnulifier_instruction(instruction);
1695 },
1697 return this->process_nullifierexists_instruction(instruction);
1698 },
1700 return this->process_emitnotehash_instruction(instruction);
1701 },
1703 return this->process_notehashexists_instruction(instruction);
1704 },
1706 return this->process_calldatacopy_instruction(instruction);
1707 },
1709 return this->process_sendl2tol1msg_instruction(instruction);
1710 },
1712 return this->process_emitunencryptedlog_instruction(instruction);
1713 },
1714 [this](CALL_Instruction instruction) { return this->process_call_instruction(instruction); },
1717 },
1719 return this->process_getcontractinstance_instruction(instruction);
1720 },
1721 [this](SUCCESSCOPY_Instruction instruction) { return this->process_successcopy_instruction(instruction); },
1722 [this](ECADD_Instruction instruction) { return this->process_ecadd_instruction(instruction); },
1724 return this->process_poseidon2perm_instruction(instruction);
1725 },
1726 [this](KECCAKF1600_Instruction instruction) { return this->process_keccakf1600_instruction(instruction); },
1728 return this->process_sha256compression_instruction(instruction);
1729 },
1731 return this->process_l1tol2msgexists_instruction(instruction);
1732 },
1733 [this](TORADIXBE_Instruction instruction) { return this->process_toradixbe_instruction(instruction); },
1734 [](auto) { throw std::runtime_error("Unknown instruction"); },
1735 },
1736 instruction);
1737}
1738
1739std::vector<bb::avm2::simulation::Instruction> ProgramBlock::get_instructions()
1740{
1741 return instructions;
1742}
::FuzzInstruction FuzzInstruction
const FF FIRST_NULLIFIER
Definition constants.hpp:25
const FF CONTRACT_ADDRESS
Definition constants.hpp:37
std::optional< uint16_t > get_memory_offset_16(bb::avm2::MemoryTag tag, uint32_t address_index)
std::optional< std::pair< ResolvedAddress, bb::avm2::testing::OperandBuilder > > get_resolved_address_and_operand_8(ParamRef address)
std::optional< bb::avm2::FF > get_emitted_note_hash(uint16_t note_hash_index)
std::optional< bb::avm2::FF > get_slot(uint16_t slot_offset_index)
bool is_memory_address_set(uint16_t address)
std::optional< uint16_t > get_leaf_index(uint16_t note_hash_index)
void set_memory_address(bb::avm2::MemoryTag tag, uint32_t address)
void append_slot(bb::avm2::FF slot)
void append_emitted_note_hash(bb::avm2::FF note_hash)
std::optional< std::pair< ResolvedAddress, bb::avm2::testing::OperandBuilder > > get_resolved_address_and_operand_16(ParamRef address)
void process_shr_16_instruction(SHR_16_Instruction instruction)
void process_set_8_instruction(SET_8_Instruction instruction)
void process_poseidon2perm_instruction(POSEIDON2PERM_Instruction instruction)
void process_returndatasize_with_returndatacopy_instruction(RETURNDATASIZE_WITH_RETURNDATACOPY_Instruction instruction)
std::vector< ProgramBlock * > predecessors
void process_sload_instruction(SLOAD_Instruction instruction)
void finalize_with_return(uint8_t return_size, MemoryTagWrapper return_value_tag, uint16_t return_value_offset_index)
finalize the program block with a return instruction Tries to find memory address with the given retu...
std::vector< bb::avm2::simulation::Instruction > get_instructions()
void preprocess_memory_addresses(ResolvedAddress resolved_address)
preprocess the memory addresses Sets M[0] = base_offset for Relative/IndirectRelative modes Sets M[po...
void insert_internal_call(ProgramBlock *target_block)
insert INTERNALCALL instruction with 0 offset
bool is_memory_address_set(uint16_t address)
void process_emitnotehash_instruction(EMITNOTEHASH_Instruction instruction)
void process_xor_16_instruction(XOR_16_Instruction instruction)
ProgramBlock * caller
the block that called this block by INTERNALCALL This field is copied to predecessors on every CFG in...
void process_or_16_instruction(OR_16_Instruction instruction)
void patch_internal_calls()
in insert_internal_call we insert INTERNALCALL instruction with 0 offset, because we don't know the r...
void finalize_with_jump(ProgramBlock *target_block, bool copy_memory_manager=true)
finalize the block with a jump Sets the terminator type to JUMP, adds the target block to the success...
uint16_t condition_offset_index
the offset index of the condition variable (for JUMP_IF)
void process_lte_16_instruction(LTE_16_Instruction instruction)
void process_eq_8_instruction(EQ_8_Instruction instruction)
void process_keccakf1600_instruction(KECCAKF1600_Instruction instruction)
void process_fdiv_8_instruction(FDIV_8_Instruction instruction)
void process_nullifierexists_instruction(NULLIFIEREXISTS_Instruction instruction)
void process_not_8_instruction(NOT_8_Instruction instruction)
void process_add_8_instruction(ADD_8_Instruction instruction)
void finalize_with_revert(uint8_t revert_size, MemoryTagWrapper revert_value_tag, uint16_t revert_value_offset_index)
finalize the program block with a revert instruction Similar to finalize_with_return but uses REVERT ...
void process_and_16_instruction(AND_16_Instruction instruction)
MemoryManager memory_manager
void process_sub_8_instruction(SUB_8_Instruction instruction)
void process_shl_8_instruction(SHL_8_Instruction instruction)
void process_notehashexists_instruction(NOTEHASHEXISTS_Instruction instruction)
void process_div_16_instruction(DIV_16_Instruction instruction)
void process_instruction(FuzzInstruction instruction)
process the instruction
void process_toradixbe_instruction(TORADIXBE_Instruction instruction)
void process_emitnulifier_instruction(EMITNULLIFIER_Instruction instruction)
void process_fdiv_16_instruction(FDIV_16_Instruction instruction)
void process_shl_16_instruction(SHL_16_Instruction instruction)
void process_mul_16_instruction(MUL_16_Instruction instruction)
void process_set_ff_instruction(SET_FF_Instruction instruction)
void process_sstore_instruction(SSTORE_Instruction instruction)
std::map< size_t, ProgramBlock * > internal_call_instruction_indicies_to_patch
void process_ecadd_instruction(ECADD_Instruction instruction)
void record_result_tag_from_param_tags(std::initializer_list< ParamRef > params, ResolvedAddress result_address)
void process_div_8_instruction(DIV_8_Instruction instruction)
void process_and_8_instruction(AND_8_Instruction instruction)
void process_lt_16_instruction(LT_16_Instruction instruction)
std::vector< ProgramBlock * > successors
void process_sub_16_instruction(SUB_16_Instruction instruction)
void process_or_8_instruction(OR_8_Instruction instruction)
void process_cast_8_instruction(CAST_8_Instruction instruction)
void process_call_instruction(CALL_Instruction instruction)
void process_cast_16_instruction(CAST_16_Instruction instruction)
void process_not_16_instruction(NOT_16_Instruction instruction)
void process_set_64_instruction(SET_64_Instruction instruction)
void process_calldatacopy_instruction(CALLDATACOPY_Instruction instruction)
void process_successcopy_instruction(SUCCESSCOPY_Instruction instruction)
void process_l1tol2msgexists_instruction(L1TOL2MSGEXISTS_Instruction instruction)
void process_sendl2tol1msg_instruction(SENDL2TOL1MSG_Instruction instruction)
void process_mov_8_instruction(MOV_8_Instruction instruction)
std::optional< uint16_t > get_terminating_condition_value()
void process_emitunencryptedlog_instruction(EMITUNENCRYPTEDLOG_Instruction instruction)
void process_sha256compression_instruction(SHA256COMPRESSION_Instruction instruction)
void process_mul_8_instruction(MUL_8_Instruction instruction)
void process_set_16_instruction(SET_16_Instruction instruction)
void process_add_16_instruction(ADD_16_Instruction instruction)
void process_xor_8_instruction(XOR_8_Instruction instruction)
void process_eq_16_instruction(EQ_16_Instruction instruction)
void process_lte_8_instruction(LTE_8_Instruction instruction)
void process_getcontractinstance_instruction(GETCONTRACTINSTANCE_Instruction instruction)
void finalize_with_jump_if(ProgramBlock *target_then_block, ProgramBlock *target_else_block, uint16_t condition_offset, bool copy_memory_manager=true)
finalize the block with a jump if Sets the terminator type to JUMP_IF, adds the target blocks to the ...
void process_set_32_instruction(SET_32_Instruction instruction)
void process_getenvvar_instruction(GETENVVAR_Instruction instruction)
TerminatorType terminator_type
void process_lt_8_instruction(LT_8_Instruction instruction)
std::vector< bb::avm2::simulation::Instruction > instructions
void process_shr_8_instruction(SHR_8_Instruction instruction)
void process_mov_16_instruction(MOV_16_Instruction instruction)
void process_set_128_instruction(SET_128_Instruction instruction)
simulation::Instruction build() const
InstructionBuilder & operand(OperandBuilder operand)
FF a
FF b
overloaded(Ts...) -> overloaded< Ts... >
uint64_t da_gas
uint64_t l2_gas
Instruction instruction
FF unconstrained_make_unique_note_hash(const FF &siloed_note_hash, const FF &first_nullifier, uint64_t note_hash_counter)
Definition merkle.cpp:41
FF unconstrained_silo_note_hash(const AztecAddress &contract_address, const FF &note_hash)
Definition merkle.cpp:36
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
unsigned __int128 uint128_t
Definition serialize.hpp:44
mem[result_offset] = mem[a_address] + mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] + mem[b_address]
mem[result_offset] = mem[a_address] & mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] & mem[b_address]
uint32_t address
CALLDATACOPY: M[dstOffset:dstOffset+M[copySizeOffset]] = calldata[M[cdStartOffset]:M[cdStartOffset]+M...
CAST_16: cast mem[src_offset_index] to target_tag and store at dst_offset.
CAST_8: cast mem[src_offset_index] to target_tag and store at dst_offset.
mem[result_offset] = mem[a_address] / mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] / mem[b_address]
EMITNOTEHASH: M[note_hash_offset] = note_hash; emit note hash to the note hash tree.
EMITNULIFIER: inserts new nullifier to the nullifier tree.
mem[result_offset] = mem[a_address] == mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] == mem[b_address]
GETENVVAR: M[result_offset] = getenvvar(type)
KECCAKF1600: Perform Keccak-f[1600] permutation on 25 U64 values M[dst_address:dst_address+25] = kecc...
L1TOL2MSGEXISTS: Check if a L1 to L2 message exists M[result_address] = L1TOL2MSGEXISTS(M[msg_hash_ad...
mem[result_offset] = mem[a_address] < mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] < mem[b_address]
mem[result_offset] = mem[a_address] <= mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] <= mem[b_address]
MOV_16 instruction: mem[dst_offset] = mem[src_offset].
MOV_8 instruction: mem[dst_offset] = mem[src_offset].
mem[result_offset] = mem[a_address] * mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] * mem[b_address]
Wrapper for MemoryTag to allow for msgpack packing and unpacking.
NOTEHASHEXISTS: M[result_offset] = NOTEHASHEXISTS(M[notehash_offset], M[leaf_index_offset]) len = len...
NULLIFIEREXISTS: checks if nullifier exists in the nullifier tree Gets contract's address by GETENVVA...
mem[result_offset] = mem[a_address] | mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] | mem[b_address]
POSEIDON2PERM: Perform Poseidon2 permutation on 4 FF values M[dst_address:dst_address+4] = poseidon2_...
: RETURNDATASIZE + RETURNDATACOPY:
Output of resolving an address in the memory manager In order to resolve a given absolute address wit...
std::optional< uint32_t > base_pointer
uint32_t absolute_address
std::optional< uint32_t > pointer_address
SET_128 instruction.
SET_16 instruction.
SET_32 instruction.
MemoryTagWrapper value_tag
SET_64 instruction.
SET_8 instruction.
SET_FF instruction.
MemoryTagWrapper value_tag
SHA256COMPRESSION: Perform SHA256 compression M[dst_address:dst_address+8] = sha256_compression(M[sta...
mem[result_offset] = mem[a_address] << mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] << mem[b_address]
mem[result_offset] = mem[a_address] >> mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] >> mem[b_address]
SLOAD: M[slot_offset] = slot; M[result_offset] = S[M[slotOffset]].
SSTORE: M[slot_offset_index] = slot; S[M[slotOffset]] = M[srcOffset].
mem[result_offset] = mem[a_address] - mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] - mem[b_address]
TORADIXBE: Convert a field element to a vector of limbs in big-endian radix representation M[dst_addr...
mem[result_offset] = mem[a_address] ^ mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] ^ mem[b_address]