Merge remote-tracking branch 'origin/develop' into rigel/fee-distribution
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
WORK IN PROGRESS
|
||||
See PR comments here https://github.com/cosmos/cosmos-sdk/pull/2072
|
||||
|
||||
# Keeper
|
||||
|
||||
## Denom Metadata
|
||||
|
||||
The BankKeeper contains a store that stores the metadata of different token denoms. Denoms are referred to by their name, same as the `denom` field in sdk.Coin. The different attributes of a denom are stored in the denom metadata store under the key `[denom name]:[attribute name]`. The default attributes in the store are explained below. However, this can be extended by the developer or through SoftwareUpgrade proposals.
|
||||
|
||||
### Decimals `int8`
|
||||
|
||||
- `Base Unit` = The common standard for the default "standard" size of a token. Examples: 1 Bitcoin or 1 Ether.
|
||||
- `Smallest Unit` = The smallest possible denomination of a token. A fraction of the base unit. Examples: 1 satoshi or 1 wei.
|
||||
|
||||
All amounts throughout the SDK are denominated in the smallest unit of a token, so that all amounts can be expressed as integers. However, UIs typically want to display token values in the base unit, so the Decimals metadata field standardizes the number of digits that come after the decimal place in the base unit.
|
||||
|
||||
`1 [Base Unit] = 10^(N) [Smallest Unit]`
|
||||
|
||||
### TotalSupply `sdk.Integer`
|
||||
|
||||
The TotalSupply of a denom is the total amount of a token that exists (known to the chain) across all accounts and modules. It is denominated in the `smallest unit` of a denom. It can be changed by the Keeper functions `MintCoins` and `BurnCoins`. `AddCoins` and `SubtractCoins` are used when adding or subtracting coins for an account, but not removing them from total supply (for example, when moving the coins to the control of the staking module).
|
||||
|
||||
### Aliases `[]string`
|
||||
|
||||
Aliases is an array of strings that are "alternative names" for a token. As an example, while the Ether's denom name might be `ether`, a possible alias could be `ETH`. This field can be useful for UIs and clients. It is intended that this field can be modified by a governance mechanism.
|
||||
@@ -1,2 +0,0 @@
|
||||
- SDK related specifications (ie. how multistore, signatures, etc. work).
|
||||
- Basecoin (SendTx)
|
||||
@@ -13,13 +13,13 @@ has to be created and the previous one rendered inactive.
|
||||
```go
|
||||
type DepositProcedure struct {
|
||||
MinDeposit sdk.Coins // Minimum deposit for a proposal to enter voting period.
|
||||
MaxDepositPeriod int64 // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
|
||||
MaxDepositPeriod time.Time // Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months
|
||||
}
|
||||
```
|
||||
|
||||
```go
|
||||
type VotingProcedure struct {
|
||||
VotingPeriod int64 // Length of the voting period. Initial value: 2 weeks
|
||||
VotingPeriod time.Time // Length of the voting period. Initial value: 2 weeks
|
||||
}
|
||||
```
|
||||
|
||||
@@ -28,7 +28,6 @@ type TallyingProcedure struct {
|
||||
Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
|
||||
Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
|
||||
GovernancePenalty sdk.Dec // Penalty if validator does not vote
|
||||
GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
|
||||
}
|
||||
```
|
||||
|
||||
@@ -97,10 +96,10 @@ type Proposal struct {
|
||||
Type ProposalType // Type of proposal. Initial set {PlainTextProposal, SoftwareUpgradeProposal}
|
||||
TotalDeposit sdk.Coins // Current deposit on this proposal. Initial value is set at InitialDeposit
|
||||
Deposits []Deposit // List of deposits on the proposal
|
||||
SubmitBlock int64 // Height of the block where TxGovSubmitProposal was included
|
||||
SubmitTime time.Time // Time of the block where TxGovSubmitProposal was included
|
||||
Submitter sdk.Address // Address of the submitter
|
||||
|
||||
VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
|
||||
VotingStartTime time.Time // Time of the block where MinDeposit was reached. time.Time{} if MinDeposit is not reached
|
||||
CurrentStatus ProposalStatus // Current status of the proposal
|
||||
|
||||
YesVotes sdk.Dec
|
||||
@@ -137,7 +136,7 @@ For pseudocode purposes, here are the two function we will use to read or write
|
||||
* `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the
|
||||
`ProposalIDs` of proposals that reached `MinDeposit`. Each round, the oldest
|
||||
element of `ProposalProcessingQueue` is checked during `BeginBlock` to see if
|
||||
`CurrentBlock == VotingStartBlock + activeProcedure.VotingPeriod`. If it is,
|
||||
`CurrentTime == VotingStartTime + activeProcedure.VotingPeriod`. If it is,
|
||||
then the application tallies the votes, compute the votes of each validator and checks if every validator in the valdiator set have voted
|
||||
and, if not, applies `GovernancePenalty`. If the proposal is accepted, deposits are refunded.
|
||||
After that proposal is ejected from `ProposalProcessingQueue` and the next element of the queue is evaluated.
|
||||
@@ -159,7 +158,7 @@ And the pseudocode for the `ProposalProcessingQueue`:
|
||||
proposal = load(Governance, <proposalID|'proposal'>) // proposal is a const key
|
||||
votingProcedure = load(GlobalParams, 'VotingProcedure')
|
||||
|
||||
if (CurrentBlock == proposal.VotingStartBlock + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive)
|
||||
if (CurrentTime == proposal.VotingStartTime + votingProcedure.VotingPeriod && proposal.CurrentStatus == ProposalStatusActive)
|
||||
|
||||
// End of voting period, tally
|
||||
|
||||
@@ -192,14 +191,10 @@ And the pseudocode for the `ProposalProcessingQueue`:
|
||||
|
||||
tallyingProcedure = load(GlobalParams, 'TallyingProcedure')
|
||||
|
||||
// Slash validators that did not vote, or update tally if they voted
|
||||
// Update tally if validator voted they voted
|
||||
for each validator in validators
|
||||
if (validator.bondHeight < CurrentBlock - tallyingProcedure.GracePeriod)
|
||||
// only slash if validator entered validator set before grace period
|
||||
if (!tmpValMap(validator).HasVoted)
|
||||
slash validator by tallyingProcedure.GovernancePenalty
|
||||
else
|
||||
proposal.updateTally(tmpValMap(validator).Vote, (validator.TotalShares - tmpValMap(validator).Minus))
|
||||
if tmpValMap(validator).HasVoted
|
||||
proposal.updateTally(tmpValMap(validator).Vote, (validator.TotalShares - tmpValMap(validator).Minus))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -43,12 +43,13 @@ type Params struct {
|
||||
Validators are identified according to the `OperatorAddr`, an SDK validator
|
||||
address for the operator of the validator.
|
||||
|
||||
Validators also have a `ConsPubKey`, the public key of the validator.
|
||||
|
||||
Validators are indexed in the store using the following maps:
|
||||
Validators also have a `ConsPubKey`, the public key of the validator used in
|
||||
Tendermint consensus. The validator can be retrieved from it's `ConsPubKey`
|
||||
once it can be converted into the corresponding `ConsAddr`. Validators are
|
||||
indexed in the store using the following maps:
|
||||
|
||||
- Validators: `0x02 | OperatorAddr -> amino(validator)`
|
||||
- ValidatorsByPubKey: `0x03 | ConsPubKey -> OperatorAddr`
|
||||
- ValidatorsByConsAddr: `0x03 | ConsAddr -> OperatorAddr`
|
||||
- ValidatorsByPower: `0x05 | power | blockHeight | blockTx -> OperatorAddr`
|
||||
|
||||
`Validators` is the primary index - it ensures that each operator can have only one
|
||||
@@ -69,7 +70,7 @@ validator.
|
||||
|
||||
```golang
|
||||
type Validator struct {
|
||||
ConsensusPubKey crypto.PubKey // Tendermint consensus pubkey of validator
|
||||
ConsPubKey crypto.PubKey // Tendermint consensus pubkey of validator
|
||||
Jailed bool // has the validator been jailed?
|
||||
|
||||
Status sdk.BondStatus // validator status (bonded/unbonding/unbonded)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user