diff --git a/app/test_common.go b/app/test_common.go index f7ca3b95..099f7a77 100644 --- a/app/test_common.go +++ b/app/test_common.go @@ -72,6 +72,12 @@ func NewTestApp() TestApp { return TestApp{App: *app} } +func NewTestAppFromSealed() TestApp { + db := tmdb.NewMemDB() + app := NewApp(log.NewNopLogger(), db, nil, AppOptions{}) + return TestApp{App: *app} +} + // nolint func (tApp TestApp) GetAccountKeeper() auth.AccountKeeper { return tApp.accountKeeper } func (tApp TestApp) GetBankKeeper() bank.Keeper { return tApp.bankKeeper } diff --git a/cmd/kvd/main.go b/cmd/kvd/main.go index 878e8424..60ad2e1e 100644 --- a/cmd/kvd/main.go +++ b/cmd/kvd/main.go @@ -57,6 +57,7 @@ func main() { genutilcli.InitCmd(ctx, cdc, app.ModuleBasics, app.DefaultNodeHome), genutilcli.CollectGenTxsCmd(ctx, cdc, auth.GenesisAccountIterator{}, app.DefaultNodeHome), migrate.MigrateGenesisCmd(ctx, cdc), + migrate.AssertInvariantsCmd(ctx, cdc), genutilcli.GenTxCmd( ctx, cdc, diff --git a/migrate/cmd.go b/migrate/cmd.go index 0facd30e..b4a34a10 100644 --- a/migrate/cmd.go +++ b/migrate/cmd.go @@ -7,9 +7,11 @@ import ( "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/genutil" "github.com/spf13/cobra" tmtypes "github.com/tendermint/tendermint/types" + "github.com/kava-labs/kava/app" "github.com/kava-labs/kava/migrate/v0_15" ) @@ -48,3 +50,38 @@ func MigrateGenesisCmd(_ *server.Context, cdc *codec.Codec) *cobra.Command { return cmd } + +func AssertInvariantsCmd(_ *server.Context, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "assert-invariants [genesis-file]", + Short: "Validates that the input genesis file is valid and invariants pass", + Long: "Reads the input genesis file into a genesis document, checks that the state is valid and asserts that all invariants pass.", + Example: fmt.Sprintf(`%s assert-invariants /path/to/genesis.json`, version.ServerName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + + importGenesis := args[0] + genDoc, err := tmtypes.GenesisDocFromFile(importGenesis) + if err != nil { + return fmt.Errorf("failed to read genesis document from file %s: %w", importGenesis, err) + } + tApp := app.NewTestAppFromSealed() + var newAppState genutil.AppMap + cdc := app.MakeCodec() + err = cdc.UnmarshalJSON(genDoc.AppState, &newAppState) + if err != nil { + return fmt.Errorf("failed to marchal app state from genesis doc: %s: %w", importGenesis, err) + } + err = app.ModuleBasics.ValidateGenesis(newAppState) + if err != nil { + return fmt.Errorf("genesis doc did not pass validate genesis: %s: %w", importGenesis, err) + } + tApp.InitializeFromGenesisStatesWithTimeAndChainID(genDoc.GenesisTime, genDoc.ChainID, app.GenesisState(newAppState)) + + fmt.Printf("successfully asserted all invariants for %s\n", importGenesis) + return nil + }, + } + + return cmd +} diff --git a/migrate/v0_15/migrate.md b/migrate/v0_15/migrate.md index eb05ef85..ab637520 100644 --- a/migrate/v0_15/migrate.md +++ b/migrate/v0_15/migrate.md @@ -79,6 +79,7 @@ kvd export --for-zero-height --height 1878509 > export-genesis.json # Verify output of genesis migration kvd validate-genesis genesis.json # should say it's valid + kvd assert-invariants genesis.json # should say invariants pass jq -S -c -M '' genesis.json | shasum -a 256 # PLACEHOLDER