Skip to content

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.RequirementCriticalityImplementationEnforcement
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;