4#include <gmock/gmock.h>
5#include <gtest/gtest.h>
7#include "barretenberg/aztec/aztec_constants.hpp"
21using simulation::ExecutionEvent;
23using ::bb::avm2::testing::InstructionBuilder;
27using ::testing::AllOf;
28using ::testing::ElementsAre;
33ExecutionEvent create_base_event(
const simulation::Instruction&
instruction,
38 ExecutionEvent ex_event;
41 ex_event.after_context_event.parent_id = parent_id;
42 ex_event.after_context_event.phase = phase;
43 ex_event.before_context_event = ex_event.after_context_event;
49 const auto add_instr =
50 InstructionBuilder(
WireOpCode::ADD_8).operand<uint8_t>(0).operand<uint8_t>(0).operand<uint8_t>(0).build();
51 auto ex_event = create_base_event(add_instr,
context_id, parent_id, phase);
57ExecutionEvent create_call_event(uint32_t
context_id,
60 uint32_t next_context_id)
70 ex_event.next_context_id = next_context_id;
71 ex_event.inputs = { MemoryValue::from<uint32_t>(10),
72 MemoryValue ::from<uint32_t>(11),
74 MemoryValue::from<uint32_t>(0xdeadbeef),
75 MemoryValue::from<uint32_t>(0) };
81 const auto return_instr = InstructionBuilder(
WireOpCode::RETURN).operand<uint8_t>(0).operand<uint8_t>(0).build();
82 auto ex_event = create_base_event(return_instr,
context_id, parent_id, phase);
83 ex_event.inputs = { MemoryValue::from<uint32_t>(2) };
87ExecutionEvent create_error_event(uint32_t
context_id,
90 uint32_t next_context_id)
93 const auto add_instr =
94 InstructionBuilder(
WireOpCode::ADD_8).operand<uint8_t>(0).operand<uint8_t>(0).operand<uint8_t>(0).build();
95 auto ex_event = create_base_event(add_instr,
context_id, parent_id, phase);
98 ex_event.next_context_id = next_context_id;
105TEST(ExecutionTraceGenTest, RegisterAllocation)
107 TestTraceContainer
trace;
119 ExecutionEvent ex_event = {
120 .wire_instruction = instr,
123 .addressing_event = {},
157TEST(ExecutionTraceGenTest, Call)
159 TestTraceContainer
trace;
167 .operand<uint8_t>(10)
168 .operand<uint8_t>(20)
171 Gas allocated_gas = { .l2_gas = 100, .da_gas = 200 };
172 Gas gas_limit = { .l2_gas = 1000, .da_gas = 2000 };
173 Gas gas_used = { .l2_gas = 500, .da_gas = 1900 };
174 Gas gas_left = gas_limit - gas_used;
176 ExecutionEvent ex_event = {
178 .inputs = { MemoryValue::from<uint32_t>(allocated_gas.l2_gas),
179 MemoryValue ::from<uint32_t>(allocated_gas.da_gas),
180 MemoryValue::from<FF>(0xdeadbeef),
181 MemoryValue::from<uint32_t>(0) },
182 .next_context_id = 2,
183 .addressing_event = {
185 { .after_relative = MemoryValue::from<uint32_t>(0),
186 .resolved_operand = MemoryValue::from<uint32_t>(0),
188 { .after_relative = MemoryValue::from<uint32_t>(0),
189 .resolved_operand = MemoryValue::from<uint32_t>(0),
191 { .after_relative = MemoryValue::from<uint32_t>(0),
192 .resolved_operand = MemoryValue::from<uint32_t>(0) },
193 { .after_relative = MemoryValue::from<uint32_t>(0),
194 .resolved_operand = MemoryValue::from<uint32_t>(10) },
195 { .after_relative = MemoryValue::from<uint32_t>(0),
196 .resolved_operand = MemoryValue::from<uint32_t>(20) },
198 .after_context_event = {
200 .contract_addr = 0xdeadbeef,
201 .gas_used = gas_used,
202 .gas_limit = gas_limit,
217 ROW_FIELD_EQ(execution_register_0_, allocated_gas.l2_gas),
218 ROW_FIELD_EQ(execution_register_1_, allocated_gas.da_gas),
234 ROW_FIELD_EQ(execution_is_l2_gas_left_gt_allocated,
true),
235 ROW_FIELD_EQ(execution_is_da_gas_left_gt_allocated,
false))));
238TEST(ExecutionTraceGenTest, Return)
240 TestTraceContainer
trace;
244 const auto return_instr = InstructionBuilder(
WireOpCode::RETURN).operand<uint8_t>(4).operand<uint8_t>(20).build();
246 ExecutionEvent ex_event = {
247 .wire_instruction = return_instr,
248 .inputs = { MemoryValue::from<uint32_t>(2) },
249 .next_context_id = 2,
250 .addressing_event = {
252 { .after_relative = MemoryValue::from<uint32_t>(0),
253 .resolved_operand = MemoryValue::from<uint32_t>(4),
255 { .after_relative = MemoryValue::from<uint32_t>(0),
256 .resolved_operand = MemoryValue::from<uint32_t>(5),
259 .after_context_event = {
261 .contract_addr = 0xdeadbeef,
285TEST(ExecutionTraceGenTest, Gas)
287 TestTraceContainer
trace;
298 ExecutionEvent ex_event = {
299 .wire_instruction = instr,
302 .addressing_event = {},
307 const uint32_t addressing_gas = 50;
308 const uint32_t opcode_gas = exec_instruction_spec.gas_cost.opcode_gas;
309 const uint32_t dynamic_l2_gas = exec_instruction_spec.gas_cost.dyn_l2;
310 const uint32_t dynamic_da_gas = exec_instruction_spec.gas_cost.dyn_da;
311 const uint32_t base_da_gas = exec_instruction_spec.gas_cost.base_da;
313 Gas gas_limit = { .l2_gas = 110149, .da_gas = 100000 };
314 Gas prev_gas_used = { .l2_gas = 100000, .da_gas = 70000 };
316 ex_event.after_context_event.gas_limit = gas_limit;
317 ex_event.before_context_event.gas_used = prev_gas_used;
318 ex_event.gas_event.addressing_gas = addressing_gas;
319 ex_event.gas_event.dynamic_gas_factor = { .l2_gas = 2, .da_gas = 1 };
320 ex_event.gas_event.oog_l2 =
true;
321 ex_event.gas_event.oog_da =
false;
323 uint64_t total_gas_used_l2 = prev_gas_used.l2_gas + opcode_gas + addressing_gas + (dynamic_l2_gas * 2);
324 uint64_t total_gas_used_da = prev_gas_used.da_gas + base_da_gas + (dynamic_da_gas * 1);
326 ex_event.gas_event.total_gas_used_l2 = total_gas_used_l2;
327 ex_event.gas_event.total_gas_used_da = total_gas_used_da;
349 ROW_FIELD_EQ(execution_total_gas_l2, total_gas_used_l2),
350 ROW_FIELD_EQ(execution_total_gas_da, total_gas_used_da))));
353TEST(ExecutionTraceGenTest, DiscardNestedFailContext)
355 TestTraceContainer
trace;
415TEST(ExecutionTraceGenTest, DiscardAppLogicDueToTeardownError)
417 TestTraceContainer
trace;
461TEST(ExecutionTraceGenTest, DiscardAppLogicDueToSecondEnqueuedCallError)
463 TestTraceContainer
trace;
508TEST(ExecutionTraceGenTest, InternalCall)
510 TestTraceContainer
trace;
515 .operand<uint32_t>(10)
518 ExecutionEvent ex_event = {
519 .wire_instruction = instr,
520 .addressing_event = {
523 .resolved_operand = MemoryValue::from<uint32_t>(10) },
526 .before_context_event {
527 .internal_call_id = 1,
528 .internal_call_return_id = 0,
529 .next_internal_call_id = 2,
548TEST(ExecutionTraceGenTest, InternalRetError)
550 TestTraceContainer
trace;
556 .wire_instruction = instr,
557 .addressing_event = {},
558 .before_context_event{
559 .internal_call_id = 1,
560 .internal_call_return_id = 0,
561 .next_internal_call_id = 2,
578 ROW_FIELD_EQ(execution_internal_call_return_id_inv, 0))));
581TEST(ExecutionTraceGenTest, Jump)
583 TestTraceContainer
trace;
587 .operand<uint32_t>(120)
590 ExecutionEvent ex_event_jump = {
591 .wire_instruction = instr,
592 .addressing_event = { .resolution_info = { {
593 .resolved_operand = MemoryValue::from<uint32_t>(120),
607 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_JUMP))));
610TEST(ExecutionTraceGenTest, JumpI)
612 TestTraceContainer
trace;
616 .operand<uint16_t>(654)
617 .operand<uint32_t>(9876)
620 ExecutionEvent ex_event_jumpi = {
621 .wire_instruction = instr,
622 .inputs = { MemoryValue::from<uint1_t>(1) },
623 .addressing_event = { .resolution_info = { {
624 .resolved_operand = MemoryValue::from<uint32_t>(654),
627 .resolved_operand = MemoryValue::from<uint32_t>(9876),
648 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_JUMPI))));
651TEST(ExecutionTraceGenTest, JumpiWrongTag)
653 TestTraceContainer
trace;
657 .operand<uint16_t>(654)
658 .operand<uint32_t>(9876)
661 ExecutionEvent ex_event_jumpi = {
663 .wire_instruction = instr,
664 .inputs = { MemoryValue::from<uint8_t>(1) },
665 .addressing_event = { .resolution_info = { {
666 .resolved_operand = MemoryValue::from<uint32_t>(654),
669 .resolved_operand = MemoryValue::from<uint32_t>(9876),
692 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_JUMPI))));
695TEST(ExecutionTraceGenTest, Mov16)
697 TestTraceContainer
trace;
701 .operand<uint32_t>(1000)
702 .operand<uint32_t>(1001)
705 ExecutionEvent ex_event_mov = {
706 .wire_instruction = instr,
707 .inputs = { MemoryValue::from<uint128_t>(100) },
708 .output = MemoryValue::from<uint128_t>(100),
709 .addressing_event = { .resolution_info = { {
710 .resolved_operand = MemoryValue::from<uint32_t>(1000),
713 .resolved_operand = MemoryValue::from<uint32_t>(1001),
736 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_MOV))));
739TEST(ExecutionTraceGenTest, Mov8)
741 TestTraceContainer
trace;
745 .operand<uint32_t>(10)
746 .operand<uint32_t>(11)
749 ExecutionEvent ex_event_mov = {
750 .wire_instruction = instr,
751 .inputs = { MemoryValue::from<uint64_t>(100) },
752 .output = MemoryValue::from<uint64_t>(100),
753 .addressing_event = { .resolution_info = { {
754 .resolved_operand = MemoryValue::from<uint32_t>(10),
757 .resolved_operand = MemoryValue::from<uint32_t>(11),
780 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_MOV))));
783TEST(ExecutionTraceGenTest, SuccessCopy)
785 TestTraceContainer
trace;
788 .operand<uint8_t>(45)
791 ExecutionEvent ex_event = {
792 .wire_instruction = instr,
794 .addressing_event = {
795 .resolution_info = { { .resolved_operand = MemoryValue::from<uint8_t>(45) } }
797 .after_context_event = { .last_child_success =
true }
813 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_SUCCESSCOPY))));
816TEST(ExecutionTraceGenTest, RdSize)
818 TestTraceContainer
trace;
821 .operand<uint16_t>(1234)
824 ExecutionEvent ex_event = {
825 .wire_instruction = instr,
827 .addressing_event = {
828 .resolution_info = { { .resolved_operand = MemoryValue::from<uint16_t>(1234) } }
831 .after_context_event = { .last_child_rd_size = 100 }
846 ROW_FIELD_EQ(execution_last_child_returndata_size, 100),
847 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_RETURNDATASIZE))));
850TEST(ExecutionTraceGenTest, SLoad)
852 TestTraceContainer
trace;
855 uint16_t slot_offset = 1234;
856 uint16_t contract_address_offset = 2345;
857 uint16_t dst_offset = 4567;
860 FF contract_address = 0xdeadbeef;
864 .operand<uint16_t>(slot_offset)
865 .operand<uint16_t>(contract_address_offset)
866 .operand<uint16_t>(dst_offset)
869 ExecutionEvent ex_event = {
870 .wire_instruction = instr,
871 .inputs = { MemoryValue::from<FF>(
slot), MemoryValue::from<FF>(contract_address) },
872 .output = MemoryValue::from<FF>(dst_value),
873 .addressing_event = { .resolution_info = { { .resolved_operand = MemoryValue::from<uint16_t>(slot_offset) },
874 { .resolved_operand =
875 MemoryValue::from<uint16_t>(contract_address_offset) },
876 { .resolved_operand = MemoryValue::from<uint16_t>(dst_offset) } } },
888 ROW_FIELD_EQ(execution_rop_1_, contract_address_offset),
896 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_SLOAD))));
899TEST(ExecutionTraceGenTest, SStore)
901 TestTraceContainer
trace;
904 uint16_t slot_offset = 1234;
905 uint16_t value_offset = 4567;
911 InstructionBuilder(
WireOpCode::SSTORE).operand<uint16_t>(value_offset).operand<uint16_t>(slot_offset).build();
913 ExecutionEvent ex_event = {
914 .wire_instruction = instr,
915 .inputs = { MemoryValue::from<FF>(
value), MemoryValue::from<FF>(
slot) },
916 .addressing_event = {
918 { .resolved_operand = MemoryValue::from<uint16_t>(value_offset) },
919 { .resolved_operand = MemoryValue::from<uint16_t>(slot_offset) },
921 .before_context_event = {
923 .public_data_tree = {
929 .dynamic_gas_factor = { .da_gas = 1 },
948 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_SSTORE),
951 FF(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX - 5).invert()),
955TEST(ExecutionTraceGenTest, NoteHashExists)
957 TestTraceContainer
trace;
960 uint16_t unique_note_hash_offset = 1234;
961 uint16_t leaf_index_offset = 4567;
962 uint16_t dst_offset = 8901;
964 FF unique_note_hash = 42;
965 uint64_t leaf_index = 27;
966 uint1_t dst_value = 1;
969 .operand<uint16_t>(unique_note_hash_offset)
970 .operand<uint16_t>(leaf_index_offset)
971 .operand<uint16_t>(dst_offset)
974 ExecutionEvent ex_event = {
975 .wire_instruction = instr,
976 .inputs = { MemoryValue::from<FF>(unique_note_hash), MemoryValue::from<uint64_t>(leaf_index) },
977 .output = MemoryValue::from<uint1_t>(dst_value),
978 .addressing_event = { .resolution_info = { { .resolved_operand =
979 MemoryValue::from<uint16_t>(unique_note_hash_offset) },
980 { .resolved_operand =
981 MemoryValue::from<uint16_t>(leaf_index_offset) },
982 { .resolved_operand = MemoryValue::from<uint16_t>(dst_offset) } } },
994 ROW_FIELD_EQ(execution_rop_0_, unique_note_hash_offset),
1004 ROW_FIELD_EQ(execution_note_hash_tree_leaf_count,
static_cast<uint64_t
>(NOTE_HASH_TREE_LEAF_COUNT)),
1005 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_NOTEHASH_EXISTS))));
1008TEST(ExecutionTraceGenTest, EmitNoteHash)
1010 TestTraceContainer
trace;
1011 ExecutionTraceBuilder
builder;
1013 uint16_t note_hash_offset = 1234;
1016 uint32_t prev_num_note_hashes_emitted = MAX_NOTE_HASHES_PER_TX - 1;
1020 ExecutionEvent ex_event = {
1021 .wire_instruction = instr,
1022 .inputs = { MemoryValue::from<FF>(
note_hash) },
1023 .addressing_event = {
1024 .resolution_info = { { .resolved_operand =
1025 MemoryValue::from<uint16_t>(note_hash_offset) } } },
1026 .before_context_event = {
1029 .counter = prev_num_note_hashes_emitted,
1047 FF(MAX_NOTE_HASHES_PER_TX - prev_num_note_hashes_emitted).invert()),
1049 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_EMIT_NOTEHASH))));
1052TEST(ExecutionTraceGenTest, L1ToL2MessageExists)
1054 TestTraceContainer
trace;
1055 ExecutionTraceBuilder
builder;
1057 uint16_t msg_hash_offset = 1234;
1058 uint16_t leaf_index_offset = 4567;
1059 uint16_t dst_offset = 8901;
1062 uint64_t leaf_index = 27;
1063 uint1_t dst_value = 1;
1066 .operand<uint16_t>(msg_hash_offset)
1067 .operand<uint16_t>(leaf_index_offset)
1068 .operand<uint16_t>(dst_offset)
1071 ExecutionEvent ex_event = {
1072 .wire_instruction = instr,
1073 .inputs = { MemoryValue::from<FF>(msg_hash), MemoryValue::from<uint64_t>(leaf_index) },
1074 .output = MemoryValue::from<uint1_t>(dst_value),
1075 .addressing_event = { .resolution_info = { { .resolved_operand = MemoryValue::from<uint16_t>(msg_hash_offset) },
1076 { .resolved_operand =
1077 MemoryValue::from<uint16_t>(leaf_index_offset) },
1078 { .resolved_operand = MemoryValue::from<uint16_t>(dst_offset) } } },
1088 ROW_FIELD_EQ(execution_sel_execute_l1_to_l2_message_exists, 1),
1100 static_cast<uint64_t
>(L1_TO_L2_MSG_TREE_LEAF_COUNT)),
1101 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_L1_TO_L2_MESSAGE_EXISTS))));
1104TEST(ExecutionTraceGenTest, NullifierExists)
1106 TestTraceContainer
trace;
1107 ExecutionTraceBuilder
builder;
1109 uint16_t nullifier_offset = 100;
1110 uint16_t exists_offset = 300;
1111 FF siloed_nullifier = 0x123456;
1115 .operand<uint16_t>(nullifier_offset)
1116 .operand<uint16_t>(exists_offset)
1118 ExecutionEvent ex_event = { .wire_instruction = instr,
1121 .addressing_event = {
1122 .resolution_info = {
1123 { .resolved_operand = MemoryValue::from<FF>(siloed_nullifier) },
1124 { .resolved_operand = MemoryValue::from<uint16_t>(exists_offset) } } } };
1127 EXPECT_THAT(
trace.as_rows(),
1133 ROW_FIELD_EQ(execution_sel_execute_nullifier_exists, 1),
1140 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_NULLIFIER_EXISTS))));
1143TEST(ExecutionTraceGenTest, EmitNullifier)
1145 TestTraceContainer
trace;
1146 ExecutionTraceBuilder
builder;
1148 uint16_t nullifier_offset = 100;
1149 FF nullifier = 0x123456;
1150 uint32_t prev_num_nullifiers_emitted = MAX_NULLIFIERS_PER_TX - 1;
1152 const auto instr = InstructionBuilder(WireOpCode::EMITNULLIFIER).operand<uint16_t>(nullifier_offset).build();
1154 ExecutionEvent ex_event = {
1155 .wire_instruction = instr,
1156 .inputs = { MemoryValue::from_tag(ValueTag::FF, nullifier) },
1157 .addressing_event = {
1158 .resolution_info = { { .resolved_operand = MemoryValue::from<FF>(nullifier) } } },
1159 .before_context_event = {
1162 .counter = prev_num_nullifiers_emitted,
1169 EXPECT_THAT(
trace.as_rows(),
1180 FF(MAX_NULLIFIERS_PER_TX - prev_num_nullifiers_emitted).invert()),
1182 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_EMIT_NULLIFIER))));
1185TEST(ExecutionTraceGenTest, SendL2ToL1Msg)
1187 TestTraceContainer
trace;
1188 ExecutionTraceBuilder
builder;
1190 uint16_t recipient_offset = 100;
1191 uint16_t content_offset = 101;
1192 FF recipient = 0x123456;
1193 FF content = 0xdeadbeef;
1194 uint32_t prev_num_l2_to_l1_msgs = MAX_L2_TO_L1_MSGS_PER_TX - 1;
1196 const auto instr = InstructionBuilder(WireOpCode::SENDL2TOL1MSG)
1197 .operand<uint16_t>(recipient_offset)
1198 .operand<uint16_t>(content_offset)
1201 ExecutionEvent ex_event = { .wire_instruction = instr,
1202 .inputs = { MemoryValue::from_tag(ValueTag::FF, recipient),
1203 MemoryValue::from_tag(ValueTag::FF, content) },
1204 .addressing_event = { .resolution_info = { { .resolved_operand =
1205 MemoryValue::from<FF>(recipient) },
1206 { .resolved_operand =
1207 MemoryValue::from<FF>(content) } } },
1208 .before_context_event = {
1209 .numL2ToL1Messages = prev_num_l2_to_l1_msgs,
1220 ROW_FIELD_EQ(execution_sel_execute_send_l2_to_l1_msg, 1),
1226 FF(MAX_L2_TO_L1_MSGS_PER_TX - prev_num_l2_to_l1_msgs).invert()),
1229 AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX + prev_num_l2_to_l1_msgs),
1230 ROW_FIELD_EQ(execution_subtrace_operation_id, AVM_EXEC_OP_ID_SENDL2TOL1MSG))));
TEST(acir_formal_proofs, uint_terms_add)
Tests 128-bit unsigned addition Verifies that the ACIR implementation of addition is correct Executio...
bb::field< bb::Bn254FrParams > FF
static TaggedValue from_tag(ValueTag tag, FF value)
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
Process the ALU events and populate the ALU relevant columns in the trace.
std::vector< AvmFullRowConstRef > as_rows() const
#define ROW_FIELD_EQ(field_name, expression)
const std::unordered_map< ExecutionOpCode, ExecInstructionSpec > & get_exec_instruction_spec()
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept