From 86f68a3e9549a2b93db89ec0d22f1cd8eb2b7b03 Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 9 Jul 2018 22:51:13 -0400 Subject: [PATCH] prevent zero genesis validators --- cmd/gaia/app/app.go | 6 +++++- cmd/gaia/cmd/gaiadebug/hack.go | 10 +++++---- x/gov/test_common.go | 5 ++++- x/slashing/app_test.go | 5 ++++- x/slashing/test_common.go | 4 +++- x/stake/app_test.go | 5 ++++- x/stake/genesis.go | 11 +++++++++- x/stake/genesis_test.go | 37 ++++++++++++++++++++++++++++++++++ 8 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 x/stake/genesis_test.go diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index b355c4ed51..72defe3012 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -164,7 +164,11 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci } // load the initial stake information - stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData) + err = stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData) + if err != nil { + panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 + // return sdk.ErrGenesisParse("").TraceCause(err, "") + } gov.InitGenesis(ctx, app.govKeeper, gov.DefaultGenesisState()) diff --git a/cmd/gaia/cmd/gaiadebug/hack.go b/cmd/gaia/cmd/gaiadebug/hack.go index ddc8466c76..b06328d134 100644 --- a/cmd/gaia/cmd/gaiadebug/hack.go +++ b/cmd/gaia/cmd/gaiadebug/hack.go @@ -228,8 +228,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci var genesisState gaia.GenesisState err := app.cdc.UnmarshalJSON(stateJSON, &genesisState) if err != nil { - panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 - // return sdk.ErrGenesisParse("").TraceCause(err, "") + panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 // return sdk.ErrGenesisParse("").TraceCause(err, "") } // load the accounts @@ -239,7 +238,10 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci } // load the initial stake information - stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData) - return abci.ResponseInitChain{} + err = stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData) + if err != nil { + panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 // return sdk.ErrGenesisParse("").TraceCause(err, "") + } + return abci.ResponseInitChain{} } diff --git a/x/gov/test_common.go b/x/gov/test_common.go index 70e47e86d7..34dcb4b143 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -61,7 +61,10 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk stakeGenesis := stake.DefaultGenesisState() stakeGenesis.Pool.LooseTokens = 100000 - stake.InitGenesis(ctx, stakeKeeper, stakeGenesis) + err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis) + if err != nil { + panic(err) + } InitGenesis(ctx, keeper, DefaultGenesisState()) return abci.ResponseInitChain{} } diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index d6fb0d9fe8..158eb21812 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -55,7 +55,10 @@ func getInitChainer(mapp *mock.App, keeper stake.Keeper) sdk.InitChainer { mapp.InitChainer(ctx, req) stakeGenesis := stake.DefaultGenesisState() stakeGenesis.Pool.LooseTokens = 100000 - stake.InitGenesis(ctx, keeper, stakeGenesis) + err := stake.InitGenesis(ctx, keeper, stakeGenesis) + if err != nil { + panic(err) + } return abci.ResponseInitChain{} } } diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index 77b553317a..f92778a1f0 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -64,7 +64,9 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, Keep sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace) genesis := stake.DefaultGenesisState() genesis.Pool.LooseTokens = initCoins.MulRaw(int64(len(addrs))).Int64() - stake.InitGenesis(ctx, sk, genesis) + err = stake.InitGenesis(ctx, sk, genesis) + require.Nil(t, err) + for _, addr := range addrs { _, _, err = ck.AddCoins(ctx, addr, sdk.Coins{ {sk.GetParams(ctx).BondDenom, initCoins}, diff --git a/x/stake/app_test.go b/x/stake/app_test.go index 02dd091341..4e39bb18b9 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -62,7 +62,10 @@ func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer { stakeGenesis := DefaultGenesisState() stakeGenesis.Pool.LooseTokens = 100000 - InitGenesis(ctx, keeper, stakeGenesis) + err := InitGenesis(ctx, keeper, stakeGenesis) + if err != nil { + panic(err) + } return abci.ResponseInitChain{} } diff --git a/x/stake/genesis.go b/x/stake/genesis.go index 1116a4748d..7632b9aee1 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -3,6 +3,7 @@ package stake import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/types" + "github.com/pkg/errors" tmtypes "github.com/tendermint/tendermint/types" ) @@ -11,7 +12,7 @@ import ( // validator in the keeper along with manually setting the indexes. In // addition, it also sets any delegations found in data. Finally, it updates // the bonded validators. -func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { +func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error { keeper.SetPool(ctx, data.Pool) keeper.SetNewParams(ctx, data.Params) keeper.InitIntraTxCounter(ctx) @@ -19,6 +20,13 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { for _, validator := range data.Validators { keeper.SetValidator(ctx, validator) + if validator.PoolShares.Amount.IsZero() { + return errors.Errorf("genesis validator cannot have zero power, validator: %v", validator) + } + if validator.DelegatorShares.IsZero() { + return errors.Errorf("genesis validator cannot have zero power, validator: %v", validator) + } + // Manually set indexes for the first time keeper.SetValidatorByPubKeyIndex(ctx, validator) keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool) @@ -33,6 +41,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) { } keeper.UpdateBondedValidatorsFull(ctx) + return nil } // WriteGenesis returns a GenesisState for a given context and keeper. The diff --git a/x/stake/genesis_test.go b/x/stake/genesis_test.go new file mode 100644 index 0000000000..4ad5b3978d --- /dev/null +++ b/x/stake/genesis_test.go @@ -0,0 +1,37 @@ +package stake + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + keep "github.com/cosmos/cosmos-sdk/x/stake/keeper" + "github.com/cosmos/cosmos-sdk/x/stake/types" +) + +func TestInitGenesis(t *testing.T) { + ctx, _, keeper := keep.CreateTestInput(t, false, 1000) + + pool := keeper.GetPool(ctx) + pool.UnbondedTokens = 1 + pool.UnbondedShares = sdk.OneRat() + + params := keeper.GetParams(ctx) + var delegations []Delegation + + validators := []Validator{ + NewValidator(keep.Addrs[0], keep.PKs[0], Description{Moniker: "hoop"}), + } + + genesisState := types.NewGenesisState(pool, params, validators, delegations) + err := InitGenesis(ctx, keeper, genesisState) + require.Error(t, err) + + validators[0].PoolShares.Amount = sdk.OneRat() + validators[0].DelegatorShares = sdk.OneRat() + + genesisState = types.NewGenesisState(pool, params, validators, delegations) + err = InitGenesis(ctx, keeper, genesisState) + require.NoError(t, err) +}