github.com/decred/dcrlnd@v0.7.6/config.go (about)

     1  // Copyright (c) 2013-2017 The btcsuite developers
     2  // Copyright (c) 2015-2019 The Decred developers
     3  // Copyright (C) 2015-2020 The Lightning Network Developers
     4  
     5  package dcrlnd
     6  
     7  import (
     8  	"fmt"
     9  	"io/ioutil"
    10  	"net"
    11  	"os"
    12  	"os/user"
    13  	"path/filepath"
    14  	"reflect"
    15  	"regexp"
    16  	"runtime"
    17  	"strconv"
    18  	"strings"
    19  	"time"
    20  
    21  	"github.com/decred/dcrd/dcrutil/v4"
    22  	"github.com/decred/dcrd/wire"
    23  	"github.com/decred/dcrlnd/autopilot"
    24  	"github.com/decred/dcrlnd/build"
    25  	"github.com/decred/dcrlnd/chainreg"
    26  	"github.com/decred/dcrlnd/chanbackup"
    27  	"github.com/decred/dcrlnd/channeldb"
    28  	"github.com/decred/dcrlnd/discovery"
    29  	"github.com/decred/dcrlnd/funding"
    30  	"github.com/decred/dcrlnd/htlcswitch"
    31  	"github.com/decred/dcrlnd/htlcswitch/hodl"
    32  	"github.com/decred/dcrlnd/input"
    33  	"github.com/decred/dcrlnd/lncfg"
    34  	"github.com/decred/dcrlnd/lnrpc"
    35  	"github.com/decred/dcrlnd/lnrpc/routerrpc"
    36  	"github.com/decred/dcrlnd/lnrpc/signrpc"
    37  	"github.com/decred/dcrlnd/lnwallet"
    38  	"github.com/decred/dcrlnd/routing"
    39  	"github.com/decred/dcrlnd/signal"
    40  	"github.com/decred/dcrlnd/tor"
    41  	flags "github.com/jessevdk/go-flags"
    42  )
    43  
    44  const (
    45  	defaultDataDirname        = "data"
    46  	defaultChainSubDirname    = "chain"
    47  	defaultGraphSubDirname    = "graph"
    48  	defaultTowerSubDirname    = "watchtower"
    49  	defaultTLSCertFilename    = "tls.cert"
    50  	defaultTLSKeyFilename     = "tls.key"
    51  	defaultAdminMacFilename   = "admin.macaroon"
    52  	defaultReadMacFilename    = "readonly.macaroon"
    53  	defaultInvoiceMacFilename = "invoice.macaroon"
    54  	defaultLogLevel           = "info"
    55  	defaultLogDirname         = "logs"
    56  	defaultLogFilename        = "lnd.log"
    57  	defaultRPCPort            = 10009
    58  	defaultRESTPort           = 8080
    59  	defaultPeerPort           = 9735
    60  	defaultRPCHost            = "localhost"
    61  
    62  	defaultNoSeedBackup                  = false
    63  	defaultPaymentsExpirationGracePeriod = time.Duration(0)
    64  	defaultTrickleDelay                  = 90 * 1000
    65  	defaultChanStatusSampleInterval      = time.Minute
    66  	defaultChanEnableTimeout             = 19 * time.Minute
    67  	defaultChanDisableTimeout            = 20 * time.Minute
    68  	defaultHeightHintCacheQueryDisable   = false
    69  	defaultMaxLogFiles                   = 3
    70  	defaultMaxLogFileSize                = 10
    71  	defaultMinBackoff                    = time.Second
    72  	defaultMaxBackoff                    = time.Hour
    73  	defaultLetsEncryptDirname            = "letsencrypt"
    74  	defaultLetsEncryptListen             = ":80"
    75  
    76  	defaultTorSOCKSPort            = 9050
    77  	defaultTorDNSHost              = "soa.nodes.lightning.directory"
    78  	defaultTorDNSPort              = 53
    79  	defaultTorControlPort          = 9051
    80  	defaultTorV2PrivateKeyFilename = "v2_onion_private_key"
    81  	defaultTorV3PrivateKeyFilename = "v3_onion_private_key"
    82  
    83  	// DefaultAutogenValidity is the default validity of a self-signed
    84  	// certificate. The value corresponds to 14 months
    85  	// (14 months * 30 days * 24 hours).
    86  	defaultTLSCertDuration = 14 * 30 * 24 * time.Hour
    87  
    88  	// minTimeLockDelta is the minimum timelock we require for incoming
    89  	// HTLCs on our channels.
    90  	minTimeLockDelta = routing.MinCLTVDelta
    91  
    92  	// defaultAcceptorTimeout is the time after which an RPCAcceptor will time
    93  	// out and return false if it hasn't yet received a response.
    94  	defaultAcceptorTimeout = 15 * time.Second
    95  
    96  	defaultAlias = ""
    97  	defaultColor = "#3399FF"
    98  
    99  	// defaultCoopCloseTargetConfs is the default confirmation target
   100  	// that will be used to estimate a fee rate to use during a
   101  	// cooperative channel closure initiated by a remote peer. By default
   102  	// we'll set this to a lax value since we weren't the ones that
   103  	// initiated the channel closure.
   104  	defaultCoopCloseTargetConfs = 6
   105  
   106  	// defaultBlockCacheSize is the size (in bytes) of blocks that will be
   107  	// keep in memory if no size is specified.
   108  	defaultBlockCacheSize uint64 = 20 * 1024 * 1024 // 20 MB
   109  
   110  	// defaultHostSampleInterval is the default amount of time that the
   111  	// HostAnnouncer will wait between DNS resolutions to check if the
   112  	// backing IP of a host has changed.
   113  	defaultHostSampleInterval = time.Minute * 5
   114  
   115  	defaultChainInterval = time.Minute
   116  	defaultChainTimeout  = time.Second * 30
   117  	defaultChainBackoff  = time.Minute * 2
   118  	defaultChainAttempts = 3
   119  
   120  	// Set defaults for a health check which ensures that we have space
   121  	// available on disk. Although this check is off by default so that we
   122  	// avoid breaking any existing setups (particularly on mobile), we still
   123  	// set the other default values so that the health check can be easily
   124  	// enabled with sane defaults.
   125  	defaultRequiredDisk = 0.1
   126  	defaultDiskInterval = time.Hour * 12
   127  	defaultDiskTimeout  = time.Second * 5
   128  	defaultDiskBackoff  = time.Minute
   129  	defaultDiskAttempts = 0
   130  
   131  	// Set defaults for a health check which ensures that the TLS certificate
   132  	// is not expired. Although this check is off by default (not all setups
   133  	// require it), we still set the other default values so that the health
   134  	// check can be easily enabled with sane defaults.
   135  	defaultTLSInterval = time.Minute
   136  	defaultTLSTimeout  = time.Second * 5
   137  	defaultTLSBackoff  = time.Minute
   138  	defaultTLSAttempts = 0
   139  
   140  	// Set defaults for a health check which ensures that the tor
   141  	// connection is alive. Although this check is off by default (not all
   142  	// setups require it), we still set the other default values so that
   143  	// the health check can be easily enabled with sane defaults.
   144  	defaultTCInterval = time.Minute
   145  	defaultTCTimeout  = time.Second * 5
   146  	defaultTCBackoff  = time.Minute
   147  	defaultTCAttempts = 0
   148  
   149  	// defaultRemoteMaxHtlcs specifies the default limit for maximum
   150  	// concurrent HTLCs the remote party may add to commitment transactions.
   151  	// This value can be overridden with --default-remote-max-htlcs.
   152  	defaultRemoteMaxHtlcs = input.MaxHTLCNumber / 2
   153  
   154  	// defaultMaxLocalCSVDelay is the maximum delay we accept on our
   155  	// commitment output.
   156  	// TODO(halseth): find a more scientific choice of value.
   157  	defaultMaxLocalCSVDelay = 10000
   158  
   159  	// defaultChannelCommitInterval is the default maximum time between receiving a
   160  	// channel state update and signing a new commitment.
   161  	defaultChannelCommitInterval = 50 * time.Millisecond
   162  
   163  	// defaultChannelCommitBatchSize is the default maximum number of
   164  	// channel state updates that is accumulated before signing a new
   165  	// commitment.
   166  	defaultChannelCommitBatchSize = 10
   167  
   168  	// defaultCoinSelectionStrategy is the coin selection strategy that is
   169  	// used by default to fund transactions.
   170  	defaultCoinSelectionStrategy = "random"
   171  )
   172  
   173  var (
   174  	// DefaultLndDir is the default directory where lnd tries to find its
   175  	// configuration file and store its data. This is a directory in the
   176  	// user's application data, for example:
   177  	// C:\Users\<username>\AppData\Local\Lnd on Windows ~/.lnd on Linux
   178  	// ~/Library/Application Support/Lnd on MacOS
   179  	DefaultLndDir = dcrutil.AppDataDir("dcrlnd", false)
   180  
   181  	// DefaultConfigFile is the default full path of lnd's configuration
   182  	// file.
   183  	DefaultConfigFile = filepath.Join(DefaultLndDir, lncfg.DefaultConfigFilename)
   184  
   185  	defaultDataDir = filepath.Join(DefaultLndDir, defaultDataDirname)
   186  	defaultLogDir  = filepath.Join(DefaultLndDir, defaultLogDirname)
   187  
   188  	defaultTowerDir = filepath.Join(defaultDataDir, defaultTowerSubDirname)
   189  
   190  	defaultTLSCertPath    = filepath.Join(DefaultLndDir, defaultTLSCertFilename)
   191  	defaultTLSKeyPath     = filepath.Join(DefaultLndDir, defaultTLSKeyFilename)
   192  	defaultLetsEncryptDir = filepath.Join(DefaultLndDir, defaultLetsEncryptDirname)
   193  
   194  	defaultDcrdDir         = dcrutil.AppDataDir("dcrd", false)
   195  	defaultDcrdRPCCertFile = filepath.Join(defaultDcrdDir, "rpc.cert")
   196  
   197  	defaultTorSOCKS   = net.JoinHostPort("localhost", strconv.Itoa(defaultTorSOCKSPort))
   198  	defaultTorDNS     = net.JoinHostPort(defaultTorDNSHost, strconv.Itoa(defaultTorDNSPort))
   199  	defaultTorControl = net.JoinHostPort("localhost", strconv.Itoa(defaultTorControlPort))
   200  )
   201  
   202  // Config defines the configuration options for lnd.
   203  //
   204  // See LoadConfig for further details regarding the configuration
   205  // loading+parsing process.
   206  type Config struct {
   207  	ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
   208  
   209  	LndDir       string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."`
   210  	ConfigFile   string `short:"C" long:"configfile" description:"Path to configuration file"`
   211  	DataDir      string `short:"b" long:"datadir" description:"The directory to store lnd's data within"`
   212  	SyncFreelist bool   `long:"sync-freelist" description:"Whether the databases used within lnd should sync their freelist to disk. This is disabled by default resulting in improved memory performance during operation, but with an increase in startup time."`
   213  
   214  	TLSCertPath        string        `long:"tlscertpath" description:"Path to write the TLS certificate for lnd's RPC and REST services"`
   215  	TLSKeyPath         string        `long:"tlskeypath" description:"Path to write the TLS private key for lnd's RPC and REST services"`
   216  	TLSExtraIPs        []string      `long:"tlsextraip" description:"Adds an extra ip to the generated certificate"`
   217  	TLSExtraDomains    []string      `long:"tlsextradomain" description:"Adds an extra domain to the generated certificate"`
   218  	TLSAutoRefresh     bool          `long:"tlsautorefresh" description:"Re-generate TLS certificate and key if the IPs or domains are changed"`
   219  	TLSDisableAutofill bool          `long:"tlsdisableautofill" description:"Do not include the interface IPs or the system hostname in TLS certificate, use first --tlsextradomain as Common Name instead, if set"`
   220  	TLSCertDuration    time.Duration `long:"tlscertduration" description:"The duration for which the auto-generated TLS certificate will be valid for"`
   221  
   222  	NoMacaroons     bool          `long:"no-macaroons" description:"Disable macaroon authentication"`
   223  	AdminMacPath    string        `long:"adminmacaroonpath" description:"Path to write the admin macaroon for lnd's RPC and REST services if it doesn't exist"`
   224  	ReadMacPath     string        `long:"readonlymacaroonpath" description:"Path to write the read-only macaroon for lnd's RPC and REST services if it doesn't exist"`
   225  	InvoiceMacPath  string        `long:"invoicemacaroonpath" description:"Path to the invoice-only macaroon for lnd's RPC and REST services if it doesn't exist"`
   226  	LogDir          string        `long:"logdir" description:"Directory to log output."`
   227  	MaxLogFiles     int           `long:"maxlogfiles" description:"Maximum logfiles to keep (0 for no rotation)"`
   228  	MaxLogFileSize  int           `long:"maxlogfilesize" description:"Maximum logfile size in MB"`
   229  	AcceptorTimeout time.Duration `long:"acceptortimeout" description:"Time after which an RPCAcceptor will time out and return false if it hasn't yet received a response"`
   230  
   231  	// IPC options
   232  	PipeTx            *uint `long:"pipetx" description:"File descriptor or handle of write end pipe to enable child -> parent process communication"`
   233  	PipeRx            *uint `long:"piperx" description:"File descriptor or handle of read end pipe to enable parent -> child process communication"`
   234  	RPCListenerEvents bool  `long:"rpclistenerevents" description:"Notify JSON-RPC and gRPC listener addresses over the TX pipe"`
   235  
   236  	LetsEncryptDir    string `long:"letsencryptdir" description:"The directory to store Let's Encrypt certificates within"`
   237  	LetsEncryptListen string `long:"letsencryptlisten" description:"The IP:port on which lnd will listen for Let's Encrypt challenges. Let's Encrypt will always try to contact on port 80. Often non-root processes are not allowed to bind to ports lower than 1024. This configuration option allows a different port to be used, but must be used in combination with port forwarding from port 80. This configuration can also be used to specify another IP address to listen on, for example an IPv6 address."`
   238  	LetsEncryptDomain string `long:"letsencryptdomain" description:"Request a Let's Encrypt certificate for this domain. Note that the certicate is only requested and stored when the first rpc connection comes in."`
   239  
   240  	// We'll parse these 'raw' string arguments into real net.Addrs in the
   241  	// loadConfig function. We need to expose the 'raw' strings so the
   242  	// command line library can access them.
   243  	// Only the parsed net.Addrs should be used!
   244  	RawRPCListeners   []string `long:"rpclisten" description:"Add an interface/port/socket to listen for RPC connections"`
   245  	RawRESTListeners  []string `long:"restlisten" description:"Add an interface/port/socket to listen for REST connections"`
   246  	RawListeners      []string `long:"listen" description:"Add an interface/port to listen for peer connections"`
   247  	RawExternalIPs    []string `long:"externalip" description:"Add an ip:port to the list of local addresses we claim to listen on to peers. If a port is not specified, the default (9735) will be used regardless of other parameters"`
   248  	ExternalHosts     []string `long:"externalhosts" description:"A set of hosts that should be periodically resolved to announce IPs for"`
   249  	RPCListeners      []net.Addr
   250  	RESTListeners     []net.Addr
   251  	RestCORS          []string `long:"restcors" description:"Add an ip:port/hostname to allow cross origin access from. To allow all origins, set as \"*\"."`
   252  	Listeners         []net.Addr
   253  	ExternalIPs       []net.Addr
   254  	DisableListen     bool          `long:"nolisten" description:"Disable listening for incoming peer connections"`
   255  	DisableRest       bool          `long:"norest" description:"Disable REST API"`
   256  	DisableRestTLS    bool          `long:"no-rest-tls" description:"Disable TLS for REST connections"`
   257  	WSPingInterval    time.Duration `long:"ws-ping-interval" description:"The ping interval for REST based WebSocket connections, set to 0 to disable sending ping messages from the server side"`
   258  	WSPongWait        time.Duration `long:"ws-pong-wait" description:"The time we wait for a pong response message on REST based WebSocket connections before the connection is closed as inactive"`
   259  	NAT               bool          `long:"nat" description:"Toggle NAT traversal support (using either UPnP or NAT-PMP) to automatically advertise your external IP address to the network -- NOTE this does not support devices behind multiple NATs"`
   260  	MinBackoff        time.Duration `long:"minbackoff" description:"Shortest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
   261  	MaxBackoff        time.Duration `long:"maxbackoff" description:"Longest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."`
   262  	ConnectionTimeout time.Duration `long:"connectiontimeout" description:"The timeout value for network connections. Valid time units are {ms, s, m, h}."`
   263  
   264  	DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <global-level>,<subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems"`
   265  
   266  	CPUProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"`
   267  	MemProfile string `long:"memprofile" description:"Write memory profile to the specified file"`
   268  
   269  	Profile string `long:"profile" description:"Enable HTTP profiling on either a port or host:port"`
   270  
   271  	UnsafeDisconnect   bool   `long:"unsafe-disconnect" description:"DEPRECATED: Allows the rpcserver to intentionally disconnect from peers with open channels. THIS FLAG WILL BE REMOVED IN THE FUTURE"`
   272  	UnsafeReplay       bool   `long:"unsafe-replay" description:"Causes a link to replay the adds on its commitment txn after starting up, this enables testing of the sphinx replay logic."`
   273  	MaxPendingChannels int    `long:"maxpendingchannels" description:"The maximum number of incoming pending channels permitted per peer."`
   274  	BackupFilePath     string `long:"backupfilepath" description:"The target location of the channel backup file"`
   275  
   276  	FeeURL string `long:"feeurl" description:"Optional URL for external fee estimation. If no URL is specified, the method for fee estimation will depend on the chosen backend and network."`
   277  
   278  	Decred    *lncfg.Chain
   279  	DcrdMode  *lncfg.DcrdConfig      `group:"dcrd" namespace:"dcrd"`
   280  	Dcrwallet *lncfg.DcrwalletConfig `group:"dcrwallet" namespace:"dcrwallet"`
   281  
   282  	BlockCacheSize uint64 `long:"blockcachesize" description:"The maximum capacity of the block cache"`
   283  
   284  	Autopilot *lncfg.AutoPilot `group:"Autopilot" namespace:"autopilot"`
   285  
   286  	Automation *lncfg.Automation `group:"Automation" namespace:"automation"`
   287  
   288  	Tor *lncfg.Tor `group:"Tor" namespace:"tor"`
   289  
   290  	SubRPCServers *subRPCServerConfigs `group:"subrpc"`
   291  
   292  	Hodl *hodl.Config `group:"hodl" namespace:"hodl"`
   293  
   294  	NoNetBootstrap bool `long:"nobootstrap" description:"If true, then automatic network bootstrapping will not be attempted."`
   295  
   296  	NoSeedBackup             bool   `long:"noseedbackup" description:"If true, NO SEED WILL BE EXPOSED -- EVER, AND THE WALLET WILL BE ENCRYPTED USING THE DEFAULT PASSPHRASE. THIS FLAG IS ONLY FOR TESTING AND SHOULD NEVER BE USED ON MAINNET."`
   297  	WalletUnlockPasswordFile string `long:"wallet-unlock-password-file" description:"The full path to a file (or pipe/device) that contains the password for unlocking the wallet; if set, no unlocking through RPC is possible and lnd will exit if no wallet exists or the password is incorrect; if wallet-unlock-allow-create is also set then lnd will ignore this flag if no wallet exists and allow a wallet to be created through RPC."`
   298  	WalletUnlockAllowCreate  bool   `long:"wallet-unlock-allow-create" description:"Don't fail with an error if wallet-unlock-password-file is set but no wallet exists yet."`
   299  
   300  	resetWalletTransactions bool `long:"reset-wallet-transaction" description:"Not supported in dcrlnd"`
   301  
   302  	CoinSelectionStrategy string `long:"coin-selection-strategy" description:"The strategy to use for selecting coins for wallet transactions." choice:"random"`
   303  
   304  	PaymentsExpirationGracePeriod time.Duration `long:"payments-expiration-grace-period" description:"A period to wait before force closing channels with outgoing htlcs that have timed-out and are a result of this node initiated payments."`
   305  	TrickleDelay                  int           `long:"trickledelay" description:"Time in milliseconds between each release of announcements to the network"`
   306  	ChanEnableTimeout             time.Duration `long:"chan-enable-timeout" description:"The duration that a peer connection must be stable before attempting to send a channel update to reenable or cancel a pending disables of the peer's channels on the network."`
   307  	ChanDisableTimeout            time.Duration `long:"chan-disable-timeout" description:"The duration that must elapse after first detecting that an already active channel is actually inactive and sending channel update disabling it to the network. The pending disable can be canceled if the peer reconnects and becomes stable for chan-enable-timeout before the disable update is sent."`
   308  	ChanStatusSampleInterval      time.Duration `long:"chan-status-sample-interval" description:"The polling interval between attempts to detect if an active channel has become inactive due to its peer going offline."`
   309  	HeightHintCacheQueryDisable   bool          `long:"height-hint-cache-query-disable" description:"Disable queries from the height-hint cache to try to recover channels stuck in the pending close state. Disabling height hint queries may cause longer chain rescans, resulting in a performance hit. Unset this after channels are unstuck so you can get better performance again."`
   310  	Alias                         string        `long:"alias" description:"The node alias. Used as a moniker by peers and intelligence services"`
   311  	Color                         string        `long:"color" description:"The color of the node in hex format (i.e. '#3399FF'). Used to customize node appearance in intelligence services"`
   312  	MinChanSize                   int64         `long:"minchansize" description:"The smallest channel size (in atoms) that we should accept. Incoming channels smaller than this will be rejected"`
   313  	MaxChanSize                   int64         `long:"maxchansize" description:"The largest channel size (in atoms) that we should accept. Incoming channels larger than this will be rejected"`
   314  	CoopCloseTargetConfs          uint32        `long:"coop-close-target-confs" description:"The target number of blocks that a cooperative channel close transaction should confirm in. This is used to estimate the fee to use as the lower bound during fee negotiation for the channel closure."`
   315  
   316  	ChannelCommitInterval  time.Duration `long:"channel-commit-interval" description:"The maximum time that is allowed to pass between receiving a channel state update and signing the next commitment. Setting this to a longer duration allows for more efficient channel operations at the cost of latency."`
   317  	ChannelCommitBatchSize uint32        `long:"channel-commit-batch-size" description:"The maximum number of channel state updates that is accumulated before signing a new commitment."`
   318  
   319  	DefaultRemoteMaxHtlcs uint16 `long:"default-remote-max-htlcs" description:"The default max_htlc applied when opening or accepting channels. This value limits the number of concurrent HTLCs that the remote party can add to the commitment. The maximum possible value is 300."`
   320  
   321  	NumGraphSyncPeers      int           `long:"numgraphsyncpeers" description:"The number of peers that we should receive new graph updates from. This option can be tuned to save bandwidth for light clients or routing nodes."`
   322  	HistoricalSyncInterval time.Duration `long:"historicalsyncinterval" description:"The polling interval between historical graph sync attempts. Each historical graph sync attempt ensures we reconcile with the remote peer's graph from the genesis block."`
   323  
   324  	IgnoreHistoricalGossipFilters bool `long:"ignore-historical-gossip-filters" description:"If true, will not reply with historical data that matches the range specified by a remote peer's gossip_timestamp_filter. Doing so will result in lower memory and bandwidth requirements."`
   325  
   326  	RejectPush bool `long:"rejectpush" description:"If true, lnd will not accept channel opening requests with non-zero push amounts. This should prevent accidental pushes to merchant nodes."`
   327  
   328  	RejectHTLC bool `long:"rejecthtlc" description:"If true, lnd will not forward any HTLCs that are meant as onward payments. This option will still allow lnd to send HTLCs and receive HTLCs but lnd won't be used as a hop."`
   329  
   330  	StaggerInitialReconnect bool `long:"stagger-initial-reconnect" description:"If true, will apply a randomized staggering between 0s and 30s when reconnecting to persistent peers on startup. The first 10 reconnections will be attempted instantly, regardless of the flag's value"`
   331  
   332  	MaxOutgoingCltvExpiry uint32 `long:"max-cltv-expiry" description:"The maximum number of blocks funds could be locked up for when forwarding payments."`
   333  
   334  	MaxChannelFeeAllocation float64 `long:"max-channel-fee-allocation" description:"The maximum percentage of total funds that can be allocated to a channel's commitment fee. This only applies for the initiator of the channel. Valid values are within [0.1, 1]."`
   335  
   336  	MaxCommitFeeRateAnchors uint64 `long:"max-commit-fee-rate-anchors" description:"The maximum fee rate in sat/vbyte that will be used for commitments of channels of the anchors type. Must be large enough to ensure transaction propagation"`
   337  
   338  	DryRunMigration bool `long:"dry-run-migration" description:"If true, lnd will abort committing a migration if it would otherwise have been successful. This leaves the database unmodified, and still compatible with the previously active version of lnd."`
   339  
   340  	net tor.Net
   341  
   342  	EnableUpfrontShutdown bool `long:"enable-upfront-shutdown" description:"If true, option upfront shutdown script will be enabled. If peers that we open channels with support this feature, we will automatically set the script to which cooperative closes should be paid out to on channel open. This offers the partial protection of a channel peer disconnecting from us if cooperative close is attempted with a different script."`
   343  
   344  	AcceptKeySend bool `long:"accept-keysend" description:"If true, spontaneous payments through keysend will be accepted. [experimental]"`
   345  
   346  	AcceptAMP bool `long:"accept-amp" description:"If true, spontaneous payments via AMP will be accepted."`
   347  
   348  	KeysendHoldTime time.Duration `long:"keysend-hold-time" description:"If non-zero, keysend payments are accepted but not immediately settled. If the payment isn't settled manually after the specified time, it is canceled automatically. [experimental]"`
   349  
   350  	GcCanceledInvoicesOnStartup bool `long:"gc-canceled-invoices-on-startup" description:"If true, we'll attempt to garbage collect canceled invoices upon start."`
   351  
   352  	GcCanceledInvoicesOnTheFly bool `long:"gc-canceled-invoices-on-the-fly" description:"If true, we'll delete newly canceled invoices on the fly."`
   353  
   354  	DustThreshold uint64 `long:"dust-threshold" description:"Sets the dust sum threshold in satoshis for a channel after which dust HTLC's will be failed."`
   355  
   356  	Invoices *lncfg.Invoices `group:"invoices" namespace:"invoices"`
   357  
   358  	Routing *lncfg.Routing `group:"routing" namespace:"routing"`
   359  
   360  	Gossip *lncfg.Gossip `group:"gossip" namespace:"gossip"`
   361  
   362  	Workers *lncfg.Workers `group:"workers" namespace:"workers"`
   363  
   364  	Caches *lncfg.Caches `group:"caches" namespace:"caches"`
   365  
   366  	Prometheus lncfg.Prometheus `group:"prometheus" namespace:"prometheus"`
   367  
   368  	WtClient *lncfg.WtClient `group:"wtclient" namespace:"wtclient"`
   369  
   370  	Watchtower *lncfg.Watchtower `group:"watchtower" namespace:"watchtower"`
   371  
   372  	ProtocolOptions *lncfg.ProtocolOptions `group:"protocol" namespace:"protocol"`
   373  
   374  	AllowCircularRoute bool `long:"allow-circular-route" description:"If true, our node will allow htlc forwards that arrive and depart on the same channel."`
   375  
   376  	HealthChecks *lncfg.HealthCheckConfig `group:"healthcheck" namespace:"healthcheck"`
   377  
   378  	DB *lncfg.DB `group:"db" namespace:"db"`
   379  
   380  	Cluster *lncfg.Cluster `group:"cluster" namespace:"cluster"`
   381  
   382  	RPCMiddleware *lncfg.RPCMiddleware `group:"rpcmiddleware" namespace:"rpcmiddleware"`
   383  
   384  	// LogWriter is the root logger that all of the daemon's subloggers are
   385  	// hooked up to.
   386  	LogWriter *build.RotatingLogWriter
   387  
   388  	// registeredChains keeps track of all chains that have been registered
   389  	// with the daemon.
   390  	registeredChains *chainreg.ChainRegistry
   391  
   392  	// networkDir is the path to the directory of the currently active
   393  	// network. This path will hold the files related to each different
   394  	// network.
   395  	networkDir string
   396  
   397  	// ActiveNetParams contains parameters of the target chain.
   398  	ActiveNetParams chainreg.DecredNetParams
   399  }
   400  
   401  // DefaultConfig returns all default values for the Config struct.
   402  func DefaultConfig() Config {
   403  	return Config{
   404  		LndDir:            DefaultLndDir,
   405  		ConfigFile:        DefaultConfigFile,
   406  		DataDir:           defaultDataDir,
   407  		DebugLevel:        defaultLogLevel,
   408  		TLSCertPath:       defaultTLSCertPath,
   409  		TLSKeyPath:        defaultTLSKeyPath,
   410  		TLSCertDuration:   defaultTLSCertDuration,
   411  		LetsEncryptDir:    defaultLetsEncryptDir,
   412  		LetsEncryptListen: defaultLetsEncryptListen,
   413  		LogDir:            defaultLogDir,
   414  		MaxLogFiles:       defaultMaxLogFiles,
   415  		MaxLogFileSize:    defaultMaxLogFileSize,
   416  		AcceptorTimeout:   defaultAcceptorTimeout,
   417  		WSPingInterval:    lnrpc.DefaultPingInterval,
   418  		WSPongWait:        lnrpc.DefaultPongWait,
   419  		Decred: &lncfg.Chain{
   420  			MinHTLCIn:     chainreg.DefaultDecredMinHTLCInMAtoms,
   421  			MinHTLCOut:    chainreg.DefaultDecredMinHTLCOutMAtoms,
   422  			BaseFee:       chainreg.DefaultDecredBaseFeeMAtoms,
   423  			FeeRate:       chainreg.DefaultDecredFeeRate,
   424  			TimeLockDelta: chainreg.DefaultDecredTimeLockDelta,
   425  			MaxLocalDelay: defaultMaxLocalCSVDelay,
   426  			Node:          "dcrd",
   427  		},
   428  		DcrdMode: &lncfg.DcrdConfig{
   429  			RPCHost: defaultRPCHost,
   430  			RPCCert: defaultDcrdRPCCertFile,
   431  		},
   432  		Dcrwallet:          &lncfg.DcrwalletConfig{},
   433  		BlockCacheSize:     defaultBlockCacheSize,
   434  		UnsafeDisconnect:   true,
   435  		MaxPendingChannels: lncfg.DefaultMaxPendingChannels,
   436  		NoSeedBackup:       defaultNoSeedBackup,
   437  		MinBackoff:         defaultMinBackoff,
   438  		MaxBackoff:         defaultMaxBackoff,
   439  		ConnectionTimeout:  tor.DefaultConnTimeout,
   440  		SubRPCServers: &subRPCServerConfigs{
   441  			SignRPC:   &signrpc.Config{},
   442  			RouterRPC: routerrpc.DefaultConfig(),
   443  		},
   444  		Autopilot: &lncfg.AutoPilot{
   445  			MaxChannels:    5,
   446  			Allocation:     0.6,
   447  			MinChannelSize: int64(funding.MinChanFundingSize),
   448  			MaxChannelSize: int64(MaxFundingAmount),
   449  			MinConfs:       1,
   450  			ConfTarget:     autopilot.DefaultConfTarget,
   451  			Heuristic: map[string]float64{
   452  				"top_centrality": 1.0,
   453  			},
   454  		},
   455  		Automation: &lncfg.Automation{
   456  			ForceCloseChanReestablishWait: 60 * 60 * 24 * 3, // 3 days
   457  		},
   458  		PaymentsExpirationGracePeriod: defaultPaymentsExpirationGracePeriod,
   459  		TrickleDelay:                  defaultTrickleDelay,
   460  		ChanStatusSampleInterval:      defaultChanStatusSampleInterval,
   461  		ChanEnableTimeout:             defaultChanEnableTimeout,
   462  		ChanDisableTimeout:            defaultChanDisableTimeout,
   463  		HeightHintCacheQueryDisable:   defaultHeightHintCacheQueryDisable,
   464  		Alias:                         defaultAlias,
   465  		Color:                         defaultColor,
   466  		MinChanSize:                   int64(funding.MinChanFundingSize),
   467  		MaxChanSize:                   int64(0),
   468  		CoopCloseTargetConfs:          defaultCoopCloseTargetConfs,
   469  		DefaultRemoteMaxHtlcs:         defaultRemoteMaxHtlcs,
   470  		NumGraphSyncPeers:             defaultMinPeers,
   471  		HistoricalSyncInterval:        discovery.DefaultHistoricalSyncInterval,
   472  		Tor: &lncfg.Tor{
   473  			SOCKS:   defaultTorSOCKS,
   474  			DNS:     defaultTorDNS,
   475  			Control: defaultTorControl,
   476  		},
   477  		net: &tor.ClearNet{},
   478  		Workers: &lncfg.Workers{
   479  			Read:  lncfg.DefaultReadWorkers,
   480  			Write: lncfg.DefaultWriteWorkers,
   481  			Sig:   lncfg.DefaultSigWorkers,
   482  		},
   483  		Caches: &lncfg.Caches{
   484  			RejectCacheSize:  channeldb.DefaultRejectCacheSize,
   485  			ChannelCacheSize: channeldb.DefaultChannelCacheSize,
   486  		},
   487  		Prometheus: lncfg.DefaultPrometheus(),
   488  		Watchtower: &lncfg.Watchtower{
   489  			TowerDir: defaultTowerDir,
   490  		},
   491  		HealthChecks: &lncfg.HealthCheckConfig{
   492  			ChainCheck: &lncfg.CheckConfig{
   493  				Interval: defaultChainInterval,
   494  				Timeout:  defaultChainTimeout,
   495  				Attempts: defaultChainAttempts,
   496  				Backoff:  defaultChainBackoff,
   497  			},
   498  			DiskCheck: &lncfg.DiskCheckConfig{
   499  				RequiredRemaining: defaultRequiredDisk,
   500  				CheckConfig: &lncfg.CheckConfig{
   501  					Interval: defaultDiskInterval,
   502  					Attempts: defaultDiskAttempts,
   503  					Timeout:  defaultDiskTimeout,
   504  					Backoff:  defaultDiskBackoff,
   505  				},
   506  			},
   507  			TLSCheck: &lncfg.CheckConfig{
   508  				Interval: defaultTLSInterval,
   509  				Timeout:  defaultTLSTimeout,
   510  				Attempts: defaultTLSAttempts,
   511  				Backoff:  defaultTLSBackoff,
   512  			},
   513  			TorConnection: &lncfg.CheckConfig{
   514  				Interval: defaultTCInterval,
   515  				Timeout:  defaultTCTimeout,
   516  				Attempts: defaultTCAttempts,
   517  				Backoff:  defaultTCBackoff,
   518  			},
   519  		},
   520  		Routing: &lncfg.Routing{
   521  			AssumeChannelValid: false,
   522  		},
   523  		Gossip: &lncfg.Gossip{
   524  			MaxChannelUpdateBurst: discovery.DefaultMaxChannelUpdateBurst,
   525  			ChannelUpdateInterval: discovery.DefaultChannelUpdateInterval,
   526  		},
   527  		Invoices: &lncfg.Invoices{
   528  			HoldExpiryDelta: lncfg.DefaultHoldInvoiceExpiryDelta,
   529  		},
   530  		MaxOutgoingCltvExpiry:   htlcswitch.DefaultMaxOutgoingCltvExpiry,
   531  		MaxChannelFeeAllocation: htlcswitch.DefaultMaxLinkFeeAllocation,
   532  		MaxCommitFeeRateAnchors: lnwallet.DefaultAnchorsCommitMaxFeeRateAtomsPerByte,
   533  		DustThreshold:           uint64(htlcswitch.DefaultDustThreshold.ToAtoms()),
   534  		LogWriter:               build.NewRotatingLogWriter(),
   535  		DB:                      lncfg.DefaultDB(),
   536  		Cluster:                 lncfg.DefaultCluster(),
   537  		RPCMiddleware:           lncfg.DefaultRPCMiddleware(),
   538  		registeredChains:        chainreg.NewChainRegistry(),
   539  		ActiveNetParams:         chainreg.DecredTestNetParams,
   540  		ChannelCommitInterval:   defaultChannelCommitInterval,
   541  		ChannelCommitBatchSize:  defaultChannelCommitBatchSize,
   542  		CoinSelectionStrategy:   defaultCoinSelectionStrategy,
   543  	}
   544  }
   545  
   546  // LoadConfig initializes and parses the config using a config file and command
   547  // line options.
   548  //
   549  // The configuration proceeds as follows:
   550  //  1. Start with a default config with sane settings
   551  //  2. Pre-parse the command line to check for an alternative config file
   552  //  3. Load configuration file overwriting defaults with any specified options
   553  //  4. Parse CLI options and overwrite/add any specified options
   554  func LoadConfig(interceptor signal.Interceptor) (*Config, error) {
   555  	// Pre-parse the command line options to pick up an alternative config
   556  	// file.
   557  	preCfg := DefaultConfig()
   558  	if _, err := flags.Parse(&preCfg); err != nil {
   559  		return nil, err
   560  	}
   561  
   562  	// Show the version and exit if the version flag was specified.
   563  	appName := filepath.Base(os.Args[0])
   564  	appName = strings.TrimSuffix(appName, filepath.Ext(appName))
   565  	usageMessage := fmt.Sprintf("Use %s -h to show usage", appName)
   566  	if preCfg.ShowVersion {
   567  		commit := build.SourceCommit()
   568  		if commit != "" {
   569  			commit = fmt.Sprintf("Commit %s; ", commit)
   570  		}
   571  		fmt.Printf("%s version %s (%sGo version %s %s/%s)\n",
   572  			appName, build.Version(), commit,
   573  			runtime.Version(), runtime.GOOS, runtime.GOARCH)
   574  		os.Exit(0)
   575  	}
   576  
   577  	// If the config file path has not been modified by the user, then we'll
   578  	// use the default config file path. However, if the user has modified
   579  	// their lnddir, then we should assume they intend to use the config
   580  	// file within it.
   581  	configFileDir := CleanAndExpandPath(preCfg.LndDir)
   582  	configFilePath := CleanAndExpandPath(preCfg.ConfigFile)
   583  	if configFileDir != DefaultLndDir {
   584  		if configFilePath == DefaultConfigFile {
   585  			configFilePath = filepath.Join(
   586  				configFileDir, lncfg.DefaultConfigFilename,
   587  			)
   588  		}
   589  	}
   590  
   591  	// Next, load any additional configuration options from the file.
   592  	var configFileError error
   593  	cfg := preCfg
   594  	fileParser := flags.NewParser(&cfg, flags.Default)
   595  	err := flags.NewIniParser(fileParser).ParseFile(configFilePath)
   596  	if err != nil {
   597  		// If it's a parsing related error, then we'll return
   598  		// immediately, otherwise we can proceed as possibly the config
   599  		// file doesn't exist which is OK.
   600  		if _, ok := err.(*flags.IniError); ok {
   601  			return nil, err
   602  		}
   603  
   604  		configFileError = err
   605  	}
   606  
   607  	// Finally, parse the remaining command line options again to ensure
   608  	// they take precedence.
   609  	flagParser := flags.NewParser(&cfg, flags.Default)
   610  	if _, err := flagParser.Parse(); err != nil {
   611  		return nil, err
   612  	}
   613  
   614  	// Make sure everything we just loaded makes sense.
   615  	cleanCfg, err := ValidateConfig(
   616  		cfg, interceptor, fileParser, flagParser,
   617  	)
   618  	if usageErr, ok := err.(*usageError); ok {
   619  		// The logging system might not yet be initialized, so we also
   620  		// write to stderr to make sure the error appears somewhere.
   621  		_, _ = fmt.Fprintln(os.Stderr, usageMessage)
   622  		ltndLog.Warnf("Incorrect usage: %v", usageMessage)
   623  
   624  		// The log subsystem might not yet be initialized. But we still
   625  		// try to log the error there since some packaging solutions
   626  		// might only look at the log and not stdout/stderr.
   627  		ltndLog.Warnf("Error validating config: %v", usageErr.err)
   628  
   629  		return nil, usageErr.err
   630  	}
   631  	if err != nil {
   632  		// The log subsystem might not yet be initialized. But we still
   633  		// try to log the error there since some packaging solutions
   634  		// might only look at the log and not stdout/stderr.
   635  		ltndLog.Warnf("Error validating config: %v", err)
   636  
   637  		return nil, err
   638  	}
   639  
   640  	// Warn about missing config file only after all other configuration is
   641  	// done. This prevents the warning on help messages and invalid options.
   642  	// Note this should go directly before the return.
   643  	if configFileError != nil {
   644  		ltndLog.Warnf("%v", configFileError)
   645  	}
   646  
   647  	return cleanCfg, nil
   648  }
   649  
   650  // usageError is an error type that signals a problem with the supplied flags.
   651  type usageError struct {
   652  	err error
   653  }
   654  
   655  // Error returns the error string.
   656  //
   657  // NOTE: This is part of the error interface.
   658  func (u *usageError) Error() string {
   659  	return u.err.Error()
   660  }
   661  
   662  // ValidateConfig check the given configuration to be sane. This makes sure no
   663  // illegal values or combination of values are set. All file system paths are
   664  // normalized. The cleaned up config is returned on success.
   665  func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
   666  	flagParser *flags.Parser) (*Config, error) {
   667  
   668  	// If the provided lnd directory is not the default, we'll modify the
   669  	// path to all of the files and directories that will live within it.
   670  	lndDir := CleanAndExpandPath(cfg.LndDir)
   671  	if lndDir != DefaultLndDir {
   672  		cfg.DataDir = filepath.Join(lndDir, defaultDataDirname)
   673  		cfg.LetsEncryptDir = filepath.Join(
   674  			lndDir, defaultLetsEncryptDirname,
   675  		)
   676  		cfg.TLSCertPath = filepath.Join(lndDir, defaultTLSCertFilename)
   677  		cfg.TLSKeyPath = filepath.Join(lndDir, defaultTLSKeyFilename)
   678  		cfg.LogDir = filepath.Join(lndDir, defaultLogDirname)
   679  
   680  		// If the watchtower's directory is set to the default, i.e. the
   681  		// user has not requested a different location, we'll move the
   682  		// location to be relative to the specified lnd directory.
   683  		if cfg.Watchtower.TowerDir == defaultTowerDir {
   684  			cfg.Watchtower.TowerDir = filepath.Join(
   685  				cfg.DataDir, defaultTowerSubDirname,
   686  			)
   687  		}
   688  	}
   689  
   690  	funcName := "ValidateConfig"
   691  	mkErr := func(format string, args ...interface{}) error {
   692  		return fmt.Errorf(funcName+": "+format, args...)
   693  	}
   694  	makeDirectory := func(dir string) error {
   695  		err := os.MkdirAll(dir, 0700)
   696  		if err != nil {
   697  			// Show a nicer error message if it's because a symlink
   698  			// is linked to a directory that does not exist
   699  			// (probably because it's not mounted).
   700  			if e, ok := err.(*os.PathError); ok && os.IsExist(err) {
   701  				link, lerr := os.Readlink(e.Path)
   702  				if lerr == nil {
   703  					str := "is symlink %s -> %s mounted?"
   704  					err = fmt.Errorf(str, e.Path, link)
   705  				}
   706  			}
   707  
   708  			str := "Failed to create lnd directory '%s': %v"
   709  			return mkErr(str, dir, err)
   710  		}
   711  
   712  		return nil
   713  	}
   714  
   715  	// IsSet returns true if an option has been set in either the config
   716  	// file or by a flag.
   717  	isSet := func(field string) (bool, error) {
   718  		fieldName, ok := reflect.TypeOf(Config{}).FieldByName(field)
   719  		if !ok {
   720  			str := "could not find field %s"
   721  			return false, mkErr(str, field)
   722  		}
   723  
   724  		long, ok := fieldName.Tag.Lookup("long")
   725  		if !ok {
   726  			str := "field %s does not have a long tag"
   727  			return false, mkErr(str, field)
   728  		}
   729  
   730  		// The user has the option to set the flag in either the config
   731  		// file or as a command line flag. If any is set, we consider it
   732  		// to be set, not applying any precedence rules here (since it
   733  		// is a boolean the default is false anyway which would screw up
   734  		// any precedence rules). Additionally, we need to also support
   735  		// the use case where the config struct is embedded _within_
   736  		// another struct with a prefix (as is the case with
   737  		// lightning-terminal).
   738  		fileOption := fileParser.FindOptionByLongName(long)
   739  		fileOptionNested := fileParser.FindOptionByLongName(
   740  			"lnd." + long,
   741  		)
   742  		flagOption := flagParser.FindOptionByLongName(long)
   743  		flagOptionNested := flagParser.FindOptionByLongName(
   744  			"lnd." + long,
   745  		)
   746  
   747  		return (fileOption != nil && fileOption.IsSet()) ||
   748  				(fileOptionNested != nil && fileOptionNested.IsSet()) ||
   749  				(flagOption != nil && flagOption.IsSet()) ||
   750  				(flagOptionNested != nil && flagOptionNested.IsSet()),
   751  			nil
   752  	}
   753  
   754  	// As soon as we're done parsing configuration options, ensure all paths
   755  	// to directories and files are cleaned and expanded before attempting
   756  	// to use them later on.
   757  	cfg.DataDir = CleanAndExpandPath(cfg.DataDir)
   758  	cfg.TLSCertPath = CleanAndExpandPath(cfg.TLSCertPath)
   759  	cfg.TLSKeyPath = CleanAndExpandPath(cfg.TLSKeyPath)
   760  	cfg.LetsEncryptDir = CleanAndExpandPath(cfg.LetsEncryptDir)
   761  	cfg.AdminMacPath = CleanAndExpandPath(cfg.AdminMacPath)
   762  	cfg.ReadMacPath = CleanAndExpandPath(cfg.ReadMacPath)
   763  	cfg.InvoiceMacPath = CleanAndExpandPath(cfg.InvoiceMacPath)
   764  	cfg.LogDir = CleanAndExpandPath(cfg.LogDir)
   765  	cfg.Tor.PrivateKeyPath = CleanAndExpandPath(cfg.Tor.PrivateKeyPath)
   766  	cfg.Tor.WatchtowerKeyPath = CleanAndExpandPath(cfg.Tor.WatchtowerKeyPath)
   767  	cfg.Watchtower.TowerDir = CleanAndExpandPath(cfg.Watchtower.TowerDir)
   768  	cfg.Dcrwallet.CertPath = CleanAndExpandPath(cfg.Dcrwallet.CertPath)
   769  	cfg.Dcrwallet.ClientKeyPath = CleanAndExpandPath(cfg.Dcrwallet.ClientKeyPath)
   770  	cfg.Dcrwallet.ClientCertPath = CleanAndExpandPath(cfg.Dcrwallet.ClientCertPath)
   771  	cfg.BackupFilePath = CleanAndExpandPath(cfg.BackupFilePath)
   772  	cfg.WalletUnlockPasswordFile = CleanAndExpandPath(
   773  		cfg.WalletUnlockPasswordFile,
   774  	)
   775  
   776  	// Ensure that the user didn't attempt to specify negative values for
   777  	// any of the autopilot params.
   778  	if cfg.Autopilot.MaxChannels < 0 {
   779  		str := "autopilot.maxchannels must be non-negative"
   780  		return nil, mkErr(str)
   781  	}
   782  	if cfg.Autopilot.Allocation < 0 {
   783  		str := "autopilot.allocation must be non-negative"
   784  		return nil, mkErr(str)
   785  	}
   786  	if cfg.Autopilot.MinChannelSize < 0 {
   787  		str := "autopilot.minchansize must be non-negative"
   788  		return nil, mkErr(str)
   789  	}
   790  	if cfg.Autopilot.MaxChannelSize < 0 {
   791  		str := "autopilot.maxchansize must be non-negative"
   792  		return nil, mkErr(str)
   793  	}
   794  	if cfg.Autopilot.MinConfs < 0 {
   795  		str := "autopilot.minconfs must be non-negative"
   796  		return nil, mkErr(str)
   797  	}
   798  	if cfg.Autopilot.ConfTarget < 1 {
   799  		str := "autopilot.conftarget must be positive"
   800  		return nil, mkErr(str)
   801  	}
   802  
   803  	// Ensure that the specified values for the min and max channel size
   804  	// are within the bounds of the normal chan size constraints.
   805  	if cfg.Autopilot.MinChannelSize < int64(funding.MinChanFundingSize) {
   806  		cfg.Autopilot.MinChannelSize = int64(funding.MinChanFundingSize)
   807  	}
   808  	if cfg.Autopilot.MaxChannelSize > int64(MaxFundingAmount) {
   809  		cfg.Autopilot.MaxChannelSize = int64(MaxFundingAmount)
   810  	}
   811  
   812  	if _, err := validateAtplCfg(cfg.Autopilot); err != nil {
   813  		return nil, mkErr("error validating autopilot: %v", err)
   814  	}
   815  
   816  	// Ensure that --maxchansize is properly handled when set by user.  For
   817  	// non-Wumbo channels this limit remains 1073741823 atoms by default as
   818  	// specified in BOLT-02. For wumbo channels this limit is 500e8 atoms
   819  	// (500 DCR). Always enforce --maxchansize explicitly set by user.  If
   820  	// unset (marked by 0 value), then enforce proper default.
   821  	if cfg.MaxChanSize == 0 {
   822  		if cfg.ProtocolOptions.Wumbo() {
   823  			cfg.MaxChanSize = int64(funding.MaxDecredFundingAmountWumbo)
   824  		} else {
   825  			cfg.MaxChanSize = int64(funding.MaxDecredFundingAmount)
   826  		}
   827  	}
   828  
   829  	// Ensure that the user specified values for the min and max channel
   830  	// size make sense.
   831  	if cfg.MaxChanSize < cfg.MinChanSize {
   832  		return nil, mkErr("invalid channel size parameters: "+
   833  			"max channel size %v, must be no less than min chan "+
   834  			"size %v", cfg.MaxChanSize, cfg.MinChanSize,
   835  		)
   836  	}
   837  
   838  	// Don't allow superflous --maxchansize greater than
   839  	// BOLT 02 soft-limit for non-wumbo channel
   840  	if !cfg.ProtocolOptions.Wumbo() &&
   841  		cfg.MaxChanSize > int64(MaxFundingAmount) {
   842  
   843  		return nil, mkErr("invalid channel size parameters: "+
   844  			"maximum channel size %v is greater than maximum "+
   845  			"non-wumbo channel size %v", cfg.MaxChanSize,
   846  			MaxFundingAmount,
   847  		)
   848  	}
   849  
   850  	// Ensure a valid max channel fee allocation was set.
   851  	if cfg.MaxChannelFeeAllocation <= 0 || cfg.MaxChannelFeeAllocation > 1 {
   852  		return nil, mkErr("invalid max channel fee allocation: %v, "+
   853  			"must be within (0, 1]", cfg.MaxChannelFeeAllocation)
   854  	}
   855  
   856  	if cfg.MaxCommitFeeRateAnchors < 1 {
   857  		return nil, mkErr("invalid max commit fee rate anchors: %v, "+
   858  			"must be at least 1 sat/vByte",
   859  			cfg.MaxCommitFeeRateAnchors)
   860  	}
   861  
   862  	// Validate the Tor config parameters.
   863  	socks, err := lncfg.ParseAddressString(
   864  		cfg.Tor.SOCKS, strconv.Itoa(defaultTorSOCKSPort),
   865  		cfg.net.ResolveTCPAddr,
   866  	)
   867  	if err != nil {
   868  		return nil, err
   869  	}
   870  	cfg.Tor.SOCKS = socks.String()
   871  
   872  	// We'll only attempt to normalize and resolve the DNS host if it hasn't
   873  	// changed, as it doesn't need to be done for the default.
   874  	if cfg.Tor.DNS != defaultTorDNS {
   875  		dns, err := lncfg.ParseAddressString(
   876  			cfg.Tor.DNS, strconv.Itoa(defaultTorDNSPort),
   877  			cfg.net.ResolveTCPAddr,
   878  		)
   879  		if err != nil {
   880  			return nil, mkErr("error parsing tor dns: %v", err)
   881  		}
   882  		cfg.Tor.DNS = dns.String()
   883  	}
   884  
   885  	control, err := lncfg.ParseAddressString(
   886  		cfg.Tor.Control, strconv.Itoa(defaultTorControlPort),
   887  		cfg.net.ResolveTCPAddr,
   888  	)
   889  	if err != nil {
   890  		return nil, mkErr("error parsing tor control address: %v", err)
   891  	}
   892  	cfg.Tor.Control = control.String()
   893  
   894  	// Ensure that tor socks host:port is not equal to tor control
   895  	// host:port. This would lead to lnd not starting up properly.
   896  	if cfg.Tor.SOCKS == cfg.Tor.Control {
   897  		str := "tor.socks and tor.control can not us the same host:port"
   898  		return nil, mkErr(str)
   899  	}
   900  
   901  	switch {
   902  	case cfg.Tor.V2 && cfg.Tor.V3:
   903  		return nil, mkErr("either tor.v2 or tor.v3 can be set, " +
   904  			"but not both")
   905  	case cfg.DisableListen && (cfg.Tor.V2 || cfg.Tor.V3):
   906  		return nil, mkErr("listening must be enabled when enabling " +
   907  			"inbound connections over Tor")
   908  	}
   909  
   910  	if cfg.Tor.PrivateKeyPath == "" {
   911  		switch {
   912  		case cfg.Tor.V2:
   913  			cfg.Tor.PrivateKeyPath = filepath.Join(
   914  				lndDir, defaultTorV2PrivateKeyFilename,
   915  			)
   916  		case cfg.Tor.V3:
   917  			cfg.Tor.PrivateKeyPath = filepath.Join(
   918  				lndDir, defaultTorV3PrivateKeyFilename,
   919  			)
   920  		}
   921  	}
   922  
   923  	if cfg.Tor.WatchtowerKeyPath == "" {
   924  		switch {
   925  		case cfg.Tor.V2:
   926  			cfg.Tor.WatchtowerKeyPath = filepath.Join(
   927  				cfg.Watchtower.TowerDir,
   928  				defaultTorV2PrivateKeyFilename,
   929  			)
   930  		case cfg.Tor.V3:
   931  			cfg.Tor.WatchtowerKeyPath = filepath.Join(
   932  				cfg.Watchtower.TowerDir,
   933  				defaultTorV3PrivateKeyFilename,
   934  			)
   935  		}
   936  	}
   937  
   938  	// Set up the network-related functions that will be used throughout
   939  	// the daemon. We use the standard Go "net" package functions by
   940  	// default. If we should be proxying all traffic through Tor, then
   941  	// we'll use the Tor proxy specific functions in order to avoid leaking
   942  	// our real information.
   943  	if cfg.Tor.Active {
   944  		cfg.net = &tor.ProxyNet{
   945  			SOCKS:                       cfg.Tor.SOCKS,
   946  			DNS:                         cfg.Tor.DNS,
   947  			StreamIsolation:             cfg.Tor.StreamIsolation,
   948  			SkipProxyForClearNetTargets: cfg.Tor.SkipProxyForClearNetTargets,
   949  		}
   950  	}
   951  
   952  	if cfg.DisableListen && cfg.NAT {
   953  		return nil, mkErr("NAT traversal cannot be used when " +
   954  			"listening is disabled")
   955  	}
   956  	if cfg.NAT && len(cfg.ExternalHosts) != 0 {
   957  		return nil, mkErr("NAT support and externalhosts are " +
   958  			"mutually exclusive, only one should be selected")
   959  	}
   960  
   961  	// Multiple networks can't be selected simultaneously.  Count number of
   962  	// network flags passed; assign active network params while we're at
   963  	// it.
   964  	numNets := 0
   965  	if cfg.Decred.TestNet3 {
   966  		numNets++
   967  		cfg.ActiveNetParams = chainreg.DecredTestNetParams
   968  	}
   969  	if cfg.Decred.RegTest {
   970  		numNets++
   971  		cfg.ActiveNetParams = chainreg.RegTestNetParams
   972  	}
   973  	if cfg.Decred.SimNet {
   974  		numNets++
   975  		cfg.ActiveNetParams = chainreg.DecredSimNetParams
   976  	}
   977  	if numNets > 1 {
   978  		return nil, mkErr("%s: The testnet, regtest, and simnet params"+
   979  			"can't be used together -- choose one of the three",
   980  			funcName)
   981  	}
   982  
   983  	// We default to mainnet if none are specified.
   984  	if numNets == 0 {
   985  		cfg.ActiveNetParams = chainreg.DecredMainNetParams
   986  	}
   987  
   988  	err = cfg.Decred.Validate(minTimeLockDelta, funding.MinDcrRemoteDelay)
   989  	if err != nil {
   990  		return nil, err
   991  	}
   992  
   993  	switch cfg.Decred.Node {
   994  	case "dcrd":
   995  		err := parseRPCParams(
   996  			cfg.Decred, cfg.DcrdMode, chainreg.DecredChain,
   997  			cfg.ActiveNetParams,
   998  		)
   999  		if err != nil {
  1000  			err := fmt.Errorf("unable to load RPC "+
  1001  				"credentials for dcrd: %v", err)
  1002  			return nil, err
  1003  		}
  1004  	case "dcrw":
  1005  		// In dcrw mode we use the underlying wallet for chain
  1006  		// operations.
  1007  	case "nochainbackend":
  1008  		// No chain sync.
  1009  	default:
  1010  		str := "%s: only dcrd and dcrw modes supported for Decred at " +
  1011  			"this time"
  1012  		return nil, fmt.Errorf(str, funcName)
  1013  	}
  1014  
  1015  	cfg.Decred.ChainDir = filepath.Join(cfg.DataDir,
  1016  		defaultChainSubDirname,
  1017  		chainreg.DecredChain.String())
  1018  
  1019  	// Ensure sane config when using a remote wallet.
  1020  	if cfg.Dcrwallet.GRPCHost != "" {
  1021  		// Update Dcrwallet.GRPCHost with correct port from
  1022  		// activeNetParam selected.
  1023  		_, _, err := net.SplitHostPort(cfg.Dcrwallet.GRPCHost)
  1024  		if err != nil {
  1025  			cfg.Dcrwallet.GRPCHost = net.JoinHostPort(
  1026  				cfg.Dcrwallet.GRPCHost,
  1027  				cfg.ActiveNetParams.DcrwPort,
  1028  			)
  1029  		}
  1030  
  1031  		// dcrwallet v1.6.0+ requires a client cert and key for gRPC
  1032  		// auth, so if any of {ClientKeyPath, ClientCertPath} are
  1033  		// specified, *both* need to be.
  1034  		//
  1035  		// Otherwise, the client key and cert will come on a
  1036  		// WalletUnlocker.Unlock() call.
  1037  		clientKeyEmpty := cfg.Dcrwallet.ClientKeyPath == ""
  1038  		clientCertEmpty := cfg.Dcrwallet.ClientCertPath == ""
  1039  		if clientKeyEmpty != clientCertEmpty {
  1040  			str := "%s: dcrwallet.clientkeypath and clientcertpath must both be specified"
  1041  			err := fmt.Errorf(str, funcName)
  1042  			return nil, err
  1043  		}
  1044  	}
  1045  
  1046  	// Finally we'll register the decred chain as our current
  1047  	// primary chain.
  1048  	cfg.registeredChains.RegisterPrimaryChain(chainreg.DecredChain)
  1049  
  1050  	// Ensure that the user didn't attempt to specify negative values for
  1051  	// any of the autopilot params.
  1052  	if cfg.Autopilot.MaxChannels < 0 {
  1053  		str := "autopilot.maxchannels must be non-negative"
  1054  		return nil, mkErr(str)
  1055  	}
  1056  	if cfg.Autopilot.Allocation < 0 {
  1057  		str := "autopilot.allocation must be non-negative"
  1058  		return nil, mkErr(str)
  1059  	}
  1060  	if cfg.Autopilot.MinChannelSize < 0 {
  1061  		str := "autopilot.minchansize must be non-negative"
  1062  		return nil, mkErr(str)
  1063  	}
  1064  	if cfg.Autopilot.MaxChannelSize < 0 {
  1065  		str := "autopilot.maxchansize must be non-negative"
  1066  		return nil, mkErr(str)
  1067  	}
  1068  
  1069  	// Ensure that the specified values for the min and max channel size
  1070  	// don't are within the bounds of the normal chan size constraints.
  1071  	if cfg.Autopilot.MinChannelSize < int64(funding.MinChanFundingSize) {
  1072  		cfg.Autopilot.MinChannelSize = int64(funding.MinChanFundingSize)
  1073  	}
  1074  	if cfg.Autopilot.MaxChannelSize > int64(MaxFundingAmount) {
  1075  		cfg.Autopilot.MaxChannelSize = int64(MaxFundingAmount)
  1076  	}
  1077  
  1078  	// Validate profile port or host:port.
  1079  	if cfg.Profile != "" {
  1080  		str := "%s: The profile port must be between 1024 and 65535"
  1081  
  1082  		// Try to parse Profile as a host:port.
  1083  		_, hostPort, err := net.SplitHostPort(cfg.Profile)
  1084  		if err == nil {
  1085  			// Determine if the port is valid.
  1086  			profilePort, err := strconv.Atoi(hostPort)
  1087  			if err != nil || profilePort < 1024 || profilePort > 65535 {
  1088  				return nil, &usageError{mkErr(str)}
  1089  			}
  1090  		} else {
  1091  			// Try to parse Profile as a port.
  1092  			profilePort, err := strconv.Atoi(cfg.Profile)
  1093  			if err != nil || profilePort < 1024 || profilePort > 65535 {
  1094  				return nil, &usageError{mkErr(str)}
  1095  			}
  1096  
  1097  			// Since the user just set a port, we will serve debugging
  1098  			// information over localhost.
  1099  			cfg.Profile = net.JoinHostPort("127.0.0.1", cfg.Profile)
  1100  		}
  1101  	}
  1102  
  1103  	// We'll now construct the network directory which will be where we
  1104  	// store all the data specific to this chain/network.
  1105  	cfg.networkDir = filepath.Join(
  1106  		cfg.DataDir, defaultChainSubDirname,
  1107  		cfg.registeredChains.PrimaryChain().String(),
  1108  		lncfg.NormalizeNetwork(cfg.ActiveNetParams.Name),
  1109  	)
  1110  
  1111  	// If a custom macaroon directory wasn't specified and the data
  1112  	// directory has changed from the default path, then we'll also update
  1113  	// the path for the macaroons to be generated.
  1114  	if cfg.AdminMacPath == "" {
  1115  		cfg.AdminMacPath = filepath.Join(
  1116  			cfg.networkDir, defaultAdminMacFilename,
  1117  		)
  1118  	}
  1119  	if cfg.ReadMacPath == "" {
  1120  		cfg.ReadMacPath = filepath.Join(
  1121  			cfg.networkDir, defaultReadMacFilename,
  1122  		)
  1123  	}
  1124  	if cfg.InvoiceMacPath == "" {
  1125  		cfg.InvoiceMacPath = filepath.Join(
  1126  			cfg.networkDir, defaultInvoiceMacFilename,
  1127  		)
  1128  	}
  1129  
  1130  	// Create the lnd directory and all other sub-directories if they don't
  1131  	// already exist. This makes sure that directory trees are also created
  1132  	// for files that point to outside the lnddir.
  1133  	dirs := []string{
  1134  		lndDir, cfg.DataDir, cfg.networkDir,
  1135  		cfg.LetsEncryptDir, cfg.Watchtower.TowerDir,
  1136  		filepath.Dir(cfg.TLSCertPath), filepath.Dir(cfg.TLSKeyPath),
  1137  		filepath.Dir(cfg.AdminMacPath), filepath.Dir(cfg.ReadMacPath),
  1138  		filepath.Dir(cfg.InvoiceMacPath),
  1139  		filepath.Dir(cfg.Tor.PrivateKeyPath),
  1140  		filepath.Dir(cfg.Tor.WatchtowerKeyPath),
  1141  	}
  1142  	for _, dir := range dirs {
  1143  		if err := makeDirectory(dir); err != nil {
  1144  			return nil, err
  1145  		}
  1146  	}
  1147  
  1148  	// Similarly, if a custom back up file path wasn't specified, then
  1149  	// we'll update the file location to match our set network directory.
  1150  	if cfg.BackupFilePath == "" {
  1151  		cfg.BackupFilePath = filepath.Join(
  1152  			cfg.networkDir, chanbackup.DefaultBackupFileName,
  1153  		)
  1154  	}
  1155  
  1156  	// Append the network type to the log directory so it is "namespaced"
  1157  	// per network in the same fashion as the data directory.
  1158  	cfg.LogDir = filepath.Join(
  1159  		cfg.LogDir, cfg.registeredChains.PrimaryChain().String(),
  1160  		lncfg.NormalizeNetwork(cfg.ActiveNetParams.Name),
  1161  	)
  1162  
  1163  	// A log writer must be passed in, otherwise we can't function and would
  1164  	// run into a panic later on.
  1165  	if cfg.LogWriter == nil {
  1166  		return nil, mkErr("log writer missing in config")
  1167  	}
  1168  
  1169  	// Special show command to list supported subsystems and exit.
  1170  	if cfg.DebugLevel == "show" {
  1171  		fmt.Println("Supported subsystems",
  1172  			cfg.LogWriter.SupportedSubsystems())
  1173  		os.Exit(0)
  1174  	}
  1175  
  1176  	// Initialize logging at the default logging level.
  1177  	SetupLoggers(cfg.LogWriter, interceptor)
  1178  	err = cfg.LogWriter.InitLogRotator(
  1179  		filepath.Join(cfg.LogDir, defaultLogFilename),
  1180  		cfg.MaxLogFileSize, cfg.MaxLogFiles,
  1181  	)
  1182  	if err != nil {
  1183  		str := "log rotation setup failed: %v"
  1184  		return nil, mkErr(str, err)
  1185  	}
  1186  
  1187  	// Parse, validate, and set debug log level(s).
  1188  	err = build.ParseAndSetDebugLevels(cfg.DebugLevel, cfg.LogWriter)
  1189  	if err != nil {
  1190  		str := "error parsing debug level: %v"
  1191  		return nil, &usageError{mkErr(str, err)}
  1192  	}
  1193  
  1194  	// At least one RPCListener is required. So listen on localhost per
  1195  	// default.
  1196  	if len(cfg.RawRPCListeners) == 0 {
  1197  		addr := fmt.Sprintf("localhost:%d", defaultRPCPort)
  1198  		cfg.RawRPCListeners = append(cfg.RawRPCListeners, addr)
  1199  	}
  1200  
  1201  	// Listen on localhost if no REST listeners were specified.
  1202  	if len(cfg.RawRESTListeners) == 0 {
  1203  		addr := fmt.Sprintf("localhost:%d", defaultRESTPort)
  1204  		cfg.RawRESTListeners = append(cfg.RawRESTListeners, addr)
  1205  	}
  1206  
  1207  	// Listen on the default interface/port if no listeners were specified.
  1208  	// An empty address string means default interface/address, which on
  1209  	// most unix systems is the same as 0.0.0.0. If Tor is active, we
  1210  	// default to only listening on localhost for hidden service
  1211  	// connections.
  1212  	if len(cfg.RawListeners) == 0 {
  1213  		addr := fmt.Sprintf(":%d", defaultPeerPort)
  1214  		if cfg.Tor.Active && !cfg.Tor.SkipProxyForClearNetTargets {
  1215  			addr = fmt.Sprintf("localhost:%d", defaultPeerPort)
  1216  		}
  1217  		cfg.RawListeners = append(cfg.RawListeners, addr)
  1218  	}
  1219  
  1220  	// Add default port to all RPC listener addresses if needed and remove
  1221  	// duplicate addresses.
  1222  	cfg.RPCListeners, err = lncfg.NormalizeAddresses(
  1223  		cfg.RawRPCListeners, strconv.Itoa(defaultRPCPort),
  1224  		cfg.net.ResolveTCPAddr,
  1225  	)
  1226  	if err != nil {
  1227  		return nil, mkErr("error normalizing RPC listen addrs: %v", err)
  1228  	}
  1229  
  1230  	// Add default port to all REST listener addresses if needed and remove
  1231  	// duplicate addresses.
  1232  	cfg.RESTListeners, err = lncfg.NormalizeAddresses(
  1233  		cfg.RawRESTListeners, strconv.Itoa(defaultRESTPort),
  1234  		cfg.net.ResolveTCPAddr,
  1235  	)
  1236  	if err != nil {
  1237  		return nil, mkErr("error normalizing REST listen addrs: %v", err)
  1238  	}
  1239  
  1240  	switch {
  1241  	// The no seed backup and auto unlock are mutually exclusive.
  1242  	case cfg.NoSeedBackup && cfg.WalletUnlockPasswordFile != "":
  1243  		return nil, mkErr("cannot set noseedbackup and " +
  1244  			"wallet-unlock-password-file at the same time")
  1245  
  1246  	// The "allow-create" flag cannot be set without the auto unlock file.
  1247  	case cfg.WalletUnlockAllowCreate && cfg.WalletUnlockPasswordFile == "":
  1248  		return nil, mkErr("cannot set wallet-unlock-allow-create " +
  1249  			"without wallet-unlock-password-file")
  1250  
  1251  	// If a password file was specified, we need it to exist.
  1252  	case cfg.WalletUnlockPasswordFile != "" &&
  1253  		!lnrpc.FileExists(cfg.WalletUnlockPasswordFile):
  1254  
  1255  		return nil, mkErr("wallet unlock password file %s does "+
  1256  			"not exist", cfg.WalletUnlockPasswordFile)
  1257  	}
  1258  
  1259  	// For each of the RPC listeners (REST+gRPC), we'll ensure that users
  1260  	// have specified a safe combo for authentication. If not, we'll bail
  1261  	// out with an error. Since we don't allow disabling TLS for gRPC
  1262  	// connections we pass in tlsActive=true.
  1263  	err = lncfg.EnforceSafeAuthentication(
  1264  		cfg.RPCListeners, !cfg.NoMacaroons, true,
  1265  	)
  1266  	if err != nil {
  1267  		return nil, mkErr("error enforcing safe authentication on "+
  1268  			"RPC ports: %v", err)
  1269  	}
  1270  
  1271  	if cfg.DisableRest {
  1272  		ltndLog.Infof("REST API is disabled!")
  1273  		cfg.RESTListeners = nil
  1274  	} else {
  1275  		err = lncfg.EnforceSafeAuthentication(
  1276  			cfg.RESTListeners, !cfg.NoMacaroons, !cfg.DisableRestTLS,
  1277  		)
  1278  		if err != nil {
  1279  			return nil, mkErr("error enforcing safe "+
  1280  				"authentication on REST ports: %v", err)
  1281  		}
  1282  	}
  1283  
  1284  	// Remove the listening addresses specified if listening is disabled.
  1285  	if cfg.DisableListen {
  1286  		ltndLog.Infof("Listening on the p2p interface is disabled!")
  1287  		cfg.Listeners = nil
  1288  		cfg.ExternalIPs = nil
  1289  	} else {
  1290  
  1291  		// Add default port to all listener addresses if needed and remove
  1292  		// duplicate addresses.
  1293  		cfg.Listeners, err = lncfg.NormalizeAddresses(
  1294  			cfg.RawListeners, strconv.Itoa(defaultPeerPort),
  1295  			cfg.net.ResolveTCPAddr,
  1296  		)
  1297  		if err != nil {
  1298  			return nil, mkErr("error normalizing p2p listen "+
  1299  				"addrs: %v", err)
  1300  		}
  1301  
  1302  		// Add default port to all external IP addresses if needed and remove
  1303  		// duplicate addresses.
  1304  		cfg.ExternalIPs, err = lncfg.NormalizeAddresses(
  1305  			cfg.RawExternalIPs, strconv.Itoa(defaultPeerPort),
  1306  			cfg.net.ResolveTCPAddr,
  1307  		)
  1308  		if err != nil {
  1309  			return nil, err
  1310  		}
  1311  
  1312  		// For the p2p port it makes no sense to listen to an Unix socket.
  1313  		// Also, we would need to refactor the brontide listener to support
  1314  		// that.
  1315  		for _, p2pListener := range cfg.Listeners {
  1316  			if lncfg.IsUnix(p2pListener) {
  1317  				return nil, mkErr("unix socket addresses "+
  1318  					"cannot be used for the p2p "+
  1319  					"connection listener: %s", p2pListener)
  1320  			}
  1321  		}
  1322  	}
  1323  
  1324  	// Ensure that the specified minimum backoff is below or equal to the
  1325  	// maximum backoff.
  1326  	if cfg.MinBackoff > cfg.MaxBackoff {
  1327  		return nil, mkErr("maxbackoff must be greater than minbackoff")
  1328  	}
  1329  
  1330  	// Newer versions of lnd added a new sub-config for bolt-specific
  1331  	// parameters. However, we want to also allow existing users to use the
  1332  	// value on the top-level config. If the outer config value is set,
  1333  	// then we'll use that directly.
  1334  	flagSet, err := isSet("SyncFreelist")
  1335  	if err != nil {
  1336  		return nil, mkErr("error parsing freelist sync flag: %v", err)
  1337  	}
  1338  	if flagSet {
  1339  		cfg.DB.Bolt.NoFreelistSync = !cfg.SyncFreelist
  1340  	}
  1341  
  1342  	// Ensure that the user hasn't chosen a remote-max-htlc value greater
  1343  	// than the protocol maximum.
  1344  	maxRemoteHtlcs := uint16(input.MaxHTLCNumber / 2)
  1345  	if cfg.DefaultRemoteMaxHtlcs > maxRemoteHtlcs {
  1346  		return nil, mkErr("default-remote-max-htlcs (%v) must be "+
  1347  			"less than %v", cfg.DefaultRemoteMaxHtlcs,
  1348  			maxRemoteHtlcs)
  1349  	}
  1350  
  1351  	// Enforce only bbolt is being used in mainnet for now.
  1352  	if cfg.ActiveNetParams.Net == wire.MainNet && cfg.DB.Backend != lncfg.BoltBackend {
  1353  		return nil, fmt.Errorf("Cannot use DB backend %q in mainnet",
  1354  			cfg.DB.Backend)
  1355  	}
  1356  
  1357  	// Enforce anchors are not used in mainnet.
  1358  	if cfg.ActiveNetParams.Net == wire.MainNet && !cfg.ProtocolOptions.NoAnchorCommitments() {
  1359  		return nil, fmt.Errorf("cannot use anchor commitments on mainnet")
  1360  	}
  1361  
  1362  	if err := cfg.Gossip.Parse(); err != nil {
  1363  		return nil, mkErr("error parsing gossip syncer: %v", err)
  1364  	}
  1365  
  1366  	// Log a warning if our expiry delta is not greater than our incoming
  1367  	// broadcast delta. We do not fail here because this value may be set
  1368  	// to zero to intentionally keep lnd's behavior unchanged from when we
  1369  	// didn't auto-cancel these invoices.
  1370  	if cfg.Invoices.HoldExpiryDelta <= lncfg.DefaultIncomingBroadcastDelta {
  1371  		ltndLog.Warnf("Invoice hold expiry delta: %v <= incoming "+
  1372  			"delta: %v, accepted hold invoices will force close "+
  1373  			"channels if they are not canceled manually",
  1374  			cfg.Invoices.HoldExpiryDelta,
  1375  			lncfg.DefaultIncomingBroadcastDelta)
  1376  	}
  1377  
  1378  	// Validate the subconfigs for workers, caches, and the tower client.
  1379  	err = lncfg.Validate(
  1380  		cfg.Workers,
  1381  		cfg.Caches,
  1382  		cfg.WtClient,
  1383  		cfg.DB,
  1384  		cfg.Cluster,
  1385  		cfg.HealthChecks,
  1386  		cfg.RPCMiddleware,
  1387  	)
  1388  	if err != nil {
  1389  		return nil, err
  1390  	}
  1391  
  1392  	// Finally, ensure that the user's color is correctly formatted,
  1393  	// otherwise the server will not be able to start after the unlocking
  1394  	// the wallet.
  1395  	_, err = parseHexColor(cfg.Color)
  1396  	if err != nil {
  1397  		return nil, mkErr("unable to parse node color: %v", err)
  1398  	}
  1399  
  1400  	// All good, return the sanitized result.
  1401  	return &cfg, nil
  1402  }
  1403  
  1404  // graphDatabaseDir returns the default directory where the local bolt graph db
  1405  // files are stored.
  1406  func (c *Config) graphDatabaseDir() string {
  1407  	return filepath.Join(
  1408  		c.DataDir, defaultGraphSubDirname,
  1409  		lncfg.NormalizeNetwork(c.ActiveNetParams.Name),
  1410  	)
  1411  }
  1412  
  1413  // ImplementationConfig returns the configuration of what actual implementations
  1414  // should be used when creating the main lnd instance.
  1415  func (c *Config) ImplementationConfig(
  1416  	interceptor signal.Interceptor) *ImplementationCfg {
  1417  
  1418  	defaultImpl := NewDefaultWalletImpl(c, ltndLog, interceptor)
  1419  
  1420  	// Switch to remote wallet mode if needed.
  1421  	var chainCC ChainControlBuilder = defaultImpl
  1422  	if c.Dcrwallet.GRPCHost != "" && c.Dcrwallet.CertPath != "" {
  1423  		chainCC = &RemoteWalletBuilder{logger: ltndLog}
  1424  	}
  1425  
  1426  	return &ImplementationCfg{
  1427  		GrpcRegistrar:       defaultImpl,
  1428  		RestRegistrar:       defaultImpl,
  1429  		ExternalValidator:   defaultImpl,
  1430  		DatabaseBuilder:     NewDefaultDatabaseBuilder(c, ltndLog),
  1431  		WalletConfigBuilder: defaultImpl,
  1432  		ChainControlBuilder: chainCC,
  1433  	}
  1434  }
  1435  
  1436  // CleanAndExpandPath expands environment variables and leading ~ in the
  1437  // passed path, cleans the result, and returns it.
  1438  // This function is taken from https://github.com/decred/dcrd
  1439  func CleanAndExpandPath(path string) string {
  1440  	if path == "" {
  1441  		return ""
  1442  	}
  1443  
  1444  	// Expand initial ~ to OS specific home directory.
  1445  	if strings.HasPrefix(path, "~") {
  1446  		var homeDir string
  1447  		u, err := user.Current()
  1448  		if err == nil {
  1449  			homeDir = u.HomeDir
  1450  		} else {
  1451  			homeDir = os.Getenv("HOME")
  1452  		}
  1453  
  1454  		path = strings.Replace(path, "~", homeDir, 1)
  1455  	}
  1456  
  1457  	// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
  1458  	// but the variables can still be expanded via POSIX-style $VARIABLE.
  1459  	return filepath.Clean(os.ExpandEnv(path))
  1460  }
  1461  
  1462  func parseRPCParams(cConfig *lncfg.Chain, nodeConfig interface{},
  1463  	net chainreg.ChainCode, netParams chainreg.DecredNetParams) error {
  1464  
  1465  	// First, we'll check our node config to make sure the RPC parameters
  1466  	// were set correctly. We'll also determine the path to the conf file
  1467  	// depending on the backend node.
  1468  	var daemonName, confDir, confFile string
  1469  	switch conf := nodeConfig.(type) {
  1470  	case *lncfg.DcrdConfig:
  1471  		// If both RPCUser and RPCPass are set, we assume those
  1472  		// credentials are good to use.
  1473  		if conf.RPCUser != "" && conf.RPCPass != "" {
  1474  			return nil
  1475  		}
  1476  
  1477  		// Get the daemon name for displaying proper errors.
  1478  		switch net {
  1479  		case chainreg.DecredChain:
  1480  			daemonName = "dcrd"
  1481  			confFile = "dcrd"
  1482  		}
  1483  
  1484  		// If only ONE of RPCUser or RPCPass is set, we assume the
  1485  		// user did that unintentionally.
  1486  		if conf.RPCUser != "" || conf.RPCPass != "" {
  1487  			return fmt.Errorf("please set both or neither of "+
  1488  				"%[1]v.rpcuser, %[1]v.rpcpass", daemonName)
  1489  		}
  1490  	}
  1491  
  1492  	// If we're in simnet mode, then the running dcrd instance won't read
  1493  	// the RPC credentials from the configuration. So if lnd wasn't
  1494  	// specified the parameters, then we won't be able to start.
  1495  	if cConfig.SimNet {
  1496  		return fmt.Errorf("rpcuser and rpcpass must be set to your " +
  1497  			"dcrd node's RPC parameters for simnet mode")
  1498  	}
  1499  
  1500  	fmt.Println("Attempting automatic RPC configuration to " + daemonName)
  1501  
  1502  	confFile = filepath.Join(confDir, fmt.Sprintf("%v.conf", confFile))
  1503  	switch cConfig.Node {
  1504  	case "dcrd":
  1505  		nConf := nodeConfig.(*lncfg.DcrdConfig)
  1506  		rpcUser, rpcPass, err := extractDcrdRPCParams(confFile)
  1507  		if err != nil {
  1508  			return fmt.Errorf("unable to extract RPC credentials: "+
  1509  				"%v, cannot start w/o RPC connection", err)
  1510  		}
  1511  		nConf.RPCUser, nConf.RPCPass = rpcUser, rpcPass
  1512  	}
  1513  
  1514  	fmt.Printf("Automatically obtained %v's RPC credentials\n", daemonName)
  1515  	return nil
  1516  }
  1517  
  1518  // extractDcrdRPCParams attempts to extract the RPC credentials for an existing
  1519  // dcrd instance. The passed path is expected to be the location of dcrd's
  1520  // application data directory on the target system.
  1521  func extractDcrdRPCParams(dcrdConfigPath string) (string, string, error) {
  1522  	// First, we'll open up the dcrd configuration file found at the target
  1523  	// destination.
  1524  	dcrdConfigFile, err := os.Open(dcrdConfigPath)
  1525  	if err != nil {
  1526  		return "", "", err
  1527  	}
  1528  	defer dcrdConfigFile.Close()
  1529  
  1530  	// With the file open extract the contents of the configuration file so
  1531  	// we can attempt to locate the RPC credentials.
  1532  	configContents, err := ioutil.ReadAll(dcrdConfigFile)
  1533  	if err != nil {
  1534  		return "", "", err
  1535  	}
  1536  
  1537  	// Attempt to locate the RPC user using a regular expression. If we
  1538  	// don't have a match for our regular expression then we'll exit with
  1539  	// an error.
  1540  	rpcUserRegexp, err := regexp.Compile(`(?m)^\s*rpcuser\s*=\s*([^\s]+)`)
  1541  	if err != nil {
  1542  		return "", "", err
  1543  	}
  1544  	userSubmatches := rpcUserRegexp.FindSubmatch(configContents)
  1545  	if userSubmatches == nil {
  1546  		return "", "", fmt.Errorf("unable to find rpcuser in config")
  1547  	}
  1548  
  1549  	// Similarly, we'll use another regular expression to find the set
  1550  	// rpcpass (if any). If we can't find the pass, then we'll exit with an
  1551  	// error.
  1552  	rpcPassRegexp, err := regexp.Compile(`(?m)^\s*rpcpass\s*=\s*([^\s]+)`)
  1553  	if err != nil {
  1554  		return "", "", err
  1555  	}
  1556  	passSubmatches := rpcPassRegexp.FindSubmatch(configContents)
  1557  	if passSubmatches == nil {
  1558  		return "", "", fmt.Errorf("unable to find rpcuser in config")
  1559  	}
  1560  
  1561  	return string(userSubmatches[1]), string(passSubmatches[1]), nil
  1562  }