simple distribution overview
This commit is contained in:
parent
7ba479e57a
commit
97397e63da
|
@ -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)
|
||||
```
|
|
@ -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.
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
# Distribution
|
||||
|
||||
## Overview
|
||||
|
||||
This _simple_ distribution mechanism describes a functional way to passively
|
||||
distribute rewards between validator and delegators. Note that this mechanism does
|
||||
not distribute funds in as precisely as active reward distribution and will therefor
|
||||
be upgraded in the future.
|
||||
|
||||
The mechanism operates as follows. Collected rewards are pooled globally and
|
||||
divided out passively to validators and delegators. Each validator has the
|
||||
opportunity to charge commission to the delegators on the rewards collected on
|
||||
behalf of the delegators by the validators. Fees are paid directly into a
|
||||
global reward pool, and validator proposer-reward pool. Due to the nature of
|
||||
passive accounting whenever changes to parameters which affect the rate of reward
|
||||
distribution occurs, withdrawal of rewards 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 rewards must occur (as the rules for lazy accounting
|
||||
change),
|
||||
- a validator chooses to change the commission on rewards, all accumulated
|
||||
commission rewards must be simultaneously withdrawn.
|
||||
|
||||
The above scenarios are covered in `triggers.md`.
|
||||
|
||||
The distribution mechanism outlines herein is used to lazily distribute the
|
||||
following rewards 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.
|
||||
|
||||
Within this spec
|
||||
|
||||
As a part of the lazy computations, each validator and delegator holds an
|
||||
accumulation term which is used to estimate what their approximate fair portion
|
||||
of tokens held in the global pool is owed to them. This approximation of owed
|
||||
rewards would be equivalent to the active distribution under the situation that
|
||||
there was a constant flow of incoming reward tokens every block. Because this
|
||||
is not the case, the approximation of owed rewards will deviate from the active
|
||||
distribution based on fluctuations of incoming reward tokens as well as timing
|
||||
of reward withdrawal by other delegators and validators from the reward pool.
|
||||
|
||||
|
||||
## 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 reward distribution calculation would become very large as the Atom
|
||||
portion for each delegator would change each block making a withdrawal of rewards
|
||||
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 rewards.
|
||||
|
|
@ -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
|
||||
}
|
||||
```
|
|
@ -0,0 +1,399 @@
|
|||
# Transactions
|
||||
|
||||
## TxWithdrawDelegation
|
||||
|
||||
When a delegator wishes to withdraw their transaction fees it must send
|
||||
`TxWithdrawDelegation`. Note that parts of this transaction logic are also
|
||||
triggered each with any change in individual delegations, such as an unbond,
|
||||
redelegation, or delegation of additional tokens to a specific validator.
|
||||
|
||||
Each time a withdrawal is made by a recipient the adjustment term must be
|
||||
modified for each block with a change in distributors shares since the time of
|
||||
last withdrawal. This is accomplished by iterating over all relevant
|
||||
`PowerChange`'s stored in distribution state.
|
||||
|
||||
|
||||
```golang
|
||||
type TxWithdrawDelegation struct {
|
||||
delegatorAddr sdk.AccAddress
|
||||
withdrawAddr sdk.AccAddress // address to make the withdrawal to
|
||||
}
|
||||
|
||||
func WithdrawDelegator(delegatorAddr, withdrawAddr sdk.AccAddress)
|
||||
entitlement = GetDelegatorEntitlement(delegatorAddr)
|
||||
AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal())
|
||||
|
||||
func GetDelegatorEntitlement(delegatorAddr sdk.AccAddress) DecCoins
|
||||
|
||||
// compile all the distribution scenarios
|
||||
delegations = GetDelegations(delegatorAddr)
|
||||
DelDistr = GetDelegationDistribution(delegation.DelegatorAddr,
|
||||
delegation.ValidatorAddr)
|
||||
pcs = GetPowerChanges(DelDistr.WithdrawalHeight)
|
||||
|
||||
// update all adjustment factors for each delegation since last withdrawal
|
||||
for pc = range pcs
|
||||
for delegation = range delegations
|
||||
DelDistr = GetDelegationDistribution(delegation.DelegatorAddr,
|
||||
delegation.ValidatorAddr)
|
||||
pc.ProcessPowerChangeDelegation(delegation, DelDistr)
|
||||
|
||||
// collect all entitled fees
|
||||
entitlement = 0
|
||||
for delegation = range delegations
|
||||
global = GetGlobal()
|
||||
pool = GetPool()
|
||||
DelDistr = GetDelegationDistribution(delegation.DelegatorAddr,
|
||||
delegation.ValidatorAddr)
|
||||
ValDistr = GetValidatorDistribution(delegation.ValidatorAddr)
|
||||
validator = GetValidator(delegation.ValidatorAddr)
|
||||
|
||||
scenerio1 = NewDelegationFromGlobalPool(delegation, validator,
|
||||
pool, global, ValDistr, DelDistr)
|
||||
scenerio2 = NewDelegationFromProvisionPool(delegation, validator,
|
||||
ValDistr, DelDistr)
|
||||
entitlement += scenerio1.WithdrawalEntitlement()
|
||||
entitlement += scenerio2.WithdrawalEntitlement()
|
||||
|
||||
return entitlement
|
||||
|
||||
func (pc PowerChange) ProcessPowerChangeDelegation(delegation sdk.Delegation,
|
||||
DelDistr DelegationDistribution)
|
||||
|
||||
// get the historical scenarios
|
||||
scenario1 = pc.DelegationFromGlobalPool(delegation, DelDistr)
|
||||
scenario2 = pc.DelegationFromProvisionPool(delegation, DelDistr)
|
||||
|
||||
// process the adjustment factors
|
||||
scenario1.UpdateAdjustmentForPowerChange(pc.Height)
|
||||
scenario2.UpdateAdjustmentForPowerChange(pc.Height)
|
||||
```
|
||||
|
||||
## TxWithdrawValidator
|
||||
|
||||
When a validator wishes to withdraw their transaction fees it must send
|
||||
`TxWithdrawDelegation`. Note that parts of this transaction logic is also
|
||||
triggered each with any change in individual delegations, such as an unbond,
|
||||
redelegation, or delegation of additional tokens to a specific validator. This
|
||||
transaction withdraws the validators commission rewards, as well as any rewards
|
||||
earning on their self-delegation.
|
||||
|
||||
```golang
|
||||
type TxWithdrawValidator struct {
|
||||
ownerAddr sdk.AccAddress // validator address to withdraw from
|
||||
withdrawAddr sdk.AccAddress // address to make the withdrawal to
|
||||
}
|
||||
|
||||
func WithdrawalValidator(ownerAddr, withdrawAddr sdk.AccAddress)
|
||||
|
||||
// update the delegator adjustment factors and also withdrawal delegation fees
|
||||
entitlement = GetDelegatorEntitlement(ownerAddr)
|
||||
|
||||
// update the validator adjustment factors for commission
|
||||
ValDistr = GetValidatorDistribution(ownerAddr.ValidatorAddr)
|
||||
pcs = GetPowerChanges(ValDistr.CommissionWithdrawalHeight)
|
||||
for pc = range pcs
|
||||
pc.ProcessPowerChangeCommission()
|
||||
|
||||
// withdrawal validator commission rewards
|
||||
global = GetGlobal()
|
||||
pool = GetPool()
|
||||
ValDistr = GetValidatorDistribution(delegation.ValidatorAddr)
|
||||
validator = GetValidator(delegation.ValidatorAddr)
|
||||
|
||||
scenerio1 = NewCommissionFromGlobalPool(validator,
|
||||
pool, global, ValDistr)
|
||||
scenerio2 = CommissionFromProposerPool(validator, ValDistr)
|
||||
entitlement += scenerio1.WithdrawalEntitlement()
|
||||
entitlement += scenerio2.WithdrawalEntitlement()
|
||||
|
||||
AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal())
|
||||
|
||||
func (pc PowerChange) ProcessPowerChangeCommission()
|
||||
|
||||
// get the historical scenarios
|
||||
scenario1 = pc.CommissionFromGlobalPool()
|
||||
scenario2 = pc.CommissionFromProposerPool()
|
||||
|
||||
// process the adjustment factors
|
||||
scenario1.UpdateAdjustmentForPowerChange(pc.Height)
|
||||
scenario2.UpdateAdjustmentForPowerChange(pc.Height)
|
||||
```
|
||||
|
||||
## Common Calculations
|
||||
|
||||
### Distribution scenario
|
||||
|
||||
A common form of abstracted calculations exists between validators and
|
||||
delegations attempting to withdrawal their rewards, either from `Global.Pool`
|
||||
or from `ValidatorDistribution.ProposerPool`. With the following interface
|
||||
fulfilled the entitled fees for the various scenarios can be calculated.
|
||||
|
||||
```golang
|
||||
type DistributionScenario interface {
|
||||
DistributorTokens() DecCoins // current tokens from distributor
|
||||
DistributorCumulativeTokens() DecCoins // total tokens ever received
|
||||
DistributorPrevReceivedTokens() DecCoins // last value of tokens received
|
||||
DistributorShares() sdk.Dec // current shares
|
||||
DistributorPrevShares() sdk.Dec // shares last block
|
||||
|
||||
RecipientAdjustment() sdk.Dec
|
||||
RecipientShares() sdk.Dec // current shares
|
||||
RecipientPrevShares() sdk.Dec // shares last block
|
||||
|
||||
ModifyAdjustments(withdrawal sdk.Dec) // proceedure to modify adjustment factors
|
||||
}
|
||||
```
|
||||
|
||||
#### Entitled reward from distribution scenario
|
||||
|
||||
The entitlement to the distributor's tokens held can be accounted for lazily.
|
||||
To begin this calculation we must determine the recipient's _simple pool_ and
|
||||
_projected pool_. The simple pool represents a lazy accounting of what a
|
||||
recipient's entitlement to the distributor's tokens would be if all recipients
|
||||
for that distributor had static shares (equal to the current shares), and no
|
||||
recipients had ever withdrawn their entitled rewards. The projected pool
|
||||
represents the anticipated recipient's entitlement to the distributors tokens
|
||||
based on the current blocks token input (for example fees reward received) to
|
||||
the distributor, and the distributor's tokens and shares of the previous block
|
||||
assuming that neither had changed in the current block. Using the simple and
|
||||
projected pools we can determine all cumulative changes which have taken place
|
||||
outside of the recipient and adjust the recipient's _adjustment factor_ to
|
||||
account for these changes and ultimately keep track of the correct entitlement
|
||||
to the distributors tokens.
|
||||
|
||||
```
|
||||
func (d DistributionScenario) RecipientCount(height int64) sdk.Dec
|
||||
return v.RecipientShares() * height
|
||||
|
||||
func (d DistributionScenario) GlobalCount(height int64) sdk.Dec
|
||||
return d.DistributorShares() * height
|
||||
|
||||
func (d DistributionScenario) SimplePool() DecCoins
|
||||
return d.RecipientCount() / d.GlobalCount() * d.DistributorCumulativeTokens
|
||||
|
||||
func (d DistributionScenario) ProjectedPool(height int64) DecCoins
|
||||
return d.RecipientPrevShares() * (height-1)
|
||||
/ (d.DistributorPrevShares() * (height-1))
|
||||
* d.DistributorCumulativeTokens
|
||||
+ d.RecipientShares() / d.DistributorShares()
|
||||
* d.DistributorPrevReceivedTokens()
|
||||
```
|
||||
|
||||
The `DistributionScenario` _adjustment_ terms account for changes in
|
||||
recipient/distributor shares and recipient withdrawals. The adjustment factor
|
||||
must be modified whenever the recipient withdraws from the distributor or the
|
||||
distributor's/recipient's shares are changed.
|
||||
- When the shares of the recipient is changed the adjustment factor is
|
||||
increased/decreased by the difference between the _simple_ and _projected_
|
||||
pools. In other words, the cumulative difference in the shares if the shares
|
||||
has been the new shares as opposed to the old shares for the entire duration of
|
||||
the blockchain up the previous block.
|
||||
- When a recipient makes a withdrawal the adjustment factor is increased by the
|
||||
withdrawal amount.
|
||||
|
||||
```
|
||||
func (d DistributionScenario) UpdateAdjustmentForPowerChange(height int64)
|
||||
simplePool = d.SimplePool()
|
||||
projectedPool = d.ProjectedPool(height)
|
||||
AdjustmentChange = simplePool - projectedPool
|
||||
if AdjustmentChange > 0
|
||||
d.ModifyAdjustments(AdjustmentChange)
|
||||
|
||||
func (d DistributionScenario) WithdrawalEntitlement() DecCoins
|
||||
entitlement = d.SimplePool() - d.RecipientAdjustment()
|
||||
d.ModifyAdjustments(entitlement)
|
||||
return entitlement
|
||||
```
|
||||
|
||||
### Distribution scenarios
|
||||
|
||||
Note that the distribution scenario structures are found in `state.md`.
|
||||
|
||||
#### Delegation's entitlement to Global.Pool
|
||||
|
||||
For delegations (including validator's self-delegation) all fees from fee pool
|
||||
are subject to commission rate from the owner of the validator. The global
|
||||
shares should be taken as true number of global bonded shares. The recipients
|
||||
shares should be taken as the bonded tokens less the validator's commission.
|
||||
|
||||
```
|
||||
type DelegationFromGlobalPool struct {
|
||||
DelegationShares sdk.Dec
|
||||
ValidatorCommission sdk.Dec
|
||||
ValidatorBondedTokens sdk.Dec
|
||||
ValidatorDelegatorShareExRate sdk.Dec
|
||||
PoolBondedTokens sdk.Dec
|
||||
Global Global
|
||||
ValDistr ValidatorDistribution
|
||||
DelDistr DelegatorDistribution
|
||||
}
|
||||
|
||||
func (d DelegationFromGlobalPool) DistributorTokens() DecCoins
|
||||
return d.Global.Pool
|
||||
|
||||
func (d DelegationFromGlobalPool) DistributorCumulativeTokens() DecCoins
|
||||
return d.Global.EverReceivedPool
|
||||
|
||||
func (d DelegationFromGlobalPool) DistributorPrevReceivedTokens() DecCoins
|
||||
return d.Global.PrevReceivedPool
|
||||
|
||||
func (d DelegationFromGlobalPool) DistributorShares() sdk.Dec
|
||||
return d.PoolBondedTokens
|
||||
|
||||
func (d DelegationFromGlobalPool) DistributorPrevShares() sdk.Dec
|
||||
return d.Global.PrevBondedTokens
|
||||
|
||||
func (d DelegationFromGlobalPool) RecipientShares() sdk.Dec
|
||||
return d.DelegationShares * d.ValidatorDelegatorShareExRate() *
|
||||
d.ValidatorBondedTokens() * (1 - d.ValidatorCommission)
|
||||
|
||||
func (d DelegationFromGlobalPool) RecipientPrevShares() sdk.Dec
|
||||
return d.DelDistr.PrevTokens
|
||||
|
||||
func (d DelegationFromGlobalPool) RecipientAdjustment() sdk.Dec
|
||||
return d.DelDistr.Adjustment
|
||||
|
||||
func (d DelegationFromGlobalPool) ModifyAdjustments(withdrawal sdk.Dec)
|
||||
d.ValDistr.Adjustment += withdrawal
|
||||
d.DelDistr.Adjustment += withdrawal
|
||||
d.global.Adjustment += withdrawal
|
||||
SetValidatorDistribution(d.ValDistr)
|
||||
SetDelegatorDistribution(d.DelDistr)
|
||||
SetGlobal(d.Global)
|
||||
```
|
||||
|
||||
#### Delegation's entitlement to ValidatorDistribution.ProposerPool
|
||||
|
||||
Delegations (including validator's self-delegation) are still subject
|
||||
commission on the rewards gained from the proposer pool. Global shares in this
|
||||
context is actually the validators total delegations shares. The recipient's
|
||||
shares is taken as the effective delegation shares less the validator's
|
||||
commission.
|
||||
|
||||
```
|
||||
type DelegationFromProposerPool struct {
|
||||
DelegationShares sdk.Dec
|
||||
ValidatorCommission sdk.Dec
|
||||
ValidatorDelegatorShares sdk.Dec
|
||||
ValDistr ValidatorDistribution
|
||||
DelDistr DelegatorDistribution
|
||||
}
|
||||
|
||||
func (d DelegationFromProposerPool) DistributorTokens() DecCoins
|
||||
return d.ValDistr.ProposerPool
|
||||
|
||||
func (d DelegationFromProposerPool) DistributorCumulativeTokens() DecCoins
|
||||
return d.ValDistr.EverReceivedProposerReward
|
||||
|
||||
func (d DelegationFromProposerPool) DistributorPrevReceivedTokens() DecCoins
|
||||
return d.ValDistr.PrevReceivedProposerReward
|
||||
|
||||
func (d DelegationFromProposerPool) DistributorShares() sdk.Dec
|
||||
return d.ValidatorDelegatorShares
|
||||
|
||||
func (d DelegationFromProposerPool) DistributorPrevShares() sdk.Dec
|
||||
return d.ValDistr.PrevDelegatorShares
|
||||
|
||||
func (d DelegationFromProposerPool) RecipientShares() sdk.Dec
|
||||
return d.DelegationShares * (1 - d.ValidatorCommission)
|
||||
|
||||
func (d DelegationFromProposerPool) RecipientPrevShares() sdk.Dec
|
||||
return d.DelDistr.PrevShares
|
||||
|
||||
func (d DelegationFromProposerPool) RecipientAdjustment() sdk.Dec
|
||||
return d.DelDistr.AdjustmentProposer
|
||||
|
||||
func (d DelegationFromProposerPool) ModifyAdjustments(withdrawal sdk.Dec)
|
||||
d.ValDistr.AdjustmentProposer += withdrawal
|
||||
d.DelDistr.AdjustmentProposer += withdrawal
|
||||
SetValidatorDistribution(d.ValDistr)
|
||||
SetDelegatorDistribution(d.DelDistr)
|
||||
```
|
||||
|
||||
#### Validators's commission entitlement to Global.Pool
|
||||
|
||||
Similar to a delegator's entitlement, but with recipient shares based on the
|
||||
commission portion of bonded tokens.
|
||||
|
||||
```
|
||||
type CommissionFromGlobalPool struct {
|
||||
ValidatorBondedTokens sdk.Dec
|
||||
ValidatorCommission sdk.Dec
|
||||
PoolBondedTokens sdk.Dec
|
||||
Global Global
|
||||
ValDistr ValidatorDistribution
|
||||
}
|
||||
|
||||
func (c CommissionFromGlobalPool) DistributorTokens() DecCoins
|
||||
return c.Global.Pool
|
||||
|
||||
func (c CommissionFromGlobalPool) DistributorCumulativeTokens() DecCoins
|
||||
return c.Global.EverReceivedPool
|
||||
|
||||
func (c CommissionFromGlobalPool) DistributorPrevReceivedTokens() DecCoins
|
||||
return c.Global.PrevReceivedPool
|
||||
|
||||
func (c CommissionFromGlobalPool) DistributorShares() sdk.Dec
|
||||
return c.PoolBondedTokens
|
||||
|
||||
func (c CommissionFromGlobalPool) DistributorPrevShares() sdk.Dec
|
||||
return c.Global.PrevBondedTokens
|
||||
|
||||
func (c CommissionFromGlobalPool) RecipientShares() sdk.Dec
|
||||
return c.ValidatorBondedTokens() * c.ValidatorCommission
|
||||
|
||||
func (c CommissionFromGlobalPool) RecipientPrevShares() sdk.Dec
|
||||
return c.ValDistr.PrevBondedTokens * c.ValidatorCommission
|
||||
|
||||
func (c CommissionFromGlobalPool) RecipientAdjustment() sdk.Dec
|
||||
return c.ValDistr.Adjustment
|
||||
|
||||
func (c CommissionFromGlobalPool) ModifyAdjustments(withdrawal sdk.Dec)
|
||||
c.ValDistr.Adjustment += withdrawal
|
||||
c.Global.Adjustment += withdrawal
|
||||
SetValidatorDistribution(c.ValDistr)
|
||||
SetGlobal(c.Global)
|
||||
```
|
||||
|
||||
#### Validators's commission entitlement to ValidatorDistribution.ProposerPool
|
||||
|
||||
Similar to a delegators entitlement to the proposer pool, but with recipient
|
||||
shares based on the commission portion of the total delegator shares.
|
||||
|
||||
```
|
||||
type CommissionFromProposerPool struct {
|
||||
ValidatorDelegatorShares sdk.Dec
|
||||
ValidatorCommission sdk.Dec
|
||||
ValDistr ValidatorDistribution
|
||||
}
|
||||
|
||||
func (c CommissionFromProposerPool) DistributorTokens() DecCoins
|
||||
return c.ValDistr.ProposerPool
|
||||
|
||||
func (c CommissionFromProposerPool) DistributorCumulativeTokens() DecCoins
|
||||
return c.ValDistr.EverReceivedProposerReward
|
||||
|
||||
func (c CommissionFromProposerPool) DistributorPrevReceivedTokens() DecCoins
|
||||
return c.ValDistr.PrevReceivedProposerReward
|
||||
|
||||
func (c CommissionFromProposerPool) DistributorShares() sdk.Dec
|
||||
return c.ValidatorDelegatorShares
|
||||
|
||||
func (c CommissionFromProposerPool) DistributorPrevShares() sdk.Dec
|
||||
return c.ValDistr.PrevDelegatorShares
|
||||
|
||||
func (c CommissionFromProposerPool) RecipientShares() sdk.Dec
|
||||
return c.ValidatorDelegatorShares * (c.ValidatorCommission)
|
||||
|
||||
func (c CommissionFromProposerPool) RecipientPrevShares() sdk.Dec
|
||||
return c.ValDistr.PrevDelegatorShares * (c.ValidatorCommission)
|
||||
|
||||
func (c CommissionFromProposerPool) RecipientAdjustment() sdk.Dec
|
||||
return c.ValDistr.AdjustmentProposer
|
||||
|
||||
func (c CommissionFromProposerPool) ModifyAdjustments(withdrawal sdk.Dec)
|
||||
c.ValDistr.AdjustmentProposer += withdrawal
|
||||
SetValidatorDistribution(c.ValDistr)
|
||||
```
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# Triggers
|
||||
|
||||
## Create validator distribution
|
||||
|
||||
- triggered-by: validator entering bonded validator group (`stake.bondValidator()`)
|
||||
|
||||
Whenever a new validator is added to the Tendermint validator set they are
|
||||
entitled to begin earning rewards of atom provisions and fees. At this point
|
||||
`ValidatorDistribution.Pool()` must be zero (as the validator has not yet
|
||||
earned any rewards) meaning that the initial value for `validator.Adjustment`
|
||||
must be set to the value of `validator.SimplePool()` for the height which the
|
||||
validator is added on the validator set.
|
||||
|
||||
## Create or modify delegation distribution
|
||||
|
||||
- triggered-by: `stake.TxDelegate`, `stake.TxBeginRedelegate`, `stake.TxBeginUnbonding`
|
||||
|
||||
The pool of a new delegator bond will be 0 for the height at which the bond was
|
||||
added. This is achieved by setting `DelegationDistribution.WithdrawalHeight` to
|
||||
the height which the bond was added. Additionally the `AdjustmentPool` and
|
||||
`AdjustmentProposerPool` must be set to the equivalent values of
|
||||
`DelegationDistribution.SimplePool()` and
|
||||
`DelegationDistribution.SimpleProposerPool()` for the height of delegation.
|
||||
|
||||
## Commission rate change
|
||||
|
||||
- triggered-by: `stake.TxEditValidator`
|
||||
|
||||
If a validator changes its commission rate, all commission on fees must be
|
||||
simultaneously withdrawn using the transaction `TxWithdrawValidator`
|
||||
|
Loading…
Reference in New Issue