From a772fd48d74100391b694f9265da0cc89e5b9016 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Fri, 4 Oct 2024 20:57:54 +0000 Subject: [PATCH] feat: new per-enqueued-call gas limit --- .../vm/avm/tests/execution.test.cpp | 22 ++++++++++++++++++- .../src/barretenberg/vm/avm/trace/helper.hpp | 9 ++++++++ .../src/barretenberg/vm/aztec_constants.hpp | 1 + .../src/core/libraries/ConstantsGen.sol | 1 + .../enqueued_call_data_validator.nr | 9 ++++++-- .../crates/types/src/constants.nr | 1 + yarn-project/circuits.js/src/constants.gen.ts | 1 + .../circuits.js/src/scripts/constants.in.ts | 1 + .../simulator/src/avm/avm_simulator.ts | 2 ++ 9 files changed, 44 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp index 921aae8a1566..63065a3935b3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp @@ -12,6 +12,7 @@ #include "barretenberg/vm/avm/trace/fixed_gas.hpp" #include "barretenberg/vm/avm/trace/kernel_trace.hpp" #include "barretenberg/vm/avm/trace/opcode.hpp" +#include "barretenberg/vm/constants.hpp" #include "common.test.hpp" #include "barretenberg/vm/aztec_constants.hpp" @@ -1815,6 +1816,25 @@ TEST_F(AvmExecutionTests, daGasLeft) validate_trace(std::move(trace), public_inputs); } +TEST_F(AvmExecutionTests, ExecutorThrowsWithTooMuchGasAllocated) +{ + std::string bytecode_hex = to_hex(OpCode::GETENVVAR_16) + // opcode SENDER + "00" // Indirect flag + + to_hex(static_cast(EnvironmentVariable::SENDER)) + "0007"; // addr 7 + + std::vector calldata = {}; + std::vector returndata = {}; + std::vector public_inputs_vec(PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, 0); + public_inputs_vec[L2_START_GAS_LEFT_PCPI_OFFSET] = MAX_L2_GAS_PER_ENQUEUED_CALL + 1; + + auto bytecode = hex_to_bytes(bytecode_hex); + auto instructions = Deserialization::parse(bytecode); + + EXPECT_THROW_WITH_MESSAGE( + Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec), + "Cannot allocate more than MAX_L2_GAS_PER_ENQUEUED_CALL to the AVM for execution of an enqueued call"); +} + // Should throw whenever the wrong number of public inputs are provided TEST_F(AvmExecutionTests, ExecutorThrowsWithIncorrectNumberOfPublicInputs) { @@ -1829,7 +1849,7 @@ TEST_F(AvmExecutionTests, ExecutorThrowsWithIncorrectNumberOfPublicInputs) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - EXPECT_THROW_WITH_MESSAGE(Execution::gen_trace(instructions, calldata, returndata, public_inputs_vec), + EXPECT_THROW_WITH_MESSAGE(Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec), "Public inputs vector is not of PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH"); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp index 3b64afe14889..3fa1f976b8c8 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp @@ -4,6 +4,7 @@ #include "barretenberg/vm/avm/trace/common.hpp" #include "barretenberg/vm/avm/trace/trace.hpp" +#include "barretenberg/vm/constants.hpp" namespace bb::avm_trace { @@ -37,6 +38,14 @@ template VmPublicInputs convert_public_inputs(std::vector MAX_L2_GAS_PER_ENQUEUED_CALL) { + throw_or_abort( + "Cannot allocate more than MAX_L2_GAS_PER_ENQUEUED_CALL to the AVM for execution of an enqueued call"); + } + std::array& kernel_inputs = std::get(public_inputs); // Copy items from PublicCircuitPublicInputs vector to public input columns diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index 6ae5af89b350..bbcf94b8a218 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -12,6 +12,7 @@ #define MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL 16 #define MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL 16 #define MAX_UNENCRYPTED_LOGS_PER_CALL 4 +#define MAX_L2_GAS_PER_ENQUEUED_CALL 1500000 #define AZTEC_ADDRESS_LENGTH 1 #define GAS_FEES_LENGTH 2 #define GAS_LENGTH 2 diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 91a9ca5a9584..9b5f7323871c 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -116,6 +116,7 @@ library Constants { 14061769416655647708490531650437236735160113654556896985372298487345; uint256 internal constant DEFAULT_GAS_LIMIT = 1000000000; uint256 internal constant DEFAULT_TEARDOWN_GAS_LIMIT = 100000000; + uint256 internal constant MAX_L2_GAS_PER_ENQUEUED_CALL = 1500000; uint256 internal constant DEFAULT_MAX_FEE_PER_GAS = 10; uint256 internal constant DEFAULT_INCLUSION_FEE = 0; uint256 internal constant DA_BYTES_PER_FIELD = 32; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr index 7688f780885f..361e86aa57c2 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr @@ -5,6 +5,7 @@ use dep::types::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, enqueued_call_data::EnqueuedCallData, public_call_request::PublicCallRequest, validation_requests::PublicValidationRequestArrayLengths }, + constants::MAX_L2_GAS_PER_ENQUEUED_CALL, utils::arrays::array_length }; @@ -89,15 +90,19 @@ impl EnqueuedCallDataValidator { // Validates that the start gas injected into the vm circuit matches the remaining gas. fn validate_start_gas(self, previous_kernel: PublicKernelCircuitPublicInputs) { let enqueued_call_start_gas = self.enqueued_call.data.start_gas_left; + // NOTE: the AVM circuit will fail to generate a proof if its "start gas" is > MAX_L2_GAS_PER_ENQUEUED_CALL, + // so the kernel never allocates more than that maximum to one enqueued call. if self.phase != PublicKernelPhase.TEARDOWN { // An enqueued call's start gas is the remaining gas left in the transaction after the previous kernel. let tx_gas_limits = previous_kernel.constants.tx_context.gas_settings.gas_limits; - let computed_start_gas = tx_gas_limits.sub(previous_kernel.end.gas_used).sub(previous_kernel.end_non_revertible.gas_used); + let mut computed_start_gas = tx_gas_limits.sub(previous_kernel.end.gas_used).sub(previous_kernel.end_non_revertible.gas_used); + computed_start_gas.l2_gas = std::cmp::min(computed_start_gas.l2_gas, MAX_L2_GAS_PER_ENQUEUED_CALL); assert_eq( enqueued_call_start_gas, computed_start_gas, "Start gas for enqueued call does not match transaction gas left" ); } else { - let teardown_gas_limit = previous_kernel.constants.tx_context.gas_settings.teardown_gas_limits; + let mut teardown_gas_limit = previous_kernel.constants.tx_context.gas_settings.teardown_gas_limits; + teardown_gas_limit.l2_gas = std::cmp::min(teardown_gas_limit.l2_gas, MAX_L2_GAS_PER_ENQUEUED_CALL); assert_eq( enqueued_call_start_gas, teardown_gas_limit, "Start gas for enqueued call does not match teardown gas allocation" ); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 4846842c401e..effc96e85a4a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -167,6 +167,7 @@ global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bd // GAS DEFAULTS global DEFAULT_GAS_LIMIT: u32 = 1_000_000_000; global DEFAULT_TEARDOWN_GAS_LIMIT: u32 = 100_000_000; +global MAX_L2_GAS_PER_ENQUEUED_CALL: u32 = 1_500_000; global DEFAULT_MAX_FEE_PER_GAS: Field = 10; global DEFAULT_INCLUSION_FEE: Field = 0; global DA_BYTES_PER_FIELD: u32 = 32; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 14ff856712f3..8199416763f4 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -101,6 +101,7 @@ export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 14061769416655647708490531650437236735160113654556896985372298487345n; export const DEFAULT_GAS_LIMIT = 1000000000; export const DEFAULT_TEARDOWN_GAS_LIMIT = 100000000; +export const MAX_L2_GAS_PER_ENQUEUED_CALL = 1500000; export const DEFAULT_MAX_FEE_PER_GAS = 10; export const DEFAULT_INCLUSION_FEE = 0; export const DA_BYTES_PER_FIELD = 32; diff --git a/yarn-project/circuits.js/src/scripts/constants.in.ts b/yarn-project/circuits.js/src/scripts/constants.in.ts index 8580b48e8baa..7f80a3c7963a 100644 --- a/yarn-project/circuits.js/src/scripts/constants.in.ts +++ b/yarn-project/circuits.js/src/scripts/constants.in.ts @@ -77,6 +77,7 @@ const CPP_CONSTANTS = [ 'MEM_TAG_U64', 'MEM_TAG_U128', 'MEM_TAG_FF', + 'MAX_L2_GAS_PER_ENQUEUED_CALL', ]; const PIL_CONSTANTS = [ diff --git a/yarn-project/simulator/src/avm/avm_simulator.ts b/yarn-project/simulator/src/avm/avm_simulator.ts index e768d27958d6..0bbcffb09242 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.ts @@ -14,12 +14,14 @@ import { } from './errors.js'; import type { Instruction } from './opcodes/index.js'; import { decodeFromBytecode } from './serialization/bytecode_serialization.js'; +import { MAX_L2_GAS_PER_ENQUEUED_CALL } from '@aztec/circuits.js'; export class AvmSimulator { private log: DebugLogger; private bytecode: Buffer | undefined; constructor(private context: AvmContext) { + assert(context.machineState.gasLeft.l2Gas > MAX_L2_GAS_PER_ENQUEUED_CALL, `Cannot allocate more than ${MAX_L2_GAS_PER_ENQUEUED_CALL} to the AVM for execution of an enqueued call`); this.log = createDebugLogger(`aztec:avm_simulator:core(f:${context.environment.functionSelector.toString()})`); }