4#include <gmock/gmock.h>
5#include <gtest/gtest.h>
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 = {},
150TEST(ExecutionTraceGenTest, Call)
152 TestTraceContainer
trace;
160 .operand<uint8_t>(10)
161 .operand<uint8_t>(20)
164 Gas allocated_gas = { .l2_gas = 100, .da_gas = 200 };
165 Gas gas_limit = { .l2_gas = 1000, .da_gas = 2000 };
166 Gas gas_used = { .l2_gas = 500, .da_gas = 1900 };
167 Gas gas_left = gas_limit - gas_used;
169 ExecutionEvent ex_event = {
171 .inputs = { MemoryValue::from<uint32_t>(allocated_gas.l2_gas),
172 MemoryValue ::from<uint32_t>(allocated_gas.da_gas),
173 MemoryValue::from<FF>(0xdeadbeef),
174 MemoryValue::from<uint32_t>(0) },
175 .next_context_id = 2,
176 .addressing_event = {
178 { .after_relative = MemoryValue::from<uint32_t>(0),
179 .resolved_operand = MemoryValue::from<uint32_t>(0),
181 { .after_relative = MemoryValue::from<uint32_t>(0),
182 .resolved_operand = MemoryValue::from<uint32_t>(0),
184 { .after_relative = MemoryValue::from<uint32_t>(0),
185 .resolved_operand = MemoryValue::from<uint32_t>(0) },
186 { .after_relative = MemoryValue::from<uint32_t>(0),
187 .resolved_operand = MemoryValue::from<uint32_t>(10) },
188 { .after_relative = MemoryValue::from<uint32_t>(0),
189 .resolved_operand = MemoryValue::from<uint32_t>(20) },
191 .after_context_event = {
193 .contract_addr = 0xdeadbeef,
194 .gas_used = gas_used,
195 .gas_limit = gas_limit,
210 ROW_FIELD_EQ(execution_register_0_, allocated_gas.l2_gas),
211 ROW_FIELD_EQ(execution_register_1_, allocated_gas.da_gas),
227 ROW_FIELD_EQ(execution_is_l2_gas_left_gt_allocated,
true),
228 ROW_FIELD_EQ(execution_is_da_gas_left_gt_allocated,
false))));
231TEST(ExecutionTraceGenTest, Return)
233 TestTraceContainer
trace;
237 const auto return_instr = InstructionBuilder(
WireOpCode::RETURN).operand<uint8_t>(4).operand<uint8_t>(20).build();
239 ExecutionEvent ex_event = {
240 .wire_instruction = return_instr,
241 .inputs = { MemoryValue::from<uint32_t>(2) },
242 .next_context_id = 2,
243 .addressing_event = {
245 { .after_relative = MemoryValue::from<uint32_t>(0),
246 .resolved_operand = MemoryValue::from<uint32_t>(4),
248 { .after_relative = MemoryValue::from<uint32_t>(0),
249 .resolved_operand = MemoryValue::from<uint32_t>(5),
252 .after_context_event = {
254 .contract_addr = 0xdeadbeef,
278TEST(ExecutionTraceGenTest, Gas)
280 TestTraceContainer
trace;
291 ExecutionEvent ex_event = {
292 .wire_instruction = instr,
295 .addressing_event = {},
300 const uint32_t addressing_gas = 50;
301 const uint32_t opcode_gas = exec_instruction_spec.gas_cost.opcode_gas;
302 const uint32_t dynamic_l2_gas = exec_instruction_spec.gas_cost.dyn_l2;
303 const uint32_t dynamic_da_gas = exec_instruction_spec.gas_cost.dyn_da;
304 const uint32_t base_da_gas = exec_instruction_spec.gas_cost.base_da;
306 Gas gas_limit = { .l2_gas = 110149, .da_gas = 100000 };
307 Gas prev_gas_used = { .l2_gas = 100000, .da_gas = 70000 };
309 ex_event.after_context_event.gas_limit = gas_limit;
310 ex_event.before_context_event.gas_used = prev_gas_used;
311 ex_event.gas_event.addressing_gas = addressing_gas;
312 ex_event.gas_event.dynamic_gas_factor = { .l2_gas = 2, .da_gas = 1 };
313 ex_event.gas_event.oog_l2 =
true;
314 ex_event.gas_event.oog_da =
false;
316 uint64_t total_gas_used_l2 = prev_gas_used.l2_gas + opcode_gas + addressing_gas + (dynamic_l2_gas * 2);
317 uint64_t total_gas_used_da = prev_gas_used.da_gas + base_da_gas + (dynamic_da_gas * 1);
319 ex_event.gas_event.total_gas_used_l2 = total_gas_used_l2;
320 ex_event.gas_event.total_gas_used_da = total_gas_used_da;
342 ROW_FIELD_EQ(execution_total_gas_l2, total_gas_used_l2),
343 ROW_FIELD_EQ(execution_total_gas_da, total_gas_used_da))));
346TEST(ExecutionTraceGenTest, DiscardNestedFailContext)
348 TestTraceContainer
trace;
408TEST(ExecutionTraceGenTest, DiscardAppLogicDueToTeardownError)
410 TestTraceContainer
trace;
454TEST(ExecutionTraceGenTest, DiscardAppLogicDueToSecondEnqueuedCallError)
456 TestTraceContainer
trace;
501TEST(ExecutionTraceGenTest, InternalCall)
503 TestTraceContainer
trace;
508 .operand<uint32_t>(10)
511 ExecutionEvent ex_event = {
512 .wire_instruction = instr,
513 .addressing_event = {
516 .resolved_operand = MemoryValue::from<uint32_t>(10) },
519 .before_context_event {
520 .internal_call_id = 1,
521 .internal_call_return_id = 0,
522 .next_internal_call_id = 2,
541TEST(ExecutionTraceGenTest, InternalRetError)
543 TestTraceContainer
trace;
549 .wire_instruction = instr,
550 .addressing_event = {},
551 .before_context_event{
552 .internal_call_id = 1,
553 .internal_call_return_id = 0,
554 .next_internal_call_id = 2,
571 ROW_FIELD_EQ(execution_internal_call_return_id_inv, 0))));
574TEST(ExecutionTraceGenTest, Jump)
576 TestTraceContainer
trace;
580 .operand<uint32_t>(120)
583 ExecutionEvent ex_event_jump = {
584 .wire_instruction = instr,
585 .addressing_event = { .resolution_info = { {
586 .resolved_operand = MemoryValue::from<uint32_t>(120),
603TEST(ExecutionTraceGenTest, JumpI)
605 TestTraceContainer
trace;
609 .operand<uint16_t>(654)
610 .operand<uint32_t>(9876)
613 ExecutionEvent ex_event_jumpi = {
614 .wire_instruction = instr,
615 .inputs = { MemoryValue::from<uint1_t>(1) },
616 .addressing_event = { .resolution_info = { {
617 .resolved_operand = MemoryValue::from<uint32_t>(654),
620 .resolved_operand = MemoryValue::from<uint32_t>(9876),
644TEST(ExecutionTraceGenTest, JumpiWrongTag)
646 TestTraceContainer
trace;
650 .operand<uint16_t>(654)
651 .operand<uint32_t>(9876)
654 ExecutionEvent ex_event_jumpi = {
656 .wire_instruction = instr,
657 .inputs = { MemoryValue::from<uint8_t>(1) },
658 .addressing_event = { .resolution_info = { {
659 .resolved_operand = MemoryValue::from<uint32_t>(654),
662 .resolved_operand = MemoryValue::from<uint32_t>(9876),
688TEST(ExecutionTraceGenTest, Mov16)
690 TestTraceContainer
trace;
694 .operand<uint32_t>(1000)
695 .operand<uint32_t>(1001)
698 ExecutionEvent ex_event_mov = {
699 .wire_instruction = instr,
700 .inputs = { MemoryValue::from<uint128_t>(100) },
701 .output = MemoryValue::from<uint128_t>(100),
702 .addressing_event = { .resolution_info = { {
703 .resolved_operand = MemoryValue::from<uint32_t>(1000),
706 .resolved_operand = MemoryValue::from<uint32_t>(1001),
732TEST(ExecutionTraceGenTest, Mov8)
734 TestTraceContainer
trace;
738 .operand<uint32_t>(10)
739 .operand<uint32_t>(11)
742 ExecutionEvent ex_event_mov = {
743 .wire_instruction = instr,
744 .inputs = { MemoryValue::from<uint64_t>(100) },
745 .output = MemoryValue::from<uint64_t>(100),
746 .addressing_event = { .resolution_info = { {
747 .resolved_operand = MemoryValue::from<uint32_t>(10),
750 .resolved_operand = MemoryValue::from<uint32_t>(11),
776TEST(ExecutionTraceGenTest, SuccessCopy)
778 TestTraceContainer
trace;
781 .operand<uint8_t>(45)
784 ExecutionEvent ex_event = {
785 .wire_instruction = instr,
787 .addressing_event = {
788 .resolution_info = { { .resolved_operand = MemoryValue::from<uint8_t>(45) } }
790 .after_context_event = { .last_child_success =
true }
809TEST(ExecutionTraceGenTest, RdSize)
811 TestTraceContainer
trace;
814 .operand<uint16_t>(1234)
817 ExecutionEvent ex_event = {
818 .wire_instruction = instr,
820 .addressing_event = {
821 .resolution_info = { { .resolved_operand = MemoryValue::from<uint16_t>(1234) } }
824 .after_context_event = { .last_child_rd_size = 100 }
839 ROW_FIELD_EQ(execution_last_child_returndata_size, 100),
843TEST(ExecutionTraceGenTest, SLoad)
845 TestTraceContainer
trace;
848 uint16_t slot_offset = 1234;
849 uint16_t dst_offset = 4567;
855 InstructionBuilder(
WireOpCode::SLOAD).operand<uint16_t>(slot_offset).operand<uint16_t>(dst_offset).build();
857 ExecutionEvent ex_event = {
858 .wire_instruction = instr,
859 .inputs = { MemoryValue::from<FF>(
slot) },
860 .output = MemoryValue::from<FF>(dst_value),
861 .addressing_event = { .resolution_info = { { .resolved_operand = MemoryValue::from<uint16_t>(slot_offset) },
862 { .resolved_operand = MemoryValue::from<uint16_t>(dst_offset) } } },
882TEST(ExecutionTraceGenTest, SStore)
884 TestTraceContainer
trace;
887 uint16_t slot_offset = 1234;
888 uint16_t value_offset = 4567;
894 InstructionBuilder(
WireOpCode::SSTORE).operand<uint16_t>(value_offset).operand<uint16_t>(slot_offset).build();
896 ExecutionEvent ex_event = {
897 .wire_instruction = instr,
898 .inputs = { MemoryValue::from<FF>(
value), MemoryValue::from<FF>(
slot) },
899 .addressing_event = {
901 { .resolved_operand = MemoryValue::from<uint16_t>(value_offset) },
902 { .resolved_operand = MemoryValue::from<uint16_t>(slot_offset) },
904 .before_context_event = {
906 .public_data_tree = {
912 .dynamic_gas_factor = { .da_gas = 1 },
938TEST(ExecutionTraceGenTest, NoteHashExists)
940 TestTraceContainer
trace;
943 uint16_t unique_note_hash_offset = 1234;
944 uint16_t leaf_index_offset = 4567;
945 uint16_t dst_offset = 8901;
947 FF unique_note_hash = 42;
948 uint64_t leaf_index = 27;
949 uint1_t dst_value = 1;
952 .operand<uint16_t>(unique_note_hash_offset)
953 .operand<uint16_t>(leaf_index_offset)
954 .operand<uint16_t>(dst_offset)
957 ExecutionEvent ex_event = {
958 .wire_instruction = instr,
959 .inputs = { MemoryValue::from<FF>(unique_note_hash), MemoryValue::from<uint64_t>(leaf_index) },
960 .output = MemoryValue::from<uint1_t>(dst_value),
961 .addressing_event = { .resolution_info = { { .resolved_operand =
962 MemoryValue::from<uint16_t>(unique_note_hash_offset) },
963 { .resolved_operand =
964 MemoryValue::from<uint16_t>(leaf_index_offset) },
965 { .resolved_operand = MemoryValue::from<uint16_t>(dst_offset) } } },
977 ROW_FIELD_EQ(execution_rop_0_, unique_note_hash_offset),
991TEST(ExecutionTraceGenTest, EmitNoteHash)
993 TestTraceContainer
trace;
996 uint16_t note_hash_offset = 1234;
1003 ExecutionEvent ex_event = {
1004 .wire_instruction = instr,
1005 .inputs = { MemoryValue::from<FF>(
note_hash) },
1006 .addressing_event = {
1007 .resolution_info = { { .resolved_operand =
1008 MemoryValue::from<uint16_t>(note_hash_offset) } } },
1009 .before_context_event = {
1012 .counter = prev_num_note_hashes_emitted,
1035TEST(ExecutionTraceGenTest, L1ToL2MessageExists)
1037 TestTraceContainer
trace;
1038 ExecutionTraceBuilder
builder;
1040 uint16_t msg_hash_offset = 1234;
1041 uint16_t leaf_index_offset = 4567;
1042 uint16_t dst_offset = 8901;
1045 uint64_t leaf_index = 27;
1046 uint1_t dst_value = 1;
1049 .operand<uint16_t>(msg_hash_offset)
1050 .operand<uint16_t>(leaf_index_offset)
1051 .operand<uint16_t>(dst_offset)
1054 ExecutionEvent ex_event = {
1055 .wire_instruction = instr,
1056 .inputs = { MemoryValue::from<FF>(msg_hash), MemoryValue::from<uint64_t>(leaf_index) },
1057 .output = MemoryValue::from<uint1_t>(dst_value),
1058 .addressing_event = { .resolution_info = { { .resolved_operand = MemoryValue::from<uint16_t>(msg_hash_offset) },
1059 { .resolved_operand =
1060 MemoryValue::from<uint16_t>(leaf_index_offset) },
1061 { .resolved_operand = MemoryValue::from<uint16_t>(dst_offset) } } },
1071 ROW_FIELD_EQ(execution_sel_execute_l1_to_l2_message_exists, 1),
1087TEST(ExecutionTraceGenTest, NullifierExists)
1089 TestTraceContainer
trace;
1090 ExecutionTraceBuilder
builder;
1092 uint16_t nullifier_offset = 100;
1093 uint16_t address_offset = 200;
1094 uint16_t exists_offset = 300;
1100 .operand<uint16_t>(nullifier_offset)
1101 .operand<uint16_t>(address_offset)
1102 .operand<uint16_t>(exists_offset)
1104 ExecutionEvent ex_event = {
1105 .wire_instruction = instr,
1108 .addressing_event = { .resolution_info = { { .resolved_operand = MemoryValue::from<FF>(
nullifier) },
1109 { .resolved_operand = MemoryValue::from<FF>(
address) },
1110 { .resolved_operand =
1111 MemoryValue::from<uint16_t>(exists_offset) } } }
1115 EXPECT_THAT(
trace.as_rows(),
1121 ROW_FIELD_EQ(execution_sel_execute_nullifier_exists, 1),
1134TEST(ExecutionTraceGenTest, EmitNullifier)
1136 TestTraceContainer
trace;
1137 ExecutionTraceBuilder
builder;
1139 uint16_t nullifier_offset = 100;
1143 const auto instr = InstructionBuilder(WireOpCode::EMITNULLIFIER).operand<uint16_t>(nullifier_offset).build();
1145 ExecutionEvent ex_event = {
1146 .wire_instruction = instr,
1147 .inputs = { MemoryValue::from_tag(ValueTag::FF,
nullifier) },
1148 .addressing_event = {
1149 .resolution_info = { { .resolved_operand = MemoryValue::from<FF>(
nullifier) } } },
1150 .before_context_event = {
1153 .counter = prev_num_nullifiers_emitted,
1160 EXPECT_THAT(
trace.as_rows(),
1176TEST(ExecutionTraceGenTest, SendL2ToL1Msg)
1178 TestTraceContainer
trace;
1179 ExecutionTraceBuilder
builder;
1181 uint16_t recipient_offset = 100;
1182 uint16_t content_offset = 101;
1187 const auto instr = InstructionBuilder(WireOpCode::SENDL2TOL1MSG)
1188 .operand<uint16_t>(recipient_offset)
1189 .operand<uint16_t>(content_offset)
1192 ExecutionEvent ex_event = { .wire_instruction = instr,
1193 .inputs = { MemoryValue::from_tag(ValueTag::FF,
recipient),
1194 MemoryValue::from_tag(ValueTag::FF,
content) },
1195 .addressing_event = { .resolution_info = { { .resolved_operand =
1197 { .resolved_operand =
1198 MemoryValue::from<FF>(
content) } } },
1199 .before_context_event = {
1200 .numL2ToL1Messages = prev_num_l2_to_l1_msgs,
1211 ROW_FIELD_EQ(execution_sel_execute_send_l2_to_l1_msg, 1),
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
#define AVM_EXEC_OP_ID_SUCCESSCOPY
#define AVM_EXEC_OP_ID_NULLIFIER_EXISTS
#define AVM_EXEC_OP_ID_SSTORE
#define AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_L2_TO_L1_MSGS_ROW_IDX
#define AVM_EXEC_OP_ID_EMIT_NULLIFIER
#define AVM_EXEC_OP_ID_NOTEHASH_EXISTS
#define AVM_EXEC_OP_ID_SLOAD
#define NOTE_HASH_TREE_LEAF_COUNT
#define AVM_EXEC_OP_ID_JUMP
#define L1_TO_L2_MSG_TREE_LEAF_COUNT
#define AVM_EXEC_OP_ID_EMIT_NOTEHASH
#define MAX_L2_TO_L1_MSGS_PER_TX
#define MAX_NOTE_HASHES_PER_TX
#define AVM_EXEC_OP_ID_MOV
#define MAX_NULLIFIERS_PER_TX
#define AVM_EXEC_OP_ID_SENDL2TOL1MSG
#define AVM_EXEC_OP_ID_RETURNDATASIZE
#define AVM_EXEC_OP_ID_JUMPI
#define AVM_EXEC_OP_ID_L1_TO_L2_MESSAGE_EXISTS
#define MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
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