diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp index 7f55fa63fd7..b83abf04c0f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp @@ -82,21 +82,6 @@ inline void read(uint8_t const*& it, ContractInstanceHint& hint) } struct ExecutionHints { - ExecutionHints() = default; - ExecutionHints(std::vector> storage_value_hints, - std::vector> note_hash_exists_hints, - std::vector> nullifier_exists_hints, - std::vector> l1_to_l2_message_exists_hints, - std::vector externalcall_hints, - std::map contract_instance_hints) - : storage_value_hints(std::move(storage_value_hints)) - , note_hash_exists_hints(std::move(note_hash_exists_hints)) - , nullifier_exists_hints(std::move(nullifier_exists_hints)) - , l1_to_l2_message_exists_hints(std::move(l1_to_l2_message_exists_hints)) - , externalcall_hints(std::move(externalcall_hints)) - , contract_instance_hints(std::move(contract_instance_hints)) - {} - std::vector> storage_value_hints; std::vector> note_hash_exists_hints; std::vector> nullifier_exists_hints; @@ -105,6 +90,40 @@ struct ExecutionHints { // TODO(dbanks): not read yet. std::map contract_instance_hints; + ExecutionHints() = default; + + // Builder. + ExecutionHints& with_storage_value_hints(std::vector> storage_value_hints) + { + this->storage_value_hints = std::move(storage_value_hints); + return *this; + } + ExecutionHints& with_note_hash_exists_hints(std::vector> note_hash_exists_hints) + { + this->note_hash_exists_hints = std::move(note_hash_exists_hints); + return *this; + } + ExecutionHints& with_nullifier_exists_hints(std::vector> nullifier_exists_hints) + { + this->nullifier_exists_hints = std::move(nullifier_exists_hints); + return *this; + } + ExecutionHints& with_l1_to_l2_message_exists_hints(std::vector> l1_to_l2_message_exists_hints) + { + this->l1_to_l2_message_exists_hints = std::move(l1_to_l2_message_exists_hints); + return *this; + } + ExecutionHints& with_externalcall_hints(std::vector externalcall_hints) + { + this->externalcall_hints = std::move(externalcall_hints); + return *this; + } + ExecutionHints& with_contract_instance_hints(std::map contract_instance_hints) + { + this->contract_instance_hints = std::move(contract_instance_hints); + return *this; + } + static void push_vec_into_map(std::unordered_map& into_map, const std::vector>& from_pair_vec) { @@ -148,6 +167,21 @@ struct ExecutionHints { std::move(nullifier_exists_hints), std::move(l1_to_l2_message_exists_hints), std::move(externalcall_hints), std::move(contract_instance_hints) }; } + + private: + ExecutionHints(std::vector> storage_value_hints, + std::vector> note_hash_exists_hints, + std::vector> nullifier_exists_hints, + std::vector> l1_to_l2_message_exists_hints, + std::vector externalcall_hints, + std::map contract_instance_hints) + : storage_value_hints(std::move(storage_value_hints)) + , note_hash_exists_hints(std::move(note_hash_exists_hints)) + , nullifier_exists_hints(std::move(nullifier_exists_hints)) + , l1_to_l2_message_exists_hints(std::move(l1_to_l2_message_exists_hints)) + , externalcall_hints(std::move(externalcall_hints)) + , contract_instance_hints(std::move(contract_instance_hints)) + {} }; } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp index 50f5ecf5c9b..33ba6823781 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp @@ -61,14 +61,21 @@ void AvmGasTraceBuilder::constrain_gas_lookup(uint32_t clk, OpCode opcode) gas_trace.push_back(entry); } -void AvmGasTraceBuilder::constrain_gas_for_external_call(uint32_t clk) +void AvmGasTraceBuilder::constrain_gas_for_external_call(uint32_t clk, + uint32_t nested_l2_gas_cost, + uint32_t nested_da_gas_cost) { - // Arbitrary constants for the moment - uint32_t l2_gas_cost = 6; // This will be hinted - uint32_t da_gas_cost = 23; // This will be hinted + const OpCode opcode = OpCode::CALL; - remaining_l2_gas -= l2_gas_cost; - remaining_da_gas -= da_gas_cost; + // TODO: increase lookup counter for the opcode we are looking up into + // gas_opcode_lookup_counter[opcode]++; + + // Get the gas prices for this opcode + uint32_t opcode_l2_gas_cost = GAS_COST_TABLE.at(opcode).l2_fixed_gas_cost; + uint32_t opcode_da_gas_cost = GAS_COST_TABLE.at(opcode).da_fixed_gas_cost; + + remaining_l2_gas -= opcode_l2_gas_cost + nested_l2_gas_cost; + remaining_da_gas -= opcode_da_gas_cost + nested_da_gas_cost; // Decrease the gas left // Create a gas trace entry diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.hpp index 7d182e9935f..cc8e53aeb36 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.hpp @@ -130,7 +130,7 @@ class AvmGasTraceBuilder { std::vector finalize(); void constrain_gas_lookup(uint32_t clk, OpCode opcode); - void constrain_gas_for_external_call(uint32_t clk); + void constrain_gas_for_external_call(uint32_t clk, uint32_t nested_l2_gas_cost, uint32_t nested_da_gas_cost); void set_initial_gas(uint32_t l2_gas, uint32_t da_gas); uint32_t get_l2_gas_left(); 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 fe78c6bf03a..d45c7967fd4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -55,7 +55,7 @@ void AvmTraceBuilder::reset() keccak_trace_builder.reset(); pedersen_trace_builder.reset(); - return_data_counter = 0; + external_call_counter = 0; } AvmTraceBuilder::IndirectThreeResolution AvmTraceBuilder::resolve_ind_three( @@ -2393,10 +2393,12 @@ void AvmTraceBuilder::op_call([[maybe_unused]] uint8_t indirect, uint32_t function_selector_offset) { auto clk = static_cast(main_trace.size()) + 1; + const ExternalCallHint& hint = execution_hints.externalcall_hints.at(external_call_counter); // We can load up to 4 things per row auto register_order = std::array{ IntermRegister::IA, IntermRegister::IB, IntermRegister::IC, IntermRegister::ID }; // Constrain gas cost - gas_trace_builder.constrain_gas_for_external_call(clk); + gas_trace_builder.constrain_gas_for_external_call( + clk, static_cast(hint.l2_gas_used), static_cast(hint.da_gas_used)); // Indirect is ZEROTH, SECOND and FOURTH bit COME BACK TO MAKING THIS ALL SUPPORTED auto read_ind_gas_offset = mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, gas_offset); @@ -2487,11 +2489,11 @@ void AvmTraceBuilder::op_call([[maybe_unused]] uint8_t indirect, AvmMemoryTag::U0, AvmMemoryTag::FF, internal_return_ptr, - execution_hints.externalcall_hints.at(return_data_counter).return_data); - return_data_counter++; + hint.return_data); clk++; write_slice_to_memory( - call_ptr, clk, success_offset, AvmMemoryTag::U0, AvmMemoryTag::U8, internal_return_ptr, { FF(1) }); + call_ptr, clk, success_offset, AvmMemoryTag::U0, AvmMemoryTag::U8, internal_return_ptr, { hint.success }); + external_call_counter++; } void AvmTraceBuilder::op_get_contract_instance(uint8_t indirect, uint32_t address_offset, uint32_t dst_offset) 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 92233be8358..b641fc78836 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -303,7 +303,7 @@ class AvmTraceBuilder { // Side effect counter will incremenent when any state writing values are // encountered uint32_t side_effect_counter = 0; - uint32_t return_data_counter = 0; + uint32_t external_call_counter = 0; // Execution hints aid witness solving for instructions that require auxiliary information to construct // Mapping of side effect counter -> value diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index 56ab35364a2..98be9b067f4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -1773,7 +1773,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageOpcodes) // Generate Hint for Sload operation // side effect counter 0 = value 42 - ExecutionHints execution_hints({ { 0, 42 } }, {}, {}, {}, {}, {}); + auto execution_hints = ExecutionHints().with_storage_value_hints({ { 0, 42 } }); auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); @@ -1854,7 +1854,7 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) std::vector returndata = {}; // Generate Hint for Sload operation - ExecutionHints execution_hints({ { 0, 1 }, { 1, 1 }, { 2, 1 } }, {}, {}, {}, {}, {}); + auto execution_hints = ExecutionHints().with_storage_value_hints({ { 0, 1 }, { 1, 1 }, { 2, 1 } }); auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); @@ -1962,9 +1962,8 @@ TEST_F(AvmExecutionTests, opCallOpcodes) std::vector returndata = {}; // Generate Hint for call operation - ExecutionHints execution_hints; - execution_hints.externalcall_hints.push_back( - { .success = 1, .return_data = { 9, 8 }, .l2_gas_used = 0, .da_gas_used = 0 }); + auto execution_hints = ExecutionHints().with_externalcall_hints( + { { .success = 1, .return_data = { 9, 8 }, .l2_gas_used = 0, .da_gas_used = 0 } }); auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 9, 8, 1 })); // The 1 represents the success @@ -2001,9 +2000,7 @@ TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) std::vector returndata = {}; // Generate Hint for call operation - ExecutionHints execution_hints = {}; - ContractInstanceHint contract_instance_hint = { 1, 1, 2, 3, 4, 5 }; // The first one represents true - execution_hints.contract_instance_hints.insert({ address, contract_instance_hint }); + auto execution_hints = ExecutionHints().with_contract_instance_hints({ { address, { 1, 1, 2, 3, 4, 5 } } }); auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 1, 1, 2, 3, 4, 5 })); // The first one represents true 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 089cf9c5ac2..1c54d62d1ed 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp @@ -778,7 +778,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSload) auto slot = 12345; // Provide a hint for sload value slot - ExecutionHints execution_hints({ { 0, value } }, {}, {}, {}, {}, {}); + auto execution_hints = ExecutionHints().with_storage_value_hints({ { 0, value } }); auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_set(0, static_cast(slot), slot_offset, AvmMemoryTag::FF); @@ -852,7 +852,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNoteHashExists) uint32_t metadata_offset = 420; auto exists = 1; - ExecutionHints execution_hints({ { 0, exists } }, {}, {}, {}, {}, {}); + auto execution_hints = ExecutionHints().with_note_hash_exists_hints({ { 0, exists } }); auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); @@ -890,7 +890,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierExists) uint32_t metadata_offset = 420; auto exists = 1; - ExecutionHints execution_hints({ { 0, exists } }, {}, {}, {}, {}, {}); + auto execution_hints = ExecutionHints().with_nullifier_exists_hints({ { 0, exists } }); auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); @@ -927,7 +927,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierNonExists) uint32_t metadata_offset = 420; auto exists = 0; - ExecutionHints execution_hints({}, { { 0, exists } }, {}, {}, {}, {}); + auto execution_hints = ExecutionHints().with_nullifier_exists_hints({ { 0, exists } }); auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); @@ -965,7 +965,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelL1ToL2MsgExists) auto exists = 1; // Create an execution hints object with the result of the operation - ExecutionHints execution_hints({ { 0, exists } }, {}, {}, {}, {}, {}); + auto execution_hints = ExecutionHints().with_l1_to_l2_message_exists_hints({ { 0, exists } }); auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF);