Abstract
This paper specifies the Staking module of the Cosmos SDK that was first described in the Cosmos Whitepaper in June 2016. The module enables Cosmos SDK-based blockchain to support an advanced Proof-of-Stake (PoS) system. In this system, holders of the native staking token of the chain can become validators and can delegate tokens to validators, ultimately determining the effective validator set for the system. This module is used in the Cosmos Hub, the first Hub in the Cosmos network.Contents
State
Pool
Pool is used for tracking bonded and not-bonded token supply of the bond denomination.LastTotalPower
LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block. Store entries prefixed with “Last” must remain unchanged until EndBlock.- LastTotalPower:
0x12 -> ProtocolBuffer(math.Int)
ValidatorUpdates
ValidatorUpdates contains the validator updates returned to ABCI at the end of every block. The values are overwritten in every block.- ValidatorUpdates
0x61 -> []abci.ValidatorUpdate
UnbondingID
UnbondingID stores the ID of the latest unbonding operation. It enables to create unique IDs for unbonding operation, i.e., UnbondingID is incremented every time a new unbonding operation (validator unbonding, unbonding delegation, redelegation) is initiated.- UnbondingID:
0x37 -> uint64
Params
The staking module stores its params in state with the prefix of0x51
, it can be updated with governance or the address with authority.
- Params:
0x51 | ProtocolBuffer(Params)
Validator
Validators can have one of three statusesUnbonded
: The validator is not in the active set. They cannot sign blocks and do not earn rewards. They can receive delegations.Bonded
: Once the validator receives sufficient bonded tokens they automatically join the active set duringEndBlock
and their status is updated toBonded
. They are signing blocks and receiving rewards. They can receive further delegations. They can be slashed for misbehavior. Delegators to this validator who unbond their delegation must wait the duration of the UnbondingTime, a chain-specific param, during which time they are still slashable for offences of the source validator if those offences were committed during the period of time that the tokens were bonded.Unbonding
: When a validator leaves the active set, either by choice or due to slashing, jailing or tombstoning, an unbonding of all their delegations begins. All delegations must then wait the UnbondingTime before their tokens are moved to their accounts from theBondedPool
.
Tombstoning is permanent, once tombstoned a validators consensus key can not be reused within the chain where the tombstoning happened.
OperatorAddr
, an SDK validator address for the operator of the validator. Two additional indices are maintained per validator object in order to fulfill required lookups for slashing and validator-set updates. A third special index (LastValidatorPower
) is also maintained which however remains constant throughout each block, unlike the first two indices which mirror the validator records within a block.
- Validators:
0x21 | OperatorAddrLen (1 byte) | OperatorAddr -> ProtocolBuffer(validator)
- ValidatorsByConsAddr:
0x22 | ConsAddrLen (1 byte) | ConsAddr -> OperatorAddr
- ValidatorsByPower:
0x23 | BigEndian(ConsensusPower) | OperatorAddrLen (1 byte) | OperatorAddr -> OperatorAddr
- LastValidatorsPower:
0x11 | OperatorAddrLen (1 byte) | OperatorAddr -> ProtocolBuffer(ConsensusPower)
- ValidatorsByUnbondingID:
0x38 | UnbondingID -> 0x21 | OperatorAddrLen (1 byte) | OperatorAddr
Validators
is the primary index - it ensures that each operator can have only one associated validator, where the public key of that validator can change in the future. Delegators can refer to the immutable operator of the validator, without concern for the changing public key.
ValidatorsByUnbondingID
is an additional index that enables lookups for validators by the unbonding IDs corresponding to their current unbonding.
ValidatorByConsAddr
is an additional index that enables lookups for slashing. When CometBFT reports evidence, it provides the validator address, so this map is needed to find the operator. Note that the ConsAddr
corresponds to the address which can be derived from the validator’s ConsPubKey
.
ValidatorsByPower
is an additional index that provides a sorted list of potential validators to quickly determine the current active set. Here ConsensusPower is validator.Tokens/10^6 by default. Note that all validators where Jailed
is true are not stored within this index.
LastValidatorsPower
is a special index that provides a historical list of the last-block’s bonded validators. This index remains constant during a block but is updated during the validator set update process which takes place in EndBlock
.
Each validator’s state is stored in a Validator
struct:
proto/cosmos/staking/v1beta1/staking.proto
Delegation
Delegations are identified by combiningDelegatorAddr
(the address of the delegator) with the ValidatorAddr
Delegators are indexed in the store as follows:
- Delegation:
0x31 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr -> ProtocolBuffer(delegation)
Delegation
data structure. It is owned by one delegator, and is associated with the shares for one validator. The sender of the transaction is the owner of the bond.
proto/cosmos/staking/v1beta1/staking.proto
Delegator Shares
When one Delegates tokens to a Validator they are issued a number of delegator shares based on a dynamic exchange rate, calculated as follows from the total number of tokens delegated to the validator and the number of shares issued so far:Shares per Token = validator.TotalShares() / validator.Tokens()
Only the number of shares received is stored on the DelegationEntry. When a delegator then Undelegates, the token amount they receive is calculated from the number of shares they currently hold and the inverse exchange rate:
Tokens per Share = validator.Tokens() / validatorShares()
These Shares
are simply an accounting mechanism. They are not a fungible asset. The reason for this mechanism is to simplify the accounting around slashing. Rather than iteratively slashing the tokens of every delegation entry, instead the Validators total bonded tokens can be slashed, effectively reducing the value of each issued delegator share.
UnbondingDelegation
Shares in aDelegation
can be unbonded, but they must for some time exist as an UnbondingDelegation
, where shares can be reduced if Byzantine behavior is detected.
UnbondingDelegation
are indexed in the store as:
- UnbondingDelegation:
0x32 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)
- UnbondingDelegationsFromValidator:
0x33 | ValidatorAddrLen (1 byte) | ValidatorAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil
- UnbondingDelegationByUnbondingId:
0x38 | UnbondingId -> 0x32 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr``UnbondingDelegation
is used in queries, to lookup all unbonding delegations for a given delegator.
UnbondingDelegationsFromValidator
is used in slashing, to lookup all unbonding delegations associated with a given validator that need to be slashed.
UnbondingDelegationByUnbondingId
is an additional index that enables lookups for unbonding delegations by the unbonding IDs of the containing unbonding delegation entries.
A UnbondingDelegation object is created every time an unbonding is initiated.
proto/cosmos/staking/v1beta1/staking.proto
Redelegation
The bonded tokens worth of aDelegation
may be instantly redelegated from a source validator to a different validator (destination validator). However when this occurs they must be tracked in a Redelegation
object, whereby their shares can be slashed if their tokens have contributed to a Byzantine fault committed by the source validator.
Redelegation
are indexed in the store as:
-
Redelegations:
0x34 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)
-
RedelegationsBySrc:
0x35 | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil
-
RedelegationsByDst:
0x36 | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil
-
RedelegationByUnbondingId:
0x38 | UnbondingId -> 0x34 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddr
Redelegations
is used for queries, to lookup all redelegations for a given delegator.RedelegationsBySrc
is used for slashing based on theValidatorSrcAddr
.RedelegationsByDst
is used for slashing based on theValidatorDstAddr
ValidatorSrcAddr
, while the third map is for slashing based on the ValidatorDstAddr
.
RedelegationByUnbondingId
is an additional index that enables lookups for redelegations by the unbonding IDs of the containing redelegation entries.
A redelegation object is created every time a redelegation occurs. To prevent “redelegation hopping” redelegations may not occur under the situation that:
- the (re)delegator already has another immature redelegation in progress with a destination to a validator (let’s call it
Validator X
) - and, the (re)delegator is attempting to create a new redelegation where the source validator for this new redelegation is
Validator X
.
Queues
All queues objects are sorted by timestamp. The time used within any queue is first rounded to the nearest nanosecond then sorted. The sortable time format used is a slight modification of the RFC3339Nano and uses the format string"2006-01-02T15:04:05.000000000"
. Notably this format:
- right pads all zeros
- drops the time zone info (uses UTC)
UnbondingDelegationQueue
For the purpose of tracking progress of unbonding delegations the unbonding delegations queue is kept.- UnbondingDelegation:
0x41 | format(time) -> []DVPair
RedelegationQueue
For the purpose of tracking progress of redelegations the redelegation queue is kept.- RedelegationQueue:
0x42 | format(time) -> []DVVTriplet
ValidatorQueue
For the purpose of tracking progress of unbonding validators the validator queue is kept.- ValidatorQueueTime:
0x43 | format(time) -> []sdk.ValAddress
HistoricalInfo
HistoricalInfo objects are stored and pruned at each block such that the staking keeper persists then
most recent historical info defined by staking module parameter: HistoricalEntries
.
proto/cosmos/staking/v1beta1/staking.proto
HistoricalInfo
object. The Validators are sorted on their address to ensure that they are in a deterministic order. The oldest HistoricalEntries will be pruned to ensure that there only exist the parameter-defined number of historical entries.
State Transitions
Validators
State transitions in validators are performed on everyEndBlock
in order to check for changes in the active ValidatorSet
.
A validator can be Unbonded
, Unbonding
or Bonded
. Unbonded
and Unbonding
are collectively called Not Bonded
. A validator can move directly between all the states, except for from Bonded
to Unbonded
.
Not bonded to Bonded
The following transition occurs when a validator’s ranking in theValidatorPowerIndex
surpasses that of the LastValidator
.
- set
validator.Status
toBonded
- send the
validator.Tokens
from theNotBondedTokens
to theBondedPool
ModuleAccount
- delete the existing record from
ValidatorByPowerIndex
- add a new updated record to the
ValidatorByPowerIndex
- update the
Validator
object for this validator - if it exists, delete any
ValidatorQueue
record for this validator
Bonded to Unbonding
When a validator begins the unbonding process the following operations occur:- send the
validator.Tokens
from theBondedPool
to theNotBondedTokens
ModuleAccount
- set
validator.Status
toUnbonding
- delete the existing record from
ValidatorByPowerIndex
- add a new updated record to the
ValidatorByPowerIndex
- update the
Validator
object for this validator - insert a new record into the
ValidatorQueue
for this validator
Unbonding to Unbonded
A validator moves from unbonding to unbonded when theValidatorQueue
object moves from bonded to unbonded
- update the
Validator
object for this validator - set
validator.Status
toUnbonded
Jail/Unjail
when a validator is jailed it is effectively removed from the CometBFT set. this process may be also be reversed. the following operations occur:- set
Validator.Jailed
and update object - if jailed delete record from
ValidatorByPowerIndex
- if unjailed add record to
ValidatorByPowerIndex
- the power store (from consensus power to address)
Delegations
Delegate
When a delegation occurs both the validator and the delegation objects are affected- determine the delegators shares based on tokens delegated and the validator’s exchange rate
- remove tokens from the sending account
- add shares the delegation object or add them to a created validator object
- add new delegator shares and update the
Validator
object - transfer the
delegation.Amount
from the delegator’s account to theBondedPool
or theNotBondedPool
ModuleAccount
depending if thevalidator.Status
isBonded
or not - delete the existing record from
ValidatorByPowerIndex
- add an new updated record to the
ValidatorByPowerIndex
Begin Unbonding
As a part of the Undelegate and Complete Unbonding state transitions Unbond Delegation may be called.- subtract the unbonded shares from delegator
- add the unbonded tokens to an
UnbondingDelegationEntry
- update the delegation or remove the delegation if there are no more shares
- if the delegation is the operator of the validator and no more shares exist then trigger a jail validator
- update the validator with removed the delegator shares and associated coins
- if the validator state is
Bonded
, transfer theCoins
worth of the unbonded shares from theBondedPool
to theNotBondedPool
ModuleAccount
- remove the validator if it is unbonded and there are no more delegation shares.
- remove the validator if it is unbonded and there are no more delegation shares
- get a unique
unbondingId
and map it to theUnbondingDelegationEntry
inUnbondingDelegationByUnbondingId
- call the
AfterUnbondingInitiated(unbondingId)
hook - add the unbonding delegation to
UnbondingDelegationQueue
with the completion time set toUnbondingTime
Cancel an UnbondingDelegation
Entry
When a cancel unbond delegation
occurs both the validator
, the delegation
and an UnbondingDelegationQueue
state will be updated.
- if cancel unbonding delegation amount equals to the
UnbondingDelegation
entrybalance
, then theUnbondingDelegation
entry deleted fromUnbondingDelegationQueue
. - if the
cancel unbonding delegation amount is less than the
UnbondingDelegationentry balance, then the
UnbondingDelegationentry will be updated with new balance in the
UnbondingDelegationQueue`. - cancel
amount
is Delegated back to the originalvalidator
.
Complete Unbonding
For undelegations which do not complete immediately, the following operations occur when the unbonding delegation queue element matures:- remove the entry from the
UnbondingDelegation
object - transfer the tokens from the
NotBondedPool
ModuleAccount
to the delegatorAccount
Begin Redelegation
Redelegations affect the delegation, source and destination validators.- perform an
unbond
delegation from the source validator to retrieve the tokens worth of the unbonded shares - using the unbonded tokens,
Delegate
them to the destination validator - if the
sourceValidator.Status
isBonded
, and thedestinationValidator
is not, transfer the newly delegated tokens from theBondedPool
to theNotBondedPool
ModuleAccount
- otherwise, if the
sourceValidator.Status
is notBonded
, and thedestinationValidator
isBonded
, transfer the newly delegated tokens from theNotBondedPool
to theBondedPool
ModuleAccount
- record the token amount in an new entry in the relevant
Redelegation
Complete Redelegation
When a redelegations complete the following occurs:- remove the entry from the
Redelegation
object
Slashing
Slash Validator
When a Validator is slashed, the following occurs:- The total
slashAmount
is calculated as theslashFactor
(a chain parameter) *TokensFromConsensusPower
, the total number of tokens bonded to the validator at the time of the infraction. - Every unbonding delegation and pseudo-unbonding redelegation such that the infraction occured before the unbonding or redelegation began from the validator are slashed by the
slashFactor
percentage of the initialBalance. - Each amount slashed from redelegations and unbonding delegations is subtracted from the total slash amount.
- The
remaingSlashAmount
is then slashed from the validator’s tokens in theBondedPool
orNonBondedPool
depending on the validator’s status. This reduces the total supply of tokens.
Slash Unbonding Delegation
When a validator is slashed, so are those unbonding delegations from the validator that began unbonding after the time of the infraction. Every entry in every unbonding delegation from the validator is slashed byslashFactor
. The amount slashed is calculated from the InitialBalance
of the delegation and is capped to prevent a resulting negative balance. Completed (or mature) unbondings are not slashed.
Slash Redelegation
When a validator is slashed, so are all redelegations from the validator that began after the infraction. Redelegations are slashed byslashFactor
. Redelegations that began before the infraction are not slashed. The amount slashed is calculated from the InitialBalance
of the delegation and is capped to prevent a resulting negative balance. Mature redelegations (that have completed pseudo-unbonding) are not slashed.
How Shares are calculated
At any given point in time, each validator has a number of tokens,T
, and has a number of shares issued, S
. Each delegator, i
, holds a number of shares, S_i
. The number of tokens is the sum of all tokens delegated to the validator, plus the rewards, minus the slashes.
The delegator is entitled to a portion of the underlying tokens proportional to their proportion of shares. So delegator i
is entitled to T * S_i / S
of the validator’s tokens.
When a delegator delegates new tokens to the validator, they receive a number of shares proportional to their contribution. So when delegator j
delegates T_j
tokens, they receive S_j = S * T_j / T
shares. The total number of tokens is now T + T_j
, and the total number of shares is S + S_j
. j
s proportion of the shares is the same as their proportion of the total tokens contributed: (S + S_j) / S = (T + T_j) / T
.
A special case is the initial delegation, when T = 0
and S = 0
, so T_j / T
is undefined. For the initial delegation, delegator j
who delegates T_j
tokens receive S_j = T_j
shares. So a validator that hasn’t received any rewards and has not been slashed will have T = S
.
Messages
In this section we describe the processing of the staking messages and the corresponding updates to the state. All created/modified state objects specified by each message are defined within the state section.MsgCreateValidator
A validator is created using theMsgCreateValidator
message. The validator must be created with an initial delegation from the operator.
proto/cosmos/staking/v1beta1/tx.proto
- another validator with this operator address is already registered
- another validator with this pubkey is already registered
- the initial self-delegation tokens are of a denom not specified as the bonding denom
-
the commission parameters are faulty, namely:
MaxRate
is either > 1 or < 0- the initial
Rate
is either negative or >MaxRate
- the initial
MaxChangeRate
is either negative or >MaxRate
- the description fields are too large
Validator
object at appropriate indexes. Additionally a self-delegation is made with the initial tokens delegation tokens Delegation
. The validator always starts as unbonded but may be bonded in the first end-block.
MsgEditValidator
TheDescription
, CommissionRate
of a validator can be updated using the MsgEditValidator
message.
proto/cosmos/staking/v1beta1/tx.proto
- the initial
CommissionRate
is either negative or >MaxRate
- the
CommissionRate
has already been updated within the previous 24 hours - the
CommissionRate
is >MaxChangeRate
- the description fields are too large
Validator
object.
MsgDelegate
Within this message the delegator provides coins, and in return receives some amount of their validator’s (newly created) delegator-shares that are assigned toDelegation.Shares
.
proto/cosmos/staking/v1beta1/tx.proto
- the validator does not exist
- the
Amount
Coin
has a denomination different than one defined byparams.BondDenom
- the exchange rate is invalid, meaning the validator has no tokens (due to slashing) but there are outstanding shares
- the amount delegated is less than the minimum allowed delegation
Delegation
object for provided addresses does not already exist then it is created as part of this message otherwise the existing Delegation
is updated to include the newly received shares.
The delegator receives newly minted shares at the current exchange rate. The exchange rate is the number of existing shares in the validator divided by the number of currently delegated tokens.
The validator is updated in the ValidatorByPower
index, and the delegation is tracked in validator object in the Validators
index.
It is possible to delegate to a jailed validator, the only difference being it will not be added to the power index until it is unjailed.
MsgUndelegate
TheMsgUndelegate
message allows delegators to undelegate their tokens from validator.
proto/cosmos/staking/v1beta1/tx.proto
- the delegation doesn’t exist
- the validator doesn’t exist
- the delegation has less shares than the ones worth of
Amount
- existing
UnbondingDelegation
has maximum entries as defined byparams.MaxEntries
- the
Amount
has a denomination different than one defined byparams.BondDenom
-
validator’s
DelegatorShares
and the delegation’sShares
are both reduced by the messageSharesAmount
- calculate the token worth of the shares remove that amount tokens held within the validator
-
with those removed tokens, if the validator is:
Bonded
- add them to an entry inUnbondingDelegation
(createUnbondingDelegation
if it doesn’t exist) with a completion time a full unbonding period from the current time. Update pool shares to reduce BondedTokens and increase NotBondedTokens by token worth of the shares.Unbonding
- add them to an entry inUnbondingDelegation
(createUnbondingDelegation
if it doesn’t exist) with the same completion time as the validator (UnbondingMinTime
).Unbonded
- then send the coins the messageDelegatorAddr
-
if there are no more
Shares
in the delegation, then the delegation object is removed from the store- under this situation if the delegation is the validator’s self-delegation then also jail the validator.
MsgCancelUnbondingDelegation
TheMsgCancelUnbondingDelegation
message allows delegators to cancel the unbondingDelegation
entry and delegate back to a previous validator.
proto/cosmos/staking/v1beta1/tx.proto
- the
unbondingDelegation
entry is already processed. - the
cancel unbonding delegation
amount is greater than theunbondingDelegation
entry balance. - the
cancel unbonding delegation
height doesn’t exist in theunbondingDelegationQueue
of the delegator.
-
if the
unbondingDelegation
Entry balance is zero- in this condition
unbondingDelegation
entry will be removed fromunbondingDelegationQueue
. - otherwise
unbondingDelegationQueue
will be updated with newunbondingDelegation
entry balance and initial balance
- in this condition
-
the validator’s
DelegatorShares
and the delegation’sShares
are both increased by the messageAmount
.
MsgBeginRedelegate
The redelegation command allows delegators to instantly switch validators. Once the unbonding period has passed, the redelegation is automatically completed in the EndBlocker. proto/cosmos/staking/v1beta1/tx.proto- the delegation doesn’t exist
- the source or destination validators don’t exist
- the delegation has less shares than the ones worth of
Amount
- the source validator has a receiving redelegation which is not matured (aka. the redelegation may be transitive)
- existing
Redelegation
has maximum entries as defined byparams.MaxEntries
- the
Amount
Coin
has a denomination different than one defined byparams.BondDenom
-
the source validator’s
DelegatorShares
and the delegationsShares
are both reduced by the messageSharesAmount
- calculate the token worth of the shares remove that amount tokens held within the source validator.
-
if the source validator is:
Bonded
- add an entry to theRedelegation
(createRedelegation
if it doesn’t exist) with a completion time a full unbonding period from the current time. Update pool shares to reduce BondedTokens and increase NotBondedTokens by token worth of the shares (this may be effectively reversed in the next step however).Unbonding
- add an entry to theRedelegation
(createRedelegation
if it doesn’t exist) with the same completion time as the validator (UnbondingMinTime
).Unbonded
- no action required in this step
- Delegate the token worth to the destination validator, possibly moving tokens back to the bonded state.
-
if there are no more
Shares
in the source delegation, then the source delegation object is removed from the store- under this situation if the delegation is the validator’s self-delegation then also jail the validator.
MsgUpdateParams
TheMsgUpdateParams
update the staking module parameters. The params are updated through a governance proposal where the signer is the gov module account address.
proto/cosmos/staking/v1beta1/tx.proto
- signer is not the authority defined in the staking keeper (usually the gov module account).
Begin-Block
Each abci begin block call, the historical info will get stored and pruned according to theHistoricalEntries
parameter.
Historical Info Tracking
If theHistoricalEntries
parameter is 0, then the BeginBlock
performs a no-op.
Otherwise, the latest historical info is stored under the key historicalInfoKey|height
, while any entries older than height - HistoricalEntries
is deleted. In most cases, this results in a single entry being pruned per block. However, if the parameter HistoricalEntries
has changed to a lower value there will be multiple entries in the store that must be pruned.
End-Block
Each abci end block call, the operations to update queues and validator set changes are specified to execute.Validator Set Changes
The staking validator set is updated during this process by state transitions that run at the end of every block. As a part of this process any updated validators are also returned back to CometBFT for inclusion in the CometBFT validator set which is responsible for validating CometBFT messages at the consensus layer. Operations are as following:-
the new validator set is taken as the top
params.MaxValidators
number of validators retrieved from theValidatorsByPower
index -
the previous validator set is compared with the new validator set:
- missing validators begin unbonding and their
Tokens
are transferred from theBondedPool
to theNotBondedPool
ModuleAccount
- new validators are instantly bonded and their
Tokens
are transferred from theNotBondedPool
to theBondedPool
ModuleAccount
- missing validators begin unbonding and their
LastTotalPower
and LastValidatorsPower
hold the state of the total power and validator power from the end of the last block, and are used to check for changes that have occurred in ValidatorsByPower
and the total new power, which is calculated during EndBlock
.
Queues
Within staking, certain state-transitions are not instantaneous but take place over a duration of time (typically the unbonding period). When these transitions are mature certain operations must take place in order to complete the state operation. This is achieved through the use of queues which are checked/processed at the end of each block.Unbonding Validators
When a validator is kicked out of the bonded validator set (either through being jailed, or not having sufficient bonded tokens) it begins the unbonding process along with all its delegations begin unbonding (while still being delegated to this validator). At this point the validator is said to be an “unbonding validator”, whereby it will mature to become an “unbonded validator” after the unbonding period has passed. Each block the validator queue is to be checked for mature unbonding validators (namely with a completion time <= current time and completion height <= current block height). At this point any mature validators which do not have any delegations remaining are deleted from state. For all other mature unbonding validators that still have remaining delegations, thevalidator.Status
is switched from types.Unbonding
to types.Unbonded
.
Unbonding operations can be put on hold by external modules via the PutUnbondingOnHold(unbondingId)
method. As a result, an unbonding operation (e.g., an unbonding delegation) that is on hold, cannot complete even if it reaches maturity. For an unbonding operation with unbondingId
to eventually complete (after it reaches maturity), every call to PutUnbondingOnHold(unbondingId)
must be matched by a call to UnbondingCanComplete(unbondingId)
.
Unbonding Delegations
Complete the unbonding of all matureUnbondingDelegations.Entries
within the UnbondingDelegations
queue with the following procedure:
- transfer the balance coins to the delegator’s wallet address
- remove the mature entry from
UnbondingDelegation.Entries
- remove the
UnbondingDelegation
object from the store if there are no remaining entries.
Redelegations
Complete the unbonding of all matureRedelegation.Entries
within the Redelegations
queue with the following procedure:
- remove the mature entry from
Redelegation.Entries
- remove the
Redelegation
object from the store if there are no remaining entries.
Hooks
Other modules may register operations to execute when a certain event has occurred within staking. These events can be registered to execute either rightBefore
or After
the staking event (as per the hook name). The following hooks can registered with staking:
AfterValidatorCreated(Context, ValAddress) error
- called when a validator is created
BeforeValidatorModified(Context, ValAddress) error
- called when a validator’s state is changed
AfterValidatorRemoved(Context, ConsAddress, ValAddress) error
- called when a validator is deleted
AfterValidatorBonded(Context, ConsAddress, ValAddress) error
- called when a validator is bonded
AfterValidatorBeginUnbonding(Context, ConsAddress, ValAddress) error
- called when a validator begins unbonding
BeforeDelegationCreated(Context, AccAddress, ValAddress) error
- called when a delegation is created
BeforeDelegationSharesModified(Context, AccAddress, ValAddress) error
- called when a delegation’s shares are modified
AfterDelegationModified(Context, AccAddress, ValAddress) error
- called when a delegation is created or modified
BeforeDelegationRemoved(Context, AccAddress, ValAddress) error
- called when a delegation is removed
AfterUnbondingInitiated(Context, UnbondingID)
- called when an unbonding operation (validator unbonding, unbonding delegation, redelegation) was initiated
Events
The staking module emits the following events:EndBlocker
Type | Attribute Key | Attribute Value |
---|---|---|
complete_unbonding | amount | {totalUnbondingAmount} |
complete_unbonding | validator | {validatorAddress} |
complete_unbonding | delegator | {delegatorAddress} |
complete_redelegation | amount | {totalRedelegationAmount} |
complete_redelegation | source_validator | {srcValidatorAddress} |
complete_redelegation | destination_validator | {dstValidatorAddress} |
complete_redelegation | delegator | {delegatorAddress} |
Msg’s
MsgCreateValidator
Type | Attribute Key | Attribute Value |
---|---|---|
create_validator | validator | {validatorAddress} |
create_validator | amount | {delegationAmount} |
message | module | staking |
message | action | create_validator |
message | sender | {senderAddress} |
MsgEditValidator
Type | Attribute Key | Attribute Value |
---|---|---|
edit_validator | commission_rate | {commissionRate} |
edit_validator | min_self_delegation | {minSelfDelegation} |
message | module | staking |
message | action | edit_validator |
message | sender | {senderAddress} |
MsgDelegate
Type | Attribute Key | Attribute Value |
---|---|---|
delegate | validator | {validatorAddress} |
delegate | amount | {delegationAmount} |
message | module | staking |
message | action | delegate |
message | sender | {senderAddress} |
MsgUndelegate
Type | Attribute Key | Attribute Value |
---|---|---|
unbond | validator | {validatorAddress} |
unbond | amount | {unbondAmount} |
unbond | completion_time [0] | {completionTime} |
message | module | staking |
message | action | begin_unbonding |
message | sender | {senderAddress} |
- [0] Time is formatted in the RFC3339 standard
MsgCancelUnbondingDelegation
Type | Attribute Key | Attribute Value |
---|---|---|
cancel_unbonding_delegation | validator | {validatorAddress} |
cancel_unbonding_delegation | delegator | {delegatorAddress} |
cancel_unbonding_delegation | amount | {cancelUnbondingDelegationAmount} |
cancel_unbonding_delegation | creation_height | {unbondingCreationHeight} |
message | module | staking |
message | action | cancel_unbond |
message | sender | {senderAddress} |
MsgBeginRedelegate
Type | Attribute Key | Attribute Value |
---|---|---|
redelegate | source_validator | {srcValidatorAddress} |
redelegate | destination_validator | {dstValidatorAddress} |
redelegate | amount | {unbondAmount} |
redelegate | completion_time [0] | {completionTime} |
message | module | staking |
message | action | begin_redelegate |
message | sender | {senderAddress} |
- [0] Time is formatted in the RFC3339 standard
Parameters
The staking module contains the following parameters:Key | Type | Example |
---|---|---|
UnbondingTime | string (time ns) | “259200000000000” |
MaxValidators | uint16 | 100 |
KeyMaxEntries | uint16 | 7 |
HistoricalEntries | uint16 | 3 |
BondDenom | string | ”stake” |
MinCommissionRate | string | ”0.000000000000000000” |
Client
CLI
A user can query and interact with thestaking
module using the CLI.
Query
Thequery
commands allows users to query staking
state.
delegation
Thedelegation
command allows users to query delegations for an individual delegator on an individual validator.
Usage:
delegations
Thedelegations
command allows users to query delegations for an individual delegator on all validators.
Usage:
delegations-to
Thedelegations-to
command allows users to query delegations on an individual validator.
Usage:
historical-info
Thehistorical-info
command allows users to query historical information at given height.
Usage:
params
Theparams
command allows users to query values set as staking parameters.
Usage:
pool
Thepool
command allows users to query values for amounts stored in the staking pool.
Usage:
redelegation
Theredelegation
command allows users to query a redelegation record based on delegator and a source and destination validator address.
Usage:
redelegations
Theredelegations
command allows users to query all redelegation records for an individual delegator.
Usage:
redelegations-from
Theredelegations-from
command allows users to query delegations that are redelegating from a validator.
Usage:
unbonding-delegation
Theunbonding-delegation
command allows users to query unbonding delegations for an individual delegator on an individual validator.
Usage:
unbonding-delegations
Theunbonding-delegations
command allows users to query all unbonding-delegations records for one delegator.
Usage:
unbonding-delegations-from
Theunbonding-delegations-from
command allows users to query delegations that are unbonding from a validator.
Usage:
validator
Thevalidator
command allows users to query details about an individual validator.
Usage:
validators
Thevalidators
command allows users to query details about all validators on a network.
Usage:
Transactions
Thetx
commands allows users to interact with the staking
module.
create-validator
The commandcreate-validator
allows users to create new validator initialized with a self-delegation to it.
Usage:
validator.json
contains:
simd tendermint show-validator
command.
delegate
The commanddelegate
allows users to delegate liquid tokens to a validator.
Usage:
edit-validator
The commandedit-validator
allows users to edit an existing validator account.
Usage:
redelegate
The commandredelegate
allows users to redelegate illiquid tokens from one validator to another.
Usage:
unbond
The commandunbond
allows users to unbond shares from a validator.
Usage:
cancel unbond
The commandcancel-unbond
allow users to cancel the unbonding delegation entry and delegate back to the original validator.
Usage:
gRPC
A user can query thestaking
module using gRPC endpoints.
Validators
TheValidators
endpoint queries all validators that match the given status.
Validator
TheValidator
endpoint queries validator information for given validator address.
ValidatorDelegations
TheValidatorDelegations
endpoint queries delegate information for given validator.
ValidatorUnbondingDelegations
TheValidatorUnbondingDelegations
endpoint queries delegate information for given validator.
Delegation
TheDelegation
endpoint queries delegate information for given validator delegator pair.
UnbondingDelegation
TheUnbondingDelegation
endpoint queries unbonding information for given validator delegator.
DelegatorDelegations
TheDelegatorDelegations
endpoint queries all delegations of a given delegator address.
DelegatorUnbondingDelegations
TheDelegatorUnbondingDelegations
endpoint queries all unbonding delegations of a given delegator address.
Redelegations
TheRedelegations
endpoint queries redelegations of given address.
DelegatorValidators
TheDelegatorValidators
endpoint queries all validators information for given delegator.
DelegatorValidator
TheDelegatorValidator
endpoint queries validator information for given delegator validator
HistoricalInfo
Pool
ThePool
endpoint queries the pool information.
Params
TheParams
endpoint queries the pool information.
REST
A user can query thestaking
module using REST endpoints.
DelegatorDelegations
TheDelegtaorDelegations
REST endpoint queries all delegations of a given delegator address.
Redelegations
TheRedelegations
REST endpoint queries redelegations of given address.
DelegatorUnbondingDelegations
TheDelegatorUnbondingDelegations
REST endpoint queries all unbonding delegations of a given delegator address.
DelegatorValidators
TheDelegatorValidators
REST endpoint queries all validators information for given delegator address.
DelegatorValidator
TheDelegatorValidator
REST endpoint queries validator information for given delegator validator pair.
HistoricalInfo
TheHistoricalInfo
REST endpoint queries the historical information for given height.
Parameters
TheParameters
REST endpoint queries the staking parameters.
Pool
ThePool
REST endpoint queries the pool information.
Validators
TheValidators
REST endpoint queries all validators that match the given status.
Validator
TheValidator
REST endpoint queries validator information for given validator address.
ValidatorDelegations
TheValidatorDelegations
REST endpoint queries delegate information for given validator.
Delegation
TheDelegation
REST endpoint queries delegate information for given validator delegator pair.
UnbondingDelegation
TheUnbondingDelegation
REST endpoint queries unbonding information for given validator delegator pair.
ValidatorUnbondingDelegations
TheValidatorUnbondingDelegations
REST endpoint queries unbonding delegations of a validator.