dec coins, refactoring distr

This commit is contained in:
rigelrozanski 2018-09-10 18:37:58 -04:00
parent cbb5a504d5
commit e498d43d03
7 changed files with 156 additions and 43 deletions

View File

@ -323,6 +323,32 @@ func (d Dec) RoundInt() Int {
//___________________________________________________________________________________
// similar to chopPrecisionAndRound, but always rounds down
func chopPrecisionAndTruncate(d *big.Int) *big.Int {
return d.Quo(d, precisionReuse)
}
func chopPrecisionAndTruncateNonMutative(d *big.Int) *big.Int {
tmp := new(big.Int).Set(d)
return chopPrecisionAndTruncate(tmp)
}
// RoundInt64 rounds the decimal using bankers rounding
func (d Dec) TruncateInt64() int64 {
chopped := chopPrecisionAndTruncateNonMutative(d.Int)
if !chopped.IsInt64() {
panic("Int64() out of bound")
}
return chopped.Int64()
}
// RoundInt round the decimal using bankers rounding
func (d Dec) TruncateInt() Int {
return NewIntFromBigInt(chopPrecisionAndTruncateNonMutative(d.Int))
}
//___________________________________________________________________________________
// reuse nil values
var (
nilAmino string

View File

@ -202,6 +202,32 @@ func TestBankerRoundChop(t *testing.T) {
}
}
func TestTruncate(t *testing.T) {
tests := []struct {
d1 Dec
exp int64
}{
{mustNewDecFromStr(t, "0"), 0},
{mustNewDecFromStr(t, "0.25"), 0},
{mustNewDecFromStr(t, "0.75"), 0},
{mustNewDecFromStr(t, "1"), 1},
{mustNewDecFromStr(t, "1.5"), 1},
{mustNewDecFromStr(t, "7.5"), 7},
{mustNewDecFromStr(t, "7.6"), 7},
{mustNewDecFromStr(t, "7.4"), 7},
{mustNewDecFromStr(t, "100.1"), 100},
{mustNewDecFromStr(t, "1000.1"), 1000},
}
for tcIndex, tc := range tests {
resNeg := tc.d1.Neg().TruncateInt64()
require.Equal(t, -1*tc.exp, resNeg, "negative tc %d", tcIndex)
resPos := tc.d1.TruncateInt64()
require.Equal(t, tc.exp, resPos, "positive tc %d", tcIndex)
}
}
func TestToLeftPadded(t *testing.T) {
tests := []struct {
dec Dec

View File

@ -7,7 +7,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/spf13/cobra"
"github.com/spf13/viper"
wire "github.com/tendermint/go-wire"
@ -38,7 +38,7 @@ var (
func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "withdraw-rewards [delegator]",
Short: "withdraw rewards from delegation accounts",
Short: "withdraw rewards for all delegations",
RunE: func(cmd *cobra.Command, args []string) error {
txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
@ -61,7 +61,7 @@ func GetCmdWithdrawDelegationRewardsAll(cdc *wire.Codec) *cobra.Command {
return err
}
msg := stake.NewMsgDelegate(delAddr, valAddr, amount)
msg := distr.NewMsgDelegate(delAddr, valAddr, amount)
// build and sign the transaction, then broadcast to Tendermint
return utils.SendTx(txCtx, cliCtx, []sdk.Msg{msg})

View File

@ -7,7 +7,6 @@ import (
// distribution fee handler
func DistributionFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {
k.
}
//////////////////////////////////////////////////////////////////////////////////

View File

@ -30,19 +30,18 @@ func (k Keeper) SetDelegatorDistInfo(ctx sdk.Context, ddi types.DelegatorDistInf
//___________________________________________________________________________________________
// XXX TODO
func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress) {
height = ctx.BlockHeight()
// withdraw all the rewards for a single delegation
func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr,
withdrawAddr sdk.AccAddress, validatorAddr sdk.ValAddress) {
// get all distribution scenarios
pool = stake.GetPool()
feePool = GetFeePool()
delInfo = GetDelegationDistInfo(delegatorAddr,
validatorAddr)
valInfo = GetValidatorDistInfo(validatorAddr)
validator = GetValidator(validatorAddr)
height := ctx.BlockHeight()
pool := stake.GetPool()
feePool := GetFeePool()
delInfo := GetDelegationDistInfo(delegatorAddr, validatorAddr)
valInfo := GetValidatorDistInfo(validatorAddr)
validator := GetValidator(validatorAddr)
feePool, withdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens,
feePool, withdraw := delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens,
validator.Tokens, validator.DelegatorShares, validator.Commission)
SetFeePool(feePool)
@ -51,30 +50,30 @@ func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr, validat
///////////////////////////////////////////////////////////////////////////////////////
// XXX TODO
// return all rewards for all delegations of a delegator
func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr, withdrawAddr sdk.AccAddress) {
height = ctx.BlockHeight()
withdraw = GetDelegatorRewardsAll(delegatorAddr, height)
height := ctx.BlockHeight()
withdraw = GetDelegatorRewardsAll(ctx, delegatorAddr, height)
k.coinsKeeper.AddCoins(withdrawAddr, withdraw.Amount.TruncateDecimal())
}
// XXX TODO
// return all rewards for all delegations of a delegator
func (k Keeper) GetDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) DecCoins {
// collect all entitled rewards
withdraw = 0
pool = stake.GetPool()
feePool = GetFeePool()
withdraw := sdk.NewDec(0)
pool := stake.GetPool()
feePool := GetFeePool()
// iterate over all the delegations
operationAtDelegation := func(_ int64, del types.Delegation) (stop bool) {
delInfo = GetDelegationDistInfo(delAddr, del.ValidatorAddr)
valInfo = GetValidatorDistInfo(del.ValidatorAddr)
validator = GetValidator(del.ValidatorAddr)
delInfo := GetDelegationDistInfo(delAddr, del.ValidatorAddr)
valInfo := GetValidatorDistInfo(del.ValidatorAddr)
validator := GetValidator(del.ValidatorAddr)
feePool, diWithdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens,
feePool, diWithdraw := delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens,
validator.Tokens, validator.DelegatorShares, validator.Commission)
withdraw += diWithdraw
withdraw = withdraw.Add(diWithdraw)
SetFeePool(feePool)
return false
}
k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation)

View File

@ -28,21 +28,22 @@ func (k Keeper) SetValidatorDistInfo(ctx sdk.Context, vdi types.ValidatorDistInf
}
// XXX TODO
func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr, withdrawAddr sdk.AccAddress) {
height = ctx.BlockHeight()
feePool = k.GetFeePool(ctx)
pool = k.stakeKeeper.GetPool(ctx)
ValInfo = k.GetValidatorDistInfo(delegation.ValidatorAddr)
validator = k.GetValidator(delegation.ValidatorAddr)
func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context,
operatorAddr sdk.ValAddress, withdrawAddr sdk.AccAddress) {
// withdraw self-delegation
withdraw = k.GetDelegatorRewardsAll(validator.OperatorAddr, height)
height := ctx.BlockHeight()
validator := k.GetValidator(operatorAddr)
withdraw := k.GetDelegatorRewardsAll(validator.OperatorAddr, height)
// withdrawal validator commission rewards
feePool, commission = valInfo.WithdrawCommission(feePool, valInfo, height, pool.BondedTokens,
pool := k.stakeKeeper.GetPool(ctx)
valInfo := k.GetValidatorDistInfo(operatorAddr)
feePool := k.GetFeePool(ctx)
feePool, commission := valInfo.WithdrawCommission(feePool, valInfo, height, pool.BondedTokens,
validator.Tokens, validator.Commission)
withdraw += commission
SetFeePool(feePool)
withdraw = withdraw.Add(commission)
k.SetFeePool(feePool)
k.coinKeeper.AddCoins(withdrawAddr, withdraw.TruncateDecimal())
}

View File

@ -1,23 +1,42 @@
package types
import sdk "github.com/cosmos/cosmos-sdk/types"
import (
"strings"
// coins with decimal
type DecCoins []DecCoin
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Coins which can have additional decimal points
type DecCoin struct {
Amount sdk.Dec `json:"amount"`
Denom string `json:"denom"`
Amount sdk.Dec `json:"amount"`
}
func NewDecCoin(coin sdk.Coin) DecCoin {
return DecCoins{
Amount: sdk.NewDec(coin.Amount),
Denom: coin.Denom,
Amount: sdk.NewDec(coin.Amount),
}
}
// Adds amounts of two coins with same denom
func (coin DecCoin) Plus(coinB DecCoin) DecCoin {
if !(coin.Denom == coinB.Denom) {
return coin
}
return Coin{coin.Denom, coin.Amount.Add(coinB.Amount)}
}
// return the decimal coins with trunctated decimals
func (coin DecCoin) TruncateDecimal() sdk.Coin {
return sdk.NewCoin(coin.Denom, coin.Amount.TruncateInt())
}
//_______________________________________________________________________
// coins with decimal
type DecCoins []DecCoin
func NewDecCoins(coins sdk.Coins) DecCoins {
dcs := make(DecCoins, len(coins))
@ -25,3 +44,46 @@ func NewDecCoins(coins sdk.Coins) DecCoins {
dcs[i] = NewDecCoin(coin)
}
}
// return the decimal coins with trunctated decimals
func (coins DecCoins) TruncateDecimal() sdk.Coins {
out := make(DecCoins, len(coins))
for i, coin := range coins {
out[i] = coin.TruncateDecimal()
}
}
// Plus combines two sets of coins
// CONTRACT: Plus will never return Coins where one Coin has a 0 amount.
func (coins DecCoins) Plus(coinsB DecCoins) DecCoins {
sum := ([]DecCoin)(nil)
indexA, indexB := 0, 0
lenA, lenB := len(coins), len(coinsB)
for {
if indexA == lenA {
if indexB == lenB {
return sum
}
return append(sum, coinsB[indexB:]...)
} else if indexB == lenB {
return append(sum, coins[indexA:]...)
}
coinA, coinB := coins[indexA], coinsB[indexB]
switch strings.Compare(coinA.Denom, coinB.Denom) {
case -1:
sum = append(sum, coinA)
indexA++
case 0:
if coinA.Amount.Add(coinB.Amount).IsZero() {
// ignore 0 sum coin type
} else {
sum = append(sum, coinA.Plus(coinB))
}
indexA++
indexB++
case 1:
sum = append(sum, coinB)
indexB++
}
}
}