gas_schedule - [mainnet]
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, store
Fields
-
key: string::String
-
val: u64
Resources
GasSchedule
struct GasSchedule has copy, drop, key
Fields
-
entries: vector<gas_schedule::GasEntry>
GasScheduleV2
struct GasScheduleV2 has copy, drop, store, key
Fields
-
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);