diff --git a/Makefile b/Makefile index 8c9c5214d..328e65f8a 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,10 @@ build: go build \ --ldflags "-X github.com/tendermint/tendermint/version.GitCommit=`git rev-parse HEAD`" -o build/tendermint ./cmd/tendermint/ +build_hsm: + go build \ + --ldflags "-X github.com/tendermint/tendermint/version.GitCommit=`git rev-parse HEAD`" -o build/tendermint ./cmd/hsm/ + build_race: go build -race -o build/tendermint ./cmd/tendermint diff --git a/cmd/hsm/commands/run_node.go b/cmd/hsm/commands/run_node.go new file mode 100644 index 000000000..94a1c548e --- /dev/null +++ b/cmd/hsm/commands/run_node.go @@ -0,0 +1,107 @@ +package commands + +import ( + "fmt" + "os" + "time" + + "github.com/spf13/cobra" + + cfg "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/node" + "github.com/tendermint/tendermint/proxy" + "github.com/tendermint/tendermint/types" + + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" +) + +var ( + config = cfg.DefaultConfig() + logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "main") +) + +var RunNodeCmd = &cobra.Command{ + Use: "node", + Short: "Run the tendermint node", + RunE: runNode, +} + +func init() { + AddNodeFlags(RunNodeCmd) +} + +// AddNodeFlags exposes some common configuration options on the command-line +// These are exposed for convenience of commands embedding a tendermint node +func AddNodeFlags(cmd *cobra.Command) { + // bind flags + cmd.Flags().String("moniker", config.Moniker, "Node Name") + + // node flags + cmd.Flags().Bool("fast_sync", config.FastSync, "Fast blockchain syncing") + + // abci flags + cmd.Flags().String("proxy_app", config.ProxyApp, "Proxy app address, or 'nilapp' or 'dummy' for local testing.") + cmd.Flags().String("abci", config.ABCI, "Specify abci transport (socket | grpc)") + + // rpc flags + cmd.Flags().String("rpc.laddr", config.RPC.ListenAddress, "RPC listen address. Port required") + cmd.Flags().String("rpc.grpc_laddr", config.RPC.GRPCListenAddress, "GRPC listen address (BroadcastTx only). Port required") + cmd.Flags().Bool("rpc.unsafe", config.RPC.Unsafe, "Enabled unsafe rpc methods") + + // p2p flags + cmd.Flags().String("p2p.laddr", config.P2P.ListenAddress, "Node listen address. (0.0.0.0:0 means any interface, any port)") + cmd.Flags().String("p2p.seeds", config.P2P.Seeds, "Comma delimited host:port seed nodes") + cmd.Flags().Bool("p2p.skip_upnp", config.P2P.SkipUPNP, "Skip UPNP configuration") + cmd.Flags().Bool("p2p.pex", config.P2P.PexReactor, "Enable Peer-Exchange (dev feature)") + + // consensus flags + cmd.Flags().Bool("consensus.create_empty_blocks", config.Consensus.CreateEmptyBlocks, "Set this to false to only produce blocks when there are txs or when the AppHash changes") +} + +// Users wishing to: +// * Use an external signer for their validators +// * Supply an in-proc abci app +// should import github.com/tendermint/tendermint/node and implement +// their own run_node to call node.NewNode (instead of node.NewNodeDefault) +// with their custom priv validator and/or custom proxy.ClientCreator +func runNode(cmd *cobra.Command, args []string) error { + + // Wait until the genesis doc becomes available + // This is for Mintnet compatibility. + // TODO: If Mintnet gets deprecated or genesis_file is + // always available, remove. + genDocFile := config.GenesisFile() + for !cmn.FileExists(genDocFile) { + logger.Info(cmn.Fmt("Waiting for genesis file %v...", genDocFile)) + time.Sleep(time.Second) + } + + genDoc, err := types.GenesisDocFromFile(genDocFile) + if err != nil { + return err + } + config.ChainID = genDoc.ChainID + + // Create & start node + // n := node.NewNodeDefault(config, logger.With("module", "node")) + + // TODO: Make types.PrivValidator an interface so that it can be provided + // by a hardware wallet or any other wallet provider. + + // The next two lines show how a private validator is setup. + privValidator := types.LoadOrGenPrivValidator(config.PrivValidatorFile(), logger) + privValidator.SetSigner(types.NewDefaultSigner(privValidator.PrivKey)) + + n := node.NewNode(config, privValidator, proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), logger) + if _, err := n.Start(); err != nil { + return fmt.Errorf("Failed to start node: %v", err) + } else { + logger.Info("Started node", "nodeInfo", n.Switch().NodeInfo()) + } + + // Trap signal, run forever. + n.RunForever() + + return nil +} diff --git a/cmd/hsm/main.go b/cmd/hsm/main.go new file mode 100644 index 000000000..743a8fcd9 --- /dev/null +++ b/cmd/hsm/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "os" + + tc "github.com/tendermint/tendermint/cmd/tendermint/commands" + "github.com/tendermint/tmlibs/cli" + + "github.com/tendermint/tendermint/cmd/hsm/commands" +) + +func main() { + // TODO: Make it easier to build a tendermint instance from scratch. + // All commands should be exported and it should be easy to override + // certain aspects of a single command. + // Probably every command should have a constructor that allows a user + // to vary the configuration. This is at least true for run_node.go + + rootCmd := tc.RootCmd + rootCmd.AddCommand(tc.GenValidatorCmd) + rootCmd.AddCommand(tc.InitFilesCmd) + rootCmd.AddCommand(tc.ProbeUpnpCmd) + rootCmd.AddCommand(tc.ReplayCmd) + rootCmd.AddCommand(tc.ReplayConsoleCmd) + rootCmd.AddCommand(tc.ResetAllCmd) + rootCmd.AddCommand(tc.ResetPrivValidatorCmd) + rootCmd.AddCommand(tc.ShowValidatorCmd) + rootCmd.AddCommand(tc.TestnetFilesCmd) + rootCmd.AddCommand(tc.VersionCmd) + + rootCmd.AddCommand(commands.RunNodeCmd) + + cmd := cli.PrepareBaseCmd(rootCmd, "TM", os.ExpandEnv("$HOME/.tendermint")) + cmd.Execute() +} diff --git a/cmd/tendermint/commands/gen_validator.go b/cmd/tendermint/commands/gen_validator.go index 97c583c22..df82554d8 100644 --- a/cmd/tendermint/commands/gen_validator.go +++ b/cmd/tendermint/commands/gen_validator.go @@ -9,16 +9,12 @@ import ( "github.com/tendermint/tendermint/types" ) -var genValidatorCmd = &cobra.Command{ +var GenValidatorCmd = &cobra.Command{ Use: "gen_validator", Short: "Generate new validator keypair", Run: genValidator, } -func init() { - RootCmd.AddCommand(genValidatorCmd) -} - func genValidator(cmd *cobra.Command, args []string) { privValidator := types.GenPrivValidator() privValidatorJSONBytes, _ := json.MarshalIndent(privValidator, "", "\t") diff --git a/cmd/tendermint/commands/init.go b/cmd/tendermint/commands/init.go index ce900defa..b844386c5 100644 --- a/cmd/tendermint/commands/init.go +++ b/cmd/tendermint/commands/init.go @@ -9,16 +9,12 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) -var initFilesCmd = &cobra.Command{ +var InitFilesCmd = &cobra.Command{ Use: "init", Short: "Initialize Tendermint", Run: initFiles, } -func init() { - RootCmd.AddCommand(initFilesCmd) -} - func initFiles(cmd *cobra.Command, args []string) { privValFile := config.PrivValidatorFile() if _, err := os.Stat(privValFile); os.IsNotExist(err) { diff --git a/cmd/tendermint/commands/probe_upnp.go b/cmd/tendermint/commands/probe_upnp.go index e23e48973..a4c71d59e 100644 --- a/cmd/tendermint/commands/probe_upnp.go +++ b/cmd/tendermint/commands/probe_upnp.go @@ -9,16 +9,12 @@ import ( "github.com/tendermint/tendermint/p2p/upnp" ) -var probeUpnpCmd = &cobra.Command{ +var ProbeUpnpCmd = &cobra.Command{ Use: "probe_upnp", Short: "Test UPnP functionality", RunE: probeUpnp, } -func init() { - RootCmd.AddCommand(probeUpnpCmd) -} - func probeUpnp(cmd *cobra.Command, args []string) error { capabilities, err := upnp.Probe(logger) if err != nil { diff --git a/cmd/tendermint/commands/replay.go b/cmd/tendermint/commands/replay.go index 0c88b2443..422d44159 100644 --- a/cmd/tendermint/commands/replay.go +++ b/cmd/tendermint/commands/replay.go @@ -6,7 +6,7 @@ import ( "github.com/tendermint/tendermint/consensus" ) -var replayCmd = &cobra.Command{ +var ReplayCmd = &cobra.Command{ Use: "replay", Short: "Replay messages from WAL", Run: func(cmd *cobra.Command, args []string) { @@ -14,15 +14,10 @@ var replayCmd = &cobra.Command{ }, } -var replayConsoleCmd = &cobra.Command{ +var ReplayConsoleCmd = &cobra.Command{ Use: "replay_console", Short: "Replay messages from WAL in a console", Run: func(cmd *cobra.Command, args []string) { consensus.RunReplayFile(config.BaseConfig, config.Consensus, true) }, } - -func init() { - RootCmd.AddCommand(replayCmd) - RootCmd.AddCommand(replayConsoleCmd) -} diff --git a/cmd/tendermint/commands/reset_priv_validator.go b/cmd/tendermint/commands/reset_priv_validator.go index fa12be4ea..389e5b79b 100644 --- a/cmd/tendermint/commands/reset_priv_validator.go +++ b/cmd/tendermint/commands/reset_priv_validator.go @@ -9,23 +9,18 @@ import ( "github.com/tendermint/tmlibs/log" ) -var resetAllCmd = &cobra.Command{ +var ResetAllCmd = &cobra.Command{ Use: "unsafe_reset_all", Short: "(unsafe) Remove all the data and WAL, reset this node's validator", Run: resetAll, } -var resetPrivValidatorCmd = &cobra.Command{ +var ResetPrivValidatorCmd = &cobra.Command{ Use: "unsafe_reset_priv_validator", Short: "(unsafe) Reset this node's validator", Run: resetPrivValidator, } -func init() { - RootCmd.AddCommand(resetAllCmd) - RootCmd.AddCommand(resetPrivValidatorCmd) -} - // XXX: this is totally unsafe. // it's only suitable for testnets. func resetAll(cmd *cobra.Command, args []string) { diff --git a/cmd/tendermint/commands/run_node.go b/cmd/tendermint/commands/run_node.go index 6740df289..413e2cc7a 100644 --- a/cmd/tendermint/commands/run_node.go +++ b/cmd/tendermint/commands/run_node.go @@ -9,15 +9,14 @@ import ( "github.com/tendermint/tendermint/types" ) -var runNodeCmd = &cobra.Command{ +var RunNodeCmd = &cobra.Command{ Use: "node", Short: "Run the tendermint node", RunE: runNode, } func init() { - AddNodeFlags(runNodeCmd) - RootCmd.AddCommand(runNodeCmd) + AddNodeFlags(RunNodeCmd) } // AddNodeFlags exposes some common configuration options on the command-line diff --git a/cmd/tendermint/commands/show_validator.go b/cmd/tendermint/commands/show_validator.go index 53a687c6d..21cc90270 100644 --- a/cmd/tendermint/commands/show_validator.go +++ b/cmd/tendermint/commands/show_validator.go @@ -9,16 +9,12 @@ import ( "github.com/tendermint/tendermint/types" ) -var showValidatorCmd = &cobra.Command{ +var ShowValidatorCmd = &cobra.Command{ Use: "show_validator", Short: "Show this node's validator info", Run: showValidator, } -func init() { - RootCmd.AddCommand(showValidatorCmd) -} - func showValidator(cmd *cobra.Command, args []string) { privValidator := types.LoadOrGenPrivValidator(config.PrivValidatorFile(), logger) pubKeyJSONBytes, _ := data.ToJSON(privValidator.PubKey) diff --git a/cmd/tendermint/commands/testnet.go b/cmd/tendermint/commands/testnet.go index 315f3b498..75e016c9d 100644 --- a/cmd/tendermint/commands/testnet.go +++ b/cmd/tendermint/commands/testnet.go @@ -11,7 +11,7 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) -var testnetFilesCmd = &cobra.Command{ +var TestnetFilesCmd = &cobra.Command{ Use: "testnet", Short: "Initialize files for a Tendermint testnet", Run: testnetFiles, @@ -24,12 +24,10 @@ var ( ) func init() { - testnetFilesCmd.Flags().IntVar(&nValidators, "n", 4, + TestnetFilesCmd.Flags().IntVar(&nValidators, "n", 4, "Number of validators to initialize the testnet with") - testnetFilesCmd.Flags().StringVar(&dataDir, "dir", "mytestnet", + TestnetFilesCmd.Flags().StringVar(&dataDir, "dir", "mytestnet", "Directory to store initialization data for the testnet") - - RootCmd.AddCommand(testnetFilesCmd) } func testnetFiles(cmd *cobra.Command, args []string) { diff --git a/cmd/tendermint/commands/version.go b/cmd/tendermint/commands/version.go index 5c92160ea..692cba4ad 100644 --- a/cmd/tendermint/commands/version.go +++ b/cmd/tendermint/commands/version.go @@ -8,14 +8,10 @@ import ( "github.com/tendermint/tendermint/version" ) -var versionCmd = &cobra.Command{ +var VersionCmd = &cobra.Command{ Use: "version", - Short: "Show version info", + Short: "Show version infoooooooo", Run: func(cmd *cobra.Command, args []string) { fmt.Println(version.Version) }, } - -func init() { - RootCmd.AddCommand(versionCmd) -}