154 lines
5.4 KiB
Go
154 lines
5.4 KiB
Go
package types
|
|
|
|
import (
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
)
|
|
|
|
// common parameters used in withdraws from validators
|
|
type WithdrawContext struct {
|
|
FeePool FeePool
|
|
Height int64 // block height
|
|
TotalPower sdk.Dec // total bonded tokens in the network
|
|
ValPower sdk.Dec // validator's bonded tokens
|
|
CommissionRate sdk.Dec // validator commission rate
|
|
}
|
|
|
|
func NewWithdrawContext(feePool FeePool, height int64, totalPower,
|
|
valPower, commissionRate sdk.Dec) WithdrawContext {
|
|
|
|
return WithdrawContext{
|
|
FeePool: feePool,
|
|
Height: height,
|
|
TotalPower: totalPower,
|
|
ValPower: valPower,
|
|
CommissionRate: commissionRate,
|
|
}
|
|
}
|
|
|
|
//_____________________________________________________________________________
|
|
|
|
// distribution info for a particular validator
|
|
type ValidatorDistInfo struct {
|
|
OperatorAddr sdk.ValAddress `json:"operator_addr"`
|
|
|
|
FeePoolWithdrawalHeight int64 `json:"fee_pool_withdrawal_height"` // last height this validator withdrew from the global pool
|
|
|
|
DelAccum TotalAccum `json:"del_accum"` // total accumulation factor held by delegators
|
|
DelPool DecCoins `json:"del_pool"` // rewards owed to delegators, commission has already been charged (includes proposer reward)
|
|
ValCommission DecCoins `json:"val_commission"` // commission collected by this validator (pending withdrawal)
|
|
}
|
|
|
|
func NewValidatorDistInfo(operatorAddr sdk.ValAddress, currentHeight int64) ValidatorDistInfo {
|
|
return ValidatorDistInfo{
|
|
OperatorAddr: operatorAddr,
|
|
FeePoolWithdrawalHeight: currentHeight,
|
|
DelPool: DecCoins{},
|
|
DelAccum: NewTotalAccum(currentHeight),
|
|
ValCommission: DecCoins{},
|
|
}
|
|
}
|
|
|
|
// update total delegator accumululation
|
|
func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares sdk.Dec) ValidatorDistInfo {
|
|
vi.DelAccum = vi.DelAccum.UpdateForNewHeight(height, totalDelShares)
|
|
return vi
|
|
}
|
|
|
|
// Get the total delegator accum within this validator at the provided height
|
|
func (vi ValidatorDistInfo) GetTotalDelAccum(height int64, totalDelShares sdk.Dec) sdk.Dec {
|
|
return vi.DelAccum.GetAccum(height, totalDelShares)
|
|
}
|
|
|
|
// Get the validator accum at the provided height
|
|
func (vi ValidatorDistInfo) GetValAccum(height int64, valTokens sdk.Dec) sdk.Dec {
|
|
blocks := height - vi.FeePoolWithdrawalHeight
|
|
return valTokens.MulInt(sdk.NewInt(blocks))
|
|
}
|
|
|
|
// Move any available accumulated fees in the FeePool to the validator's pool
|
|
// - updates validator info's FeePoolWithdrawalHeight, thus setting accum to 0
|
|
// - updates fee pool to latest height and total val accum w/ given totalBonded
|
|
// This is the only way to update the FeePool's validator TotalAccum.
|
|
// NOTE: This algorithm works as long as TakeFeePoolRewards is called after every power change.
|
|
// - called in ValidationDistInfo.WithdrawCommission
|
|
// - called in DelegationDistInfo.WithdrawRewards
|
|
// NOTE: When a delegator unbonds, say, onDelegationSharesModified ->
|
|
// WithdrawDelegationReward -> WithdrawRewards
|
|
func (vi ValidatorDistInfo) TakeFeePoolRewards(wc WithdrawContext) (
|
|
ValidatorDistInfo, FeePool) {
|
|
|
|
fp := wc.FeePool.UpdateTotalValAccum(wc.Height, wc.TotalPower)
|
|
|
|
if fp.TotalValAccum.Accum.IsZero() {
|
|
vi.FeePoolWithdrawalHeight = wc.Height
|
|
return vi, fp
|
|
}
|
|
|
|
// update the validators pool
|
|
accum := vi.GetValAccum(wc.Height, wc.ValPower)
|
|
vi.FeePoolWithdrawalHeight = wc.Height
|
|
|
|
if accum.GT(fp.TotalValAccum.Accum) {
|
|
panic("individual accum should never be greater than the total")
|
|
}
|
|
withdrawalTokens := fp.ValPool.MulDec(accum).QuoDec(fp.TotalValAccum.Accum) // XXX ensure this doesn't cause problems
|
|
remValPool := fp.ValPool.Minus(withdrawalTokens)
|
|
|
|
commission := withdrawalTokens.MulDec(wc.CommissionRate)
|
|
afterCommission := withdrawalTokens.Minus(commission)
|
|
|
|
fp.TotalValAccum.Accum = fp.TotalValAccum.Accum.Sub(accum)
|
|
fp.ValPool = remValPool
|
|
vi.ValCommission = vi.ValCommission.Plus(commission)
|
|
vi.DelPool = vi.DelPool.Plus(afterCommission)
|
|
|
|
return vi, fp
|
|
}
|
|
|
|
// withdraw commission rewards
|
|
func (vi ValidatorDistInfo) WithdrawCommission(wc WithdrawContext) (
|
|
vio ValidatorDistInfo, fpo FeePool, withdrawn DecCoins) {
|
|
|
|
vi, fp := vi.TakeFeePoolRewards(wc)
|
|
|
|
withdrawalTokens := vi.ValCommission
|
|
vi.ValCommission = DecCoins{} // zero
|
|
|
|
return vi, fp, withdrawalTokens
|
|
}
|
|
|
|
// get the validator's pool rewards at this current state,
|
|
func (vi ValidatorDistInfo) CurrentPoolRewards(
|
|
wc WithdrawContext) DecCoins {
|
|
|
|
fp := wc.FeePool
|
|
totalValAccum := fp.GetTotalValAccum(wc.Height, wc.TotalPower)
|
|
valAccum := vi.GetValAccum(wc.Height, wc.ValPower)
|
|
|
|
if valAccum.GT(totalValAccum) {
|
|
panic("individual accum should never be greater than the total")
|
|
}
|
|
withdrawalTokens := fp.ValPool.MulDec(valAccum).QuoDec(totalValAccum)
|
|
commission := withdrawalTokens.MulDec(wc.CommissionRate)
|
|
afterCommission := withdrawalTokens.Minus(commission)
|
|
pool := vi.DelPool.Plus(afterCommission)
|
|
return pool
|
|
}
|
|
|
|
// get the validator's commission pool rewards at this current state,
|
|
func (vi ValidatorDistInfo) CurrentCommissionRewards(
|
|
wc WithdrawContext) DecCoins {
|
|
|
|
fp := wc.FeePool
|
|
totalValAccum := fp.GetTotalValAccum(wc.Height, wc.TotalPower)
|
|
valAccum := vi.GetValAccum(wc.Height, wc.ValPower)
|
|
|
|
if valAccum.GT(totalValAccum) {
|
|
panic("individual accum should never be greater than the total")
|
|
}
|
|
withdrawalTokens := fp.ValPool.MulDec(valAccum).QuoDec(totalValAccum)
|
|
commission := withdrawalTokens.MulDec(wc.CommissionRate)
|
|
commissionPool := vi.ValCommission.Plus(commission)
|
|
return commissionPool
|
|
}
|