diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index 4aa6c03603c..13ff821ee2e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -434,37 +434,42 @@ std::vector Execution::gen_trace(std::vector const& instructio break; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6284): support indirect for below case OpCode::SENDER: - trace_builder.op_sender(std::get(inst.operands.at(1))); + trace_builder.op_sender(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; case OpCode::ADDRESS: - trace_builder.op_address(std::get(inst.operands.at(1))); + trace_builder.op_address(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; case OpCode::STORAGEADDRESS: - trace_builder.op_storage_address(std::get(inst.operands.at(1))); + trace_builder.op_storage_address(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::FEEPERL2GAS: - trace_builder.op_fee_per_l2_gas(std::get(inst.operands.at(1))); + trace_builder.op_fee_per_l2_gas(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::FEEPERDAGAS: - trace_builder.op_fee_per_da_gas(std::get(inst.operands.at(1))); + trace_builder.op_fee_per_da_gas(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::TRANSACTIONFEE: - trace_builder.op_transaction_fee(std::get(inst.operands.at(1))); + trace_builder.op_transaction_fee(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::CHAINID: - trace_builder.op_chain_id(std::get(inst.operands.at(1))); + trace_builder.op_chain_id(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; case OpCode::VERSION: - trace_builder.op_version(std::get(inst.operands.at(1))); + trace_builder.op_version(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; case OpCode::BLOCKNUMBER: - trace_builder.op_block_number(std::get(inst.operands.at(1))); + trace_builder.op_block_number(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::COINBASE: - trace_builder.op_coinbase(std::get(inst.operands.at(1))); + trace_builder.op_coinbase(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; case OpCode::TIMESTAMP: - trace_builder.op_timestamp(std::get(inst.operands.at(1))); + trace_builder.op_timestamp(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; case OpCode::NOTEHASHEXISTS: trace_builder.op_note_hash_exists(std::get(inst.operands.at(1)), diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index daaea2106ca..0ecd5d1179a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -1149,21 +1149,32 @@ void AvmTraceBuilder::op_cmov( } // Helper function to add kernel lookup operations into the main trace -Row AvmTraceBuilder::create_kernel_lookup_opcode(uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag) +Row AvmTraceBuilder::create_kernel_lookup_opcode( + bool indirect, uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag) { auto const clk = static_cast(main_trace.size()) + 1; + bool tag_match = true; + uint32_t direct_dst_offset = dst_offset; + if (indirect) { + auto read_ind_dst = + mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, dst_offset); + direct_dst_offset = uint32_t(read_ind_dst.val); + tag_match = tag_match && read_ind_dst.tag_match; + } + AvmMemoryTag r_tag = AvmMemoryTag::U0; - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IA, dst_offset, value, r_tag, w_tag); + mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IA, direct_dst_offset, value, r_tag, w_tag); return Row{ .avm_main_clk = clk, .avm_kernel_kernel_in_offset = selector, .avm_main_call_ptr = call_ptr, .avm_main_ia = value, - .avm_main_ind_a = 0, + .avm_main_ind_a = indirect ? FF(dst_offset) : FF(0), + .avm_main_ind_op_a = FF(static_cast(indirect)), .avm_main_internal_return_ptr = internal_return_ptr, - .avm_main_mem_idx_a = dst_offset, + .avm_main_mem_idx_a = direct_dst_offset, .avm_main_mem_op_a = 1, .avm_main_pc = pc++, .avm_main_q_kernel_lookup = 1, @@ -1172,10 +1183,13 @@ Row AvmTraceBuilder::create_kernel_lookup_opcode(uint32_t dst_offset, uint32_t s }; } -void AvmTraceBuilder::op_storage_address(uint32_t dst_offset) +void AvmTraceBuilder::op_storage_address(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_storage_address(); - Row row = create_kernel_lookup_opcode(dst_offset, STORAGE_ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = create_kernel_lookup_opcode( + indirect_dst_flag, dst_offset, STORAGE_ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_storage_address = FF(1); // Constrain gas cost @@ -1184,10 +1198,12 @@ void AvmTraceBuilder::op_storage_address(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_sender(uint32_t dst_offset) +void AvmTraceBuilder::op_sender(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_sender(); - Row row = create_kernel_lookup_opcode(dst_offset, SENDER_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, SENDER_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_sender = FF(1); // Constrain gas cost @@ -1196,10 +1212,12 @@ void AvmTraceBuilder::op_sender(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_address(uint32_t dst_offset) +void AvmTraceBuilder::op_address(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_address(); - Row row = create_kernel_lookup_opcode(dst_offset, ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_address = FF(1); // Constrain gas cost @@ -1208,10 +1226,13 @@ void AvmTraceBuilder::op_address(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_fee_per_da_gas(uint32_t dst_offset) +void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_fee_per_da_gas(); - Row row = create_kernel_lookup_opcode(dst_offset, FEE_PER_DA_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = + create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, FEE_PER_DA_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_fee_per_da_gas = FF(1); // Constrain gas cost @@ -1220,10 +1241,13 @@ void AvmTraceBuilder::op_fee_per_da_gas(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_fee_per_l2_gas(uint32_t dst_offset) +void AvmTraceBuilder::op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_fee_per_l2_gas(); - Row row = create_kernel_lookup_opcode(dst_offset, FEE_PER_L2_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = + create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, FEE_PER_L2_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_fee_per_l2_gas = FF(1); // Constrain gas cost @@ -1232,10 +1256,13 @@ void AvmTraceBuilder::op_fee_per_l2_gas(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_transaction_fee(uint32_t dst_offset) +void AvmTraceBuilder::op_transaction_fee(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_transaction_fee(); - Row row = create_kernel_lookup_opcode(dst_offset, TRANSACTION_FEE_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = create_kernel_lookup_opcode( + indirect_dst_flag, dst_offset, TRANSACTION_FEE_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_transaction_fee = FF(1); // Constrain gas cost @@ -1244,10 +1271,12 @@ void AvmTraceBuilder::op_transaction_fee(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_chain_id(uint32_t dst_offset) +void AvmTraceBuilder::op_chain_id(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_chain_id(); - Row row = create_kernel_lookup_opcode(dst_offset, CHAIN_ID_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, CHAIN_ID_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_chain_id = FF(1); // Constrain gas cost @@ -1256,10 +1285,12 @@ void AvmTraceBuilder::op_chain_id(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_version(uint32_t dst_offset) +void AvmTraceBuilder::op_version(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_version(); - Row row = create_kernel_lookup_opcode(dst_offset, VERSION_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, VERSION_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_version = FF(1); // Constrain gas cost @@ -1268,10 +1299,13 @@ void AvmTraceBuilder::op_version(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_block_number(uint32_t dst_offset) +void AvmTraceBuilder::op_block_number(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_block_number(); - Row row = create_kernel_lookup_opcode(dst_offset, BLOCK_NUMBER_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = + create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, BLOCK_NUMBER_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_block_number = FF(1); // Constrain gas cost @@ -1280,10 +1314,12 @@ void AvmTraceBuilder::op_block_number(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_coinbase(uint32_t dst_offset) +void AvmTraceBuilder::op_coinbase(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_coinbase(); - Row row = create_kernel_lookup_opcode(dst_offset, COINBASE_SELECTOR, ia_value, AvmMemoryTag::FF); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, COINBASE_SELECTOR, ia_value, AvmMemoryTag::FF); row.avm_main_sel_op_coinbase = FF(1); // Constrain gas cost @@ -1292,10 +1328,13 @@ void AvmTraceBuilder::op_coinbase(uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_timestamp(uint32_t dst_offset) +void AvmTraceBuilder::op_timestamp(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_timestamp(); - Row row = create_kernel_lookup_opcode(dst_offset, TIMESTAMP_SELECTOR, ia_value, AvmMemoryTag::U64); + + bool indirect_dst_flag = is_operand_indirect(indirect, 0); + Row row = + create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, TIMESTAMP_SELECTOR, ia_value, AvmMemoryTag::U64); row.avm_main_sel_op_timestamp = FF(1); // Constrain gas cost diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index 63a68316433..8e9cbb233b2 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -85,21 +85,21 @@ class AvmTraceBuilder { void op_cmov(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t cond_offset, uint32_t dst_offset); // Call Context - void op_storage_address(uint32_t dst_offset); - void op_sender(uint32_t dst_offset); - void op_address(uint32_t dst_offset); + void op_storage_address(uint8_t indirect, uint32_t dst_offset); + void op_sender(uint8_t indirect, uint32_t dst_offset); + void op_address(uint8_t indirect, uint32_t dst_offset); // Fees - void op_fee_per_da_gas(uint32_t dst_offset); - void op_fee_per_l2_gas(uint32_t dst_offset); - void op_transaction_fee(uint32_t dst_offset); + void op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset); + void op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset); + void op_transaction_fee(uint8_t indirect, uint32_t dst_offset); // Globals - void op_chain_id(uint32_t dst_offset); - void op_version(uint32_t dst_offset); - void op_block_number(uint32_t dst_offset); - void op_coinbase(uint32_t dst_offset); - void op_timestamp(uint32_t dst_offset); + void op_chain_id(uint8_t indirect, uint32_t dst_offset); + void op_version(uint8_t indirect, uint32_t dst_offset); + void op_block_number(uint8_t indirect, uint32_t dst_offset); + void op_coinbase(uint8_t indirect, uint32_t dst_offset); + void op_timestamp(uint8_t indirect, uint32_t dst_offset); // Outputs // With single output values @@ -223,13 +223,15 @@ class AvmTraceBuilder { * * Used for looking up into the kernel inputs (context) - {caller, address, etc.} * + * @param indirect - Perform indirect memory resolution * @param dst_offset - Memory address to write the lookup result to * @param selector - The index of the kernel input lookup column * @param value - The value read from the memory address * @param w_tag - The memory tag of the value read * @return Row */ - Row create_kernel_lookup_opcode(uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag); + Row create_kernel_lookup_opcode( + bool indirect, uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag); /** * @brief Create a kernel output opcode object diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp index 1c54d62d1ed..1cabd6f9f36 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp @@ -38,7 +38,10 @@ VmPublicInputs get_public_inputs() // Template helper function to apply boilerplate around the kernel lookup tests template -void test_kernel_lookup(OpcodesFunc apply_opcodes, CheckFunc check_trace, ExecutionHints execution_hints = {}) +void test_kernel_lookup(bool indirect, + OpcodesFunc apply_opcodes, + CheckFunc check_trace, + ExecutionHints execution_hints = {}) { VmPublicInputs public_inputs = get_public_inputs(); @@ -51,7 +54,7 @@ void test_kernel_lookup(OpcodesFunc apply_opcodes, CheckFunc check_trace, Execut auto trace = trace_builder.finalize(); - check_trace(trace); + check_trace(indirect, trace); validate_trace(std::move(trace), public_inputs); } @@ -59,7 +62,7 @@ void test_kernel_lookup(OpcodesFunc apply_opcodes, CheckFunc check_trace, Execut /* * Helper function to assert row values for a kernel lookup opcode */ -void expect_row(std::vector::const_iterator row, FF selector, FF ia, FF mem_idx_a, AvmMemoryTag w_in_tag) +void expect_row(std::vector::const_iterator row, FF selector, FF ia, FF ind_a, FF mem_idx_a, AvmMemoryTag w_in_tag) { // Checks dependent on the opcode EXPECT_EQ(row->avm_kernel_kernel_in_offset, selector); @@ -68,8 +71,9 @@ void expect_row(std::vector::const_iterator row, FF selector, FF ia, FF mem // Checks that are fixed for kernel inputs EXPECT_EQ(row->avm_main_rwa, FF(1)); - EXPECT_EQ(row->avm_main_ind_a, FF(0)); - EXPECT_EQ(row->avm_mem_op_a, FF(1)); + EXPECT_EQ(row->avm_main_ind_a, ind_a); + EXPECT_EQ(row->avm_main_ind_op_a, FF(ind_a != 0)); + EXPECT_EQ(row->avm_main_mem_op_a, FF(1)); EXPECT_EQ(row->avm_main_w_in_tag, static_cast(w_in_tag)); EXPECT_EQ(row->avm_main_q_kernel_lookup, FF(1)); } @@ -147,10 +151,23 @@ void check_kernel_outputs(const Row& row, FF value, FF side_effect_counter, FF m TEST_F(AvmKernelPositiveTests, kernelSender) { + // Direct uint32_t dst_offset = 42; + uint32_t indirect_dst_offset = 69; // We test that the sender opcode is included at index 0 in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_sender(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_sender(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_sender(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_sender == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -159,18 +176,32 @@ TEST_F(AvmKernelPositiveTests, kernelSender) /*kernel_in_offset=*/SENDER_SELECTOR, /*ia=*/SENDER_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelAddress) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_address(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_address(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_address(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator address_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_address == FF(1); }); EXPECT_TRUE(address_row != trace.end()); @@ -179,17 +210,31 @@ TEST_F(AvmKernelPositiveTests, kernelAddress) /*kernel_in_offset=*/ADDRESS_SELECTOR, /*ia=*/ADDRESS_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelStorageAddress) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_storage_address(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_storage_address(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_storage_address(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator storage_address_row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_storage_address == FF(1); }); EXPECT_TRUE(storage_address_row != trace.end()); @@ -198,17 +243,32 @@ TEST_F(AvmKernelPositiveTests, kernelStorageAddress) /*kernel_in_offset=*/STORAGE_ADDRESS_SELECTOR, /*ia=*/STORAGE_ADDRESS_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelFeePerDa) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_fee_per_da_gas(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_fee_per_da_gas(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_fee_per_da_gas(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator fee_row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fee_per_da_gas == FF(1); }); EXPECT_TRUE(fee_row != trace.end()); @@ -217,17 +277,32 @@ TEST_F(AvmKernelPositiveTests, kernelFeePerDa) /*kernel_in_offset=*/FEE_PER_DA_GAS_SELECTOR, /*ia=*/FEE_PER_DA_GAS_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelFeePerL2) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_fee_per_l2_gas(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_fee_per_l2_gas(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_fee_per_l2_gas(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator fee_row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fee_per_l2_gas == FF(1); }); EXPECT_TRUE(fee_row != trace.end()); @@ -236,17 +311,32 @@ TEST_F(AvmKernelPositiveTests, kernelFeePerL2) /*kernel_in_offset=*/FEE_PER_L2_GAS_SELECTOR, /*ia=*/FEE_PER_L2_GAS_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelTransactionFee) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_transaction_fee(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_transaction_fee(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_transaction_fee(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator fee_row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_transaction_fee == FF(1); }); EXPECT_TRUE(fee_row != trace.end()); @@ -255,17 +345,32 @@ TEST_F(AvmKernelPositiveTests, kernelTransactionFee) /*kernel_in_offset=*/TRANSACTION_FEE_SELECTOR, /*ia=*/TRANSACTION_FEE_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelChainId) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_chain_id(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_chain_id(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_chain_id(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator fee_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_chain_id == FF(1); }); EXPECT_TRUE(fee_row != trace.end()); @@ -274,17 +379,32 @@ TEST_F(AvmKernelPositiveTests, kernelChainId) /*kernel_in_offset=*/CHAIN_ID_SELECTOR, /*ia=*/CHAIN_ID_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelVersion) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_version(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_version(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_version(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator fee_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_version == FF(1); }); EXPECT_TRUE(fee_row != trace.end()); @@ -293,17 +413,32 @@ TEST_F(AvmKernelPositiveTests, kernelVersion) /*kernel_in_offset=*/VERSION_SELECTOR, /*ia=*/VERSION_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelBlockNumber) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_block_number(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_block_number(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_block_number(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator fee_row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_block_number == FF(1); }); EXPECT_TRUE(fee_row != trace.end()); @@ -312,17 +447,32 @@ TEST_F(AvmKernelPositiveTests, kernelBlockNumber) /*kernel_in_offset=*/BLOCK_NUMBER_SELECTOR, /*ia=*/BLOCK_NUMBER_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelCoinbase) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_coinbase(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_coinbase(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_coinbase(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator fee_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_coinbase == FF(1); }); EXPECT_TRUE(fee_row != trace.end()); @@ -331,17 +481,32 @@ TEST_F(AvmKernelPositiveTests, kernelCoinbase) /*kernel_in_offset=*/COINBASE_SELECTOR, /*ia=*/COINBASE_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a*/ dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; - test_kernel_lookup(apply_opcodes, checks); + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } TEST_F(AvmKernelPositiveTests, kernelTimestamp) { uint32_t dst_offset = 42; - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_timestamp(dst_offset); }; - auto checks = [=](const std::vector& trace) { + uint32_t indirect_dst_offset = 69; + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_timestamp(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_timestamp(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator fee_row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_timestamp == FF(1); }); EXPECT_TRUE(fee_row != trace.end()); @@ -350,10 +515,13 @@ TEST_F(AvmKernelPositiveTests, kernelTimestamp) /*kernel_in_offset=*/TIMESTAMP_SELECTOR, /*ia=*/TIMESTAMP_SELECTOR + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, /*mem_idx_a*/ dst_offset, /*w_in_tag=*/AvmMemoryTag::U64); }; - test_kernel_lookup(apply_opcodes, checks); + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); } /** @@ -383,7 +551,7 @@ void negative_test_incorrect_ia_kernel_lookup(OpcodesFunc apply_opcodes, ta.avm_main_ia = incorrect_ia; - check_trace(trace); + check_trace(/*indirect*/ false, trace); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace), public_inputs), expected_message); } @@ -394,8 +562,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaSender) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_sender(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_sender(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_sender == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -404,6 +574,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaSender) row, /*kernel_in_offset=*/SENDER_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -417,8 +588,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaAddress) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_address(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_address(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_address == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -427,6 +600,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaAddress) row, /*kernel_in_offset=*/ADDRESS_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -440,8 +614,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaStorageAddress) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_storage_address(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_storage_address(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_storage_address == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -450,6 +626,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaStorageAddress) row, /*kernel_in_offset=*/STORAGE_ADDRESS_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -463,8 +640,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaDaGas) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_fee_per_da_gas(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_fee_per_da_gas(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fee_per_da_gas == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -473,6 +652,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaDaGas) row, /*kernel_in_offset=*/FEE_PER_DA_GAS_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -486,8 +666,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIal2Gas) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_fee_per_l2_gas(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_fee_per_l2_gas(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_fee_per_l2_gas == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -496,6 +678,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIal2Gas) row, /*kernel_in_offset=*/FEE_PER_L2_GAS_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -509,8 +692,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaTransactionFee) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_transaction_fee(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_transaction_fee(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_transaction_fee == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -519,6 +704,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaTransactionFee) row, /*kernel_in_offset=*/TRANSACTION_FEE_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -532,8 +718,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaChainId) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_chain_id(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_chain_id(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_chain_id == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -542,6 +730,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaChainId) row, /*kernel_in_offset=*/CHAIN_ID_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -555,8 +744,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaVersion) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_version(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_version(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_version == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -565,6 +756,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaVersion) row, /*kernel_in_offset=*/VERSION_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -578,8 +770,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaBlockNumber) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_block_number(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_block_number(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_block_number == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -588,6 +782,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaBlockNumber) row, /*kernel_in_offset=*/BLOCK_NUMBER_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -601,8 +796,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaTimestamp) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_timestamp(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_timestamp(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_timestamp == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -611,6 +808,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaTimestamp) row, /*kernel_in_offset=*/TIMESTAMP_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a*/ dst_offset, /*w_in_tag=*/AvmMemoryTag::U64); }; @@ -624,8 +822,10 @@ TEST_F(AvmKernelNegativeTests, incorrectIaCoinbase) FF incorrect_ia = FF(69); // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_coinbase(dst_offset); }; - auto checks = [=](const std::vector& trace) { + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_coinbase(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_coinbase == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -634,6 +834,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaCoinbase) row, /*kernel_in_offset=*/COINBASE_SELECTOR, /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, /*mem_idx_a=*/dst_offset, /*w_in_tag=*/AvmMemoryTag::FF); }; @@ -653,7 +854,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitNoteHash) trace_builder.op_set(0, 1234, offset, AvmMemoryTag::FF); trace_builder.op_emit_note_hash(offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_emit_note_hash == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -672,7 +873,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitNoteHash) check_kernel_outputs(trace.at(output_offset), 1234, /*side_effect_counter=*/0, /*metadata=*/0); }; - test_kernel_lookup(apply_opcodes, checks); + test_kernel_lookup(false, apply_opcodes, checks); } TEST_F(AvmKernelOutputPositiveTests, kernelEmitNullifier) @@ -682,7 +883,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitNullifier) trace_builder.op_set(0, 1234, offset, AvmMemoryTag::FF); trace_builder.op_emit_nullifier(offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_emit_nullifier == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -703,7 +904,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitNullifier) check_kernel_outputs(trace.at(output_offset), 1234, /*side_effect_counter=*/0, /*metadata=*/0); }; - test_kernel_lookup(apply_opcodes, checks); + test_kernel_lookup(false, apply_opcodes, checks); } TEST_F(AvmKernelOutputPositiveTests, kernelEmitL2ToL1Msg) @@ -715,7 +916,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitL2ToL1Msg) trace_builder.op_set(0, 420, recipient_offset, AvmMemoryTag::FF); trace_builder.op_emit_l2_to_l1_msg(recipient_offset, msg_offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_emit_l2_to_l1_msg == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -738,7 +939,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitL2ToL1Msg) check_kernel_outputs(trace.at(output_offset), 1234, /*side_effect_counter=*/0, /*metadata=*/420); }; - test_kernel_lookup(apply_opcodes, checks); + test_kernel_lookup(false, apply_opcodes, checks); } TEST_F(AvmKernelOutputPositiveTests, kernelEmitUnencryptedLog) @@ -748,7 +949,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitUnencryptedLog) trace_builder.op_set(0, 1234, offset, AvmMemoryTag::FF); trace_builder.op_emit_unencrypted_log(offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_emit_unencrypted_log == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -767,7 +968,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitUnencryptedLog) check_kernel_outputs(trace.at(output_offset), 1234, 0, 0); }; - test_kernel_lookup(apply_opcodes, checks); + test_kernel_lookup(false, apply_opcodes, checks); } TEST_F(AvmKernelOutputPositiveTests, kernelSload) @@ -784,7 +985,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSload) trace_builder.op_set(0, static_cast(slot), slot_offset, AvmMemoryTag::FF); trace_builder.op_sload(slot_offset, value_offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_sload == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -806,7 +1007,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSload) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, slot); }; - test_kernel_lookup(apply_opcodes, checks, execution_hints); + test_kernel_lookup(false, apply_opcodes, checks, execution_hints); } TEST_F(AvmKernelOutputPositiveTests, kernelSstore) @@ -821,7 +1022,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSstore) trace_builder.op_set(0, static_cast(slot), metadata_offset, AvmMemoryTag::FF); trace_builder.op_sstore(metadata_offset, value_offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_sstore == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -842,7 +1043,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSstore) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, slot); }; - test_kernel_lookup(apply_opcodes, checks); + test_kernel_lookup(false, apply_opcodes, checks); } TEST_F(AvmKernelOutputPositiveTests, kernelNoteHashExists) @@ -858,7 +1059,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNoteHashExists) trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); trace_builder.op_note_hash_exists(value_offset, metadata_offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_note_hash_exists == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -880,7 +1081,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNoteHashExists) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, exists); }; - test_kernel_lookup(apply_opcodes, checks, execution_hints); + test_kernel_lookup(false, apply_opcodes, checks, execution_hints); } TEST_F(AvmKernelOutputPositiveTests, kernelNullifierExists) @@ -896,7 +1097,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierExists) trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); trace_builder.op_nullifier_exists(value_offset, metadata_offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_nullifier_exists == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -917,7 +1118,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierExists) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, exists); }; - test_kernel_lookup(apply_opcodes, checks, execution_hints); + test_kernel_lookup(false, apply_opcodes, checks, execution_hints); } TEST_F(AvmKernelOutputPositiveTests, kernelNullifierNonExists) @@ -933,7 +1134,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierNonExists) trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); trace_builder.op_nullifier_exists(value_offset, metadata_offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_nullifier_exists == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -954,7 +1155,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierNonExists) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, exists); }; - test_kernel_lookup(apply_opcodes, checks, execution_hints); + test_kernel_lookup(false, apply_opcodes, checks, execution_hints); } TEST_F(AvmKernelOutputPositiveTests, kernelL1ToL2MsgExists) @@ -971,7 +1172,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelL1ToL2MsgExists) trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); trace_builder.op_l1_to_l2_msg_exists(value_offset, metadata_offset); }; - auto checks = [=](const std::vector& trace) { + auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { std::vector::const_iterator row = std::ranges::find_if( trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_l1_to_l2_msg_exists == FF(1); }); EXPECT_TRUE(row != trace.end()); @@ -992,7 +1193,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelL1ToL2MsgExists) check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, exists); }; - test_kernel_lookup(apply_opcodes, checks, execution_hints); + test_kernel_lookup(false, apply_opcodes, checks, execution_hints); } } // namespace tests_avm