node: remove mode defaults. Make node mode explicit (#6282)

This commit is contained in:
Callum Waters
2021-04-02 09:31:25 +02:00
committed by GitHub
parent f2f085c7a3
commit 358d1a28b8
23 changed files with 120 additions and 90 deletions

1
.gitignore vendored
View File

@@ -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

View File

@@ -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

View File

@@ -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\"/" \

View File

@@ -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`:
```

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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"

View File

@@ -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)

View File

@@ -63,7 +63,7 @@ Tendermint binary installed. If not, follow the steps from
before, use:
```sh
tendermint init
tendermint init validator
tendermint start
```

View File

@@ -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.

View File

@@ -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
- <span v-pre>`mode = "{{ .BaseConfig.Mode }}"`</span> 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

View File

@@ -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
```

View File

@@ -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.

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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=$!

View File

@@ -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 {