Module 0x3::validator_set
- Struct
ValidatorSet
- Struct
ValidatorEpochInfoEvent
- Struct
ValidatorEpochInfoEventV2
- Struct
ValidatorJoinEvent
- Struct
ValidatorLeaveEvent
- Constants
- Function
new
- Function
request_add_validator_candidate
- Function
request_remove_validator_candidate
- Function
request_add_validator
- Function
assert_no_pending_or_active_duplicates
- Function
request_remove_validator
- Function
request_add_stake
- Function
request_withdraw_stake
- Function
request_set_commission_rate
- Function
advance_epoch
- Function
update_and_process_low_stake_departures
- Function
effectuate_staged_metadata
- Function
derive_reference_gas_price
- Function
total_stake
- Function
validator_total_stake_amount
- Function
validator_stake_amount
- Function
validator_voting_power
- Function
validator_staking_pool_id
- Function
staking_pool_mappings
- Function
pool_exchange_rates
- Function
next_epoch_validator_count
- Function
is_active_validator_by_sui_address
- Function
is_duplicate_with_active_validator
- Function
is_duplicate_validator
- Function
count_duplicates_vec
- Function
is_duplicate_with_pending_validator
- Function
count_duplicates_tablevec
- Function
get_candidate_or_active_validator_mut
- Function
find_validator
- Function
find_validator_from_table_vec
- Function
get_validator_indices
- Function
get_validator_mut
- Function
get_active_or_pending_or_candidate_validator_mut
- Function
get_validator_mut_with_verified_cap
- Function
get_validator_mut_with_ctx
- Function
get_validator_mut_with_ctx_including_candidates
- Function
get_validator_ref
- Function
get_active_or_pending_or_candidate_validator_ref
- Function
get_active_validator_ref
- Function
get_pending_validator_ref
- Function
verify_cap
- Function
process_pending_removals
- Function
process_validator_departure
- Function
clean_report_records_leaving_validator
- Function
process_pending_validators
- Function
sort_removal_list
- Function
process_pending_stakes_and_withdraws
- Function
calculate_total_stakes
- Function
adjust_stake_and_gas_price
- Function
compute_reward_adjustments
- Function
compute_slashed_validators
- Function
compute_unadjusted_reward_distribution
- Function
compute_adjusted_reward_distribution
- Function
distribute_reward
- Function
emit_validator_epoch_events
- Function
sum_voting_power_by_addresses
- Function
active_validators
- Function
is_validator_candidate
- Function
is_inactive_validator
- Function
active_validator_addresses
use 0x1::option;
use 0x1::vector;
use 0x2::bag;
use 0x2::balance;
use 0x2::event;
use 0x2::object;
use 0x2::priority_queue;
use 0x2::sui;
use 0x2::table;
use 0x2::table_vec;
use 0x2::transfer;
use 0x2::tx_context;
use 0x2::vec_map;
use 0x2::vec_set;
use 0x3::staking_pool;
use 0x3::validator;
use 0x3::validator_cap;
use 0x3::validator_wrapper;
use 0x3::voting_power;
Struct ValidatorSet
struct ValidatorSet has store
Fields
- total_stake: u64
- Total amount of stake from all active validators at the beginning of the epoch.
- active_validators: vector<validator::Validator>
- The current list of active validators.
- pending_active_validators: table_vec::TableVec<validator::Validator>
- List of new validator candidates added during the current epoch. They will be processed at the end of the epoch.
- pending_removals: vector<u64>
- Removal requests from the validators. Each element is an index pointing to active_validators.
- staking_pool_mappings: table::Table<object::ID, address>
- Mappings from staking pool's ID to the sui address of a validator.
- inactive_validators: table::Table<object::ID, validator_wrapper::ValidatorWrapper>
- Mapping from a staking pool ID to the inactive validator that has that pool as its staking pool. When a validator is deactivated the validator is removed from active_validators it is added to this table so that stakers can continue to withdraw their stake from it.
- validator_candidates: table::Table<address, validator_wrapper::ValidatorWrapper>
- Table storing preactive/candidate validators, mapping their addresses to their Validator structs. When an address calls request_add_validator_candidate, they get added to this table and become a preactive validator. When the candidate has met the min stake requirement, they can call request_add_validator to officially add them to the active validator set active_validators next epoch.
- at_risk_validators: vec_map::VecMap<address, u64>
- Table storing the number of epochs during which a validator's stake has been below the low stake threshold.
- extra_fields: bag::Bag
- Any extra fields that's not defined statically.
Struct ValidatorEpochInfoEvent
Event containing staking and rewards related information of each validator, emitted during epoch advancement.
struct ValidatorEpochInfoEvent has copy, drop
Fields
Struct ValidatorEpochInfoEventV2
V2 of ValidatorEpochInfoEvent containing more information about the validator.
struct ValidatorEpochInfoEventV2 has copy, drop
Fields
- epoch: u64
- validator_address: address
- reference_gas_survey_quote: u64
- stake: u64
- voting_power: u64
- commission_rate: u64
- pool_staking_reward: u64
- storage_fund_staking_reward: u64
- pool_token_exchange_rate: staking_pool::PoolTokenExchangeRate
- tallying_rule_reporters: vector<address>
- tallying_rule_global_score: u64
Struct ValidatorJoinEvent
Event emitted every time a new validator joins the committee. The epoch value corresponds to the first epoch this change takes place.
struct ValidatorJoinEvent has copy, drop
Fields
- epoch: u64
- validator_address: address
- staking_pool_id: object::ID
Struct ValidatorLeaveEvent
Event emitted every time a validator leaves the committee. The epoch value corresponds to the first epoch this change takes place.
struct ValidatorLeaveEvent has copy, drop
Fields
- epoch: u64
- validator_address: address
- staking_pool_id: object::ID
- is_voluntary: bool
Constants
const MIN_STAKING_THRESHOLD: u64 = 1000000000;
const EInvalidCap: u64 = 101;
const ENotValidatorCandidate: u64 = 8;
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 EAlreadyValidatorCandidate: u64 = 6;
const EDuplicateValidator: u64 = 2;
const EInvalidStakeAdjustmentAmount: u64 = 1;
const EMinJoiningStakeNotReached: u64 = 5;
const ENoPoolFound: u64 = 3;
const ENonValidatorInReportRecords: u64 = 0;
const ENotAPendingValidator: u64 = 12;
const ENotAValidator: u64 = 4;
const ENotActiveOrPendingValidator: u64 = 9;
const EStakingBelowThreshold: u64 = 10;
const EValidatorAlreadyRemoved: u64 = 11;
const EValidatorNotCandidate: u64 = 7;
const EValidatorSetEmpty: u64 = 13;
Function new
public(friend) fun new(init_active_validators: vector<validator::Validator>, ctx: &mut tx_context::TxContext): validator_set::ValidatorSet
Implementation
public(package) fun new(init_active_validators: vector<Validator>, ctx: &mut TxContext): ValidatorSet {
let total_stake = calculate_total_stakes(&init_active_validators);
let mut staking_pool_mappings = table::new(ctx);
let num_validators = init_active_validators.length();
let mut i = 0;
while (i < num_validators) {
let validator = &init_active_validators[i];
staking_pool_mappings.add(staking_pool_id(validator), sui_address(validator));
i = i + 1;
};
let mut validators = ValidatorSet {
total_stake,
active_validators: init_active_validators,
pending_active_validators: table_vec::empty(ctx),
pending_removals: vector[],
staking_pool_mappings,
inactive_validators: table::new(ctx),
validator_candidates: table::new(ctx),
at_risk_validators: vec_map::empty(),
extra_fields: bag::new(ctx),
};
voting_power::set_voting_power(&mut validators.active_validators);
validators
}
Function request_add_validator_candidate
Called by sui_system to add a new validator candidate.
public(friend) fun request_add_validator_candidate(self: &mut validator_set::ValidatorSet, validator: validator::Validator, ctx: &mut tx_context::TxContext)
Implementation
public(package) fun request_add_validator_candidate(
self: &mut ValidatorSet,
validator: Validator,
ctx: &mut TxContext,
) {
// The next assertions are not critical for the protocol, but they are here to catch problematic configs earlier.
assert!(
!is_duplicate_with_active_validator(self, &validator)
&& !is_duplicate_with_pending_validator(self, &validator),
EDuplicateValidator
);
let validator_address = sui_address(&validator);
assert!(
!self.validator_candidates.contains(validator_address),
EAlreadyValidatorCandidate
);
assert!(validator.is_preactive(), EValidatorNotCandidate);
// Add validator to the candidates mapping and the pool id mappings so that users can start
// staking with this candidate.
self.staking_pool_mappings.add(staking_pool_id(&validator), validator_address);
self.validator_candidates.add(
sui_address(&validator),
validator_wrapper::create_v1(validator, ctx),
);
}
Function request_remove_validator_candidate
Called by sui_system to remove a validator candidate, and move them to inactive_validators.
public(friend) fun request_remove_validator_candidate(self: &mut validator_set::ValidatorSet, ctx: &mut tx_context::TxContext)
Implementation
public(package) fun request_remove_validator_candidate(self: &mut ValidatorSet, ctx: &mut TxContext) {
let validator_address = ctx.sender();
assert!(
self.validator_candidates.contains(validator_address),
ENotValidatorCandidate
);
let wrapper = self.validator_candidates.remove(validator_address);
let mut validator = wrapper.destroy();
assert!(validator.is_preactive(), EValidatorNotCandidate);
let staking_pool_id = staking_pool_id(&validator);
// Remove the validator's staking pool from mappings.
self.staking_pool_mappings.remove(staking_pool_id);
// Deactivate the staking pool.
validator.deactivate(ctx.epoch());
// Add to the inactive tables.
self.inactive_validators.add(
staking_pool_id,
validator_wrapper::create_v1(validator, ctx),
);
}
Function request_add_validator
Called by sui_system to add a new validator to pending_active_validators, which will be processed at the end of epoch.
public(friend) fun request_add_validator(self: &mut validator_set::ValidatorSet, min_joining_stake_amount: u64, ctx: &tx_context::TxContext)
Implementation
public(package) fun request_add_validator(self: &mut ValidatorSet, min_joining_stake_amount: u64, ctx: &TxContext) {
let validator_address = ctx.sender();
assert!(
self.validator_candidates.contains(validator_address),
ENotValidatorCandidate
);
let wrapper = self.validator_candidates.remove(validator_address);
let validator = wrapper.destroy();
assert!(
!is_duplicate_with_active_validator(self, &validator)
&& !is_duplicate_with_pending_validator(self, &validator),
EDuplicateValidator
);
assert!(validator.is_preactive(), EValidatorNotCandidate);
assert!(validator.total_stake_amount() >= min_joining_stake_amount, EMinJoiningStakeNotReached);
self.pending_active_validators.push_back(validator);
}
Function assert_no_pending_or_active_duplicates
public(friend) fun assert_no_pending_or_active_duplicates(self: &validator_set::ValidatorSet, validator: &validator::Validator)
Implementation
public(package) fun assert_no_pending_or_active_duplicates(self: &ValidatorSet, validator: &Validator) {
// Validator here must be active or pending, and thus must be identified as duplicate exactly once.
assert!(
count_duplicates_vec(&self.active_validators, validator) +
count_duplicates_tablevec(&self.pending_active_validators, validator) == 1,
EDuplicateValidator
);
}
Function request_remove_validator
Called by sui_system, to remove a validator. The index of the validator is added to pending_removals and will be processed at the end of epoch. Only an active validator can request to be removed.
public(friend) fun request_remove_validator(self: &mut validator_set::ValidatorSet, ctx: &tx_context::TxContext)
Implementation
public(package) fun request_remove_validator(
self: &mut ValidatorSet,
ctx: &TxContext,
) {
let validator_address = ctx.sender();
let mut validator_index_opt = find_validator(&self.active_validators, validator_address);
assert!(validator_index_opt.is_some(), ENotAValidator);
let validator_index = validator_index_opt.extract();
assert!(
!self.pending_removals.contains(&validator_index),
EValidatorAlreadyRemoved
);
self.pending_removals.push_back(validator_index);
}
Function request_add_stake
Called by sui_system, to add a new stake to the validator. This request is added to the validator's staking pool's pending stake entries, processed at the end of the epoch. Aborts in case the staking amount is smaller than MIN_STAKING_THRESHOLD
public(friend) fun request_add_stake(self: &mut validator_set::ValidatorSet, validator_address: address, stake: balance::Balance<sui::SUI>, ctx: &mut tx_context::TxContext): staking_pool::StakedSui
Implementation
public(package) fun request_add_stake(
self: &mut ValidatorSet,
validator_address: address,
stake: Balance<SUI>,
ctx: &mut TxContext,
) : StakedSui {
let sui_amount = stake.value();
assert!(sui_amount >= MIN_STAKING_THRESHOLD, EStakingBelowThreshold);
let validator = get_candidate_or_active_validator_mut(self, validator_address);
validator.request_add_stake(stake, ctx.sender(), ctx)
}