many bug fixes, introduce PoolShare type

This commit is contained in:
rigelrozanski
2018-05-17 09:19:33 -04:00
parent be9413517d
commit 1ab432a7e1
9 changed files with 270 additions and 114 deletions
+1 -1
View File
@@ -161,7 +161,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (appState jso
if len(genTx.Name) > 0 {
desc := stake.NewDescription(genTx.Name, "", "", "")
validator := stake.NewValidator(genTx.Address, genTx.PubKey, desc)
validator.BondedShares = sdk.NewRat(freeFermionVal)
validator.PShares = stake.NewBondedShares(sdk.NewRat(freeFermionVal))
stakeData.Validators = append(stakeData.Validators, validator)
// pool logic
+2 -2
View File
@@ -10,9 +10,9 @@ type BondStatus byte
// nolint
const (
Bonded BondStatus = 0x00
Unbonded BondStatus = 0x00
Unbonding BondStatus = 0x01
Unbonded BondStatus = 0x02
Bonded BondStatus = 0x02
Revoked BondStatus = 0x03
)
+22 -1
View File
@@ -2,6 +2,7 @@ package stake
import (
"bytes"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/abci/types"
@@ -64,7 +65,7 @@ func handleMsgDeclareCandidacy(ctx sdk.Context, msg MsgDeclareCandidacy, k Keepe
}
validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description)
k.setValidator(ctx, validator)
validator = k.setValidator(ctx, validator)
tags := sdk.NewTags(
"action", []byte("declareCandidacy"),
"validator", msg.ValidatorAddr.Bytes(),
@@ -117,26 +118,38 @@ func handleMsgEditCandidacy(ctx sdk.Context, msg MsgEditCandidacy, k Keeper) sdk
}
func handleMsgDelegate(ctx sdk.Context, msg MsgDelegate, k Keeper) sdk.Result {
fmt.Println("wackydebugoutput handleMsgDelegate 0")
validator, found := k.GetValidator(ctx, msg.ValidatorAddr)
if !found {
fmt.Println("wackydebugoutput handleMsgDelegate 1")
return ErrBadValidatorAddr(k.codespace).Result()
}
fmt.Println("wackydebugoutput handleMsgDelegate 2")
if msg.Bond.Denom != k.GetParams(ctx).BondDenom {
fmt.Println("wackydebugoutput handleMsgDelegate 3")
return ErrBadBondingDenom(k.codespace).Result()
}
fmt.Println("wackydebugoutput handleMsgDelegate 4")
if validator.Status == sdk.Revoked {
fmt.Println("wackydebugoutput handleMsgDelegate 5")
return ErrValidatorRevoked(k.codespace).Result()
}
fmt.Println("wackydebugoutput handleMsgDelegate 6")
if ctx.IsCheckTx() {
fmt.Println("wackydebugoutput handleMsgDelegate 7")
return sdk.Result{
GasUsed: GasDelegate,
}
fmt.Println("wackydebugoutput handleMsgDelegate 9")
}
fmt.Println("wackydebugoutput handleMsgDelegate 10")
tags, err := delegate(ctx, k, msg.DelegatorAddr, msg.Bond, validator)
if err != nil {
fmt.Println("wackydebugoutput handleMsgDelegate 11")
return err.Result()
}
fmt.Println("wackydebugoutput handleMsgDelegate 12")
return sdk.Result{
Tags: tags,
}
@@ -145,24 +158,32 @@ func handleMsgDelegate(ctx sdk.Context, msg MsgDelegate, k Keeper) sdk.Result {
// common functionality between handlers
func delegate(ctx sdk.Context, k Keeper, delegatorAddr sdk.Address,
bondAmt sdk.Coin, validator Validator) (sdk.Tags, sdk.Error) {
fmt.Println("wackydebugoutput delegate 0")
// Get or create the delegator bond
bond, found := k.GetDelegation(ctx, delegatorAddr, validator.Address)
if !found {
fmt.Println("wackydebugoutput delegate 1")
bond = Delegation{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validator.Address,
Shares: sdk.ZeroRat(),
}
fmt.Println("wackydebugoutput delegate 3")
}
fmt.Println("wackydebugoutput delegate 4")
// Account new shares, save
pool := k.GetPool(ctx)
_, _, err := k.coinKeeper.SubtractCoins(ctx, bond.DelegatorAddr, sdk.Coins{bondAmt})
fmt.Println("wackydebugoutput delegate 5")
if err != nil {
fmt.Println("wackydebugoutput delegate 6")
return nil, err
}
fmt.Println("wackydebugoutput delegate 7")
validator, pool, newShares := validator.addTokensFromDel(pool, bondAmt.Amount)
fmt.Printf("debug newShares: %v\n", newShares)
bond.Shares = bond.Shares.Add(newShares)
// Update bond height
+20
View File
@@ -1,6 +1,7 @@
package stake
import (
"fmt"
"strconv"
"testing"
@@ -71,9 +72,23 @@ func TestIncrementsMsgDelegate(t *testing.T) {
validator, found := keeper.GetValidator(ctx, validatorAddr)
require.True(t, found)
require.Equal(t, sdk.Bonded, validator.Status)
assert.Equal(t, bondAmount, validator.DelegatorShares.Evaluate())
assert.Equal(t, bondAmount, validator.BondedShares.Evaluate(), "validator: %v", validator)
_, found = keeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
require.False(t, found)
bond, found := keeper.GetDelegation(ctx, validatorAddr, validatorAddr)
require.True(t, found)
assert.Equal(t, bondAmount, bond.Shares.Evaluate())
pool := keeper.GetPool(ctx)
exRate := validator.DelegatorShareExRate(pool)
require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v", exRate)
assert.Equal(t, bondAmount, pool.BondedShares.Evaluate())
assert.Equal(t, bondAmount, pool.BondedTokens)
// just send the same msgbond multiple times
msgDelegate := newTestMsgDelegate(delegatorAddr, validatorAddr, bondAmount)
@@ -89,6 +104,11 @@ func TestIncrementsMsgDelegate(t *testing.T) {
bond, found := keeper.GetDelegation(ctx, delegatorAddr, validatorAddr)
require.True(t, found)
pool := keeper.GetPool(ctx)
exRate := validator.DelegatorShareExRate(pool)
fmt.Printf("debug validator: %v\n", validator)
require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v, i = %v", exRate, i)
expBond := int64(i+1) * bondAmount
expDelegatorShares := int64(i+2) * bondAmount // (1 self delegation)
expDelegatorAcc := initBond - expBond
+10 -13
View File
@@ -2,7 +2,6 @@ package stake
import (
"bytes"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
@@ -68,7 +67,7 @@ func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve int16) (validators Va
return validators[:i] // trim
}
func (k Keeper) setValidator(ctx sdk.Context, validator Validator) {
func (k Keeper) setValidator(ctx sdk.Context, validator Validator) Validator {
store := ctx.KVStore(k.storeKey)
pool := k.getPool(store)
address := validator.Address
@@ -86,9 +85,9 @@ func (k Keeper) setValidator(ctx sdk.Context, validator Validator) {
if oldFound {
// if the voting power is the same no need to update any of the other indexes
if oldValidator.Status == sdk.Bonded &&
oldValidator.BondedShares.Equal(validator.BondedShares) {
return
} else if oldValidator.BondedShares.LT(validator.BondedShares) {
oldValidator.PShares.Equal(validator.PShares) {
return validator
} else if oldValidator.PShares.Bonded().LT(validator.PShares.Bonded()) {
powerIncreasing = true
}
// delete the old record in the power ordered list
@@ -111,7 +110,7 @@ func (k Keeper) setValidator(ctx sdk.Context, validator Validator) {
store.Set(GetValidatorsBondedByPowerKey(validator, pool), bz)
// add to the validators and return to update list if is already a validator and power is increasing
if powerIncreasing && oldValidator.Status == sdk.Bonded {
if powerIncreasing && oldFound && oldValidator.Status == sdk.Bonded {
// update the recent validator store
store.Set(GetValidatorsBondedKey(validator.PubKey), bz)
@@ -119,22 +118,20 @@ func (k Keeper) setValidator(ctx sdk.Context, validator Validator) {
// and the Tendermint updates
bz := k.cdc.MustMarshalBinary(validator.abciValidator(k.cdc))
store.Set(GetTendermintUpdatesKey(address), bz)
return
return validator
}
// update the validator set for this validator
valIsNowBonded := k.updateValidators(ctx, store, validator.Address)
fmt.Printf("debug valIsNowBonded: %v\n", valIsNowBonded)
fmt.Printf("debug validator0: %v\n", validator)
if oldValidator.Status != sdk.Bonded && valIsNowBonded {
if (!oldFound && valIsNowBonded) ||
(oldFound && oldValidator.Status != sdk.Bonded && valIsNowBonded) {
validator.Status = sdk.Bonded
validator, pool = validator.UpdateSharesLocation(pool)
k.setPool(ctx, pool)
}
fmt.Printf("debug validator1: %v\n", validator)
return
return validator
}
func (k Keeper) removeValidator(ctx sdk.Context, address sdk.Address) {
+21
View File
@@ -23,6 +23,27 @@ var (
}
)
func TestSetValidator(t *testing.T) {
ctx, _, keeper := createTestInput(t, false, 0)
pool := keeper.GetPool(ctx)
// test how the validator is set from a purely unbonbed pool
validator := NewValidator(addrVals[0], pks[0], Description{})
validator, pool, _ = validator.addTokensFromDel(pool, 10)
require.Equal(t, sdk.Unbonded, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.UnbondedShares))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
keeper.setPool(ctx, pool)
keeper.setValidator(ctx, validator)
// after the save the validator should be bonded
validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(t, found)
require.Equal(t, sdk.Bonded, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedShares))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
}
// This function tests setValidator, GetValidator, GetValidatorsBonded, removeValidator
func TestValidatorBasics(t *testing.T) {
ctx, _, keeper := createTestInput(t, false, 0)
+1 -1
View File
@@ -89,8 +89,8 @@ func (p Pool) unbondedShareExRate() sdk.Rat {
func (p Pool) addTokensBonded(amount int64) (p2 Pool, issuedShares sdk.Rat) {
issuedShares = sdk.NewRat(amount).Quo(p.bondedShareExRate()) // tokens * (shares/tokens)
p.BondedTokens += amount
p.BondedShares = p.BondedShares.Add(issuedShares)
p.BondedTokens += amount
return p, issuedShares
}
+139
View File
@@ -0,0 +1,139 @@
package stake
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// kind of shares
type PoolShareKind byte
// nolint
const (
ShareUnbonded PoolShareKind = 0x00
ShareUnbonding PoolShareKind = 0x01
ShareBonded PoolShareKind = 0x02
)
// pool shares held by a validator
type PoolShares struct {
Kind PoolShareKind `json:"kind"`
Amount sdk.Rat `json:"shares"` // total shares of type ShareKind
}
// only the vitals - does not check bond height of IntraTxCounter
func (s PoolShares) Equal(s2 PoolShares) bool {
return s.Kind == s2.Kind &&
s.Amount.Equal(s2.Amount)
}
func NewUnbondedShares(amount sdk.Rat) PoolShares {
return PoolShares{
Kind: ShareUnbonded,
Amount: amount,
}
}
func NewUnbondingShares(amount sdk.Rat) PoolShares {
return PoolShares{
Kind: ShareUnbonding,
Amount: amount,
}
}
func NewBondedShares(amount sdk.Rat) PoolShares {
return PoolShares{
Kind: ShareBonded,
Amount: amount,
}
}
//_________________________________________________________________________________________________________
// amount of unbonded shares
func (s PoolShares) Unbonded() sdk.Rat {
if s.Kind == ShareUnbonded {
return s.Amount
}
return sdk.ZeroRat()
}
// amount of unbonding shares
func (s PoolShares) Unbonding() sdk.Rat {
if s.Kind == ShareUnbonding {
return s.Amount
}
return sdk.ZeroRat()
}
// amount of bonded shares
func (s PoolShares) Bonded() sdk.Rat {
if s.Kind == ShareBonded {
return s.Amount
}
return sdk.ZeroRat()
}
//_________________________________________________________________________________________________________
// equivalent amount of shares if the shares were unbonded
func (s PoolShares) ToUnbonded(p Pool) PoolShares {
var amount sdk.Rat
switch s.Kind {
case ShareBonded:
exRate := p.bondedShareExRate().Quo(p.unbondedShareExRate()) // (tok/bondedshr)/(tok/unbondedshr) = unbondedshr/bondedshr
amount = s.Amount.Mul(exRate) // bondedshr*unbondedshr/bondedshr = unbondedshr
case ShareUnbonding:
exRate := p.unbondingShareExRate().Quo(p.unbondedShareExRate()) // (tok/unbondingshr)/(tok/unbondedshr) = unbondedshr/unbondingshr
amount = s.Amount.Mul(exRate) // unbondingshr*unbondedshr/unbondingshr = unbondedshr
case ShareUnbonded:
amount = s.Amount
}
return NewUnbondedShares(amount)
}
// equivalent amount of shares if the shares were unbonding
func (s PoolShares) ToUnbonding(p Pool) PoolShares {
var amount sdk.Rat
switch s.Kind {
case ShareBonded:
exRate := p.bondedShareExRate().Quo(p.unbondingShareExRate()) // (tok/bondedshr)/(tok/unbondingshr) = unbondingshr/bondedshr
amount = s.Amount.Mul(exRate) // bondedshr*unbondingshr/bondedshr = unbondingshr
case ShareUnbonding:
amount = s.Amount
case ShareUnbonded:
exRate := p.unbondedShareExRate().Quo(p.unbondingShareExRate()) // (tok/unbondedshr)/(tok/unbondingshr) = unbondingshr/unbondedshr
amount = s.Amount.Mul(exRate) // unbondedshr*unbondingshr/unbondedshr = unbondingshr
}
return NewUnbondingShares(amount)
}
// equivalent amount of shares if the shares were bonded
func (s PoolShares) ToBonded(p Pool) PoolShares {
var amount sdk.Rat
switch s.Kind {
case ShareBonded:
amount = s.Amount
case ShareUnbonding:
exRate := p.unbondingShareExRate().Quo(p.bondedShareExRate()) // (tok/ubshr)/(tok/bshr) = bshr/ubshr
amount = s.Amount.Mul(exRate) // ubshr*bshr/ubshr = bshr
case ShareUnbonded:
exRate := p.unbondedShareExRate().Quo(p.bondedShareExRate()) // (tok/ubshr)/(tok/bshr) = bshr/ubshr
amount = s.Amount.Mul(exRate) // ubshr*bshr/ubshr = bshr
}
return NewUnbondedShares(amount)
}
//_________________________________________________________________________________________________________
// get the equivalent amount of tokens contained by the shares
func (s PoolShares) Tokens(p Pool) sdk.Rat {
switch s.Kind {
case ShareBonded:
return p.unbondedShareExRate().Mul(s.Amount) // (tokens/shares) * shares
case ShareUnbonding:
return p.unbondedShareExRate().Mul(s.Amount)
case ShareUnbonded:
return p.unbondedShareExRate().Mul(s.Amount)
}
return sdk.ZeroRat()
}
+54 -96
View File
@@ -22,13 +22,8 @@ type Validator struct {
Address sdk.Address `json:"address"` // sender of BondTx - UnbondTx returns here
PubKey crypto.PubKey `json:"pub_key"` // pubkey of validator
// note: There should only be one of the following 3 shares ever active in a delegator
// multiple terms are only added here for clarity.
BondedShares sdk.Rat `json:"bonded_shares"` // total shares of bonded global hold pool
UnbondingShares sdk.Rat `json:"unbonding_shares"` // total shares of unbonding global hold pool
UnbondedShares sdk.Rat `json:"unbonded_shares"` // total shares of unbonded global hold pool
DelegatorShares sdk.Rat `json:"liabilities"` // total shares issued to a validator's delegators
PShares PoolShares `json:"pool_shares"` // total shares for tokens held in the pool
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators
Description Description `json:"description"` // description terms for the validator
BondHeight int64 `json:"validator_bond_height"` // earliest height as a bonded validator
@@ -53,9 +48,7 @@ func NewValidator(address sdk.Address, pubKey crypto.PubKey, description Descrip
Status: sdk.Unbonded,
Address: address,
PubKey: pubKey,
BondedShares: sdk.ZeroRat(),
UnbondingShares: sdk.ZeroRat(),
UnbondedShares: sdk.ZeroRat(),
PShares: NewUnbondedShares(sdk.ZeroRat()),
DelegatorShares: sdk.ZeroRat(),
Description: description,
BondHeight: int64(0),
@@ -74,7 +67,7 @@ func (v Validator) equal(c2 Validator) bool {
return v.Status == c2.Status &&
v.PubKey.Equals(c2.PubKey) &&
bytes.Equal(v.Address, c2.Address) &&
v.BondedShares.Equal(c2.BondedShares) &&
v.PShares.Equal(c2.PShares) &&
v.DelegatorShares.Equal(c2.DelegatorShares) &&
v.Description == c2.Description &&
//v.BondHeight == c2.BondHeight &&
@@ -118,15 +111,15 @@ func (v Validator) DelegatorShareExRate(p Pool) sdk.Rat {
if v.DelegatorShares.IsZero() {
return sdk.OneRat()
}
tokens := v.EquivalentBondedShares(p)
return tokens.Quo(v.DelegatorShares)
eqBondedShares := v.PShares.ToBonded(p).Amount
return eqBondedShares.Quo(v.DelegatorShares)
}
// abci validator from stake validator type
func (v Validator) abciValidator(cdc *wire.Codec) abci.Validator {
return abci.Validator{
PubKey: v.PubKey.Bytes(),
Power: v.BondedShares.Evaluate(),
Power: v.PShares.Bonded().Evaluate(),
}
}
@@ -144,35 +137,36 @@ func (v Validator) UpdateSharesLocation(p Pool) (Validator, Pool) {
var tokens int64
switch {
case !v.BondedShares.IsZero():
if v.Status == sdk.Bonded { // return if nothing needs switching
return v, p
}
p, tokens = p.removeSharesBonded(v.BondedShares)
v.BondedShares = sdk.ZeroRat()
case !v.UnbondingShares.IsZero():
if v.Status == sdk.Unbonding {
return v, p
}
p, tokens = p.removeSharesUnbonding(v.UnbondingShares)
v.UnbondingShares = sdk.ZeroRat()
case !v.UnbondedShares.IsZero():
case v.PShares.Kind == ShareUnbonded:
if v.Status == sdk.Unbonded {
return v, p
}
p, tokens = p.removeSharesUnbonded(v.UnbondedShares)
v.UnbondedShares = sdk.ZeroRat()
p, tokens = p.removeSharesUnbonded(v.PShares.Amount)
case v.PShares.Kind == ShareUnbonding:
if v.Status == sdk.Unbonding {
return v, p
}
p, tokens = p.removeSharesUnbonding(v.PShares.Amount)
case v.PShares.Kind == ShareBonded:
if v.Status == sdk.Bonded { // return if nothing needs switching
return v, p
}
p, tokens = p.removeSharesBonded(v.PShares.Amount)
}
var shares sdk.Rat
switch v.Status {
case sdk.Bonded:
p, v.BondedShares = p.addTokensBonded(tokens)
case sdk.Unbonding:
p, v.UnbondingShares = p.addTokensUnbonding(tokens)
case sdk.Unbonded, sdk.Revoked:
p, v.UnbondedShares = p.addTokensUnbonded(tokens)
p, shares = p.addTokensUnbonded(tokens)
v.PShares = NewUnbondedShares(shares)
case sdk.Unbonding:
p, shares = p.addTokensUnbonding(tokens)
v.PShares = NewUnbondingShares(shares)
case sdk.Bonded:
p, shares = p.addTokensBonded(tokens)
v.PShares = NewBondedShares(shares)
}
return v, p
}
@@ -183,92 +177,56 @@ func (v Validator) UpdateSharesLocation(p Pool) (Validator, Pool) {
// if not bonded, the power is the amount of bonded shares which the
// the validator would have it was bonded
func (v Validator) EquivalentBondedShares(p Pool) (eqBondedShares sdk.Rat) {
switch v.Status {
case sdk.Bonded:
eqBondedShares = v.BondedShares
case sdk.Unbonding:
shares := v.UnbondingShares // ubShr
exRate := p.unbondingShareExRate().Quo(p.bondedShareExRate()) // (tok/ubshr)/(tok/bshr) = bshr/ubshr
eqBondedShares = shares.Mul(exRate) // ubshr*bshr/ubshr = bshr
case sdk.Unbonded, sdk.Revoked:
shares := v.UnbondedShares // ubShr
exRate := p.unbondedShareExRate().Quo(p.bondedShareExRate()) // (tok/ubshr)/(tok/bshr) = bshr/ubshr
eqBondedShares = shares.Mul(exRate) // ubshr*bshr/ubshr = bshr
}
return
return v.PShares.ToBonded(p).Amount
}
// convert the equivalent bonded shares to a worth in unbonding shares
func EquivalentBondedSharesToUnbonding(p Pool, eqBondedShares sdk.Rat) (unbondingShares sdk.Rat) {
exRate := p.bondedShareExRate().Quo(p.unbondingShareExRate()) // (tok/bshr)/(tok/ubshr) = ubshr/bshr
return eqBondedShares.Mul(exRate) // bshr*ubshr/bshr = ubshr
}
// convert the equivalent bonded shares to a worth in unbonded shares
func EquivalentBondedSharesToUnbonded(p Pool, eqBondedShares sdk.Rat) (unbondedShares sdk.Rat) {
exRate := p.bondedShareExRate().Quo(p.unbondedShareExRate()) // (tok/bshr)/(tok/ubshr) = ubshr/bshr
return eqBondedShares.Mul(exRate) // bshr*ubshr/bshr = ubshr
}
// TODO Implement Use in query functionality
// get the equivalent amount of tokens contained by a validator
func (v Validator) Tokens(p Pool) sdk.Rat {
switch v.Status {
case sdk.Bonded:
return p.unbondedShareExRate().Mul(v.BondedShares) // (tokens/shares) * shares
case sdk.Unbonding:
return p.unbondedShareExRate().Mul(v.UnbondingShares)
case sdk.Unbonded, sdk.Revoked:
return p.unbondedShareExRate().Mul(v.UnbondedShares)
}
return sdk.ZeroRat()
}
//_________________________________________________________________________________________________________
// XXX Audit this function further to make sure it's correct
// add tokens to a validator
func (v Validator) addTokensFromDel(p Pool,
amount int64) (validator2 Validator, p2 Pool, issuedDelegatorShares sdk.Rat) {
var poolShares sdk.Rat
var equivalentBondedShares, poolShares sdk.Rat
switch v.Status {
case sdk.Bonded:
p, poolShares = p.addTokensBonded(amount)
v.BondedShares = v.BondedShares.Add(poolShares)
case sdk.Unbonding:
p, poolShares = p.addTokensUnbonding(amount)
v.UnbondingShares = v.UnbondingShares.Add(poolShares)
case sdk.Unbonded, sdk.Revoked:
p, poolShares = p.addTokensUnbonded(amount)
v.UnbondedShares = v.UnbondedShares.Add(poolShares)
case sdk.Unbonding:
p, poolShares = p.addTokensUnbonding(amount)
case sdk.Bonded:
p, poolShares = p.addTokensBonded(amount)
}
v.PShares.Amount = v.PShares.Amount.Add(poolShares)
equivalentBondedShares = v.PShares.ToBonded(p).Amount
equivalentBondedShares := v.EquivalentBondedShares(p)
exRate := v.DelegatorShareExRate(p) // eq-val-bonded-shares/delegator-shares
issuedDelegatorShares = equivalentBondedShares.Quo(exRate)
exRate := v.DelegatorShareExRate(p) // bshr/delshr
issuedDelegatorShares = equivalentBondedShares.Quo(exRate) // bshr/(bshr/delshr) = delshr
v.DelegatorShares = v.DelegatorShares.Add(issuedDelegatorShares)
return v, p, issuedDelegatorShares
}
// remove delegator shares from a validator
// NOTE this function assumes the shares have already been updated for the validator status
func (v Validator) removeDelShares(p Pool,
delShares sdk.Rat) (validator2 Validator, p2 Pool, createdCoins int64) {
eqBondedSharesToRemove := v.DelegatorShareExRate(p).Mul(delShares)
amount := v.DelegatorShareExRate(p).Mul(delShares)
eqBondedSharesToRemove := NewBondedShares(amount)
v.DelegatorShares = v.DelegatorShares.Sub(delShares)
switch v.Status {
case sdk.Bonded:
p, createdCoins = p.removeSharesBonded(eqBondedSharesToRemove)
v.BondedShares = v.BondedShares.Sub(eqBondedSharesToRemove)
case sdk.Unbonding:
unbondingShares := EquivalentBondedSharesToUnbonding(p, eqBondedSharesToRemove)
p, createdCoins = p.removeSharesUnbonding(unbondingShares)
v.UnbondingShares = v.UnbondingShares.Sub(unbondingShares)
case sdk.Unbonded, sdk.Revoked:
unbondedShares := EquivalentBondedSharesToUnbonded(p, eqBondedSharesToRemove)
unbondedShares := eqBondedSharesToRemove.ToUnbonded(p).Amount
p, createdCoins = p.removeSharesUnbonded(unbondedShares)
v.UnbondedShares = v.UnbondedShares.Sub(unbondedShares)
v.PShares.Amount = v.PShares.Amount.Sub(unbondedShares)
case sdk.Unbonding:
unbondingShares := eqBondedSharesToRemove.ToUnbonding(p).Amount
p, createdCoins = p.removeSharesUnbonding(unbondingShares)
v.PShares.Amount = v.PShares.Amount.Sub(unbondingShares)
case sdk.Bonded:
p, createdCoins = p.removeSharesBonded(eqBondedSharesToRemove.Amount)
v.PShares.Amount = v.PShares.Amount.Sub(eqBondedSharesToRemove.Amount)
}
return v, p, createdCoins
}
@@ -282,5 +240,5 @@ var _ sdk.Validator = Validator{}
func (v Validator) GetStatus() sdk.BondStatus { return v.Status }
func (v Validator) GetAddress() sdk.Address { return v.Address }
func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey }
func (v Validator) GetPower() sdk.Rat { return v.BondedShares }
func (v Validator) GetPower() sdk.Rat { return v.PShares.Bonded() }
func (v Validator) GetBondHeight() int64 { return v.BondHeight }