Skip to content

Commit

Permalink
remove global shares (cosmos#1644)
Browse files Browse the repository at this point in the history
* wip removing pool shares

* remove PoolShares/Tokens entirely

* worked through stake/type compile error

* work through a bunch of keeper errors

* worked through compile errors

* debugging tests

* resolve compilation error

* resolved types errors

* ...

* move inflation to pool type

* ...

* stumped problem

* Calculate newly issued shares, remove unnecessary pool arg from exchange rate calculation

* Rounding changed

* Update x/slashing tests for sdk.Rat BondedTokens

* testing fixes

* resolved test fixes

* cwgoes comments, changelog, lint

* cli bugfixes

* ..

* cli fixed

* spec update

* 'make format'

* cwgoes comments

* Increase test_cover parallelism
  • Loading branch information
rigelrozanski authored and ebuchman committed Jul 13, 2018
1 parent faa88d8 commit 3231daa
Show file tree
Hide file tree
Showing 41 changed files with 784 additions and 1,419 deletions.
3 changes: 1 addition & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:
test_cover:
<<: *defaults
parallelism: 2
parallelism: 4
steps:
- attach_workspace:
at: /tmp/workspace
Expand All @@ -103,7 +103,6 @@ jobs:
make install
for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | circleci tests split --split-by=timings); do
id=$(basename "$pkg")
GOCACHE=off go test -v -timeout 8m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic "$pkg" | tee "/tmp/logs/$id-$RANDOM.log"
done
- persist_to_workspace:
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

BREAKING CHANGES
* [x/stake] Specify DelegatorAddress in MsgCreateValidator
* [x/stake] Remove the use of global shares in the pool
* Remove the use of `PoolShares` type in `x/stake/validator` type - replace with `Status` `Tokens` fields
* [x/auth] NewAccountMapper takes a constructor instead of a prototype
* [keys] Keybase.Update function now takes in a function to get the newpass, rather than the password itself

Expand Down
5 changes: 2 additions & 3 deletions client/lcd/lcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake"
stakerest "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
)

func init() {
Expand Down Expand Up @@ -834,11 +833,11 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string,
return results[0]
}

func getValidators(t *testing.T, port string) []stakerest.StakeValidatorOutput {
func getValidators(t *testing.T, port string) []stake.BechValidator {
// get the account to get the sequence
res, body := Request(t, port, "GET", "/stake/validators", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var validators []stakerest.StakeValidatorOutput
var validators []stake.BechValidator
err := cdc.UnmarshalJSON([]byte(body), &validators)
require.Nil(t, err)
return validators
Expand Down
2 changes: 1 addition & 1 deletion client/lcd/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress
accAuth.Coins = sdk.Coins{sdk.NewCoin("steak", 100)}
acc := gapp.NewGenesisAccount(&accAuth)
genesisState.Accounts = append(genesisState.Accounts, acc)
genesisState.StakeData.Pool.LooseTokens += 100
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewRat(100))
}

appState, err := wire.MarshalJSONIndent(cdc, genesisState)
Expand Down
4 changes: 2 additions & 2 deletions cmd/gaia/app/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,15 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
}
acc := NewGenesisAccount(&accAuth)
genaccs[i] = acc
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens + freeFermionsAcc // increase the supply
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionsAcc)) // increase the supply

// add the validator
if len(genTx.Name) > 0 {
desc := stake.NewDescription(genTx.Name, "", "", "")
validator := stake.NewValidator(genTx.Address,
sdk.MustGetAccPubKeyBech32(genTx.PubKey), desc)

stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens + freeFermionVal // increase the supply
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionVal)) // increase the supply

// add some new shares to the validator
var issuedDelShares sdk.Rat
Expand Down
4 changes: 2 additions & 2 deletions cmd/gaia/cli_test/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {

validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
require.Equal(t, validator.Owner, barAddr)
require.Equal(t, "2/1", validator.PoolShares.Amount.String())
require.True(sdk.RatEq(t, sdk.NewRat(2), validator.Tokens))

// unbond a single share
unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags)
Expand All @@ -149,7 +149,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc)
*/
validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
require.Equal(t, "1/1", validator.PoolShares.Amount.String())
require.Equal(t, "1/1", validator.Tokens.String())
}

func TestGaiaCLISubmitProposal(t *testing.T) {
Expand Down
22 changes: 6 additions & 16 deletions docs/spec/staking/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,18 @@
- value: `amino(pool)`

The pool is a space for all dynamic global state of the Cosmos Hub. It tracks
information about the total amounts of Atoms in all states, representative
validator shares for stake in the global pools, moving Atom inflation
information, etc.
information about the total amounts of Atoms in all states, moving Atom
inflation information, etc.

```golang
type Pool struct {
LooseTokens int64 // tokens not associated with any validator
UnbondedTokens int64 // reserve of unbonded tokens held with validators
UnbondingTokens int64 // tokens moving from bonded to unbonded pool
LooseTokens int64 // tokens not associated with any bonded validator
BondedTokens int64 // reserve of bonded tokens
UnbondedShares sdk.Rat // sum of all shares distributed for the Unbonded Pool
UnbondingShares sdk.Rat // shares moving from Bonded to Unbonded Pool
BondedShares sdk.Rat // sum of all shares distributed for the Bonded Pool
InflationLastTime int64 // block which the last inflation was processed // TODO make time
Inflation sdk.Rat // current annual inflation rate

DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily)
}

type PoolShares struct {
Status sdk.BondStatus // either: unbonded, unbonding, or bonded
Amount sdk.Rat // total shares of type ShareKind
}
```

### Params
Expand Down Expand Up @@ -85,7 +74,8 @@ type Validator struct {
ConsensusPubKey crypto.PubKey // Tendermint consensus pubkey of validator
Revoked bool // has the validator been revoked?

PoolShares PoolShares // total shares for tokens held in the pool
Status sdk.BondStatus // validator status (bonded/unbonding/unbonded)
Tokens sdk.Rat // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Rat // total shares issued to a validator's delegators
SlashRatio sdk.Rat // increases each time the validator is slashed

Expand All @@ -100,7 +90,7 @@ type Validator struct {
ProposerRewardPool sdk.Coins // reward pool collected from being the proposer

// TODO: maybe this belongs in distribution module ?
PrevPoolShares PoolShares // total shares of a global hold pools
LastBondedTokens sdk.Rat // last bonded token amount
}

type CommissionInfo struct {
Expand Down
6 changes: 3 additions & 3 deletions store/tracekvstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
)

var kvPairs = []KVPair{
KVPair{Key: keyFmt(1), Value: valFmt(1)},
KVPair{Key: keyFmt(2), Value: valFmt(2)},
KVPair{Key: keyFmt(3), Value: valFmt(3)},
{Key: keyFmt(1), Value: valFmt(1)},
{Key: keyFmt(2), Value: valFmt(2)},
{Key: keyFmt(3), Value: valFmt(3)},
}

func newTraceKVStore(w io.Writer) *TraceKVStore {
Expand Down
8 changes: 8 additions & 0 deletions types/rational.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,11 @@ func RatsEqual(r1s, r2s []Rat) bool {
func RatEq(t *testing.T, exp, got Rat) (*testing.T, bool, string, Rat, Rat) {
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp, got
}

// minimum rational between two
func MinRat(r1, r2 Rat) Rat {
if r1.LT(r2) {
return r1
}
return r2
}
7 changes: 6 additions & 1 deletion types/stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,15 @@ func BondStatusToString(b BondStatus) string {
case 0x02:
return "Bonded"
default:
return ""
panic("improper use of BondStatusToString")
}
}

// nolint
func (b BondStatus) Equal(b2 BondStatus) bool {
return byte(b) == byte(b2)
}

// validator for a delegated proof of stake system
type Validator interface {
GetRevoked() bool // whether the validator is revoked
Expand Down
2 changes: 1 addition & 1 deletion x/gov/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk
mapp.InitChainer(ctx, req)

stakeGenesis := stake.DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = 100000
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)

err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions x/slashing/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func getInitChainer(mapp *mock.App, keeper stake.Keeper) sdk.InitChainer {
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
mapp.InitChainer(ctx, req)
stakeGenesis := stake.DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = 100000
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
err := stake.InitGenesis(ctx, keeper, stakeGenesis)
if err != nil {
panic(err)
Expand Down Expand Up @@ -101,8 +101,8 @@ func TestSlashingMsgs(t *testing.T) {

validator := checkValidator(t, mapp, stakeKeeper, addr1, true)
require.Equal(t, addr1, validator.Owner)
require.Equal(t, sdk.Bonded, validator.Status())
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.PoolShares.Bonded()))
require.Equal(t, sdk.Bonded, validator.Status)
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens()))
unrevokeMsg := MsgUnrevoke{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())}

// no signing info yet
Expand Down
6 changes: 3 additions & 3 deletions x/slashing/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func TestHandleAbsentValidator(t *testing.T) {
validator, _ := sk.GetValidatorByPubKey(ctx, val)
require.Equal(t, sdk.Bonded, validator.GetStatus())
pool := sk.GetPool(ctx)
require.Equal(t, int64(amtInt), pool.BondedTokens)
require.Equal(t, int64(amtInt), pool.BondedTokens.RoundInt64())

// 501st block missed
ctx = ctx.WithBlockHeight(height)
Expand Down Expand Up @@ -129,7 +129,7 @@ func TestHandleAbsentValidator(t *testing.T) {

// validator should have been slashed
pool = sk.GetPool(ctx)
require.Equal(t, int64(amtInt-1), pool.BondedTokens)
require.Equal(t, int64(amtInt-1), pool.BondedTokens.RoundInt64())

// validator start height should have been changed
info, found = keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
Expand Down Expand Up @@ -194,5 +194,5 @@ func TestHandleNewValidator(t *testing.T) {
validator, _ := sk.GetValidatorByPubKey(ctx, val)
require.Equal(t, sdk.Bonded, validator.GetStatus())
pool := sk.GetPool(ctx)
require.Equal(t, int64(100), pool.BondedTokens)
require.Equal(t, int64(100), pool.BondedTokens.RoundInt64())
}
4 changes: 3 additions & 1 deletion x/slashing/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, Keep
ck := bank.NewKeeper(accountMapper)
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
genesis := stake.DefaultGenesisState()
genesis.Pool.LooseTokens = initCoins.MulRaw(int64(len(addrs))).Int64()

genesis.Pool.LooseTokens = sdk.NewRat(initCoins.MulRaw(int64(len(addrs))).Int64())

err = stake.InitGenesis(ctx, sk, genesis)
require.Nil(t, err)

Expand Down
10 changes: 5 additions & 5 deletions x/stake/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer {
mapp.InitChainer(ctx, req)

stakeGenesis := DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = 100000
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)

err := InitGenesis(ctx, keeper, stakeGenesis)
if err != nil {
Expand Down Expand Up @@ -135,8 +135,8 @@ func TestStakeMsgs(t *testing.T) {

validator := checkValidator(t, mApp, keeper, addr1, true)
require.Equal(t, addr1, validator.Owner)
require.Equal(t, sdk.Bonded, validator.Status())
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.PoolShares.Bonded()))
require.Equal(t, sdk.Bonded, validator.Status)
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens()))

// addr1 create validator on behalf of addr2
createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(addr1, addr2, priv2.PubKey(), bondCoin, description)
Expand All @@ -147,8 +147,8 @@ func TestStakeMsgs(t *testing.T) {

validator = checkValidator(t, mApp, keeper, addr2, true)
require.Equal(t, addr2, validator.Owner)
require.Equal(t, sdk.Bonded, validator.Status())
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.PoolShares.Bonded()))
require.Equal(t, sdk.Bonded, validator.Status)
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))

// check the bond that should have been created as well
checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewRat(10))
Expand Down
55 changes: 2 additions & 53 deletions x/stake/client/rest/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,57 +215,6 @@ func redHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc {
}
}

// TODO move exist next to validator struct for maintainability
type StakeValidatorOutput struct {
Owner sdk.AccAddress `json:"owner"` // in bech32
PubKey string `json:"pub_key"` // in bech32
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?

PoolShares stake.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 stake.Description `json:"description"` // description terms for the validator
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer

Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators
CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)

// fee related
PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // total shares of a global hold pools
}

func bech32StakeValidatorOutput(validator stake.Validator) (StakeValidatorOutput, error) {
bechValPubkey, err := sdk.Bech32ifyValPub(validator.PubKey)
if err != nil {
return StakeValidatorOutput{}, err
}

return StakeValidatorOutput{
Owner: validator.Owner,
PubKey: bechValPubkey,
Revoked: validator.Revoked,

PoolShares: validator.PoolShares,
DelegatorShares: validator.DelegatorShares,

Description: validator.Description,
BondHeight: validator.BondHeight,
BondIntraTxCounter: validator.BondIntraTxCounter,
ProposerRewardPool: validator.ProposerRewardPool,

Commission: validator.Commission,
CommissionMax: validator.CommissionMax,
CommissionChangeRate: validator.CommissionChangeRate,
CommissionChangeToday: validator.CommissionChangeToday,

PrevBondedShares: validator.PrevBondedShares,
}, nil
}

// TODO bech32
// http request handler to query list of validators
func validatorsHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc {
Expand All @@ -284,7 +233,7 @@ func validatorsHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerF
}

// parse out the validators
validators := make([]StakeValidatorOutput, len(kvs))
validators := make([]types.BechValidator, len(kvs))
for i, kv := range kvs {

addr := kv.Key[1:]
Expand All @@ -295,7 +244,7 @@ func validatorsHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerF
return
}

bech32Validator, err := bech32StakeValidatorOutput(validator)
bech32Validator, err := validator.Bech32Validator()
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
Expand Down
4 changes: 2 additions & 2 deletions x/stake/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error
for _, validator := range data.Validators {
keeper.SetValidator(ctx, validator)

if validator.PoolShares.Amount.IsZero() {
if validator.Tokens.IsZero() {
return errors.Errorf("genesis validator cannot have zero pool shares, validator: %v", validator)
}
if validator.DelegatorShares.IsZero() {
Expand All @@ -31,7 +31,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error
keeper.SetValidatorByPubKeyIndex(ctx, validator)
keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool)

if validator.Status() == sdk.Bonded {
if validator.Status == sdk.Bonded {
keeper.SetValidatorBondedIndex(ctx, validator)
}
}
Expand Down
5 changes: 2 additions & 3 deletions x/stake/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ func TestInitGenesis(t *testing.T) {
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)

pool := keeper.GetPool(ctx)
pool.UnbondedTokens = 1
pool.UnbondedShares = sdk.OneRat()
pool.LooseTokens = sdk.OneRat()

params := keeper.GetParams(ctx)
var delegations []Delegation
Expand All @@ -28,7 +27,7 @@ func TestInitGenesis(t *testing.T) {
err := InitGenesis(ctx, keeper, genesisState)
require.Error(t, err)

validators[0].PoolShares.Amount = sdk.OneRat()
validators[0].Tokens = sdk.OneRat()
validators[0].DelegatorShares = sdk.OneRat()

genesisState = types.NewGenesisState(pool, params, validators, delegations)
Expand Down
Loading

0 comments on commit 3231daa

Please sign in to comment.