diff --git a/PENDING.md b/PENDING.md index 3aef0023fdcd..73e2f4ce3f79 100644 --- a/PENDING.md +++ b/PENDING.md @@ -58,6 +58,7 @@ IMPROVEMENTS * [\#3418](https://github.com/cosmos/cosmos-sdk/issues/3418) Add vesting account genesis validation checks to `GaiaValidateGenesisState`. * [\#3420](https://github.com/cosmos/cosmos-sdk/issues/3420) Added maximum length to governance proposal descriptions and titles + * [\#3454](https://github.com/cosmos/cosmos-sdk/pull/3454) Add `--jail-whitelist` to `gaiad export` to enable testing of complex exports * [\#3424](https://github.com/cosmos/cosmos-sdk/issues/3424) Allow generation of gentxs with empty memo field. * SDK @@ -79,7 +80,7 @@ BUG FIXES - [\#3419](https://github.com/cosmos/cosmos-sdk/pull/3419) Fix `q distr slashes` panic - [\#3453](https://github.com/cosmos/cosmos-sdk/pull/3453) The `rest-server` command didn't respect persistent flags such as `--chain-id` and `--trust-node` if they were passed on the command line. - + * Gaia * SDK diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go index 81f57abd6a6f..0ee1596ea878 100644 --- a/cmd/gaia/app/app_test.go +++ b/cmd/gaia/app/app_test.go @@ -58,6 +58,6 @@ func TestGaiadExport(t *testing.T) { // Making a new app object with the db, so that initchain hasn't been called newGapp := NewGaiaApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true) - _, _, err := newGapp.ExportAppStateAndValidators(false) + _, _, err := newGapp.ExportAppStateAndValidators(false, []string{}) require.NoError(t, err, "ExportAppStateAndValidators should not have an error") } diff --git a/cmd/gaia/app/export.go b/cmd/gaia/app/export.go index edf319cfa1f1..efc9c2051451 100644 --- a/cmd/gaia/app/export.go +++ b/cmd/gaia/app/export.go @@ -2,6 +2,7 @@ package app import ( "encoding/json" + "log" abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" @@ -18,14 +19,14 @@ import ( ) // export the state of gaia for a genesis file -func (app *GaiaApp) ExportAppStateAndValidators(forZeroHeight bool) ( +func (app *GaiaApp) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteList []string) ( appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) { // as if they could withdraw from the start of the next block ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()}) if forZeroHeight { - app.prepForZeroHeightGenesis(ctx) + app.prepForZeroHeightGenesis(ctx, jailWhiteList) } // iterate to get the accounts @@ -56,7 +57,23 @@ func (app *GaiaApp) ExportAppStateAndValidators(forZeroHeight bool) ( } // prepare for fresh start at zero height -func (app *GaiaApp) prepForZeroHeightGenesis(ctx sdk.Context) { +func (app *GaiaApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []string) { + applyWhiteList := false + + //Check if there is a whitelist + if len(jailWhiteList) > 0 { + applyWhiteList = true + } + + whiteListMap := make(map[string]bool) + + for _, addr := range jailWhiteList { + _, err := sdk.ValAddressFromBech32(addr) + if err != nil { + log.Fatal(err) + } + whiteListMap[addr] = true + } /* Just to be safe, assert the invariants on current state. */ app.assertRuntimeInvariantsOnContext(ctx) @@ -136,6 +153,9 @@ func (app *GaiaApp) prepForZeroHeightGenesis(ctx sdk.Context) { validator.BondHeight = 0 validator.UnbondingHeight = 0 valConsAddrs = append(valConsAddrs, validator.ConsAddress()) + if applyWhiteList && !whiteListMap[addr.String()] { + validator.Jailed = true + } app.stakingKeeper.SetValidator(ctx, validator) counter++ @@ -143,6 +163,8 @@ func (app *GaiaApp) prepForZeroHeightGenesis(ctx sdk.Context) { iter.Close() + _ = app.stakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) + /* Handle slashing state. */ // reset start height on signing infos diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index bbb5a2b4e6c4..dae525342a46 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -416,7 +416,7 @@ func TestGaiaImportExport(t *testing.T) { fmt.Printf("Exporting genesis...\n") - appState, _, err := app.ExportAppStateAndValidators(false) + appState, _, err := app.ExportAppStateAndValidators(false, []string{}) if err != nil { panic(err) } @@ -520,7 +520,7 @@ func TestGaiaSimulationAfterImport(t *testing.T) { fmt.Printf("Exporting genesis...\n") - appState, _, err := app.ExportAppStateAndValidators(true) + appState, _, err := app.ExportAppStateAndValidators(true, []string{}) if err != nil { panic(err) } diff --git a/cmd/gaia/cmd/gaiad/main.go b/cmd/gaia/cmd/gaiad/main.go index 00ebb9667a55..d6d88e0dfa30 100644 --- a/cmd/gaia/cmd/gaiad/main.go +++ b/cmd/gaia/cmd/gaiad/main.go @@ -66,7 +66,7 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application } func exportAppStateAndTMValidators( - logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, + logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailWhiteList []string, ) (json.RawMessage, []tmtypes.GenesisValidator, error) { if height != -1 { gApp := app.NewGaiaApp(logger, db, traceStore, false) @@ -74,8 +74,8 @@ func exportAppStateAndTMValidators( if err != nil { return nil, nil, err } - return gApp.ExportAppStateAndValidators(forZeroHeight) + return gApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList) } gApp := app.NewGaiaApp(logger, db, traceStore, true) - return gApp.ExportAppStateAndValidators(forZeroHeight) + return gApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList) } diff --git a/server/constructors.go b/server/constructors.go index 909bda8e2535..5a51937a9a95 100644 --- a/server/constructors.go +++ b/server/constructors.go @@ -19,7 +19,7 @@ type ( // AppExporter is a function that dumps all app state to // JSON-serializable structure and returns the current validator set. - AppExporter func(log.Logger, dbm.DB, io.Writer, int64, bool) (json.RawMessage, []tmtypes.GenesisValidator, error) + AppExporter func(log.Logger, dbm.DB, io.Writer, int64, bool, []string) (json.RawMessage, []tmtypes.GenesisValidator, error) ) func openDB(rootDir string) (dbm.DB, error) { diff --git a/server/export.go b/server/export.go index 16187fa664e5..1637b1dd2e81 100644 --- a/server/export.go +++ b/server/export.go @@ -18,6 +18,7 @@ import ( const ( flagHeight = "height" flagForZeroHeight = "for-zero-height" + flagJailWhitelist = "jail-whitelist" ) // ExportCmd dumps app state to JSON. @@ -54,7 +55,8 @@ func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.C } height := viper.GetInt64(flagHeight) forZeroHeight := viper.GetBool(flagForZeroHeight) - appState, validators, err := appExporter(ctx.Logger, db, traceWriter, height, forZeroHeight) + jailWhiteList := viper.GetStringSlice(flagJailWhitelist) + appState, validators, err := appExporter(ctx.Logger, db, traceWriter, height, forZeroHeight, jailWhiteList) if err != nil { return errors.Errorf("error exporting state: %v\n", err) } @@ -78,6 +80,7 @@ func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.C } cmd.Flags().Int64(flagHeight, -1, "Export state from a particular height (-1 means latest height)") cmd.Flags().Bool(flagForZeroHeight, false, "Export state to start at height zero (perform preproccessing)") + cmd.Flags().StringSlice(flagJailWhitelist, []string{}, "List of validators to not jail state export") return cmd }