Skip to content

Staking Notes

Yang SONG edited this page Dec 15, 2021 · 4 revisions

Staking Notes

MsgCreateValidator

  • New Validator entry is created and written in store.
  • New Delegation entry is added in store.
  • Tokens are transfered from delegator account to module account (BondedPool module account or NotBondedPool module acount).
  • Delegation amount is added to Validator.Tokens.

x/staking/keeper/msg_server.go CreateValidator()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/msg_server.go#L30

1. k.Keeper.Delegate()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/msg_server.go#L111

x/staking/keeper/delegation.go Delegate()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/delegation.go#L551

  1. Find/Create Delegation entry from store, identifier (DelegatorAddr, ValidatorOperator)

  2. subtractAccount == true

  • k.bankKeeper.DelegateCoinsFromAccountToModule(): Remove tokens from delegator account, add tokens to module account

    • Validator.IsBonded: Tokens from delegator account sent to BondedPool module account
    • Validator.IsUnbonded OR Validator.IsUnbonding (Validator Not Bonded): Tokens from delegator account sent to NotBondedPool module account
  1. k.AddValidatorTokensAndShares(): add tokens and shares on Validator entry in store

  2. Update Delegation entry in store

MsgDelegate

Pretty much the same as the MsgCreateValidator. Except not doing Validator initial setup.

  • New Delegation entry is added in store.
  • Tokens are transfered from Delegator account to module account (BondedPool module account or NotBondedPool module acount).
  • Delegation amount is added to Validator.Tokens.

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/msg_server.go#L198

MsgBeginRedelegate

  • Delete/Update existing Delegation entry (relates to source validator) in store.
  • Create/Update the Delegation entry (relates to destination validator) in store.
  • Tokens are still in module accounts, transfer may happen between these module accounts (BondedPool module account or NotBondedPool module acount).
  • Redelegation amount is removed from source Validator.Tokens. Shares is removed from source Validator.DelegatorShares (total shares).
  • Redelegation amount is added to destination Validator.Tokens. Shares is added to destination Validator.DelegatorShares (total shares).
  • (Optional) Redelegation entry is created/updated.

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/msg_server.go#L257

x/staking/keeper/delegation.go BeginRedelegation()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/delegation.go#L822

1. k.Unbond()

  • Get Delegation entry from store, identifier (DelegatorAddr, SrcValidatorOperator)
  • Get SrcValidator from store.
  • Delete shares on Delegation entry.
  • Delete/Update Delegation in store.
  • k.RemoveValidatorTokensAndShares(): remove tokens and shares on source Validator, update source Validator in store.

2. k.Delegate()

  1. Find/Create Delegation entry from store, identifier (DelegatorAddr, DstValidatorOperator)

  2. subtractAccount == false:

  • Source Validator Not Bonded -> destination Validator Bonded: sent tokens from NotBondedPool to BondedPool module account
  • Source Validator Bonded -> destination Validator Not Bonded: sent tokens from BondedPool to NotBondedPool module account
  • Other cases, do nothing
  • Undefined case, panic
  1. k.AddValidatorTokensAndShares(): add tokens and shares on destination Validator in store

  2. Update Delegation in store

3. k.getBeginInfo()

Calculate completion time for RedelegationQueueEntry

  1. Source Validator.IsBonded: Wait for A full unbonding time (longest wait)
  2. Source Validator.IsUnbonded: Complete right away
  3. Source Validator.IsUnbonding: Wait until validator's unbonding is done

4. (Optional) k.SetRedelegationEntry() and k.InsertRedelegationQueue()

  • Create/Update Redelegation entry in store.
  • Insert a corresponding entry to RedelegationQueue. The queue is for checking and completing mature Redelegation entries at EndBlocker.

MsgUndelegate

  • Delete/Update existing Delegation entry on Validator in store.
  • Tokens are still in module accounts, transfer may happen between these module accounts (BondedPool module account or NotBondedPool module acount).
  • Undelegation amount is removed from Validator.Tokens. Shares is removed from Validator.DelegatorShares (total shares)
  • UnbondingDelegation entry is created/updated.

The tokens are removed from Validator.Tokens, but is still in module accounts. Only when it is complete (mature), the tokens will be sent back to delegator.

x/staking/keeper/msg_server.go Undelegate()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/msg_server.go#L325

  • k.Keeper.Undelegate(): x/staking/keeper/delegation.go Undelegate()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/delegation.go#L743

1. k.Unbond()

  • Get Delegation entry from store, identifier (DelegatorAddr, ValidatorOperator)
  • Get Validator in store.
  • Delete shares on Delegation entry.
  • Delete/Update Delegation entry in store.
  • k.RemoveValidatorTokensAndShares(): remove tokens and shares on Validator, update Validator in store.

2. (Optional) Validator.IsBonded

k.bondedTokensToNotBonded(): sent tokens from BondedPool module account to NotBondedPool module account.

3. Calculate completion time

4. k.SetUnbondingDelegationEntry() and k.InsertUBDQueue()

  • Create/Update UnbindingDelegation entry in store.
  • Insert a corresponding entry to UnbondingDelegationQueue. The queue is for checking and completing mature UnbindingDelegation entries at EndBlocker.

EndBlocker

x/staking/abci.go EndBlocker()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/abci.go#L23

x/staking/keeper/val_state_change.go BlockValidatorUpdates()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/val_state_change.go#L17

Complete Unbonding

  • Loop through UBDQueue (kind of like an index for finding mature UnbindingDelegation entries), find and delete mature entry in it.
  • Mature UnbondingDelegation entry will trigger transfer of tokens, from NotBondedPool module account to Delegator account.
  • Then the UnbondingDelegation entry is removed from store.

x/staking/keeper/delegation.go CompleteUnbonding()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/delegation.go#L775

  • k.bankKeeper.UndelegateCoinsFromModuleToAccount()

Complete Redelegation

  • Loop through RedelegationQueue (kind of like an index for finding mature Redelegation entries), find and delete mature entry in it.
  • Deleting the Redelegation entries from store, not moving funds in any account.

x/staking/keeper/delegation.go CompleteRedelegation()

https://github.com/cosmos/cosmos-sdk/blob/fec35777f9646c162b79e98409179e374374e6e0/x/staking/keeper/delegation.go#L881

Glossary

This section list a few important types for staking.

x/staking/types/staking.pb.go

Validator

// Validator defines a validator, together with the total amount of the
// Validator's bond shares and their exchange rate to coins. Slashing results in
// a decrease in the exchange rate, allowing correct calculation of future
// undelegations without iterating over delegators. When coins are delegated to
// this validator, the validator is credited with a delegation whose number of
// bond shares is based on the amount of coins delegated divided by the current
// exchange rate. Voting power can be calculated as total bonded shares
// multiplied by exchange rate.
type Validator struct {
	// operator_address defines the address of the validator's operator; bech encoded in JSON.
	OperatorAddress string 
	// consensus_pubkey is the consensus public key of the validator, as a Protobuf Any.
	ConsensusPubkey *types1.Any 
	// jailed defined whether the validator has been jailed from bonded status or not.
	Jailed bool 
	// status is the validator status (bonded/unbonding/unbonded).
	Status BondStatus 
	// tokens define the delegated tokens (incl. self-delegation).
	Tokens github_com_cosmos_cosmos_sdk_types.Int 
	// delegator_shares defines total shares issued to a validator's delegators.
	DelegatorShares github_com_cosmos_cosmos_sdk_types.Dec 
	// description defines the description terms for the validator.
	Description Description 
	// unbonding_height defines, if unbonding, the height at which this validator has begun unbonding.
	UnbondingHeight int64 
	// unbonding_time defines, if unbonding, the min time for the validator to complete unbonding.
	UnbondingTime time.Time 
	// commission defines the commission parameters.
	Commission Commission 
	// min_self_delegation is the validator's self declared minimum self delegation.
	MinSelfDelegation github_com_cosmos_cosmos_sdk_types.Int 
}

Delegation

One important thing on Delegation is it does not contain actual tokens amount, it only contains shares amount.

To calculate the corresponding tokens amount, you will need to find the corresponding Validator entry.

// Delegation represents the bond with tokens held by an account. It is
// owned by one delegator, and is associated with the voting power of one
// validator.
type Delegation struct {
	// delegator_address is the bech32-encoded address of the delegator.
	DelegatorAddress string 
	// validator_address is the bech32-encoded address of the validator.
	ValidatorAddress string 
	// shares define the delegation shares received.
	Shares github_com_cosmos_cosmos_sdk_types.Dec  
}

UnbondingDelegation (Undelegation)

One thing to keep in mind is that a delegator could have multiple on-going UnbondingDelegationEntry on a validator.

Another important thing is the difference between UnbondingDelegationEntry.InitialBalance and UnbondingDelegationEntry.Balance.

  • UnbondingDelegationEntry.InitialBalance: will not change after created.
  • UnbondingDelegationEntry.Balance: this value could change if a slash happen.
// UnbondingDelegation stores all of a single delegator's unbonding bonds
// for a single validator in an time-ordered list.
type UnbondingDelegation struct {
	// delegator_address is the bech32-encoded address of the delegator.
	DelegatorAddress string 
	// validator_address is the bech32-encoded address of the validator.
	ValidatorAddress string 
	// entries are the unbonding delegation entries.
	Entries []UnbondingDelegationEntry 
}

// UnbondingDelegationEntry defines an unbonding object with relevant metadata.
type UnbondingDelegationEntry struct {
	// creation_height is the height which the unbonding took place.
	CreationHeight int64
	// completion_time is the unix time for unbonding completion.
	CompletionTime time.Time 
	// initial_balance defines the tokens initially scheduled to receive at completion.
	InitialBalance github_com_cosmos_cosmos_sdk_types.Int 
	// balance defines the tokens to receive at completion.
	Balance github_com_cosmos_cosmos_sdk_types.Int 
}

Redelegation

Similar to UnbondingDelegation, a delegator could have multiple on-going RedelegationEntry on a validator.

RedelegationEntry.SharesDst will not be changed when a slash happens.

// Redelegation contains the list of a particular delegator's redelegating bonds
// from a particular source validator to a particular destination validator.
type Redelegation struct {
	// delegator_address is the bech32-encoded address of the delegator.
	DelegatorAddress string 
	// validator_src_address is the validator redelegation source operator address.
	ValidatorSrcAddress string
	// validator_dst_address is the validator redelegation destination operator address.
	ValidatorDstAddress string 
	// entries are the redelegation entries.
	Entries []RedelegationEntry 
}

type RedelegationEntry struct {
	// creation_height  defines the height which the redelegation took place.
	CreationHeight int64 
	// completion_time defines the unix time for redelegation completion.
	CompletionTime time.Time 
	// initial_balance defines the initial balance when redelegation started.
	InitialBalance github_com_cosmos_cosmos_sdk_types.Int `
	// shares_dst is the amount of destination-validator shares created by redelegation.
	SharesDst github_com_cosmos_cosmos_sdk_types.Dec 
}