diff --git a/config/config.go b/config/config.go index 91c780402..a178e5c36 100644 --- a/config/config.go +++ b/config/config.go @@ -134,29 +134,36 @@ func (cfg *Config) SetRoot(root string) *Config { // ValidateBasic performs basic validation (checking param bounds, etc.) and // returns an error if any check fails. func (cfg *Config) ValidateBasic() error { + var errs error - if err := cfg.Abci.ValidateBasic(); err != nil { - return fmt.Errorf("error in [abci] section: %w", err) - } if err := cfg.BaseConfig.ValidateBasic(); err != nil { - return err + errs = multierror.Append(errs, err) + } + + // ignore [abci] section on seed nodes + if cfg.Mode != ModeSeed { + if err := cfg.Abci.ValidateBasic(); err != nil { + errs = multierror.Append(errs, fmt.Errorf("error in [abci] section: %w", err)) + } } + if err := cfg.RPC.ValidateBasic(); err != nil { - return fmt.Errorf("error in [rpc] section: %w", err) + errs = multierror.Append(errs, fmt.Errorf("error in [rpc] section: %w", err)) } if err := cfg.Mempool.ValidateBasic(); err != nil { - return fmt.Errorf("error in [mempool] section: %w", err) + errs = multierror.Append(errs, fmt.Errorf("error in [mempool] section: %w", err)) } if err := cfg.StateSync.ValidateBasic(); err != nil { - return fmt.Errorf("error in [statesync] section: %w", err) + errs = multierror.Append(errs, fmt.Errorf("error in [statesync] section: %w", err)) } if err := cfg.Consensus.ValidateBasic(); err != nil { - return fmt.Errorf("error in [consensus] section: %w", err) + errs = multierror.Append(errs, fmt.Errorf("error in [consensus] section: %w", err)) } if err := cfg.Instrumentation.ValidateBasic(); err != nil { - return fmt.Errorf("error in [instrumentation] section: %w", err) + errs = multierror.Append(errs, fmt.Errorf("error in [instrumentation] section: %w", err)) } - return nil + + return errs } func (cfg *Config) DeprecatedFieldWarning() error { @@ -466,6 +473,11 @@ func TestAbciConfig() *AbciConfig { func (cfg *AbciConfig) ValidateBasic() error { var err error + if cfg == nil { + err = multierror.Append(err, errors.New("[abci] config section is nil")) + return err + } + for key := range cfg.Other { err = multierror.Append(err, fmt.Errorf("unknown field: %s", key)) } diff --git a/config/config_test.go b/config/config_test.go index a86ab8463..5833f00e1 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -34,6 +34,65 @@ func TestConfigValidateBasic(t *testing.T) { assert.Error(t, cfg.ValidateBasic()) } +func TestAbciConfigValidation(t *testing.T) { + type testCase struct { + name string + *AbciConfig + expectErr string // empty when no error, or error message to expect + } + // negative test cases that should fail on validator, but pass on seeds + invalidCases := []testCase{ + { + name: "no abci config", + expectErr: "", + }, + { + name: "unexpected data", + AbciConfig: &AbciConfig{Other: map[string]interface{}{"foo": "bar"}}, + expectErr: "", + }, + { + name: "invalid transport", + AbciConfig: &AbciConfig{ + Transport: "invalid", + Address: "tcp://127.0.0.1:1234", + }, + expectErr: "", + }, + { + name: "missing address", + AbciConfig: &AbciConfig{ + Transport: "invalid", + Address: "", + }, + expectErr: "", + }, + } + + for _, tc := range invalidCases { + tc := tc + + t.Run(tc.name+" on validator", func(t *testing.T) { + cfg := DefaultConfig() + cfg.Mode = ModeValidator + cfg.Abci = nil + + err := cfg.ValidateBasic() + if tc.expectErr != "" { + assert.ErrorContains(t, err, tc.expectErr) + } + }) + t.Run(tc.name+" on seed", func(t *testing.T) { + cfg := DefaultConfig() + cfg.Mode = ModeSeed + cfg.Abci = nil + + err := cfg.ValidateBasic() + assert.NoError(t, err) + }) + } +} + func TestTLSConfiguration(t *testing.T) { cfg := DefaultConfig() cfg.SetRoot("/home/user")