mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 23:35:19 +00:00
remove old init package
This commit is contained in:
parent
cfbd4e92aa
commit
566c0258a6
145
init/collect.go
145
init/collect.go
@ -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,
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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))
|
||||
})
|
||||
}
|
||||
}
|
312
init/gentx.go
312
init/gentx.go
@ -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
|
||||
}
|
@ -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) })
|
||||
}
|
||||
}
|
95
init/init.go
95
init/init.go
@ -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
|
||||
}
|
@ -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()))
|
||||
}
|
385
init/testnet.go
385
init/testnet.go
@ -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
|
||||
}
|
114
init/utils.go
114
init/utils.go
@ -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())
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user