Merge PR #1142: Export validators to genesis
* Validator export skeleton * Update export command, add tests, update CHANGELOG * Rename exportAppState to exportAppStateAndTMValidators
This commit is contained in:
parent
5f409ce832
commit
3fbee11ccc
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
BREAKING CHANGES
|
BREAKING CHANGES
|
||||||
|
|
||||||
|
FEATURES
|
||||||
|
|
||||||
|
IMPROVEMENTS
|
||||||
|
* export command now writes current validator set for Tendermint
|
||||||
|
|
||||||
|
FIXES
|
||||||
* [lcd] Switch to bech32 for addresses on all human readable inputs and outputs
|
* [lcd] Switch to bech32 for addresses on all human readable inputs and outputs
|
||||||
|
|
||||||
## 0.18.0
|
## 0.18.0
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
abci "github.com/tendermint/abci/types"
|
abci "github.com/tendermint/abci/types"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
cmn "github.com/tendermint/tmlibs/common"
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
"github.com/tendermint/tmlibs/log"
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
@ -153,7 +154,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
|
||||||
}
|
}
|
||||||
|
|
||||||
// export the state of gaia for a genesis file
|
// export the state of gaia for a genesis file
|
||||||
func (app *GaiaApp) ExportAppStateJSON() (appState json.RawMessage, err error) {
|
func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) {
|
||||||
ctx := app.NewContext(true, abci.Header{})
|
ctx := app.NewContext(true, abci.Header{})
|
||||||
|
|
||||||
// iterate to get the accounts
|
// iterate to get the accounts
|
||||||
|
@ -169,5 +170,10 @@ func (app *GaiaApp) ExportAppStateJSON() (appState json.RawMessage, err error) {
|
||||||
Accounts: accounts,
|
Accounts: accounts,
|
||||||
StakeData: stake.WriteGenesis(ctx, app.stakeKeeper),
|
StakeData: stake.WriteGenesis(ctx, app.stakeKeeper),
|
||||||
}
|
}
|
||||||
return wire.MarshalJSONIndent(app.cdc, genState)
|
appState, err = wire.MarshalJSONIndent(app.cdc, genState)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
validators = stake.WriteValidators(ctx, app.stakeKeeper)
|
||||||
|
return appState, validators, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -430,6 +430,42 @@ func TestStakeMsgs(t *testing.T) {
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExportValidators(t *testing.T) {
|
||||||
|
gapp := newGaiaApp()
|
||||||
|
|
||||||
|
genCoins, err := sdk.ParseCoins("42steak")
|
||||||
|
require.Nil(t, err)
|
||||||
|
bondCoin, err := sdk.ParseCoin("10steak")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
acc1 := &auth.BaseAccount{
|
||||||
|
Address: addr1,
|
||||||
|
Coins: genCoins,
|
||||||
|
}
|
||||||
|
acc2 := &auth.BaseAccount{
|
||||||
|
Address: addr2,
|
||||||
|
Coins: genCoins,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = setGenesis(gapp, acc1, acc2)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// Create Validator
|
||||||
|
description := stake.NewDescription("foo_moniker", "", "", "")
|
||||||
|
createValidatorMsg := stake.NewMsgCreateValidator(
|
||||||
|
addr1, priv1.PubKey(), bondCoin, description,
|
||||||
|
)
|
||||||
|
SignCheckDeliver(t, gapp, createValidatorMsg, []int64{0}, true, priv1)
|
||||||
|
gapp.Commit()
|
||||||
|
|
||||||
|
// Export validator set
|
||||||
|
_, validators, err := gapp.ExportAppStateAndValidators()
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, 1, len(validators)) // 1 validator
|
||||||
|
require.Equal(t, priv1.PubKey(), validators[0].PubKey)
|
||||||
|
require.Equal(t, int64(10), validators[0].Power)
|
||||||
|
}
|
||||||
|
|
||||||
//____________________________________________________________________________________
|
//____________________________________________________________________________________
|
||||||
|
|
||||||
func CheckBalance(t *testing.T, gapp *GaiaApp, addr sdk.Address, balExpected string) {
|
func CheckBalance(t *testing.T, gapp *GaiaApp, addr sdk.Address, balExpected string) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
abci "github.com/tendermint/abci/types"
|
abci "github.com/tendermint/abci/types"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
"github.com/tendermint/tmlibs/cli"
|
"github.com/tendermint/tmlibs/cli"
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
"github.com/tendermint/tmlibs/log"
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
@ -26,7 +27,7 @@ func main() {
|
||||||
|
|
||||||
server.AddCommands(ctx, cdc, rootCmd, app.GaiaAppInit(),
|
server.AddCommands(ctx, cdc, rootCmd, app.GaiaAppInit(),
|
||||||
server.ConstructAppCreator(newApp, "gaia"),
|
server.ConstructAppCreator(newApp, "gaia"),
|
||||||
server.ConstructAppExporter(exportAppState, "gaia"))
|
server.ConstructAppExporter(exportAppStateAndTMValidators, "gaia"))
|
||||||
|
|
||||||
// prepare and add flags
|
// prepare and add flags
|
||||||
executor := cli.PrepareBaseCmd(rootCmd, "GA", app.DefaultNodeHome)
|
executor := cli.PrepareBaseCmd(rootCmd, "GA", app.DefaultNodeHome)
|
||||||
|
@ -37,7 +38,7 @@ func newApp(logger log.Logger, db dbm.DB) abci.Application {
|
||||||
return app.NewGaiaApp(logger, db)
|
return app.NewGaiaApp(logger, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportAppState(logger log.Logger, db dbm.DB) (json.RawMessage, error) {
|
func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB) (json.RawMessage, []tmtypes.GenesisValidator, error) {
|
||||||
gapp := app.NewGaiaApp(logger, db)
|
gapp := app.NewGaiaApp(logger, db)
|
||||||
return gapp.ExportAppStateJSON()
|
return gapp.ExportAppStateAndValidators()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
abci "github.com/tendermint/abci/types"
|
abci "github.com/tendermint/abci/types"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
cmn "github.com/tendermint/tmlibs/common"
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
"github.com/tendermint/tmlibs/log"
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
@ -155,7 +156,7 @@ func (app *BasecoinApp) initChainer(ctx sdk.Context, req abci.RequestInitChain)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom logic for state export
|
// Custom logic for state export
|
||||||
func (app *BasecoinApp) ExportAppStateJSON() (appState json.RawMessage, err error) {
|
func (app *BasecoinApp) ExportAppStateAndValidators() (appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) {
|
||||||
ctx := app.NewContext(true, abci.Header{})
|
ctx := app.NewContext(true, abci.Header{})
|
||||||
|
|
||||||
// iterate to get the accounts
|
// iterate to get the accounts
|
||||||
|
@ -173,5 +174,10 @@ func (app *BasecoinApp) ExportAppStateJSON() (appState json.RawMessage, err erro
|
||||||
genState := types.GenesisState{
|
genState := types.GenesisState{
|
||||||
Accounts: accounts,
|
Accounts: accounts,
|
||||||
}
|
}
|
||||||
return wire.MarshalJSONIndent(app.cdc, genState)
|
appState, err = wire.MarshalJSONIndent(app.cdc, genState)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
validators = stake.WriteValidators(ctx, app.stakeKeeper)
|
||||||
|
return appState, validators, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
abci "github.com/tendermint/abci/types"
|
abci "github.com/tendermint/abci/types"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
"github.com/tendermint/tmlibs/cli"
|
"github.com/tendermint/tmlibs/cli"
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
"github.com/tendermint/tmlibs/log"
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
@ -27,7 +28,7 @@ func main() {
|
||||||
|
|
||||||
server.AddCommands(ctx, cdc, rootCmd, server.DefaultAppInit,
|
server.AddCommands(ctx, cdc, rootCmd, server.DefaultAppInit,
|
||||||
server.ConstructAppCreator(newApp, "basecoin"),
|
server.ConstructAppCreator(newApp, "basecoin"),
|
||||||
server.ConstructAppExporter(exportAppState, "basecoin"))
|
server.ConstructAppExporter(exportAppStateAndTMValidators, "basecoin"))
|
||||||
|
|
||||||
// prepare and add flags
|
// prepare and add flags
|
||||||
rootDir := os.ExpandEnv("$HOME/.basecoind")
|
rootDir := os.ExpandEnv("$HOME/.basecoind")
|
||||||
|
@ -39,7 +40,7 @@ func newApp(logger log.Logger, db dbm.DB) abci.Application {
|
||||||
return app.NewBasecoinApp(logger, db)
|
return app.NewBasecoinApp(logger, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportAppState(logger log.Logger, db dbm.DB) (json.RawMessage, error) {
|
func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB) (json.RawMessage, []tmtypes.GenesisValidator, error) {
|
||||||
bapp := app.NewBasecoinApp(logger, db)
|
bapp := app.NewBasecoinApp(logger, db)
|
||||||
return bapp.ExportAppStateJSON()
|
return bapp.ExportAppStateAndValidators()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
abci "github.com/tendermint/abci/types"
|
abci "github.com/tendermint/abci/types"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
cmn "github.com/tendermint/tmlibs/common"
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
"github.com/tendermint/tmlibs/log"
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
@ -154,7 +155,7 @@ func (app *DemocoinApp) initChainerFn(coolKeeper cool.Keeper, powKeeper pow.Keep
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom logic for state export
|
// Custom logic for state export
|
||||||
func (app *DemocoinApp) ExportAppStateJSON() (appState json.RawMessage, err error) {
|
func (app *DemocoinApp) ExportAppStateAndValidators() (appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) {
|
||||||
ctx := app.NewContext(true, abci.Header{})
|
ctx := app.NewContext(true, abci.Header{})
|
||||||
|
|
||||||
// iterate to get the accounts
|
// iterate to get the accounts
|
||||||
|
@ -174,5 +175,9 @@ func (app *DemocoinApp) ExportAppStateJSON() (appState json.RawMessage, err erro
|
||||||
POWGenesis: pow.WriteGenesis(ctx, app.powKeeper),
|
POWGenesis: pow.WriteGenesis(ctx, app.powKeeper),
|
||||||
CoolGenesis: cool.WriteGenesis(ctx, app.coolKeeper),
|
CoolGenesis: cool.WriteGenesis(ctx, app.coolKeeper),
|
||||||
}
|
}
|
||||||
return wire.MarshalJSONIndent(app.cdc, genState)
|
appState, err = wire.MarshalJSONIndent(app.cdc, genState)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return appState, validators, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
abci "github.com/tendermint/abci/types"
|
abci "github.com/tendermint/abci/types"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
"github.com/tendermint/tmlibs/cli"
|
"github.com/tendermint/tmlibs/cli"
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
"github.com/tendermint/tmlibs/log"
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
@ -46,9 +47,9 @@ func newApp(logger log.Logger, db dbm.DB) abci.Application {
|
||||||
return app.NewDemocoinApp(logger, db)
|
return app.NewDemocoinApp(logger, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportAppState(logger log.Logger, db dbm.DB) (json.RawMessage, error) {
|
func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB) (json.RawMessage, []tmtypes.GenesisValidator, error) {
|
||||||
dapp := app.NewDemocoinApp(logger, db)
|
dapp := app.NewDemocoinApp(logger, db)
|
||||||
return dapp.ExportAppStateJSON()
|
return dapp.ExportAppStateAndValidators()
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -63,7 +64,7 @@ func main() {
|
||||||
|
|
||||||
server.AddCommands(ctx, cdc, rootCmd, CoolAppInit,
|
server.AddCommands(ctx, cdc, rootCmd, CoolAppInit,
|
||||||
server.ConstructAppCreator(newApp, "democoin"),
|
server.ConstructAppCreator(newApp, "democoin"),
|
||||||
server.ConstructAppExporter(exportAppState, "democoin"))
|
server.ConstructAppExporter(exportAppStateAndTMValidators, "democoin"))
|
||||||
|
|
||||||
// prepare and add flags
|
// prepare and add flags
|
||||||
rootDir := os.ExpandEnv("$HOME/.democoind")
|
rootDir := os.ExpandEnv("$HOME/.democoind")
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
abci "github.com/tendermint/abci/types"
|
abci "github.com/tendermint/abci/types"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
"github.com/tendermint/tmlibs/log"
|
"github.com/tendermint/tmlibs/log"
|
||||||
)
|
)
|
||||||
|
@ -13,8 +14,8 @@ import (
|
||||||
// and other flags (?) to start
|
// and other flags (?) to start
|
||||||
type AppCreator func(string, log.Logger) (abci.Application, error)
|
type AppCreator func(string, log.Logger) (abci.Application, error)
|
||||||
|
|
||||||
// AppExporter dumps all app state to JSON-serializable structure
|
// AppExporter dumps all app state to JSON-serializable structure and returns the current validator set
|
||||||
type AppExporter func(home string, log log.Logger) (json.RawMessage, error)
|
type AppExporter func(home string, log log.Logger) (json.RawMessage, []tmtypes.GenesisValidator, error)
|
||||||
|
|
||||||
// ConstructAppCreator returns an application generation function
|
// ConstructAppCreator returns an application generation function
|
||||||
func ConstructAppCreator(appFn func(log.Logger, dbm.DB) abci.Application, name string) AppCreator {
|
func ConstructAppCreator(appFn func(log.Logger, dbm.DB) abci.Application, name string) AppCreator {
|
||||||
|
@ -30,12 +31,12 @@ func ConstructAppCreator(appFn func(log.Logger, dbm.DB) abci.Application, name s
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConstructAppExporter returns an application export function
|
// ConstructAppExporter returns an application export function
|
||||||
func ConstructAppExporter(appFn func(log.Logger, dbm.DB) (json.RawMessage, error), name string) AppExporter {
|
func ConstructAppExporter(appFn func(log.Logger, dbm.DB) (json.RawMessage, []tmtypes.GenesisValidator, error), name string) AppExporter {
|
||||||
return func(rootDir string, logger log.Logger) (json.RawMessage, error) {
|
return func(rootDir string, logger log.Logger) (json.RawMessage, []tmtypes.GenesisValidator, error) {
|
||||||
dataDir := filepath.Join(rootDir, "data")
|
dataDir := filepath.Join(rootDir, "data")
|
||||||
db, err := dbm.NewGoLevelDB(name, dataDir)
|
db, err := dbm.NewGoLevelDB(name, dataDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return appFn(logger, db)
|
return appFn(logger, db)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ func ExportCmd(ctx *Context, cdc *wire.Codec, appExporter AppExporter) *cobra.Co
|
||||||
Short: "Export state to JSON",
|
Short: "Export state to JSON",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
home := viper.GetString("home")
|
home := viper.GetString("home")
|
||||||
appState, err := appExporter(home, ctx.Logger)
|
appState, validators, err := appExporter(home, ctx.Logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("Error exporting state: %v\n", err)
|
return errors.Errorf("Error exporting state: %v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ func ExportCmd(ctx *Context, cdc *wire.Codec, appExporter AppExporter) *cobra.Co
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
doc.AppStateJSON = appState
|
doc.AppStateJSON = appState
|
||||||
|
doc.Validators = validators
|
||||||
encoded, err := wire.MarshalJSONIndent(cdc, doc)
|
encoded, err := wire.MarshalJSONIndent(cdc, doc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -32,6 +32,7 @@ func BondStatusToString(b BondStatus) string {
|
||||||
|
|
||||||
// validator for a delegated proof of stake system
|
// validator for a delegated proof of stake system
|
||||||
type Validator interface {
|
type Validator interface {
|
||||||
|
GetMoniker() string // moniker of the validator
|
||||||
GetStatus() BondStatus // status of the validator
|
GetStatus() BondStatus // status of the validator
|
||||||
GetOwner() Address // owner address to receive/return validators coins
|
GetOwner() Address // owner address to receive/return validators coins
|
||||||
GetPubKey() crypto.PubKey // validation pubkey
|
GetPubKey() crypto.PubKey // validation pubkey
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package stake
|
package stake
|
||||||
|
|
||||||
import sdk "github.com/cosmos/cosmos-sdk/types"
|
import (
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
// GenesisState - all staking state that must be provided at genesis
|
// GenesisState - all staking state that must be provided at genesis
|
||||||
type GenesisState struct {
|
type GenesisState struct {
|
||||||
|
@ -63,3 +67,16 @@ func WriteGenesis(ctx sdk.Context, k Keeper) GenesisState {
|
||||||
bonds,
|
bonds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteValidators - output current validator set
|
||||||
|
func WriteValidators(ctx sdk.Context, k Keeper) (vals []tmtypes.GenesisValidator) {
|
||||||
|
k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) (stop bool) {
|
||||||
|
vals = append(vals, tmtypes.GenesisValidator{
|
||||||
|
PubKey: validator.GetPubKey(),
|
||||||
|
Power: validator.GetPower().Evaluate(),
|
||||||
|
Name: validator.GetMoniker(),
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -251,6 +251,7 @@ func (v Validator) DelegatorShareExRate(pool Pool) sdk.Rat {
|
||||||
var _ sdk.Validator = Validator{}
|
var _ sdk.Validator = Validator{}
|
||||||
|
|
||||||
// nolint - for sdk.Validator
|
// nolint - for sdk.Validator
|
||||||
|
func (v Validator) GetMoniker() string { return v.Description.Moniker }
|
||||||
func (v Validator) GetStatus() sdk.BondStatus { return v.Status() }
|
func (v Validator) GetStatus() sdk.BondStatus { return v.Status() }
|
||||||
func (v Validator) GetOwner() sdk.Address { return v.Owner }
|
func (v Validator) GetOwner() sdk.Address { return v.Owner }
|
||||||
func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey }
|
func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey }
|
||||||
|
|
Loading…
Reference in New Issue