diff --git a/config.go b/config.go index 698329fd80..b46d13303d 100644 --- a/config.go +++ b/config.go @@ -292,6 +292,19 @@ var ( defaultPrunedNodeMaxPeers = 4 ) +// GeneralizedConfig is an interface that defines the functions a config struct +// must support to be passable in the generalizedConfigLoader function. +type GeneralizedConfig interface { + // GetShowVersion returns the current value for the ShowVersion field + GetShowVersion() bool + + // GetLndDir returns the current value for the LndDir field + GetLndDir() string + + // GetConfigFile returns the current value for the ConfigFile field + GetConfigFile() string +} + // Config defines the configuration options for lnd. // // See LoadConfig for further details regarding the configuration @@ -525,6 +538,21 @@ type Config struct { HTTPHeaderTimeout time.Duration `long:"http-header-timeout" description:"The maximum duration that the server will wait before timing out reading the headers of an HTTP request."` } +// GetShowVersion returns the current value for the ShowVersion field. +func (c Config) GetShowVersion() bool { + return c.ShowVersion +} + +// GetLndDir returns the current value for the LndDir field. +func (c Config) GetLndDir() string { + return c.LndDir +} + +// GetConfigFile returns the current value for the ConfigFile field. +func (c Config) GetConfigFile() string { + return c.ConfigFile +} + // GRPCConfig holds the configuration options for the gRPC server. // See https://github.com/grpc/grpc-go/blob/v1.41.0/keepalive/keepalive.go#L50 // for more details. Any value of 0 means we use the gRPC internal default @@ -748,6 +776,10 @@ func DefaultConfig() Config { } } +// A compile time assertion to ensure Config meets the GeneralizedConfig +// interface. +var _ GeneralizedConfig = (*Config)(nil) + // SignerConfig defines the configuration options for lndsigner. // // Note! Any new fields added to this struct MUST also be applied to the merged @@ -791,6 +823,21 @@ type SignerConfig struct { RequestTimeout time.Duration `long:"requesttimeout" description:"The time we will wait when making requests to the watch-only node. Valid time units are {s, m, h}."` } +// GetShowVersion returns the current value for the ShowVersion field. +func (s SignerConfig) GetShowVersion() bool { + return s.ShowVersion +} + +// GetLndDir returns the current value for the LndDir field. +func (s SignerConfig) GetLndDir() string { + return s.LndDir +} + +// GetConfigFile returns the current value for the ConfigFile field. +func (s SignerConfig) GetConfigFile() string { + return s.ConfigFile +} + // DefaultSignerConfig returns all default values for the SignerConfig struct. func DefaultSignerConfig() SignerConfig { return SignerConfig{ @@ -812,6 +859,10 @@ func DefaultSignerConfig() SignerConfig { } } +// A compile time assertion to ensure SignerConfig meets the GeneralizedConfig +// interface. +var _ GeneralizedConfig = (*SignerConfig)(nil) + // LoadConfig initializes and parses the config using a config file and command // line options. // @@ -828,24 +879,12 @@ func LoadConfig(interceptor signal.Interceptor) (*Config, error) { return cfg, nil } - getShowVersion := func(cfg *Config) bool { - return cfg.ShowVersion - } - - getLndDir := func(cfg *Config) string { - return cfg.LndDir - } - - getConfigPath := func(cfg *Config) string { - return cfg.ConfigFile - } - preCfg := DefaultConfig() // Load and validate the config. cfg, err := generalizedConfigLoader( - interceptor, preCfg, mergeConf, getShowVersion, getLndDir, - getConfigPath, DefaultConfigFile, lncfg.DefaultConfigFilename, + interceptor, preCfg, mergeConf, DefaultConfigFile, + lncfg.DefaultConfigFilename, ) return cfg, err @@ -921,26 +960,13 @@ func LoadSignerConfig(interceptor signal.Interceptor) (*Config, error) { return &cfg, nil } - getShowVersion := func(signerCfg *SignerConfig) bool { - return signerCfg.ShowVersion - } - - getLndDir := func(signerCfg *SignerConfig) string { - return signerCfg.LndDir - } - - getConfigPath := func(signerCfg *SignerConfig) string { - return signerCfg.ConfigFile - } - // We use the SignerConfig, as the lndsigner should have more limited // config options for an easier UX. preCfg := DefaultSignerConfig() // Load and validate the config. cfg, err := generalizedConfigLoader( - interceptor, preCfg, mergeConf, getShowVersion, getLndDir, - getConfigPath, DefaultSignerConfigFile, + interceptor, preCfg, mergeConf, DefaultSignerConfigFile, lncfg.DefaultSignerConfigFilename, ) if err != nil { @@ -960,10 +986,9 @@ func LoadSignerConfig(interceptor signal.Interceptor) (*Config, error) { return cfg, err } -func generalizedConfigLoader[R interface{}](interceptor signal.Interceptor, - preCfg R, mergeConfig func(cfg *R) (*Config, error), - getShowVersion func(cfg *R) bool, - getLndDir, getConfigPath func(cfg *R) string, defaultConfigPath, +func generalizedConfigLoader[R GeneralizedConfig]( + interceptor signal.Interceptor, preCfg R, + mergeConfig func(cfg *R) (*Config, error), defaultConfigPath, defaultConfigFileName string) (*Config, error) { // Pre-parse the command line options to pick up an alternative config @@ -976,7 +1001,7 @@ func generalizedConfigLoader[R interface{}](interceptor signal.Interceptor, appName := filepath.Base(os.Args[0]) appName = strings.TrimSuffix(appName, filepath.Ext(appName)) usageMessage := fmt.Sprintf("Use %s -h to show usage", appName) - if getShowVersion(&preCfg) { + if preCfg.GetShowVersion() { fmt.Println(appName, "version", build.Version(), "commit="+build.Commit) os.Exit(0) @@ -986,8 +1011,8 @@ func generalizedConfigLoader[R interface{}](interceptor signal.Interceptor, // use the default config file path. However, if the user has modified // their lnddir, then we should assume they intend to use the config // file within it. - configFileDir := CleanAndExpandPath(getLndDir(&preCfg)) - configFilePath := CleanAndExpandPath(getConfigPath(&preCfg)) + configFileDir := CleanAndExpandPath(preCfg.GetLndDir()) + configFilePath := CleanAndExpandPath(preCfg.GetConfigFile()) switch { // User specified --lnddir but no --configfile. Update the config file // path to the lnd config directory, but don't require it to exist.