From b32285ec3b11aea53beb79d5fcd4c2488881d038 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Thu, 23 Aug 2018 03:19:21 -0400 Subject: [PATCH] commission actively calculated, withdrawDelegationReward Tx --- docs/spec/distribution/end_block.md | 12 ++-- docs/spec/distribution/state.md | 25 +------ docs/spec/distribution/transactions.md | 92 +++++++++++++++----------- 3 files changed, 64 insertions(+), 65 deletions(-) diff --git a/docs/spec/distribution/end_block.md b/docs/spec/distribution/end_block.md index 19c9e83021..952d1832ac 100644 --- a/docs/spec/distribution/end_block.md +++ b/docs/spec/distribution/end_block.md @@ -1,6 +1,6 @@ # End Block -At each endblock, the fees received are sorted to the proposer, community fund, +At each endblock, the fees received are allocated 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 community tax is then charged, then the remainder is distributed @@ -15,13 +15,17 @@ pool which validator holds individually (`ValidatorDistribution.ProvisionsRewardPool`). ``` -func SortFees(feesCollected sdk.Coins, global Global, proposer ValidatorDistribution, - sumPowerPrecommitValidators, totalBondedTokens, communityTax sdk.Dec) +func AllocateFees(feesCollected sdk.Coins, global Global, proposer ValidatorDistribution, + sumPowerPrecommitValidators, totalBondedTokens, communityTax, + proposerCommissionRate sdk.Dec) feesCollectedDec = MakeDecCoins(feesCollected) proposerReward = feesCollectedDec * (0.01 + 0.04 * sumPowerPrecommitValidators / totalBondedTokens) - proposer.ProposerPool += proposerReward + + commission = proposerReward * proposerCommissionRate + proposer.PoolCommission += commission + proposer.Pool += proposerReward - commission communityFunding = feesCollectedDec * communityTax global.CommunityFund += communityFunding diff --git a/docs/spec/distribution/state.md b/docs/spec/distribution/state.md index 7dc011e957..3e3669789a 100644 --- a/docs/spec/distribution/state.md +++ b/docs/spec/distribution/state.md @@ -42,10 +42,9 @@ Validator distribution information for the relevant validator is updated each ti ```golang type ValidatorDistInfo struct { - CommissionWithdrawalHeight int64 // last height this validator withdrew commission - GlobalWithdrawalHeight int64 // last height this validator withdrew from the global pool - Pool DecCoins // reward pool collected held within this validator (includes proposer rewards) + Pool DecCoins // rewards owed to delegators, commission has already been charged (includes proposer reward) + PoolCommission DecCoins // commission collected by this validator (pending withdrawal) TotalDelAccumUpdateHeight int64 // last height which the total delegator accum was updated TotalDelAccum sdk.Dec // total proposer pool accumulation factor held by delegators @@ -67,23 +66,3 @@ type DelegatorDistInfo struct { WithdrawalHeight int64 // last time this delegation withdrew rewards } ``` - -### Validator Update - -Every instance that a validator: - - enters into the bonded state, - - leaves the bonded state, - - is slashed, or - - changes its commission rate, - -information about the state change to each validator must be recorded as a `ValidatorUpdate`. -Each power change is indexed by validator and its block height. - - - ValidatorUpdate: `0x03 | ValOperatorAddr | amino(Height) -> amino(ValidatorUpdate)` - -```golang -type ValidatorUpdate struct { - Height int64 // block height of update - OldCommissionRate sdk.Dec // commission rate at this height -} -``` diff --git a/docs/spec/distribution/transactions.md b/docs/spec/distribution/transactions.md index 82f9e84f76..2ed12d2c32 100644 --- a/docs/spec/distribution/transactions.md +++ b/docs/spec/distribution/transactions.md @@ -1,9 +1,9 @@ # Transactions -## TxWithdrawDelegation +## TxWithdrawDelegationRewards When a delegator wishes to withdraw their rewards it must send -`TxWithdrawDelegation`. Note that parts of this transaction logic are also +`TxWithdrawDelegationRewards`. 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. @@ -16,7 +16,7 @@ type TxWithdrawDelegationRewards struct { func WithdrawDelegationRewards(delegatorAddr, withdrawAddr sdk.AccAddress) height = GetHeight() withdraw = GetDelegatorAllWithdraws(delegatorAddr, height) - AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoins @@ -33,15 +33,6 @@ func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoi valInfo = GetValidatorDistInfo(delegation.ValidatorAddr) validator = GetValidator(delegation.ValidatorAddr) - // get all commission rate changes since last withdraw - vus = GetValidatorUpdates(delegation.ValidatorAddr, delInfo.WithdrawalHeight) - - for vu = range vus { - global, diWithdraw = delInfo.WithdrawRewards(global, valInfo, vu.Height, pool.BondedTokens, - validator.Tokens, validator.DelegatorShares, vu.OldCommissionRate) - withdraw += diWithdraw - } - global, diWithdraw = delInfo.WithdrawRewards(global, valInfo, height, pool.BondedTokens, validator.Tokens, validator.DelegatorShares, validator.Commission) withdraw += diWithdraw @@ -50,7 +41,38 @@ func GetDelegatorAllWithdraws(delegatorAddr sdk.AccAddress, height int64) DecCoi return withdraw ``` -## TxWithdrawValidator +## TxWithdrawDelegationReward + +under special circumstances a delegator may wish to withdraw rewards from only +a single validator. + +```golang +type TxWithdrawDelegationReward struct { + delegatorAddr sdk.AccAddress + validatorAddr sdk.AccAddress + withdrawAddr sdk.AccAddress // address to make the withdrawal to +} + +func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress) + height = GetHeight() + + // get all distribution scenarios + pool = stake.GetPool() + global = GetGlobal() + delInfo = GetDelegationDistInfo(delegatorAddr, + validatorAddr) + valInfo = GetValidatorDistInfo(validatorAddr) + validator = GetValidator(validatorAddr) + + global, withdraw = delInfo.WithdrawRewards(global, valInfo, height, pool.BondedTokens, + validator.Tokens, validator.DelegatorShares, validator.Commission) + + SetGlobal(global) + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) +``` + + +## TxWithdrawValidatorRewards When a validator wishes to withdraw their rewards it must send `TxWithdrawValidatorRewards`. Note that parts of this transaction logic are also @@ -78,11 +100,11 @@ func WithdrawValidatorRewards(operatorAddr, withdrawAddr sdk.AccAddress) // withdrawal validator commission rewards global, commission = valInfo.WithdrawCommission(global, valInfo, height, pool.BondedTokens, - validator.Tokens, validator.DelegatorShares, validator.Commission) + validator.Tokens, validator.Commission) withdraw += commission SetGlobal(global) - AddCoins(withdrawAddr, totalEntitlment.TruncateDecimal()) + AddCoins(withdrawAddr, withdraw.TruncateDecimal()) ``` ## Common calculations @@ -118,12 +140,13 @@ func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec ### Global pool to validator pool -Every time a validator or delegator executes a withdrawal or the validator is the -proposer and receives new tokens, the relevant validator must move tokens from -the passive global pool to their own pool. +Every time a validator or delegator executes a withdrawal or the validator is +the proposer and receives new tokens, the relevant validator must move tokens +from the passive global pool to their own pool. It is at this point that the +commission is withdrawn ``` -func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTokens Dec) g Global +func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTokens, commissionRate Dec) g Global g.UpdateTotalValAccum(height, totalBondedShares) g.UpdateValAccum(height, totalBondedShares) @@ -132,9 +155,11 @@ func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTok vi.GlobalWithdrawalHeight = height accum = blocks * vdTokens withdrawalTokens := g.Pool * accum / g.TotalValAccum + commission := withdrawalTokens * commissionRate g.TotalValAccum -= accumm - vi.Pool += withdrawalTokens + vi.PoolCommission += commission + vi.PoolCommissionFree += withdrawalTokens - commission g.Pool -= withdrawalTokens return g @@ -143,19 +168,19 @@ func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTok ### Delegation reward withdrawal -For delegations (including validator's self-delegation) all rewards from reward pool -are subject to commission rate from the operator of the validator. +For delegations (including validator's self-delegation) all rewards from reward +pool have already had the validator's commission taken away. ``` func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) vi.UpdateTotalDelAccum(height, totalDelShares) - g = vi.TakeAccum(g, height, totalBonded, vdTokens) + g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate) blocks = height - di.WithdrawalHeight di.WithdrawalHeight = height - accum = delegatorShares * blocks * (1 - commissionRate) + accum = delegatorShares * blocks withdrawalTokens := vi.Pool * accum / vi.TotalDelAccum vi.TotalDelAccum -= accum @@ -168,25 +193,16 @@ func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo, ### Validator commission withdrawal -Similar to a delegator's entitlement, but with recipient shares based on the -commission portion of bonded tokens. +Commission is calculated each time rewards enter into the validator. ``` func (vi ValidatorDistInfo) WithdrawCommission(g Global, height int64, - totalBonded, vdTokens, totalDelShares, commissionRate Dec) (g Global, withdrawn DecCoins) + totalBonded, vdTokens, commissionRate Dec) (g Global, withdrawn DecCoins) - vi.UpdateTotalDelAccum(height, totalDelShares) - g = vi.TakeAccum(g, height, totalBonded, vdTokens) + g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate) - blocks = height - vi.CommissionWithdrawalHeight - vi.CommissionWithdrawalHeight = height - accum = delegatorShares * blocks * (commissionRate) - - withdrawalTokens := vi.Pool * accum / vi.TotalDelAccum - vi.TotalDelAccum -= accum - - vi.Pool -= withdrawalTokens - vi.TotalDelAccum -= accum + withdrawalTokens := vi.PoolCommission + vi.PoolCommission = 0 return g, withdrawalTokens ```