Merge PR #2365: Validator Commission Model

* Update validator commission fields

* Remove CommissionChangeToday and update to use CommissionChangeTime

* Implement commission as a first class citizen type

* Implement stringer for Comission

* Move commission type and logic to new  file

* Add new commission errors

* Add commission to create validator message

* Implement and call UpdateValidatorCommission

* Update godoc for UpdateValidatorCommission

* Add Abs to the decimal type

* Implement new SetValidatorCommission

* Update decimal short godocs

* Move set initial commission logic

* Move initial commission validation to Commission type

* Update initial validator commission logic and unit tests

* Remove commission update time from struct and move to validator

* Update validator create handler tests

* Implement commission logic for CLI

* Fix make lint failure

* Fix make cover failure

* Update edit validator logic to handle new commission rate

* Fix lint and cover

* Update create/edit validator simulation to include commission params

* Update MsgEditValidator godoc

* Update pending log

* Update staking tx docs

* Fix CLI create validator test

* Update variables names for commission  strings

* Merge UpdateTime into Commission type

* Update create-validator usage in docs

* Update more docs with examples

* More doc updates
This commit is contained in:
Alexander Bezobchuk
2018-09-24 18:23:58 -04:00
committed by Rigel
parent 8774adc7de
commit 9dafa3252d
25 changed files with 728 additions and 282 deletions
+70 -49
View File
@@ -1,86 +1,107 @@
## Transaction Overview
# Transaction Overview
In this section we describe the processing of the transactions and the
corresponding updates to the state. Transactions:
- TxCreateValidator
- TxEditValidator
- TxDelegation
- TxStartUnbonding
- TxCompleteUnbonding
- TxRedelegate
- TxCompleteRedelegation
* TxCreateValidator
* TxEditValidator
* TxDelegation
* TxStartUnbonding
* TxCompleteUnbonding
* TxRedelegate
* TxCompleteRedelegation
Other important state changes:
- Update Validators
* Update Validators
Other notes:
- `tx` denotes a reference to the transaction being processed
- `sender` denotes the address of the sender of the transaction
- `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and
modify objects from the store
- `sdk.Dec` refers to a decimal type specified by the SDK.
### TxCreateValidator
* `tx` denotes a reference to the transaction being processed
* `sender` denotes the address of the sender of the transaction
* `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and
modify objects from the store
* `sdk.Dec` refers to a decimal type specified by the SDK.
- triggers: `distribution.CreateValidatorDistribution`
## TxCreateValidator
* triggers: `distribution.CreateValidatorDistribution`
A validator is created using the `TxCreateValidator` transaction.
```golang
type TxCreateValidator struct {
Operator sdk.Address
ConsensusPubKey crypto.PubKey
GovernancePubKey crypto.PubKey
SelfDelegation coin.Coin
Description Description
Commission Commission
Description Description
Commission sdk.Dec
CommissionMax sdk.Dec
CommissionMaxChange sdk.Dec
DelegatorAddr sdk.AccAddress
ValidatorAddr sdk.ValAddress
PubKey crypto.PubKey
Delegation sdk.Coin
}
createValidator(tx TxCreateValidator):
validator = getValidator(tx.Operator)
if validator != nil return // only one validator per address
ok := validatorExists(tx.ValidatorAddr)
if ok return err // only one validator per address
validator = NewValidator(operatorAddr, ConsensusPubKey, GovernancePubKey, Description)
init validator poolShares, delegatorShares set to 0
init validator commision fields from tx
validator.PoolShares = 0
ok := validatorByPubKeyExists(tx.PubKey)
if ok return err // only one validator per public key
err := validateDenom(tx.Delegation.Denom)
if err != nil return err // denomination must be valid
validator := NewValidator(tx.ValidatorAddr, tx.PubKey, tx.Description)
err := setInitialCommission(validator, tx.Commission, blockTime)
if err != nil return err // must be able to set initial commission correctly
// set the validator and public key
setValidator(validator)
setValidatorByPubKeyIndex(validator)
txDelegate = TxDelegate(tx.Operator, tx.Operator, tx.SelfDelegation)
delegate(txDelegate, validator) // see delegate function in [TxDelegate](TxDelegate)
return
// delegate coins from tx.DelegatorAddr to the validator
err := delegate(tx.DelegatorAddr, tx.Delegation, validator)
if err != nil return err // must be able to set delegation correctly
tags := createTags(tx)
return tags
```
### TxEditValidator
## TxEditValidator
If either the `Description` (excluding `DateBonded` which is constant),
`Commission`, or the `GovernancePubKey` need to be updated, the
`TxEditCandidacy` transaction should be sent from the operator account:
If either the `Description`, `Commission`, or the `ValidatorAddr` need to be
updated, the `TxEditCandidacy` transaction should be sent from the operator
account:
```golang
type TxEditCandidacy struct {
GovernancePubKey crypto.PubKey
Commission sdk.Dec
Description Description
Description Description
ValidatorAddr sdk.ValAddress
CommissionRate sdk.Dec
}
editCandidacy(tx TxEditCandidacy):
validator = getValidator(tx.ValidatorAddr)
validator, ok := getValidator(tx.ValidatorAddr)
if !ok return err // validator must exist
if tx.Commission > CommissionMax || tx.Commission < 0 then fail
if rateChange(tx.Commission) > CommissionMaxChange then fail
validator.Commission = tx.Commission
// Attempt to update the validator's description. The description provided
// must be valid.
description, err := updateDescription(validator, tx.Description)
if err != nil return err
if tx.GovernancePubKey != nil validator.GovernancePubKey = tx.GovernancePubKey
if tx.Description != nil validator.Description = tx.Description
// a validator is not required to update it's commission rate
if tx.CommissionRate != nil {
// Attempt to update a validator's commission rate. The rate provided
// must be valid. It's rate can only be updated once a day.
err := updateValidatorCommission(validator, tx.CommissionRate)
if err != nil return err
}
setValidator(store, validator)
return
// set the validator and public key
setValidator(validator)
tags := createTags(tx)
return tags
```
### TxDelegate
+17 -2
View File
@@ -35,9 +35,16 @@ gaiacli stake create-validator \
--address-validator=<account_cosmosval>
--moniker="choose a moniker" \
--chain-id=<chain_id> \
--name=<key_name>
--name=<key_name> \
--commission-rate="0.10" \
--commission-max-rate="0.20" \
--commission-max-change-rate="0.01"
```
__Note__: When specifying commission parameters, the `commission-max-change-rate`
is used to measure % _point_ change over the `commission-rate`. E.g. 1% to 2% is
a 100% rate increase, but only 1 percentage point.
### Edit Validator Description
You can edit your validator's public description. This info is to identify your validator, and will be relied on by delegators to decide which validators to stake to. Make sure to provide input for every flag below, otherwise the field will default to empty (`--moniker` defaults to the machine name).
@@ -52,9 +59,17 @@ gaiacli stake edit-validator
--identity=6A0D65E29A4CBC8E
--details="To infinity and beyond!"
--chain-id=<chain_id> \
--name=<key_name>
--name=<key_name> \
--commission-rate="0.10"
```
__Note__: The `commission-rate` value must adhere to the following invariants:
- Must be between 0 and the validator's `commission-max-rate`
- Must not exceed the validator's `commission-max-change-rate` which is maximum
% point change rate **per day**. In other words, a validator can only change
its commission once per day and within `commission-max-change-rate` bounds.
### View Validator Description
View the validator's information with this command: