0g-chain/cmd/kvd/main.go

200 lines
5.5 KiB
Go
Raw Normal View History

// Copyright 2016 All in Bits, inc
// Modifications copyright 2018 Kava Labs
2018-05-25 13:46:33 +00:00
package main
import (
"encoding/json"
2018-10-03 17:11:13 +00:00
"fmt"
2018-08-14 22:13:54 +00:00
"io"
2018-10-03 17:11:13 +00:00
"io/ioutil"
2018-10-02 22:50:49 +00:00
"os"
"path/filepath"
2018-10-03 17:11:13 +00:00
"regexp"
2018-08-14 22:13:54 +00:00
"github.com/cosmos/cosmos-sdk/baseapp"
2018-05-25 13:46:33 +00:00
"github.com/spf13/cobra"
2018-08-14 22:13:54 +00:00
"github.com/spf13/viper"
2018-05-25 13:46:33 +00:00
2018-08-14 22:13:54 +00:00
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/cli"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
2018-06-16 21:34:07 +00:00
tmtypes "github.com/tendermint/tendermint/types"
2018-05-25 13:46:33 +00:00
"github.com/cosmos/cosmos-sdk/server"
2018-06-16 16:21:13 +00:00
"github.com/kava-labs/kava/internal/app"
2018-05-25 13:46:33 +00:00
)
func main() {
2018-08-14 22:13:54 +00:00
// Create an app codec
cdc := app.CreateKavaAppCodec()
// Create a server context (a struct of a tendermint config and a logger)
2018-05-25 13:46:33 +00:00
ctx := server.NewDefaultContext()
2018-08-14 22:13:54 +00:00
// Create the root kvd command
cobra.EnableCommandSorting = false
2018-05-25 13:46:33 +00:00
rootCmd := &cobra.Command{
2018-06-16 21:34:07 +00:00
Use: "kvd",
2018-06-16 16:21:13 +00:00
Short: "Kava Daemon",
2018-05-25 13:46:33 +00:00
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
}
2018-08-14 22:13:54 +00:00
// Add server commands to kvd, passing in the app
appInit := app.KavaAppInit()
appCreator := server.ConstructAppCreator(newApp, "kava") // init db before calling newApp
appExporter := server.ConstructAppExporter(exportAppStateAndTMValidators, "kava")
server.AddCommands(ctx, cdc, rootCmd, appInit, appCreator, appExporter)
2018-05-25 13:46:33 +00:00
2018-10-02 22:50:49 +00:00
// Add custom init command
rootCmd.AddCommand(initTestnetCmd())
2018-08-14 22:13:54 +00:00
// handle envs and add some flags and stuff
executor := cli.PrepareBaseCmd(rootCmd, "KV", app.DefaultNodeHome)
// Run kvd
err := executor.Execute()
if err != nil {
panic(err)
}
2018-05-25 13:46:33 +00:00
}
2018-08-14 22:13:54 +00:00
func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application {
return app.NewKavaApp(logger, db, traceStore, baseapp.SetPruning(viper.GetString("pruning")))
2018-05-25 13:46:33 +00:00
}
2018-08-14 22:13:54 +00:00
func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, traceStore io.Writer) (json.RawMessage, []tmtypes.GenesisValidator, error) {
tempApp := app.NewKavaApp(logger, db, traceStore)
return tempApp.ExportAppStateAndValidators()
2018-05-25 13:46:33 +00:00
}
2018-10-02 22:50:49 +00:00
func initTestnetCmd() *cobra.Command {
2018-10-03 17:11:13 +00:00
flagChainID := server.FlagChainID
flagName := server.FlagName
2018-10-02 22:50:49 +00:00
cmd := &cobra.Command{
2018-10-03 17:11:13 +00:00
Use: "init-testnet",
2018-10-02 22:50:49 +00:00
Short: "Setup genesis and config to join testnet.",
2018-10-03 17:11:13 +00:00
Long: "Copy the genesis.json and config.toml files from the testnets folder into the default config directories. Also set the validator moniker.",
2018-10-02 22:50:49 +00:00
RunE: func(cmd *cobra.Command, args []string) error {
2018-10-03 17:11:13 +00:00
// This only works with default config locations
2018-10-02 22:50:49 +00:00
testnetVersion := viper.GetString(flagChainID)
genesisFileName := "genesis.json"
configFileName := "config.toml"
configPath := "config"
testnetsPath := os.ExpandEnv("$GOPATH/src/github.com/kava-labs/kava/testnets/")
// Copy genesis file from testnet folder to config directories
// Copied to .kvcli to enable automatic reading of chain-id
genesis := filepath.Join(testnetsPath, testnetVersion, genesisFileName)
err := copyFile(genesis, filepath.Join(app.DefaultNodeHome, configPath, genesisFileName))
if err != nil {
return err
}
err = copyFile(genesis, filepath.Join(app.DefaultCLIHome, configPath, genesisFileName))
if err != nil {
return err
}
// Copy config file from testnet folder to config directories
// Custom config file specifies seeds and altered ports
2018-10-03 17:11:13 +00:00
// Also add back validator moniker to config file
2018-10-02 22:50:49 +00:00
config := filepath.Join(testnetsPath, testnetVersion, configFileName)
2018-10-03 21:01:42 +00:00
monikerPattern, err := regexp.Compile("moniker = \"[^\n]*\"") // anything that's not a new line
2018-10-03 17:11:13 +00:00
if err != nil {
return err
}
2018-10-03 21:01:42 +00:00
monikerReplaceString := fmt.Sprintf("moniker = \"%v\"", viper.GetString(flagName))
2018-10-03 17:11:13 +00:00
2018-10-02 22:50:49 +00:00
err = copyFile(config, filepath.Join(app.DefaultNodeHome, configPath, configFileName))
if err != nil {
return err
}
2018-10-03 17:11:13 +00:00
err = replaceStringInFile(
filepath.Join(app.DefaultNodeHome, configPath, configFileName),
monikerPattern,
monikerReplaceString)
if err != nil {
return err
}
2018-10-02 22:50:49 +00:00
err = copyFile(config, filepath.Join(app.DefaultCLIHome, configPath, configFileName))
if err != nil {
return err
}
2018-10-03 17:11:13 +00:00
err = replaceStringInFile(
filepath.Join(app.DefaultCLIHome, configPath, configFileName),
monikerPattern,
monikerReplaceString)
if err != nil {
return err
}
2018-10-02 22:50:49 +00:00
return nil
},
}
2018-10-03 17:11:13 +00:00
cmd.Flags().String(flagChainID, "", "testnet chain-id, required")
cmd.Flags().String(flagName, "", "validator moniker, required")
2018-10-02 22:50:49 +00:00
return cmd
}
func copyFile(src string, dst string) error {
// read in source file
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
// create destination file (and any necessary directories)(overwriting if it exists already)
path := filepath.Dir(dst)
err = os.MkdirAll(path, os.ModePerm)
if err != nil {
return err
}
out, err := os.Create(dst)
if err != nil {
return err
}
defer func() {
cerr := out.Close()
if err == nil {
err = cerr
}
}()
// copy file contents
if _, err = io.Copy(out, in); err != nil {
return err
}
// write to disk
err = out.Sync()
return err
}
2018-10-03 17:11:13 +00:00
// replaceStringInFile finds strings matching a regexp in a file and replaces them with a new string, before saving file.
func replaceStringInFile(filePath string, re *regexp.Regexp, replace string) error {
// get permissions of file
fileInfo, err := os.Stat(filePath)
if err != nil {
return err
}
// read in file contents
in, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
// replace string
newContents := re.ReplaceAll(in, []byte(replace))
// write file
err = ioutil.WriteFile(filePath, newContents, fileInfo.Mode())
if err != nil {
return err
}
return nil
}