many bug fixes, introduce PoolShare type
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user