Alessio/server refactor (#2472)
* Add arg to PrintUnsignedStdTx() to actually operate in offline mode * WIP simplifying server module * Expose ExternalIP() * Move {GenTx,Init}Cmd into gaia's new init package
This commit is contained in:
parent
e251088672
commit
0f4a03b44e
|
@ -2,6 +2,9 @@
|
|||
.DS_Store
|
||||
*.swp
|
||||
*.swo
|
||||
*.swl
|
||||
*.swm
|
||||
*.swn
|
||||
.vscode
|
||||
.idea
|
||||
|
||||
|
|
|
@ -87,8 +87,14 @@ func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc *
|
|||
}
|
||||
|
||||
// PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout.
|
||||
func PrintUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (err error) {
|
||||
stdTx, err := buildUnsignedStdTx(txBldr, cliCtx, msgs)
|
||||
// Don't perform online validation or lookups if offline is true.
|
||||
func PrintUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg, offline bool) (err error) {
|
||||
var stdTx auth.StdTx
|
||||
if offline {
|
||||
stdTx, err = buildUnsignedStdTxOffline(txBldr, cliCtx, msgs)
|
||||
} else {
|
||||
stdTx, err = buildUnsignedStdTx(txBldr, cliCtx, msgs)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -204,6 +210,10 @@ func buildUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msg
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
return buildUnsignedStdTxOffline(txBldr, cliCtx, msgs)
|
||||
}
|
||||
|
||||
func buildUnsignedStdTxOffline(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) {
|
||||
if txBldr.SimulateGas {
|
||||
var name string
|
||||
name, err = cliCtx.GetFromName()
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||
gaiaInit "github.com/cosmos/cosmos-sdk/cmd/gaia/init"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
)
|
||||
|
||||
|
@ -28,10 +29,12 @@ func main() {
|
|||
Short: "Gaia Daemon (server)",
|
||||
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
|
||||
}
|
||||
appInit := app.GaiaAppInit()
|
||||
rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc, appInit))
|
||||
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, appInit))
|
||||
|
||||
server.AddCommands(ctx, cdc, rootCmd, app.GaiaAppInit(),
|
||||
server.ConstructAppCreator(newApp, "gaia"),
|
||||
server.ConstructAppExporter(exportAppStateAndTMValidators, "gaia"))
|
||||
server.AddCommands(ctx, cdc, rootCmd, appInit,
|
||||
newApp, exportAppStateAndTMValidators)
|
||||
|
||||
// prepare and add flags
|
||||
executor := cli.PrepareBaseCmd(rootCmd, "GA", app.DefaultNodeHome)
|
||||
|
|
|
@ -0,0 +1,321 @@
|
|||
package init
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
servercfg "github.com/cosmos/cosmos-sdk/server/config"
|
||||
"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/libs/common"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// get cmd to initialize all files for tendermint and application
|
||||
func GenTxCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "gen-tx",
|
||||
Short: "Create genesis transaction file (under [--home]/config/gentx/gentx-[nodeID].json)",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
config := ctx.Config
|
||||
config.SetRoot(viper.GetString(cli.HomeFlag))
|
||||
|
||||
ip := viper.GetString(server.FlagIP)
|
||||
if len(ip) == 0 {
|
||||
eip, err := server.ExternalIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ip = eip
|
||||
}
|
||||
|
||||
genTxConfig := servercfg.GenTx{
|
||||
viper.GetString(server.FlagName),
|
||||
viper.GetString(server.FlagClientHome),
|
||||
viper.GetBool(server.FlagOWK),
|
||||
ip,
|
||||
}
|
||||
cliPrint, genTxFile, err := gentxWithConfig(cdc, appInit, config, genTxConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
toPrint := struct {
|
||||
AppMessage json.RawMessage `json:"app_message"`
|
||||
GenTxFile json.RawMessage `json:"gen_tx_file"`
|
||||
}{
|
||||
cliPrint,
|
||||
genTxFile,
|
||||
}
|
||||
out, err := codec.MarshalJSONIndent(cdc, toPrint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
cmd.Flags().String(server.FlagIP, "", "external facing IP to use if left blank IP will be retrieved from this machine")
|
||||
cmd.Flags().AddFlagSet(appInit.FlagsAppGenTx)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NOTE: This will update (write) the config file with
|
||||
// updated name (moniker) for node.
|
||||
func gentxWithConfig(cdc *codec.Codec, appInit server.AppInit, config *cfg.Config, genTxConfig servercfg.GenTx) (
|
||||
cliPrint json.RawMessage, genTxFile json.RawMessage, err error) {
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nodeID := string(nodeKey.ID())
|
||||
pubKey := readOrCreatePrivValidator(config)
|
||||
|
||||
appGenTx, cliPrint, validator, err := appInit.AppGenTx(cdc, pubKey, genTxConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
tx := server.GenesisTx{
|
||||
NodeID: nodeID,
|
||||
IP: genTxConfig.IP,
|
||||
Validator: validator,
|
||||
AppGenTx: appGenTx,
|
||||
}
|
||||
bz, err := codec.MarshalJSONIndent(cdc, tx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
genTxFile = json.RawMessage(bz)
|
||||
name := fmt.Sprintf("gentx-%v.json", nodeID)
|
||||
writePath := filepath.Join(config.RootDir, "config", "gentx")
|
||||
file := filepath.Join(writePath, name)
|
||||
err = common.EnsureDir(writePath, 0700)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = common.WriteFile(file, bz, 0644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Write updated config with moniker
|
||||
config.Moniker = genTxConfig.Name
|
||||
configFilePath := filepath.Join(config.RootDir, "config", "config.toml")
|
||||
cfg.WriteConfigFile(configFilePath, config)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get cmd to initialize all files for tendermint and application
|
||||
// nolint: golint
|
||||
func InitCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize genesis config, priv-validator file, and p2p-node file",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(_ *cobra.Command, _ []string) error {
|
||||
|
||||
config := ctx.Config
|
||||
config.SetRoot(viper.GetString(cli.HomeFlag))
|
||||
initConfig := server.InitConfig{
|
||||
viper.GetString(server.FlagChainID),
|
||||
viper.GetBool(server.FlagWithTxs),
|
||||
filepath.Join(config.RootDir, "config", "gentx"),
|
||||
viper.GetBool(server.FlagOverwrite),
|
||||
}
|
||||
|
||||
chainID, nodeID, appMessage, err := initWithConfig(cdc, appInit, config, initConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// print out some key information
|
||||
toPrint := struct {
|
||||
ChainID string `json:"chain_id"`
|
||||
NodeID string `json:"node_id"`
|
||||
AppMessage json.RawMessage `json:"app_message"`
|
||||
}{
|
||||
chainID,
|
||||
nodeID,
|
||||
appMessage,
|
||||
}
|
||||
out, err := codec.MarshalJSONIndent(cdc, toPrint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolP(server.FlagOverwrite, "o", false, "overwrite the genesis.json file")
|
||||
cmd.Flags().String(server.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
|
||||
cmd.Flags().Bool(server.FlagWithTxs, false, "apply existing genesis transactions from [--home]/config/gentx/")
|
||||
cmd.Flags().AddFlagSet(appInit.FlagsAppGenState)
|
||||
cmd.Flags().AddFlagSet(appInit.FlagsAppGenTx) // need to add this flagset for when no GenTx's provided
|
||||
cmd.AddCommand(GenTxCmd(ctx, cdc, appInit))
|
||||
return cmd
|
||||
}
|
||||
|
||||
func initWithConfig(cdc *codec.Codec, appInit server.AppInit, config *cfg.Config, initConfig server.InitConfig) (
|
||||
chainID string, nodeID string, appMessage json.RawMessage, err error) {
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nodeID = string(nodeKey.ID())
|
||||
pubKey := readOrCreatePrivValidator(config)
|
||||
|
||||
if initConfig.ChainID == "" {
|
||||
initConfig.ChainID = fmt.Sprintf("test-chain-%v", common.RandStr(6))
|
||||
}
|
||||
chainID = initConfig.ChainID
|
||||
|
||||
genFile := config.GenesisFile()
|
||||
if !initConfig.Overwrite && common.FileExists(genFile) {
|
||||
err = fmt.Errorf("genesis.json file already exists: %v", genFile)
|
||||
return
|
||||
}
|
||||
|
||||
// process genesis transactions, or otherwise create one for defaults
|
||||
var appGenTxs []json.RawMessage
|
||||
var validators []types.GenesisValidator
|
||||
var persistentPeers string
|
||||
|
||||
if initConfig.GenTxs {
|
||||
validators, appGenTxs, persistentPeers, err = processGenTxs(initConfig.GenTxsDir, cdc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config.P2P.PersistentPeers = persistentPeers
|
||||
configFilePath := filepath.Join(config.RootDir, "config", "config.toml")
|
||||
cfg.WriteConfigFile(configFilePath, config)
|
||||
} else {
|
||||
genTxConfig := servercfg.GenTx{
|
||||
viper.GetString(server.FlagName),
|
||||
viper.GetString(server.FlagClientHome),
|
||||
viper.GetBool(server.FlagOWK),
|
||||
"127.0.0.1",
|
||||
}
|
||||
|
||||
// Write updated config with moniker
|
||||
config.Moniker = genTxConfig.Name
|
||||
configFilePath := filepath.Join(config.RootDir, "config", "config.toml")
|
||||
cfg.WriteConfigFile(configFilePath, config)
|
||||
appGenTx, am, validator, err := appInit.AppGenTx(cdc, pubKey, genTxConfig)
|
||||
appMessage = am
|
||||
if err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
validators = []types.GenesisValidator{validator}
|
||||
appGenTxs = []json.RawMessage{appGenTx}
|
||||
}
|
||||
|
||||
appState, err := appInit.AppGenState(cdc, appGenTxs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = writeGenesisFile(cdc, genFile, initConfig.ChainID, validators, appState)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// append a genesis-piece
|
||||
func processGenTxs(genTxsDir string, cdc *codec.Codec) (
|
||||
validators []types.GenesisValidator, appGenTxs []json.RawMessage, persistentPeers string, err error) {
|
||||
|
||||
var fos []os.FileInfo
|
||||
fos, err = ioutil.ReadDir(genTxsDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
genTxs := make(map[string]server.GenesisTx)
|
||||
var nodeIDs []string
|
||||
for _, fo := range fos {
|
||||
filename := path.Join(genTxsDir, fo.Name())
|
||||
if !fo.IsDir() && (path.Ext(filename) != ".json") {
|
||||
continue
|
||||
}
|
||||
|
||||
// get the genTx
|
||||
var bz []byte
|
||||
bz, err = ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var genTx server.GenesisTx
|
||||
err = cdc.UnmarshalJSON(bz, &genTx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
genTxs[genTx.NodeID] = genTx
|
||||
nodeIDs = append(nodeIDs, genTx.NodeID)
|
||||
}
|
||||
|
||||
sort.Strings(nodeIDs)
|
||||
|
||||
for _, nodeID := range nodeIDs {
|
||||
genTx := genTxs[nodeID]
|
||||
|
||||
// combine some stuff
|
||||
validators = append(validators, genTx.Validator)
|
||||
appGenTxs = append(appGenTxs, genTx.AppGenTx)
|
||||
|
||||
// Add a persistent peer
|
||||
comma := ","
|
||||
if len(persistentPeers) == 0 {
|
||||
comma = ""
|
||||
}
|
||||
persistentPeers += fmt.Sprintf("%s%s@%s:26656", comma, genTx.NodeID, genTx.IP)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// read of create the private key file for this config
|
||||
func readOrCreatePrivValidator(tmConfig *cfg.Config) crypto.PubKey {
|
||||
// private validator
|
||||
privValFile := tmConfig.PrivValidatorFile()
|
||||
var privValidator *privval.FilePV
|
||||
if common.FileExists(privValFile) {
|
||||
privValidator = privval.LoadFilePV(privValFile)
|
||||
} else {
|
||||
privValidator = privval.GenFilePV(privValFile)
|
||||
privValidator.Save()
|
||||
}
|
||||
return privValidator.GetPubKey()
|
||||
}
|
||||
|
||||
// writeGenesisFile creates and writes the genesis configuration to disk. An
|
||||
// error is returned if building or writing the configuration to file fails.
|
||||
// nolint: unparam
|
||||
func writeGenesisFile(cdc *codec.Codec, genesisFile, 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(genesisFile)
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package init
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/server/mock"
|
||||
"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/log"
|
||||
)
|
||||
|
||||
func TestInitCmd(t *testing.T) {
|
||||
defer server.SetupViper(t)()
|
||||
|
||||
logger := log.NewNopLogger()
|
||||
cfg, err := tcmd.ParseConfig()
|
||||
require.Nil(t, err)
|
||||
ctx := server.NewContext(cfg, logger)
|
||||
cdc := codec.New()
|
||||
appInit := server.AppInit{
|
||||
AppGenState: mock.AppGenState,
|
||||
AppGenTx: mock.AppGenTx,
|
||||
}
|
||||
cmd := InitCmd(ctx, cdc, appInit)
|
||||
err = cmd.RunE(nil, nil)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestEmptyState(t *testing.T) {
|
||||
defer server.SetupViper(t)()
|
||||
logger := log.NewNopLogger()
|
||||
cfg, err := tcmd.ParseConfig()
|
||||
require.Nil(t, err)
|
||||
ctx := server.NewContext(cfg, logger)
|
||||
cdc := codec.New()
|
||||
appInit := server.AppInit{
|
||||
AppGenTx: mock.AppGenTx,
|
||||
AppGenState: mock.AppGenStateEmpty,
|
||||
}
|
||||
cmd := InitCmd(ctx, cdc, appInit)
|
||||
err = cmd.RunE(nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
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, "WARNING: State is not initialized")
|
||||
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)
|
||||
}()
|
||||
|
||||
logger := log.NewNopLogger()
|
||||
cfg, err := tcmd.ParseConfig()
|
||||
require.Nil(t, err)
|
||||
ctx := server.NewContext(cfg, logger)
|
||||
cdc := codec.New()
|
||||
appInit := server.AppInit{
|
||||
AppGenState: mock.AppGenState,
|
||||
AppGenTx: mock.AppGenTx,
|
||||
}
|
||||
initCmd := InitCmd(ctx, cdc, appInit)
|
||||
err = initCmd.RunE(nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package server
|
||||
package init
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"net"
|
||||
"path/filepath"
|
||||
|
||||
|
@ -30,7 +31,7 @@ var (
|
|||
const nodeDirPerm = 0755
|
||||
|
||||
// get cmd to initialize all files for tendermint testnet and application
|
||||
func TestnetFilesCmd(ctx *Context, cdc *codec.Codec, appInit AppInit) *cobra.Command {
|
||||
func TestnetFilesCmd(ctx *server.Context, cdc *codec.Codec, appInit server.AppInit) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "testnet",
|
||||
Short: "Initialize files for a Gaiad testnet",
|
||||
|
@ -65,7 +66,7 @@ Example:
|
|||
return cmd
|
||||
}
|
||||
|
||||
func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit AppInit) error {
|
||||
func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit server.AppInit) error {
|
||||
outDir := viper.GetString(outputDir)
|
||||
numValidators := viper.GetInt(nValidators)
|
||||
|
||||
|
@ -133,7 +134,7 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit AppInit) er
|
|||
nodeDaemonHomeName := viper.GetString(nodeDaemonHome)
|
||||
nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
|
||||
gentxsDir := filepath.Join(outDir, "gentxs")
|
||||
initConfig := InitConfig{
|
||||
initConfig := server.InitConfig{
|
||||
chainID,
|
||||
true,
|
||||
gentxsDir,
|
||||
|
@ -156,7 +157,7 @@ func testnetWithConfig(config *cfg.Config, cdc *codec.Codec, appInit AppInit) er
|
|||
func getIP(i int) (ip string, err error) {
|
||||
ip = viper.GetString(startingIPAddress)
|
||||
if len(ip) == 0 {
|
||||
ip, err = externalIP()
|
||||
ip, err = server.ExternalIP()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
gaiaInit "github.com/cosmos/cosmos-sdk/cmd/gaia/init"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/app"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
|
@ -28,9 +29,12 @@ func main() {
|
|||
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
|
||||
}
|
||||
|
||||
server.AddCommands(ctx, cdc, rootCmd, server.DefaultAppInit,
|
||||
server.ConstructAppCreator(newApp, "basecoin"),
|
||||
server.ConstructAppExporter(exportAppStateAndTMValidators, "basecoin"))
|
||||
appInit := server.DefaultAppInit
|
||||
rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc, appInit))
|
||||
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, appInit))
|
||||
|
||||
server.AddCommands(ctx, cdc, rootCmd, appInit,
|
||||
newApp, exportAppStateAndTMValidators)
|
||||
|
||||
// prepare and add flags
|
||||
rootDir := os.ExpandEnv("$HOME/.basecoind")
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
gaiaInit "github.com/cosmos/cosmos-sdk/cmd/gaia/init"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/examples/democoin/app"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
|
@ -70,9 +71,11 @@ func main() {
|
|||
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
|
||||
}
|
||||
|
||||
rootCmd.AddCommand(gaiaInit.InitCmd(ctx, cdc, CoolAppInit))
|
||||
rootCmd.AddCommand(gaiaInit.TestnetFilesCmd(ctx, cdc, CoolAppInit))
|
||||
|
||||
server.AddCommands(ctx, cdc, rootCmd, CoolAppInit,
|
||||
server.ConstructAppCreator(newApp, "democoin"),
|
||||
server.ConstructAppExporter(exportAppStateAndTMValidators, "democoin"))
|
||||
newApp, exportAppStateAndTMValidators)
|
||||
|
||||
// prepare and add flags
|
||||
rootDir := os.ExpandEnv("$HOME/.democoind")
|
||||
|
|
|
@ -13,72 +13,29 @@ import (
|
|||
)
|
||||
|
||||
type (
|
||||
// AppCreator reflects a function that allows us to lazily initialize an
|
||||
// AppCreator is a function that allows us to lazily initialize an
|
||||
// application using various configurations.
|
||||
AppCreator func(home string, logger log.Logger, traceStore string) (abci.Application, error)
|
||||
AppCreator func(log.Logger, dbm.DB, io.Writer) abci.Application
|
||||
|
||||
// AppExporter reflects a function that dumps all app state to
|
||||
// AppExporter is a function that dumps all app state to
|
||||
// JSON-serializable structure and returns the current validator set.
|
||||
AppExporter func(home string, logger log.Logger, traceStore string) (json.RawMessage, []tmtypes.GenesisValidator, error)
|
||||
|
||||
// AppCreatorInit reflects a function that performs initialization of an
|
||||
// AppCreator.
|
||||
AppCreatorInit func(log.Logger, dbm.DB, io.Writer) abci.Application
|
||||
|
||||
// AppExporterInit reflects a function that performs initialization of an
|
||||
// AppExporter.
|
||||
AppExporterInit func(log.Logger, dbm.DB, io.Writer) (json.RawMessage, []tmtypes.GenesisValidator, error)
|
||||
AppExporter func(log.Logger, dbm.DB, io.Writer) (json.RawMessage, []tmtypes.GenesisValidator, error)
|
||||
)
|
||||
|
||||
// ConstructAppCreator returns an application generation function.
|
||||
func ConstructAppCreator(appFn AppCreatorInit, name string) AppCreator {
|
||||
return func(rootDir string, logger log.Logger, traceStore string) (abci.Application, error) {
|
||||
dataDir := filepath.Join(rootDir, "data")
|
||||
|
||||
db, err := dbm.NewGoLevelDB(name, dataDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var traceStoreWriter io.Writer
|
||||
if traceStore != "" {
|
||||
traceStoreWriter, err = os.OpenFile(
|
||||
traceStore,
|
||||
os.O_WRONLY|os.O_APPEND|os.O_CREATE,
|
||||
0666,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
app := appFn(logger, db, traceStoreWriter)
|
||||
return app, nil
|
||||
}
|
||||
func openDB(rootDir string) (dbm.DB, error) {
|
||||
dataDir := filepath.Join(rootDir, "data")
|
||||
db, err := dbm.NewGoLevelDB("application", dataDir)
|
||||
return db, err
|
||||
}
|
||||
|
||||
// ConstructAppExporter returns an application export function.
|
||||
func ConstructAppExporter(appFn AppExporterInit, name string) AppExporter {
|
||||
return func(rootDir string, logger log.Logger, traceStore string) (json.RawMessage, []tmtypes.GenesisValidator, error) {
|
||||
dataDir := filepath.Join(rootDir, "data")
|
||||
|
||||
db, err := dbm.NewGoLevelDB(name, dataDir)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var traceStoreWriter io.Writer
|
||||
if traceStore != "" {
|
||||
traceStoreWriter, err = os.OpenFile(
|
||||
traceStore,
|
||||
os.O_WRONLY|os.O_APPEND|os.O_CREATE,
|
||||
0666,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return appFn(logger, db, traceStoreWriter)
|
||||
func openTraceWriter(traceWriterFile string) (w io.Writer, err error) {
|
||||
if traceWriterFile != "" {
|
||||
w, err = os.OpenFile(
|
||||
traceWriterFile,
|
||||
os.O_WRONLY|os.O_APPEND|os.O_CREATE,
|
||||
0666,
|
||||
)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.C
|
|||
Short: "Export state to JSON",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
home := viper.GetString("home")
|
||||
traceStore := viper.GetString(flagTraceStore)
|
||||
traceWriterFile := viper.GetString(flagTraceStore)
|
||||
emptyState, err := isEmptyState(home)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -37,7 +37,15 @@ func ExportCmd(ctx *Context, cdc *codec.Codec, appExporter AppExporter) *cobra.C
|
|||
return nil
|
||||
}
|
||||
|
||||
appState, validators, err := appExporter(home, ctx.Logger, traceStore)
|
||||
db, err := openDB(home)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
traceWriter, err := openTraceWriter(traceWriterFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
appState, validators, err := appExporter(ctx.Logger, db, traceWriter)
|
||||
if err != nil {
|
||||
return errors.Errorf("error exporting state: %v\n", err)
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/server/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEmptyState(t *testing.T) {
|
||||
defer setupViper(t)()
|
||||
logger := log.NewNopLogger()
|
||||
cfg, err := tcmd.ParseConfig()
|
||||
require.Nil(t, err)
|
||||
ctx := NewContext(cfg, logger)
|
||||
cdc := codec.New()
|
||||
appInit := AppInit{
|
||||
AppGenTx: mock.AppGenTx,
|
||||
AppGenState: mock.AppGenStateEmpty,
|
||||
}
|
||||
cmd := InitCmd(ctx, cdc, appInit)
|
||||
err = cmd.RunE(nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
old := os.Stdout
|
||||
r, w, _ := os.Pipe()
|
||||
os.Stdout = w
|
||||
cmd = 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, "WARNING: State is not initialized")
|
||||
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")
|
||||
}
|
313
server/init.go
313
server/init.go
|
@ -3,26 +3,12 @@ package server
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
cfg "github.com/tendermint/tendermint/config"
|
||||
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
pvm "github.com/tendermint/tendermint/privval"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
clkeys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
|
@ -62,303 +48,8 @@ type InitConfig struct {
|
|||
Overwrite bool
|
||||
}
|
||||
|
||||
// get cmd to initialize all files for tendermint and application
|
||||
func GenTxCmd(ctx *Context, cdc *codec.Codec, appInit AppInit) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "gen-tx",
|
||||
Short: "Create genesis transaction file (under [--home]/config/gentx/gentx-[nodeID].json)",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
|
||||
config := ctx.Config
|
||||
config.SetRoot(viper.GetString(tmcli.HomeFlag))
|
||||
|
||||
ip := viper.GetString(FlagIP)
|
||||
if len(ip) == 0 {
|
||||
eip, err := externalIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ip = eip
|
||||
}
|
||||
|
||||
genTxConfig := serverconfig.GenTx{
|
||||
viper.GetString(FlagName),
|
||||
viper.GetString(FlagClientHome),
|
||||
viper.GetBool(FlagOWK),
|
||||
ip,
|
||||
}
|
||||
cliPrint, genTxFile, err := gentxWithConfig(cdc, appInit, config, genTxConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
toPrint := struct {
|
||||
AppMessage json.RawMessage `json:"app_message"`
|
||||
GenTxFile json.RawMessage `json:"gen_tx_file"`
|
||||
}{
|
||||
cliPrint,
|
||||
genTxFile,
|
||||
}
|
||||
out, err := codec.MarshalJSONIndent(cdc, toPrint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
cmd.Flags().String(FlagIP, "", "external facing IP to use if left blank IP will be retrieved from this machine")
|
||||
cmd.Flags().AddFlagSet(appInit.FlagsAppGenTx)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func gentxWithConfig(cdc *codec.Codec, appInit AppInit, config *cfg.Config, genTxConfig serverconfig.GenTx) (
|
||||
cliPrint json.RawMessage, genTxFile json.RawMessage, err error) {
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nodeID := string(nodeKey.ID())
|
||||
pubKey := readOrCreatePrivValidator(config)
|
||||
|
||||
appGenTx, cliPrint, validator, err := appInit.AppGenTx(cdc, pubKey, genTxConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
tx := GenesisTx{
|
||||
NodeID: nodeID,
|
||||
IP: genTxConfig.IP,
|
||||
Validator: validator,
|
||||
AppGenTx: appGenTx,
|
||||
}
|
||||
bz, err := codec.MarshalJSONIndent(cdc, tx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
genTxFile = json.RawMessage(bz)
|
||||
name := fmt.Sprintf("gentx-%v.json", nodeID)
|
||||
writePath := filepath.Join(config.RootDir, "config", "gentx")
|
||||
file := filepath.Join(writePath, name)
|
||||
err = cmn.EnsureDir(writePath, 0700)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = cmn.WriteFile(file, bz, 0644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Write updated config with moniker
|
||||
config.Moniker = genTxConfig.Name
|
||||
configFilePath := filepath.Join(config.RootDir, "config", "config.toml")
|
||||
cfg.WriteConfigFile(configFilePath, config)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// get cmd to initialize all files for tendermint and application
|
||||
func InitCmd(ctx *Context, cdc *codec.Codec, appInit AppInit) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Initialize genesis config, priv-validator file, and p2p-node file",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(_ *cobra.Command, _ []string) error {
|
||||
|
||||
config := ctx.Config
|
||||
config.SetRoot(viper.GetString(tmcli.HomeFlag))
|
||||
initConfig := InitConfig{
|
||||
viper.GetString(FlagChainID),
|
||||
viper.GetBool(FlagWithTxs),
|
||||
filepath.Join(config.RootDir, "config", "gentx"),
|
||||
viper.GetBool(FlagOverwrite),
|
||||
}
|
||||
|
||||
chainID, nodeID, appMessage, err := initWithConfig(cdc, appInit, config, initConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// print out some key information
|
||||
toPrint := struct {
|
||||
ChainID string `json:"chain_id"`
|
||||
NodeID string `json:"node_id"`
|
||||
AppMessage json.RawMessage `json:"app_message"`
|
||||
}{
|
||||
chainID,
|
||||
nodeID,
|
||||
appMessage,
|
||||
}
|
||||
out, err := codec.MarshalJSONIndent(cdc, toPrint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolP(FlagOverwrite, "o", false, "overwrite the genesis.json file")
|
||||
cmd.Flags().String(FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
|
||||
cmd.Flags().Bool(FlagWithTxs, false, "apply existing genesis transactions from [--home]/config/gentx/")
|
||||
cmd.Flags().AddFlagSet(appInit.FlagsAppGenState)
|
||||
cmd.Flags().AddFlagSet(appInit.FlagsAppGenTx) // need to add this flagset for when no GenTx's provided
|
||||
cmd.AddCommand(GenTxCmd(ctx, cdc, appInit))
|
||||
return cmd
|
||||
}
|
||||
|
||||
func initWithConfig(cdc *codec.Codec, appInit AppInit, config *cfg.Config, initConfig InitConfig) (
|
||||
chainID string, nodeID string, appMessage json.RawMessage, err error) {
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nodeID = string(nodeKey.ID())
|
||||
pubKey := readOrCreatePrivValidator(config)
|
||||
|
||||
if initConfig.ChainID == "" {
|
||||
initConfig.ChainID = fmt.Sprintf("test-chain-%v", cmn.RandStr(6))
|
||||
}
|
||||
chainID = initConfig.ChainID
|
||||
|
||||
genFile := config.GenesisFile()
|
||||
if !initConfig.Overwrite && cmn.FileExists(genFile) {
|
||||
err = fmt.Errorf("genesis.json file already exists: %v", genFile)
|
||||
return
|
||||
}
|
||||
|
||||
// process genesis transactions, or otherwise create one for defaults
|
||||
var appGenTxs []json.RawMessage
|
||||
var validators []tmtypes.GenesisValidator
|
||||
var persistentPeers string
|
||||
|
||||
if initConfig.GenTxs {
|
||||
validators, appGenTxs, persistentPeers, err = processGenTxs(initConfig.GenTxsDir, cdc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config.P2P.PersistentPeers = persistentPeers
|
||||
configFilePath := filepath.Join(config.RootDir, "config", "config.toml")
|
||||
cfg.WriteConfigFile(configFilePath, config)
|
||||
} else {
|
||||
genTxConfig := serverconfig.GenTx{
|
||||
viper.GetString(FlagName),
|
||||
viper.GetString(FlagClientHome),
|
||||
viper.GetBool(FlagOWK),
|
||||
"127.0.0.1",
|
||||
}
|
||||
|
||||
// Write updated config with moniker
|
||||
config.Moniker = genTxConfig.Name
|
||||
configFilePath := filepath.Join(config.RootDir, "config", "config.toml")
|
||||
cfg.WriteConfigFile(configFilePath, config)
|
||||
appGenTx, am, validator, err := appInit.AppGenTx(cdc, pubKey, genTxConfig)
|
||||
appMessage = am
|
||||
if err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
validators = []tmtypes.GenesisValidator{validator}
|
||||
appGenTxs = []json.RawMessage{appGenTx}
|
||||
}
|
||||
|
||||
appState, err := appInit.AppGenState(cdc, appGenTxs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = writeGenesisFile(cdc, genFile, initConfig.ChainID, validators, appState)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// append a genesis-piece
|
||||
func processGenTxs(genTxsDir string, cdc *codec.Codec) (
|
||||
validators []tmtypes.GenesisValidator, appGenTxs []json.RawMessage, persistentPeers string, err error) {
|
||||
|
||||
var fos []os.FileInfo
|
||||
fos, err = ioutil.ReadDir(genTxsDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
genTxs := make(map[string]GenesisTx)
|
||||
var nodeIDs []string
|
||||
for _, fo := range fos {
|
||||
filename := path.Join(genTxsDir, fo.Name())
|
||||
if !fo.IsDir() && (path.Ext(filename) != ".json") {
|
||||
continue
|
||||
}
|
||||
|
||||
// get the genTx
|
||||
var bz []byte
|
||||
bz, err = ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var genTx GenesisTx
|
||||
err = cdc.UnmarshalJSON(bz, &genTx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
genTxs[genTx.NodeID] = genTx
|
||||
nodeIDs = append(nodeIDs, genTx.NodeID)
|
||||
}
|
||||
|
||||
sort.Strings(nodeIDs)
|
||||
|
||||
for _, nodeID := range nodeIDs {
|
||||
genTx := genTxs[nodeID]
|
||||
|
||||
// combine some stuff
|
||||
validators = append(validators, genTx.Validator)
|
||||
appGenTxs = append(appGenTxs, genTx.AppGenTx)
|
||||
|
||||
// Add a persistent peer
|
||||
comma := ","
|
||||
if len(persistentPeers) == 0 {
|
||||
comma = ""
|
||||
}
|
||||
persistentPeers += fmt.Sprintf("%s%s@%s:26656", comma, genTx.NodeID, genTx.IP)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
//________________________________________________________________________________________
|
||||
|
||||
// read of create the private key file for this config
|
||||
func readOrCreatePrivValidator(tmConfig *cfg.Config) crypto.PubKey {
|
||||
// private validator
|
||||
privValFile := tmConfig.PrivValidatorFile()
|
||||
var privValidator *pvm.FilePV
|
||||
if cmn.FileExists(privValFile) {
|
||||
privValidator = pvm.LoadFilePV(privValFile)
|
||||
} else {
|
||||
privValidator = pvm.GenFilePV(privValFile)
|
||||
privValidator.Save()
|
||||
}
|
||||
return privValidator.GetPubKey()
|
||||
}
|
||||
|
||||
// writeGenesisFile creates and writes the genesis configuration to disk. An
|
||||
// error is returned if building or writing the configuration to file fails.
|
||||
// nolint: unparam
|
||||
func writeGenesisFile(cdc *codec.Codec, genesisFile, chainID string, validators []tmtypes.GenesisValidator, appState json.RawMessage) error {
|
||||
genDoc := tmtypes.GenesisDoc{
|
||||
ChainID: chainID,
|
||||
Validators: validators,
|
||||
AppState: appState,
|
||||
}
|
||||
|
||||
if err := genDoc.ValidateAndComplete(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return genDoc.SaveAs(genesisFile)
|
||||
}
|
||||
|
||||
//_____________________________________________________________________
|
||||
|
||||
// Core functionality passed from the application to the server init command
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/server/mock"
|
||||
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
||||
)
|
||||
|
||||
// TODO update
|
||||
func TestInitCmd(t *testing.T) {
|
||||
defer setupViper(t)()
|
||||
|
||||
logger := log.NewNopLogger()
|
||||
cfg, err := tcmd.ParseConfig()
|
||||
require.Nil(t, err)
|
||||
ctx := NewContext(cfg, logger)
|
||||
cdc := codec.New()
|
||||
appInit := AppInit{
|
||||
AppGenState: mock.AppGenState,
|
||||
AppGenTx: mock.AppGenTx,
|
||||
}
|
||||
cmd := InitCmd(ctx, cdc, appInit)
|
||||
err = cmd.RunE(nil, nil)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGenTxCmd(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestTestnetFilesCmd(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestSimpleAppGenTx(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestSimpleAppGenState(t *testing.T) {
|
||||
// TODO
|
||||
}
|
|
@ -57,12 +57,18 @@ func StartCmd(ctx *Context, appCreator AppCreator) *cobra.Command {
|
|||
func startStandAlone(ctx *Context, appCreator AppCreator) error {
|
||||
addr := viper.GetString(flagAddress)
|
||||
home := viper.GetString("home")
|
||||
traceStore := viper.GetString(flagTraceStore)
|
||||
traceWriterFile := viper.GetString(flagTraceStore)
|
||||
|
||||
app, err := appCreator(home, ctx.Logger, traceStore)
|
||||
db, err := openDB(home)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
traceWriter, err := openTraceWriter(traceWriterFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app := appCreator(ctx.Logger, db, traceWriter)
|
||||
|
||||
svr, err := server.NewServer(addr, "socket", app)
|
||||
if err != nil {
|
||||
|
@ -91,12 +97,18 @@ func startStandAlone(ctx *Context, appCreator AppCreator) error {
|
|||
func startInProcess(ctx *Context, appCreator AppCreator) (*node.Node, error) {
|
||||
cfg := ctx.Config
|
||||
home := cfg.RootDir
|
||||
traceStore := viper.GetString(flagTraceStore)
|
||||
traceWriterFile := viper.GetString(flagTraceStore)
|
||||
|
||||
app, err := appCreator(home, ctx.Logger, traceStore)
|
||||
db, err := openDB(home)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
traceWriter, err := openTraceWriter(traceWriterFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
app := appCreator(ctx.Logger, db, traceWriter)
|
||||
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile())
|
||||
if err != nil {
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/server/mock"
|
||||
"github.com/tendermint/tendermint/abci/server"
|
||||
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
)
|
||||
|
||||
func TestStartStandAlone(t *testing.T) {
|
||||
home, err := ioutil.TempDir("", "mock-sdk-cmd")
|
||||
require.Nil(t, err)
|
||||
defer func() {
|
||||
os.RemoveAll(home)
|
||||
}()
|
||||
|
||||
logger := log.NewNopLogger()
|
||||
cfg, err := tcmd.ParseConfig()
|
||||
require.Nil(t, err)
|
||||
ctx := NewContext(cfg, logger)
|
||||
cdc := codec.New()
|
||||
appInit := AppInit{
|
||||
AppGenState: mock.AppGenState,
|
||||
AppGenTx: mock.AppGenTx,
|
||||
}
|
||||
initCmd := InitCmd(ctx, cdc, appInit)
|
||||
err = initCmd.RunE(nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
app, err := mock.NewApp(home, logger)
|
||||
require.Nil(t, err)
|
||||
svrAddr, _, err := FreeTCPAddr()
|
||||
require.Nil(t, err)
|
||||
svr, err := server.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()
|
||||
}
|
||||
}
|
|
@ -36,9 +36,9 @@ func FreeTCPAddr() (addr, port string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// setupViper creates a homedir to run inside,
|
||||
// SetupViper creates a homedir to run inside,
|
||||
// and returns a cleanup function to defer
|
||||
func setupViper(t *testing.T) func() {
|
||||
func SetupViper(t *testing.T) func() {
|
||||
rootDir, err := ioutil.TempDir("", "mock-sdk-cmd")
|
||||
require.Nil(t, err)
|
||||
viper.Set(cli.HomeFlag, rootDir)
|
||||
|
|
|
@ -42,7 +42,7 @@ func NewContext(config *cfg.Config, logger log.Logger) *Context {
|
|||
|
||||
// PersistentPreRunEFn returns a PersistentPreRunE function for cobra
|
||||
// that initailizes the passed in context with a properly configured
|
||||
// logger and config objecy
|
||||
// logger and config object.
|
||||
func PersistentPreRunEFn(context *Context) func(*cobra.Command, []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
if cmd.Name() == version.VersionCmd.Name() {
|
||||
|
@ -85,7 +85,7 @@ func interceptLoadConfig() (conf *cfg.Config, err error) {
|
|||
|
||||
if _, err := os.Stat(configFilePath); os.IsNotExist(err) {
|
||||
// the following parse config is needed to create directories
|
||||
conf, _ = tcmd.ParseConfig()
|
||||
conf, _ = tcmd.ParseConfig() // NOTE: ParseConfig() creates dir/files as necessary.
|
||||
conf.ProfListenAddress = "localhost:6060"
|
||||
conf.P2P.RecvRate = 5120000
|
||||
conf.P2P.SendRate = 5120000
|
||||
|
@ -96,7 +96,7 @@ func interceptLoadConfig() (conf *cfg.Config, err error) {
|
|||
}
|
||||
|
||||
if conf == nil {
|
||||
conf, err = tcmd.ParseConfig()
|
||||
conf, err = tcmd.ParseConfig() // NOTE: ParseConfig() creates dir/files as necessary.
|
||||
}
|
||||
|
||||
cosmosConfigFilePath := filepath.Join(rootDir, "config/gaiad.toml")
|
||||
|
@ -143,8 +143,6 @@ func AddCommands(
|
|||
)
|
||||
|
||||
rootCmd.AddCommand(
|
||||
InitCmd(ctx, cdc, appInit),
|
||||
TestnetFilesCmd(ctx, cdc, appInit),
|
||||
StartCmd(ctx, appCreator),
|
||||
UnsafeResetAllCmd(ctx),
|
||||
client.LineBreak,
|
||||
|
@ -177,7 +175,7 @@ func InsertKeyJSON(cdc *codec.Codec, baseJSON []byte, key string, value json.Raw
|
|||
|
||||
// https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go
|
||||
// TODO there must be a better way to get external IP
|
||||
func externalIP() (string, error) {
|
||||
func ExternalIP() (string, error) {
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
@ -66,7 +66,7 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command {
|
|||
// build and sign the transaction, then broadcast to Tendermint
|
||||
msg := client.CreateMsg(from, to, coins)
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
|
|
|
@ -103,7 +103,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome
|
|||
}
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
|
||||
// Build and sign the transaction, then broadcast to Tendermint
|
||||
|
@ -183,7 +183,7 @@ func GetCmdDeposit(cdc *codec.Codec) *cobra.Command {
|
|||
}
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
|
||||
// Build and sign the transaction, then broadcast to a Tendermint
|
||||
|
@ -229,7 +229,7 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command {
|
|||
}
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
|
||||
fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]",
|
||||
|
|
|
@ -42,7 +42,7 @@ func IBCTransferCmd(cdc *codec.Codec) *cobra.Command {
|
|||
return err
|
||||
}
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
|
|
|
@ -31,7 +31,7 @@ func GetCmdUnjail(cdc *codec.Codec) *cobra.Command {
|
|||
|
||||
msg := slashing.NewMsgUnjail(sdk.ValAddress(valAddr))
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
|
|
|
@ -88,7 +88,7 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
|
|||
}
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, true)
|
||||
}
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
|
@ -143,7 +143,7 @@ func GetCmdEditValidator(cdc *codec.Codec) *cobra.Command {
|
|||
msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description, newRate)
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
|
@ -186,7 +186,7 @@ func GetCmdDelegate(cdc *codec.Codec) *cobra.Command {
|
|||
msg := stake.NewMsgDelegate(delAddr, valAddr, amount)
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
|
@ -256,7 +256,7 @@ func GetCmdBeginRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
|
|||
msg := stake.NewMsgBeginRedelegate(delAddr, valSrcAddr, valDstAddr, sharesAmount)
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
|
@ -319,7 +319,7 @@ func GetCmdBeginUnbonding(storeName string, cdc *codec.Codec) *cobra.Command {
|
|||
msg := stake.NewMsgBeginUnbonding(delAddr, valAddr, sharesAmount)
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
|
|
Loading…
Reference in New Issue