-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge PR #1702: lamborghini distribution & inflation spec upgrade
- Loading branch information
1 parent
45a010b
commit 7fb626f
Showing
22 changed files
with
742 additions
and
320 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# End Block | ||
|
||
At each endblock, the fees received are sorted to the proposer, community fund, | ||
and global pool. When the validator is the proposer of the round, that | ||
validator (and their delegators) receives between 1% and 5% of fee rewards, the | ||
reserve tax is then charged, then the remainder is distributed proportionally | ||
by voting power to all bonded validators independent of whether they voted | ||
(social distribution). Note the social distribution is applied to proposer | ||
validator in addition to the proposer reward. | ||
|
||
The amount of proposer reward is calculated from pre-commits Tendermint | ||
messages in order to incentivize validators to wait and include additional | ||
pre-commits in the block. All provision rewards are added to a provision reward | ||
pool which validator holds individually | ||
(`ValidatorDistribution.ProvisionsRewardPool`). | ||
|
||
``` | ||
func SortFees(feesCollected sdk.Coins, global Global, proposer ValidatorDistribution, | ||
sumPowerPrecommitValidators, totalBondedTokens, communityTax sdk.Dec) | ||
feesCollectedDec = MakeDecCoins(feesCollected) | ||
proposerReward = feesCollectedDec * (0.01 + 0.04 | ||
* sumPowerPrecommitValidators / totalBondedTokens) | ||
proposer.ProposerPool += proposerReward | ||
communityFunding = feesCollectedDec * communityTax | ||
global.CommunityFund += communityFunding | ||
poolReceived = feesCollectedDec - proposerReward - communityFunding | ||
global.Pool += poolReceived | ||
global.EverReceivedPool += poolReceived | ||
global.LastReceivedPool = poolReceived | ||
SetValidatorDistribution(proposer) | ||
SetGlobal(global) | ||
``` |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
## Future Improvements | ||
|
||
### Power Change | ||
|
||
Within the current implementation all power changes ever made are indefinitely stored | ||
within the current state. In the future this state should be trimmed on an epoch basis. Delegators | ||
which will have not withdrawn their fees will be penalized in some way, depending on what is | ||
computationally feasible this may include: | ||
- burning non-withdrawn fees | ||
- requiring more expensive withdrawal costs which include proofs from archive nodes of historical state | ||
|
||
In addition or as an alternative it may make sense to implement a "rolling" epoch which cycles through | ||
all the delegators in small groups (for example 5 delegators per block) and just runs the withdrawal transaction | ||
at standard rates and takes transaction fees from the withdrawal amount. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Distribution | ||
|
||
## Overview | ||
|
||
Collected fees are pooled globally and divided out passively to validators and | ||
delegators. Each validator has the opportunity to charge commission to the | ||
delegators on the fees collected on behalf of the delegators by the validators. | ||
Fees are paid directly into a global fee pool, and validator proposer-reward | ||
pool. Due to the nature of passive accounting whenever changes to parameters | ||
which affect the rate of fee distribution occurs, withdrawal of fees must also | ||
occur when: | ||
|
||
- withdrawing one must withdrawal the maximum amount they are entitled | ||
too, leaving nothing in the pool, | ||
- bonding, unbonding, or re-delegating tokens to an existing account a | ||
full withdrawal of the fees must occur (as the rules for lazy accounting | ||
change), | ||
- a validator chooses to change the commission on fees, all accumulated | ||
commission fees must be simultaneously withdrawn. | ||
|
||
The above scenarios are covered in `triggers.md`. | ||
|
||
The distribution mechanism outlines herein is used to lazily distribute the | ||
following between validators and associated delegators: | ||
- multi-token fees to be socially distributed, | ||
- proposer reward pool, | ||
- inflated atom provisions, and | ||
- validator commission on all rewards earned by their delegators stake | ||
|
||
Fees are pooled within a global pool, as well as validator specific | ||
proposer-reward pools. The mechanisms used allow for validators and delegators | ||
to independently and lazily withdrawn their rewards. As a part of the lazy | ||
computations adjustment factors must be maintained for each validator and | ||
delegator to determine the true proportion of fees in each pool which they are | ||
entitled too. Adjustment factors are updated every time a validator or | ||
delegator's voting power changes. Validators and delegators must withdraw all | ||
fees they are entitled too before they can change their portion of bonded | ||
Atoms. | ||
|
||
## Affect on Staking | ||
|
||
|
||
Charging commission on Atom provisions while also allowing for Atom-provisions | ||
to be auto-bonded (distributed directly to the validators bonded stake) is | ||
problematic within DPoS. Fundamentally these two mechnisms are mutually | ||
exclusive. If there are atoms commissions and auto-bonding Atoms, the portion | ||
of Atoms the fee distribution calculation would become very large as the Atom | ||
portion for each delegator would change each block making a withdrawal of fees | ||
for a delegator require a calculation for every single block since the last | ||
withdrawal. In conclusion we can only have atom commission and unbonded atoms | ||
provisions, or bonded atom provisions with no Atom commission, and we elect to | ||
implement the former. Stakeholders wishing to rebond their provisions may elect | ||
to set up a script to periodically withdraw and rebond fees. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
## State | ||
|
||
### Global | ||
|
||
All globally tracked parameters for distribution are stored within | ||
`Global`. Rewards are collected and added to the reward pool and | ||
distributed to validators/delegators from here. | ||
|
||
Note that the reward pool holds decimal coins (`DecCoins`) to allow | ||
for fractions of coins to be received from operations like inflation. | ||
When coins are distributed from the pool they are truncated back to | ||
`sdk.Coins` which are non-decimal. | ||
|
||
- Global: `0x00 -> amino(global)` | ||
|
||
```golang | ||
// coins with decimal | ||
type DecCoins []DecCoin | ||
|
||
type DecCoin struct { | ||
Amount sdk.Dec | ||
Denom string | ||
} | ||
|
||
type Global struct { | ||
PrevBondedTokens sdk.Dec // bonded token amount for the global pool on the previous block | ||
Adjustment sdk.Dec // global adjustment factor for lazy calculations | ||
Pool DecCoins // funds for all validators which have yet to be withdrawn | ||
PrevReceivedPool DecCoins // funds added to the pool on the previous block | ||
EverReceivedPool DecCoins // total funds ever added to the pool | ||
CommunityFund DecCoins // pool for community funds yet to be spent | ||
} | ||
``` | ||
|
||
### Validator Distribution | ||
|
||
Validator distribution information for the relevant validator is updated each time: | ||
1. delegation amount to a validator are updated, | ||
2. a validator successfully proposes a block and receives a reward, | ||
3. any delegator withdraws from a validator, or | ||
4. the validator withdraws it's commission. | ||
|
||
- ValidatorDistribution: `0x02 | ValOwnerAddr -> amino(validatorDistribution)` | ||
|
||
```golang | ||
type ValidatorDistribution struct { | ||
CommissionWithdrawalHeight int64 // last time this validator withdrew commission | ||
Adjustment sdk.Dec // global pool adjustment factor | ||
ProposerAdjustment DecCoins // proposer pool adjustment factor | ||
ProposerPool DecCoins // reward pool collected from being the proposer | ||
EverReceivedProposerReward DecCoins // all rewards ever collected from being the proposer | ||
PrevReceivedProposerReward DecCoins // previous rewards collected from being the proposer | ||
PrevBondedTokens sdk.Dec // bonded token amount on the previous block | ||
PrevDelegatorShares sdk.Dec // amount of delegator shares for the validator on the previous block | ||
} | ||
``` | ||
|
||
### Delegation Distribution | ||
|
||
Each delegation holds multiple adjustment factors to specify its entitlement to | ||
the rewards from a validator. `AdjustmentPool` is used to passively calculate | ||
each bonds entitled fees from the `RewardPool`. `AdjustmentPool` is used to | ||
passively calculate each bonds entitled fees from | ||
`ValidatorDistribution.ProposerRewardPool` | ||
|
||
- DelegatorDistribution: ` 0x02 | DelegatorAddr | ValOwnerAddr -> amino(delegatorDist)` | ||
|
||
```golang | ||
type DelegatorDist struct { | ||
WithdrawalHeight int64 // last time this delegation withdrew rewards | ||
Adjustment sdk.Dec // fee provisioning adjustment factor | ||
AdjustmentProposer DecCoins // proposers pool adjustment factor | ||
PrevTokens sdk.Dec // bonded tokens held by the delegation on the previous block | ||
PrevShares sdk.Dec // delegator shares held by the delegation on the previous block | ||
} | ||
``` | ||
|
||
### Power Change | ||
|
||
Every instance that the voting power changes, information about the state of | ||
the validator set during the change must be recorded as a `PowerChange` for | ||
other validators to run through. Each power change is indexed by its block | ||
height. | ||
|
||
- PowerChange: `0x03 | amino(Height) -> amino(validatorDist)` | ||
|
||
```golang | ||
type PowerChange struct { | ||
Height int64 // block height at change | ||
ValidatorBondedTokens sdk.Dec // following used to create distribution scenarios | ||
ValidatorDelegatorShares sdk.Dec | ||
ValidatorDelegatorShareExRate sdk.Dec | ||
ValidatorCommission sdk.Dec | ||
PoolBondedTokens sdk.Dec | ||
Global Global | ||
ValDistr ValidatorDistribution | ||
DelegationShares sdk.Dec | ||
DelDistr DelegatorDistribution | ||
} | ||
``` |
Oops, something went wrong.