Skip to main content

Module 0x3::iota_system_state_inner

use 0x1::option; use 0x1::vector; use 0x2::bag; use 0x2::balance; use 0x2::coin; use 0x2::event; use 0x2::iota; use 0x2::object; use 0x2::pay; use 0x2::system_admin_cap; use 0x2::table; use 0x2::transfer; use 0x2::tx_context; use 0x2::vec_map; use 0x2::vec_set; use 0x3::staking_pool; use 0x3::storage_fund; use 0x3::validator; use 0x3::validator_cap; use 0x3::validator_set;

Struct SystemParametersV1

A list of system config parameters.

struct SystemParametersV1 has store

Fields
epoch_duration_ms: u64

The duration of an epoch, in milliseconds.

min_validator_count: u64

Minimum number of active validators at any moment.

max_validator_count: u64

Maximum number of active validators at any moment. We do not allow the number of validators in any epoch to go above this.

min_validator_joining_stake: u64

Lower-bound on the amount of stake required to become a validator.

validator_low_stake_threshold: u64

Validators with stake amount below validator_low_stake_threshold are considered to have low stake and will be escorted out of the validator set after being below this threshold for more than validator_low_stake_grace_period number of epochs.

validator_very_low_stake_threshold: u64

Validators with stake below validator_very_low_stake_threshold will be removed immediately at epoch change, no grace period.

validator_low_stake_grace_period: u64

A validator can have stake below validator_low_stake_threshold for this many epochs before being kicked out.

extra_fields: bag::Bag

Any extra fields that's not defined statically.

Struct IotaSystemStateV1

The top-level object containing all information of the Iota system.

struct IotaSystemStateV1 has store

Fields
epoch: u64

The current epoch ID, starting from 0.

protocol_version: u64

The current protocol version, starting from 1.

system_state_version: u64

The current version of the system state data structure type. This is always the same as IotaSystemState.version. Keeping a copy here so that we know what version it is by inspecting IotaSystemStateV1 as well.

iota_treasury_cap: iota::IotaTreasuryCap

The IOTA's TreasuryCap.

validators: validator_set::ValidatorSetV1

Contains all information about the validators.

storage_fund: storage_fund::StorageFundV1

The storage fund.

parameters: iota_system_state_inner::SystemParametersV1

A list of system config parameters.

iota_system_admin_cap: system_admin_cap::IotaSystemAdminCap

A capability allows to perform privileged IOTA system operations.

reference_gas_price: u64

The reference gas price for the current epoch.

validator_report_records: vec_map::VecMap<address, vec_set::VecSet<address>>

A map storing the records of validator reporting each other. There is an entry in the map for each validator that has been reported at least once. The entry VecSet contains all the validators that reported them. If a validator has never been reported they don't have an entry in this map. This map persists across epoch: a peer continues being in a reported state until the reporter doesn't explicitly remove their report. Note that in case we want to support validator address change in future, the reports should be based on validator ids

safe_mode: bool

Whether the system is running in a downgraded safe mode due to a non-recoverable bug. This is set whenever we failed to execute advance_epoch, and ended up executing advance_epoch_safe_mode. It can be reset once we are able to successfully execute advance_epoch. The rest of the fields starting with safe_mode_ are accmulated during safe mode when advance_epoch_safe_mode is executed. They will eventually be processed once we are out of safe mode.

safe_mode_storage_charges: balance::Balance<iota::IOTA>
safe_mode_computation_rewards: balance::Balance<iota::IOTA>
safe_mode_storage_rebates: u64
safe_mode_non_refundable_storage_fee: u64
epoch_start_timestamp_ms: u64

Unix timestamp of the current epoch start

extra_fields: bag::Bag

Any extra fields that's not defined statically.

Struct SystemEpochInfoEventV1

Event containing system-level epoch information, emitted during the epoch advancement transaction.

struct SystemEpochInfoEventV1 has copy, drop

Fields
epoch: u64
protocol_version: u64
reference_gas_price: u64
total_stake: u64
storage_charge: u64
storage_rebate: u64
storage_fund_balance: u64
total_gas_fees: u64
total_stake_rewards_distributed: u64
burnt_tokens_amount: u64
minted_tokens_amount: u64

Constants

const ENotSystemAddress: u64 = 2;

const ACTIVE_OR_PENDING_VALIDATOR: u8 = 2;

const ACTIVE_VALIDATOR_ONLY: u8 = 1;

const ANY_VALIDATOR: u8 = 3;

const BASIS_POINT_DENOMINATOR: u128 = 10000;

const EAdvancedToWrongEpoch: u64 = 8;

const EBpsTooLarge: u64 = 5;

const ECannotReportOneself: u64 = 3;

const ELimitExceeded: u64 = 1;

const ENotValidator: u64 = 0;

const EReportRecordNotFound: u64 = 4;

const ESafeModeGasNotProcessed: u64 = 7;

const SYSTEM_STATE_VERSION_V1: u64 = 1;

Function create

Create a new IotaSystemState object and make it shared. This function will be called only once in genesis.

public(friend) fun create(iota_treasury_cap: iota::IotaTreasuryCap, validators: vector<validator::ValidatorV1>, initial_storage_fund: balance::Balance<iota::IOTA>, protocol_version: u64, epoch_start_timestamp_ms: u64, parameters: iota_system_state_inner::SystemParametersV1, iota_system_admin_cap: system_admin_cap::IotaSystemAdminCap, ctx: &mut tx_context::TxContext): iota_system_state_inner::IotaSystemStateV1

Implementation

public(package) fun create( iota_treasury_cap: IotaTreasuryCap, validators: vector<ValidatorV1>, initial_storage_fund: Balance<IOTA>, protocol_version: u64, epoch_start_timestamp_ms: u64, parameters: SystemParametersV1, iota_system_admin_cap: IotaSystemAdminCap, ctx: &mut TxContext, ): IotaSystemStateV1 { let validators = validator_set::new(validators, ctx); let reference_gas_price = validators.derive_reference_gas_price(); // This type is fixed as it's created at genesis. It should not be updated during type upgrade. let system_state = IotaSystemStateV1 { epoch: 0, protocol_version, system_state_version: genesis_system_state_version(), iota_treasury_cap, validators, storage_fund: storage_fund::new(initial_storage_fund), parameters, iota_system_admin_cap, reference_gas_price, validator_report_records: vec_map::empty(), safe_mode: false, safe_mode_storage_charges: balance::zero(), safe_mode_computation_rewards: balance::zero(), safe_mode_storage_rebates: 0, safe_mode_non_refundable_storage_fee: 0, epoch_start_timestamp_ms, extra_fields: bag::new(ctx), }; system_state }

Function create_system_parameters

public(friend) fun create_system_parameters(epoch_duration_ms: u64, max_validator_count: u64, min_validator_joining_stake: u64, validator_low_stake_threshold: u64, validator_very_low_stake_threshold: u64, validator_low_stake_grace_period: u64, ctx: &mut tx_context::TxContext): iota_system_state_inner::SystemParametersV1

Implementation

public(package) fun create_system_parameters( epoch_duration_ms: u64,

// ValidatorV1 committee parameters max_validator_count: u64, min_validator_joining_stake: u64, validator_low_stake_threshold: u64, validator_very_low_stake_threshold: u64, validator_low_stake_grace_period: u64, ctx: &mut TxContext, ): SystemParametersV1 { SystemParametersV1 { epoch_duration_ms, min_validator_count: 4, max_validator_count, min_validator_joining_stake, validator_low_stake_threshold, validator_very_low_stake_threshold, validator_low_stake_grace_period, extra_fields: bag::new(ctx), } }

Function request_add_validator_candidate

Can be called by anyone who wishes to become a validator candidate and starts accuring delegated stakes in their staking pool. Once they have at least MIN_VALIDATOR_JOINING_STAKE amount of stake they can call request_add_validator to officially become an active validator at the next epoch. Aborts if the caller is already a pending or active validator, or a validator candidate. Note: proof_of_possession MUST be a valid signature using iota_address and authority_pubkey_bytes. To produce a valid PoP, run [fn test_proof_of_possession].

public(friend) fun request_add_validator_candidate(self: &mut iota_system_state_inner::IotaSystemStateV1, authority_pubkey_bytes: vector<u8>, network_pubkey_bytes: vector<u8>, protocol_pubkey_bytes: vector<u8>, proof_of_possession: vector<u8>, name: vector<u8>, description: vector<u8>, image_url: vector<u8>, project_url: vector<u8>, net_address: vector<u8>, p2p_address: vector<u8>, primary_address: vector<u8>, gas_price: u64, commission_rate: u64, ctx: &mut tx_context::TxContext)

Implementation

public(package) fun request_add_validator_candidate( self: &mut IotaSystemStateV1, authority_pubkey_bytes: vector<u8>, network_pubkey_bytes: vector<u8>, protocol_pubkey_bytes: vector<u8>, proof_of_possession: vector<u8>, name: vector<u8>, description: vector<u8>, image_url: vector<u8>, project_url: vector<u8>, net_address: vector<u8>, p2p_address: vector<u8>, primary_address: vector<u8>, gas_price: u64, commission_rate: u64, ctx: &mut TxContext, ) { let validator = validator::new( ctx.sender(), authority_pubkey_bytes, network_pubkey_bytes, protocol_pubkey_bytes, proof_of_possession, name, description, image_url, project_url, net_address, p2p_address, primary_address, gas_price, commission_rate, ctx );

self.validators.request_add_validator_candidate(validator, ctx); }

Function request_remove_validator_candidate

Called by a validator candidate to remove themselves from the candidacy. After this call their staking pool becomes deactivate.

public(friend) fun request_remove_validator_candidate(self: &mut iota_system_state_inner::IotaSystemStateV1, ctx: &mut tx_context::TxContext)

Implementation

public(package) fun request_remove_validator_candidate( self: &mut IotaSystemStateV1, ctx: &mut TxContext, ) { self.validators.request_remove_validator_candidate(ctx); }

Function request_add_validator

Called by a validator candidate to add themselves to the active validator set beginning next epoch. Aborts if the validator is a duplicate with one of the pending or active validators, or if the amount of stake the validator has doesn't meet the min threshold, or if the number of new validators for the next epoch has already reached the maximum.

public(friend) fun request_add_validator(self: &mut iota_system_state_inner::IotaSystemStateV1, ctx: &tx_context::TxContext)

Implementation

public(package) fun request_add_validator( self: &mut IotaSystemStateV1, ctx: &TxContext, ) { assert!( self.validators.next_epoch_validator_count() < self.parameters.max_validator_count, ELimitExceeded, );

self.validators.request_add_validator(self.parameters.min_validator_joining_stake, ctx); }

Function request_remove_validator

A validator can call this function to request a removal in the next epoch. We use the sender of ctx to look up the validator (i.e. sender must match the iota_address in the validator). At the end of the epoch, the validator object will be returned to the iota_address of the validator.

public(friend) fun request_remove_validator(self: &mut iota_system_state_inner::IotaSystemStateV1, ctx: &tx_context::TxContext)

Implementation

public(package) fun request_remove_validator( self: &mut IotaSystemStateV1, ctx: &TxContext, ) { // Only check min validator condition if the current number of validators satisfy the constraint. // This is so that if we somehow already are in a state where we have less than min validators, it no longer matters // and is ok to stay so. This is useful for a test setup. if (self.validators.active_validators().length() >= self.parameters.min_validator_count) { assert!( self.validators.next_epoch_validator_count() > self.parameters.min_validator_count, ELimitExceeded, ); };

self.validators.request_remove_validator(ctx) }

Function request_set_gas_price

A validator can call this function to submit a new gas price quote, to be used for the reference gas price calculation at the end of the epoch.

public(friend) fun request_set_gas_price(self: &mut iota_system_state_inner::IotaSystemStateV1, cap: &validator_cap::UnverifiedValidatorOperationCap, new_gas_price: u64)

Implementation

public(package) fun request_set_gas_price( self: &mut IotaSystemStateV1, cap: &UnverifiedValidatorOperationCap, new_gas_price: u64, ) { // Verify the represented address is an active or pending validator, and the capability is still valid. let verified_cap = self.validators.verify_cap(cap, ACTIVE_OR_PENDING_VALIDATOR); let validator = self.validators.get_validator_mut_with_verified_cap(&verified_cap, false /* include_candidate */);

validator.request_set_gas_price(verified_cap, new_gas_price); }

Function set_candidate_validator_gas_price

This function is used to set new gas price for candidate validators

public(friend) fun set_candidate_validator_gas_price(self: &mut iota_system_state_inner::IotaSystemStateV1, cap: &validator_cap::UnverifiedValidatorOperationCap, new_gas_price: u64)

Implementation

public(package) fun set_candidate_validator_gas_price( self: &mut IotaSystemStateV1, cap: &UnverifiedValidatorOperationCap, new_gas_price: u64, ) { // Verify the represented address is an active or pending validator, and the capability is still valid. let verified_cap = self.validators.verify_cap(cap, ANY_VALIDATOR); let candidate = self.validators.get_validator_mut_with_verified_cap(&verified_cap, true /* include_candidate */); candidate.set_candidate_gas_price(verified_cap, new_gas_price) }

Function request_set_commission_rate

A validator can call this function to set a new commission rate, updated at the end of the epoch.

public(friend) fun request_set_commission_rate(self: &mut iota_system_state_inner::IotaSystemStateV1, new_commission_rate: u64, ctx: &tx_context::TxContext)

Implementation

public(package) fun request_set_commission_rate( self: &mut IotaSystemStateV1, new_commission_rate: u64, ctx: &TxContext, ) { self.validators.request_set_commission_rate( new_commission_rate, ctx ) }

Function set_candidate_validator_commission_rate

This function is used to set new commission rate for candidate validators

public(friend) fun set_candidate_validator_commission_rate(self: &mut iota_system_state_inner::IotaSystemStateV1, new_commission_rate: u64, ctx: &tx_context::TxContext)

Implementation

public(package) fun set_candidate_validator_commission_rate( self: &mut IotaSystemStateV1, new_commission_rate: u64, ctx: &TxContext, ) { let candidate = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); candidate.set_candidate_commission_rate(new_commission_rate) }

Function request_add_stake

Add stake to a validator's staking pool.

public(friend) fun request_add_stake(self: &mut iota_system_state_inner::IotaSystemStateV1, stake: coin::Coin<iota::IOTA>, validator_address: address, ctx: &mut tx_context::TxContext): staking_pool::StakedIota

Implementation

public(package) fun request_add_stake( self: &mut IotaSystemStateV1, stake: Coin<IOTA>, validator_address: address, ctx: &mut TxContext, ) : StakedIota { self.validators.request_add_stake( validator_address, stake.into_balance(), ctx, ) }

Function request_add_stake_mul_coin

Add stake to a validator's staking pool using multiple coins.

public(friend) fun request_add_stake_mul_coin(self: &mut iota_system_state_inner::IotaSystemStateV1, stakes: vector<coin::Coin<iota::IOTA>>, stake_amount: option::Option<u64>, validator_address: address, ctx: &mut tx_context::TxContext): staking_pool::StakedIota

Implementation

public(package) fun request_add_stake_mul_coin( self: &mut IotaSystemStateV1, stakes: vector<Coin<IOTA>>, stake_amount: option::Option<u64>, validator_address: address, ctx: &mut TxContext, ) : StakedIota { let balance = extract_coin_balance(stakes, stake_amount, ctx); self.validators.request_add_stake(validator_address, balance, ctx) }

Function request_withdraw_stake

Withdraw some portion of a stake from a validator's staking pool.

public(friend) fun request_withdraw_stake(self: &mut iota_system_state_inner::IotaSystemStateV1, staked_iota: staking_pool::StakedIota, ctx: &tx_context::TxContext): balance::Balance<iota::IOTA>

Implementation

public(package) fun request_withdraw_stake( self: &mut IotaSystemStateV1, staked_iota: StakedIota, ctx: &TxContext, ) : Balance<IOTA> { self.validators.request_withdraw_stake(staked_iota, ctx) }

Function report_validator

Report a validator as a bad or non-performant actor in the system. Succeeds if all the following are satisfied:

  1. both the reporter in cap and the input reportee_addr are active validators.
  2. reporter and reportee not the same address.
  3. the cap object is still valid. This function is idempotent.

public(friend) fun report_validator(self: &mut iota_system_state_inner::IotaSystemStateV1, cap: &validator_cap::UnverifiedValidatorOperationCap, reportee_addr: address)

Implementation

public(package) fun report_validator( self: &mut IotaSystemStateV1, cap: &UnverifiedValidatorOperationCap, reportee_addr: address, ) { // Reportee needs to be an active validator assert!(self.validators.is_active_validator_by_iota_address(reportee_addr), ENotValidator); // Verify the represented reporter address is an active validator, and the capability is still valid. let verified_cap = self.validators.verify_cap(cap, ACTIVE_VALIDATOR_ONLY); report_validator_impl(verified_cap, reportee_addr, &mut self.validator_report_records); }

Function undo_report_validator

Undo a report_validator action. Aborts if

  1. the reportee is not a currently active validator or
  2. the sender has not previously reported the reportee_addr, or
  3. the cap is not valid

public(friend) fun undo_report_validator(self: &mut iota_system_state_inner::IotaSystemStateV1, cap: &validator_cap::UnverifiedValidatorOperationCap, reportee_addr: address)

Implementation

public(package) fun undo_report_validator( self: &mut IotaSystemStateV1, cap: &UnverifiedValidatorOperationCap, reportee_addr: address, ) { let verified_cap = self.validators.verify_cap(cap, ACTIVE_VALIDATOR_ONLY); undo_report_validator_impl(verified_cap, reportee_addr, &mut self.validator_report_records); }

Function report_validator_impl

fun report_validator_impl(verified_cap: validator_cap::ValidatorOperationCap, reportee_addr: address, validator_report_records: &mut vec_map::VecMap<address, vec_set::VecSet<address>>)

Implementation

fun report_validator_impl( verified_cap: ValidatorOperationCap, reportee_addr: address, validator_report_records: &mut VecMap<address, VecSet<address>>, ) { let reporter_address = *verified_cap.verified_operation_cap_address(); assert!(reporter_address != reportee_addr, ECannotReportOneself); if (!validator_report_records.contains(&reportee_addr)) { validator_report_records.insert(reportee_addr, vec_set::singleton(reporter_address)); } else { let reporters = validator_report_records.get_mut(&reportee_addr); if (!reporters.contains(&reporter_address)) { reporters.insert(reporter_address); } } }

Function undo_report_validator_impl

fun undo_report_validator_impl(verified_cap: validator_cap::ValidatorOperationCap, reportee_addr: address, validator_report_records: &mut vec_map::VecMap<address, vec_set::VecSet<address>>)

Implementation

fun undo_report_validator_impl( verified_cap: ValidatorOperationCap, reportee_addr: address, validator_report_records: &mut VecMap<address, VecSet<address>>, ) { assert!(validator_report_records.contains(&reportee_addr), EReportRecordNotFound); let reporters = validator_report_records.get_mut(&reportee_addr);

let reporter_addr = *verified_cap.verified_operation_cap_address(); assert!(reporters.contains(&reporter_addr), EReportRecordNotFound);

reporters.remove(&reporter_addr); if (reporters.is_empty()) { validator_report_records.remove(&reportee_addr); } }

Function rotate_operation_cap

Create a new UnverifiedValidatorOperationCap, transfer it to the validator and registers it. The original object is thus revoked.

public(friend) fun rotate_operation_cap(self: &mut iota_system_state_inner::IotaSystemStateV1, ctx: &mut tx_context::TxContext)

Implementation

public(package) fun rotate_operation_cap( self: &mut IotaSystemStateV1, ctx: &mut TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); validator.new_unverified_validator_operation_cap_and_transfer(ctx); }

Function update_validator_name

Update a validator's name.

public(friend) fun update_validator_name(self: &mut iota_system_state_inner::IotaSystemStateV1, name: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_name( self: &mut IotaSystemStateV1, name: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx_including_candidates(ctx);

validator.update_name(name); }

Function update_validator_description

Update a validator's description

public(friend) fun update_validator_description(self: &mut iota_system_state_inner::IotaSystemStateV1, description: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_description( self: &mut IotaSystemStateV1, description: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); validator.update_description(description); }

Function update_validator_image_url

Update a validator's image url

public(friend) fun update_validator_image_url(self: &mut iota_system_state_inner::IotaSystemStateV1, image_url: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_image_url( self: &mut IotaSystemStateV1, image_url: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); validator.update_image_url(image_url); }

Function update_validator_project_url

Update a validator's project url

public(friend) fun update_validator_project_url(self: &mut iota_system_state_inner::IotaSystemStateV1, project_url: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_project_url( self: &mut IotaSystemStateV1, project_url: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); validator.update_project_url(project_url); }

Function update_validator_next_epoch_network_address

Update a validator's network address. The change will only take effects starting from the next epoch.

public(friend) fun update_validator_next_epoch_network_address(self: &mut iota_system_state_inner::IotaSystemStateV1, network_address: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_next_epoch_network_address( self: &mut IotaSystemStateV1, network_address: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx(ctx); validator.update_next_epoch_network_address(network_address); let validator :&ValidatorV1 = validator; // Force immutability for the following call self.validators.assert_no_pending_or_active_duplicates(validator); }

Function update_candidate_validator_network_address

Update candidate validator's network address.

public(friend) fun update_candidate_validator_network_address(self: &mut iota_system_state_inner::IotaSystemStateV1, network_address: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_candidate_validator_network_address( self: &mut IotaSystemStateV1, network_address: vector<u8>, ctx: &TxContext, ) { let candidate = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); candidate.update_candidate_network_address(network_address); }

Function update_validator_next_epoch_p2p_address

Update a validator's p2p address. The change will only take effects starting from the next epoch.

public(friend) fun update_validator_next_epoch_p2p_address(self: &mut iota_system_state_inner::IotaSystemStateV1, p2p_address: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_next_epoch_p2p_address( self: &mut IotaSystemStateV1, p2p_address: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx(ctx); validator.update_next_epoch_p2p_address(p2p_address); let validator :&ValidatorV1 = validator; // Force immutability for the following call self.validators.assert_no_pending_or_active_duplicates(validator); }

Function update_candidate_validator_p2p_address

Update candidate validator's p2p address.

public(friend) fun update_candidate_validator_p2p_address(self: &mut iota_system_state_inner::IotaSystemStateV1, p2p_address: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_candidate_validator_p2p_address( self: &mut IotaSystemStateV1, p2p_address: vector<u8>, ctx: &TxContext, ) { let candidate = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); candidate.update_candidate_p2p_address(p2p_address); }

Function update_validator_next_epoch_primary_address

Update a validator's primary address. The change will only take effects starting from the next epoch.

public(friend) fun update_validator_next_epoch_primary_address(self: &mut iota_system_state_inner::IotaSystemStateV1, primary_address: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_next_epoch_primary_address( self: &mut IotaSystemStateV1, primary_address: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx(ctx); validator.update_next_epoch_primary_address(primary_address); }

Function update_candidate_validator_primary_address

Update candidate validator's primary address.

public(friend) fun update_candidate_validator_primary_address(self: &mut iota_system_state_inner::IotaSystemStateV1, primary_address: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_candidate_validator_primary_address( self: &mut IotaSystemStateV1, primary_address: vector<u8>, ctx: &TxContext, ) { let candidate = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); candidate.update_candidate_primary_address(primary_address); }

Function update_validator_next_epoch_authority_pubkey

Update a validator's public key of authority key and proof of possession. The change will only take effects starting from the next epoch.

public(friend) fun update_validator_next_epoch_authority_pubkey(self: &mut iota_system_state_inner::IotaSystemStateV1, authority_pubkey: vector<u8>, proof_of_possession: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_next_epoch_authority_pubkey( self: &mut IotaSystemStateV1, authority_pubkey: vector<u8>, proof_of_possession: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx(ctx); validator.update_next_epoch_authority_pubkey(authority_pubkey, proof_of_possession); let validator :&ValidatorV1 = validator; // Force immutability for the following call self.validators.assert_no_pending_or_active_duplicates(validator); }

Function update_candidate_validator_authority_pubkey

Update candidate validator's public key of authority key and proof of possession.

public(friend) fun update_candidate_validator_authority_pubkey(self: &mut iota_system_state_inner::IotaSystemStateV1, authority_pubkey: vector<u8>, proof_of_possession: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_candidate_validator_authority_pubkey( self: &mut IotaSystemStateV1, authority_pubkey: vector<u8>, proof_of_possession: vector<u8>, ctx: &TxContext, ) { let candidate = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); candidate.update_candidate_authority_pubkey(authority_pubkey, proof_of_possession); }

Function update_validator_next_epoch_protocol_pubkey

Update a validator's public key of protocol key. The change will only take effects starting from the next epoch.

public(friend) fun update_validator_next_epoch_protocol_pubkey(self: &mut iota_system_state_inner::IotaSystemStateV1, protocol_pubkey: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_next_epoch_protocol_pubkey( self: &mut IotaSystemStateV1, protocol_pubkey: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx(ctx); validator.update_next_epoch_protocol_pubkey(protocol_pubkey); let validator :&ValidatorV1 = validator; // Force immutability for the following call self.validators.assert_no_pending_or_active_duplicates(validator); }

Function update_candidate_validator_protocol_pubkey

Update candidate validator's public key of protocol key.

public(friend) fun update_candidate_validator_protocol_pubkey(self: &mut iota_system_state_inner::IotaSystemStateV1, protocol_pubkey: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_candidate_validator_protocol_pubkey( self: &mut IotaSystemStateV1, protocol_pubkey: vector<u8>, ctx: &TxContext, ) { let candidate = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); candidate.update_candidate_protocol_pubkey(protocol_pubkey); }

Function update_validator_next_epoch_network_pubkey

Update a validator's public key of network key. The change will only take effects starting from the next epoch.

public(friend) fun update_validator_next_epoch_network_pubkey(self: &mut iota_system_state_inner::IotaSystemStateV1, network_pubkey: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_validator_next_epoch_network_pubkey( self: &mut IotaSystemStateV1, network_pubkey: vector<u8>, ctx: &TxContext, ) { let validator = self.validators.get_validator_mut_with_ctx(ctx); validator.update_next_epoch_network_pubkey(network_pubkey); let validator :&ValidatorV1 = validator; // Force immutability for the following call self.validators.assert_no_pending_or_active_duplicates(validator); }

Function update_candidate_validator_network_pubkey

Update candidate validator's public key of network key.

public(friend) fun update_candidate_validator_network_pubkey(self: &mut iota_system_state_inner::IotaSystemStateV1, network_pubkey: vector<u8>, ctx: &tx_context::TxContext)

Implementation

public(package) fun update_candidate_validator_network_pubkey( self: &mut IotaSystemStateV1, network_pubkey: vector<u8>, ctx: &TxContext, ) { let candidate = self.validators.get_validator_mut_with_ctx_including_candidates(ctx); candidate.update_candidate_network_pubkey(network_pubkey); }

Function advance_epoch

This function should be called at the end of an epoch, and advances the system to the next epoch. It does the following things:

  1. Add storage charge to the storage fund.
  2. Burn the storage rebates from the storage fund. These are already refunded to transaction sender's gas coins.
  3. Mint or burn IOTA tokens depending on whether the validator target reward is greater or smaller than the computation reward.
  4. Distribute the target reward to the validators.
  5. Burn any leftover rewards.
  6. Update all validators.

public(friend) fun advance_epoch(self: &mut iota_system_state_inner::IotaSystemStateV1, new_epoch: u64, next_protocol_version: u64, validator_target_reward: u64, storage_charge: balance::Balance<iota::IOTA>, computation_reward: balance::Balance<iota::IOTA>, storage_rebate_amount: u64, non_refundable_storage_fee_amount: u64, reward_slashing_rate: u64, epoch_start_timestamp_ms: u64, ctx: &mut tx_context::TxContext): balance::Balance<iota::IOTA>

Implementation

public(package) fun advance_epoch( self: &mut IotaSystemStateV1, new_epoch: u64, next_protocol_version: u64, validator_target_reward: u64, mut storage_charge: Balance<IOTA>, mut computation_reward: Balance<IOTA>, mut storage_rebate_amount: u64, mut non_refundable_storage_fee_amount: u64, reward_slashing_rate: u64, // how much rewards are slashed to punish a validator, in bps. epoch_start_timestamp_ms: u64, // Timestamp of the epoch start ctx: &mut TxContext, ) : Balance<IOTA> { self.epoch_start_timestamp_ms = epoch_start_timestamp_ms;

let bps_denominator_u64 = BASIS_POINT_DENOMINATOR as u64; // Rates can't be higher than 100%. assert!(reward_slashing_rate <= bps_denominator_u64, EBpsTooLarge);

// Accumulate the gas summary during safe_mode before processing any rewards: let safe_mode_storage_charges = self.safe_mode_storage_charges.withdraw_all(); storage_charge.join(safe_mode_storage_charges); let safe_mode_computation_rewards = self.safe_mode_computation_rewards.withdraw_all(); computation_reward.join(safe_mode_computation_rewards); storage_rebate_amount = storage_rebate_amount + self.safe_mode_storage_rebates; self.safe_mode_storage_rebates = 0; non_refundable_storage_fee_amount = non_refundable_storage_fee_amount + self.safe_mode_non_refundable_storage_fee; self.safe_mode_non_refundable_storage_fee = 0;

let storage_charge_value = storage_charge.value(); let computation_charge = computation_reward.value();

// Mints or burns tokens depending on the target reward. // Since not all rewards are distributed in case of slashed validators, // tokens might be minted here and burnt in the same epoch change. let (mut total_validator_rewards, minted_tokens_amount, mut burnt_tokens_amount) = match_computation_reward_to_target_reward( validator_target_reward, computation_reward, &mut self.iota_treasury_cap, ctx );

self.epoch = self.epoch + 1; // Sanity check to make sure we are advancing to the right epoch. assert!(new_epoch == self.epoch, EAdvancedToWrongEpoch);

let total_validator_rewards_amount_before_distribution = total_validator_rewards.value();

self.validators.advance_epoch( &mut total_validator_rewards, &mut self.validator_report_records, reward_slashing_rate, self.parameters.validator_low_stake_threshold, self.parameters.validator_very_low_stake_threshold, self.parameters.validator_low_stake_grace_period, ctx, );

let new_total_stake = self.validators.total_stake();

let remaining_validator_rewards_amount_after_distribution = total_validator_rewards.value(); let total_stake_rewards_distributed = total_validator_rewards_amount_before_distribution - remaining_validator_rewards_amount_after_distribution;

self.protocol_version = next_protocol_version;

// Derive the reference gas price for the new epoch self.reference_gas_price = self.validators.derive_reference_gas_price(); // Because of precision issues with integer divisions, we expect that there will be some // remaining balance in total_validator_rewards. let leftover_staking_rewards = total_validator_rewards; // Burn any remaining leftover rewards. burnt_tokens_amount = burnt_tokens_amount + leftover_staking_rewards.value(); self.iota_treasury_cap.burn_balance(leftover_staking_rewards, ctx);

let refunded_storage_rebate = self.storage_fund.advance_epoch( storage_charge, storage_rebate_amount, non_refundable_storage_fee_amount, );

event::emit( SystemEpochInfoEventV1 { epoch: self.epoch, protocol_version: self.protocol_version, reference_gas_price: self.reference_gas_price, total_stake: new_total_stake, storage_charge: storage_charge_value, storage_rebate: storage_rebate_amount, storage_fund_balance: self.storage_fund.total_balance(), total_gas_fees: computation_charge, total_stake_rewards_distributed, burnt_tokens_amount, minted_tokens_amount, } ); self.safe_mode = false; // Double check that the gas from safe mode has been processed. assert!(self.safe_mode_storage_rebates == 0 && self.safe_mode_storage_charges.value() == 0 && self.safe_mode_computation_rewards.value() == 0, ESafeModeGasNotProcessed);

// Return the storage rebate split from storage fund that's already refunded to the transaction senders. // This will be burnt at the last step of epoch change programmable transaction. refunded_storage_rebate }

Function match_computation_reward_to_target_reward

Mint or burn IOTA tokens depending on the given target reward per validator and the amount of computation fees burned in this epoch.

fun match_computation_reward_to_target_reward(validator_target_reward: u64, computation_charges: balance::Balance<iota::IOTA>, iota_treasury_cap: &mut iota::IotaTreasuryCap, ctx: &tx_context::TxContext): (balance::Balance<iota::IOTA>, u64, u64)

Implementation

fun match_computation_reward_to_target_reward( validator_target_reward: u64, mut computation_charges: Balance<IOTA>, iota_treasury_cap: &mut iota::iota::IotaTreasuryCap, ctx: &TxContext, ): (Balance<IOTA>, u64, u64) { let burnt_tokens_amount = computation_charges.value(); let minted_tokens_amount = validator_target_reward; if (burnt_tokens_amount < minted_tokens_amount) { let actual_amount_to_mint = minted_tokens_amount - burnt_tokens_amount; let balance_to_mint = iota_treasury_cap.mint_balance(actual_amount_to_mint, ctx); computation_charges.join(balance_to_mint); } else if (burnt_tokens_amount > minted_tokens_amount) { let actual_amount_to_burn = burnt_tokens_amount - minted_tokens_amount; let balance_to_burn = computation_charges.split(actual_amount_to_burn); iota_treasury_cap.burn_balance(balance_to_burn, ctx); }; (computation_charges, minted_tokens_amount, burnt_tokens_amount) }

Function epoch

Return the current epoch number. Useful for applications that need a coarse-grained concept of time, since epochs are ever-increasing and epoch changes are intended to happen every 24 hours.

public(friend) fun epoch(self: &iota_system_state_inner::IotaSystemStateV1): u64

Implementation

public(package) fun epoch(self: &IotaSystemStateV1): u64 { self.epoch }

Function protocol_version

public(friend) fun protocol_version(self: &iota_system_state_inner::IotaSystemStateV1): u64

Implementation

public(package) fun protocol_version(self: &IotaSystemStateV1): u64 { self.protocol_version }

Function system_state_version

public(friend) fun system_state_version(self: &iota_system_state_inner::IotaSystemStateV1): u64

Implementation

public(package) fun system_state_version(self: &IotaSystemStateV1): u64 { self.system_state_version }

Function iota_system_admin_cap

public(friend) fun iota_system_admin_cap(self: &iota_system_state_inner::IotaSystemStateV1): &system_admin_cap::IotaSystemAdminCap

Implementation

public(package) fun iota_system_admin_cap(self: &IotaSystemStateV1): &IotaSystemAdminCap { &self.iota_system_admin_cap }

Function genesis_system_state_version

This function always return the genesis system state version, which is used to create the system state in genesis. It should never change for a given network.

public(friend) fun genesis_system_state_version(): u64

Implementation

Function epoch_start_timestamp_ms

Returns unix timestamp of the start of current epoch

public(friend) fun epoch_start_timestamp_ms(self: &iota_system_state_inner::IotaSystemStateV1): u64

Implementation

public(package) fun epoch_start_timestamp_ms(self: &IotaSystemStateV1): u64 { self.epoch_start_timestamp_ms }

Function validator_stake_amount

Returns the total amount staked with validator_addr. Aborts if validator_addr is not an active validator.

public(friend) fun validator_stake_amount(self: &iota_system_state_inner::IotaSystemStateV1, validator_addr: address): u64

Implementation

public(package) fun validator_stake_amount(self: &IotaSystemStateV1, validator_addr: address): u64 { self.validators.validator_total_stake_amount(validator_addr) }

Function active_validator_voting_powers

Returns the voting power for validator_addr. Aborts if validator_addr is not an active validator.

public(friend) fun active_validator_voting_powers(self: &iota_system_state_inner::IotaSystemStateV1): vec_map::VecMap<address, u64>

Implementation

public(package) fun active_validator_voting_powers(self: &IotaSystemStateV1): VecMap<address, u64> { let mut active_validators = active_validator_addresses(self); let mut voting_powers = vec_map::empty(); while (!vector::is_empty(&active_validators)) { let validator = vector::pop_back(&mut active_validators); let voting_power = validator_set::validator_voting_power(&self.validators, validator); vec_map::insert(&mut voting_powers, validator, voting_power); }; voting_powers }

Function validator_staking_pool_id

Returns the staking pool id of a given validator. Aborts if validator_addr is not an active validator.

public(friend) fun validator_staking_pool_id(self: &iota_system_state_inner::IotaSystemStateV1, validator_addr: address): object::ID

Implementation

public(package) fun validator_staking_pool_id(self: &IotaSystemStateV1, validator_addr: address): ID {

self.validators.validator_staking_pool_id(validator_addr) }

Function validator_staking_pool_mappings

Returns reference to the staking pool mappings that map pool ids to active validator addresses

public(friend) fun validator_staking_pool_mappings(self: &iota_system_state_inner::IotaSystemStateV1): &table::Table<object::ID, address>

Implementation

public(package) fun validator_staking_pool_mappings(self: &IotaSystemStateV1): &Table<ID, address> {

self.validators.staking_pool_mappings() }

Function get_total_iota_supply

Returns the total iota supply.

public(friend) fun get_total_iota_supply(self: &iota_system_state_inner::IotaSystemStateV1): u64

Implementation

public(package) fun get_total_iota_supply(self: &IotaSystemStateV1): u64 { self.iota_treasury_cap.total_supply() }

Function get_reporters_of

Returns all the validators who are currently reporting addr

public(friend) fun get_reporters_of(self: &iota_system_state_inner::IotaSystemStateV1, addr: address): vec_set::VecSet<address>

Implementation

public(package) fun get_reporters_of(self: &IotaSystemStateV1, addr: address): VecSet<address> {

if (self.validator_report_records.contains(&addr)) { self.validator_report_records[&addr] } else { vec_set::empty() } }

Function get_storage_fund_total_balance

public(friend) fun get_storage_fund_total_balance(self: &iota_system_state_inner::IotaSystemStateV1): u64

Implementation

public(package) fun get_storage_fund_total_balance(self: &IotaSystemStateV1): u64 { self.storage_fund.total_balance() }

Function get_storage_fund_object_rebates

public(friend) fun get_storage_fund_object_rebates(self: &iota_system_state_inner::IotaSystemStateV1): u64

Implementation

public(package) fun get_storage_fund_object_rebates(self: &IotaSystemStateV1): u64 { self.storage_fund.total_object_storage_rebates() }

Function pool_exchange_rates

public(friend) fun pool_exchange_rates(self: &mut iota_system_state_inner::IotaSystemStateV1, pool_id: &object::ID): &table::Table<u64, staking_pool::PoolTokenExchangeRate>

Implementation

public(package) fun pool_exchange_rates( self: &mut IotaSystemStateV1, pool_id: &ID ): &Table<u64, PoolTokenExchangeRate> { let validators = &mut self.validators; validators.pool_exchange_rates(pool_id) }

Function active_validator_addresses

public(friend) fun active_validator_addresses(self: &iota_system_state_inner::IotaSystemStateV1): vector<address>

Implementation

public(package) fun active_validator_addresses(self: &IotaSystemStateV1): vector<address> { let validator_set = &self.validators; validator_set.active_validator_addresses() }

Function extract_coin_balance

Extract required Balance from vector of Coin<IOTA>, transfer the remainder back to sender.

fun extract_coin_balance(coins: vector<coin::Coin<iota::IOTA>>, amount: option::Option<u64>, ctx: &mut tx_context::TxContext): balance::Balance<iota::IOTA>

Implementation

fun extract_coin_balance(mut coins: vector<Coin<IOTA>>, amount: option::Option<u64>, ctx: &mut TxContext): Balance<IOTA> { let mut merged_coin = coins.pop_back(); merged_coin.join_vec(coins);

let mut total_balance = merged_coin.into_balance(); // return the full amount if amount is not specified if (amount.is_some()) { let amount = amount.destroy_some(); let balance = total_balance.split(amount); // transfer back the remainder if non zero. if (total_balance.value() > 0) { transfer::public_transfer(total_balance.into_coin(ctx), ctx.sender()); } else { total_balance.destroy_zero(); }; balance } else { total_balance } }