diff --git a/.gitignore b/.gitignore index b2a29d086..6eb5b9675 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ shunit2 terraform.tfstate terraform.tfstate.backup terraform.tfstate.d +test/app/grpc_client test/e2e/build test/e2e/networks/*/ test/logs diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index da3fdd837..92af3dc30 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -15,6 +15,7 @@ Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermi - [cli] \#5777 use hyphen-case instead of snake_case for all cli commands and config parameters (@cmwaters) - [rpc] \#6019 standardise RPC errors and return the correct status code (@bipulprasad & @cmwaters) - [rpc] \#6168 Change default sorting to desc for `/tx_search` results (@melekes) + - [cli] \#6282 User must specify the node mode when using `tendermint init` (@cmwaters) - Apps - [ABCI] \#5447 Remove `SetOption` method from `ABCI.Client` interface diff --git a/DOCKER/docker-entrypoint.sh b/DOCKER/docker-entrypoint.sh index d74511c17..e6442b485 100755 --- a/DOCKER/docker-entrypoint.sh +++ b/DOCKER/docker-entrypoint.sh @@ -3,7 +3,7 @@ set -e if [ ! -d "$TMHOME/config" ]; then echo "Running tendermint init to create (default) configuration for docker run." - tendermint init + tendermint init validator sed -i \ -e "s/^proxy-app\s*=.*/proxy-app = \"$PROXY_APP\"/" \ diff --git a/UPGRADING.md b/UPGRADING.md index ce8c2a2a6..e9170ffab 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -24,9 +24,11 @@ This guide provides instructions for upgrading to specific versions of Tendermin ### CLI Changes +* You must now specify the node mode (validator|full|seed) in `tendermint init [mode]` + * If you had previously used `tendermint gen_node_key` to generate a new node key, keep in mind that it no longer saves the output to a file. You can use - `tendermint init` or pipe the output of `tendermint gen_node_key` to + `tendermint init validator` or pipe the output of `tendermint gen_node_key` to `$TMHOME/config/node_key.json`: ``` diff --git a/cmd/tendermint/commands/init.go b/cmd/tendermint/commands/init.go index efe0f0244..99a59773c 100644 --- a/cmd/tendermint/commands/init.go +++ b/cmd/tendermint/commands/init.go @@ -2,6 +2,7 @@ package commands import ( "context" + "errors" "fmt" "github.com/spf13/cobra" @@ -17,9 +18,12 @@ import ( // InitFilesCmd initializes a fresh Tendermint Core instance. var InitFilesCmd = &cobra.Command{ - Use: "init", - Short: "Initialize Tendermint", - RunE: initFiles, + Use: "init [full|validator|seed]", + Short: "Initializes a Tendermint node", + ValidArgs: []string{"full", "validator", "seed"}, + // We allow for zero args so we can throw a more informative error + Args: cobra.MaximumNArgs(1), + RunE: initFiles, } var ( @@ -32,33 +36,40 @@ func init() { } func initFiles(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return errors.New("must specify a node type: tendermint init [validator|full|seed]") + } + config.Mode = args[0] return initFilesWithConfig(config) } func initFilesWithConfig(config *cfg.Config) error { - // private validator - privValKeyFile := config.PrivValidatorKeyFile() - privValStateFile := config.PrivValidatorStateFile() var ( pv *privval.FilePV err error ) - if tmos.FileExists(privValKeyFile) { - pv, err = privval.LoadFilePV(privValKeyFile, privValStateFile) - if err != nil { - return err - } - logger.Info("Found private validator", "keyFile", privValKeyFile, - "stateFile", privValStateFile) - } else { - pv, err = privval.GenFilePV(privValKeyFile, privValStateFile, keyType) - if err != nil { - return err + if config.Mode == cfg.ModeValidator { + // private validator + privValKeyFile := config.PrivValidatorKeyFile() + privValStateFile := config.PrivValidatorStateFile() + if tmos.FileExists(privValKeyFile) { + pv, err = privval.LoadFilePV(privValKeyFile, privValStateFile) + if err != nil { + return err + } + + logger.Info("Found private validator", "keyFile", privValKeyFile, + "stateFile", privValStateFile) + } else { + pv, err = privval.GenFilePV(privValKeyFile, privValStateFile, keyType) + if err != nil { + return err + } + pv.Save() + logger.Info("Generated private validator", "keyFile", privValKeyFile, + "stateFile", privValStateFile) } - pv.Save() - logger.Info("Generated private validator", "keyFile", privValKeyFile, - "stateFile", privValStateFile) } nodeKeyFile := config.NodeKeyFile() @@ -91,15 +102,18 @@ func initFilesWithConfig(config *cfg.Config) error { ctx, cancel := context.WithTimeout(context.TODO(), ctxTimeout) defer cancel() - pubKey, err := pv.GetPubKey(ctx) - if err != nil { - return fmt.Errorf("can't get pubkey: %w", err) + // if this is a validator we add it to genesis + if pv != nil { + pubKey, err := pv.GetPubKey(ctx) + if err != nil { + return fmt.Errorf("can't get pubkey: %w", err) + } + genDoc.Validators = []types.GenesisValidator{{ + Address: pubKey.Address(), + PubKey: pubKey, + Power: 10, + }} } - genDoc.Validators = []types.GenesisValidator{{ - Address: pubKey.Address(), - PubKey: pubKey, - Power: 10, - }} if err := genDoc.SaveAs(genFile); err != nil { return err @@ -107,5 +121,9 @@ func initFilesWithConfig(config *cfg.Config) error { logger.Info("Generated genesis file", "path", genFile) } + // write config file + cfg.WriteConfigFile(config.RootDir, config) + logger.Info("Generated config", "mode", config.Mode) + return nil } diff --git a/cmd/tendermint/commands/testnet.go b/cmd/tendermint/commands/testnet.go index 6dcf17e1e..5d225413f 100644 --- a/cmd/tendermint/commands/testnet.go +++ b/cmd/tendermint/commands/testnet.go @@ -106,8 +106,7 @@ func testnetFiles(cmd *cobra.Command, args []string) error { } // set mode to validator for testnet - config := cfg.DefaultConfig() - config.Mode = cfg.ModeValidator + config := cfg.DefaultValidatorConfig() // overwrite default config if set and valid if configFile != "" { @@ -242,7 +241,7 @@ func testnetFiles(cmd *cobra.Command, args []string) error { } config.Moniker = moniker(i) - cfg.WriteConfigFile(filepath.Join(nodeDir, "config", "config.toml"), config) + cfg.WriteConfigFile(nodeDir, config) } fmt.Printf("Successfully initialized %v node directories\n", nValidators+nNonValidators) diff --git a/config/config.go b/config/config.go index 8e43e2bb5..79be27d11 100644 --- a/config/config.go +++ b/config/config.go @@ -93,6 +93,13 @@ func DefaultConfig() *Config { } } +// DefaultValidatorConfig returns default config with mode as validator +func DefaultValidatorConfig() *Config { + cfg := DefaultConfig() + cfg.Mode = ModeValidator + return cfg +} + // TestConfig returns a configuration that can be used for testing func TestConfig() *Config { return &Config{ @@ -167,13 +174,13 @@ type BaseConfig struct { //nolint: maligned // A custom human readable name for this node Moniker string `mapstructure:"moniker"` - // Mode of Node: full | validator | seed (default: "full") - // * full (default) - // - all reactors - // - No priv_validator_key.json, priv_validator_state.json + // Mode of Node: full | validator | seed // * validator // - all reactors // - with priv_validator_key.json, priv_validator_state.json + // * full + // - all reactors + // - No priv_validator_key.json, priv_validator_state.json // * seed // - only P2P, PEX Reactor // - No priv_validator_key.json, priv_validator_state.json @@ -346,6 +353,8 @@ func (cfg BaseConfig) ValidateBasic() error { } switch cfg.Mode { case ModeFull, ModeValidator, ModeSeed: + case "": + return errors.New("no mode has been set") default: return fmt.Errorf("unknown mode: %v", cfg.Mode) } diff --git a/config/toml.go b/config/toml.go index f98a35198..84d26935d 100644 --- a/config/toml.go +++ b/config/toml.go @@ -41,32 +41,29 @@ func EnsureRoot(rootDir string) { if err := tmos.EnsureDir(filepath.Join(rootDir, defaultDataDir), DefaultDirPerm); err != nil { panic(err.Error()) } - - configFilePath := filepath.Join(rootDir, defaultConfigFilePath) - - // Write default config file if missing. - if !tmos.FileExists(configFilePath) { - writeDefaultConfigFile(configFilePath) - } -} - -// XXX: this func should probably be called by cmd/tendermint/commands/init.go -// alongside the writing of the genesis.json and priv_validator.json -func writeDefaultConfigFile(configFilePath string) { - WriteConfigFile(configFilePath, DefaultConfig()) } // WriteConfigFile renders config using the template and writes it to configFilePath. -func WriteConfigFile(configFilePath string, config *Config) { +// This function is called by cmd/tendermint/commands/init.go +func WriteConfigFile(rootDir string, config *Config) { var buffer bytes.Buffer if err := configTemplate.Execute(&buffer, config); err != nil { panic(err) } + configFilePath := filepath.Join(rootDir, defaultConfigFilePath) + mustWriteFile(configFilePath, buffer.Bytes(), 0644) } +func writeDefaultConfigFileIfNone(rootDir string) { + configFilePath := filepath.Join(rootDir, defaultConfigFilePath) + if !tmos.FileExists(configFilePath) { + WriteConfigFile(rootDir, DefaultConfig()) + } +} + // Note: any changes to the comments/variables/mapstructure // must be reflected in the appropriate struct in config/config.go const defaultConfigTemplate = `# This is a TOML config file. @@ -88,14 +85,13 @@ proxy-app = "{{ .BaseConfig.ProxyApp }}" # A custom human readable name for this node moniker = "{{ .BaseConfig.Moniker }}" -# Mode of Node: full | validator | seed (default: "full") -# You will need to set it to "validator" if you want to run the node as a validator -# * full node (default) -# - all reactors -# - No priv_validator_key.json, priv_validator_state.json +# Mode of Node: full | validator | seed # * validator node # - all reactors # - with priv_validator_key.json, priv_validator_state.json +# * full node +# - all reactors +# - No priv_validator_key.json, priv_validator_state.json # * seed node # - only P2P, PEX Reactor # - No priv_validator_key.json, priv_validator_state.json @@ -502,15 +498,12 @@ func ResetTestRootWithChainID(testName string, chainID string) *Config { } baseConfig := DefaultBaseConfig() - configFilePath := filepath.Join(rootDir, defaultConfigFilePath) genesisFilePath := filepath.Join(rootDir, baseConfig.Genesis) privKeyFilePath := filepath.Join(rootDir, baseConfig.PrivValidatorKey) privStateFilePath := filepath.Join(rootDir, baseConfig.PrivValidatorState) // Write default config file if missing. - if !tmos.FileExists(configFilePath) { - writeDefaultConfigFile(configFilePath) - } + writeDefaultConfigFileIfNone(rootDir) if !tmos.FileExists(genesisFilePath) { if chainID == "" { chainID = "tendermint_test" diff --git a/config/toml_test.go b/config/toml_test.go index fa587d583..950d218ec 100644 --- a/config/toml_test.go +++ b/config/toml_test.go @@ -30,6 +30,8 @@ func TestEnsureRoot(t *testing.T) { // create root dir EnsureRoot(tmpDir) + WriteConfigFile(tmpDir, DefaultConfig()) + // make sure config is set properly data, err := ioutil.ReadFile(filepath.Join(tmpDir, defaultConfigFilePath)) require.Nil(err) diff --git a/docs/app-dev/getting-started.md b/docs/app-dev/getting-started.md index 126da9371..7d261ae25 100644 --- a/docs/app-dev/getting-started.md +++ b/docs/app-dev/getting-started.md @@ -63,7 +63,7 @@ Tendermint binary installed. If not, follow the steps from before, use: ```sh -tendermint init +tendermint init validator tendermint start ``` diff --git a/docs/architecture/adr-008-priv-validator.md b/docs/architecture/adr-008-priv-validator.md index a8499465c..a3d31048a 100644 --- a/docs/architecture/adr-008-priv-validator.md +++ b/docs/architecture/adr-008-priv-validator.md @@ -4,7 +4,7 @@ Tendermint node's should support only two in-process PrivValidator implementations: - FilePV uses an unencrypted private key in a "priv_validator.json" file - no - configuration required (just `tendermint init`). + configuration required (just `tendermint init validator`). - TCPVal and IPCVal use TCP and Unix sockets respectively to send signing requests to another process - the user is responsible for starting that process themselves. diff --git a/docs/architecture/adr-052-tendermint-mode.md b/docs/architecture/adr-052-tendermint-mode.md index 4848b5356..866f92278 100644 --- a/docs/architecture/adr-052-tendermint-mode.md +++ b/docs/architecture/adr-052-tendermint-mode.md @@ -4,6 +4,7 @@ * 27-11-2019: Initial draft from ADR-051 * 13-01-2020: Separate ADR Tendermint Mode from ADR-051 +* 29-03-2021: Update info regarding defaults ## Context @@ -16,7 +17,7 @@ We would like to suggest a simple Tendermint mode abstraction. These modes will live under one binary, and when initializing a node the user will be able to specify which node they would like to create. - Which reactor, component to include for each node - - full *(default)* + - full - switch, transport - reactors - mempool @@ -46,7 +47,8 @@ We would like to suggest a simple Tendermint mode abstraction. These modes will - We would like to suggest by introducing `mode` parameter in `config.toml` and cli - `mode = "{{ .BaseConfig.Mode }}"` in `config.toml` - `tendermint start --mode validator` in cli - - full | validator | seednode (default: "full") + - full | validator | seednode + - There will be no default. Users will need to specify when they run `tendermint init` - RPC modification - `host:26657/status` - return empty `validator_info` when in full mode diff --git a/docs/introduction/install.md b/docs/introduction/install.md index 4d72cb90c..42394b9d6 100644 --- a/docs/introduction/install.md +++ b/docs/introduction/install.md @@ -56,7 +56,7 @@ tendermint version To start a one-node blockchain with a simple in-process application: ```sh -tendermint init +tendermint init validator tendermint start --proxy-app=kvstore ``` diff --git a/docs/introduction/quick-start.md b/docs/introduction/quick-start.md index c1a81c075..bc6f36af0 100644 --- a/docs/introduction/quick-start.md +++ b/docs/introduction/quick-start.md @@ -34,7 +34,7 @@ For manual installation, see the [install instructions](install.md) Running: ```sh -tendermint init +tendermint init validator ``` will create the required files for a single, local node. diff --git a/docs/nodes/configuration.md b/docs/nodes/configuration.md index eaf448c7e..35e639754 100644 --- a/docs/nodes/configuration.md +++ b/docs/nodes/configuration.md @@ -41,18 +41,17 @@ moniker = "anonymous" # and verifying their commits fast-sync = true -# Mode of Node: full | validator | seed -# You will need to set it to "validator" if you want to run the node as a validator -# * full node (default) -# - all reactors -# - No priv_validator_key.json, priv_validator_state.json -# * validator node +# Mode of Node: full | validator | seed (default: "validator") +# * validator node (default) # - all reactors # - with priv_validator_key.json, priv_validator_state.json +# * full node +# - all reactors +# - No priv_validator_key.json, priv_validator_state.json # * seed node # - only P2P, PEX Reactor # - No priv_validator_key.json, priv_validator_state.json -mode = "full" +mode = "validator" # Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb # * goleveldb (github.com/syndtr/goleveldb - most popular implementation) diff --git a/docs/tendermint-core/using-tendermint.md b/docs/tendermint-core/using-tendermint.md index f743a5dec..e6204c89e 100644 --- a/docs/tendermint-core/using-tendermint.md +++ b/docs/tendermint-core/using-tendermint.md @@ -21,7 +21,7 @@ this by setting the `TMHOME` environment variable. Initialize the root directory by running: ```sh -tendermint init +tendermint init validator ``` This will create a new private key (`priv_validator_key.json`), and a diff --git a/docs/tools/remote-signer-validation.md b/docs/tools/remote-signer-validation.md index 3099d7e4d..80a6a64bc 100644 --- a/docs/tools/remote-signer-validation.md +++ b/docs/tools/remote-signer-validation.md @@ -75,7 +75,7 @@ example, we will simply export a signing key from our local Tendermint instance. # Will generate all necessary Tendermint configuration files, including: # - ~/.tendermint/config/priv_validator_key.json # - ~/.tendermint/data/priv_validator_state.json -tendermint init +tendermint init validator # Extract the signing key from our local Tendermint instance tm-signer-harness extract_key \ # Use the "extract_key" command diff --git a/docs/tutorials/go-built-in.md b/docs/tutorials/go-built-in.md index f32a17eb7..040891637 100644 --- a/docs/tutorials/go-built-in.md +++ b/docs/tutorials/go-built-in.md @@ -393,7 +393,7 @@ func main() { func newTendermint(app abci.Application, configFile string) (*nm.Node, error) { // read config - config := cfg.DefaultConfig() + config := cfg.DefaultValidatorConfig() config.RootDir = filepath.Dir(filepath.Dir(configFile)) viper.SetConfigFile(configFile) if err := viper.ReadInConfig(); err != nil { @@ -503,7 +503,7 @@ of one communicating through a socket or gRPC. which we will generate later using the `tendermint init` command. ```go -config := cfg.DefaultConfig() +config := cfg.DefaultValidatorConfig() config.RootDir = filepath.Dir(filepath.Dir(configFile)) viper.SetConfigFile(configFile) if err := viper.ReadInConfig(); err != nil { @@ -604,7 +604,7 @@ go build ``` To create a default configuration, nodeKey and private validator files, let's -execute `tendermint init`. But before we do that, we will need to install +execute `tendermint init validator`. But before we do that, we will need to install Tendermint Core. Please refer to [the official guide](https://docs.tendermint.com/master/introduction/install.html). If you're installing from source, don't forget to checkout the latest release (`git @@ -613,11 +613,12 @@ major version. ```bash $ rm -rf /tmp/example -$ TMHOME="/tmp/example" tendermint init +$ TMHOME="/tmp/example" tendermint init validator I[2019-07-16|18:40:36.480] Generated private validator module=main keyFile=/tmp/example/config/priv_validator_key.json stateFile=/tmp/example2/data/priv_validator_state.json I[2019-07-16|18:40:36.481] Generated node key module=main path=/tmp/example/config/node_key.json I[2019-07-16|18:40:36.482] Generated genesis file module=main path=/tmp/example/config/genesis.json +I[2019-07-16|18:40:36.483] Generated config module=main mode=validator ``` We are ready to start our application: diff --git a/docs/tutorials/go.md b/docs/tutorials/go.md index a01292112..02625291f 100644 --- a/docs/tutorials/go.md +++ b/docs/tutorials/go.md @@ -461,7 +461,7 @@ go build ``` To create a default configuration, nodeKey and private validator files, let's -execute `tendermint init`. But before we do that, we will need to install +execute `tendermint init validator`. But before we do that, we will need to install Tendermint Core. Please refer to [the official guide](https://docs.tendermint.com/master/introduction/install.html). If you're installing from source, don't forget to checkout the latest release (`git @@ -470,11 +470,12 @@ major version. ```bash rm -rf /tmp/example -TMHOME="/tmp/example" tendermint init +TMHOME="/tmp/example" tendermint init validator I[2019-07-16|18:20:36.480] Generated private validator module=main keyFile=/tmp/example/config/priv_validator_key.json stateFile=/tmp/example2/data/priv_validator_state.json I[2019-07-16|18:20:36.481] Generated node key module=main path=/tmp/example/config/node_key.json I[2019-07-16|18:20:36.482] Generated genesis file module=main path=/tmp/example/config/genesis.json +I[2019-07-16|18:20:36.483] Generated config module=main mode=validator ``` Feel free to explore the generated files, which can be found at diff --git a/docs/tutorials/java.md b/docs/tutorials/java.md index f27ba1a9f..c36cafcf0 100644 --- a/docs/tutorials/java.md +++ b/docs/tutorials/java.md @@ -550,11 +550,12 @@ Tendermint Core. $ rm -rf /tmp/example $ cd $GOPATH/src/github.com/tendermint/tendermint $ make install -$ TMHOME="/tmp/example" tendermint init +$ TMHOME="/tmp/example" tendermint init validator I[2019-07-16|18:20:36.480] Generated private validator module=main keyFile=/tmp/example/config/priv_validator_key.json stateFile=/tmp/example2/data/priv_validator_state.json I[2019-07-16|18:20:36.481] Generated node key module=main path=/tmp/example/config/node_key.json I[2019-07-16|18:20:36.482] Generated genesis file module=main path=/tmp/example/config/genesis.json +I[2019-07-16|18:20:36.483] Generated config module=main mode=validator ``` Feel free to explore the generated files, which can be found at diff --git a/docs/tutorials/kotlin.md b/docs/tutorials/kotlin.md index a46053427..6fa1d1894 100644 --- a/docs/tutorials/kotlin.md +++ b/docs/tutorials/kotlin.md @@ -517,18 +517,19 @@ class GrpcServer( ## 1.5 Getting Up and Running To create a default configuration, nodeKey and private validator files, let's -execute `tendermint init`. But before we do that, we will need to install +execute `tendermint init validator`. But before we do that, we will need to install Tendermint Core. ```bash rm -rf /tmp/example cd $GOPATH/src/github.com/tendermint/tendermint make install -TMHOME="/tmp/example" tendermint init +TMHOME="/tmp/example" tendermint init validator I[2019-07-16|18:20:36.480] Generated private validator module=main keyFile=/tmp/example/config/priv_validator_key.json stateFile=/tmp/example2/data/priv_validator_state.json I[2019-07-16|18:20:36.481] Generated node key module=main path=/tmp/example/config/node_key.json I[2019-07-16|18:20:36.482] Generated genesis file module=main path=/tmp/example/config/genesis.json +I[2019-07-16|18:20:36.482] Generated config module=main mode=validator ``` Feel free to explore the generated files, which can be found at diff --git a/test/app/test.sh b/test/app/test.sh index d415bc10e..67fb2d9b6 100755 --- a/test/app/test.sh +++ b/test/app/test.sh @@ -13,7 +13,7 @@ export TMHOME=$HOME/.tendermint_app function kvstore_over_socket(){ rm -rf $TMHOME - tendermint init + tendermint init validator echo "Starting kvstore_over_socket" abci-cli kvstore > /dev/null & pid_kvstore=$! @@ -30,7 +30,7 @@ function kvstore_over_socket(){ # start tendermint first function kvstore_over_socket_reorder(){ rm -rf $TMHOME - tendermint init + tendermint init validator echo "Starting kvstore_over_socket_reorder (ie. start tendermint first)" tendermint start --mode validator > tendermint.log & pid_tendermint=$! @@ -48,7 +48,7 @@ function kvstore_over_socket_reorder(){ function counter_over_socket() { rm -rf $TMHOME - tendermint init + tendermint init validator echo "Starting counter_over_socket" abci-cli counter --serial > /dev/null & pid_counter=$! @@ -64,7 +64,7 @@ function counter_over_socket() { function counter_over_grpc() { rm -rf $TMHOME - tendermint init + tendermint init validator echo "Starting counter_over_grpc" abci-cli counter --serial --abci grpc > /dev/null & pid_counter=$! @@ -80,7 +80,7 @@ function counter_over_grpc() { function counter_over_grpc_grpc() { rm -rf $TMHOME - tendermint init + tendermint init validator echo "Starting counter_over_grpc_grpc (ie. with grpc broadcast_tx)" abci-cli counter --serial --abci grpc > /dev/null & pid_counter=$! diff --git a/test/e2e/runner/setup.go b/test/e2e/runner/setup.go index 22ff58b15..b2dbfe5a9 100644 --- a/test/e2e/runner/setup.go +++ b/test/e2e/runner/setup.go @@ -85,7 +85,7 @@ func Setup(testnet *e2e.Testnet) error { if err != nil { return err } - config.WriteConfigFile(filepath.Join(nodeDir, "config", "config.toml"), cfg) // panics + config.WriteConfigFile(nodeDir, cfg) // panics appCfg, err := MakeAppConfig(node) if err != nil {