github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/staking/spec/01_state.md (about)

     1  <!--
     2  order: 1
     3  -->
     4  
     5  # State
     6  
     7  ## LastTotalPower
     8  
     9  LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block.
    10  
    11  - LastTotalPower: `0x12 -> amino(sdk.Int)`
    12  
    13  ## Params
    14  
    15  Params is a module-wide configuration structure that stores system parameters
    16  and defines overall functioning of the staking module.
    17  
    18  - Params: `Paramsspace("staking") -> amino(params)`
    19  
    20  ```go
    21  type Params struct {
    22      UnbondingTime time.Duration // time duration of unbonding
    23      MaxValidators uint16        // maximum number of validators
    24      MaxEntries    uint16        // max entries for either unbonding delegation or redelegation (per pair/trio)
    25      BondDenom     string        // bondable coin denomination
    26  }
    27  ```
    28  
    29  ## Validator
    30  
    31  Validators can have one of three statuses
    32  
    33  - `Unbonded`: The validator is not in the active set. They cannot sign blocks and do not earn
    34    rewards. They can receive delegations.
    35  - `Bonded`": Once the validator receives sufficient bonded tokens they automtically join the
    36    active set during [`EndBlock`](./05_end_block.md#validator-set-changes) and their status is updated to `Bonded`.
    37    They are signing blocks and receiving rewards. They can receive further delegations.
    38    They can be slashed for misbehavior. Delegators to this validator who unbond their delegation
    39    must wait the duration of the UnbondingTime, a chain-specific param. during which time
    40    they are still slashable for offences of the source validator if those offences were committed 
    41    during the period of time that the tokens were bonded. 
    42  - `Unbonding`: When a validator leaves the active set, either by choice or due to slashing or
    43    tombstoning, an unbonding of all their delegations begins. All delegations must then wait the UnbondingTime
    44    before moving receiving their tokens to their accounts from the `BondedPool`.
    45  
    46  Validators objects should be primarily stored and accessed by the
    47  `OperatorAddr`, an SDK validator address for the operator of the validator. Two
    48  additional indices are maintained per validator object in order to fulfill
    49  required lookups for slashing and validator-set updates. A third special index
    50  (`LastValidatorPower`) is also maintained which however remains constant
    51  throughout each block, unlike the first two indices which mirror the validator
    52  records within a block.
    53  
    54  - Validators: `0x21 | OperatorAddr -> amino(validator)`
    55  - ValidatorsByConsAddr: `0x22 | ConsAddr -> OperatorAddr`
    56  - ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddr -> OperatorAddr`
    57  - LastValidatorsPower: `0x11 OperatorAddr -> amino(ConsensusPower)`
    58  
    59  `Validators` is the primary index - it ensures that each operator can have only one
    60  associated validator, where the public key of that validator can change in the
    61  future. Delegators can refer to the immutable operator of the validator, without
    62  concern for the changing public key.
    63  
    64  `ValidatorByConsAddr` is an additional index that enables lookups for slashing.
    65  When Tendermint reports evidence, it provides the validator address, so this
    66  map is needed to find the operator. Note that the `ConsAddr` corresponds to the
    67  address which can be derived from the validator's `ConsPubKey`.
    68  
    69  `ValidatorsByPower` is an additional index that provides a sorted list o
    70  potential validators to quickly determine the current active set. Here
    71  ConsensusPower is validator.Tokens/10^6.  Note that all validators where
    72  `Jailed` is true are not stored within this index.
    73  
    74  `LastValidatorsPower` is a special index that provides a historical list of the
    75  last-block's bonded validators. This index remains constant during a block but
    76  is updated during the validator set update process which takes place in [`EndBlock`](./05_end_block.md).
    77  
    78  Each validator's state is stored in a `Validator` struct:
    79  
    80  ```go
    81  type Validator struct {
    82      OperatorAddress         sdk.ValAddress  // address of the validator's operator; bech encoded in JSON
    83      ConsPubKey              crypto.PubKey   // the consensus public key of the validator; bech encoded in JSON
    84      Jailed                  bool            // has the validator been jailed from bonded status?
    85      Status                  sdk.BondStatus  // validator status (bonded/unbonding/unbonded)
    86      Tokens                  sdk.Int         // delegated tokens (incl. self-delegation)
    87      DelegatorShares         sdk.Dec         // total shares issued to a validator's delegators
    88      Description             Description     // description terms for the validator
    89      UnbondingHeight         int64           // if unbonding, height at which this validator has begun unbonding
    90      UnbondingCompletionTime time.Time       // if unbonding, min time for the validator to complete unbonding
    91      Commission              Commission      // commission parameters
    92      MinSelfDelegation       sdk.Int         // validator's self declared minimum self delegation
    93  }
    94  
    95  type Commission struct {
    96      CommissionRates
    97      UpdateTime time.Time // the last time the commission rate was changed
    98  }
    99  
   100  CommissionRates struct {
   101      Rate          sdk.Dec // the commission rate charged to delegators, as a fraction
   102      MaxRate       sdk.Dec // maximum commission rate which validator can ever charge, as a fraction
   103      MaxChangeRate sdk.Dec // maximum daily increase of the validator commission, as a fraction
   104  }
   105  
   106  type Description struct {
   107      Moniker          string // name
   108      Identity         string // optional identity signature (ex. UPort or Keybase)
   109      Website          string // optional website link
   110      SecurityContact  string // optional email for security contact
   111      Details          string // optional details
   112  }
   113  ```
   114  
   115  ## Delegation
   116  
   117  Delegations are identified by combining `DelegatorAddr` (the address of the delegator)
   118  with the `ValidatorAddr` Delegators are indexed in the store as follows:
   119  
   120  - Delegation: `0x31 | DelegatorAddr | ValidatorAddr -> amino(delegation)`
   121  
   122  Stake holders may delegate coins to validators; under this circumstance their
   123  funds are held in a `Delegation` data structure. It is owned by one
   124  delegator, and is associated with the shares for one validator. The sender of
   125  the transaction is the owner of the bond.
   126  
   127  ```go
   128  type Delegation struct {
   129      DelegatorAddr sdk.AccAddress
   130      ValidatorAddr sdk.ValAddress
   131      Shares        sdk.Dec        // delegation shares received
   132  }
   133  ```
   134  
   135  ### Delegator Shares
   136  
   137  When one Delegates tokens to a Validator they are issued a number of delegator shares based on a
   138  dynamic exchange rate, calculated as follows from the total number of tokens delegated to the
   139  validator and the number of shares issued so far:
   140  
   141  `Shares per Token = validator.TotalShares() / validator.Tokens()`
   142  
   143  Only the number of shares received is stored on the DelegationEntry. When a delegator then
   144  Undelegates, the token amount they receive is calculated from the number of shares they currently
   145  hold and the inverse exchange rate:
   146  
   147  `Tokens per Share = validator.Tokens() / validatorShares()`
   148  
   149  These `Shares` are simply an accounting mechanism. They are not a fungible asset. The reason for
   150  this mechanism is to simplify the accounting around slashing. Rather than iteratively slashing the
   151  tokens of every delegation entry, instead the Validators total bonded tokens can be slashed,
   152  effectively reducing the value of each issued delegator share.
   153  
   154  ## UnbondingDelegation
   155  
   156  Shares in a `Delegation` can be unbonded, but they must for some time exist as
   157  an `UnbondingDelegation`, where shares can be reduced if Byzantine behavior is
   158  detected.
   159  
   160  `UnbondingDelegation` are indexed in the store as:
   161  
   162  - UnbondingDelegation: `0x32 | DelegatorAddr | ValidatorAddr ->
   163     amino(unbondingDelegation)`
   164  - UnbondingDelegationsFromValidator: `0x33 | ValidatorAddr | DelegatorAddr ->
   165     nil`
   166  
   167  The first map here is used in queries, to lookup all unbonding delegations for
   168  a given delegator, while the second map is used in slashing, to lookup all
   169  unbonding delegations associated with a given validator that need to be
   170  slashed.
   171  
   172  A UnbondingDelegation object is created every time an unbonding is initiated.
   173  
   174  ```go
   175  type UnbondingDelegation struct {
   176      DelegatorAddr sdk.AccAddress             // delegator
   177      ValidatorAddr sdk.ValAddress             // validator unbonding from operator addr
   178      Entries       []UnbondingDelegationEntry // unbonding delegation entries
   179  }
   180  
   181  type UnbondingDelegationEntry struct {
   182      CreationHeight int64     // height which the unbonding took place
   183      CompletionTime time.Time // unix time for unbonding completion
   184      InitialBalance sdk.Coin  // atoms initially scheduled to receive at completion
   185      Balance        sdk.Coin  // atoms to receive at completion
   186  }
   187  ```
   188  
   189  ## Redelegation
   190  
   191  The bonded tokens worth of a `Delegation` may be instantly redelegated from a
   192  source validator to a different validator (destination validator). However when
   193  this occurs they must be tracked in a `Redelegation` object, whereby their
   194  shares can be slashed if their tokens have contributed to a Byzantine fault
   195  committed by the source validator.
   196  
   197  `Redelegation` are indexed in the store as:
   198  
   199  - Redelegations: `0x34 | DelegatorAddr | ValidatorSrcAddr | ValidatorDstAddr -> amino(redelegation)`
   200  - RedelegationsBySrc: `0x35 | ValidatorSrcAddr | ValidatorDstAddr | DelegatorAddr -> nil`
   201  - RedelegationsByDst: `0x36 | ValidatorDstAddr | ValidatorSrcAddr | DelegatorAddr -> nil`
   202  
   203  The first map here is used for queries, to lookup all redelegations for a given
   204  delegator. The second map is used for slashing based on the `ValidatorSrcAddr`,
   205  while the third map is for slashing based on the `ValidatorDstAddr`.
   206  
   207  A redelegation object is created every time a redelegation occurs.  To prevent
   208  "redelegation hopping" redelegations may not occur under the situation that:
   209  
   210  - the (re)delegator already has another immature redelegation in progress
   211  with a destination to a validator (let's call it `Validator X`)
   212  - and, the (re)delegator is attempting to create a _new_ redelegation
   213  where the source validator for this new redelegation is `Validator-X`.
   214  
   215  ```go
   216  type Redelegation struct {
   217      DelegatorAddr    sdk.AccAddress      // delegator
   218      ValidatorSrcAddr sdk.ValAddress      // validator redelegation source operator addr
   219      ValidatorDstAddr sdk.ValAddress      // validator redelegation destination operator addr
   220      Entries          []RedelegationEntry // redelegation entries
   221  }
   222  
   223  type RedelegationEntry struct {
   224      CreationHeight int64     // height which the redelegation took place
   225      CompletionTime time.Time // unix time for redelegation completion
   226      InitialBalance sdk.Coin  // initial balance when redelegation started
   227      Balance        sdk.Coin  // current balance (current value held in destination validator)
   228      SharesDst      sdk.Dec   // amount of destination-validator shares created by redelegation
   229  }
   230  ```
   231  
   232  ## Queues
   233  
   234  All queues objects are sorted by timestamp. The time used within any queue is
   235  first rounded to the nearest nanosecond then sorted. The sortable time format
   236  used is a slight modification of the RFC3339Nano and uses the the format string
   237  `"2006-01-02T15:04:05.000000000"`. Notably this format:
   238  
   239  - right pads all zeros
   240  - drops the time zone info (uses UTC)
   241  
   242  In all cases, the stored timestamp represents the maturation time of the queue
   243  element.
   244  
   245  ### UnbondingDelegationQueue
   246  
   247  For the purpose of tracking progress of unbonding delegations the unbonding
   248  delegations queue is kept.
   249  
   250  - UnbondingDelegation: `0x41 | format(time) -> []DVPair`
   251  
   252  ```go
   253  type DVPair struct {
   254      DelegatorAddr sdk.AccAddress
   255      ValidatorAddr sdk.ValAddress
   256  }
   257  ```
   258  
   259  ### RedelegationQueue
   260  
   261  For the purpose of tracking progress of redelegations the redelegation queue is
   262  kept.
   263  
   264  - UnbondingDelegation: `0x42 | format(time) -> []DVVTriplet`
   265  
   266  ```go
   267  type DVVTriplet struct {
   268      DelegatorAddr    sdk.AccAddress
   269      ValidatorSrcAddr sdk.ValAddress
   270      ValidatorDstAddr sdk.ValAddress
   271  }
   272  ```
   273  
   274  ### ValidatorQueue
   275  
   276  For the purpose of tracking progress of unbonding validators the validator
   277  queue is kept.
   278  
   279  - ValidatorQueueTime: `0x43 | format(time) -> []sdk.ValAddress`
   280  
   281  The stored object as each key is an array of validator operator addresses from
   282  which the validator object can be accessed.  Typically it is expected that only
   283  a single validator record will be associated with a given timestamp however it is possible
   284  that multiple validators exist in the queue at the same location.
   285  
   286  ## HistoricalInfo
   287  
   288  HistoricalInfo objects are stored and pruned at each block such that the staking keeper persists
   289  the `n` most recent historical info defined by staking module parameter: `HistoricalEntries`.
   290  
   291  ```go
   292  type HistoricalInfo struct {
   293      Header abci.Header
   294      ValSet []types.Validator
   295  }
   296  ```
   297  
   298  At each BeginBlock, the staking keeper will persist the current Header and the Validators that committed
   299  the current block in a `HistoricalInfo` object. The Validators are sorted on their address to ensure that 
   300  they are in a determisnistic order.
   301  The oldest HistoricalEntries will be pruned to ensure that there only exist the parameter-defined number of 
   302  historical entries.