Skip to main content

Module 0x3::validator

use 0x1::ascii;
use 0x1::bcs;
use 0x1::option;
use 0x1::string;
use 0x2::bag;
use 0x2::balance;
use 0x2::event;
use 0x2::object;
use 0x2::sui;
use 0x2::transfer;
use 0x2::tx_context;
use 0x2::url;
use 0x3::staking_pool;
use 0x3::validator_cap;

Struct ValidatorMetadata

struct ValidatorMetadata has store
Fields
sui_address: address
The Sui Address of the validator. This is the sender that created the Validator object, and also the address to send validator/coins to during withdraws.
protocol_pubkey_bytes: vector<u8>
The public key bytes corresponding to the private key that the validator holds to sign transactions. For now, this is the same as AuthorityName.
network_pubkey_bytes: vector<u8>
The public key bytes corresponding to the private key that the validator uses to establish TLS connections
worker_pubkey_bytes: vector<u8>
The public key bytes correstponding to the Narwhal Worker
proof_of_possession: vector<u8>
This is a proof that the validator has ownership of the private key
name: string::String
A unique human-readable name of this validator.
description: string::String
image_url: url::Url
project_url: url::Url
net_address: string::String
The network address of the validator (could also contain extra info such as port, DNS and etc.).
p2p_address: string::String
The address of the validator used for p2p activities such as state sync (could also contain extra info such as port, DNS and etc.).
primary_address: string::String
The address of the narwhal primary
worker_address: string::String
The address of the narwhal worker
next_epoch_protocol_pubkey_bytes: option::Option<vector<u8>>
"next_epoch" metadata only takes effects in the next epoch. If none, current value will stay unchanged.
next_epoch_proof_of_possession: option::Option<vector<u8>>
next_epoch_network_pubkey_bytes: option::Option<vector<u8>>
next_epoch_worker_pubkey_bytes: option::Option<vector<u8>>
next_epoch_net_address: option::Option<string::String>
next_epoch_p2p_address: option::Option<string::String>
next_epoch_primary_address: option::Option<string::String>
next_epoch_worker_address: option::Option<string::String>
extra_fields: bag::Bag
Any extra fields that's not defined statically.

Struct Validator

struct Validator has store
Fields
metadata: validator::ValidatorMetadata
Summary of the validator.
voting_power: u64
The voting power of this validator, which might be different from its stake amount.
operation_cap_id: object::ID
The ID of this validator's current valid UnverifiedValidatorOperationCap
gas_price: u64
Gas price quote, updated only at end of epoch.
staking_pool: staking_pool::StakingPool
Staking pool for this validator.
commission_rate: u64
Commission rate of the validator, in basis point.
next_epoch_stake: u64
Total amount of stake that would be active in the next epoch.
next_epoch_gas_price: u64
This validator's gas price quote for the next epoch.
next_epoch_commission_rate: u64
The commission rate of the validator starting the next epoch, in basis point.
extra_fields: bag::Bag
Any extra fields that's not defined statically.

Struct StakingRequestEvent

Event emitted when a new stake request is received.

struct StakingRequestEvent has copy, drop
Fields
pool_id: object::ID
validator_address: address
staker_address: address
epoch: u64
amount: u64

Struct UnstakingRequestEvent

Event emitted when a new unstake request is received.

struct UnstakingRequestEvent has copy, drop
Fields
pool_id: object::ID
validator_address: address
staker_address: address
stake_activation_epoch: u64
unstaking_epoch: u64
principal_amount: u64
reward_amount: u64

Constants

Function called during non-genesis times.

const ECalledDuringNonGenesis: u64 = 12;

Commission rate set by the validator is higher than the threshold

const ECommissionRateTooHigh: u64 = 8;

Validator trying to set gas price higher than threshold.

const EGasPriceHigherThanThreshold: u64 = 102;

Capability code is not valid

const EInvalidCap: u64 = 101;

Invalid proof_of_possession field in ValidatorMetadata

const EInvalidProofOfPossession: u64 = 0;

Stake amount is invalid or wrong.

const EInvalidStakeAmount: u64 = 11;

Invalid net_address field in ValidatorMetadata

const EMetadataInvalidNetAddr: u64 = 4;

Invalid network_pubkey_bytes field in ValidatorMetadata

const EMetadataInvalidNetPubkey: u64 = 2;

Invalid p2p_address field in ValidatorMetadata

const EMetadataInvalidP2pAddr: u64 = 5;

Invalid primary_address field in ValidatorMetadata

const EMetadataInvalidPrimaryAddr: u64 = 6;

Invalid pubkey_bytes field in ValidatorMetadata

const EMetadataInvalidPubkey: u64 = 1;

Invalidworker_address field in ValidatorMetadata

const EMetadataInvalidWorkerAddr: u64 = 7;

Invalid worker_pubkey_bytes field in ValidatorMetadata

const EMetadataInvalidWorkerPubkey: u64 = 3;

New Capability is not created by the validator itself

const ENewCapNotCreatedByValidatorItself: u64 = 100;

Intended validator is not a candidate one.

const ENotValidatorCandidate: u64 = 10;

Validator Metadata is too long

const EValidatorMetadataExceedingLengthLimit: u64 = 9;

const MAX_COMMISSION_RATE: u64 = 2000;

Max gas price a validator can set is 100K MIST.

const MAX_VALIDATOR_GAS_PRICE: u64 = 100000;

const MAX_VALIDATOR_METADATA_LENGTH: u64 = 256;

Function new_metadata

public(friend) fun new_metadata(sui_address: address, protocol_pubkey_bytes: vector<u8>, network_pubkey_bytes: vector<u8>, worker_pubkey_bytes: vector<u8>, proof_of_possession: vector<u8>, name: string::String, description: string::String, image_url: url::Url, project_url: url::Url, net_address: string::String, p2p_address: string::String, primary_address: string::String, worker_address: string::String, extra_fields: bag::Bag): validator::ValidatorMetadata
Implementation
public(package) fun new_metadata(
    sui_address: address,
    protocol_pubkey_bytes: vector<u8>,
    network_pubkey_bytes: vector<u8>,
    worker_pubkey_bytes: vector<u8>,
    proof_of_possession: vector<u8>,
    name: String,
    description: String,
    image_url: Url,
    project_url: Url,
    net_address: String,
    p2p_address: String,
    primary_address: String,
    worker_address: String,
    extra_fields: Bag,
): ValidatorMetadata {
    let metadata = ValidatorMetadata {
        sui_address,
        protocol_pubkey_bytes,
        network_pubkey_bytes,
        worker_pubkey_bytes,
        proof_of_possession,
        name,
        description,
        image_url,
        project_url,
        net_address,
        p2p_address,
        primary_address,
        worker_address,
        next_epoch_protocol_pubkey_bytes: option::none(),
        next_epoch_network_pubkey_bytes: option::none(),
        next_epoch_worker_pubkey_bytes: option::none(),
        next_epoch_proof_of_possession: option::none(),
        next_epoch_net_address: option::none(),
        next_epoch_p2p_address: option::none(),
        next_epoch_primary_address: option::none(),
        next_epoch_worker_address: option::none(),
        extra_fields,
    };
    metadata
}

Function new

public(friend) fun new(sui_address: address, protocol_pubkey_bytes: vector<u8>, network_pubkey_bytes: vector<u8>, worker_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>, worker_address: vector<u8>, gas_price: u64, commission_rate: u64, ctx: &mut tx_context::TxContext): validator::Validator
Implementation
public(package) fun new(
    sui_address: address,
    protocol_pubkey_bytes: vector<u8>,
    network_pubkey_bytes: vector<u8>,
    worker_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>,
    worker_address: vector<u8>,
    gas_price: u64,
    commission_rate: u64,
    ctx: &mut TxContext
): Validator {
    assert!(
        net_address.length() <= MAX_VALIDATOR_METADATA_LENGTH
            && p2p_address.length() <= MAX_VALIDATOR_METADATA_LENGTH
            && primary_address.length() <= MAX_VALIDATOR_METADATA_LENGTH
            && worker_address.length() <= MAX_VALIDATOR_METADATA_LENGTH
            && name.length() <= MAX_VALIDATOR_METADATA_LENGTH
            && description.length() <= MAX_VALIDATOR_METADATA_LENGTH
            && image_url.length() <= MAX_VALIDATOR_METADATA_LENGTH
            && project_url.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    assert!(commission_rate <= MAX_COMMISSION_RATE, ECommissionRateTooHigh);
    assert!(gas_price < MAX_VALIDATOR_GAS_PRICE, EGasPriceHigherThanThreshold);

    let metadata = new_metadata(
        sui_address,
        protocol_pubkey_bytes,
        network_pubkey_bytes,
        worker_pubkey_bytes,
        proof_of_possession,
        name.to_ascii_string().to_string(),
        description.to_ascii_string().to_string(),
        url::new_unsafe_from_bytes(image_url),
        url::new_unsafe_from_bytes(project_url),
        net_address.to_ascii_string().to_string(),
        p2p_address.to_ascii_string().to_string(),
        primary_address.to_ascii_string().to_string(),
        worker_address.to_ascii_string().to_string(),
        bag::new(ctx),
    );

    // Checks that the keys & addresses & PoP are valid.
    validate_metadata(&metadata);

    new_from_metadata(
        metadata,
        gas_price,
        commission_rate,
        ctx
    )
}

Function deactivate

Deactivate this validator's staking pool

public(friend) fun deactivate(self: &mut validator::Validator, deactivation_epoch: u64)
Implementation
public(package) fun deactivate(self: &mut Validator, deactivation_epoch: u64) {
    self.staking_pool.deactivate_staking_pool(deactivation_epoch)
}

Function activate

public(friend) fun activate(self: &mut validator::Validator, activation_epoch: u64)
Implementation
public(package) fun activate(self: &mut Validator, activation_epoch: u64) {
    self.staking_pool.activate_staking_pool(activation_epoch);
}

Function adjust_stake_and_gas_price

Process pending stake and pending withdraws, and update the gas price.

public(friend) fun adjust_stake_and_gas_price(self: &mut validator::Validator)
Implementation
public(package) fun adjust_stake_and_gas_price(self: &mut Validator) {
    self.gas_price = self.next_epoch_gas_price;
    self.commission_rate = self.next_epoch_commission_rate;
}

Function request_add_stake

Request to add stake to the validator's staking pool, processed at the end of the epoch.

public(friend) fun request_add_stake(self: &mut validator::Validator, stake: balance::Balance<sui::SUI>, staker_address: address, ctx: &mut tx_context::TxContext): staking_pool::StakedSui
Implementation
public(package) fun request_add_stake(
    self: &mut Validator,
    stake: Balance<SUI>,
    staker_address: address,
    ctx: &mut TxContext,
) : StakedSui {
    let stake_amount = stake.value();
    assert!(stake_amount > 0, EInvalidStakeAmount);
    let stake_epoch = ctx.epoch() + 1;
    let staked_sui = self.staking_pool.request_add_stake(stake, stake_epoch, ctx);
    // Process stake right away if staking pool is preactive.
    if (self.staking_pool.is_preactive()) {
        self.staking_pool.process_pending_stake();
    };
    self.next_epoch_stake = self.next_epoch_stake + stake_amount;
    event::emit(
        StakingRequestEvent {
            pool_id: staking_pool_id(self),
            validator_address: self.metadata.sui_address,
            staker_address,
            epoch: ctx.epoch(),
            amount: stake_amount,
        }
    );
    staked_sui
}

Function request_add_stake_at_genesis

Request to add stake to the validator's staking pool at genesis

public(friend) fun request_add_stake_at_genesis(self: &mut validator::Validator, stake: balance::Balance<sui::SUI>, staker_address: address, ctx: &mut tx_context::TxContext)
Implementation
public(package) fun request_add_stake_at_genesis(
    self: &mut Validator,
    stake: Balance<SUI>,
    staker_address: address,
    ctx: &mut TxContext,
) {
    assert!(ctx.epoch() == 0, ECalledDuringNonGenesis);
    let stake_amount = stake.value();
    assert!(stake_amount > 0, EInvalidStakeAmount);

    let staked_sui = self.staking_pool.request_add_stake(
        stake,
        0, // epoch 0 -- genesis
        ctx
    );

    transfer::public_transfer(staked_sui, staker_address);

    // Process stake right away
    self.staking_pool.process_pending_stake();
    self.next_epoch_stake = self.next_epoch_stake + stake_amount;
}

Function request_withdraw_stake

Request to withdraw stake from the validator's staking pool, processed at the end of the epoch.

public(friend) fun request_withdraw_stake(self: &mut validator::Validator, staked_sui: staking_pool::StakedSui, ctx: &tx_context::TxContext): balance::Balance<sui::SUI>
Implementation
public(package) fun request_withdraw_stake(
    self: &mut Validator,
    staked_sui: StakedSui,
    ctx: &TxContext,
) : Balance<SUI> {
    let principal_amount = staked_sui.staked_sui_amount();
    let stake_activation_epoch = staked_sui.stake_activation_epoch();
    let withdrawn_stake = self.staking_pool.request_withdraw_stake(staked_sui, ctx);
    let withdraw_amount = withdrawn_stake.value();
    let reward_amount = withdraw_amount - principal_amount;
    self.next_epoch_stake = self.next_epoch_stake - withdraw_amount;
    event::emit(
        UnstakingRequestEvent {
            pool_id: staking_pool_id(self),
            validator_address: self.metadata.sui_address,
            staker_address: ctx.sender(),
            stake_activation_epoch,
            unstaking_epoch: ctx.epoch(),
            principal_amount,
            reward_amount,
        }
    );
    withdrawn_stake
}

Function request_set_gas_price

Request to set new gas price for the next epoch. Need to present a ValidatorOperationCap.

public(friend) fun request_set_gas_price(self: &mut validator::Validator, verified_cap: validator_cap::ValidatorOperationCap, new_price: u64)
Implementation
public(package) fun request_set_gas_price(
    self: &mut Validator,
    verified_cap: ValidatorOperationCap,
    new_price: u64,
) {
    assert!(new_price < MAX_VALIDATOR_GAS_PRICE, EGasPriceHigherThanThreshold);
    let validator_address = *verified_cap.verified_operation_cap_address();
    assert!(validator_address == self.metadata.sui_address, EInvalidCap);
    self.next_epoch_gas_price = new_price;
}

Function set_candidate_gas_price

Set new gas price for the candidate validator.

public(friend) fun set_candidate_gas_price(self: &mut validator::Validator, verified_cap: validator_cap::ValidatorOperationCap, new_price: u64)
Implementation
public(package) fun set_candidate_gas_price(
    self: &mut Validator,
    verified_cap: ValidatorOperationCap,
    new_price: u64
) {
    assert!(is_preactive(self), ENotValidatorCandidate);
    assert!(new_price < MAX_VALIDATOR_GAS_PRICE, EGasPriceHigherThanThreshold);
    let validator_address = *verified_cap.verified_operation_cap_address();
    assert!(validator_address == self.metadata.sui_address, EInvalidCap);
    self.next_epoch_gas_price = new_price;
    self.gas_price = new_price;
}

Function request_set_commission_rate

Request to set new commission rate for the next epoch.

public(friend) fun request_set_commission_rate(self: &mut validator::Validator, new_commission_rate: u64)
Implementation
public(package) fun request_set_commission_rate(self: &mut Validator, new_commission_rate: u64) {
    assert!(new_commission_rate <= MAX_COMMISSION_RATE, ECommissionRateTooHigh);
    self.next_epoch_commission_rate = new_commission_rate;
}

Function set_candidate_commission_rate

Set new commission rate for the candidate validator.

public(friend) fun set_candidate_commission_rate(self: &mut validator::Validator, new_commission_rate: u64)
Implementation
public(package) fun set_candidate_commission_rate(self: &mut Validator, new_commission_rate: u64) {
    assert!(is_preactive(self), ENotValidatorCandidate);
    assert!(new_commission_rate <= MAX_COMMISSION_RATE, ECommissionRateTooHigh);
    self.commission_rate = new_commission_rate;
}

Function deposit_stake_rewards

Deposit stakes rewards into the validator's staking pool, called at the end of the epoch.

public(friend) fun deposit_stake_rewards(self: &mut validator::Validator, reward: balance::Balance<sui::SUI>)
Implementation
public(package) fun deposit_stake_rewards(self: &mut Validator, reward: Balance<SUI>) {
    self.next_epoch_stake = self.next_epoch_stake + reward.value();
    self.staking_pool.deposit_rewards(reward);
}

Function process_pending_stakes_and_withdraws

Process pending stakes and withdraws, called at the end of the epoch.

public(friend) fun process_pending_stakes_and_withdraws(self: &mut validator::Validator, ctx: &tx_context::TxContext)
Implementation
public(package) fun process_pending_stakes_and_withdraws(self: &mut Validator, ctx: &TxContext) {
    self.staking_pool.process_pending_stakes_and_withdraws(ctx);
    assert!(stake_amount(self) == self.next_epoch_stake, EInvalidStakeAmount);
}

Function is_preactive

Returns true if the validator is preactive.

public fun is_preactive(self: &validator::Validator): bool
Implementation
public fun is_preactive(self: &Validator): bool {
    self.staking_pool.is_preactive()
}

Function metadata

public fun metadata(self: &validator::Validator): &validator::ValidatorMetadata
Implementation
public fun metadata(self: &Validator): &ValidatorMetadata {
    &self.metadata
}

Function sui_address

public fun sui_address(self: &validator::Validator): address
Implementation
public fun sui_address(self: &Validator): address {
    self.metadata.sui_address
}

Function name

public fun name(self: &validator::Validator): &string::String
Implementation
public fun name(self: &Validator): &String {
    &self.metadata.name
}

Function description

public fun description(self: &validator::Validator): &string::String
Implementation
public fun description(self: &Validator): &String {
    &self.metadata.description
}

Function image_url

public fun image_url(self: &validator::Validator): &url::Url
Implementation
public fun image_url(self: &Validator): &Url {
    &self.metadata.image_url
}

Function project_url

public fun project_url(self: &validator::Validator): &url::Url
Implementation
public fun project_url(self: &Validator): &Url {
    &self.metadata.project_url
}

Function network_address

public fun network_address(self: &validator::Validator): &string::String
Implementation
public fun network_address(self: &Validator): &String {
    &self.metadata.net_address
}

Function p2p_address

public fun p2p_address(self: &validator::Validator): &string::String
Implementation
public fun p2p_address(self: &Validator): &String {
    &self.metadata.p2p_address
}

Function primary_address

public fun primary_address(self: &validator::Validator): &string::String
Implementation
public fun primary_address(self: &Validator): &String {
    &self.metadata.primary_address
}

Function worker_address

public fun worker_address(self: &validator::Validator): &string::String
Implementation
public fun worker_address(self: &Validator): &String {
    &self.metadata.worker_address
}

Function protocol_pubkey_bytes

public fun protocol_pubkey_bytes(self: &validator::Validator): &vector<u8>
Implementation
public fun protocol_pubkey_bytes(self: &Validator): &vector<u8> {
    &self.metadata.protocol_pubkey_bytes
}

Function proof_of_possession

public fun proof_of_possession(self: &validator::Validator): &vector<u8>
Implementation
public fun proof_of_possession(self: &Validator): &vector<u8> {
    &self.metadata.proof_of_possession
}

Function network_pubkey_bytes

public fun network_pubkey_bytes(self: &validator::Validator): &vector<u8>
Implementation
public fun network_pubkey_bytes(self: &Validator): &vector<u8> {
    &self.metadata.network_pubkey_bytes
}

Function worker_pubkey_bytes

public fun worker_pubkey_bytes(self: &validator::Validator): &vector<u8>
Implementation
public fun worker_pubkey_bytes(self: &Validator): &vector<u8> {
    &self.metadata.worker_pubkey_bytes
}

Function next_epoch_network_address

public fun next_epoch_network_address(self: &validator::Validator): &option::Option<string::String>
Implementation
public fun next_epoch_network_address(self: &Validator): &Option<String> {
    &self.metadata.next_epoch_net_address
}

Function next_epoch_p2p_address

public fun next_epoch_p2p_address(self: &validator::Validator): &option::Option<string::String>
Implementation
public fun next_epoch_p2p_address(self: &Validator): &Option<String> {
    &self.metadata.next_epoch_p2p_address
}

Function next_epoch_primary_address

public fun next_epoch_primary_address(self: &validator::Validator): &option::Option<string::String>
Implementation
public fun next_epoch_primary_address(self: &Validator): &Option<String> {
    &self.metadata.next_epoch_primary_address
}

Function next_epoch_worker_address

public fun next_epoch_worker_address(self: &validator::Validator): &option::Option<string::String>
Implementation
public fun next_epoch_worker_address(self: &Validator): &Option<String> {
    &self.metadata.next_epoch_worker_address
}

Function next_epoch_protocol_pubkey_bytes

public fun next_epoch_protocol_pubkey_bytes(self: &validator::Validator): &option::Option<vector<u8>>
Implementation
public fun next_epoch_protocol_pubkey_bytes(self: &Validator): &Option<vector<u8>> {
    &self.metadata.next_epoch_protocol_pubkey_bytes
}

Function next_epoch_proof_of_possession

public fun next_epoch_proof_of_possession(self: &validator::Validator): &option::Option<vector<u8>>
Implementation
public fun next_epoch_proof_of_possession(self: &Validator): &Option<vector<u8>> {
    &self.metadata.next_epoch_proof_of_possession
}

Function next_epoch_network_pubkey_bytes

public fun next_epoch_network_pubkey_bytes(self: &validator::Validator): &option::Option<vector<u8>>
Implementation
public fun next_epoch_network_pubkey_bytes(self: &Validator): &Option<vector<u8>> {
    &self.metadata.next_epoch_network_pubkey_bytes
}

Function next_epoch_worker_pubkey_bytes

public fun next_epoch_worker_pubkey_bytes(self: &validator::Validator): &option::Option<vector<u8>>
Implementation
public fun next_epoch_worker_pubkey_bytes(self: &Validator): &Option<vector<u8>> {
    &self.metadata.next_epoch_worker_pubkey_bytes
}

Function operation_cap_id

public fun operation_cap_id(self: &validator::Validator): &object::ID
Implementation
public fun operation_cap_id(self: &Validator): &ID {
    &self.operation_cap_id
}

Function next_epoch_gas_price

public fun next_epoch_gas_price(self: &validator::Validator): u64
Implementation
public fun next_epoch_gas_price(self: &Validator): u64 {
    self.next_epoch_gas_price
}

Function total_stake_amount

public fun total_stake_amount(self: &validator::Validator): u64
Implementation
public fun total_stake_amount(self: &Validator): u64 {
    self.staking_pool.sui_balance()
}

Function stake_amount

public fun stake_amount(self: &validator::Validator): u64
Implementation
public fun stake_amount(self: &Validator): u64 {
    self.staking_pool.sui_balance()
}

Function total_stake

Return the total amount staked with this validator

public fun total_stake(self: &validator::Validator): u64
Implementation
public fun total_stake(self: &Validator): u64 {
    stake_amount(self)
}

Function voting_power

Return the voting power of this validator.

public fun voting_power(self: &validator::Validator): u64
Implementation
public fun voting_power(self: &Validator): u64 {
    self.voting_power
}

Function set_voting_power

Set the voting power of this validator, called only from validator_set.

public(friend) fun set_voting_power(self: &mut validator::Validator, new_voting_power: u64)
Implementation
public(package) fun set_voting_power(self: &mut Validator, new_voting_power: u64) {
    self.voting_power = new_voting_power;
}

Function pending_stake_amount

public fun pending_stake_amount(self: &validator::Validator): u64
Implementation

Function pending_stake_withdraw_amount

public fun pending_stake_withdraw_amount(self: &validator::Validator): u64
Implementation

Function gas_price

public fun gas_price(self: &validator::Validator): u64
Implementation
public fun gas_price(self: &Validator): u64 {
    self.gas_price
}

Function commission_rate

public fun commission_rate(self: &validator::Validator): u64
Implementation
public fun commission_rate(self: &Validator): u64 {
    self.commission_rate
}

Function pool_token_exchange_rate_at_epoch

public fun pool_token_exchange_rate_at_epoch(self: &validator::Validator, epoch: u64): staking_pool::PoolTokenExchangeRate
Implementation
public fun pool_token_exchange_rate_at_epoch(self: &Validator, epoch: u64): PoolTokenExchangeRate {
    self.staking_pool.pool_token_exchange_rate_at_epoch(epoch)
}

Function staking_pool_id

public fun staking_pool_id(self: &validator::Validator): object::ID
Implementation
public fun staking_pool_id(self: &Validator): ID {
    object::id(&self.staking_pool)
}

Function is_duplicate

public fun is_duplicate(self: &validator::Validator, other: &validator::Validator): bool
Implementation
public fun is_duplicate(self: &Validator, other: &Validator): bool {
     self.metadata.sui_address == other.metadata.sui_address
        || self.metadata.name == other.metadata.name
        || self.metadata.net_address == other.metadata.net_address
        || self.metadata.p2p_address == other.metadata.p2p_address
        || self.metadata.protocol_pubkey_bytes == other.metadata.protocol_pubkey_bytes
        || self.metadata.network_pubkey_bytes == other.metadata.network_pubkey_bytes
        || self.metadata.network_pubkey_bytes == other.metadata.worker_pubkey_bytes
        || self.metadata.worker_pubkey_bytes == other.metadata.worker_pubkey_bytes
        || self.metadata.worker_pubkey_bytes == other.metadata.network_pubkey_bytes
        // All next epoch parameters.
        || is_equal_some(&self.metadata.next_epoch_net_address, &other.metadata.next_epoch_net_address)
        || is_equal_some(&self.metadata.next_epoch_p2p_address, &other.metadata.next_epoch_p2p_address)
        || is_equal_some(&self.metadata.next_epoch_protocol_pubkey_bytes, &other.metadata.next_epoch_protocol_pubkey_bytes)
        || is_equal_some(&self.metadata.next_epoch_network_pubkey_bytes, &other.metadata.next_epoch_network_pubkey_bytes)
        || is_equal_some(&self.metadata.next_epoch_network_pubkey_bytes, &other.metadata.next_epoch_worker_pubkey_bytes)
        || is_equal_some(&self.metadata.next_epoch_worker_pubkey_bytes, &other.metadata.next_epoch_worker_pubkey_bytes)
        || is_equal_some(&self.metadata.next_epoch_worker_pubkey_bytes, &other.metadata.next_epoch_network_pubkey_bytes)
        // My next epoch parameters with other current epoch parameters.
        || is_equal_some_and_value(&self.metadata.next_epoch_net_address, &other.metadata.net_address)
        || is_equal_some_and_value(&self.metadata.next_epoch_p2p_address, &other.metadata.p2p_address)
        || is_equal_some_and_value(&self.metadata.next_epoch_protocol_pubkey_bytes, &other.metadata.protocol_pubkey_bytes)
        || is_equal_some_and_value(&self.metadata.next_epoch_network_pubkey_bytes, &other.metadata.network_pubkey_bytes)
        || is_equal_some_and_value(&self.metadata.next_epoch_network_pubkey_bytes, &other.metadata.worker_pubkey_bytes)
        || is_equal_some_and_value(&self.metadata.next_epoch_worker_pubkey_bytes, &other.metadata.worker_pubkey_bytes)
        || is_equal_some_and_value(&self.metadata.next_epoch_worker_pubkey_bytes, &other.metadata.network_pubkey_bytes)
        // Other next epoch parameters with my current epoch parameters.
        || is_equal_some_and_value(&other.metadata.next_epoch_net_address, &self.metadata.net_address)
        || is_equal_some_and_value(&other.metadata.next_epoch_p2p_address, &self.metadata.p2p_address)
        || is_equal_some_and_value(&other.metadata.next_epoch_protocol_pubkey_bytes, &self.metadata.protocol_pubkey_bytes)
        || is_equal_some_and_value(&other.metadata.next_epoch_network_pubkey_bytes, &self.metadata.network_pubkey_bytes)
        || is_equal_some_and_value(&other.metadata.next_epoch_network_pubkey_bytes, &self.metadata.worker_pubkey_bytes)
        || is_equal_some_and_value(&other.metadata.next_epoch_worker_pubkey_bytes, &self.metadata.worker_pubkey_bytes)
        || is_equal_some_and_value(&other.metadata.next_epoch_worker_pubkey_bytes, &self.metadata.network_pubkey_bytes)
}

Function is_equal_some_and_value

fun is_equal_some_and_value<T>(a: &option::Option<T>, b: &T): bool
Implementation
fun is_equal_some_and_value<T>(a: &Option<T>, b: &T): bool {
    if (a.is_none()) {
        false
    } else {
        a.borrow() == b
    }
}

Function is_equal_some

fun is_equal_some<T>(a: &option::Option<T>, b: &option::Option<T>): bool
Implementation
fun is_equal_some<T>(a: &Option<T>, b: &Option<T>): bool {
    if (a.is_none() || b.is_none()) {
        false
    } else {
        a.borrow() == b.borrow()
    }
}

Function new_unverified_validator_operation_cap_and_transfer

Create a new UnverifiedValidatorOperationCap, transfer to the validator, and registers it, thus revoking the previous cap's permission.

public(friend) fun new_unverified_validator_operation_cap_and_transfer(self: &mut validator::Validator, ctx: &mut tx_context::TxContext)
Implementation
public(package) fun new_unverified_validator_operation_cap_and_transfer(self: &mut Validator, ctx: &mut TxContext) {
    let address = ctx.sender();
    assert!(address == self.metadata.sui_address, ENewCapNotCreatedByValidatorItself);
    let new_id = validator_cap::new_unverified_validator_operation_cap_and_transfer(address, ctx);
    self.operation_cap_id = new_id;
}

Function update_name

Update name of the validator.

public(friend) fun update_name(self: &mut validator::Validator, name: vector<u8>)
Implementation
public(package) fun update_name(self: &mut Validator, name: vector<u8>) {
    assert!(
        name.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    self.metadata.name = name.to_ascii_string().to_string();
}

Function update_description

Update description of the validator.

public(friend) fun update_description(self: &mut validator::Validator, description: vector<u8>)
Implementation
public(package) fun update_description(self: &mut Validator, description: vector<u8>) {
    assert!(
        description.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    self.metadata.description = description.to_ascii_string().to_string();
}

Function update_image_url

Update image url of the validator.

public(friend) fun update_image_url(self: &mut validator::Validator, image_url: vector<u8>)
Implementation
public(package) fun update_image_url(self: &mut Validator, image_url: vector<u8>) {
    assert!(
        image_url.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    self.metadata.image_url = url::new_unsafe_from_bytes(image_url);
}

Function update_project_url

Update project url of the validator.

public(friend) fun update_project_url(self: &mut validator::Validator, project_url: vector<u8>)
Implementation
public(package) fun update_project_url(self: &mut Validator, project_url: vector<u8>) {
    assert!(
        project_url.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    self.metadata.project_url = url::new_unsafe_from_bytes(project_url);
}

Function update_next_epoch_network_address

Update network address of this validator, taking effects from next epoch

public(friend) fun update_next_epoch_network_address(self: &mut validator::Validator, net_address: vector<u8>)
Implementation
public(package) fun update_next_epoch_network_address(self: &mut Validator, net_address: vector<u8>) {
    assert!(
        net_address.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    let net_address = net_address.to_ascii_string().to_string();
    self.metadata.next_epoch_net_address = option::some(net_address);
    validate_metadata(&self.metadata);
}

Function update_candidate_network_address

Update network address of this candidate validator

public(friend) fun update_candidate_network_address(self: &mut validator::Validator, net_address: vector<u8>)
Implementation
public(package) fun update_candidate_network_address(self: &mut Validator, net_address: vector<u8>) {
    assert!(is_preactive(self), ENotValidatorCandidate);
    assert!(
        net_address.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    let net_address = net_address.to_ascii_string().to_string();
    self.metadata.net_address = net_address;
    validate_metadata(&self.metadata);
}

Function update_next_epoch_p2p_address

Update p2p address of this validator, taking effects from next epoch

public(friend) fun update_next_epoch_p2p_address(self: &mut validator::Validator, p2p_address: vector<u8>)
Implementation
public(package) fun update_next_epoch_p2p_address(self: &mut Validator, p2p_address: vector<u8>) {
    assert!(
        p2p_address.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    let p2p_address = p2p_address.to_ascii_string().to_string();
    self.metadata.next_epoch_p2p_address = option::some(p2p_address);
    validate_metadata(&self.metadata);
}

Function update_candidate_p2p_address

Update p2p address of this candidate validator

public(friend) fun update_candidate_p2p_address(self: &mut validator::Validator, p2p_address: vector<u8>)
Implementation
public(package) fun update_candidate_p2p_address(self: &mut Validator, p2p_address: vector<u8>) {
    assert!(is_preactive(self), ENotValidatorCandidate);
    assert!(
        p2p_address.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    let p2p_address = p2p_address.to_ascii_string().to_string();
    self.metadata.p2p_address = p2p_address;
    validate_metadata(&self.metadata);
}

Function update_next_epoch_primary_address

Update primary address of this validator, taking effects from next epoch

public(friend) fun update_next_epoch_primary_address(self: &mut validator::Validator, primary_address: vector<u8>)
Implementation
public(package) fun update_next_epoch_primary_address(self: &mut Validator, primary_address: vector<u8>) {
    assert!(
        primary_address.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    let primary_address = primary_address.to_ascii_string().to_string();
    self.metadata.next_epoch_primary_address = option::some(primary_address);
    validate_metadata(&self.metadata);
}

Function update_candidate_primary_address

Update primary address of this candidate validator

public(friend) fun update_candidate_primary_address(self: &mut validator::Validator, primary_address: vector<u8>)
Implementation
public(package) fun update_candidate_primary_address(self: &mut Validator, primary_address: vector<u8>) {
    assert!(is_preactive(self), ENotValidatorCandidate);
    assert!(
        primary_address.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    let primary_address = primary_address.to_ascii_string().to_string();
    self.metadata.primary_address = primary_address;
    validate_metadata(&self.metadata);
}

Function update_next_epoch_worker_address

Update worker address of this validator, taking effects from next epoch

public(friend) fun update_next_epoch_worker_address(self: &mut validator::Validator, worker_address: vector<u8>)
Implementation
public(package) fun update_next_epoch_worker_address(self: &mut Validator, worker_address: vector<u8>) {
    assert!(
        worker_address.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    let worker_address = worker_address.to_ascii_string().to_string();
    self.metadata.next_epoch_worker_address = option::some(worker_address);
    validate_metadata(&self.metadata);
}

Function update_candidate_worker_address

Update worker address of this candidate validator

public(friend) fun update_candidate_worker_address(self: &mut validator::Validator, worker_address: vector<u8>)
Implementation
public(package) fun update_candidate_worker_address(self: &mut Validator, worker_address: vector<u8>) {
    assert!(is_preactive(self), ENotValidatorCandidate);
    assert!(
        worker_address.length() <= MAX_VALIDATOR_METADATA_LENGTH,
        EValidatorMetadataExceedingLengthLimit
    );
    let worker_address = worker_address.to_ascii_string().to_string();
    self.metadata.worker_address = worker_address;
    validate_metadata(&self.metadata);
}

Function update_next_epoch_protocol_pubkey

Update protocol public key of this validator, taking effects from next epoch

public(friend) fun update_next_epoch_protocol_pubkey(self: &mut validator::Validator, protocol_pubkey: vector<u8>, proof_of_possession: vector<u8>)
Implementation
public(package) fun update_next_epoch_protocol_pubkey(self: &mut Validator, protocol_pubkey: vector<u8>, proof_of_possession: vector<u8>) {
    self.metadata.next_epoch_protocol_pubkey_bytes = option::some(protocol_pubkey);
    self.metadata.next_epoch_proof_of_possession = option::some(proof_of_possession);
    validate_metadata(&self.metadata);
}

Function update_candidate_protocol_pubkey

Update protocol public key of this candidate validator

public(friend) fun update_candidate_protocol_pubkey(self: &mut validator::Validator, protocol_pubkey: vector<u8>, proof_of_possession: vector<u8>)
Implementation
public(package) fun update_candidate_protocol_pubkey(self: &mut Validator, protocol_pubkey: vector<u8>, proof_of_possession: vector<u8>) {
    assert!(is_preactive(self), ENotValidatorCandidate);
    self.metadata.protocol_pubkey_bytes = protocol_pubkey;
    self.metadata.proof_of_possession = proof_of_possession;
    validate_metadata(&self.metadata);
}

Function update_next_epoch_network_pubkey

Update network public key of this validator, taking effects from next epoch

public(friend) fun update_next_epoch_network_pubkey(self: &mut validator::Validator, network_pubkey: vector<u8>)
Implementation
public(package) fun update_next_epoch_network_pubkey(self: &mut Validator, network_pubkey: vector<u8>) {
    self.metadata.next_epoch_network_pubkey_bytes = option::some(network_pubkey);
    validate_metadata(&self.metadata);
}

Function update_candidate_network_pubkey

Update network public key of this candidate validator

public(friend) fun update_candidate_network_pubkey(self: &mut validator::Validator, network_pubkey: vector<u8>)
Implementation
public(package) fun update_candidate_network_pubkey(self: &mut Validator, network_pubkey: vector<u8>) {
    assert!(is_preactive(self), ENotValidatorCandidate);
    self.metadata.network_pubkey_bytes = network_pubkey;
    validate_metadata(&self.metadata);
}

Function update_next_epoch_worker_pubkey

Update Narwhal worker public key of this validator, taking effects from next epoch

public(friend) fun update_next_epoch_worker_pubkey(self: &mut validator::Validator, worker_pubkey: vector<u8>)
Implementation
public(package) fun update_next_epoch_worker_pubkey(self: &mut Validator, worker_pubkey: vector<u8>) {
    self.metadata.next_epoch_worker_pubkey_bytes = option::some(worker_pubkey);
    validate_metadata(&self.metadata);
}

Function update_candidate_worker_pubkey

Update Narwhal worker public key of this candidate validator

public(friend) fun update_candidate_worker_pubkey(self: &mut validator::Validator, worker_pubkey: vector<u8>)
Implementation
public(package) fun update_candidate_worker_pubkey(self: &mut Validator, worker_pubkey: vector<u8>) {
    assert!(is_preactive(self), ENotValidatorCandidate);
    self.metadata.worker_pubkey_bytes = worker_pubkey;
    validate_metadata(&self.metadata);
}

Function effectuate_staged_metadata

Effectutate all staged next epoch metadata for this validator. NOTE: this function SHOULD ONLY be called by validator_set when advancing an epoch.

public(friend) fun effectuate_staged_metadata(self: &mut validator::Validator)
Implementation
public(package) fun effectuate_staged_metadata(self: &mut Validator) {
    if (next_epoch_network_address(self).is_some()) {
        self.metadata.net_address = self.metadata.next_epoch_net_address.extract();
        self.metadata.next_epoch_net_address = option::none();
    };

    if (next_epoch_p2p_address(self).is_some()) {
        self.metadata.p2p_address = self.metadata.next_epoch_p2p_address.extract();
        self.metadata.next_epoch_p2p_address = option::none();
    };

    if (next_epoch_primary_address(self).is_some()) {
        self.metadata.primary_address = self.metadata.next_epoch_primary_address.extract();
        self.metadata.next_epoch_primary_address = option::none();
    };

    if (next_epoch_worker_address(self).is_some()) {
        self.metadata.worker_address = self.metadata.next_epoch_worker_address.extract();
        self.metadata.next_epoch_worker_address = option::none();
    };

    if (next_epoch_protocol_pubkey_bytes(self).is_some()) {
        self.metadata.protocol_pubkey_bytes = self.metadata.next_epoch_protocol_pubkey_bytes.extract();
        self.metadata.next_epoch_protocol_pubkey_bytes = option::none();
        self.metadata.proof_of_possession = self.metadata.next_epoch_proof_of_possession.extract();
        self.metadata.next_epoch_proof_of_possession = option::none();
    };

    if (next_epoch_network_pubkey_bytes(self).is_some()) {
        self.metadata.network_pubkey_bytes = self.metadata.next_epoch_network_pubkey_bytes.extract();
        self.metadata.next_epoch_network_pubkey_bytes = option::none();
    };

    if (next_epoch_worker_pubkey_bytes(self).is_some()) {
        self.metadata.worker_pubkey_bytes = self.metadata.next_epoch_worker_pubkey_bytes.extract();
        self.metadata.next_epoch_worker_pubkey_bytes = option::none();
    };
}

Function validate_metadata

Aborts if validator metadata is valid

public fun validate_metadata(metadata: &validator::ValidatorMetadata)
Implementation

Function validate_metadata_bcs

public fun validate_metadata_bcs(metadata: vector<u8>)
Implementation
public native fun validate_metadata_bcs(metadata: vector<u8>);

Function get_staking_pool_ref

public(friend) fun get_staking_pool_ref(self: &validator::Validator): &staking_pool::StakingPool
Implementation
public(package) fun get_staking_pool_ref(self: &Validator) : &StakingPool {
    &self.staking_pool
}

Function new_from_metadata

Create a new validator from the given ValidatorMetadata, called by both new and new_for_testing.

fun new_from_metadata(metadata: validator::ValidatorMetadata, gas_price: u64, commission_rate: u64, ctx: &mut tx_context::TxContext): validator::Validator
Implementation
fun new_from_metadata(
    metadata: ValidatorMetadata,
    gas_price: u64,
    commission_rate: u64,
    ctx: &mut TxContext
): Validator {
    let sui_address = metadata.sui_address;

    let staking_pool = staking_pool::new(ctx);

    let operation_cap_id = validator_cap::new_unverified_validator_operation_cap_and_transfer(sui_address, ctx);
    Validator {
        metadata,
        // Initialize the voting power to be 0.
        // At the epoch change where this validator is actually added to the
        // active validator set, the voting power will be updated accordingly.
        voting_power: 0,
        operation_cap_id,
        gas_price,
        staking_pool,
        commission_rate,
        next_epoch_stake: 0,
        next_epoch_gas_price: gas_price,
        next_epoch_commission_rate: commission_rate,
        extra_fields: bag::new(ctx),
    }
}