diff --git a/PENDING.md b/PENDING.md index f699ef463..af4a1193b 100644 --- a/PENDING.md +++ b/PENDING.md @@ -27,10 +27,12 @@ FEATURES * [gov][cli] [\#2479](https://github.com/cosmos/cosmos-sdk/issues/2479) Added governance parameter query commands. * [stake][cli] [\#2027] Add CLI query command for getting all delegations to a specific validator. - + * Gaia + * [app] \#2791 Support export at a specific height, with `gaiad export --height=HEIGHT`. * [x/gov] [#2479](https://github.com/cosmos/cosmos-sdk/issues/2479) Implemented querier for getting governance parameters. + * [app] \#2791 Support export at a specific height, with `gaiad export --height=HEIGHT`. * SDK * [simulator] \#2682 MsgEditValidator now looks at the validator's max rate, thus it now succeeds a significant portion of the time @@ -67,7 +69,7 @@ BUG FIXES * [\#2742](https://github.com/cosmos/cosmos-sdk/issues/2742) Fix time format of TimeoutCommit override * SDK - + - \#2733 [x/gov, x/mock/simulation] Fix governance simulation, update x/gov import/export * Tendermint diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 765d624e9..25265a361 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -324,6 +324,11 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val return appState, validators, nil } +// load a particular height +func (app *GaiaApp) LoadHeight(height int64) error { + return app.LoadVersion(height, app.keyMain) +} + //______________________________________________________________________________________________ // Combined Staking Hooks diff --git a/cmd/gaia/cmd/gaiad/main.go b/cmd/gaia/cmd/gaiad/main.go index ef7b39d11..2a72b42cc 100644 --- a/cmd/gaia/cmd/gaiad/main.go +++ b/cmd/gaia/cmd/gaiad/main.go @@ -64,8 +64,14 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application } func exportAppStateAndTMValidators( - logger log.Logger, db dbm.DB, traceStore io.Writer, + logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, ) (json.RawMessage, []tmtypes.GenesisValidator, error) { gApp := app.NewGaiaApp(logger, db, traceStore) + if height != -1 { + err := gApp.LoadHeight(height) + if err != nil { + return nil, nil, err + } + } return gApp.ExportAppStateAndValidators() } diff --git a/docs/examples/basecoin/cmd/basecoind/main.go b/docs/examples/basecoin/cmd/basecoind/main.go index 0e265d189..731c5135f 100644 --- a/docs/examples/basecoin/cmd/basecoind/main.go +++ b/docs/examples/basecoin/cmd/basecoind/main.go @@ -126,7 +126,7 @@ func newApp(logger log.Logger, db dbm.DB, storeTracer io.Writer) abci.Applicatio return app.NewBasecoinApp(logger, db, baseapp.SetPruning(viper.GetString("pruning"))) } -func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, storeTracer io.Writer) ( +func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, storeTracer io.Writer, _ int64) ( json.RawMessage, []tmtypes.GenesisValidator, error) { bapp := app.NewBasecoinApp(logger, db) return bapp.ExportAppStateAndValidators() diff --git a/docs/examples/democoin/cmd/democoind/main.go b/docs/examples/democoin/cmd/democoind/main.go index 36ea11cc3..506d888a5 100644 --- a/docs/examples/democoin/cmd/democoind/main.go +++ b/docs/examples/democoin/cmd/democoind/main.go @@ -133,7 +133,7 @@ func newApp(logger log.Logger, db dbm.DB, _ io.Writer) abci.Application { return app.NewDemocoinApp(logger, db) } -func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, _ io.Writer) ( +func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, _ io.Writer, _ int64) ( json.RawMessage, []tmtypes.GenesisValidator, error) { dapp := app.NewDemocoinApp(logger, db) return dapp.ExportAppStateAndValidators() diff --git a/docs/gaia/join-testnet.md b/docs/gaia/join-testnet.md index 560bbcf6e..bdbff65e2 100644 --- a/docs/gaia/join-testnet.md +++ b/docs/gaia/join-testnet.md @@ -129,6 +129,21 @@ gaiacli status View the status of the network with the [Cosmos Explorer](https://explorecosmos.network). Once your full node syncs up to the current block height, you should see it appear on the [list of full nodes](https://explorecosmos.network/validators). If it doesn't show up, that's ok--the Explorer does not connect to every node. +## Export State + +Gaia can dump the entire application state to a JSON file, which could be useful for manual analysis and can also be used as the genesis file of a new network. + +Export state with: + +```bash +gaiad export > [filename].json +``` + +You can also export state from a particular height (at the end of processing the block of that height): + +```bash +gaiad export --height=[height] > [filename].json +``` ## Upgrade to Validator Node diff --git a/server/constructors.go b/server/constructors.go index 57282e43b..9039d8a81 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) (json.RawMessage, []tmtypes.GenesisValidator, error) + AppExporter func(log.Logger, dbm.DB, io.Writer, int64) (json.RawMessage, []tmtypes.GenesisValidator, error) ) func openDB(rootDir string) (dbm.DB, error) { diff --git a/server/export.go b/server/export.go index 43ea10866..fbe52eef6 100644 --- a/server/export.go +++ b/server/export.go @@ -13,9 +13,13 @@ import ( "path" ) +const ( + flagHeight = "height" +) + // ExportCmd dumps app state to JSON. func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "export", Short: "Export state to JSON", RunE: func(cmd *cobra.Command, args []string) error { @@ -45,7 +49,8 @@ func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.C if err != nil { return err } - appState, validators, err := appExporter(ctx.Logger, db, traceWriter) + height := viper.GetInt64(flagHeight) + appState, validators, err := appExporter(ctx.Logger, db, traceWriter, height) if err != nil { return errors.Errorf("error exporting state: %v\n", err) } @@ -67,6 +72,8 @@ func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.C return nil }, } + cmd.Flags().Int64(flagHeight, -1, "Export state from a particular height (-1 means latest height)") + return cmd } func isEmptyState(home string) (bool, error) {