Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Module 0x1::version

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;

Resource Version

struct Version has drop, store, key
Fields
major: u64

Resource SetVersionCapability

struct SetVersionCapability has key
Fields
dummy_field: bool

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;

Function 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 {});
}

Function 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();
}

Function 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});
}

Function 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);
        }
    }
}

Function 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;

Function 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 {};

Function 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;

Function 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);

Function 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;

Function 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;