version - [mainnet]
Maintains the version number for the blockchain.
use 0x1::chain_status;use 0x1::config_buffer;use 0x1::error;use 0x1::reconfiguration;use 0x1::signer;use 0x1::system_addresses;
Constants
Specified major version number must be greater than current version number.
const EINVALID_MAJOR_VERSION_NUMBER: u64 = 1;
Account is not authorized to make this change.
const ENOT_AUTHORIZED: u64 = 2;
Resources
Version
struct Version has drop, store, key
Fields
-
major: u64
SetVersionCapability
struct SetVersionCapability has key
Fields
-
dummy_field: bool
Functions
initialize
Only called during genesis. Publishes the Version config.
public(friend) fun initialize(aptos_framework: &signer, initial_version: u64)
Implementation
public(friend) fun initialize(aptos_framework: &signer, initial_version: u64) { system_addresses::assert_aptos_framework(aptos_framework);
move_to(aptos_framework, Version { major: initial_version }); // Give aptos framework account capability to call set version. This allows on chain governance to do it through // control of the aptos framework account. move_to(aptos_framework, SetVersionCapability {});}
set_version
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 entry fun set_version(account: &signer, major: u64)
Implementation
public entry fun set_version(account: &signer, major: u64) acquires Version { assert!(exists<SetVersionCapability>(signer::address_of(account)), error::permission_denied(ENOT_AUTHORIZED)); chain_status::assert_genesis();
let old_major = borrow_global<Version>(@aptos_framework).major; assert!(old_major < major, error::invalid_argument(EINVALID_MAJOR_VERSION_NUMBER));
let config = borrow_global_mut<Version>(@aptos_framework); config.major = major;
// Need to trigger reconfiguration so validator nodes can sync on the updated version. reconfiguration::reconfigure();}
set_for_next_epoch
Used in on-chain governances to update the major version for the next epoch. Example usage:
aptos_framework::version::set_for_next_epoch(&framework_signer, new_version);
aptos_framework::aptos_governance::reconfigure(&framework_signer);
public entry fun set_for_next_epoch(account: &signer, major: u64)
Implementation
public entry fun set_for_next_epoch(account: &signer, major: u64) acquires Version { assert!(exists<SetVersionCapability>(signer::address_of(account)), error::permission_denied(ENOT_AUTHORIZED)); let old_major = borrow_global<Version>(@aptos_framework).major; assert!(old_major < major, error::invalid_argument(EINVALID_MAJOR_VERSION_NUMBER)); config_buffer::upsert(Version {major});}
on_new_epoch
Only used in reconfigurations to apply the pending Version
, if there is any.
public(friend) fun on_new_epoch(framework: &signer)
Implementation
public(friend) fun on_new_epoch(framework: &signer) acquires Version { system_addresses::assert_aptos_framework(framework); if (config_buffer::does_exist<Version>()) { let new_value = config_buffer::extract_v2<Version>(); if (exists<Version>(@aptos_framework)) { *borrow_global_mut<Version>(@aptos_framework) = new_value; } else { move_to(framework, new_value); } }}
initialize_for_test
Only called in tests and testnets. This allows the core resources account, which only exists in tests/testnets, to update the version.
fun initialize_for_test(core_resources: &signer)
Implementation
fun initialize_for_test(core_resources: &signer) { system_addresses::assert_core_resource(core_resources); move_to(core_resources, SetVersionCapability {});}
Specification
High-level Requirements
No. | Requirement | Criticality | Implementation | Enforcement |
---|---|---|---|---|
1 | During genesis, the Version resource should be initialized with the initial version and stored along with its capability under the aptos framework account. | Medium | The initialize function ensures that the signer is the aptos framework account and stores the Version and SetVersionCapability resources in it. | Formally verified via initialize. |
2 | The version should be updateable after initialization, but only by the Aptos framework account and with an increasing version number. | Medium | The version number for the blockchain should be updatable whenever necessary. This functionality is provided by the set_version function which ensures that the new version is greater than the previous one. | Formally verified via set_version. |
Module-level Specification
pragma verify = true;pragma aborts_if_is_strict;
initialize
public(friend) fun initialize(aptos_framework: &signer, initial_version: u64)
Abort if resource already exists in @aptos_framwork
when initializing.
// This enforces high-level requirement 1:aborts_if signer::address_of(aptos_framework) != @aptos_framework;aborts_if exists<Version>(@aptos_framework);aborts_if exists<SetVersionCapability>(@aptos_framework);ensures exists<Version>(@aptos_framework);ensures exists<SetVersionCapability>(@aptos_framework);ensures global<Version>(@aptos_framework) == Version { major: initial_version };ensures global<SetVersionCapability>(@aptos_framework) == SetVersionCapability {};
set_version
public entry fun set_version(account: &signer, major: u64)
pragma verify_duration_estimate = 120;include staking_config::StakingRewardsConfigRequirement;requires chain_status::is_genesis();requires timestamp::spec_now_microseconds() >= reconfiguration::last_reconfiguration_time();requires exists<CoinInfo<AptosCoin>>(@aptos_framework);aborts_if !exists<SetVersionCapability>(signer::address_of(account));aborts_if !exists<Version>(@aptos_framework);let old_major = global<Version>(@aptos_framework).major;// This enforces high-level requirement 2:aborts_if !(old_major < major);ensures global<Version>(@aptos_framework).major == major;
set_for_next_epoch
public entry fun set_for_next_epoch(account: &signer, major: u64)
aborts_if !exists<SetVersionCapability>(signer::address_of(account));aborts_if !exists<Version>(@aptos_framework);aborts_if global<Version>(@aptos_framework).major >= major;aborts_if !exists<config_buffer::PendingConfigs>(@aptos_framework);
on_new_epoch
public(friend) fun on_new_epoch(framework: &signer)
requires @aptos_framework == std::signer::address_of(framework);include config_buffer::OnNewEpochRequirement<Version>;aborts_if false;
initialize_for_test
fun initialize_for_test(core_resources: &signer)
This module turns on aborts_if_is_strict
, so need to add spec for test function initialize_for_test
.
pragma verify = false;