From d647ff25e1bc065f172b04668903dea4efd44221 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 --- .../cpp/src/barretenberg/vm/avm/trace/helper.hpp | 9 +++++++++ barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp | 1 + l1-contracts/src/core/libraries/ConstantsGen.sol | 1 + .../src/components/enqueued_call_data_validator.nr | 9 +++++++-- .../src/components/public_kernel_output_composer.nr | 6 ++++++ .../noir-protocol-circuits/crates/types/src/constants.nr | 1 + yarn-project/circuits.js/src/constants.gen.ts | 1 + yarn-project/circuits.js/src/scripts/constants.in.ts | 1 + yarn-project/simulator/src/avm/avm_simulator.ts | 2 ++ 9 files changed, 29 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp index 3b64afe1488..3fa1f976b8c 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 6ae5af89b35..bbcf94b8a21 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 91a9ca5a958..9b5f7323871 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 7688f780885..361e86aa57c 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/public-kernel-lib/src/components/public_kernel_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr index 7f9964cacd2..5d316ad9acf 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr @@ -134,6 +134,8 @@ impl PublicKernelOutputComposer { let gas_used = self.output_builder.end.gas_used; self.output_builder.end = PublicAccumulatedDataBuilder::empty(); self.output_builder.end.gas_used = gas_used; + // TODO: consume all remaining gas on revert? + //self.output_builder.end.gas_used = self.output_builder.constants.tx_context.gas_settings.gas_limits; } } @@ -143,6 +145,10 @@ impl PublicKernelOutputComposer { fn update_gas_used(&mut self, enqueued_call: VMCircuitPublicInputs, phase: u8) { let call_gas_used = enqueued_call.accumulated_data.gas_used; + // TODO: since we're using gas used here, this should be fine + // but if vm circuit public inputs change to use expose gas_left instead, + // then we need to compute the call's gas used as start_gas_left - end_gas_left + //let call_gas_used = enqueued_call.start_gas_left - enqueued_call.accumulated_data.gas_left; if phase == PublicKernelPhase.SETUP { self.output_builder.end_non_revertible.gas_used += call_gas_used; } 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 4846842c401..effc96e85a4 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 14ff856712f..8199416763f 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 8580b48e8ba..7f80a3c7963 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 e768d27958d..0bbcffb0924 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()})`); }