diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 3c1aa8213..992a05d36 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -19,6 +19,7 @@ Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermi - [state/indexer] \#6382 reconstruct indexer, move txindex into the indexer package (@JayT106) - [cli] \#6372 Introduce `BootstrapPeers` as part of the new p2p stack. Peers to be connected on startup (@cmwaters) + - [config] \#6462 Move `PrivValidator` configuration out of `BaseConfig` into its own section. - Apps - [ABCI] \#6408 Change the `key` and `value` fields from `[]byte` to `string` in the `EventAttribute` type. (@alexanderbez) diff --git a/UPGRADING.md b/UPGRADING.md index 247847085..61c2ca528 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -26,6 +26,9 @@ This guide provides instructions for upgrading to specific versions of Tendermin `Seeds`. Bootstrap peers are connected with on startup if needed for peer discovery. Unlike persistent peers, there's no gaurantee that the node will remain connected with these peers. +- configuration values starting with `priv-validator-` have moved to the new + `priv-validator` section, without the `priv-validator-` prefix. + ### CLI Changes * You must now specify the node mode (validator|full|seed) in `tendermint init [mode]` diff --git a/cmd/tendermint/commands/run_node.go b/cmd/tendermint/commands/run_node.go index 42c2075fb..1a2ea7f0d 100644 --- a/cmd/tendermint/commands/run_node.go +++ b/cmd/tendermint/commands/run_node.go @@ -30,7 +30,7 @@ func AddNodeFlags(cmd *cobra.Command) { // priv val flags cmd.Flags().String( "priv-validator-laddr", - config.PrivValidatorListenAddr, + config.PrivValidator.ListenAddr, "socket address to listen on for connections from external priv-validator process") // node flags diff --git a/cmd/tendermint/commands/show_validator.go b/cmd/tendermint/commands/show_validator.go index 59cc5bbfc..2bdca9b8e 100644 --- a/cmd/tendermint/commands/show_validator.go +++ b/cmd/tendermint/commands/show_validator.go @@ -30,7 +30,7 @@ func showValidator(cmd *cobra.Command, args []string) error { ) //TODO: remove once gRPC is the only supported protocol - protocol, _ := tmnet.ProtocolAndAddress(config.PrivValidatorListenAddr) + protocol, _ := tmnet.ProtocolAndAddress(config.PrivValidator.ListenAddr) switch protocol { case "grpc": pvsc, err := tmgrpc.DialRemoteSigner(config, config.ChainID(), logger) diff --git a/cmd/tendermint/commands/testnet.go b/cmd/tendermint/commands/testnet.go index 5d225413f..0090ec0a6 100644 --- a/cmd/tendermint/commands/testnet.go +++ b/cmd/tendermint/commands/testnet.go @@ -144,8 +144,8 @@ func testnetFiles(cmd *cobra.Command, args []string) error { return err } - pvKeyFile := filepath.Join(nodeDir, config.BaseConfig.PrivValidatorKey) - pvStateFile := filepath.Join(nodeDir, config.BaseConfig.PrivValidatorState) + pvKeyFile := filepath.Join(nodeDir, config.PrivValidator.Key) + pvStateFile := filepath.Join(nodeDir, config.PrivValidator.State) pv, err := privval.LoadFilePV(pvKeyFile, pvStateFile) if err != nil { return err diff --git a/config/config.go b/config/config.go index 94a99f38f..a87558249 100644 --- a/config/config.go +++ b/config/config.go @@ -76,6 +76,7 @@ type Config struct { Consensus *ConsensusConfig `mapstructure:"consensus"` TxIndex *TxIndexConfig `mapstructure:"tx-index"` Instrumentation *InstrumentationConfig `mapstructure:"instrumentation"` + PrivValidator *PrivValidatorConfig `mapstructure:"priv-validator"` } // DefaultConfig returns a default configuration for a Tendermint node @@ -90,6 +91,7 @@ func DefaultConfig() *Config { Consensus: DefaultConsensusConfig(), TxIndex: DefaultTxIndexConfig(), Instrumentation: DefaultInstrumentationConfig(), + PrivValidator: DefaultPrivValidatorConfig(), } } @@ -112,6 +114,7 @@ func TestConfig() *Config { Consensus: TestConsensusConfig(), TxIndex: TestTxIndexConfig(), Instrumentation: TestInstrumentationConfig(), + PrivValidator: DefaultPrivValidatorConfig(), } } @@ -125,6 +128,31 @@ func (cfg *Config) SetRoot(root string) *Config { return cfg } +// PrivValidatorClientKeyFile returns the full path to the priv_validator_key.json file +func (cfg Config) PrivValidatorClientKeyFile() string { + return rootify(cfg.PrivValidator.ClientKey, cfg.RootDir) +} + +// PrivValidatorClientCertificateFile returns the full path to the priv_validator_key.json file +func (cfg Config) PrivValidatorClientCertificateFile() string { + return rootify(cfg.PrivValidator.ClientCertificate, cfg.RootDir) +} + +// PrivValidatorCertificateAuthorityFile returns the full path to the priv_validator_key.json file +func (cfg Config) PrivValidatorRootCAFile() string { + return rootify(cfg.PrivValidator.RootCA, cfg.RootDir) +} + +// PrivValidatorKeyFile returns the full path to the priv_validator_key.json file +func (cfg Config) PrivValidatorKeyFile() string { + return rootify(cfg.PrivValidator.Key, cfg.RootDir) +} + +// PrivValidatorFile returns the full path to the priv_validator_state.json file +func (cfg Config) PrivValidatorStateFile() string { + return rootify(cfg.PrivValidator.State, cfg.RootDir) +} + // ValidateBasic performs basic validation (checking param bounds, etc.) and // returns an error if any check fails. func (cfg *Config) ValidateBasic() error { @@ -224,26 +252,6 @@ type BaseConfig struct { //nolint: maligned // Path to the JSON file containing the initial validator set and other meta data Genesis string `mapstructure:"genesis-file"` - // Path to the JSON file containing the private key to use as a validator in the consensus protocol - PrivValidatorKey string `mapstructure:"priv-validator-key-file"` - - // Path to the JSON file containing the last sign state of a validator - PrivValidatorState string `mapstructure:"priv-validator-state-file"` - - // TCP or UNIX socket address for Tendermint to listen on for - // connections from an external PrivValidator process - PrivValidatorListenAddr string `mapstructure:"priv-validator-laddr"` - - // Client certificate generated while creating needed files for secure connection. - // If a remote validator address is provided but no certificate, the connection will be insecure - PrivValidatorClientCertificate string `mapstructure:"priv-validator-client-certificate-file"` - - // Client key generated while creating certificates for secure connection - PrivValidatorClientKey string `mapstructure:"priv-validator-client-key-file"` - - // Path Root Certificate Authority used to sign both client and server certificates - PrivValidatorRootCA string `mapstructure:"priv-validator-root-ca-file"` - // A JSON file containing the private key to use for p2p authenticated encryption NodeKey string `mapstructure:"node-key-file"` @@ -258,20 +266,18 @@ type BaseConfig struct { //nolint: maligned // DefaultBaseConfig returns a default base configuration for a Tendermint node func DefaultBaseConfig() BaseConfig { return BaseConfig{ - Genesis: defaultGenesisJSONPath, - PrivValidatorKey: defaultPrivValKeyPath, - PrivValidatorState: defaultPrivValStatePath, - NodeKey: defaultNodeKeyPath, - Mode: defaultMode, - Moniker: defaultMoniker, - ProxyApp: "tcp://127.0.0.1:26658", - ABCI: "socket", - LogLevel: DefaultLogLevel, - LogFormat: LogFormatPlain, - FastSyncMode: true, - FilterPeers: false, - DBBackend: "goleveldb", - DBPath: "data", + Genesis: defaultGenesisJSONPath, + NodeKey: defaultNodeKeyPath, + Mode: defaultMode, + Moniker: defaultMoniker, + ProxyApp: "tcp://127.0.0.1:26658", + ABCI: "socket", + LogLevel: DefaultLogLevel, + LogFormat: LogFormatPlain, + FastSyncMode: true, + FilterPeers: false, + DBBackend: "goleveldb", + DBPath: "data", } } @@ -295,31 +301,6 @@ func (cfg BaseConfig) GenesisFile() string { return rootify(cfg.Genesis, cfg.RootDir) } -// PrivValidatorClientKeyFile returns the full path to the priv_validator_key.json file -func (cfg BaseConfig) PrivValidatorClientKeyFile() string { - return rootify(cfg.PrivValidatorClientKey, cfg.RootDir) -} - -// PrivValidatorClientCertificateFile returns the full path to the priv_validator_key.json file -func (cfg BaseConfig) PrivValidatorClientCertificateFile() string { - return rootify(cfg.PrivValidatorClientCertificate, cfg.RootDir) -} - -// PrivValidatorCertificateAuthorityFile returns the full path to the priv_validator_key.json file -func (cfg BaseConfig) PrivValidatorRootCAFile() string { - return rootify(cfg.PrivValidatorRootCA, cfg.RootDir) -} - -// PrivValidatorKeyFile returns the full path to the priv_validator_key.json file -func (cfg BaseConfig) PrivValidatorKeyFile() string { - return rootify(cfg.PrivValidatorKey, cfg.RootDir) -} - -// PrivValidatorFile returns the full path to the priv_validator_state.json file -func (cfg BaseConfig) PrivValidatorStateFile() string { - return rootify(cfg.PrivValidatorState, cfg.RootDir) -} - // NodeKeyFile returns the full path to the node_key.json file func (cfg BaseConfig) NodeKeyFile() string { return rootify(cfg.NodeKey, cfg.RootDir) @@ -330,13 +311,13 @@ func (cfg BaseConfig) DBDir() string { return rootify(cfg.DBPath, cfg.RootDir) } -func (cfg *BaseConfig) ArePrivValidatorClientSecurityOptionsPresent() bool { +func (cfg Config) ArePrivValidatorClientSecurityOptionsPresent() bool { switch { - case cfg.PrivValidatorRootCA == "": + case cfg.PrivValidator.RootCA == "": return false - case cfg.PrivValidatorClientKey == "": + case cfg.PrivValidator.ClientKey == "": return false - case cfg.PrivValidatorClientCertificate == "": + case cfg.PrivValidator.ClientCertificate == "": return false default: return true @@ -361,6 +342,41 @@ func (cfg BaseConfig) ValidateBasic() error { return nil } +//----------------------------------------------------------------------------- +// PrivValidatorConfig + +// PrivValidatorConfig defines the configuration parameters for running a validator +type PrivValidatorConfig struct { + // Path to the JSON file containing the private key to use as a validator in the consensus protocol + Key string `mapstructure:"key-file"` + + // Path to the JSON file containing the last sign state of a validator + State string `mapstructure:"state-file"` + + // TCP or UNIX socket address for Tendermint to listen on for + // connections from an external PrivValidator process + ListenAddr string `mapstructure:"laddr"` + + // Client certificate generated while creating needed files for secure connection. + // If a remote validator address is provided but no certificate, the connection will be insecure + ClientCertificate string `mapstructure:"client-certificate-file"` + + // Client key generated while creating certificates for secure connection + ClientKey string `mapstructure:"client-key-file"` + + // Path Root Certificate Authority used to sign both client and server certificates + RootCA string `mapstructure:"root-ca-file"` +} + +// DefaultBaseConfig returns a default private validator configuration +// for a Tendermint node. +func DefaultPrivValidatorConfig() *PrivValidatorConfig { + return &PrivValidatorConfig{ + Key: defaultPrivValKeyPath, + State: defaultPrivValStatePath, + } +} + //----------------------------------------------------------------------------- // RPCConfig diff --git a/config/toml.go b/config/toml.go index f33f48444..768f1c5ef 100644 --- a/config/toml.go +++ b/config/toml.go @@ -137,36 +137,43 @@ log-format = "{{ .BaseConfig.LogFormat }}" # Path to the JSON file containing the initial validator set and other meta data genesis-file = "{{ js .BaseConfig.Genesis }}" +# Path to the JSON file containing the private key to use for node authentication in the p2p protocol +node-key-file = "{{ js .BaseConfig.NodeKey }}" + +# Mechanism to connect to the ABCI application: socket | grpc +abci = "{{ .BaseConfig.ABCI }}" + +# If true, query the ABCI app on connecting to a new peer +# so the app can decide if we should keep the connection or not +filter-peers = {{ .BaseConfig.FilterPeers }} + + +####################################################### +### Priv Validator Configuration ### +####################################################### +[priv-validator] + # Path to the JSON file containing the private key to use as a validator in the consensus protocol -priv-validator-key-file = "{{ js .BaseConfig.PrivValidatorKey }}" +key-file = "{{ js .PrivValidator.Key }}" # Path to the JSON file containing the last sign state of a validator -priv-validator-state-file = "{{ js .BaseConfig.PrivValidatorState }}" +state-file = "{{ js .PrivValidator.State }}" # TCP or UNIX socket address for Tendermint to listen on for # connections from an external PrivValidator process # when the listenAddr is prefixed with grpc instead of tcp it will use the gRPC Client -priv-validator-laddr = "{{ .BaseConfig.PrivValidatorListenAddr }}" +laddr = "{{ .PrivValidator.ListenAddr }}" # Client certificate generated while creating needed files for secure connection. # If a remote validator address is provided but no certificate, the connection will be insecure -priv-validator-client-certificate-file = "{{ js .BaseConfig.PrivValidatorClientCertificate }}" +client-certificate-file = "{{ js .PrivValidator.ClientCertificate }}" # Client key generated while creating certificates for secure connection -priv-validator-client-key-file = "{{ js .BaseConfig.PrivValidatorClientKey }}" +validator-client-key-file = "{{ js .PrivValidator.ClientKey }}" # Path Root Certificate Authority used to sign both client and server certificates -priv-validator-certificate-authority = "{{ js .BaseConfig.PrivValidatorRootCA }}" - -# Path to the JSON file containing the private key to use for node authentication in the p2p protocol -node-key-file = "{{ js .BaseConfig.NodeKey }}" +certificate-authority = "{{ js .PrivValidator.RootCA }}" -# Mechanism to connect to the ABCI application: socket | grpc -abci = "{{ .BaseConfig.ABCI }}" - -# If true, query the ABCI app on connecting to a new peer -# so the app can decide if we should keep the connection or not -filter-peers = {{ .BaseConfig.FilterPeers }} ####################################################################### ### Advanced Configuration Options ### @@ -529,10 +536,10 @@ func ResetTestRootWithChainID(testName string, chainID string) *Config { panic(err) } - baseConfig := DefaultBaseConfig() - genesisFilePath := filepath.Join(rootDir, baseConfig.Genesis) - privKeyFilePath := filepath.Join(rootDir, baseConfig.PrivValidatorKey) - privStateFilePath := filepath.Join(rootDir, baseConfig.PrivValidatorState) + conf := DefaultConfig() + genesisFilePath := filepath.Join(rootDir, conf.Genesis) + privKeyFilePath := filepath.Join(rootDir, conf.PrivValidator.Key) + privStateFilePath := filepath.Join(rootDir, conf.PrivValidator.State) // Write default config file if missing. writeDefaultConfigFileIfNone(rootDir) diff --git a/config/toml_test.go b/config/toml_test.go index 950d218ec..418cea8fa 100644 --- a/config/toml_test.go +++ b/config/toml_test.go @@ -63,7 +63,8 @@ func TestEnsureTestRoot(t *testing.T) { // TODO: make sure the cfg returned and testconfig are the same! baseConfig := DefaultBaseConfig() - ensureFiles(t, rootDir, defaultDataDir, baseConfig.Genesis, baseConfig.PrivValidatorKey, baseConfig.PrivValidatorState) + pvConfig := DefaultPrivValidatorConfig() + ensureFiles(t, rootDir, defaultDataDir, baseConfig.Genesis, pvConfig.Key, pvConfig.State) } func checkConfig(configFile string) bool { diff --git a/node/node.go b/node/node.go index ae034d431..8e152e8a1 100644 --- a/node/node.go +++ b/node/node.go @@ -173,8 +173,8 @@ func NewNode(config *cfg.Config, // If an address is provided, listen on the socket for a connection from an // external signing process. - if config.PrivValidatorListenAddr != "" { - protocol, _ := tmnet.ProtocolAndAddress(config.PrivValidatorListenAddr) + if config.PrivValidator.ListenAddr != "" { + protocol, _ := tmnet.ProtocolAndAddress(config.PrivValidator.ListenAddr) // FIXME: we should start services inside OnStart switch protocol { case "grpc": @@ -183,7 +183,7 @@ func NewNode(config *cfg.Config, return nil, fmt.Errorf("error with private validator grpc client: %w", err) } default: - privValidator, err = createAndStartPrivValidatorSocketClient(config.PrivValidatorListenAddr, genDoc.ChainID, logger) + privValidator, err = createAndStartPrivValidatorSocketClient(config.PrivValidator.ListenAddr, genDoc.ChainID, logger) if err != nil { return nil, fmt.Errorf("error with private validator socket client: %w", err) } diff --git a/node/node_test.go b/node/node_test.go index 0c6d01af2..81e3c11e4 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -122,7 +122,7 @@ func TestNodeSetPrivValTCP(t *testing.T) { config := cfg.ResetTestRoot("node_priv_val_tcp_test") defer os.RemoveAll(config.RootDir) - config.BaseConfig.PrivValidatorListenAddr = addr + config.PrivValidator.ListenAddr = addr dialer := privval.DialTCPFn(addr, 100*time.Millisecond, ed25519.GenPrivKey()) dialerEndpoint := privval.NewSignerDialerEndpoint( @@ -156,7 +156,7 @@ func TestPrivValidatorListenAddrNoProtocol(t *testing.T) { config := cfg.ResetTestRoot("node_priv_val_tcp_test") defer os.RemoveAll(config.RootDir) - config.BaseConfig.PrivValidatorListenAddr = addrNoPrefix + config.PrivValidator.ListenAddr = addrNoPrefix _, err := DefaultNewNode(config, log.TestingLogger()) assert.Error(t, err) @@ -168,7 +168,7 @@ func TestNodeSetPrivValIPC(t *testing.T) { config := cfg.ResetTestRoot("node_priv_val_tcp_test") defer os.RemoveAll(config.RootDir) - config.BaseConfig.PrivValidatorListenAddr = "unix://" + tmpfile + config.PrivValidator.ListenAddr = "unix://" + tmpfile dialer := privval.DialUnixFn(tmpfile) dialerEndpoint := privval.NewSignerDialerEndpoint( diff --git a/privval/grpc/util.go b/privval/grpc/util.go index a70ab54bf..916d7b689 100644 --- a/privval/grpc/util.go +++ b/privval/grpc/util.go @@ -93,7 +93,7 @@ func DialRemoteSigner( logger log.Logger, ) (*SignerClient, error) { var transportSecurity grpc.DialOption - if config.BaseConfig.ArePrivValidatorClientSecurityOptionsPresent() { + if config.ArePrivValidatorClientSecurityOptionsPresent() { transportSecurity = GenerateTLS(config.PrivValidatorClientCertificateFile(), config.PrivValidatorClientKeyFile(), config.PrivValidatorRootCAFile(), logger) } else { @@ -110,7 +110,7 @@ func DialRemoteSigner( dialOptions = append(dialOptions, transportSecurity) ctx := context.Background() - _, address := tmnet.ProtocolAndAddress(config.PrivValidatorListenAddr) + _, address := tmnet.ProtocolAndAddress(config.PrivValidator.ListenAddr) conn, err := grpc.DialContext(ctx, address, dialOptions...) if err != nil { logger.Error("unable to connect to server", "target", address, "err", err) diff --git a/test/e2e/runner/setup.go b/test/e2e/runner/setup.go index 372d13360..545f57958 100644 --- a/test/e2e/runner/setup.go +++ b/test/e2e/runner/setup.go @@ -266,22 +266,22 @@ func MakeConfig(node *e2e.Node) (*config.Config, error) { // it's actually needed (e.g. for remote KMS or non-validators). We set up a dummy // key here by default, and use the real key for actual validators that should use // the file privval. - cfg.PrivValidatorListenAddr = "" - cfg.PrivValidatorKey = PrivvalDummyKeyFile - cfg.PrivValidatorState = PrivvalDummyStateFile + cfg.PrivValidator.ListenAddr = "" + cfg.PrivValidator.Key = PrivvalDummyKeyFile + cfg.PrivValidator.State = PrivvalDummyStateFile switch node.Mode { case e2e.ModeValidator: switch node.PrivvalProtocol { case e2e.ProtocolFile: - cfg.PrivValidatorKey = PrivvalKeyFile - cfg.PrivValidatorState = PrivvalStateFile + cfg.PrivValidator.Key = PrivvalKeyFile + cfg.PrivValidator.State = PrivvalStateFile case e2e.ProtocolUNIX: - cfg.PrivValidatorListenAddr = PrivvalAddressUNIX + cfg.PrivValidator.ListenAddr = PrivvalAddressUNIX case e2e.ProtocolTCP: - cfg.PrivValidatorListenAddr = PrivvalAddressTCP + cfg.PrivValidator.ListenAddr = PrivvalAddressTCP case e2e.ProtocolGRPC: - cfg.PrivValidatorListenAddr = PrivvalAddressGRPC + cfg.PrivValidator.ListenAddr = PrivvalAddressGRPC default: return nil, fmt.Errorf("invalid privval protocol setting %q", node.PrivvalProtocol) }