gas_schedule - [devnet]
This module defines structs and methods to initialize the gas schedule, which dictates how much it costs to execute Move on the network.
use 0x1::aptos_hash;use 0x1::bcs;use 0x1::chain_status;use 0x1::config_buffer;use 0x1::error;use 0x1::reconfiguration;use 0x1::storage_gas;use 0x1::string;use 0x1::system_addresses;use 0x1::util;use 0x1::vector;Constants
const EINVALID_GAS_FEATURE_VERSION: u64 = 2;The provided gas schedule bytes are empty or invalid
const EINVALID_GAS_SCHEDULE: u64 = 1;const EINVALID_GAS_SCHEDULE_HASH: u64 = 3;Structs
GasEntry
struct GasEntry has copy, drop, storeFields
- 
key: string::String - 
val: u64 
Resources
GasSchedule
struct GasSchedule has copy, drop, keyFields
- 
entries: vector<gas_schedule::GasEntry> 
GasScheduleV2
struct GasScheduleV2 has copy, drop, store, keyFields
- 
feature_version: u64 - 
entries: vector<gas_schedule::GasEntry> 
Functions
initialize
Only called during genesis.
public(friend) fun initialize(aptos_framework: &signer, gas_schedule_blob: vector<u8>)Implementation
public(friend) fun initialize(aptos_framework: &signer, gas_schedule_blob: vector<u8>) {    system_addresses::assert_aptos_framework(aptos_framework);    assert!(!vector::is_empty(&gas_schedule_blob), error::invalid_argument(EINVALID_GAS_SCHEDULE));
    // TODO(Gas): check if gas schedule is consistent    let gas_schedule: GasScheduleV2 = from_bytes(gas_schedule_blob);    move_to<GasScheduleV2>(aptos_framework, gas_schedule);}set_gas_schedule
Deprecated by set_for_next_epoch().
WARNING: calling this while randomness is enabled will trigger a new epoch without randomness!
TODO: update all the tests that reference this function, then disable this function.
public fun set_gas_schedule(aptos_framework: &signer, gas_schedule_blob: vector<u8>)Implementation
public fun set_gas_schedule(aptos_framework: &signer, gas_schedule_blob: vector<u8>) acquires GasSchedule, GasScheduleV2 {    system_addresses::assert_aptos_framework(aptos_framework);    assert!(!vector::is_empty(&gas_schedule_blob), error::invalid_argument(EINVALID_GAS_SCHEDULE));    chain_status::assert_genesis();
    if (exists<GasScheduleV2>(@aptos_framework)) {        let gas_schedule = borrow_global_mut<GasScheduleV2>(@aptos_framework);        let new_gas_schedule: GasScheduleV2 = from_bytes(gas_schedule_blob);        assert!(new_gas_schedule.feature_version >= gas_schedule.feature_version,            error::invalid_argument(EINVALID_GAS_FEATURE_VERSION));        // TODO(Gas): check if gas schedule is consistent        *gas_schedule = new_gas_schedule;    }    else {        if (exists<GasSchedule>(@aptos_framework)) {            _ = move_from<GasSchedule>(@aptos_framework);        };        let new_gas_schedule: GasScheduleV2 = from_bytes(gas_schedule_blob);        // TODO(Gas): check if gas schedule is consistent        move_to<GasScheduleV2>(aptos_framework, new_gas_schedule);    };
    // Need to trigger reconfiguration so validator nodes can sync on the updated gas schedule.    reconfiguration::reconfigure();}set_for_next_epoch
Set the gas schedule for the next epoch, typically called by on-chain governance. Abort if the version of the given schedule is lower than the current version.
Example usage:
aptos_framework::gas_schedule::set_for_next_epoch(&framework_signer, some_gas_schedule_blob);aptos_framework::aptos_governance::reconfigure(&framework_signer);public fun set_for_next_epoch(aptos_framework: &signer, gas_schedule_blob: vector<u8>)Implementation
public fun set_for_next_epoch(aptos_framework: &signer, gas_schedule_blob: vector<u8>) acquires GasScheduleV2 {    system_addresses::assert_aptos_framework(aptos_framework);    assert!(!vector::is_empty(&gas_schedule_blob), error::invalid_argument(EINVALID_GAS_SCHEDULE));    let new_gas_schedule: GasScheduleV2 = from_bytes(gas_schedule_blob);    if (exists<GasScheduleV2>(@aptos_framework)) {        let cur_gas_schedule = borrow_global<GasScheduleV2>(@aptos_framework);        assert!(            new_gas_schedule.feature_version >= cur_gas_schedule.feature_version,            error::invalid_argument(EINVALID_GAS_FEATURE_VERSION)        );    };    config_buffer::upsert(new_gas_schedule);}set_for_next_epoch_check_hash
Set the gas schedule for the next epoch, typically called by on-chain governance. Abort if the version of the given schedule is lower than the current version. Require a hash of the old gas schedule to be provided and will abort if the hashes mismatch.
public fun set_for_next_epoch_check_hash(aptos_framework: &signer, old_gas_schedule_hash: vector<u8>, new_gas_schedule_blob: vector<u8>)Implementation
public fun set_for_next_epoch_check_hash(    aptos_framework: &signer,    old_gas_schedule_hash: vector<u8>,    new_gas_schedule_blob: vector<u8>) acquires GasScheduleV2 {    system_addresses::assert_aptos_framework(aptos_framework);    assert!(!vector::is_empty(&new_gas_schedule_blob), error::invalid_argument(EINVALID_GAS_SCHEDULE));
    let new_gas_schedule: GasScheduleV2 = from_bytes(new_gas_schedule_blob);    if (exists<GasScheduleV2>(@aptos_framework)) {        let cur_gas_schedule = borrow_global<GasScheduleV2>(@aptos_framework);        assert!(            new_gas_schedule.feature_version >= cur_gas_schedule.feature_version,            error::invalid_argument(EINVALID_GAS_FEATURE_VERSION)        );        let cur_gas_schedule_bytes = bcs::to_bytes(cur_gas_schedule);        let cur_gas_schedule_hash = aptos_hash::sha3_512(cur_gas_schedule_bytes);        assert!(            cur_gas_schedule_hash == old_gas_schedule_hash,            error::invalid_argument(EINVALID_GAS_SCHEDULE_HASH)        );    };
    config_buffer::upsert(new_gas_schedule);}on_new_epoch
Only used in reconfigurations to apply the pending GasScheduleV2, if there is any.
public(friend) fun on_new_epoch(framework: &signer)Implementation
public(friend) fun on_new_epoch(framework: &signer) acquires GasScheduleV2 {    system_addresses::assert_aptos_framework(framework);    if (config_buffer::does_exist<GasScheduleV2>()) {        let new_gas_schedule = config_buffer::extract_v2<GasScheduleV2>();        if (exists<GasScheduleV2>(@aptos_framework)) {            *borrow_global_mut<GasScheduleV2>(@aptos_framework) = new_gas_schedule;        } else {            move_to(framework, new_gas_schedule);        }    }}set_storage_gas_config
public fun set_storage_gas_config(aptos_framework: &signer, config: storage_gas::StorageGasConfig)Implementation
public fun set_storage_gas_config(aptos_framework: &signer, config: StorageGasConfig) {    storage_gas::set_config(aptos_framework, config);    // Need to trigger reconfiguration so the VM is guaranteed to load the new gas fee starting from the next    // transaction.    reconfiguration::reconfigure();}set_storage_gas_config_for_next_epoch
public fun set_storage_gas_config_for_next_epoch(aptos_framework: &signer, config: storage_gas::StorageGasConfig)Implementation
public fun set_storage_gas_config_for_next_epoch(aptos_framework: &signer, config: StorageGasConfig) {    storage_gas::set_config(aptos_framework, config);}Specification
High-level Requirements
| No. | Requirement | Criticality | Implementation | Enforcement | 
|---|---|---|---|---|
| 1 | During genesis, the Aptos framework account should be assigned the gas schedule resource. | Medium | The gas_schedule::initialize function calls the assert_aptos_framework function to ensure that the signer is the aptos_framework and then assigns the GasScheduleV2 resource to it. | Formally verified via initialize. | 
| 2 | Only the Aptos framework account should be allowed to update the gas schedule resource. | Critical | The gas_schedule::set_gas_schedule function calls the assert_aptos_framework function to ensure that the signer is the aptos framework account. | Formally verified via set_gas_schedule. | 
| 3 | Only valid gas schedule should be allowed for initialization and update. | Medium | The initialize and set_gas_schedule functions ensures that the gas_schedule_blob is not empty. | Formally verified via initialize and set_gas_schedule. | 
| 4 | Only a gas schedule with the feature version greater or equal than the current feature version is allowed to be provided when performing an update operation. | Medium | The set_gas_schedule function validates the feature_version of the new_gas_schedule by ensuring that it is greater or equal than the current gas_schedule.feature_version. | Formally verified via set_gas_schedule. | 
Module-level Specification
pragma verify = true;pragma aborts_if_is_strict;initialize
public(friend) fun initialize(aptos_framework: &signer, gas_schedule_blob: vector<u8>)let addr = signer::address_of(aptos_framework);// This enforces high-level requirement 1:include system_addresses::AbortsIfNotAptosFramework{ account: aptos_framework };// This enforces high-level requirement 3:aborts_if len(gas_schedule_blob) == 0;aborts_if exists<GasScheduleV2>(addr);ensures exists<GasScheduleV2>(addr);set_gas_schedule
public fun set_gas_schedule(aptos_framework: &signer, gas_schedule_blob: vector<u8>)pragma verify_duration_estimate = 600;requires exists<CoinInfo<AptosCoin>>(@aptos_framework);requires chain_status::is_genesis();include staking_config::StakingRewardsConfigRequirement;// This enforces high-level requirement 2:include system_addresses::AbortsIfNotAptosFramework{ account: aptos_framework };// This enforces high-level requirement 3:aborts_if len(gas_schedule_blob) == 0;let new_gas_schedule = util::spec_from_bytes<GasScheduleV2>(gas_schedule_blob);let gas_schedule = global<GasScheduleV2>(@aptos_framework);// This enforces high-level requirement 4:aborts_if exists<GasScheduleV2>(@aptos_framework) && new_gas_schedule.feature_version < gas_schedule.feature_version;ensures exists<GasScheduleV2>(signer::address_of(aptos_framework));ensures global<GasScheduleV2>(@aptos_framework) == new_gas_schedule;set_for_next_epoch
public fun set_for_next_epoch(aptos_framework: &signer, gas_schedule_blob: vector<u8>)include system_addresses::AbortsIfNotAptosFramework{ account: aptos_framework };include config_buffer::SetForNextEpochAbortsIf {    account: aptos_framework,    config: gas_schedule_blob};let new_gas_schedule = util::spec_from_bytes<GasScheduleV2>(gas_schedule_blob);let cur_gas_schedule = global<GasScheduleV2>(@aptos_framework);aborts_if exists<GasScheduleV2>(@aptos_framework) && new_gas_schedule.feature_version < cur_gas_schedule.feature_version;set_for_next_epoch_check_hash
public fun set_for_next_epoch_check_hash(aptos_framework: &signer, old_gas_schedule_hash: vector<u8>, new_gas_schedule_blob: vector<u8>)include system_addresses::AbortsIfNotAptosFramework{ account: aptos_framework };include config_buffer::SetForNextEpochAbortsIf {    account: aptos_framework,    config: new_gas_schedule_blob};let new_gas_schedule = util::spec_from_bytes<GasScheduleV2>(new_gas_schedule_blob);let cur_gas_schedule = global<GasScheduleV2>(@aptos_framework);aborts_if exists<GasScheduleV2>(@aptos_framework) && new_gas_schedule.feature_version < cur_gas_schedule.feature_version;aborts_if exists<GasScheduleV2>(@aptos_framework) && (!features::spec_sha_512_and_ripemd_160_enabled() || aptos_hash::spec_sha3_512_internal(bcs::serialize(cur_gas_schedule)) != old_gas_schedule_hash);on_new_epoch
public(friend) fun on_new_epoch(framework: &signer)requires @aptos_framework == std::signer::address_of(framework);include config_buffer::OnNewEpochRequirement<GasScheduleV2>;aborts_if false;set_storage_gas_config
public fun set_storage_gas_config(aptos_framework: &signer, config: storage_gas::StorageGasConfig)pragma verify_duration_estimate = 600;requires exists<CoinInfo<AptosCoin>>(@aptos_framework);include system_addresses::AbortsIfNotAptosFramework{ account: aptos_framework };include staking_config::StakingRewardsConfigRequirement;aborts_if !exists<StorageGasConfig>(@aptos_framework);ensures global<StorageGasConfig>(@aptos_framework) == config;include system_addresses::AbortsIfNotAptosFramework{ account: aptos_framework };aborts_if !exists<storage_gas::StorageGasConfig>(@aptos_framework);set_storage_gas_config_for_next_epoch
public fun set_storage_gas_config_for_next_epoch(aptos_framework: &signer, config: storage_gas::StorageGasConfig)include system_addresses::AbortsIfNotAptosFramework{ account: aptos_framework };aborts_if !exists<storage_gas::StorageGasConfig>(@aptos_framework);