remove old init package

This commit is contained in:
rhuairahrighairigh 2019-07-18 19:05:57 +01:00
parent cfbd4e92aa
commit 566c0258a6
11 changed files with 0 additions and 1601 deletions

View File

@ -1,145 +0,0 @@
package init
// DONTCOVER
import (
"encoding/json"
"path/filepath"
"github.com/spf13/cobra"
"github.com/spf13/viper"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/kava-labs/kava/app"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/x/auth"
)
const (
flagGenTxDir = "gentx-dir"
)
type initConfig struct {
ChainID string
GenTxsDir string
Name string
NodeID string
ValPubKey crypto.PubKey
}
// nolint
func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "collect-gentxs",
Short: "Collect genesis txs and output a genesis.json file",
RunE: func(_ *cobra.Command, _ []string) error {
config := ctx.Config
config.SetRoot(viper.GetString(cli.HomeFlag))
name := viper.GetString(client.FlagName)
nodeID, valPubKey, err := InitializeNodeValidatorFiles(config)
if err != nil {
return err
}
genDoc, err := LoadGenesisDoc(cdc, config.GenesisFile())
if err != nil {
return err
}
genTxsDir := viper.GetString(flagGenTxDir)
if genTxsDir == "" {
genTxsDir = filepath.Join(config.RootDir, "config", "gentx")
}
toPrint := newPrintInfo(config.Moniker, genDoc.ChainID, nodeID, genTxsDir, json.RawMessage(""))
initCfg := newInitConfig(genDoc.ChainID, genTxsDir, name, nodeID, valPubKey)
appMessage, err := genAppStateFromConfig(cdc, config, initCfg, genDoc)
if err != nil {
return err
}
toPrint.AppMessage = appMessage
// print out some key information
return displayInfo(cdc, toPrint)
},
}
cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().String(flagGenTxDir, "",
"override default \"gentx\" directory from which collect and execute "+
"genesis transactions; default [--home]/config/gentx/")
return cmd
}
func genAppStateFromConfig(
cdc *codec.Codec, config *cfg.Config, initCfg initConfig, genDoc types.GenesisDoc,
) (appState json.RawMessage, err error) {
genFile := config.GenesisFile()
var (
appGenTxs []auth.StdTx
persistentPeers string
genTxs []json.RawMessage
jsonRawTx json.RawMessage
)
// process genesis transactions, else create default genesis.json
appGenTxs, persistentPeers, err = app.CollectStdTxs(
cdc, config.Moniker, initCfg.GenTxsDir, genDoc,
)
if err != nil {
return
}
genTxs = make([]json.RawMessage, len(appGenTxs))
config.P2P.PersistentPeers = persistentPeers
for i, stdTx := range appGenTxs {
jsonRawTx, err = cdc.MarshalJSON(stdTx)
if err != nil {
return
}
genTxs[i] = jsonRawTx
}
cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
appState, err = app.AppGenStateJSON(cdc, genDoc, genTxs)
if err != nil {
return
}
err = ExportGenesisFile(genFile, initCfg.ChainID, nil, appState)
return
}
func newInitConfig(chainID, genTxsDir, name, nodeID string,
valPubKey crypto.PubKey) initConfig {
return initConfig{
ChainID: chainID,
GenTxsDir: genTxsDir,
Name: name,
NodeID: nodeID,
ValPubKey: valPubKey,
}
}
func newPrintInfo(moniker, chainID, nodeID, genTxsDir string,
appMessage json.RawMessage) printInfo {
return printInfo{
Moniker: moniker,
ChainID: chainID,
NodeID: nodeID,
GenTxsDir: genTxsDir,
AppMessage: appMessage,
}
}

View File

@ -1,141 +0,0 @@
package init
import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/kava-labs/kava/app"
)
// AddGenesisAccountCmd returns add-genesis-account cobra Command.
func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]",
Short: "Add genesis account to genesis.json",
Args: cobra.ExactArgs(2),
RunE: func(_ *cobra.Command, args []string) error {
config := ctx.Config
config.SetRoot(viper.GetString(cli.HomeFlag))
addr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
kb, err := keys.NewKeyBaseFromDir(viper.GetString(flagClientHome))
if err != nil {
return err
}
info, err := kb.Get(args[0])
if err != nil {
return err
}
addr = info.GetAddress()
}
coins, err := sdk.ParseCoins(args[1])
if err != nil {
return err
}
vestingStart := viper.GetInt64(flagVestingStart)
vestingEnd := viper.GetInt64(flagVestingEnd)
vestingAmt, err := sdk.ParseCoins(viper.GetString(flagVestingAmt))
if err != nil {
return err
}
genFile := config.GenesisFile()
if !common.FileExists(genFile) {
return fmt.Errorf("%s does not exist, run `kvd init` first", genFile)
}
genDoc, err := LoadGenesisDoc(cdc, genFile)
if err != nil {
return err
}
var appState app.GenesisState
if err = cdc.UnmarshalJSON(genDoc.AppState, &appState); err != nil {
return err
}
appState, err = addGenesisAccount(cdc, appState, addr, coins, vestingAmt, vestingStart, vestingEnd)
if err != nil {
return err
}
appStateJSON, err := cdc.MarshalJSON(appState)
if err != nil {
return err
}
return ExportGenesisFile(genFile, genDoc.ChainID, nil, appStateJSON)
},
}
cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory")
cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts")
cmd.Flags().Uint64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts")
cmd.Flags().Uint64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts")
return cmd
}
func addGenesisAccount(
cdc *codec.Codec, appState app.GenesisState, addr sdk.AccAddress,
coins, vestingAmt sdk.Coins, vestingStart, vestingEnd int64,
) (app.GenesisState, error) {
for _, stateAcc := range appState.Accounts {
if stateAcc.Address.Equals(addr) {
return appState, fmt.Errorf("the application state already contains account %v", addr)
}
}
acc := auth.NewBaseAccountWithAddress(addr)
acc.Coins = coins
if !vestingAmt.IsZero() {
var vacc auth.VestingAccount
bvacc := &auth.BaseVestingAccount{
BaseAccount: &acc,
OriginalVesting: vestingAmt,
EndTime: vestingEnd,
}
if bvacc.OriginalVesting.IsAllGT(acc.Coins) {
return appState, fmt.Errorf("vesting amount cannot be greater than total amount")
}
if vestingStart >= vestingEnd {
return appState, fmt.Errorf("vesting start time must before end time")
}
if vestingStart != 0 {
vacc = &auth.ContinuousVestingAccount{
BaseVestingAccount: bvacc,
StartTime: vestingStart,
}
} else {
vacc = &auth.DelayedVestingAccount{
BaseVestingAccount: bvacc,
}
}
appState.Accounts = append(appState.Accounts, app.NewGenesisAccountI(vacc))
} else {
appState.Accounts = append(appState.Accounts, app.NewGenesisAccount(&acc))
}
return appState, nil
}

View File

@ -1,88 +0,0 @@
package init
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/kava-labs/kava/app"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func TestAddGenesisAccount(t *testing.T) {
cdc := codec.New()
addr1 := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
type args struct {
appState app.GenesisState
addr sdk.AccAddress
coins sdk.Coins
vestingAmt sdk.Coins
vestingStart int64
vestingEnd int64
}
tests := []struct {
name string
args args
wantErr bool
}{
{
"valid account",
args{
app.GenesisState{},
addr1,
sdk.NewCoins(),
sdk.NewCoins(),
0,
0,
},
false,
},
{
"dup account",
args{
app.GenesisState{Accounts: []app.GenesisAccount{{Address: addr1}}},
addr1,
sdk.NewCoins(),
sdk.NewCoins(),
0,
0,
},
true,
},
{
"invalid vesting amount",
args{
app.GenesisState{},
addr1,
sdk.NewCoins(sdk.NewInt64Coin("stake", 50)),
sdk.NewCoins(sdk.NewInt64Coin("stake", 100)),
0,
0,
},
true,
},
{
"invalid vesting times",
args{
app.GenesisState{},
addr1,
sdk.NewCoins(sdk.NewInt64Coin("stake", 50)),
sdk.NewCoins(sdk.NewInt64Coin("stake", 50)),
1654668078,
1554668078,
},
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := addGenesisAccount(
cdc, tt.args.appState, tt.args.addr, tt.args.coins,
tt.args.vestingAmt, tt.args.vestingStart, tt.args.vestingEnd,
)
require.Equal(t, tt.wantErr, (err != nil))
})
}
}

View File

@ -1,312 +0,0 @@
package init
// DONTCOVER
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/spf13/viper"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/codec"
kbkeys "github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/staking/client/cli"
"github.com/kava-labs/kava/app"
)
var (
defaultTokens = sdk.TokensFromTendermintPower(100)
defaultAmount = defaultTokens.String() + sdk.DefaultBondDenom
defaultCommissionRate = "0.1"
defaultCommissionMaxRate = "0.2"
defaultCommissionMaxChangeRate = "0.01"
defaultMinSelfDelegation = "1"
)
// GenTxCmd builds the kvd gentx command.
// nolint: errcheck
func GenTxCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "gentx",
Short: "Generate a genesis tx carrying a self delegation",
Args: cobra.NoArgs,
Long: fmt.Sprintf(`This command is an alias of the 'kvd tx create-validator' command'.
It creates a genesis piece carrying a self delegation with the
following delegation and commission default parameters:
delegation amount: %s
commission rate: %s
commission max rate: %s
commission max change rate: %s
minimum self delegation: %s
`, defaultAmount, defaultCommissionRate, defaultCommissionMaxRate, defaultCommissionMaxChangeRate, defaultMinSelfDelegation),
RunE: func(cmd *cobra.Command, args []string) error {
config := ctx.Config
config.SetRoot(viper.GetString(tmcli.HomeFlag))
nodeID, valPubKey, err := InitializeNodeValidatorFiles(ctx.Config)
if err != nil {
return err
}
// Read --nodeID, if empty take it from priv_validator.json
if nodeIDString := viper.GetString(cli.FlagNodeID); nodeIDString != "" {
nodeID = nodeIDString
}
ip := viper.GetString(cli.FlagIP)
if ip == "" {
fmt.Fprintf(os.Stderr, "couldn't retrieve an external IP; "+
"the tx's memo field will be unset")
}
genDoc, err := LoadGenesisDoc(cdc, config.GenesisFile())
if err != nil {
return err
}
genesisState := app.GenesisState{}
if err = cdc.UnmarshalJSON(genDoc.AppState, &genesisState); err != nil {
return err
}
if err = app.ValidateGenesisState(genesisState); err != nil {
return err
}
kb, err := keys.NewKeyBaseFromDir(viper.GetString(flagClientHome))
if err != nil {
return err
}
name := viper.GetString(client.FlagName)
key, err := kb.Get(name)
if err != nil {
return err
}
// Read --pubkey, if empty take it from priv_validator.json
if valPubKeyString := viper.GetString(cli.FlagPubKey); valPubKeyString != "" {
valPubKey, err = sdk.GetConsPubKeyBech32(valPubKeyString)
if err != nil {
return err
}
}
website := viper.GetString(cli.FlagWebsite)
details := viper.GetString(cli.FlagDetails)
identity := viper.GetString(cli.FlagIdentity)
// Set flags for creating gentx
prepareFlagsForTxCreateValidator(config, nodeID, ip, genDoc.ChainID, valPubKey, website, details, identity)
// Fetch the amount of coins staked
amount := viper.GetString(cli.FlagAmount)
coins, err := sdk.ParseCoins(amount)
if err != nil {
return err
}
err = accountInGenesis(genesisState, key.GetAddress(), coins)
if err != nil {
return err
}
txBldr := authtxb.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)
// XXX: Set the generate-only flag here after the CLI context has
// been created. This allows the from name/key to be correctly populated.
//
// TODO: Consider removing the manual setting of generate-only in
// favor of a 'gentx' flag in the create-validator command.
viper.Set(client.FlagGenerateOnly, true)
// create a 'create-validator' message
txBldr, msg, err := cli.BuildCreateValidatorMsg(cliCtx, txBldr)
if err != nil {
return err
}
info, err := txBldr.Keybase().Get(name)
if err != nil {
return err
}
if info.GetType() == kbkeys.TypeOffline || info.GetType() == kbkeys.TypeMulti {
fmt.Println("Offline key passed in. Use `kvcli tx sign` command to sign:")
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, true)
}
// write the unsigned transaction to the buffer
w := bytes.NewBuffer([]byte{})
cliCtx = cliCtx.WithOutput(w)
if err = utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, true); err != nil {
return err
}
// read the transaction
stdTx, err := readUnsignedGenTxFile(cdc, w)
if err != nil {
return err
}
// sign the transaction and write it to the output file
signedTx, err := utils.SignStdTx(txBldr, cliCtx, name, stdTx, false, true)
if err != nil {
return err
}
// Fetch output file name
outputDocument := viper.GetString(client.FlagOutputDocument)
if outputDocument == "" {
outputDocument, err = makeOutputFilepath(config.RootDir, nodeID)
if err != nil {
return err
}
}
if err := writeSignedGenTx(cdc, outputDocument, signedTx); err != nil {
return err
}
fmt.Fprintf(os.Stderr, "Genesis transaction written to %q\n", outputDocument)
return nil
},
}
ip, _ := server.ExternalIP()
cmd.Flags().String(tmcli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory")
cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx")
cmd.Flags().String(client.FlagOutputDocument, "",
"write the genesis transaction JSON document to the given file instead of the default location")
cmd.Flags().String(cli.FlagIP, ip, "The node's public IP")
cmd.Flags().String(cli.FlagNodeID, "", "The node's NodeID")
cmd.Flags().String(cli.FlagWebsite, "", "The validator's (optional) website")
cmd.Flags().String(cli.FlagDetails, "", "The validator's (optional) details")
cmd.Flags().String(cli.FlagIdentity, "", "The (optional) identity signature (ex. UPort or Keybase)")
cmd.Flags().AddFlagSet(cli.FsCommissionCreate)
cmd.Flags().AddFlagSet(cli.FsMinSelfDelegation)
cmd.Flags().AddFlagSet(cli.FsAmount)
cmd.Flags().AddFlagSet(cli.FsPk)
cmd.MarkFlagRequired(client.FlagName)
return cmd
}
func accountInGenesis(genesisState app.GenesisState, key sdk.AccAddress, coins sdk.Coins) error {
accountIsInGenesis := false
bondDenom := genesisState.StakingData.Params.BondDenom
// Check if the account is in genesis
for _, acc := range genesisState.Accounts {
// Ensure that account is in genesis
if acc.Address.Equals(key) {
// Ensure account contains enough funds of default bond denom
if coins.AmountOf(bondDenom).GT(acc.Coins.AmountOf(bondDenom)) {
return fmt.Errorf(
"account %v is in genesis, but it only has %v%v available to stake, not %v%v",
key.String(), acc.Coins.AmountOf(bondDenom), bondDenom, coins.AmountOf(bondDenom), bondDenom,
)
}
accountIsInGenesis = true
break
}
}
if accountIsInGenesis {
return nil
}
return fmt.Errorf("account %s in not in the app_state.accounts array of genesis.json", key)
}
func prepareFlagsForTxCreateValidator(
config *cfg.Config, nodeID, ip, chainID string, valPubKey crypto.PubKey, website, details, identity string,
) {
viper.Set(tmcli.HomeFlag, viper.GetString(flagClientHome))
viper.Set(client.FlagChainID, chainID)
viper.Set(client.FlagFrom, viper.GetString(client.FlagName))
viper.Set(cli.FlagNodeID, nodeID)
viper.Set(cli.FlagIP, ip)
viper.Set(cli.FlagPubKey, sdk.MustBech32ifyConsPub(valPubKey))
viper.Set(cli.FlagMoniker, config.Moniker)
viper.Set(cli.FlagWebsite, website)
viper.Set(cli.FlagDetails, details)
viper.Set(cli.FlagIdentity, identity)
if config.Moniker == "" {
viper.Set(cli.FlagMoniker, viper.GetString(client.FlagName))
}
if viper.GetString(cli.FlagAmount) == "" {
viper.Set(cli.FlagAmount, defaultAmount)
}
if viper.GetString(cli.FlagCommissionRate) == "" {
viper.Set(cli.FlagCommissionRate, defaultCommissionRate)
}
if viper.GetString(cli.FlagCommissionMaxRate) == "" {
viper.Set(cli.FlagCommissionMaxRate, defaultCommissionMaxRate)
}
if viper.GetString(cli.FlagCommissionMaxChangeRate) == "" {
viper.Set(cli.FlagCommissionMaxChangeRate, defaultCommissionMaxChangeRate)
}
if viper.GetString(cli.FlagMinSelfDelegation) == "" {
viper.Set(cli.FlagMinSelfDelegation, defaultMinSelfDelegation)
}
}
func makeOutputFilepath(rootDir, nodeID string) (string, error) {
writePath := filepath.Join(rootDir, "config", "gentx")
if err := common.EnsureDir(writePath, 0700); err != nil {
return "", err
}
return filepath.Join(writePath, fmt.Sprintf("gentx-%v.json", nodeID)), nil
}
func readUnsignedGenTxFile(cdc *codec.Codec, r io.Reader) (auth.StdTx, error) {
var stdTx auth.StdTx
bytes, err := ioutil.ReadAll(r)
if err != nil {
return stdTx, err
}
err = cdc.UnmarshalJSON(bytes, &stdTx)
return stdTx, err
}
// nolint: errcheck
func writeSignedGenTx(cdc *codec.Codec, outputDocument string, tx auth.StdTx) error {
outputFile, err := os.OpenFile(outputDocument, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer outputFile.Close()
json, err := cdc.MarshalJSON(tx)
if err != nil {
return err
}
_, err = fmt.Fprintf(outputFile, "%s\n", json)
return err
}

View File

@ -1,85 +0,0 @@
package init
import (
"testing"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/client/cli"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/log"
)
func Test_prepareFlagsForTxCreateValidator(t *testing.T) {
defer server.SetupViper(t)()
defer setupClientHome(t)()
config, err := tcmd.ParseConfig()
require.Nil(t, err)
logger := log.NewNopLogger()
ctx := server.NewContext(config, logger)
valPubKey, _ := sdk.GetConsPubKeyBech32("cosmosvalconspub1zcjduepq7jsrkl9fgqk0wj3ahmfr8pgxj6vakj2wzn656s8pehh0zhv2w5as5gd80a")
type args struct {
config *cfg.Config
nodeID string
ip string
chainID string
valPubKey crypto.PubKey
website string
details string
identity string
}
type extraParams struct {
amount string
commissionRate string
commissionMaxRate string
commissionMaxChangeRate string
minSelfDelegation string
}
type testcase struct {
name string
args args
}
runTest := func(t *testing.T, tt testcase, params extraParams) {
prepareFlagsForTxCreateValidator(tt.args.config, tt.args.nodeID, tt.args.ip, tt.args.chainID, tt.args.valPubKey, tt.args.website, tt.args.details, tt.args.identity)
require.Equal(t, tt.args.website, viper.GetString(cli.FlagWebsite))
require.Equal(t, tt.args.details, viper.GetString(cli.FlagDetails))
require.Equal(t, tt.args.identity, viper.GetString(cli.FlagIdentity))
require.Equal(t, params.amount, viper.GetString(cli.FlagAmount))
require.Equal(t, params.commissionRate, viper.GetString(cli.FlagCommissionRate))
require.Equal(t, params.commissionMaxRate, viper.GetString(cli.FlagCommissionMaxRate))
require.Equal(t, params.commissionMaxChangeRate, viper.GetString(cli.FlagCommissionMaxChangeRate))
require.Equal(t, params.minSelfDelegation, viper.GetString(cli.FlagMinSelfDelegation))
}
tests := []testcase{
{"No parameters", args{ctx.Config, "X", "0.0.0.0", "chainId", valPubKey, "", "", ""}},
{"Optional parameters fed", args{ctx.Config, "X", "0.0.0.0", "chainId", valPubKey, "cosmos.network", "details", "identity"}},
}
defaultParams := extraParams{defaultAmount, defaultCommissionRate, defaultCommissionMaxRate, defaultCommissionMaxChangeRate, defaultMinSelfDelegation}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { runTest(t, tt, defaultParams) })
})
}
// Override default params
params := extraParams{"5stake", "1.0", "1.0", "1.0", "1.0"}
viper.Set(cli.FlagAmount, params.amount)
viper.Set(cli.FlagCommissionRate, params.commissionRate)
viper.Set(cli.FlagCommissionMaxRate, params.commissionMaxRate)
viper.Set(cli.FlagCommissionMaxChangeRate, params.commissionMaxChangeRate)
viper.Set(cli.FlagMinSelfDelegation, params.minSelfDelegation)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { runTest(t, tt, params) })
}
}

View File

@ -1,95 +0,0 @@
package init
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/spf13/viper"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/client"
"github.com/kava-labs/kava/app"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
)
const (
flagOverwrite = "overwrite"
flagClientHome = "home-client"
flagVestingStart = "vesting-start-time"
flagVestingEnd = "vesting-end-time"
flagVestingAmt = "vesting-amount"
)
type printInfo struct {
Moniker string `json:"moniker"`
ChainID string `json:"chain_id"`
NodeID string `json:"node_id"`
GenTxsDir string `json:"gentxs_dir"`
AppMessage json.RawMessage `json:"app_message"`
}
func displayInfo(cdc *codec.Codec, info printInfo) error {
out, err := codec.MarshalJSONIndent(cdc, info)
if err != nil {
return err
}
fmt.Fprintf(os.Stderr, "%s\n", string(out)) // nolint: errcheck
return nil
}
// InitCmd returns a command that initializes all files needed for Tendermint
// and the respective application.
func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { // nolint: golint
cmd := &cobra.Command{
Use: "init [moniker]",
Short: "Initialize private validator, p2p, genesis, and application configuration files",
Long: `Initialize validators's and node's configuration files.`,
Args: cobra.ExactArgs(1),
RunE: func(_ *cobra.Command, args []string) error {
config := ctx.Config
config.SetRoot(viper.GetString(cli.HomeFlag))
chainID := viper.GetString(client.FlagChainID)
if chainID == "" {
chainID = fmt.Sprintf("test-chain-%v", common.RandStr(6))
}
nodeID, _, err := InitializeNodeValidatorFiles(config)
if err != nil {
return err
}
config.Moniker = args[0]
var appState json.RawMessage
genFile := config.GenesisFile()
if appState, err = initializeEmptyGenesis(cdc, genFile, chainID,
viper.GetBool(flagOverwrite)); err != nil {
return err
}
if err = ExportGenesisFile(genFile, chainID, nil, appState); err != nil {
return err
}
toPrint := newPrintInfo(config.Moniker, chainID, nodeID, "", appState)
cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
return displayInfo(cdc, toPrint)
},
}
cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the genesis.json file")
cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
return cmd
}

View File

@ -1,136 +0,0 @@
package init
import (
"bytes"
"io"
"io/ioutil"
"os"
"testing"
"time"
"github.com/cosmos/cosmos-sdk/client"
"github.com/kava-labs/kava/app"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/mock"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
abciServer "github.com/tendermint/tendermint/abci/server"
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
"github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/log"
)
func TestInitCmd(t *testing.T) {
defer server.SetupViper(t)()
defer setupClientHome(t)()
logger := log.NewNopLogger()
cfg, err := tcmd.ParseConfig()
require.Nil(t, err)
ctx := server.NewContext(cfg, logger)
cdc := app.MakeCodec()
cmd := InitCmd(ctx, cdc)
require.NoError(t, cmd.RunE(nil, []string{"kavanode-test"}))
}
func setupClientHome(t *testing.T) func() {
clientDir, err := ioutil.TempDir("", "mock-sdk-cmd")
require.Nil(t, err)
viper.Set(flagClientHome, clientDir)
return func() {
if err := os.RemoveAll(clientDir); err != nil {
// TODO: Handle with #870
panic(err)
}
}
}
func TestEmptyState(t *testing.T) {
defer server.SetupViper(t)()
defer setupClientHome(t)()
logger := log.NewNopLogger()
cfg, err := tcmd.ParseConfig()
require.Nil(t, err)
ctx := server.NewContext(cfg, logger)
cdc := app.MakeCodec()
cmd := InitCmd(ctx, cdc)
require.NoError(t, cmd.RunE(nil, []string{"kavanode-test"}))
old := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
cmd = server.ExportCmd(ctx, cdc, nil)
err = cmd.RunE(nil, nil)
require.NoError(t, err)
outC := make(chan string)
go func() {
var buf bytes.Buffer
io.Copy(&buf, r)
outC <- buf.String()
}()
w.Close()
os.Stdout = old
out := <-outC
require.Contains(t, out, "genesis_time")
require.Contains(t, out, "chain_id")
require.Contains(t, out, "consensus_params")
require.Contains(t, out, "validators")
require.Contains(t, out, "app_hash")
}
func TestStartStandAlone(t *testing.T) {
home, err := ioutil.TempDir("", "mock-sdk-cmd")
require.Nil(t, err)
defer func() {
os.RemoveAll(home)
}()
viper.Set(cli.HomeFlag, home)
defer setupClientHome(t)()
logger := log.NewNopLogger()
cfg, err := tcmd.ParseConfig()
require.Nil(t, err)
ctx := server.NewContext(cfg, logger)
cdc := app.MakeCodec()
initCmd := InitCmd(ctx, cdc)
require.NoError(t, initCmd.RunE(nil, []string{"kavanode-test"}))
app, err := mock.NewApp(home, logger)
require.Nil(t, err)
svrAddr, _, err := server.FreeTCPAddr()
require.Nil(t, err)
svr, err := abciServer.NewServer(svrAddr, "socket", app)
require.Nil(t, err, "error creating listener")
svr.SetLogger(logger.With("module", "abci-server"))
svr.Start()
timer := time.NewTimer(time.Duration(2) * time.Second)
select {
case <-timer.C:
svr.Stop()
}
}
func TestInitNodeValidatorFiles(t *testing.T) {
home, err := ioutil.TempDir("", "mock-sdk-cmd")
require.Nil(t, err)
defer func() {
os.RemoveAll(home)
}()
viper.Set(cli.HomeFlag, home)
viper.Set(client.FlagName, "moniker")
cfg, err := tcmd.ParseConfig()
require.Nil(t, err)
nodeID, valPubKey, err := InitializeNodeValidatorFiles(cfg)
require.Nil(t, err)
require.NotEqual(t, "", nodeID)
require.NotEqual(t, 0, len(valPubKey.Bytes()))
}

View File

@ -1,385 +0,0 @@
package init
// DONTCOVER
import (
"encoding/json"
"fmt"
"net"
"os"
"path/filepath"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/kava-labs/kava/app"
"github.com/spf13/cobra"
"github.com/spf13/viper"
tmconfig "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
"github.com/cosmos/cosmos-sdk/server"
)
var (
flagNodeDirPrefix = "node-dir-prefix"
flagNumValidators = "v"
flagOutputDir = "output-dir"
flagNodeDaemonHome = "node-daemon-home"
flagNodeCliHome = "node-cli-home"
flagStartingIPAddress = "starting-ip-address"
)
const nodeDirPerm = 0755
// get cmd to initialize all files for tendermint testnet and application
func TestnetFilesCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "testnet",
Short: "Initialize files for a testnet",
Long: `testnet will create "v" number of directories and populate each with
necessary files (private validator, genesis, config, etc.).
Note, strict routability for addresses is turned off in the config file.
Example:
kvd testnet --v 4 --output-dir ./output --starting-ip-address 192.168.10.2
`,
RunE: func(_ *cobra.Command, _ []string) error {
config := ctx.Config
return initTestnet(config, cdc)
},
}
cmd.Flags().Int(flagNumValidators, 4,
"Number of validators to initialize the testnet with",
)
cmd.Flags().StringP(flagOutputDir, "o", "./mytestnet",
"Directory to store initialization data for the testnet",
)
cmd.Flags().String(flagNodeDirPrefix, "node",
"Prefix the directory name for each node with (node results in node0, node1, ...)",
)
cmd.Flags().String(flagNodeDaemonHome, "kvd",
"Home directory of the node's daemon configuration",
)
cmd.Flags().String(flagNodeCliHome, "kvcli",
"Home directory of the node's cli configuration",
)
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1",
"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
cmd.Flags().String(
client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created",
)
cmd.Flags().String(
server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom),
"Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)",
)
return cmd
}
func initTestnet(config *tmconfig.Config, cdc *codec.Codec) error {
var chainID string
outDir := viper.GetString(flagOutputDir)
numValidators := viper.GetInt(flagNumValidators)
chainID = viper.GetString(client.FlagChainID)
if chainID == "" {
chainID = "chain-" + cmn.RandStr(6)
}
monikers := make([]string, numValidators)
nodeIDs := make([]string, numValidators)
valPubKeys := make([]crypto.PubKey, numValidators)
appConfig := srvconfig.DefaultConfig()
appConfig.MinGasPrices = viper.GetString(server.FlagMinGasPrices)
var (
accs []app.GenesisAccount
genFiles []string
)
// generate private keys, node IDs, and initial transactions
for i := 0; i < numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", viper.GetString(flagNodeDirPrefix), i)
nodeDaemonHomeName := viper.GetString(flagNodeDaemonHome)
nodeCliHomeName := viper.GetString(flagNodeCliHome)
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
clientDir := filepath.Join(outDir, nodeDirName, nodeCliHomeName)
gentxsDir := filepath.Join(outDir, "gentxs")
config.SetRoot(nodeDir)
err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm)
if err != nil {
_ = os.RemoveAll(outDir)
return err
}
err = os.MkdirAll(clientDir, nodeDirPerm)
if err != nil {
_ = os.RemoveAll(outDir)
return err
}
monikers = append(monikers, nodeDirName)
config.Moniker = nodeDirName
ip, err := getIP(i, viper.GetString(flagStartingIPAddress))
if err != nil {
_ = os.RemoveAll(outDir)
return err
}
nodeIDs[i], valPubKeys[i], err = InitializeNodeValidatorFiles(config)
if err != nil {
_ = os.RemoveAll(outDir)
return err
}
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
genFiles = append(genFiles, config.GenesisFile())
buf := client.BufferStdin()
prompt := fmt.Sprintf(
"Password for account '%s' (default %s):", nodeDirName, app.DefaultKeyPass,
)
keyPass, err := client.GetPassword(prompt, buf)
if err != nil && keyPass != "" {
// An error was returned that either failed to read the password from
// STDIN or the given password is not empty but failed to meet minimum
// length requirements.
return err
}
if keyPass == "" {
keyPass = app.DefaultKeyPass
}
addr, secret, err := server.GenerateSaveCoinKey(clientDir, nodeDirName, keyPass, true)
if err != nil {
_ = os.RemoveAll(outDir)
return err
}
info := map[string]string{"secret": secret}
cliPrint, err := json.Marshal(info)
if err != nil {
return err
}
// save private key seed words
err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, cliPrint)
if err != nil {
return err
}
accTokens := sdk.TokensFromTendermintPower(1000)
accStakingTokens := sdk.TokensFromTendermintPower(500)
accs = append(accs, app.GenesisAccount{
Address: addr,
Coins: sdk.Coins{
sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), accTokens),
sdk.NewCoin(sdk.DefaultBondDenom, accStakingTokens),
},
})
valTokens := sdk.TokensFromTendermintPower(100)
msg := staking.NewMsgCreateValidator(
sdk.ValAddress(addr),
valPubKeys[i],
sdk.NewCoin(sdk.DefaultBondDenom, valTokens),
staking.NewDescription(nodeDirName, "", "", ""),
staking.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
sdk.OneInt(),
)
kb, err := keys.NewKeyBaseFromDir(clientDir)
if err != nil {
return err
}
tx := auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, []auth.StdSignature{}, memo)
txBldr := authtx.NewTxBuilderFromCLI().WithChainID(chainID).WithMemo(memo).WithKeybase(kb)
signedTx, err := txBldr.SignStdTx(nodeDirName, app.DefaultKeyPass, tx, false)
if err != nil {
_ = os.RemoveAll(outDir)
return err
}
txBytes, err := cdc.MarshalJSON(signedTx)
if err != nil {
_ = os.RemoveAll(outDir)
return err
}
// gather gentxs folder
err = writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBytes)
if err != nil {
_ = os.RemoveAll(outDir)
return err
}
appConfigFilePath := filepath.Join(nodeDir, "config/kvd.toml")
srvconfig.WriteConfigFile(appConfigFilePath, appConfig)
}
if err := initGenFiles(cdc, chainID, accs, genFiles, numValidators); err != nil {
return err
}
err := collectGenFiles(
cdc, config, chainID, monikers, nodeIDs, valPubKeys, numValidators,
outDir, viper.GetString(flagNodeDirPrefix), viper.GetString(flagNodeDaemonHome),
)
if err != nil {
return err
}
fmt.Printf("Successfully initialized %d node directories\n", numValidators)
return nil
}
func initGenFiles(
cdc *codec.Codec, chainID string, accs []app.GenesisAccount,
genFiles []string, numValidators int,
) error {
appGenState := app.NewDefaultGenesisState()
appGenState.Accounts = accs
appGenStateJSON, err := codec.MarshalJSONIndent(cdc, appGenState)
if err != nil {
return err
}
genDoc := types.GenesisDoc{
ChainID: chainID,
AppState: appGenStateJSON,
Validators: nil,
}
// generate empty genesis files for each validator and save
for i := 0; i < numValidators; i++ {
if err := genDoc.SaveAs(genFiles[i]); err != nil {
return err
}
}
return nil
}
func collectGenFiles(
cdc *codec.Codec, config *tmconfig.Config, chainID string,
monikers, nodeIDs []string, valPubKeys []crypto.PubKey,
numValidators int, outDir, nodeDirPrefix, nodeDaemonHomeName string,
) error {
var appState json.RawMessage
genTime := tmtime.Now()
for i := 0; i < numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
gentxsDir := filepath.Join(outDir, "gentxs")
moniker := monikers[i]
config.Moniker = nodeDirName
config.SetRoot(nodeDir)
nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
initCfg := newInitConfig(chainID, gentxsDir, moniker, nodeID, valPubKey)
genDoc, err := LoadGenesisDoc(cdc, config.GenesisFile())
if err != nil {
return err
}
nodeAppState, err := genAppStateFromConfig(cdc, config, initCfg, genDoc)
if err != nil {
return err
}
if appState == nil {
// set the canonical application state (they should not differ)
appState = nodeAppState
}
genFile := config.GenesisFile()
// overwrite each validator's genesis file to have a canonical genesis time
err = ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime)
if err != nil {
return err
}
}
return nil
}
func getIP(i int, startingIPAddr string) (string, error) {
var (
ip string
err error
)
if len(startingIPAddr) == 0 {
ip, err = server.ExternalIP()
if err != nil {
return "", err
}
} else {
ip, err = calculateIP(startingIPAddr, i)
if err != nil {
return "", err
}
}
return ip, nil
}
func writeFile(name string, dir string, contents []byte) error {
writePath := filepath.Join(dir)
file := filepath.Join(writePath, name)
err := cmn.EnsureDir(writePath, 0700)
if err != nil {
return err
}
err = cmn.WriteFile(file, contents, 0600)
if err != nil {
return err
}
return nil
}
func calculateIP(ip string, i int) (string, error) {
ipv4 := net.ParseIP(ip).To4()
if ipv4 == nil {
return "", fmt.Errorf("%v: non ipv4 address", ip)
}
for j := 0; j < i; j++ {
ipv4[3]++
}
return ipv4.String(), nil
}

View File

@ -1,114 +0,0 @@
package init
import (
"encoding/json"
"fmt"
"io/ioutil"
"path/filepath"
"time"
amino "github.com/tendermint/go-amino"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/types"
"github.com/kava-labs/kava/app"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
)
// ExportGenesisFile creates and writes the genesis configuration to disk. An
// error is returned if building or writing the configuration to file fails.
func ExportGenesisFile(
genFile, chainID string, validators []types.GenesisValidator, appState json.RawMessage,
) error {
genDoc := types.GenesisDoc{
ChainID: chainID,
Validators: validators,
AppState: appState,
}
if err := genDoc.ValidateAndComplete(); err != nil {
return err
}
return genDoc.SaveAs(genFile)
}
// ExportGenesisFileWithTime creates and writes the genesis configuration to disk.
// An error is returned if building or writing the configuration to file fails.
func ExportGenesisFileWithTime(
genFile, chainID string, validators []types.GenesisValidator,
appState json.RawMessage, genTime time.Time,
) error {
genDoc := types.GenesisDoc{
GenesisTime: genTime,
ChainID: chainID,
Validators: validators,
AppState: appState,
}
if err := genDoc.ValidateAndComplete(); err != nil {
return err
}
return genDoc.SaveAs(genFile)
}
// InitializeNodeValidatorFiles creates private validator and p2p configuration files.
func InitializeNodeValidatorFiles(
config *cfg.Config) (nodeID string, valPubKey crypto.PubKey, err error,
) {
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
if err != nil {
return nodeID, valPubKey, err
}
nodeID = string(nodeKey.ID())
server.UpgradeOldPrivValFile(config)
pvKeyFile := config.PrivValidatorKeyFile()
if err := common.EnsureDir(filepath.Dir(pvKeyFile), 0777); err != nil {
return nodeID, valPubKey, nil
}
pvStateFile := config.PrivValidatorStateFile()
if err := common.EnsureDir(filepath.Dir(pvStateFile), 0777); err != nil {
return nodeID, valPubKey, nil
}
valPubKey = privval.LoadOrGenFilePV(pvKeyFile, pvStateFile).GetPubKey()
return nodeID, valPubKey, nil
}
// LoadGenesisDoc reads and unmarshals GenesisDoc from the given file.
func LoadGenesisDoc(cdc *amino.Codec, genFile string) (genDoc types.GenesisDoc, err error) {
genContents, err := ioutil.ReadFile(genFile)
if err != nil {
return genDoc, err
}
if err := cdc.UnmarshalJSON(genContents, &genDoc); err != nil {
return genDoc, err
}
return genDoc, err
}
func initializeEmptyGenesis(
cdc *codec.Codec, genFile, chainID string, overwrite bool,
) (appState json.RawMessage, err error) {
if !overwrite && common.FileExists(genFile) {
return nil, fmt.Errorf("genesis.json file already exists: %v", genFile)
}
return codec.MarshalJSONIndent(cdc, app.NewDefaultGenesisState())
}

View File

@ -1,49 +0,0 @@
package init
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"
"time"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/tests"
"github.com/stretchr/testify/require"
)
func TestExportGenesisFileWithTime(t *testing.T) {
t.Parallel()
dir, cleanup := tests.NewTestCaseDir(t)
defer cleanup()
fname := filepath.Join(dir, "genesis.json")
require.NoError(t, ExportGenesisFileWithTime(fname, "test", nil, json.RawMessage(""), time.Now()))
}
func TestLoadGenesisDoc(t *testing.T) {
t.Parallel()
dir, cleanup := tests.NewTestCaseDir(t)
defer cleanup()
fname := filepath.Join(dir, "genesis.json")
require.NoError(t, ExportGenesisFileWithTime(fname, "test", nil, json.RawMessage(""), time.Now()))
_, err := LoadGenesisDoc(codec.Cdc, fname)
require.NoError(t, err)
// Non-existing file
_, err = LoadGenesisDoc(codec.Cdc, "non-existing-file")
require.Error(t, err)
malformedFilename := filepath.Join(dir, "malformed")
malformedFile, err := os.Create(malformedFilename)
require.NoError(t, err)
fmt.Fprint(malformedFile, "invalidjson")
malformedFile.Close()
// Non-existing file
_, err = LoadGenesisDoc(codec.Cdc, malformedFilename)
require.Error(t, err)
}

View File

@ -1,51 +0,0 @@
package init
import (
"fmt"
"os"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
"github.com/kava-labs/kava/app"
"github.com/spf13/cobra"
"github.com/tendermint/tendermint/types"
)
// Validate genesis command takes
func ValidateGenesisCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "validate-genesis [file]",
Args: cobra.RangeArgs(0, 1),
Short: "validates the genesis file at the default location or at the location passed as an arg",
RunE: func(cmd *cobra.Command, args []string) (err error) {
// Load default if passed no args, otherwise load passed file
var genesis string
if len(args) == 0 {
genesis = ctx.Config.GenesisFile()
} else {
genesis = args[0]
}
//nolint
fmt.Fprintf(os.Stderr, "validating genesis file at %s\n", genesis)
var genDoc types.GenesisDoc
if genDoc, err = LoadGenesisDoc(cdc, genesis); err != nil {
return fmt.Errorf("Error loading genesis doc from %s: %s", genesis, err.Error())
}
var genstate app.GenesisState
if err = cdc.UnmarshalJSON(genDoc.AppState, &genstate); err != nil {
return fmt.Errorf("Error unmarshaling genesis doc %s: %s", genesis, err.Error())
}
if err = app.ValidateGenesisState(genstate); err != nil {
return fmt.Errorf("Error validating genesis file %s: %s", genesis, err.Error())
}
fmt.Printf("File at %s is a valid genesis file for kvd\n", genesis)
return nil
},
}
}