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.pointer_address.has_value()) {
15 if (resolved_address.via_relative) {
16 // Indirect relative: Write the pointer in a relative manner
18 .operand(static_cast<uint16_t>(resolved_address.operand_address))
19 .relative()
21 .operand(resolved_address.absolute_address)
22 .build();
23 instructions.push_back(set_pointer_instruction);
24 } else {
25 // Indirect: Write the pointer directly
27 .operand(static_cast<uint16_t>(resolved_address.pointer_address.value()))
29 .operand(resolved_address.absolute_address)
30 .build();
31 instructions.push_back(set_pointer_instruction);
32 }
33
35 }
36}
37
40{
41 for (const auto& param : params) {
42 auto tag =
43 std::visit(overloaded{ [](const VariableRef& var) -> std::optional<MemoryTag> { return var.tag.value; },
44 [](const AddressRef&) -> std::optional<MemoryTag> { return std::nullopt; } },
45 param);
46 if (tag.has_value()) {
47 memory_manager.set_memory_address(tag.value(), result_address.absolute_address);
48 return;
49 }
50 }
51}
52
54{
55#ifdef DISABLE_ADD_8_INSTRUCTION
56 return;
57#endif
61 if (!a.has_value() || !b.has_value() || !result.has_value()) {
62 return;
63 }
64 preprocess_memory_addresses(a.value().first);
65 preprocess_memory_addresses(b.value().first);
66 preprocess_memory_addresses(result.value().first);
67
69 .operand(a.value().second)
70 .operand(b.value().second)
71 .operand(result.value().second)
72 .build();
73 instructions.push_back(add_8_instruction);
74 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
75}
76
78{
79#ifdef DISABLE_SUB_8_INSTRUCTION
80 return;
81#endif
85 if (!a.has_value() || !b.has_value() || !result.has_value()) {
86 return;
87 }
88 preprocess_memory_addresses(a.value().first);
89 preprocess_memory_addresses(b.value().first);
90 preprocess_memory_addresses(result.value().first);
92 .operand(a.value().second)
93 .operand(b.value().second)
94 .operand(result.value().second)
95 .build();
96 instructions.push_back(sub_8_instruction);
97 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
98}
99
101{
102#ifdef DISABLE_MUL_8_INSTRUCTION
103 return;
104#endif
108 if (!a.has_value() || !b.has_value() || !result.has_value()) {
109 return;
110 }
111 preprocess_memory_addresses(a.value().first);
112 preprocess_memory_addresses(b.value().first);
113 preprocess_memory_addresses(result.value().first);
115 .operand(a.value().second)
116 .operand(b.value().second)
117 .operand(result.value().second)
118 .build();
119 instructions.push_back(mul_8_instruction);
120 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
121}
122
124{
125#ifdef DISABLE_DIV_8_INSTRUCTION
126 return;
127#endif
131 if (!a.has_value() || !b.has_value() || !result.has_value()) {
132 return;
133 }
134 preprocess_memory_addresses(a.value().first);
135 preprocess_memory_addresses(b.value().first);
136 preprocess_memory_addresses(result.value().first);
138 .operand(a.value().second)
139 .operand(b.value().second)
140 .operand(result.value().second)
141 .build();
142 instructions.push_back(div_8_instruction);
143 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
144}
145
147{
148#ifdef DISABLE_EQ_8_INSTRUCTION
149 return;
150#endif
154 if (!a.has_value() || !b.has_value() || !result.has_value()) {
155 return;
156 }
157 preprocess_memory_addresses(a.value().first);
158 preprocess_memory_addresses(b.value().first);
159 preprocess_memory_addresses(result.value().first);
161 .operand(a.value().second)
162 .operand(b.value().second)
163 .operand(result.value().second)
164 .build();
165 instructions.push_back(eq_8_instruction);
166 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address);
167}
168
170{
171#ifdef DISABLE_LT_8_INSTRUCTION
172 return;
173#endif
177 if (!a.has_value() || !b.has_value() || !result.has_value()) {
178 return;
179 }
180 preprocess_memory_addresses(a.value().first);
181 preprocess_memory_addresses(b.value().first);
182 preprocess_memory_addresses(result.value().first);
184 .operand(a.value().second)
185 .operand(b.value().second)
186 .operand(result.value().second)
187 .build();
188 instructions.push_back(lt_8_instruction);
189 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address);
190}
191
193{
194#ifdef DISABLE_LTE_8_INSTRUCTION
195 return;
196#endif
200 if (!a.has_value() || !b.has_value() || !result.has_value()) {
201 return;
202 }
203 preprocess_memory_addresses(a.value().first);
204 preprocess_memory_addresses(b.value().first);
205 preprocess_memory_addresses(result.value().first);
207 .operand(a.value().second)
208 .operand(b.value().second)
209 .operand(result.value().second)
210 .build();
211 instructions.push_back(lte_8_instruction);
212 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address);
213}
214
216{
217#ifdef DISABLE_AND_8_INSTRUCTION
218 return;
219#endif
223 if (!a.has_value() || !b.has_value() || !result.has_value()) {
224 return;
225 }
226
227 preprocess_memory_addresses(a.value().first);
228 preprocess_memory_addresses(b.value().first);
229 preprocess_memory_addresses(result.value().first);
231 .operand(a.value().second)
232 .operand(b.value().second)
233 .operand(result.value().second)
234 .build();
235 instructions.push_back(and_8_instruction);
236 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
237}
238
240{
241#ifdef DISABLE_OR_8_INSTRUCTION
242 return;
243#endif
247 if (!a.has_value() || !b.has_value() || !result.has_value()) {
248 return;
249 }
250
251 preprocess_memory_addresses(a.value().first);
252 preprocess_memory_addresses(b.value().first);
253 preprocess_memory_addresses(result.value().first);
255 .operand(a.value().second)
256 .operand(b.value().second)
257 .operand(result.value().second)
258 .build();
259 instructions.push_back(or_8_instruction);
260 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
261}
262
264{
265#ifdef DISABLE_XOR_8_INSTRUCTION
266 return;
267#endif
271 if (!a.has_value() || !b.has_value() || !result.has_value()) {
272 return;
273 }
274
275 preprocess_memory_addresses(a.value().first);
276 preprocess_memory_addresses(b.value().first);
277 preprocess_memory_addresses(result.value().first);
279 .operand(a.value().second)
280 .operand(b.value().second)
281 .operand(result.value().second)
282 .build();
283 instructions.push_back(xor_8_instruction);
284 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
285}
286
288{
289#ifdef DISABLE_SHL_8_INSTRUCTION
290 return;
291#endif
295 if (!a.has_value() || !b.has_value() || !result.has_value()) {
296 return;
297 }
298
299 preprocess_memory_addresses(a.value().first);
300 preprocess_memory_addresses(b.value().first);
301 preprocess_memory_addresses(result.value().first);
303 .operand(a.value().second)
304 .operand(b.value().second)
305 .operand(result.value().second)
306 .build();
307 instructions.push_back(shl_8_instruction);
308 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
309}
310
312{
313#ifdef DISABLE_SHR_8_INSTRUCTION
314 return;
315#endif
319 if (!a.has_value() || !b.has_value() || !result.has_value()) {
320 return;
321 }
322
323 preprocess_memory_addresses(a.value().first);
324 preprocess_memory_addresses(b.value().first);
325 preprocess_memory_addresses(result.value().first);
327 .operand(a.value().second)
328 .operand(b.value().second)
329 .operand(result.value().second)
330 .build();
331 instructions.push_back(shr_8_instruction);
332 record_result_tag_from_param_tags({ instruction.a_address, instruction.b_address }, result.value().first);
333}
334
336{
337#ifdef DISABLE_SET_8_INSTRUCTION
338 return;
339#endif
340 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
341 if (!effective_address_operand.has_value()) {
342 return;
343 }
344 preprocess_memory_addresses(effective_address_operand.value().first);
346 .operand(effective_address_operand.value().second)
347 .operand(instruction.value_tag.value)
348 .operand(instruction.value)
349 .build());
351 effective_address_operand.value().first.absolute_address);
352}
353
355{
356#ifdef DISABLE_SET_16_INSTRUCTION
357 return;
358#endif
359 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
360 if (!effective_address_operand.has_value()) {
361 return;
362 }
363 preprocess_memory_addresses(effective_address_operand.value().first);
365 .operand(effective_address_operand.value().second)
366 .operand(instruction.value_tag.value)
367 .operand(instruction.value)
368 .build());
370 effective_address_operand.value().first.absolute_address);
371}
372
374{
375#ifdef DISABLE_SET_32_INSTRUCTION
376 return;
377#endif
378 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
379 if (!effective_address_operand.has_value()) {
380 return;
381 }
382 preprocess_memory_addresses(effective_address_operand.value().first);
384 .operand(effective_address_operand.value().second)
385 .operand(instruction.value_tag.value)
386 .operand(instruction.value)
387 .build());
389 effective_address_operand.value().first.absolute_address);
390}
391
393{
394#ifdef DISABLE_SET_64_INSTRUCTION
395 return;
396#endif
397 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
398 if (!effective_address_operand.has_value()) {
399 return;
400 }
401 preprocess_memory_addresses(effective_address_operand.value().first);
403 .operand(effective_address_operand.value().second)
404 .operand(instruction.value_tag.value)
405 .operand(instruction.value)
406 .build());
408 effective_address_operand.value().first.absolute_address);
409}
410
412{
413#ifdef DISABLE_SET_128_INSTRUCTION
414 return;
415#endif
416 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
417 if (!effective_address_operand.has_value()) {
418 return;
419 }
421 (static_cast<uint128_t>(instruction.value_high) << 64) | static_cast<uint128_t>(instruction.value_low);
422 preprocess_memory_addresses(effective_address_operand.value().first);
424 .operand(effective_address_operand.value().second)
425 .operand(instruction.value_tag.value)
426 .operand(value)
427 .build());
429 effective_address_operand.value().first.absolute_address);
430}
431
433{
434#ifdef DISABLE_SET_FF_INSTRUCTION
435 return;
436#endif
437 auto effective_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
438 if (!effective_address_operand.has_value()) {
439 return;
440 }
441 preprocess_memory_addresses(effective_address_operand.value().first);
443 .operand(effective_address_operand.value().second)
444 .operand(instruction.value_tag.value)
445 .operand(instruction.value)
446 .build());
448 effective_address_operand.value().first.absolute_address);
449}
450
452{
453#ifdef DISABLE_MOV_8_INSTRUCTION
454 return;
455#endif
456 auto src_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.src_address);
457 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
458 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
459 return;
460 }
461 preprocess_memory_addresses(src_address_operand.value().first);
462 preprocess_memory_addresses(result_address_operand.value().first);
464 .operand(src_address_operand.value().second)
465 .operand(result_address_operand.value().second)
466 .build();
467 instructions.push_back(mov_8_instruction);
468 record_result_tag_from_param_tags({ instruction.src_address }, result_address_operand.value().first);
469}
470
472{
473#ifdef DISABLE_MOV_16_INSTRUCTION
474 return;
475#endif
476 auto src_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.src_address);
477 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
478 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
479 return;
480 }
481
482 preprocess_memory_addresses(src_address_operand.value().first);
483 preprocess_memory_addresses(result_address_operand.value().first);
485 .operand(src_address_operand.value().second)
486 .operand(result_address_operand.value().second)
487 .build();
488 instructions.push_back(mov_16_instruction);
489 record_result_tag_from_param_tags({ instruction.src_address }, result_address_operand.value().first);
490}
491
493{
494#ifdef DISABLE_FDIV_8_INSTRUCTION
495 return;
496#endif
497 auto a_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.a_address);
498 auto b_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.b_address);
499 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
500 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
501 return;
502 }
503
504 preprocess_memory_addresses(a_address_operand.value().first);
505 preprocess_memory_addresses(b_address_operand.value().first);
506 preprocess_memory_addresses(result_address_operand.value().first);
508 .operand(a_address_operand.value().second)
509 .operand(b_address_operand.value().second)
510 .operand(result_address_operand.value().second)
511 .build();
512 instructions.push_back(fdiv_8_instruction);
514 result_address_operand.value().first);
515}
516
518{
519#ifdef DISABLE_NOT_8_INSTRUCTION
520 return;
521#endif
522 auto a_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.a_address);
523 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
524 if (!a_address_operand.has_value() || !result_address_operand.has_value()) {
525 return;
526 }
527
528 preprocess_memory_addresses(a_address_operand.value().first);
529 preprocess_memory_addresses(result_address_operand.value().first);
531 .operand(a_address_operand.value().second)
532 .operand(result_address_operand.value().second)
533 .build();
534 instructions.push_back(not_8_instruction);
535 record_result_tag_from_param_tags({ instruction.a_address }, result_address_operand.value().first);
536}
537
539{
540#ifdef DISABLE_ADD_16_INSTRUCTION
541 return;
542#endif
543 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
544 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
545 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
546 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
547 return;
548 }
549
550 preprocess_memory_addresses(a_address_operand.value().first);
551 preprocess_memory_addresses(b_address_operand.value().first);
552 preprocess_memory_addresses(result_address_operand.value().first);
554 .operand(a_address_operand.value().second)
555 .operand(b_address_operand.value().second)
556 .operand(result_address_operand.value().second)
557 .build();
558 instructions.push_back(add_16_instruction);
560 result_address_operand.value().first);
561}
562
564{
565#ifdef DISABLE_SUB_16_INSTRUCTION
566 return;
567#endif
568 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
569 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
570 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
571 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
572 return;
573 }
574
575 preprocess_memory_addresses(a_address_operand.value().first);
576 preprocess_memory_addresses(b_address_operand.value().first);
577 preprocess_memory_addresses(result_address_operand.value().first);
579 .operand(a_address_operand.value().second)
580 .operand(b_address_operand.value().second)
581 .operand(result_address_operand.value().second)
582 .build();
583 instructions.push_back(sub_16_instruction);
585 result_address_operand.value().first);
586}
587
589{
590#ifdef DISABLE_MUL_16_INSTRUCTION
591 return;
592#endif
593 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
594 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
595 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
596 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
597 return;
598 }
599
600 preprocess_memory_addresses(a_address_operand.value().first);
601 preprocess_memory_addresses(b_address_operand.value().first);
602 preprocess_memory_addresses(result_address_operand.value().first);
604 .operand(a_address_operand.value().second)
605 .operand(b_address_operand.value().second)
606 .operand(result_address_operand.value().second)
607 .build();
608 instructions.push_back(mul_16_instruction);
610 result_address_operand.value().first);
611}
612
614{
615#ifdef DISABLE_DIV_16_INSTRUCTION
616 return;
617#endif
618 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
619 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
620 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
621 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
622 return;
623 }
624
625 preprocess_memory_addresses(a_address_operand.value().first);
626 preprocess_memory_addresses(b_address_operand.value().first);
627 preprocess_memory_addresses(result_address_operand.value().first);
629 .operand(a_address_operand.value().second)
630 .operand(b_address_operand.value().second)
631 .operand(result_address_operand.value().second)
632 .build();
633 instructions.push_back(div_16_instruction);
635 result_address_operand.value().first);
636}
637
639{
640#ifdef DISABLE_FDIV_16_INSTRUCTION
641 return;
642#endif
643 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
644 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
645 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
646 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
647 return;
648 }
649
650 preprocess_memory_addresses(a_address_operand.value().first);
651 preprocess_memory_addresses(b_address_operand.value().first);
652 preprocess_memory_addresses(result_address_operand.value().first);
654 .operand(a_address_operand.value().second)
655 .operand(b_address_operand.value().second)
656 .operand(result_address_operand.value().second)
657 .build();
658 instructions.push_back(fdiv_16_instruction);
660 result_address_operand.value().first);
661}
662
664{
665#ifdef DISABLE_EQ_16_INSTRUCTION
666 return;
667#endif
668 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
669 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
670 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
671 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
672 return;
673 }
674
675 preprocess_memory_addresses(a_address_operand.value().first);
676 preprocess_memory_addresses(b_address_operand.value().first);
677 preprocess_memory_addresses(result_address_operand.value().first);
679 .operand(a_address_operand.value().second)
680 .operand(b_address_operand.value().second)
681 .operand(result_address_operand.value().second)
682 .build();
683 instructions.push_back(eq_16_instruction);
684 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
685}
686
688{
689#ifdef DISABLE_LT_16_INSTRUCTION
690 return;
691#endif
692 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
693 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
694 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
695 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
696 return;
697 }
698
699 preprocess_memory_addresses(a_address_operand.value().first);
700 preprocess_memory_addresses(b_address_operand.value().first);
701 preprocess_memory_addresses(result_address_operand.value().first);
703 .operand(a_address_operand.value().second)
704 .operand(b_address_operand.value().second)
705 .operand(result_address_operand.value().second)
706 .build();
707 instructions.push_back(lt_16_instruction);
708 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
709}
710
712{
713#ifdef DISABLE_LTE_16_INSTRUCTION
714 return;
715#endif
716 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
717 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
718 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
719 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
720 return;
721 }
722
723 preprocess_memory_addresses(a_address_operand.value().first);
724 preprocess_memory_addresses(b_address_operand.value().first);
725 preprocess_memory_addresses(result_address_operand.value().first);
727 .operand(a_address_operand.value().second)
728 .operand(b_address_operand.value().second)
729 .operand(result_address_operand.value().second)
730 .build();
731 instructions.push_back(lte_16_instruction);
732 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
733}
734
736{
737#ifdef DISABLE_AND_16_INSTRUCTION
738 return;
739#endif
740 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
741 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
742 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
743 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
744 return;
745 }
746
747 preprocess_memory_addresses(a_address_operand.value().first);
748 preprocess_memory_addresses(b_address_operand.value().first);
749 preprocess_memory_addresses(result_address_operand.value().first);
751 .operand(a_address_operand.value().second)
752 .operand(b_address_operand.value().second)
753 .operand(result_address_operand.value().second)
754 .build();
755 instructions.push_back(and_16_instruction);
757 result_address_operand.value().first);
758}
759
761{
762#ifdef DISABLE_OR_16_INSTRUCTION
763 return;
764#endif
765 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
766 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
767 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
768 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
769 return;
770 }
771
772 preprocess_memory_addresses(a_address_operand.value().first);
773 preprocess_memory_addresses(b_address_operand.value().first);
774 preprocess_memory_addresses(result_address_operand.value().first);
776 .operand(a_address_operand.value().second)
777 .operand(b_address_operand.value().second)
778 .operand(result_address_operand.value().second)
779 .build();
780 instructions.push_back(or_16_instruction);
782 result_address_operand.value().first);
783}
784
786{
787#ifdef DISABLE_XOR_16_INSTRUCTION
788 return;
789#endif
790 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
791 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
792 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
793 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
794 return;
795 }
796
797 preprocess_memory_addresses(a_address_operand.value().first);
798 preprocess_memory_addresses(b_address_operand.value().first);
799 preprocess_memory_addresses(result_address_operand.value().first);
801 .operand(a_address_operand.value().second)
802 .operand(b_address_operand.value().second)
803 .operand(result_address_operand.value().second)
804 .build();
805 instructions.push_back(xor_16_instruction);
807 result_address_operand.value().first);
808}
809
811{
812#ifdef DISABLE_NOT_16_INSTRUCTION
813 return;
814#endif
815 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
816 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
817 if (!a_address_operand.has_value() || !result_address_operand.has_value()) {
818 return;
819 }
820
821 preprocess_memory_addresses(a_address_operand.value().first);
822 preprocess_memory_addresses(result_address_operand.value().first);
824 .operand(a_address_operand.value().second)
825 .operand(result_address_operand.value().second)
826 .build();
827 instructions.push_back(not_16_instruction);
828 record_result_tag_from_param_tags({ instruction.a_address }, result_address_operand.value().first);
829}
830
832{
833#ifdef DISABLE_SHL_16_INSTRUCTION
834 return;
835#endif
836 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
837 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
838 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
839 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
840 return;
841 }
842 preprocess_memory_addresses(a_address_operand.value().first);
843 preprocess_memory_addresses(b_address_operand.value().first);
844 preprocess_memory_addresses(result_address_operand.value().first);
845
847 .operand(a_address_operand.value().second)
848 .operand(b_address_operand.value().second)
849 .operand(result_address_operand.value().second)
850 .build();
851 instructions.push_back(shl_16_instruction);
853 result_address_operand.value().first);
854}
855
857{
858#ifdef DISABLE_SHR_16_INSTRUCTION
859 return;
860#endif
861 auto a_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.a_address);
862 auto b_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.b_address);
863 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
864 if (!a_address_operand.has_value() || !b_address_operand.has_value() || !result_address_operand.has_value()) {
865 return;
866 }
867
868 preprocess_memory_addresses(a_address_operand.value().first);
869 preprocess_memory_addresses(b_address_operand.value().first);
870 preprocess_memory_addresses(result_address_operand.value().first);
872 .operand(a_address_operand.value().second)
873 .operand(b_address_operand.value().second)
874 .operand(result_address_operand.value().second)
875 .build();
876 instructions.push_back(shr_16_instruction);
878 result_address_operand.value().first);
879}
880
882{
883#ifdef DISABLE_CAST_8_INSTRUCTION
884 return;
885#endif
886 auto src_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.src_address);
887 auto result_address_operand = memory_manager.get_resolved_address_and_operand_8(instruction.result_address);
888 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
889 return;
890 }
891
892 preprocess_memory_addresses(src_address_operand.value().first);
893 preprocess_memory_addresses(result_address_operand.value().first);
895 .operand(src_address_operand.value().second)
896 .operand(result_address_operand.value().second)
897 .operand(instruction.target_tag.value)
898 .build();
899 instructions.push_back(cast_8_instruction);
901 result_address_operand.value().first.absolute_address);
902}
903
905{
906#ifdef DISABLE_CAST_16_INSTRUCTION
907 return;
908#endif
909 auto src_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.src_address);
910 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
911 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
912 return;
913 }
914
915 preprocess_memory_addresses(src_address_operand.value().first);
916 preprocess_memory_addresses(result_address_operand.value().first);
918 .operand(src_address_operand.value().second)
919 .operand(result_address_operand.value().second)
920 .operand(instruction.target_tag.value)
921 .build();
922 instructions.push_back(cast_16_instruction);
924 result_address_operand.value().first.absolute_address);
925}
926
928{
929#ifdef DISABLE_SSTORE_INSTRUCTION
930 return;
931#endif
932 auto src_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.src_address);
933 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
934 if (!src_address_operand.has_value() || !result_address_operand.has_value()) {
935 return;
936 }
937 preprocess_memory_addresses(src_address_operand.value().first);
938 preprocess_memory_addresses(result_address_operand.value().first);
939 auto set_slot_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
940 .result_address = instruction.result_address,
941 .value = instruction.slot };
942 this->process_set_ff_instruction(set_slot_instruction);
944 .operand(src_address_operand.value().second)
945 .operand(result_address_operand.value().second)
946 .build();
947 instructions.push_back(sstore_instruction);
949}
950
952{
953#ifdef DISABLE_SLOAD_INSTRUCTION
954 return;
955#endif
956 auto slot_addr = memory_manager.get_slot(instruction.slot_index);
957 if (!slot_addr.has_value()) {
958 return;
959 }
960
961 auto set_slot_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
962 .result_address = instruction.slot_address,
963 .value = *slot_addr };
964 this->process_set_ff_instruction(set_slot_instruction);
965 auto slot_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.slot_address);
966 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
967 auto contract_address_operand =
969 if (!slot_address_operand.has_value() || !result_address_operand.has_value() ||
970 !contract_address_operand.has_value()) {
971 return;
972 }
973 preprocess_memory_addresses(slot_address_operand.value().first);
974 preprocess_memory_addresses(result_address_operand.value().first);
975 preprocess_memory_addresses(contract_address_operand.value().first);
976
978 .operand(slot_address_operand.value().second)
979 .operand(contract_address_operand.value().second)
980 .operand(result_address_operand.value().second)
981 .build();
982 instructions.push_back(sload_instruction);
983 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, result_address_operand.value().first.absolute_address);
984}
985
987{
988#ifdef DISABLE_GETENVVAR_INSTRUCTION
989 return;
990#endif
991 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
992 if (!result_address_operand.has_value()) {
993 return;
994 }
995 preprocess_memory_addresses(result_address_operand.value().first);
997 .operand(result_address_operand.value().second)
998 .operand(instruction.type)
999 .build();
1000 instructions.push_back(getenvvar_instruction);
1001 // special case for timestamp, it returns a 64-bit value
1002 if (instruction.type == 6) {
1004 result_address_operand.value().first.absolute_address);
1005 } else {
1007 result_address_operand.value().first.absolute_address);
1008 }
1009}
1010
1012{
1013#ifdef DISABLE_EMITNULLIFIER_INSTRUCTION
1014 return;
1015#endif
1016 auto nullifier_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.nullifier_address);
1017 if (!nullifier_address_operand.has_value()) {
1018 return;
1019 }
1020 preprocess_memory_addresses(nullifier_address_operand.value().first);
1022 .operand(nullifier_address_operand.value().second)
1023 .build();
1024 instructions.push_back(emitnulifier_instruction);
1025}
1026
1028{
1029#ifdef DISABLE_NULLIFIEREXISTS_INSTRUCTION
1030 return;
1031#endif
1032 auto siloed_nullifier_operand =
1034 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1035 if (!siloed_nullifier_operand.has_value() || !result_address_operand.has_value()) {
1036 return;
1037 }
1038
1039 preprocess_memory_addresses(siloed_nullifier_operand.value().first);
1040 preprocess_memory_addresses(result_address_operand.value().first);
1041
1043 .operand(siloed_nullifier_operand.value().second)
1044 .operand(result_address_operand.value().second)
1045 .build();
1046 instructions.push_back(nullifierexists_instruction);
1047 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
1048}
1049
1051{
1052#ifdef DISABLE_EMITNOTEHASH_INSTRUCTION
1053 return;
1054#endif
1055 auto set_note_hash_instruction = SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1056 .result_address = instruction.note_hash_address,
1057 .value = instruction.note_hash };
1058 this->process_set_ff_instruction(set_note_hash_instruction);
1059
1060 // EMITNOTEHASH expects UINT16 operand
1061 auto note_hash_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.note_hash_address);
1062 if (!note_hash_address_operand.has_value()) {
1063 return;
1064 }
1065 preprocess_memory_addresses(note_hash_address_operand.value().first);
1066
1068 .operand(note_hash_address_operand.value().second)
1069 .build();
1070 instructions.push_back(emitnotehash_instruction);
1071}
1072
1074{
1075#ifdef DISABLE_NOTEHASHEXISTS_INSTRUCTION
1076 return;
1077#endif
1078 auto notehash_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.notehash_address);
1079 auto leaf_index_address_operand =
1081 auto result_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1082 if (!notehash_address_operand.has_value() || !leaf_index_address_operand.has_value() ||
1083 !result_address_operand.has_value()) {
1084 return;
1085 }
1086 preprocess_memory_addresses(notehash_address_operand.value().first);
1087 preprocess_memory_addresses(leaf_index_address_operand.value().first);
1088 preprocess_memory_addresses(result_address_operand.value().first);
1089
1091 .operand(notehash_address_operand.value().second)
1092 .operand(leaf_index_address_operand.value().second)
1093 .operand(result_address_operand.value().second)
1094 .build();
1095 instructions.push_back(notehashexists_instruction);
1096 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_address_operand.value().first.absolute_address);
1097}
1098
1100{
1101#ifdef DISABLE_CALLDATACOPY_INSTRUCTION
1102 return;
1103#endif
1104 auto copy_size_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.copy_size_address);
1105 auto cd_offset_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.cd_offset_address);
1106 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1107 if (!copy_size_address_operand.has_value() || !cd_offset_address_operand.has_value() ||
1108 !dst_address_operand.has_value()) {
1109 return;
1110 }
1111
1112 preprocess_memory_addresses(copy_size_address_operand.value().first);
1113 preprocess_memory_addresses(cd_offset_address_operand.value().first);
1114 preprocess_memory_addresses(dst_address_operand.value().first);
1116 .operand(copy_size_address_operand.value().second)
1117 .operand(cd_offset_address_operand.value().second)
1118 .operand(dst_address_operand.value().second)
1119 .build();
1120 instructions.push_back(calldatacopy_instruction);
1121}
1122
1124{
1125#ifdef DISABLE_SENDL2TOL1MSG_INSTRUCTION
1126 return;
1127#endif
1128 auto recipient_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.recipient_address);
1129 auto content_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.content_address);
1130 if (!recipient_address_operand.has_value() || !content_address_operand.has_value()) {
1131 return;
1132 }
1133 preprocess_memory_addresses(recipient_address_operand.value().first);
1134 preprocess_memory_addresses(content_address_operand.value().first);
1136 .operand(recipient_address_operand.value().second)
1137 .operand(content_address_operand.value().second)
1138 .build();
1139 instructions.push_back(sendl2tol1msg_instruction);
1140}
1141
1143{
1144#ifdef DISABLE_EMITPUBLICLOG_INSTRUCTION
1145 return;
1146#endif
1147 auto log_size_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.log_size_address);
1148 auto log_values_address_operand =
1150 if (!log_size_address_operand.has_value() || !log_values_address_operand.has_value()) {
1151 return;
1152 }
1153 preprocess_memory_addresses(log_size_address_operand.value().first);
1154 preprocess_memory_addresses(log_values_address_operand.value().first);
1156 .operand(log_size_address_operand.value().second)
1157 .operand(log_values_address_operand.value().second)
1158 .build();
1159 instructions.push_back(emitpubliclog_instruction);
1160}
1161
1163{
1164#ifdef DISABLE_CALL_INSTRUCTION
1165 return;
1166#endif
1173 if (!l2_gas.has_value() || !da_gas.has_value() || !contract_address_address.has_value() ||
1174 !calldata_size_address.has_value() || !calldata_address.has_value()) {
1175 return;
1176 }
1177 preprocess_memory_addresses(l2_gas.value().first);
1178 preprocess_memory_addresses(da_gas.value().first);
1182
1184 .result_address = instruction.calldata_size_address,
1185 .value = static_cast<uint32_t>(instruction.calldata_size) });
1186
1187 auto call_instruction_builder = instruction.is_static_call
1190 auto call_instruction = call_instruction_builder.operand(l2_gas.value().second)
1191 .operand(da_gas.value().second)
1192 .operand(contract_address_address.value().second)
1193 .operand(calldata_size_address.value().second)
1194 .operand(calldata_address.value().second)
1195 .build();
1196 instructions.push_back(call_instruction);
1197}
1198
1200{
1201#ifdef DISABLE_RETURNDATASIZE_INSTRUCTION
1202 return;
1203#endif
1204 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1205 if (!dst_address_operand.has_value()) {
1206 return;
1207 }
1208 preprocess_memory_addresses(dst_address_operand.value().first);
1210 .operand(dst_address_operand.value().second)
1211 .build();
1212 instructions.push_back(returndatasize_instruction);
1213 memory_manager.set_memory_address(bb::avm2::MemoryTag::U32, dst_address_operand.value().first.absolute_address);
1214}
1215
1217{
1218#ifdef DISABLE_RETURNDATACOPY_INSTRUCTION
1219 return;
1220#endif
1221 auto copy_size_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.copy_size_address);
1222 auto rd_offset_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.rd_offset_address);
1223 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1224 if (!copy_size_address_operand.has_value() || !rd_offset_address_operand.has_value() ||
1225 !dst_address_operand.has_value()) {
1226 return;
1227 }
1228 preprocess_memory_addresses(copy_size_address_operand.value().first);
1229 preprocess_memory_addresses(rd_offset_address_operand.value().first);
1230 preprocess_memory_addresses(dst_address_operand.value().first);
1231
1233 .operand(copy_size_address_operand.value().second)
1234 .operand(rd_offset_address_operand.value().second)
1235 .operand(dst_address_operand.value().second)
1236 .build();
1237 instructions.push_back(returndatacopy_instruction);
1238}
1239
1241{
1242#ifdef DISABLE_GETCONTRACTINSTANCE_INSTRUCTION
1243 return;
1244#endif
1247
1249 if (!contract_address_address.has_value() || !dst_address.has_value()) {
1250 return;
1251 }
1254
1255 auto get_contract_instance_instruction =
1257 .operand(contract_address_address.value().second)
1258 .operand(dst_address.value().second)
1259 .operand(instruction.member_enum)
1260 .build();
1261 instructions.push_back(get_contract_instance_instruction);
1263 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, dst_address.value().first.absolute_address + 1);
1264}
1265
1267{
1268#ifdef DISABLE_SUCCESSCOPY_INSTRUCTION
1269 return;
1270#endif
1271 auto dst_address_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1272 if (!dst_address_operand.has_value()) {
1273 return;
1274 }
1275 preprocess_memory_addresses(dst_address_operand.value().first);
1277 .operand(dst_address_operand.value().second)
1278 .build();
1279 instructions.push_back(successcopy_instruction);
1280 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, dst_address_operand.value().first.absolute_address);
1281}
1282
1284{
1285#ifdef DISABLE_ECADD_INSTRUCTION
1286 return;
1287#endif
1295
1296 if (!p1_x.has_value() || !p1_y.has_value() || !p1_inf.has_value() || !p2_x.has_value() || !p2_y.has_value() ||
1297 !p2_inf.has_value() || !result.has_value()) {
1298 return;
1299 }
1300
1301 preprocess_memory_addresses(p1_x.value().first);
1302 preprocess_memory_addresses(p1_y.value().first);
1303 preprocess_memory_addresses(p1_inf.value().first);
1304 preprocess_memory_addresses(p2_x.value().first);
1305 preprocess_memory_addresses(p2_y.value().first);
1306 preprocess_memory_addresses(p2_inf.value().first);
1307 preprocess_memory_addresses(result.value().first);
1308
1310 .operand(p1_x.value().second)
1311 .operand(p1_y.value().second)
1312 .operand(p1_inf.value().second)
1313 .operand(p2_x.value().second)
1314 .operand(p2_y.value().second)
1315 .operand(p2_inf.value().second)
1316 .operand(result.value().second)
1317 .build();
1318 instructions.push_back(ecadd_instruction);
1319
1320 // ECADD writes 3 consecutive memory locations: result_x (FF), result_y (FF), result_is_inf (U1)
1321 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, result.value().first.absolute_address);
1322 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, result.value().first.absolute_address + 1);
1323 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result.value().first.absolute_address + 2);
1324}
1325
1327{
1328#ifdef DISABLE_POSEIDON2PERM_INSTRUCTION
1329 return;
1330#endif
1333
1334 if (!src.has_value() || !dst.has_value()) {
1335 return;
1336 }
1337
1338 preprocess_memory_addresses(src.value().first);
1339 preprocess_memory_addresses(dst.value().first);
1340
1342 .operand(src.value().second)
1343 .operand(dst.value().second)
1344 .build();
1345 instructions.push_back(poseidon2perm_instruction);
1346
1347 // Poseidon2 permutation writes 4 consecutive FF values to dst
1348 for (uint32_t i = 0; i < 4; i++) {
1349 memory_manager.set_memory_address(bb::avm2::MemoryTag::FF, dst.value().first.absolute_address + i);
1350 }
1351}
1352
1354{
1355#ifdef DISABLE_KECCAKF1600_INSTRUCTION
1356 return;
1357#endif
1360
1361 if (!src.has_value() || !dst.has_value()) {
1362 return;
1363 }
1364
1365 preprocess_memory_addresses(src.value().first);
1366 preprocess_memory_addresses(dst.value().first);
1367
1369 .operand(dst.value().second)
1370 .operand(src.value().second)
1371 .build();
1372 instructions.push_back(keccakf1600_instruction);
1373
1374 // Keccak-f[1600] permutation writes 25 consecutive U64 values to dst
1375 for (uint32_t i = 0; i < 25; i++) {
1376 memory_manager.set_memory_address(bb::avm2::MemoryTag::U64, dst.value().first.absolute_address + i);
1377 }
1378}
1379
1381{
1382#ifdef DISABLE_SHA256COMPRESSION_INSTRUCTION
1383 return;
1384#endif
1388
1389 if (!state.has_value() || !input.has_value() || !dst.has_value()) {
1390 return;
1391 }
1392
1393 preprocess_memory_addresses(state.value().first);
1394 preprocess_memory_addresses(input.value().first);
1395 preprocess_memory_addresses(dst.value().first);
1396
1398 .operand(dst.value().second)
1399 .operand(state.value().second)
1400 .operand(input.value().second)
1401 .build();
1402 instructions.push_back(sha256compression_instruction);
1403
1404 // SHA256 compression writes 8 consecutive U32 values to dst
1405 for (uint32_t i = 0; i < 8; i++) {
1406 memory_manager.set_memory_address(bb::avm2::MemoryTag::U32, dst.value().first.absolute_address + i);
1407 }
1408}
1409
1411{
1412 auto msg_hash_operand = memory_manager.get_resolved_address_and_operand_16(instruction.msg_hash_address);
1413 auto leaf_index_operand = memory_manager.get_resolved_address_and_operand_16(instruction.leaf_index_address);
1414 auto result_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1415
1416 if (!msg_hash_operand.has_value() || !leaf_index_operand.has_value() || !result_operand.has_value()) {
1417 return;
1418 }
1419
1420 preprocess_memory_addresses(msg_hash_operand.value().first);
1421 preprocess_memory_addresses(leaf_index_operand.value().first);
1422 preprocess_memory_addresses(result_operand.value().first);
1423
1425 .operand(msg_hash_operand.value().second)
1426 .operand(leaf_index_operand.value().second)
1427 .operand(result_operand.value().second)
1428 .build();
1429 instructions.push_back(l1tol2msgexists_instruction);
1430 memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_operand.value().first.absolute_address);
1431}
1432
1434{
1435 auto value_operand = memory_manager.get_resolved_address_and_operand_16(instruction.value_address);
1436 auto radix_operand = memory_manager.get_resolved_address_and_operand_16(instruction.radix_address);
1437 auto num_limbs_operand = memory_manager.get_resolved_address_and_operand_16(instruction.num_limbs_address);
1438 auto output_bits_operand = memory_manager.get_resolved_address_and_operand_16(instruction.output_bits_address);
1439 auto dst_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1440
1441 if (!value_operand.has_value() || !radix_operand.has_value() || !num_limbs_operand.has_value() ||
1442 !output_bits_operand.has_value() || !dst_operand.has_value()) {
1443 return;
1444 }
1445
1446 preprocess_memory_addresses(value_operand.value().first);
1447 preprocess_memory_addresses(radix_operand.value().first);
1448 preprocess_memory_addresses(num_limbs_operand.value().first);
1449 preprocess_memory_addresses(output_bits_operand.value().first);
1450 preprocess_memory_addresses(dst_operand.value().first);
1451
1453 .operand(value_operand.value().second)
1454 .operand(radix_operand.value().second)
1455 .operand(num_limbs_operand.value().second)
1456 .operand(output_bits_operand.value().second)
1457 .operand(dst_operand.value().second)
1458 .build();
1459 instructions.push_back(toradixbe_instruction);
1460
1461 // Use is_output_bits to determine the output memory tag
1462 auto output_tag = instruction.is_output_bits ? bb::avm2::MemoryTag::U1 : bb::avm2::MemoryTag::U8;
1463 memory_manager.set_memory_address(output_tag, dst_operand.value().first.absolute_address);
1464}
1465
1467{
1468 auto level_operand = memory_manager.get_resolved_address_and_operand_16(instruction.level_offset);
1469 auto message_operand = memory_manager.get_resolved_address_and_operand_16(instruction.message_offset);
1470 auto fields_operand = memory_manager.get_resolved_address_and_operand_16(instruction.fields_offset);
1471 auto fields_size_operand = memory_manager.get_resolved_address_and_operand_16(instruction.fields_size_offset);
1472 auto message_size = instruction.message_size;
1473
1474 if (!level_operand.has_value() || !message_operand.has_value() || !fields_operand.has_value() ||
1475 !fields_size_operand.has_value()) {
1476 return;
1477 }
1478
1479 preprocess_memory_addresses(level_operand.value().first);
1480 preprocess_memory_addresses(message_operand.value().first);
1481 preprocess_memory_addresses(fields_operand.value().first);
1482 preprocess_memory_addresses(fields_size_operand.value().first);
1483
1485 .operand(level_operand.value().second)
1486 .operand(message_operand.value().second)
1487 .operand(fields_operand.value().second)
1488 .operand(fields_size_operand.value().second)
1490 .build();
1491 instructions.push_back(debuglog_instruction);
1492}
1493
1497{
1499 // if the block is called by INTERNALCALL, just insert INTERNALRETURN
1500 if (caller != nullptr) {
1501 auto internalreturn_instruction =
1503 instructions.push_back(internalreturn_instruction);
1504 return;
1505 }
1506
1508 if (!return_addr.has_value()) {
1509 return_addr = std::optional<uint32_t>(0);
1510 }
1511
1512 // TODO(defkit): return_size_offset should be const and defined by fuzzer
1513
1514 uint16_t return_size_offset = 5U;
1515 // Ensure operands are created as U16 to match wire format (UINT16)
1517 .operand(return_size_offset)
1519 .operand(static_cast<uint16_t>(return_size))
1520 .build();
1521 instructions.push_back(set_size_instruction);
1522 // RETURN expects UINT16 operands, ensure we cast to uint16_t explicitly
1524 .operand(static_cast<uint16_t>(return_size_offset))
1525 .operand(return_addr.value())
1526 .build();
1527 instructions.push_back(return_instruction);
1528}
1529
1530void ProgramBlock::finalize_with_revert(uint8_t revert_size,
1531 MemoryTagWrapper revert_value_tag,
1532 uint16_t revert_value_offset_index)
1533{
1535
1536 auto revert_addr = memory_manager.get_memory_offset_16(revert_value_tag.value, revert_value_offset_index);
1537 if (!revert_addr.has_value()) {
1538 revert_addr = std::optional<uint32_t>(0);
1539 }
1540
1541 // Once we do more of the randomness in Instruction selection, revert_size_offset we shouldnt need to hardcode
1542 uint16_t revert_size_offset = 5U;
1543 // Ensure operands are created as U16 to match wire format (UINT16)
1545 .operand(revert_size_offset)
1547 .operand(static_cast<uint16_t>(revert_size))
1548 .build();
1549 instructions.push_back(set_size_instruction);
1550 // REVERT_16 expects UINT16 operands, ensure we cast to uint16_t explicitly
1552 .operand(static_cast<uint16_t>(revert_size_offset))
1553 .operand(revert_addr.value())
1554 .build();
1555 instructions.push_back(revert_instruction);
1556}
1557
1558void ProgramBlock::finalize_with_jump(ProgramBlock* target_block, bool copy_memory_manager)
1559{
1561 successors.push_back(target_block);
1562 target_block->predecessors.push_back(this);
1563 target_block->caller = this->caller;
1564 if (copy_memory_manager) {
1565 target_block->memory_manager = memory_manager;
1566 }
1567}
1568
1570 ProgramBlock* target_else_block,
1571 uint16_t condition_offset,
1572 bool copy_memory_manager)
1573{
1575 successors.push_back(target_then_block);
1576 successors.push_back(target_else_block);
1578 target_then_block->predecessors.push_back(this);
1579 target_else_block->predecessors.push_back(this);
1580 target_then_block->caller = this->caller;
1581 target_else_block->caller = this->caller;
1582 if (copy_memory_manager) {
1583 target_then_block->memory_manager = memory_manager;
1584 target_else_block->memory_manager = memory_manager;
1585 }
1586}
1587
1589{
1590 auto internalcall_instruction =
1592 instructions.push_back(internalcall_instruction);
1594 this->successors.push_back(target_block);
1595 target_block->predecessors.push_back(this);
1596 target_block->caller = this->caller;
1597}
1598
1600{
1601 for (auto [instruction_index, target_block] : internal_call_instruction_indicies_to_patch) {
1602 auto internalcall_instruction = instructions.at(instruction_index);
1603 if (target_block->offset == -1) {
1604 throw std::runtime_error("Target block offset is not set, should not happen");
1605 }
1606 auto internalcall_instruction_builder =
1608 .operand(static_cast<uint32_t>(target_block->offset));
1609 instructions.at(instruction_index) = internalcall_instruction_builder.build();
1610 }
1612}
1613
1615{
1617 if (!condition_addr.has_value()) {
1618 return std::nullopt;
1619 }
1620 return condition_addr;
1621}
1622
1631
1636
1638{
1639 memory_manager.set_base_offset(instruction_block.base_offset);
1642 .result_address = AddressRef{ .address = 0, .mode = AddressingMode::Direct },
1643 .value = instruction_block.base_offset });
1644 for (const auto& instr : instruction_block.instructions) {
1645 process_instruction(instr);
1646 }
1647}
1648
1650{
1651 std::visit(
1652 overloaded{
1653 [this](ADD_8_Instruction instruction) { return this->process_add_8_instruction(instruction); },
1654 [this](SUB_8_Instruction instruction) { return this->process_sub_8_instruction(instruction); },
1655 [this](MUL_8_Instruction instruction) { return this->process_mul_8_instruction(instruction); },
1656 [this](DIV_8_Instruction instruction) { return this->process_div_8_instruction(instruction); },
1657 [this](EQ_8_Instruction instruction) { return this->process_eq_8_instruction(instruction); },
1658 [this](LT_8_Instruction instruction) { return this->process_lt_8_instruction(instruction); },
1659 [this](LTE_8_Instruction instruction) { return this->process_lte_8_instruction(instruction); },
1660 [this](AND_8_Instruction instruction) { return this->process_and_8_instruction(instruction); },
1661 [this](OR_8_Instruction instruction) { return this->process_or_8_instruction(instruction); },
1662 [this](XOR_8_Instruction instruction) { return this->process_xor_8_instruction(instruction); },
1663 [this](SHL_8_Instruction instruction) { return this->process_shl_8_instruction(instruction); },
1664 [this](SHR_8_Instruction instruction) { return this->process_shr_8_instruction(instruction); },
1665 [this](SET_8_Instruction instruction) { return this->process_set_8_instruction(instruction); },
1666 [this](SET_16_Instruction instruction) { return this->process_set_16_instruction(instruction); },
1667 [this](SET_32_Instruction instruction) { return this->process_set_32_instruction(instruction); },
1668 [this](SET_64_Instruction instruction) { return this->process_set_64_instruction(instruction); },
1669 [this](SET_128_Instruction instruction) { return this->process_set_128_instruction(instruction); },
1670 [this](SET_FF_Instruction instruction) { return this->process_set_ff_instruction(instruction); },
1671 [this](MOV_8_Instruction instruction) { return this->process_mov_8_instruction(instruction); },
1672 [this](MOV_16_Instruction instruction) { return this->process_mov_16_instruction(instruction); },
1673 [this](FDIV_8_Instruction instruction) { return this->process_fdiv_8_instruction(instruction); },
1674 [this](NOT_8_Instruction instruction) { return this->process_not_8_instruction(instruction); },
1675 [this](ADD_16_Instruction instruction) { return this->process_add_16_instruction(instruction); },
1676 [this](SUB_16_Instruction instruction) { return this->process_sub_16_instruction(instruction); },
1677 [this](MUL_16_Instruction instruction) { return this->process_mul_16_instruction(instruction); },
1678 [this](DIV_16_Instruction instruction) { return this->process_div_16_instruction(instruction); },
1679 [this](FDIV_16_Instruction instruction) { return this->process_fdiv_16_instruction(instruction); },
1680 [this](EQ_16_Instruction instruction) { return this->process_eq_16_instruction(instruction); },
1681 [this](LT_16_Instruction instruction) { return this->process_lt_16_instruction(instruction); },
1682 [this](LTE_16_Instruction instruction) { return this->process_lte_16_instruction(instruction); },
1683 [this](AND_16_Instruction instruction) { return this->process_and_16_instruction(instruction); },
1684 [this](OR_16_Instruction instruction) { return this->process_or_16_instruction(instruction); },
1685 [this](XOR_16_Instruction instruction) { return this->process_xor_16_instruction(instruction); },
1686 [this](NOT_16_Instruction instruction) { return this->process_not_16_instruction(instruction); },
1687 [this](SHL_16_Instruction instruction) { return this->process_shl_16_instruction(instruction); },
1688 [this](SHR_16_Instruction instruction) { return this->process_shr_16_instruction(instruction); },
1689 [this](CAST_8_Instruction instruction) { return this->process_cast_8_instruction(instruction); },
1690 [this](CAST_16_Instruction instruction) { return this->process_cast_16_instruction(instruction); },
1691 [this](SSTORE_Instruction instruction) { return this->process_sstore_instruction(instruction); },
1692 [this](SLOAD_Instruction instruction) { return this->process_sload_instruction(instruction); },
1693 [this](GETENVVAR_Instruction instruction) { return this->process_getenvvar_instruction(instruction); },
1695 return this->process_emitnulifier_instruction(instruction);
1696 },
1698 return this->process_nullifierexists_instruction(instruction);
1699 },
1701 return this->process_emitnotehash_instruction(instruction);
1702 },
1704 return this->process_notehashexists_instruction(instruction);
1705 },
1707 return this->process_calldatacopy_instruction(instruction);
1708 },
1710 return this->process_sendl2tol1msg_instruction(instruction);
1711 },
1713 return this->process_emitpubliclog_instruction(instruction);
1714 },
1715 [this](CALL_Instruction instruction) { return this->process_call_instruction(instruction); },
1717 return this->process_returndatasize_instruction(instruction);
1718 },
1720 return this->process_returndatacopy_instruction(instruction);
1721 },
1723 return this->process_getcontractinstance_instruction(instruction);
1724 },
1725 [this](SUCCESSCOPY_Instruction instruction) { return this->process_successcopy_instruction(instruction); },
1726 [this](ECADD_Instruction instruction) { return this->process_ecadd_instruction(instruction); },
1728 return this->process_poseidon2perm_instruction(instruction);
1729 },
1730 [this](KECCAKF1600_Instruction instruction) { return this->process_keccakf1600_instruction(instruction); },
1732 return this->process_sha256compression_instruction(instruction);
1733 },
1735 return this->process_l1tol2msgexists_instruction(instruction);
1736 },
1737 [this](TORADIXBE_Instruction instruction) { return this->process_toradixbe_instruction(instruction); },
1738 [this](DEBUGLOG_Instruction instruction) { return this->process_debuglog_instruction(instruction); },
1739 [](auto) { throw std::runtime_error("Unknown instruction"); },
1740 },
1741 instruction);
1742}
1743
1744std::vector<bb::avm2::simulation::Instruction> ProgramBlock::get_instructions()
1745{
1746 return instructions;
1747}
::FuzzInstruction FuzzInstruction
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_slot(uint16_t slot_offset_index)
bool is_memory_address_set(uint16_t address)
void set_memory_address(bb::avm2::MemoryTag tag, uint32_t address)
void append_slot(bb::avm2::FF slot)
void set_base_offset(uint32_t base_offset)
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)
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...
void process_debuglog_instruction(DEBUGLOG_Instruction instruction)
void process_returndatacopy_instruction(RETURNDATACOPY_Instruction instruction)
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_emitpubliclog_instruction(EMITPUBLICLOG_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_write_terminating_condition_value()
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_returndatasize_instruction(RETURNDATASIZE_Instruction instruction)
void process_sha256compression_instruction(SHA256COMPRESSION_Instruction instruction)
void process_instruction_block(InstructionBlock &instruction_block)
process the instruction block
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
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
unsigned __int128 uint128_t
Definition serialize.hpp:45
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
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.
NULLIFIEREXISTS: checks if a siloed nullifier exists in the nullifier tree M[result_address] = NULLIF...
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_...
Output of resolving an address in the memory manager In order to resolve a given absolute address wit...
uint32_t operand_address
uint32_t absolute_address
std::optional< uint32_t > pointer_address
SET_128 instruction.
SET_16 instruction.
MemoryTagWrapper value_tag
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]
std::vector< FuzzInstruction > instructions