From 41458956a1950960cd9c13a6006d23f7fcb58519 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Tue, 22 May 2018 18:50:59 -0400 Subject: [PATCH] fix tests, pool.TotalSupply -> pool.TokenSupply() --- cmd/gaia/app/genesis.go | 3 +- x/stake/handler_test.go | 3 - x/stake/keeper.go | 254 ++++++++++++++---------------- x/stake/keeper_test.go | 27 ++-- x/stake/pool.go | 37 +++-- x/stake/pool_test.go | 5 +- x/stake/tick.go | 3 +- x/stake/tick_test.go | 57 ++++--- x/stake/validator_test.go | 4 +- x/stake/view_slash_keeper_test.go | 2 +- 10 files changed, 192 insertions(+), 203 deletions(-) diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 1db14986d9..525fe8ab07 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -155,7 +155,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (appState jso } acc := NewGenesisAccount(&accAuth) genaccs[i] = acc - stakeData.Pool.TotalSupply += freeFermionsAcc // increase the supply + stakeData.Pool.LooseUnbondedTokens += freeFermionsAcc // increase the supply // add the validator if len(genTx.Name) > 0 { @@ -165,7 +165,6 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (appState jso stakeData.Validators = append(stakeData.Validators, validator) // pool logic - stakeData.Pool.TotalSupply += freeFermionVal stakeData.Pool.BondedTokens += freeFermionVal stakeData.Pool.BondedShares = sdk.NewRat(stakeData.Pool.BondedTokens) } diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 467e36b470..19848e8e6d 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -1,7 +1,6 @@ package stake import ( - "fmt" "strconv" "testing" @@ -225,14 +224,12 @@ func TestMultipleMsgDeclareCandidacy(t *testing.T) { // bond them all for i, validatorAddr := range validatorAddrs { - fmt.Printf("debug i: %v\n", i) msgDeclareCandidacy := newTestMsgDeclareCandidacy(validatorAddr, pks[i], 10) got := handleMsgDeclareCandidacy(ctx, msgDeclareCandidacy, keeper) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) //Check that the account is bonded validators := keeper.GetValidators(ctx, 100) - fmt.Printf("debug validators: %v\n", validators) require.Equal(t, (i + 1), len(validators)) val := validators[i] balanceExpd := initBond - 10 diff --git a/x/stake/keeper.go b/x/stake/keeper.go index 6131fa7406..4fe7574c10 100644 --- a/x/stake/keeper.go +++ b/x/stake/keeper.go @@ -38,7 +38,7 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.Address) (validator Valid return k.getValidator(store, addr) } -// get a single validator +// get a single validator (reuse store) func (k Keeper) getValidator(store sdk.KVStore, addr sdk.Address) (validator Validator, found bool) { b := store.Get(GetValidatorKey(addr)) if b == nil { @@ -48,6 +48,13 @@ func (k Keeper) getValidator(store sdk.KVStore, addr sdk.Address) (validator Val return validator, true } +// set the main record holding validator details +func (k Keeper) setValidator(ctx sdk.Context, validator Validator) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshalBinary(validator) + store.Set(GetValidatorKey(validator.Owner), bz) +} + // Get the set of all validators with no limits, used during genesis dump func (k Keeper) getAllValidators(ctx sdk.Context) (validators Validators) { store := ctx.KVStore(k.storeKey) @@ -89,100 +96,6 @@ func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve int16) (validators Va return validators[:i] // trim } -func (k Keeper) setValidator(ctx sdk.Context, validator Validator) { - store := ctx.KVStore(k.storeKey) - bz := k.cdc.MustMarshalBinary(validator) - store.Set(GetValidatorKey(validator.Owner), bz) -} - -func (k Keeper) updateValidator(ctx sdk.Context, validator Validator) Validator { - store := ctx.KVStore(k.storeKey) - pool := k.getPool(store) - ownerAddr := validator.Owner - - // always update the main list ordered by owner address before exiting - defer func() { - bz := k.cdc.MustMarshalBinary(validator) - store.Set(GetValidatorKey(ownerAddr), bz) - }() - - // retreive the old validator record - oldValidator, oldFound := k.GetValidator(ctx, ownerAddr) - - powerIncreasing := false - if oldFound { - // if the voting power/status is the same no need to update any of the other indexes - // TODO will need to implement this to have regard for "unrevoke" transaction however - // it shouldn't return here under that transaction - if oldValidator.Status() == validator.Status() && - oldValidator.PoolShares.Equal(validator.PoolShares) { - return validator - } else if oldValidator.PoolShares.Bonded().LT(validator.PoolShares.Bonded()) { - powerIncreasing = true - } - } - - // update the list ordered by voting power - if oldFound { - store.Delete(GetValidatorsByPowerKey(oldValidator, pool)) - } - store.Set(GetValidatorsByPowerKey(validator, pool), validator.Owner) - - // if already a validator, copy the old block height and counter, else set them - if oldFound && oldValidator.Status() == sdk.Bonded { - validator.BondHeight = oldValidator.BondHeight - validator.BondIntraTxCounter = oldValidator.BondIntraTxCounter - } else { - validator.BondHeight = ctx.BlockHeight() - counter := k.getIntraTxCounter(ctx) - validator.BondIntraTxCounter = counter - k.setIntraTxCounter(ctx, counter+1) - } - - // efficiency case: - // if already bonded and power increasing only need to update tendermint - if powerIncreasing && oldValidator.Status() == sdk.Bonded { - bz := k.cdc.MustMarshalBinary(validator.abciValidator(k.cdc)) - store.Set(GetTendermintUpdatesKey(ownerAddr), bz) - return validator - } - - // TODO efficiency case: - // if was unbonded/or is a new validator - and the new power is less than the cliff validator - - // update the validator set for this validator - updatedVal := k.updateBondedValidatorsNew(ctx, store, validator) - if updatedVal.Owner != nil { // updates to validator occured to be updated - validator = updatedVal - } - return validator -} - -func (k Keeper) removeValidator(ctx sdk.Context, address sdk.Address) { - - // first retreive the old validator record - validator, found := k.GetValidator(ctx, address) - if !found { - return - } - - // delete the old validator record - store := ctx.KVStore(k.storeKey) - pool := k.getPool(store) - store.Delete(GetValidatorKey(address)) - store.Delete(GetValidatorsByPowerKey(validator, pool)) - - // delete from the current and power weighted validator groups if the validator - // is bonded - and add validator with zero power to the validator updates - if store.Get(GetValidatorsBondedKey(validator.PubKey)) == nil { - return - } - store.Delete(GetValidatorsBondedKey(validator.PubKey)) - - bz := k.cdc.MustMarshalBinary(validator.abciValidatorZero(k.cdc)) - store.Set(GetTendermintUpdatesKey(address), bz) -} - //___________________________________________________________________________ // get the group of the bonded validators @@ -240,6 +153,101 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []Validator { return validators[:i] // trim } +//_________________________________________________________________________ +// Accumulated updates to the active/bonded validator set for tendermint + +// get the most recently updated validators +func (k Keeper) getTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) { + store := ctx.KVStore(k.storeKey) + + iterator := store.SubspaceIterator(TendermintUpdatesKey) //smallest to largest + for ; iterator.Valid(); iterator.Next() { + valBytes := iterator.Value() + var val abci.Validator + k.cdc.MustUnmarshalBinary(valBytes, &val) + updates = append(updates, val) + } + iterator.Close() + return +} + +// remove all validator update entries after applied to Tendermint +func (k Keeper) clearTendermintUpdates(ctx sdk.Context) { + store := ctx.KVStore(k.storeKey) + + // delete subspace + iterator := store.SubspaceIterator(TendermintUpdatesKey) + for ; iterator.Valid(); iterator.Next() { + store.Delete(iterator.Key()) + } + iterator.Close() +} + +//___________________________________________________________________________ + +func (k Keeper) updateValidator(ctx sdk.Context, validator Validator) Validator { + store := ctx.KVStore(k.storeKey) + pool := k.getPool(store) + ownerAddr := validator.Owner + + // always update the main list ordered by owner address before exiting + defer func() { + bz := k.cdc.MustMarshalBinary(validator) + store.Set(GetValidatorKey(ownerAddr), bz) + }() + + // retreive the old validator record + oldValidator, oldFound := k.GetValidator(ctx, ownerAddr) + + powerIncreasing := false + if oldFound { + // if the voting power/status is the same no need to update any of the other indexes + // TODO will need to implement this to have regard for "unrevoke" transaction however + // it shouldn't return here under that transaction + if oldValidator.Status() == validator.Status() && + oldValidator.PoolShares.Equal(validator.PoolShares) { + return validator + } else if oldValidator.PoolShares.Bonded().LT(validator.PoolShares.Bonded()) { + powerIncreasing = true + } + } + + // if already a validator, copy the old block height and counter, else set them + if oldFound && oldValidator.Status() == sdk.Bonded { + validator.BondHeight = oldValidator.BondHeight + validator.BondIntraTxCounter = oldValidator.BondIntraTxCounter + } else { + validator.BondHeight = ctx.BlockHeight() + counter := k.getIntraTxCounter(ctx) + validator.BondIntraTxCounter = counter + k.setIntraTxCounter(ctx, counter+1) + } + + // update the list ordered by voting power + if oldFound { + store.Delete(GetValidatorsByPowerKey(oldValidator, pool)) + } + store.Set(GetValidatorsByPowerKey(validator, pool), validator.Owner) + + // efficiency case: + // if already bonded and power increasing only need to update tendermint + if powerIncreasing && oldValidator.Status() == sdk.Bonded { + bz := k.cdc.MustMarshalBinary(validator.abciValidator(k.cdc)) + store.Set(GetTendermintUpdatesKey(ownerAddr), bz) + return validator + } + + // TODO efficiency case: + // if was unbonded/or is a new validator - and the new power is less than the cliff validator + + // update the validator set for this validator + updatedVal := k.updateBondedValidatorsNew(ctx, store, validator) + if updatedVal.Owner != nil { // updates to validator occured to be updated + validator = updatedVal + } + return validator +} + // XXX TODO build in consideration for revoked // // Update the validator group and kick out any old validators. In addition this @@ -262,11 +270,11 @@ func (k Keeper) updateBondedValidatorsNew(ctx sdk.Context, store sdk.KVStore, newValidator Validator) (updatedVal Validator) { // clear the current validators store, add to the ToKickOut temp store - toKickOut := make(map[string]int8) // map[key]value + toKickOut := make(map[string]byte) iterator := store.SubspaceIterator(ValidatorsBondedKey) for ; iterator.Valid(); iterator.Next() { ownerAddr := iterator.Value() - toKickOut[string(ownerAddr)] = 0 // dummy set, only need key + toKickOut[string(ownerAddr)] = 0 // set anything } iterator.Close() @@ -298,12 +306,7 @@ func (k Keeper) updateBondedValidatorsNew(ctx sdk.Context, store sdk.KVStore, _, found := toKickOut[string(ownerAddr)] if found { - - // remove from ToKickOut group delete(toKickOut, string(ownerAddr)) - - // XXX also add to the current validators group - //store.Set(GetValidatorsBondedKey(validator.PubKey), validator.Owner) } else { // if it wasn't in the toKickOut group it means @@ -340,9 +343,6 @@ func (k Keeper) unbondValidator(ctx sdk.Context, store sdk.KVStore, validator Va panic(fmt.Sprintf("should not already be be unbonded, validator: %v\n", validator)) } - // XXX first delete the old record in the pool - //store.Delete(GetValidatorsByPowerKey(validator, pool)) - // set the status validator, pool = validator.UpdateStatus(pool, sdk.Unbonded) k.setPool(ctx, pool) @@ -350,7 +350,6 @@ func (k Keeper) unbondValidator(ctx sdk.Context, store sdk.KVStore, validator Va // save the now unbonded validator record bzVal := k.cdc.MustMarshalBinary(validator) store.Set(GetValidatorKey(validator.Owner), bzVal) - // XXX store.Set(GetValidatorsByPowerKey(validator, pool), validator.Owner) // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.abciValidatorZero(k.cdc)) @@ -369,9 +368,6 @@ func (k Keeper) bondValidator(ctx sdk.Context, store sdk.KVStore, validator Vali panic(fmt.Sprintf("should not already be be bonded, validator: %v\n", validator)) } - // XXX first delete the old record in the pool - //store.Delete(GetValidatorsByPowerKey(validator, pool)) - // set the status validator, pool = validator.UpdateStatus(pool, sdk.Bonded) k.setPool(ctx, pool) @@ -379,7 +375,6 @@ func (k Keeper) bondValidator(ctx sdk.Context, store sdk.KVStore, validator Vali // save the now bonded validator record to the three referenced stores bzVal := k.cdc.MustMarshalBinary(validator) store.Set(GetValidatorKey(validator.Owner), bzVal) - // XXX store.Set(GetValidatorsByPowerKey(validator, pool), validator.Owner) store.Set(GetValidatorsBondedKey(validator.PubKey), validator.Owner) // add to accumulated changes for tendermint @@ -389,34 +384,29 @@ func (k Keeper) bondValidator(ctx sdk.Context, store sdk.KVStore, validator Vali return validator } -//_________________________________________________________________________ -// Accumulated updates to the active/bonded validator set for tendermint +func (k Keeper) removeValidator(ctx sdk.Context, address sdk.Address) { -// get the most recently updated validators -func (k Keeper) getTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) { - store := ctx.KVStore(k.storeKey) - - iterator := store.SubspaceIterator(TendermintUpdatesKey) //smallest to largest - for ; iterator.Valid(); iterator.Next() { - valBytes := iterator.Value() - var val abci.Validator - k.cdc.MustUnmarshalBinary(valBytes, &val) - updates = append(updates, val) + // first retreive the old validator record + validator, found := k.GetValidator(ctx, address) + if !found { + return } - iterator.Close() - return -} -// remove all validator update entries after applied to Tendermint -func (k Keeper) clearTendermintUpdates(ctx sdk.Context) { + // delete the old validator record store := ctx.KVStore(k.storeKey) + pool := k.getPool(store) + store.Delete(GetValidatorKey(address)) + store.Delete(GetValidatorsByPowerKey(validator, pool)) - // delete subspace - iterator := store.SubspaceIterator(TendermintUpdatesKey) - for ; iterator.Valid(); iterator.Next() { - store.Delete(iterator.Key()) + // delete from the current and power weighted validator groups if the validator + // is bonded - and add validator with zero power to the validator updates + if store.Get(GetValidatorsBondedKey(validator.PubKey)) == nil { + return } - iterator.Close() + store.Delete(GetValidatorsBondedKey(validator.PubKey)) + + bz := k.cdc.MustMarshalBinary(validator.abciValidatorZero(k.cdc)) + store.Set(GetTendermintUpdatesKey(address), bz) } //_____________________________________________________________________ diff --git a/x/stake/keeper_test.go b/x/stake/keeper_test.go index 50bca889b1..f28a2cf684 100644 --- a/x/stake/keeper_test.go +++ b/x/stake/keeper_test.go @@ -283,6 +283,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { require.True(t, found) } resValidators := keeper.GetValidatorsByPower(ctx) + require.Equal(t, nMax, uint16(len(resValidators))) assert.True(ValEq(t, validators[2], resValidators[0])) assert.True(ValEq(t, validators[3], resValidators[1])) @@ -402,7 +403,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) { assert.True(ValEq(t, validators[3], resValidators[1])) // test a swap in voting power - validators[0].PoolShares = NewBondedShares(sdk.NewRat(600)) + validators[0].PoolShares = NewUnbondedShares(sdk.NewRat(600)) validators[0] = keeper.updateValidator(ctx, validators[0]) resValidators = keeper.GetValidatorsByPower(ctx) require.Equal(t, max, len(resValidators)) @@ -418,7 +419,7 @@ func TestClearTendermintUpdates(t *testing.T) { validators := make([]Validator, len(amts)) for i, amt := range amts { validators[i] = NewValidator(addrs[i], pks[i], Description{}) - validators[i].PoolShares = NewBondedShares(sdk.NewRat(amt)) + validators[i].PoolShares = NewUnbondedShares(sdk.NewRat(amt)) validators[i].DelegatorShares = sdk.NewRat(amt) keeper.updateValidator(ctx, validators[i]) } @@ -437,7 +438,7 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) { var validators [2]Validator for i, amt := range amts { validators[i] = NewValidator(addrs[i], pks[i], Description{}) - validators[i].PoolShares = NewBondedShares(sdk.NewRat(amt)) + validators[i].PoolShares = NewUnbondedShares(sdk.NewRat(amt)) validators[i].DelegatorShares = sdk.NewRat(amt) } @@ -475,7 +476,7 @@ func TestGetTendermintUpdatesIdentical(t *testing.T) { var validators [2]Validator for i, amt := range amts { validators[i] = NewValidator(addrs[i], pks[i], Description{}) - validators[i].PoolShares = NewBondedShares(sdk.NewRat(amt)) + validators[i].PoolShares = NewUnbondedShares(sdk.NewRat(amt)) validators[i].DelegatorShares = sdk.NewRat(amt) } validators[0] = keeper.updateValidator(ctx, validators[0]) @@ -497,7 +498,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) { var validators [2]Validator for i, amt := range amts { validators[i] = NewValidator(addrs[i], pks[i], Description{}) - validators[i].PoolShares = NewBondedShares(sdk.NewRat(amt)) + validators[i].PoolShares = NewUnbondedShares(sdk.NewRat(amt)) validators[i].DelegatorShares = sdk.NewRat(amt) } validators[0] = keeper.updateValidator(ctx, validators[0]) @@ -523,7 +524,7 @@ func TestGetTendermintUpdatesMultipleValueChange(t *testing.T) { var validators [2]Validator for i, amt := range amts { validators[i] = NewValidator(addrs[i], pks[i], Description{}) - validators[i].PoolShares = NewBondedShares(sdk.NewRat(amt)) + validators[i].PoolShares = NewUnbondedShares(sdk.NewRat(amt)) validators[i].DelegatorShares = sdk.NewRat(amt) } validators[0] = keeper.updateValidator(ctx, validators[0]) @@ -551,7 +552,7 @@ func TestGetTendermintUpdatesInserted(t *testing.T) { var validators [5]Validator for i, amt := range amts { validators[i] = NewValidator(addrs[i], pks[i], Description{}) - validators[i].PoolShares = NewBondedShares(sdk.NewRat(amt)) + validators[i].PoolShares = NewUnbondedShares(sdk.NewRat(amt)) validators[i].DelegatorShares = sdk.NewRat(amt) } validators[0] = keeper.updateValidator(ctx, validators[0]) @@ -561,7 +562,7 @@ func TestGetTendermintUpdatesInserted(t *testing.T) { // test validtor added at the beginning // tendermintUpdate set: {} -> {c0} - keeper.updateValidator(ctx, validators[2]) + validators[2] = keeper.updateValidator(ctx, validators[2]) updates := keeper.getTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) require.Equal(t, validators[2].abciValidator(keeper.cdc), updates[0]) @@ -569,7 +570,7 @@ func TestGetTendermintUpdatesInserted(t *testing.T) { // test validtor added at the beginning // tendermintUpdate set: {} -> {c0} keeper.clearTendermintUpdates(ctx) - keeper.updateValidator(ctx, validators[3]) + validators[3] = keeper.updateValidator(ctx, validators[3]) updates = keeper.getTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) require.Equal(t, validators[3].abciValidator(keeper.cdc), updates[0]) @@ -577,7 +578,7 @@ func TestGetTendermintUpdatesInserted(t *testing.T) { // test validtor added at the end // tendermintUpdate set: {} -> {c0} keeper.clearTendermintUpdates(ctx) - keeper.updateValidator(ctx, validators[4]) + validators[4] = keeper.updateValidator(ctx, validators[4]) updates = keeper.getTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) require.Equal(t, validators[4].abciValidator(keeper.cdc), updates[0]) @@ -593,7 +594,7 @@ func TestGetTendermintUpdatesNotValidatorCliff(t *testing.T) { var validators [5]Validator for i, amt := range amts { validators[i] = NewValidator(addrs[i], pks[i], Description{}) - validators[i].PoolShares = NewBondedShares(sdk.NewRat(amt)) + validators[i].PoolShares = NewUnbondedShares(sdk.NewRat(amt)) validators[i].DelegatorShares = sdk.NewRat(amt) } validators[0] = keeper.updateValidator(ctx, validators[0]) @@ -612,7 +613,7 @@ func TestGetTendermintUpdatesNotValidatorCliff(t *testing.T) { keeper.clearTendermintUpdates(ctx) assert.Equal(t, 0, len(keeper.getTendermintUpdates(ctx))) - validators[2].PoolShares = NewBondedShares(sdk.NewRat(15)) + validators[2].PoolShares = NewUnbondedShares(sdk.NewRat(15)) validators[2] = keeper.updateValidator(ctx, validators[2]) updates = keeper.getTendermintUpdates(ctx) @@ -742,7 +743,7 @@ func TestPool(t *testing.T) { assert.True(t, expPool.equal(resPool)) //modify a params, save, and retrieve - expPool.TotalSupply = 777 + expPool.BondedTokens = 777 keeper.setPool(ctx, expPool) resPool = keeper.GetPool(ctx) assert.True(t, expPool.equal(resPool)) diff --git a/x/stake/pool.go b/x/stake/pool.go index c062580961..e2547b0503 100644 --- a/x/stake/pool.go +++ b/x/stake/pool.go @@ -8,15 +8,15 @@ import ( // Pool - dynamic parameters of the current state type Pool struct { - TotalSupply int64 `json:"total_supply"` // total supply of all tokens - UnbondedShares sdk.Rat `json:"unbonded_shares"` // sum of all shares distributed for the Unbonded Pool - UnbondingShares sdk.Rat `json:"unbonding_shares"` // shares moving from Bonded to Unbonded Pool - BondedShares sdk.Rat `json:"bonded_shares"` // sum of all shares distributed for the Bonded Pool - UnbondedTokens int64 `json:"unbonded_pool"` // reserve of unbonded tokens held with validators - UnbondingTokens int64 `json:"unbonding_pool"` // tokens moving from bonded to unbonded pool - BondedTokens int64 `json:"bonded_pool"` // reserve of bonded tokens - InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time - Inflation sdk.Rat `json:"inflation"` // current annual inflation rate + LooseUnbondedTokens int64 `json:"loose_unbonded_tokens"` // tokens not associated with any validator + UnbondedTokens int64 `json:"unbonded_tokens"` // reserve of unbonded tokens held with validators + UnbondingTokens int64 `json:"unbonding_tokens"` // tokens moving from bonded to unbonded pool + BondedTokens int64 `json:"bonded_tokens"` // reserve of bonded tokens + UnbondedShares sdk.Rat `json:"unbonded_shares"` // sum of all shares distributed for the Unbonded Pool + UnbondingShares sdk.Rat `json:"unbonding_shares"` // shares moving from Bonded to Unbonded Pool + BondedShares sdk.Rat `json:"bonded_shares"` // sum of all shares distributed for the Bonded Pool + InflationLastTime int64 `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time + Inflation sdk.Rat `json:"inflation"` // current annual inflation rate DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily) @@ -33,13 +33,13 @@ func (p Pool) equal(p2 Pool) bool { // initial pool for testing func initialPool() Pool { return Pool{ - TotalSupply: 0, - BondedShares: sdk.ZeroRat(), - UnbondingShares: sdk.ZeroRat(), - UnbondedShares: sdk.ZeroRat(), + LooseUnbondedTokens: 0, BondedTokens: 0, UnbondingTokens: 0, UnbondedTokens: 0, + BondedShares: sdk.ZeroRat(), + UnbondingShares: sdk.ZeroRat(), + UnbondedShares: sdk.ZeroRat(), InflationLastTime: 0, Inflation: sdk.NewRat(7, 100), DateLastCommissionReset: 0, @@ -49,10 +49,17 @@ func initialPool() Pool { //____________________________________________________________________ +// Sum total of all staking tokens in the pool +func (p Pool) TokenSupply() int64 { + return p.LooseUnbondedTokens + p.UnbondedTokens + p.UnbondingTokens + p.BondedTokens +} + +//____________________________________________________________________ + // get the bond ratio of the global state func (p Pool) bondedRatio() sdk.Rat { - if p.TotalSupply > 0 { - return sdk.NewRat(p.BondedTokens, p.TotalSupply) + if p.TokenSupply() > 0 { + return sdk.NewRat(p.BondedTokens, p.TokenSupply()) } return sdk.ZeroRat() } diff --git a/x/stake/pool_test.go b/x/stake/pool_test.go index 143c33bfb9..99cfa5a127 100644 --- a/x/stake/pool_test.go +++ b/x/stake/pool_test.go @@ -12,14 +12,15 @@ import ( func TestBondedRatio(t *testing.T) { ctx, _, keeper := createTestInput(t, false, 0) pool := keeper.GetPool(ctx) - pool.TotalSupply = 3 + pool.LooseUnbondedTokens = 1 pool.BondedTokens = 2 // bonded pool / total supply require.Equal(t, pool.bondedRatio(), sdk.NewRat(2).Quo(sdk.NewRat(3))) - pool.TotalSupply = 0 // avoids divide-by-zero + pool.LooseUnbondedTokens = 0 + pool.BondedTokens = 0 require.Equal(t, pool.bondedRatio(), sdk.ZeroRat()) } diff --git a/x/stake/tick.go b/x/stake/tick.go index a40427eb36..a8d9457347 100644 --- a/x/stake/tick.go +++ b/x/stake/tick.go @@ -46,9 +46,8 @@ func (k Keeper) processProvisions(ctx sdk.Context) Pool { // more bonded tokens are added proportionally to all validators the only term // which needs to be updated is the `BondedPool`. So for each previsions cycle: - provisions := pool.Inflation.Mul(sdk.NewRat(pool.TotalSupply)).Quo(hrsPerYrRat).Evaluate() + provisions := pool.Inflation.Mul(sdk.NewRat(pool.TokenSupply())).Quo(hrsPerYrRat).Evaluate() pool.BondedTokens += provisions - pool.TotalSupply += provisions return pool } diff --git a/x/stake/tick_test.go b/x/stake/tick_test.go index 967e9408f3..4f0f6dc061 100644 --- a/x/stake/tick_test.go +++ b/x/stake/tick_test.go @@ -1,7 +1,6 @@ package stake import ( - "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -20,35 +19,35 @@ func TestGetInflation(t *testing.T) { // inflationRateChangePerYear = (1- bondedRatio/ GoalBonded) * MaxInflationRateChange tests := []struct { - name string - setBondedPool, setTotalSupply int64 - setInflation, expectedChange sdk.Rat + name string + setBondedTokens, setLooseTokens int64 + setInflation, expectedChange sdk.Rat }{ // with 0% bonded atom supply the inflation should increase by InflationRateChange {"test 1", 0, 0, sdk.NewRat(7, 100), params.InflationRateChange.Quo(hrsPerYrRat).Round(precision)}, // 100% bonded, starting at 20% inflation and being reduced // (1 - (1/0.67))*(0.13/8667) - {"test 2", 1, 1, sdk.NewRat(20, 100), + {"test 2", 1, 0, sdk.NewRat(20, 100), sdk.OneRat().Sub(sdk.OneRat().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)}, // 50% bonded, starting at 10% inflation and being increased - {"test 3", 1, 2, sdk.NewRat(10, 100), + {"test 3", 1, 1, sdk.NewRat(10, 100), sdk.OneRat().Sub(sdk.NewRat(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)}, // test 7% minimum stop (testing with 100% bonded) - {"test 4", 1, 1, sdk.NewRat(7, 100), sdk.ZeroRat()}, - {"test 5", 1, 1, sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000).Round(precision)}, + {"test 4", 1, 0, sdk.NewRat(7, 100), sdk.ZeroRat()}, + {"test 5", 1, 0, sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000).Round(precision)}, // test 20% maximum stop (testing with 0% bonded) {"test 6", 0, 0, sdk.NewRat(20, 100), sdk.ZeroRat()}, {"test 7", 0, 0, sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000).Round(precision)}, // perfect balance shouldn't change inflation - {"test 8", 67, 100, sdk.NewRat(15, 100), sdk.ZeroRat()}, + {"test 8", 67, 33, sdk.NewRat(15, 100), sdk.ZeroRat()}, } for _, tc := range tests { - pool.BondedTokens, pool.TotalSupply = tc.setBondedPool, tc.setTotalSupply + pool.BondedTokens, pool.LooseUnbondedTokens = tc.setBondedTokens, tc.setLooseTokens pool.Inflation = tc.setInflation keeper.setPool(ctx, pool) @@ -67,7 +66,7 @@ func TestProcessProvisions(t *testing.T) { keeper.setParams(ctx, params) pool := keeper.GetPool(ctx) - var totalSupply int64 = 550000000 + var tokenSupply int64 = 550000000 var bondedShares int64 = 150000000 var unbondedShares int64 = 400000000 @@ -75,10 +74,11 @@ func TestProcessProvisions(t *testing.T) { var validators [5]Validator validators[0] = NewValidator(addrs[0], pks[0], Description{}) validators[0], pool, _ = validators[0].addTokensFromDel(pool, 150000000) - validators[0] = keeper.updateValidator(ctx, validators[0]) keeper.setPool(ctx, pool) - assert.Equal(t, bondedShares, pool.BondedTokens, "%v", pool) - fmt.Printf("debug pool: %v validator: %v\n", pool, validators[0]) + validators[0] = keeper.updateValidator(ctx, validators[0]) + pool = keeper.GetPool(ctx) + require.Equal(t, bondedShares, pool.BondedTokens, "%v", pool) + validators[1] = NewValidator(addrs[1], pks[1], Description{}) validators[1], pool, _ = validators[1].addTokensFromDel(pool, 100000000) keeper.setPool(ctx, pool) @@ -96,45 +96,42 @@ func TestProcessProvisions(t *testing.T) { keeper.setPool(ctx, pool) validators[4] = keeper.updateValidator(ctx, validators[4]) - validator, _ := keeper.GetValidator(ctx, addrs[0]) - fmt.Printf("debug validators[0]: %v\n", validator) - - assert.Equal(t, totalSupply, pool.TotalSupply) + assert.Equal(t, tokenSupply, pool.TokenSupply()) assert.Equal(t, bondedShares, pool.BondedTokens) assert.Equal(t, unbondedShares, pool.UnbondedTokens) // initial bonded ratio ~ 27% - assert.True(t, pool.bondedRatio().Equal(sdk.NewRat(bondedShares, totalSupply)), "%v", pool.bondedRatio()) + assert.True(t, pool.bondedRatio().Equal(sdk.NewRat(bondedShares, tokenSupply)), "%v", pool.bondedRatio()) // test the value of validator shares assert.True(t, pool.bondedShareExRate().Equal(sdk.OneRat()), "%v", pool.bondedShareExRate()) - initialSupply := pool.TotalSupply - initialUnbonded := pool.TotalSupply - pool.BondedTokens + initialSupply := pool.TokenSupply() + initialUnbonded := pool.TokenSupply() - pool.BondedTokens // process the provisions a year for hr := 0; hr < 8766; hr++ { pool := keeper.GetPool(ctx) expInflation := keeper.nextInflation(ctx).Round(1000000000) - expProvisions := (expInflation.Mul(sdk.NewRat(pool.TotalSupply)).Quo(hrsPerYrRat)).Evaluate() - startBondedPool := pool.BondedTokens - startTotalSupply := pool.TotalSupply + expProvisions := (expInflation.Mul(sdk.NewRat(pool.TokenSupply())).Quo(hrsPerYrRat)).Evaluate() + startBondedTokens := pool.BondedTokens + startTotalSupply := pool.TokenSupply() pool = keeper.processProvisions(ctx) keeper.setPool(ctx, pool) - //fmt.Printf("hr %v, startBondedPool %v, expProvisions %v, pool.BondedTokens %v\n", hr, startBondedPool, expProvisions, pool.BondedTokens) - require.Equal(t, startBondedPool+expProvisions, pool.BondedTokens, "hr %v", hr) - require.Equal(t, startTotalSupply+expProvisions, pool.TotalSupply) + //fmt.Printf("hr %v, startBondedTokens %v, expProvisions %v, pool.BondedTokens %v\n", hr, startBondedTokens, expProvisions, pool.BondedTokens) + require.Equal(t, startBondedTokens+expProvisions, pool.BondedTokens, "hr %v", hr) + require.Equal(t, startTotalSupply+expProvisions, pool.TokenSupply()) } pool = keeper.GetPool(ctx) - assert.NotEqual(t, initialSupply, pool.TotalSupply) + assert.NotEqual(t, initialSupply, pool.TokenSupply()) assert.Equal(t, initialUnbonded, pool.UnbondedTokens) - //panic(fmt.Sprintf("debug total %v, bonded %v, diff %v\n", p.TotalSupply, p.BondedTokens, pool.TotalSupply-pool.BondedTokens)) + //panic(fmt.Sprintf("debug total %v, bonded %v, diff %v\n", p.TotalSupply, p.BondedTokens, pool.TokenSupply()-pool.BondedTokens)) // initial bonded ratio ~ from 27% to 40% increase for bonded holders ownership of total supply assert.True(t, pool.bondedRatio().Equal(sdk.NewRat(211813022, 611813022)), "%v", pool.bondedRatio()) // global supply - assert.Equal(t, int64(611813022), pool.TotalSupply) + assert.Equal(t, int64(611813022), pool.TokenSupply()) assert.Equal(t, int64(211813022), pool.BondedTokens) assert.Equal(t, unbondedShares, pool.UnbondedTokens) diff --git a/x/stake/validator_test.go b/x/stake/validator_test.go index 22bd601ce1..1ca5ba2f75 100644 --- a/x/stake/validator_test.go +++ b/x/stake/validator_test.go @@ -96,7 +96,6 @@ func TestRemoveShares(t *testing.T) { DelegatorShares: delShares, } pool := Pool{ - TotalSupply: 0, BondedShares: sdk.NewRat(248305), UnbondedShares: sdk.NewRat(232147), BondedTokens: 248305, @@ -136,7 +135,7 @@ func TestUpdateStatus(t *testing.T) { assert.Equal(t, int64(100), pool.UnbondingTokens) assert.Equal(t, int64(0), pool.UnbondedTokens) - val, pool = val.UpdateStatus(pool, sdk.Unbonded) + val, pool = val.UpdateStatus(pool, sdk.Bonded) assert.Equal(t, int64(100), val.PoolShares.Bonded().Evaluate()) assert.Equal(t, int64(0), val.PoolShares.Unbonding().Evaluate()) assert.Equal(t, int64(0), val.PoolShares.Unbonded().Evaluate()) @@ -329,7 +328,6 @@ func TestPossibleOverflow(t *testing.T) { DelegatorShares: delShares, } pool := Pool{ - TotalSupply: 0, BondedShares: poolShares, UnbondedShares: sdk.ZeroRat(), BondedTokens: poolShares.Evaluate(), diff --git a/x/stake/view_slash_keeper_test.go b/x/stake/view_slash_keeper_test.go index a186e62e8d..7f481fc601 100644 --- a/x/stake/view_slash_keeper_test.go +++ b/x/stake/view_slash_keeper_test.go @@ -20,7 +20,7 @@ func TestViewSlashBond(t *testing.T) { validators[i] = Validator{ Owner: addrVals[i], PubKey: pks[i], - PoolShares: NewBondedShares(sdk.NewRat(amt)), + PoolShares: NewUnbondedShares(sdk.NewRat(amt)), DelegatorShares: sdk.NewRat(amt), } }