starcoin-framework

Module 0x1::VMConfig

VMConfig keep track of VM related configuration, like gas schedule.

use 0x1::ChainId;
use 0x1::Config;
use 0x1::CoreAddresses;
use 0x1::Vector;

Struct VMConfig

The struct to hold all config data needed to operate the VM.

struct VMConfig has copy, drop, store
Fields
gas_schedule: VMConfig::GasSchedule

Struct GasSchedule

The gas schedule keeps two separate schedules for the gas:

struct GasSchedule has copy, drop, store
Fields
instruction_schedule: vector<u8>
native_schedule: vector<u8>
gas_constants: VMConfig::GasConstants

Struct GasConstants

The gas constants contains all kind of constants used in gas calculation.

struct GasConstants has copy, drop, store
Fields
global_memory_per_byte_cost: u64
The cost per-byte written to global storage.
global_memory_per_byte_write_cost: u64
The cost per-byte written to storage.
min_transaction_gas_units: u64
We charge one unit of gas per-byte for the first 600 bytes
large_transaction_cutoff: u64
Any transaction over this size will be charged INTRINSIC_GAS_PER_BYTE per byte
instrinsic_gas_per_byte: u64
The units of gas that should be charged per byte for every transaction.
maximum_number_of_gas_units: u64
1 nanosecond should equal one unit of computational gas. We bound the maximum computational time of any given transaction at 10 milliseconds. We want this number and MAX_PRICE_PER_GAS_UNIT to always satisfy the inequality that MAXIMUM_NUMBER_OF_GAS_UNITS * MAX_PRICE_PER_GAS_UNIT < min(u64::MAX, GasUnits::MAX) </dd>
min_price_per_gas_unit: u64
The minimum gas price that a transaction can be submitted with.
max_price_per_gas_unit: u64
The maximum gas unit price that a transaction can be submitted with.
max_transaction_size_in_bytes: u64
The max transaction size in bytes that a transaction can have.
gas_unit_scaling_factor: u64
gas unit scaling factor.
default_account_size: u64
default account size.
</dl> </details> ## Struct `GasCost` The GasCost tracks: - instruction cost: how much time/computational power is needed to perform the instruction - memory cost: how much memory is required for the instruction, and storage overhead
struct GasCost has copy, drop, store
Fields
instruction_gas: u64
memory_gas: u64
## Function `instruction_schedule`
public fun instruction_schedule(): vector<VMConfig::GasCost>
Implementation
public fun instruction_schedule(): vector<GasCost> {
    let table = Vector::empty();

    // POP
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // RET
    Vector::push_back(&mut table, new_gas_cost(638, 1));
    // BR_TRUE
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // BR_FALSE
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // BRANCH
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // LD_U64
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // LD_CONST
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // LD_TRUE
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // LD_FALSE
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // COPY_LOC
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // MOVE_LOC
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // ST_LOC
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // MUT_BORROW_LOC
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // IMM_BORROW_LOC
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // MUT_BORROW_FIELD
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // IMM_BORROW_FIELD
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // CALL
    Vector::push_back(&mut table, new_gas_cost(1132, 1));
    // PACK
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // UNPACK
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // READ_REF
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // WRITE_REF
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // ADD
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // SUB
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // MUL
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // MOD
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // DIV
    Vector::push_back(&mut table, new_gas_cost(3, 1));
    // BIT_OR
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // BIT_AND
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // XOR
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // OR
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // AND
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // NOT
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // EQ
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // NEQ
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // LT
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // GT
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // LE
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // GE
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // ABORT
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // NOP
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // EXISTS
    Vector::push_back(&mut table, new_gas_cost(41, 1));
    // MUT_BORROW_GLOBAL
    Vector::push_back(&mut table, new_gas_cost(21, 1));
    // IML_BORROW_GLOBAL
    Vector::push_back(&mut table, new_gas_cost(23, 1));
    // MOVE_FROM
    Vector::push_back(&mut table, new_gas_cost(459, 1));
    // MOVE_TO
    Vector::push_back(&mut table, new_gas_cost(13, 1));
    // FREEZE_REF
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // SHL
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // SHR
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // LD_U8
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // LD_U128
    Vector::push_back(&mut table, new_gas_cost(1, 1));

    // CAST_U8
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // CAST_U64
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // CAST_U128
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // MUT_BORORW_FIELD_GENERIC
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // IMM_BORORW_FIELD_GENERIC
    Vector::push_back(&mut table, new_gas_cost(1, 1));
    // CALL_GENERIC
    Vector::push_back(&mut table, new_gas_cost(582, 1));
    // PACK_GENERIC
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // UNPACK_GENERIC
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    // EXISTS_GENERIC
    Vector::push_back(&mut table, new_gas_cost(34, 1));
    // MUT_BORROW_GLOBAL_GENERIC
    Vector::push_back(&mut table, new_gas_cost(15, 1));
    // IMM_BORROW_GLOBAL_GENERIC
    Vector::push_back(&mut table, new_gas_cost(14, 1));
    // MOVE_FROM_GENERIC
    Vector::push_back(&mut table, new_gas_cost(13, 1));
    // MOVE_TO_GENERIC
    Vector::push_back(&mut table, new_gas_cost(27, 1));

    // VEC_PACK
    Vector::push_back(&mut table, new_gas_cost(84, 1));
    // VEC_LEN
    Vector::push_back(&mut table, new_gas_cost(98, 1));
    // VEC_IMM_BORROW
    Vector::push_back(&mut table, new_gas_cost(1334, 1));
    // VEC_MUT_BORROW
    Vector::push_back(&mut table, new_gas_cost(1902, 1));
    // VEC_PUSH_BACK
    Vector::push_back(&mut table, new_gas_cost(53, 1));
    // VEC_POP_BACK
    Vector::push_back(&mut table, new_gas_cost(227, 1));
    // VEC_UNPACK
    Vector::push_back(&mut table, new_gas_cost(572, 1));
    // VEC_SWAP
    Vector::push_back(&mut table, new_gas_cost(1436, 1));
    table
}
## Function `native_schedule`
public fun native_schedule(): vector<VMConfig::GasCost>
Implementation
public fun native_schedule(): vector<GasCost> {
    let table = Vector::empty();
    //Hash::sha2_256 0
    Vector::push_back(&mut table, new_gas_cost(21, 1));
    //Hash::sha3_256 1
    Vector::push_back(&mut table, new_gas_cost(64, 1));
    //Signature::ed25519_verify 2
    Vector::push_back(&mut table, new_gas_cost(61, 1));
    //ED25519_THRESHOLD_VERIFY 3 this native funciton is deprecated
    Vector::push_back(&mut table, new_gas_cost(3351, 1));
    //BSC::to_bytes 4
    Vector::push_back(&mut table, new_gas_cost(181, 1));
    //Vector::length 5
    Vector::push_back(&mut table, new_gas_cost(98, 1));
    //Vector::empty 6
    Vector::push_back(&mut table, new_gas_cost(84, 1));
    //Vector::borrow 7
    Vector::push_back(&mut table, new_gas_cost(1334, 1));
    //Vector::borrow_mut 8
    Vector::push_back(&mut table, new_gas_cost(1902, 1));
    //Vector::push_back 9
    Vector::push_back(&mut table, new_gas_cost(53, 1));
    //Vector::pop_back 10
    Vector::push_back(&mut table, new_gas_cost(227, 1));
    //Vector::destory_empty 11
    Vector::push_back(&mut table, new_gas_cost(572, 1));
    //Vector::swap 12
    Vector::push_back(&mut table, new_gas_cost(1436, 1));
    //Signature::ed25519_validate_pubkey 13
    Vector::push_back(&mut table, new_gas_cost(26, 1));
    //Signer::borrow_address 14
    Vector::push_back(&mut table, new_gas_cost(353, 1));
    //Account::creator_signer 15
    Vector::push_back(&mut table, new_gas_cost(24, 1));
    //Account::destroy_signer 16
    Vector::push_back(&mut table, new_gas_cost(212, 1));
    //Event::emit_event 17
    Vector::push_back(&mut table, new_gas_cost(52, 1));
    //BCS::to_address 18
    Vector::push_back(&mut table, new_gas_cost(26, 1));
    //Token::name_of 19
    Vector::push_back(&mut table, new_gas_cost(2002, 1));
    //Hash::keccak_256 20
    Vector::push_back(&mut table, new_gas_cost(64, 1));
    //Hash::ripemd160 21
    Vector::push_back(&mut table, new_gas_cost(64, 1));
    //Signature::native_ecrecover 22
    Vector::push_back(&mut table, new_gas_cost(128, 1));
    //U256::from_bytes 23
    Vector::push_back(&mut table, new_gas_cost(2, 1));
    //U256::add 24
    Vector::push_back(&mut table, new_gas_cost(4, 1));
    //U256::sub 25
    Vector::push_back(&mut table, new_gas_cost(4, 1));
    //U256::mul 26
    Vector::push_back(&mut table, new_gas_cost(4, 1));
    //U256::div 27
    Vector::push_back(&mut table, new_gas_cost(10, 1));
    // U256::rem 28
    Vector::push_back(&mut table, new_gas_cost(4, 1));
    // U256::pow 29
    Vector::push_back(&mut table, new_gas_cost(8, 1));
    // TODO: settle down the gas cost
    // Vector::append 30
    Vector::push_back(&mut table, new_gas_cost(40, 1));
    // Vector::remove 31
    Vector::push_back(&mut table, new_gas_cost(20, 1));
    // Vector::reverse 32
    Vector::push_back(&mut table, new_gas_cost(10, 1));

    table
}
## Function `gas_constants`
public fun gas_constants(): VMConfig::GasConstants
Implementation
public fun gas_constants(): GasConstants {
    let min_price_per_gas_unit: u64 = if (ChainId::is_test()) { 0 }  else { 1 };
    let maximum_number_of_gas_units: u64 = 40000000;//must less than base_block_gas_limit

    if (ChainId::is_test() || ChainId::is_dev() || ChainId::is_halley()) {
        maximum_number_of_gas_units = maximum_number_of_gas_units * 10
    };
    GasConstants {
        global_memory_per_byte_cost: 4,
        global_memory_per_byte_write_cost: 9,
        min_transaction_gas_units: 600,
        large_transaction_cutoff: 600,
        instrinsic_gas_per_byte: 8,
        maximum_number_of_gas_units,
        min_price_per_gas_unit,
        max_price_per_gas_unit: 10000,
        max_transaction_size_in_bytes: 1024 * 128,
        gas_unit_scaling_factor: 1,
        default_account_size: 800,
    }
}
## Function `new_gas_cost`
fun new_gas_cost(instr_gas: u64, mem_gas: u64): VMConfig::GasCost
Implementation
fun new_gas_cost(instr_gas: u64, mem_gas: u64): GasCost {
    GasCost {
        instruction_gas: instr_gas,
        memory_gas: mem_gas,
    }
}
## Function `new_vm_config` Create a new vm config, mainly used in DAO.
public fun new_vm_config(instruction_schedule: vector<u8>, native_schedule: vector<u8>, global_memory_per_byte_cost: u64, global_memory_per_byte_write_cost: u64, min_transaction_gas_units: u64, large_transaction_cutoff: u64, instrinsic_gas_per_byte: u64, maximum_number_of_gas_units: u64, min_price_per_gas_unit: u64, max_price_per_gas_unit: u64, max_transaction_size_in_bytes: u64, gas_unit_scaling_factor: u64, default_account_size: u64): VMConfig::VMConfig
Implementation
public fun new_vm_config(
    instruction_schedule: vector<u8>,
    native_schedule: vector<u8>,
    global_memory_per_byte_cost: u64,
    global_memory_per_byte_write_cost: u64,
    min_transaction_gas_units: u64,
    large_transaction_cutoff: u64,
    instrinsic_gas_per_byte: u64,
    maximum_number_of_gas_units: u64,
    min_price_per_gas_unit: u64,
    max_price_per_gas_unit: u64,
    max_transaction_size_in_bytes: u64,
    gas_unit_scaling_factor: u64,
    default_account_size: u64,
): VMConfig {
    let gas_constants = GasConstants {
        global_memory_per_byte_cost,
        global_memory_per_byte_write_cost,
        min_transaction_gas_units,
        large_transaction_cutoff,
        instrinsic_gas_per_byte,
        maximum_number_of_gas_units,
        min_price_per_gas_unit,
        max_price_per_gas_unit,
        max_transaction_size_in_bytes,
        gas_unit_scaling_factor,
        default_account_size,
    };
    VMConfig {
        gas_schedule: GasSchedule { instruction_schedule, native_schedule, gas_constants },
    }
}
## Function `initialize` Initialize the table under the genesis account
public fun initialize(account: &signer, instruction_schedule: vector<u8>, native_schedule: vector<u8>, global_memory_per_byte_cost: u64, global_memory_per_byte_write_cost: u64, min_transaction_gas_units: u64, large_transaction_cutoff: u64, instrinsic_gas_per_byte: u64, maximum_number_of_gas_units: u64, min_price_per_gas_unit: u64, max_price_per_gas_unit: u64, max_transaction_size_in_bytes: u64, gas_unit_scaling_factor: u64, default_account_size: u64)
Implementation
public fun initialize(
    account: &signer,
    instruction_schedule: vector<u8>,
    native_schedule: vector<u8>,
    global_memory_per_byte_cost: u64,
    global_memory_per_byte_write_cost: u64,
    min_transaction_gas_units: u64,
    large_transaction_cutoff: u64,
    instrinsic_gas_per_byte: u64,
    maximum_number_of_gas_units: u64,
    min_price_per_gas_unit: u64,
    max_price_per_gas_unit: u64,
    max_transaction_size_in_bytes: u64,
    gas_unit_scaling_factor: u64,
    default_account_size: u64,
) {
    CoreAddresses::assert_genesis_address(account);
    Config::publish_new_config<VMConfig>(
        account,
        new_vm_config(
            instruction_schedule,
            native_schedule,
            global_memory_per_byte_cost,
            global_memory_per_byte_write_cost,
            min_transaction_gas_units,
            large_transaction_cutoff,
            instrinsic_gas_per_byte,
            maximum_number_of_gas_units,
            min_price_per_gas_unit,
            max_price_per_gas_unit,
            max_transaction_size_in_bytes,
            gas_unit_scaling_factor,
            default_account_size,
        ),
    );
}
Specification
aborts_if Signer::address_of(account) != CoreAddresses::SPEC_GENESIS_ADDRESS();
aborts_if exists<Config::Config<VMConfig>>(Signer::address_of(account));
aborts_if
    exists<Config::ModifyConfigCapabilityHolder<VMConfig>>(
        Signer::address_of(account),
    );
ensures exists<Config::Config<VMConfig>>(Signer::address_of(account));
ensures
    exists<Config::ModifyConfigCapabilityHolder<VMConfig>>(
        Signer::address_of(account),
    );
## Module Specification
pragma verify = false;
pragma aborts_if_is_strict;