cosmos-sdk/x/distribution/keeper/delegation.go

201 lines
6.8 KiB
Go

package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
// check whether a delegator distribution info exists
func (k Keeper) HasDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
valOperatorAddr sdk.ValAddress) (has bool) {
store := ctx.KVStore(k.storeKey)
return store.Has(GetDelegationDistInfoKey(delAddr, valOperatorAddr))
}
// get the delegator distribution info
func (k Keeper) GetDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
valOperatorAddr sdk.ValAddress) (ddi types.DelegationDistInfo) {
store := ctx.KVStore(k.storeKey)
b := store.Get(GetDelegationDistInfoKey(delAddr, valOperatorAddr))
if b == nil {
panic("Stored delegation-distribution info should not have been nil")
}
k.cdc.MustUnmarshalBinaryLengthPrefixed(b, &ddi)
return
}
// set the delegator distribution info
func (k Keeper) SetDelegationDistInfo(ctx sdk.Context, ddi types.DelegationDistInfo) {
store := ctx.KVStore(k.storeKey)
b := k.cdc.MustMarshalBinaryLengthPrefixed(ddi)
store.Set(GetDelegationDistInfoKey(ddi.DelegatorAddr, ddi.ValOperatorAddr), b)
}
// remove a delegator distribution info
func (k Keeper) RemoveDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
valOperatorAddr sdk.ValAddress) {
store := ctx.KVStore(k.storeKey)
store.Delete(GetDelegationDistInfoKey(delAddr, valOperatorAddr))
}
//___________________________________________________________________________________________
// get the delegator withdraw address, return the delegator address if not set
func (k Keeper) GetDelegatorWithdrawAddr(ctx sdk.Context, delAddr sdk.AccAddress) sdk.AccAddress {
store := ctx.KVStore(k.storeKey)
b := store.Get(GetDelegatorWithdrawAddrKey(delAddr))
if b == nil {
return delAddr
}
return sdk.AccAddress(b)
}
// set the delegator withdraw address
func (k Keeper) SetDelegatorWithdrawAddr(ctx sdk.Context, delAddr, withdrawAddr sdk.AccAddress) {
store := ctx.KVStore(k.storeKey)
store.Set(GetDelegatorWithdrawAddrKey(delAddr), withdrawAddr.Bytes())
}
// remove a delegator withdraw info
func (k Keeper) RemoveDelegatorWithdrawAddr(ctx sdk.Context, delAddr, withdrawAddr sdk.AccAddress) {
store := ctx.KVStore(k.storeKey)
store.Delete(GetDelegatorWithdrawAddrKey(delAddr))
}
//___________________________________________________________________________________________
// return all rewards for a delegation
func (k Keeper) withdrawDelegationReward(ctx sdk.Context,
delAddr sdk.AccAddress, valAddr sdk.ValAddress) (types.FeePool,
types.ValidatorDistInfo, types.DelegationDistInfo, types.DecCoins) {
wc := k.GetWithdrawContext(ctx, valAddr)
valInfo := k.GetValidatorDistInfo(ctx, valAddr)
delInfo := k.GetDelegationDistInfo(ctx, delAddr, valAddr)
validator := k.stakeKeeper.Validator(ctx, valAddr)
delegation := k.stakeKeeper.Delegation(ctx, delAddr, valAddr)
delInfo, valInfo, feePool, withdraw := delInfo.WithdrawRewards(wc, valInfo,
validator.GetDelegatorShares(), delegation.GetShares())
return feePool, valInfo, delInfo, withdraw
}
// get all rewards for all delegations of a delegator
func (k Keeper) currentDelegationReward(ctx sdk.Context, delAddr sdk.AccAddress,
valAddr sdk.ValAddress) types.DecCoins {
wc := k.GetWithdrawContext(ctx, valAddr)
valInfo := k.GetValidatorDistInfo(ctx, valAddr)
delInfo := k.GetDelegationDistInfo(ctx, delAddr, valAddr)
validator := k.stakeKeeper.Validator(ctx, valAddr)
delegation := k.stakeKeeper.Delegation(ctx, delAddr, valAddr)
estimation := delInfo.CurrentRewards(wc, valInfo,
validator.GetDelegatorShares(), delegation.GetShares())
return estimation
}
//___________________________________________________________________________________________
// withdraw all rewards for a single delegation
// NOTE: This gets called "onDelegationSharesModified",
// meaning any changes to bonded coins
func (k Keeper) WithdrawToDelegator(ctx sdk.Context, feePool types.FeePool,
delAddr sdk.AccAddress, amount types.DecCoins) {
withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delAddr)
coinsToAdd, change := amount.TruncateDecimal()
feePool.CommunityPool = feePool.CommunityPool.Plus(change)
k.SetFeePool(ctx, feePool)
_, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, coinsToAdd)
if err != nil {
panic(err)
}
}
//___________________________________________________________________________________________
// withdraw all rewards for a single delegation
// NOTE: This gets called "onDelegationSharesModified",
// meaning any changes to bonded coins
func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delAddr sdk.AccAddress,
valAddr sdk.ValAddress) sdk.Error {
if !k.HasDelegationDistInfo(ctx, delAddr, valAddr) {
return types.ErrNoDelegationDistInfo(k.codespace)
}
feePool, valInfo, delInfo, withdraw :=
k.withdrawDelegationReward(ctx, delAddr, valAddr)
k.SetValidatorDistInfo(ctx, valInfo)
k.SetDelegationDistInfo(ctx, delInfo)
k.WithdrawToDelegator(ctx, feePool, delAddr, withdraw)
return nil
}
// current rewards for a single delegation
func (k Keeper) CurrentDelegationReward(ctx sdk.Context, delAddr sdk.AccAddress,
valAddr sdk.ValAddress) (sdk.Coins, sdk.Error) {
if !k.HasDelegationDistInfo(ctx, delAddr, valAddr) {
return sdk.Coins{}, types.ErrNoDelegationDistInfo(k.codespace)
}
estCoins := k.currentDelegationReward(ctx, delAddr, valAddr)
trucate, _ := estCoins.TruncateDecimal()
return trucate, nil
}
//___________________________________________________________________________________________
// return all rewards for all delegations of a delegator
func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress) {
withdraw := k.withdrawDelegationRewardsAll(ctx, delAddr)
feePool := k.GetFeePool(ctx)
k.WithdrawToDelegator(ctx, feePool, delAddr, withdraw)
}
func (k Keeper) withdrawDelegationRewardsAll(ctx sdk.Context,
delAddr sdk.AccAddress) types.DecCoins {
// iterate over all the delegations
withdraw := types.DecCoins{}
operationAtDelegation := func(_ int64, del sdk.Delegation) (stop bool) {
valAddr := del.GetValidatorAddr()
feePool, valInfo, delInfo, diWithdraw :=
k.withdrawDelegationReward(ctx, delAddr, valAddr)
withdraw = withdraw.Plus(diWithdraw)
k.SetFeePool(ctx, feePool)
k.SetValidatorDistInfo(ctx, valInfo)
k.SetDelegationDistInfo(ctx, delInfo)
return false
}
k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation)
return withdraw
}
// get all rewards for all delegations of a delegator
func (k Keeper) CurrentDelegationRewardsAll(ctx sdk.Context,
delAddr sdk.AccAddress) types.DecCoins {
// iterate over all the delegations
total := types.DecCoins{}
operationAtDelegation := func(_ int64, del sdk.Delegation) (stop bool) {
valAddr := del.GetValidatorAddr()
est := k.currentDelegationReward(ctx, delAddr, valAddr)
total = total.Plus(est)
return false
}
k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation)
return total
}