github.com/lbryio/lbcd@v0.22.119/config.go (about)

     1  // Copyright (c) 2013-2017 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"bufio"
     9  	"crypto/rand"
    10  	_ "embed"
    11  	"encoding/base64"
    12  	"encoding/hex"
    13  	"errors"
    14  	"fmt"
    15  	"io"
    16  	"net"
    17  	"os"
    18  	"path/filepath"
    19  	"runtime"
    20  	"sort"
    21  	"strconv"
    22  	"strings"
    23  	"time"
    24  
    25  	"github.com/btcsuite/go-socks/socks"
    26  	flags "github.com/jessevdk/go-flags"
    27  	"github.com/lbryio/lbcd/blockchain"
    28  	"github.com/lbryio/lbcd/chaincfg"
    29  	"github.com/lbryio/lbcd/chaincfg/chainhash"
    30  	"github.com/lbryio/lbcd/connmgr"
    31  	"github.com/lbryio/lbcd/database"
    32  	_ "github.com/lbryio/lbcd/database/ffldb"
    33  	"github.com/lbryio/lbcd/mempool"
    34  	"github.com/lbryio/lbcd/peer"
    35  	"github.com/lbryio/lbcd/version"
    36  	"github.com/lbryio/lbcd/wire"
    37  	btcutil "github.com/lbryio/lbcutil"
    38  )
    39  
    40  const (
    41  	defaultConfigFilename        = "lbcd.conf"
    42  	defaultDataDirname           = "data"
    43  	defaultLogLevel              = "info"
    44  	defaultLogDirname            = "logs"
    45  	defaultLogFilename           = "lbcd.log"
    46  	defaultMaxPeers              = 125
    47  	defaultBanDuration           = time.Hour * 24
    48  	defaultBanThreshold          = 100
    49  	defaultConnectTimeout        = time.Second * 30
    50  	defaultMaxRPCClients         = 10
    51  	defaultMaxRPCWebsockets      = 25
    52  	defaultMaxRPCConcurrentReqs  = 20
    53  	defaultDbType                = "ffldb"
    54  	defaultFreeTxRelayLimit      = 15.0
    55  	defaultTrickleInterval       = peer.DefaultTrickleInterval
    56  	defaultBlockMinSize          = 0
    57  	defaultBlockMaxSize          = 750000
    58  	defaultBlockMinWeight        = 0
    59  	defaultBlockMaxWeight        = 3000000
    60  	blockMaxSizeMin              = 1000
    61  	blockMaxSizeMax              = blockchain.MaxBlockBaseSize - 1000
    62  	blockMaxWeightMin            = 4000
    63  	blockMaxWeightMax            = blockchain.MaxBlockWeight - 4000
    64  	defaultGenerate              = false
    65  	defaultMaxOrphanTransactions = 100
    66  	defaultMaxOrphanTxSize       = 100000
    67  	defaultSigCacheMaxSize       = 100000
    68  	sampleConfigFilename         = "sample-lbcd.conf"
    69  	defaultTxIndex               = true
    70  	defaultAddrIndex             = false
    71  	defaultUpnp                  = true
    72  )
    73  
    74  var (
    75  	defaultHomeDir     = btcutil.AppDataDir("lbcd", false)
    76  	defaultConfigFile  = filepath.Join(defaultHomeDir, defaultConfigFilename)
    77  	defaultDataDir     = filepath.Join(defaultHomeDir, defaultDataDirname)
    78  	knownDbTypes       = database.SupportedDrivers()
    79  	defaultRPCKeyFile  = filepath.Join(defaultHomeDir, "rpc.key")
    80  	defaultRPCCertFile = filepath.Join(defaultHomeDir, "rpc.cert")
    81  	defaultLogDir      = filepath.Join(defaultHomeDir, defaultLogDirname)
    82  )
    83  
    84  //go:embed sample-lbcd.conf
    85  var sampleConfig string
    86  
    87  // runServiceCommand is only set to a real function on Windows.  It is used
    88  // to parse and execute service commands specified via the -s flag.
    89  var runServiceCommand func(string) error
    90  
    91  // minUint32 is a helper function to return the minimum of two uint32s.
    92  // This avoids a math import and the need to cast to floats.
    93  func minUint32(a, b uint32) uint32 {
    94  	if a < b {
    95  		return a
    96  	}
    97  	return b
    98  }
    99  
   100  // config defines the configuration options for btcd.
   101  //
   102  // See loadConfig for details on the configuration load process.
   103  type config struct {
   104  	AddCheckpoints       []string      `long:"addcheckpoint" description:"Add a custom checkpoint.  Format: '<height>:<hash>'"`
   105  	AddPeers             []string      `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"`
   106  	AddrIndex            bool          `long:"addrindex" description:"Maintain a full address-based transaction index which makes the searchrawtransactions RPC available"`
   107  	AgentBlacklist       []string      `long:"agentblacklist" description:"A comma separated list of user-agent substrings which will cause lbcd to reject any peers whose user-agent contains any of the blacklisted substrings."`
   108  	AgentWhitelist       []string      `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause lbcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the whitelist, and an empty whitelist will allow all agents that do not fail the blacklist."`
   109  	BanDuration          time.Duration `long:"banduration" description:"How long to ban misbehaving peers.  Valid time units are {s, m, h}.  Minimum 1 second"`
   110  	BanThreshold         uint32        `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."`
   111  	BlockMaxSize         uint32        `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"`
   112  	BlockMinSize         uint32        `long:"blockminsize" description:"Mininum block size in bytes to be used when creating a block"`
   113  	BlockMaxWeight       uint32        `long:"blockmaxweight" description:"Maximum block weight to be used when creating a block"`
   114  	BlockMinWeight       uint32        `long:"blockminweight" description:"Mininum block weight to be used when creating a block"`
   115  	BlockPrioritySize    uint32        `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"`
   116  	BlocksOnly           bool          `long:"blocksonly" description:"Do not accept transactions from remote peers."`
   117  	ConfigFile           string        `short:"C" long:"configfile" description:"Path to configuration file"`
   118  	ConnectPeers         []string      `long:"connect" description:"Connect only to the specified peers at startup"`
   119  	CPUProfile           string        `long:"cpuprofile" description:"Write CPU profile to the specified file"`
   120  	MemProfile           string        `long:"memprofile" description:"Write memory profile to the specified file"`
   121  	DataDir              string        `short:"b" long:"datadir" description:"Directory to store data"`
   122  	DbType               string        `long:"dbtype" description:"Database backend to use for the Block Chain"`
   123  	DebugLevel           string        `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems"`
   124  	DropAddrIndex        bool          `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up and then exits."`
   125  	DropCfIndex          bool          `long:"dropcfindex" description:"Deletes the index used for committed filtering (CF) support from the database on start up and then exits."`
   126  	DropTxIndex          bool          `long:"droptxindex" description:"Deletes the hash-based transaction index from the database on start up and then exits."`
   127  	ExternalIPs          []string      `long:"externalip" description:"Add an ip to the list of local addresses we claim to listen on to peers"`
   128  	Generate             bool          `long:"generate" description:"Generate (mine) bitcoins using the CPU"`
   129  	FreeTxRelayLimit     float64       `long:"limitfreerelay" description:"Limit relay of transactions with no transaction fee to the given amount in thousands of bytes per minute"`
   130  	Listeners            []string      `long:"listen" description:"Add an interface/port to listen for connections (default all interfaces port: 9246, testnet: 19246, regtest: 29246)"`
   131  	LogDir               string        `long:"logdir" description:"Directory to log output."`
   132  	MaxOrphanTxs         int           `long:"maxorphantx" description:"Max number of orphan transactions to keep in memory"`
   133  	MaxPeers             int           `long:"maxpeers" description:"Max number of inbound and outbound peers"`
   134  	MiningAddrs          []string      `long:"miningaddr" description:"Add the specified payment address to the list of addresses to use for generated blocks -- At least one address is required if the generate option is set"`
   135  	MinRelayTxFee        float64       `long:"minrelaytxfee" description:"The minimum transaction fee in LBC/kB to be considered a non-zero fee."`
   136  	DisableBanning       bool          `long:"nobanning" description:"Disable banning of misbehaving peers"`
   137  	NoCFilters           bool          `long:"nocfilters" description:"Disable committed filtering (CF) support"`
   138  	DisableCheckpoints   bool          `long:"nocheckpoints" description:"Disable built-in checkpoints.  Don't do this unless you know what you're doing."`
   139  	DisableDNSSeed       bool          `long:"nodnsseed" description:"Disable DNS seeding for peers"`
   140  	DisableListen        bool          `long:"nolisten" description:"Disable listening for incoming connections -- NOTE: Listening is automatically disabled if the --connect or --proxy options are used without also specifying listen interfaces via --listen"`
   141  	NoOnion              bool          `long:"noonion" description:"Disable connecting to tor hidden services"`
   142  	NoPeerBloomFilters   bool          `long:"nopeerbloomfilters" description:"Disable bloom filtering support"`
   143  	NoRelayPriority      bool          `long:"norelaypriority" description:"Do not require free or low-fee transactions to have high priority for relaying"`
   144  	NoWinService         bool          `long:"nowinservice" description:"Do not start as a background service on Windows -- NOTE: This flag only works on the command line, not in the config file"`
   145  	DisableRPC           bool          `long:"norpc" description:"Disable built-in RPC server -- NOTE: The RPC server is disabled by default if no rpcuser/rpcpass or rpclimituser/rpclimitpass is specified"`
   146  	DisableStallHandler  bool          `long:"nostalldetect" description:"Disables the stall handler system for each peer, useful in simnet/regtest integration tests frameworks"`
   147  	DisableTLS           bool          `long:"notls" description:"Disable TLS for the RPC server -- NOTE: This is only allowed if the RPC server is bound to localhost"`
   148  	OnionProxy           string        `long:"onion" description:"Connect to tor hidden services via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
   149  	OnionProxyPass       string        `long:"onionpass" default-mask:"-" description:"Password for onion proxy server"`
   150  	OnionProxyUser       string        `long:"onionuser" description:"Username for onion proxy server"`
   151  	Profile              string        `long:"profile" description:"Enable HTTP profiling on given port -- NOTE port must be between 1024 and 65536"`
   152  	Proxy                string        `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
   153  	ProxyPass            string        `long:"proxypass" default-mask:"-" description:"Password for proxy server"`
   154  	ProxyUser            string        `long:"proxyuser" description:"Username for proxy server"`
   155  	RegressionTest       bool          `long:"regtest" description:"Use the regression test network"`
   156  	RejectNonStd         bool          `long:"rejectnonstd" description:"Reject non-standard transactions regardless of the default settings for the active network."`
   157  	RejectReplacement    bool          `long:"rejectreplacement" description:"Reject transactions that attempt to replace existing transactions within the mempool through the Replace-By-Fee (RBF) signaling policy."`
   158  	RelayNonStd          bool          `long:"relaynonstd" description:"Relay non-standard transactions regardless of the default settings for the active network."`
   159  	RPCCert              string        `long:"rpccert" description:"File containing the certificate file"`
   160  	RPCKey               string        `long:"rpckey" description:"File containing the certificate key"`
   161  	RPCLimitPass         string        `long:"rpclimitpass" default-mask:"-" description:"Password for limited RPC connections"`
   162  	RPCLimitUser         string        `long:"rpclimituser" description:"Username for limited RPC connections"`
   163  	RPCListeners         []string      `long:"rpclisten" description:"Add an interface/port to listen for RPC connections (default port: 9245, testnet: 19245, regtest: 29245)"`
   164  	RPCMaxClients        int           `long:"rpcmaxclients" description:"Max number of RPC clients for standard connections"`
   165  	RPCMaxConcurrentReqs int           `long:"rpcmaxconcurrentreqs" description:"Max number of concurrent RPC requests that may be processed concurrently"`
   166  	RPCMaxWebsockets     int           `long:"rpcmaxwebsockets" description:"Max number of RPC websocket connections"`
   167  	RPCQuirks            bool          `long:"rpcquirks" description:"Mirror some JSON-RPC quirks of Bitcoin Core -- NOTE: Discouraged unless interoperability issues need to be worked around"`
   168  	RPCPass              string        `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
   169  	RPCUser              string        `short:"u" long:"rpcuser" description:"Username for RPC connections"`
   170  	SigCacheMaxSize      uint          `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"`
   171  	SimNet               bool          `long:"simnet" description:"Use the simulation test network"`
   172  	SigNet               bool          `long:"signet" description:"Use the signet test network"`
   173  	SigNetChallenge      string        `long:"signetchallenge" description:"Connect to a custom signet network defined by this challenge instead of using the global default signet test network -- Can be specified multiple times"`
   174  	SigNetSeedNode       []string      `long:"signetseednode" description:"Specify a seed node for the signet network instead of using the global default signet network seed nodes"`
   175  	TestNet3             bool          `long:"testnet" description:"Use the test network"`
   176  	TorIsolation         bool          `long:"torisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."`
   177  	TrickleInterval      time.Duration `long:"trickleinterval" description:"Minimum time between attempts to send new inventory to a connected peer"`
   178  	TxIndex              bool          `long:"txindex" description:"Maintain a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"`
   179  	UserAgentComments    []string      `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."`
   180  	Upnp                 bool          `long:"upnp" description:"Use UPnP to map our listening port outside of NAT"`
   181  	ShowVersion          bool          `short:"V" long:"version" description:"Display version information and exit"`
   182  	Whitelists           []string      `long:"whitelist" description:"Add an IP network or IP that will not be banned. (eg. 192.168.1.0/24 or ::1)"`
   183  	lookup               func(string) ([]net.IP, error)
   184  	oniondial            func(string, string, time.Duration) (net.Conn, error)
   185  	dial                 func(string, string, time.Duration) (net.Conn, error)
   186  	addCheckpoints       []chaincfg.Checkpoint
   187  	miningAddrs          []btcutil.Address
   188  	minRelayTxFee        btcutil.Amount
   189  	whitelists           []*net.IPNet
   190  }
   191  
   192  // serviceOptions defines the configuration options for the daemon as a service on
   193  // Windows.
   194  type serviceOptions struct {
   195  	ServiceCommand string `short:"s" long:"service" description:"Service command {install, remove, start, stop}"`
   196  }
   197  
   198  // cleanAndExpandPath expands environment variables and leading ~ in the
   199  // passed path, cleans the result, and returns it.
   200  func cleanAndExpandPath(path string) string {
   201  	// Expand initial ~ to OS specific home directory.
   202  	if strings.HasPrefix(path, "~") {
   203  		homeDir := filepath.Dir(defaultHomeDir)
   204  		path = strings.Replace(path, "~", homeDir, 1)
   205  	}
   206  
   207  	// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
   208  	// but they variables can still be expanded via POSIX-style $VARIABLE.
   209  	return filepath.Clean(os.ExpandEnv(path))
   210  }
   211  
   212  // validLogLevel returns whether or not logLevel is a valid debug log level.
   213  func validLogLevel(logLevel string) bool {
   214  	switch logLevel {
   215  	case "trace":
   216  		fallthrough
   217  	case "debug":
   218  		fallthrough
   219  	case "info":
   220  		fallthrough
   221  	case "warn":
   222  		fallthrough
   223  	case "error":
   224  		fallthrough
   225  	case "critical":
   226  		return true
   227  	}
   228  	return false
   229  }
   230  
   231  // supportedSubsystems returns a sorted slice of the supported subsystems for
   232  // logging purposes.
   233  func supportedSubsystems() []string {
   234  	// Convert the subsystemLoggers map keys to a slice.
   235  	subsystems := make([]string, 0, len(subsystemLoggers))
   236  	for subsysID := range subsystemLoggers {
   237  		subsystems = append(subsystems, subsysID)
   238  	}
   239  
   240  	// Sort the subsystems for stable display.
   241  	sort.Strings(subsystems)
   242  	return subsystems
   243  }
   244  
   245  // parseAndSetDebugLevels attempts to parse the specified debug level and set
   246  // the levels accordingly.  An appropriate error is returned if anything is
   247  // invalid.
   248  func parseAndSetDebugLevels(debugLevel string) error {
   249  	// When the specified string doesn't have any delimters, treat it as
   250  	// the log level for all subsystems.
   251  	if !strings.Contains(debugLevel, ",") && !strings.Contains(debugLevel, "=") {
   252  		// Validate debug log level.
   253  		if !validLogLevel(debugLevel) {
   254  			str := "The specified debug level [%v] is invalid"
   255  			return fmt.Errorf(str, debugLevel)
   256  		}
   257  
   258  		// Change the logging level for all subsystems.
   259  		setLogLevels(debugLevel)
   260  
   261  		return nil
   262  	}
   263  
   264  	// Split the specified string into subsystem/level pairs while detecting
   265  	// issues and update the log levels accordingly.
   266  	for _, logLevelPair := range strings.Split(debugLevel, ",") {
   267  		if !strings.Contains(logLevelPair, "=") {
   268  			str := "The specified debug level contains an invalid " +
   269  				"subsystem/level pair [%v]"
   270  			return fmt.Errorf(str, logLevelPair)
   271  		}
   272  
   273  		// Extract the specified subsystem and log level.
   274  		fields := strings.Split(logLevelPair, "=")
   275  		subsysID, logLevel := fields[0], fields[1]
   276  
   277  		// Validate subsystem.
   278  		if _, exists := subsystemLoggers[subsysID]; !exists {
   279  			str := "The specified subsystem [%v] is invalid -- " +
   280  				"supported subsytems %v"
   281  			return fmt.Errorf(str, subsysID, supportedSubsystems())
   282  		}
   283  
   284  		// Validate log level.
   285  		if !validLogLevel(logLevel) {
   286  			str := "The specified debug level [%v] is invalid"
   287  			return fmt.Errorf(str, logLevel)
   288  		}
   289  
   290  		setLogLevel(subsysID, logLevel)
   291  	}
   292  
   293  	return nil
   294  }
   295  
   296  // validDbType returns whether or not dbType is a supported database type.
   297  func validDbType(dbType string) bool {
   298  	for _, knownType := range knownDbTypes {
   299  		if dbType == knownType {
   300  			return true
   301  		}
   302  	}
   303  
   304  	return false
   305  }
   306  
   307  // removeDuplicateAddresses returns a new slice with all duplicate entries in
   308  // addrs removed.
   309  func removeDuplicateAddresses(addrs []string) []string {
   310  	result := make([]string, 0, len(addrs))
   311  	seen := map[string]struct{}{}
   312  	for _, val := range addrs {
   313  		if _, ok := seen[val]; !ok {
   314  			result = append(result, val)
   315  			seen[val] = struct{}{}
   316  		}
   317  	}
   318  	return result
   319  }
   320  
   321  // normalizeAddress returns addr with the passed default port appended if
   322  // there is not already a port specified.
   323  func normalizeAddress(addr, defaultPort string) string {
   324  	_, _, err := net.SplitHostPort(addr)
   325  	if err != nil {
   326  		return net.JoinHostPort(addr, defaultPort)
   327  	}
   328  	return addr
   329  }
   330  
   331  // normalizeAddresses returns a new slice with all the passed peer addresses
   332  // normalized with the given default port, and all duplicates removed.
   333  func normalizeAddresses(addrs []string, defaultPort string) []string {
   334  	for i, addr := range addrs {
   335  		addrs[i] = normalizeAddress(addr, defaultPort)
   336  	}
   337  
   338  	return removeDuplicateAddresses(addrs)
   339  }
   340  
   341  // newCheckpointFromStr parses checkpoints in the '<height>:<hash>' format.
   342  func newCheckpointFromStr(checkpoint string) (chaincfg.Checkpoint, error) {
   343  	parts := strings.Split(checkpoint, ":")
   344  	if len(parts) != 2 {
   345  		return chaincfg.Checkpoint{}, fmt.Errorf("unable to parse "+
   346  			"checkpoint %q -- use the syntax <height>:<hash>",
   347  			checkpoint)
   348  	}
   349  
   350  	height, err := strconv.ParseInt(parts[0], 10, 32)
   351  	if err != nil {
   352  		return chaincfg.Checkpoint{}, fmt.Errorf("unable to parse "+
   353  			"checkpoint %q due to malformed height", checkpoint)
   354  	}
   355  
   356  	if len(parts[1]) == 0 {
   357  		return chaincfg.Checkpoint{}, fmt.Errorf("unable to parse "+
   358  			"checkpoint %q due to missing hash", checkpoint)
   359  	}
   360  	hash, err := chainhash.NewHashFromStr(parts[1])
   361  	if err != nil {
   362  		return chaincfg.Checkpoint{}, fmt.Errorf("unable to parse "+
   363  			"checkpoint %q due to malformed hash", checkpoint)
   364  	}
   365  
   366  	return chaincfg.Checkpoint{
   367  		Height: int32(height),
   368  		Hash:   hash,
   369  	}, nil
   370  }
   371  
   372  // parseCheckpoints checks the checkpoint strings for valid syntax
   373  // ('<height>:<hash>') and parses them to chaincfg.Checkpoint instances.
   374  func parseCheckpoints(checkpointStrings []string) ([]chaincfg.Checkpoint, error) {
   375  	if len(checkpointStrings) == 0 {
   376  		return nil, nil
   377  	}
   378  	checkpoints := make([]chaincfg.Checkpoint, len(checkpointStrings))
   379  	for i, cpString := range checkpointStrings {
   380  		checkpoint, err := newCheckpointFromStr(cpString)
   381  		if err != nil {
   382  			return nil, err
   383  		}
   384  		checkpoints[i] = checkpoint
   385  	}
   386  	return checkpoints, nil
   387  }
   388  
   389  // filesExists reports whether the named file or directory exists.
   390  func fileExists(name string) bool {
   391  	if _, err := os.Stat(name); err != nil {
   392  		if os.IsNotExist(err) {
   393  			return false
   394  		}
   395  	}
   396  	return true
   397  }
   398  
   399  // newConfigParser returns a new command line flags parser.
   400  func newConfigParser(cfg *config, so *serviceOptions, options flags.Options) *flags.Parser {
   401  	parser := flags.NewParser(cfg, options)
   402  	if runtime.GOOS == "windows" {
   403  		parser.AddGroup("Service Options", "Service Options", so)
   404  	}
   405  	return parser
   406  }
   407  
   408  // loadConfig initializes and parses the config using a config file and command
   409  // line options.
   410  //
   411  // The configuration proceeds as follows:
   412  //  1. Start with a default config with sane settings
   413  //  2. Pre-parse the command line to check for an alternative config file
   414  //  3. Load configuration file overwriting defaults with any specified options
   415  //  4. Parse CLI options and overwrite/add any specified options
   416  //
   417  // The above results in lbcd functioning properly without any config settings
   418  // while still allowing the user to override settings with config files and
   419  // command line options.  Command line options always take precedence.
   420  func loadConfig() (*config, []string, error) {
   421  	// Default config.
   422  	cfg := config{
   423  		ConfigFile:           defaultConfigFile,
   424  		DebugLevel:           defaultLogLevel,
   425  		MaxPeers:             defaultMaxPeers,
   426  		BanDuration:          defaultBanDuration,
   427  		BanThreshold:         defaultBanThreshold,
   428  		RPCMaxClients:        defaultMaxRPCClients,
   429  		RPCMaxWebsockets:     defaultMaxRPCWebsockets,
   430  		RPCMaxConcurrentReqs: defaultMaxRPCConcurrentReqs,
   431  		DataDir:              defaultDataDir,
   432  		LogDir:               defaultLogDir,
   433  		DbType:               defaultDbType,
   434  		RPCKey:               defaultRPCKeyFile,
   435  		RPCCert:              defaultRPCCertFile,
   436  		MinRelayTxFee:        mempool.DefaultMinRelayTxFee.ToBTC(),
   437  		FreeTxRelayLimit:     defaultFreeTxRelayLimit,
   438  		TrickleInterval:      defaultTrickleInterval,
   439  		BlockMinSize:         defaultBlockMinSize,
   440  		BlockMaxSize:         defaultBlockMaxSize,
   441  		BlockMinWeight:       defaultBlockMinWeight,
   442  		BlockMaxWeight:       defaultBlockMaxWeight,
   443  		BlockPrioritySize:    mempool.DefaultBlockPrioritySize,
   444  		MaxOrphanTxs:         defaultMaxOrphanTransactions,
   445  		SigCacheMaxSize:      defaultSigCacheMaxSize,
   446  		Generate:             defaultGenerate,
   447  		TxIndex:              defaultTxIndex,
   448  		AddrIndex:            defaultAddrIndex,
   449  		Upnp:                 defaultUpnp,
   450  	}
   451  
   452  	// Service options which are only added on Windows.
   453  	serviceOpts := serviceOptions{}
   454  
   455  	// Pre-parse the command line options to see if an alternative config
   456  	// file or the version flag was specified.  Any errors aside from the
   457  	// help message error can be ignored here since they will be caught by
   458  	// the final parse below.
   459  	preCfg := cfg
   460  	preParser := newConfigParser(&preCfg, &serviceOpts, flags.HelpFlag)
   461  	_, err := preParser.Parse()
   462  	if err != nil {
   463  		if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
   464  			fmt.Fprintln(os.Stderr, err)
   465  			return nil, nil, err
   466  		}
   467  	}
   468  
   469  	// Show the version and exit if the version flag was specified.
   470  	appName := filepath.Base(os.Args[0])
   471  	appName = strings.TrimSuffix(appName, filepath.Ext(appName))
   472  	usageMessage := fmt.Sprintf("Use %s -h to show usage", appName)
   473  	if preCfg.ShowVersion {
   474  		fmt.Println(appName, "version", version.Full())
   475  		os.Exit(0)
   476  	}
   477  
   478  	// Perform service command and exit if specified.  Invalid service
   479  	// commands show an appropriate error.  Only runs on Windows since
   480  	// the runServiceCommand function will be nil when not on Windows.
   481  	if serviceOpts.ServiceCommand != "" && runServiceCommand != nil {
   482  		err := runServiceCommand(serviceOpts.ServiceCommand)
   483  		if err != nil {
   484  			fmt.Fprintln(os.Stderr, err)
   485  		}
   486  		os.Exit(0)
   487  	}
   488  
   489  	// Load additional config from file.
   490  	var configFileError error
   491  	parser := newConfigParser(&cfg, &serviceOpts, flags.Default)
   492  	if !(preCfg.RegressionTest || preCfg.SimNet || preCfg.SigNet) ||
   493  		preCfg.ConfigFile != defaultConfigFile {
   494  
   495  		if _, err := os.Stat(preCfg.ConfigFile); os.IsNotExist(err) {
   496  			err := createDefaultConfigFile(preCfg.ConfigFile)
   497  			if err != nil {
   498  				fmt.Fprintf(os.Stderr, "Error creating a "+
   499  					"default config file: %v\n", err)
   500  			}
   501  		}
   502  
   503  		err := flags.NewIniParser(parser).ParseFile(preCfg.ConfigFile)
   504  		if err != nil {
   505  			if _, ok := err.(*os.PathError); !ok {
   506  				fmt.Fprintf(os.Stderr, "Error parsing config "+
   507  					"file: %v\n", err)
   508  				fmt.Fprintln(os.Stderr, usageMessage)
   509  				return nil, nil, err
   510  			}
   511  			configFileError = err
   512  		}
   513  	}
   514  
   515  	// Don't add peers from the config file when in regression test mode.
   516  	if preCfg.RegressionTest && len(cfg.AddPeers) > 0 {
   517  		cfg.AddPeers = nil
   518  	}
   519  
   520  	// Parse command line options again to ensure they take precedence.
   521  	remainingArgs, err := parser.Parse()
   522  	if err != nil {
   523  		if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
   524  			fmt.Fprintln(os.Stderr, usageMessage)
   525  		}
   526  		return nil, nil, err
   527  	}
   528  
   529  	// Create the home directory if it doesn't already exist.
   530  	funcName := "loadConfig"
   531  	err = os.MkdirAll(defaultHomeDir, 0700)
   532  	if err != nil {
   533  		// Show a nicer error message if it's because a symlink is
   534  		// linked to a directory that does not exist (probably because
   535  		// it's not mounted).
   536  		if e, ok := err.(*os.PathError); ok && os.IsExist(err) {
   537  			if link, lerr := os.Readlink(e.Path); lerr == nil {
   538  				str := "is symlink %s -> %s mounted?"
   539  				err = fmt.Errorf(str, e.Path, link)
   540  			}
   541  		}
   542  
   543  		str := "%s: Failed to create home directory: %v"
   544  		err := fmt.Errorf(str, funcName, err)
   545  		fmt.Fprintln(os.Stderr, err)
   546  		return nil, nil, err
   547  	}
   548  
   549  	// Multiple networks can't be selected simultaneously.
   550  	numNets := 0
   551  	// Count number of network flags passed; assign active network params
   552  	// while we're at it
   553  	if cfg.TestNet3 {
   554  		numNets++
   555  		activeNetParams = &testNet3Params
   556  	}
   557  	if cfg.RegressionTest {
   558  		numNets++
   559  		activeNetParams = &regressionNetParams
   560  	}
   561  	if cfg.SimNet {
   562  		numNets++
   563  		// Also disable dns seeding on the simulation test network.
   564  		activeNetParams = &simNetParams
   565  		cfg.DisableDNSSeed = true
   566  	}
   567  	if cfg.SigNet {
   568  		numNets++
   569  		activeNetParams = &sigNetParams
   570  
   571  		// Let the user overwrite the default signet parameters. The
   572  		// challenge defines the actual signet network to join and the
   573  		// seed nodes are needed for network discovery.
   574  		sigNetChallenge := chaincfg.DefaultSignetChallenge
   575  		sigNetSeeds := chaincfg.DefaultSignetDNSSeeds
   576  		if cfg.SigNetChallenge != "" {
   577  			challenge, err := hex.DecodeString(cfg.SigNetChallenge)
   578  			if err != nil {
   579  				str := "%s: Invalid signet challenge, hex " +
   580  					"decode failed: %v"
   581  				err := fmt.Errorf(str, funcName, err)
   582  				fmt.Fprintln(os.Stderr, err)
   583  				fmt.Fprintln(os.Stderr, usageMessage)
   584  				return nil, nil, err
   585  			}
   586  			sigNetChallenge = challenge
   587  		}
   588  
   589  		if len(cfg.SigNetSeedNode) > 0 {
   590  			sigNetSeeds = make(
   591  				[]chaincfg.DNSSeed, len(cfg.SigNetSeedNode),
   592  			)
   593  			for idx, seed := range cfg.SigNetSeedNode {
   594  				sigNetSeeds[idx] = chaincfg.DNSSeed{
   595  					Host:         seed,
   596  					HasFiltering: false,
   597  				}
   598  			}
   599  		}
   600  
   601  		chainParams := chaincfg.CustomSignetParams(
   602  			sigNetChallenge, sigNetSeeds,
   603  		)
   604  		activeNetParams.Params = &chainParams
   605  	}
   606  	if numNets > 1 {
   607  		str := "%s: The testnet, regtest, segnet, signet and simnet " +
   608  			"params can't be used together -- choose one of the " +
   609  			"five"
   610  		err := fmt.Errorf(str, funcName)
   611  		fmt.Fprintln(os.Stderr, err)
   612  		fmt.Fprintln(os.Stderr, usageMessage)
   613  		return nil, nil, err
   614  	}
   615  
   616  	// If mainnet is active, then we won't allow the stall handler to be
   617  	// disabled.
   618  	if activeNetParams.Params.Net == wire.MainNet && cfg.DisableStallHandler {
   619  		str := "%s: stall handler cannot be disabled on mainnet"
   620  		err := fmt.Errorf(str, funcName)
   621  		fmt.Fprintln(os.Stderr, err)
   622  		fmt.Fprintln(os.Stderr, usageMessage)
   623  		return nil, nil, err
   624  	}
   625  
   626  	// Set the default policy for relaying non-standard transactions
   627  	// according to the default of the active network. The set
   628  	// configuration value takes precedence over the default value for the
   629  	// selected network.
   630  	relayNonStd := activeNetParams.RelayNonStdTxs
   631  	switch {
   632  	case cfg.RelayNonStd && cfg.RejectNonStd:
   633  		str := "%s: rejectnonstd and relaynonstd cannot be used " +
   634  			"together -- choose only one"
   635  		err := fmt.Errorf(str, funcName)
   636  		fmt.Fprintln(os.Stderr, err)
   637  		fmt.Fprintln(os.Stderr, usageMessage)
   638  		return nil, nil, err
   639  	case cfg.RejectNonStd:
   640  		relayNonStd = false
   641  	case cfg.RelayNonStd:
   642  		relayNonStd = true
   643  	}
   644  	cfg.RelayNonStd = relayNonStd
   645  
   646  	// Append the network type to the data directory so it is "namespaced"
   647  	// per network.  In addition to the block database, there are other
   648  	// pieces of data that are saved to disk such as address manager state.
   649  	// All data is specific to a network, so namespacing the data directory
   650  	// means each individual piece of serialized data does not have to
   651  	// worry about changing names per network and such.
   652  	cfg.DataDir = cleanAndExpandPath(cfg.DataDir)
   653  	cfg.DataDir = filepath.Join(cfg.DataDir, netName(activeNetParams))
   654  
   655  	// Append the network type to the log directory so it is "namespaced"
   656  	// per network in the same fashion as the data directory.
   657  	cfg.LogDir = cleanAndExpandPath(cfg.LogDir)
   658  	cfg.LogDir = filepath.Join(cfg.LogDir, netName(activeNetParams))
   659  
   660  	// Special show command to list supported subsystems and exit.
   661  	if cfg.DebugLevel == "show" {
   662  		fmt.Println("Supported subsystems", supportedSubsystems())
   663  		os.Exit(0)
   664  	}
   665  
   666  	// Initialize log rotation.  After log rotation has been initialized, the
   667  	// logger variables may be used.
   668  	initLogRotator(filepath.Join(cfg.LogDir, defaultLogFilename))
   669  
   670  	// Parse, validate, and set debug log level(s).
   671  	if err := parseAndSetDebugLevels(cfg.DebugLevel); err != nil {
   672  		err := fmt.Errorf("%s: %v", funcName, err.Error())
   673  		fmt.Fprintln(os.Stderr, err)
   674  		fmt.Fprintln(os.Stderr, usageMessage)
   675  		return nil, nil, err
   676  	}
   677  
   678  	// Validate database type.
   679  	if !validDbType(cfg.DbType) {
   680  		str := "%s: The specified database type [%v] is invalid -- " +
   681  			"supported types %v"
   682  		err := fmt.Errorf(str, funcName, cfg.DbType, knownDbTypes)
   683  		fmt.Fprintln(os.Stderr, err)
   684  		fmt.Fprintln(os.Stderr, usageMessage)
   685  		return nil, nil, err
   686  	}
   687  
   688  	// Validate profile port number
   689  	if cfg.Profile != "" {
   690  		profilePort, err := strconv.Atoi(cfg.Profile)
   691  		if err != nil || profilePort < 1024 || profilePort > 65535 {
   692  			str := "%s: The profile port must be between 1024 and 65535"
   693  			err := fmt.Errorf(str, funcName)
   694  			fmt.Fprintln(os.Stderr, err)
   695  			fmt.Fprintln(os.Stderr, usageMessage)
   696  			return nil, nil, err
   697  		}
   698  	}
   699  
   700  	// Don't allow ban durations that are too short.
   701  	if cfg.BanDuration < time.Second {
   702  		str := "%s: The banduration option may not be less than 1s -- parsed [%v]"
   703  		err := fmt.Errorf(str, funcName, cfg.BanDuration)
   704  		fmt.Fprintln(os.Stderr, err)
   705  		fmt.Fprintln(os.Stderr, usageMessage)
   706  		return nil, nil, err
   707  	}
   708  
   709  	// Validate any given whitelisted IP addresses and networks.
   710  	if len(cfg.Whitelists) > 0 {
   711  		var ip net.IP
   712  		cfg.whitelists = make([]*net.IPNet, 0, len(cfg.Whitelists))
   713  
   714  		for _, addr := range cfg.Whitelists {
   715  			_, ipnet, err := net.ParseCIDR(addr)
   716  			if err != nil {
   717  				ip = net.ParseIP(addr)
   718  				if ip == nil {
   719  					str := "%s: The whitelist value of '%s' is invalid"
   720  					err = fmt.Errorf(str, funcName, addr)
   721  					fmt.Fprintln(os.Stderr, err)
   722  					fmt.Fprintln(os.Stderr, usageMessage)
   723  					return nil, nil, err
   724  				}
   725  				var bits int
   726  				if ip.To4() == nil {
   727  					// IPv6
   728  					bits = 128
   729  				} else {
   730  					bits = 32
   731  				}
   732  				ipnet = &net.IPNet{
   733  					IP:   ip,
   734  					Mask: net.CIDRMask(bits, bits),
   735  				}
   736  			}
   737  			cfg.whitelists = append(cfg.whitelists, ipnet)
   738  		}
   739  	}
   740  
   741  	// --addPeer and --connect do not mix.
   742  	if len(cfg.AddPeers) > 0 && len(cfg.ConnectPeers) > 0 {
   743  		str := "%s: the --addpeer and --connect options can not be " +
   744  			"mixed"
   745  		err := fmt.Errorf(str, funcName)
   746  		fmt.Fprintln(os.Stderr, err)
   747  		fmt.Fprintln(os.Stderr, usageMessage)
   748  		return nil, nil, err
   749  	}
   750  
   751  	// --proxy or --connect without --listen disables listening.
   752  	if (cfg.Proxy != "" || len(cfg.ConnectPeers) > 0) &&
   753  		len(cfg.Listeners) == 0 {
   754  		cfg.DisableListen = true
   755  	}
   756  
   757  	// Connect means no DNS seeding.
   758  	if len(cfg.ConnectPeers) > 0 {
   759  		cfg.DisableDNSSeed = true
   760  	}
   761  
   762  	// Add the default listener if none were specified. The default
   763  	// listener is all addresses on the listen port for the network
   764  	// we are to connect to.
   765  	if len(cfg.Listeners) == 0 {
   766  		cfg.Listeners = []string{
   767  			net.JoinHostPort("", activeNetParams.DefaultPort),
   768  		}
   769  	}
   770  
   771  	// Check to make sure limited and admin users don't have the same username
   772  	if cfg.RPCUser == cfg.RPCLimitUser && cfg.RPCUser != "" {
   773  		str := "%s: --rpcuser and --rpclimituser must not specify the " +
   774  			"same username"
   775  		err := fmt.Errorf(str, funcName)
   776  		fmt.Fprintln(os.Stderr, err)
   777  		fmt.Fprintln(os.Stderr, usageMessage)
   778  		return nil, nil, err
   779  	}
   780  
   781  	// Check to make sure limited and admin users don't have the same password
   782  	if cfg.RPCPass == cfg.RPCLimitPass && cfg.RPCPass != "" {
   783  		str := "%s: --rpcpass and --rpclimitpass must not specify the " +
   784  			"same password"
   785  		err := fmt.Errorf(str, funcName)
   786  		fmt.Fprintln(os.Stderr, err)
   787  		fmt.Fprintln(os.Stderr, usageMessage)
   788  		return nil, nil, err
   789  	}
   790  
   791  	// The RPC server is disabled if no username or password is provided.
   792  	if (cfg.RPCUser == "" || cfg.RPCPass == "") &&
   793  		(cfg.RPCLimitUser == "" || cfg.RPCLimitPass == "") {
   794  		cfg.DisableRPC = true
   795  	}
   796  
   797  	if cfg.DisableRPC {
   798  		btcdLog.Infof("RPC service is disabled")
   799  	}
   800  
   801  	// Default RPC to listen on localhost only.
   802  	if !cfg.DisableRPC && len(cfg.RPCListeners) == 0 {
   803  		addrs, err := net.LookupHost("localhost")
   804  		if err != nil {
   805  			return nil, nil, err
   806  		}
   807  		cfg.RPCListeners = make([]string, 0, len(addrs))
   808  		for _, addr := range addrs {
   809  			addr = net.JoinHostPort(addr, activeNetParams.rpcPort)
   810  			cfg.RPCListeners = append(cfg.RPCListeners, addr)
   811  		}
   812  	}
   813  
   814  	if cfg.RPCMaxConcurrentReqs < 0 {
   815  		str := "%s: The rpcmaxwebsocketconcurrentrequests option may " +
   816  			"not be less than 0 -- parsed [%d]"
   817  		err := fmt.Errorf(str, funcName, cfg.RPCMaxConcurrentReqs)
   818  		fmt.Fprintln(os.Stderr, err)
   819  		fmt.Fprintln(os.Stderr, usageMessage)
   820  		return nil, nil, err
   821  	}
   822  
   823  	// Validate the the minrelaytxfee.
   824  	cfg.minRelayTxFee, err = btcutil.NewAmount(cfg.MinRelayTxFee)
   825  	if err != nil {
   826  		str := "%s: invalid minrelaytxfee: %v"
   827  		err := fmt.Errorf(str, funcName, err)
   828  		fmt.Fprintln(os.Stderr, err)
   829  		fmt.Fprintln(os.Stderr, usageMessage)
   830  		return nil, nil, err
   831  	}
   832  
   833  	// Limit the max block size to a sane value.
   834  	if cfg.BlockMaxSize < blockMaxSizeMin || cfg.BlockMaxSize >
   835  		blockMaxSizeMax {
   836  
   837  		str := "%s: The blockmaxsize option must be in between %d " +
   838  			"and %d -- parsed [%d]"
   839  		err := fmt.Errorf(str, funcName, blockMaxSizeMin,
   840  			blockMaxSizeMax, cfg.BlockMaxSize)
   841  		fmt.Fprintln(os.Stderr, err)
   842  		fmt.Fprintln(os.Stderr, usageMessage)
   843  		return nil, nil, err
   844  	}
   845  
   846  	// Limit the max block weight to a sane value.
   847  	if cfg.BlockMaxWeight < blockMaxWeightMin ||
   848  		cfg.BlockMaxWeight > blockMaxWeightMax {
   849  
   850  		str := "%s: The blockmaxweight option must be in between %d " +
   851  			"and %d -- parsed [%d]"
   852  		err := fmt.Errorf(str, funcName, blockMaxWeightMin,
   853  			blockMaxWeightMax, cfg.BlockMaxWeight)
   854  		fmt.Fprintln(os.Stderr, err)
   855  		fmt.Fprintln(os.Stderr, usageMessage)
   856  		return nil, nil, err
   857  	}
   858  
   859  	// Limit the max orphan count to a sane vlue.
   860  	if cfg.MaxOrphanTxs < 0 {
   861  		str := "%s: The maxorphantx option may not be less than 0 " +
   862  			"-- parsed [%d]"
   863  		err := fmt.Errorf(str, funcName, cfg.MaxOrphanTxs)
   864  		fmt.Fprintln(os.Stderr, err)
   865  		fmt.Fprintln(os.Stderr, usageMessage)
   866  		return nil, nil, err
   867  	}
   868  
   869  	// Limit the block priority and minimum block sizes to max block size.
   870  	cfg.BlockPrioritySize = minUint32(cfg.BlockPrioritySize, cfg.BlockMaxSize)
   871  	cfg.BlockMinSize = minUint32(cfg.BlockMinSize, cfg.BlockMaxSize)
   872  	cfg.BlockMinWeight = minUint32(cfg.BlockMinWeight, cfg.BlockMaxWeight)
   873  
   874  	switch {
   875  	// If the max block size isn't set, but the max weight is, then we'll
   876  	// set the limit for the max block size to a safe limit so weight takes
   877  	// precedence.
   878  	case cfg.BlockMaxSize == defaultBlockMaxSize &&
   879  		cfg.BlockMaxWeight != defaultBlockMaxWeight:
   880  
   881  		cfg.BlockMaxSize = blockchain.MaxBlockBaseSize - 1000
   882  
   883  	// If the max block weight isn't set, but the block size is, then we'll
   884  	// scale the set weight accordingly based on the max block size value.
   885  	case cfg.BlockMaxSize != defaultBlockMaxSize &&
   886  		cfg.BlockMaxWeight == defaultBlockMaxWeight:
   887  
   888  		cfg.BlockMaxWeight = cfg.BlockMaxSize * blockchain.WitnessScaleFactor
   889  	}
   890  
   891  	// Look for illegal characters in the user agent comments.
   892  	for _, uaComment := range cfg.UserAgentComments {
   893  		if strings.ContainsAny(uaComment, "/:()") {
   894  			err := fmt.Errorf("%s: The following characters must not "+
   895  				"appear in user agent comments: '/', ':', '(', ')'",
   896  				funcName)
   897  			fmt.Fprintln(os.Stderr, err)
   898  			fmt.Fprintln(os.Stderr, usageMessage)
   899  			return nil, nil, err
   900  		}
   901  	}
   902  
   903  	// --txindex and --droptxindex do not mix.
   904  	if cfg.TxIndex && cfg.DropTxIndex {
   905  		err := fmt.Errorf("%s: the --txindex and --droptxindex "+
   906  			"options may  not be activated at the same time",
   907  			funcName)
   908  		fmt.Fprintln(os.Stderr, err)
   909  		fmt.Fprintln(os.Stderr, usageMessage)
   910  		return nil, nil, err
   911  	}
   912  
   913  	// --addrindex and --dropaddrindex do not mix.
   914  	if cfg.AddrIndex && cfg.DropAddrIndex {
   915  		err := fmt.Errorf("%s: the --addrindex and --dropaddrindex "+
   916  			"options may not be activated at the same time",
   917  			funcName)
   918  		fmt.Fprintln(os.Stderr, err)
   919  		fmt.Fprintln(os.Stderr, usageMessage)
   920  		return nil, nil, err
   921  	}
   922  
   923  	// --addrindex and --droptxindex do not mix.
   924  	if cfg.AddrIndex && cfg.DropTxIndex {
   925  		err := fmt.Errorf("%s: the --addrindex and --droptxindex "+
   926  			"options may not be activated at the same time "+
   927  			"because the address index relies on the transaction "+
   928  			"index",
   929  			funcName)
   930  		fmt.Fprintln(os.Stderr, err)
   931  		fmt.Fprintln(os.Stderr, usageMessage)
   932  		return nil, nil, err
   933  	}
   934  
   935  	// Check mining addresses are valid and saved parsed versions.
   936  	cfg.miningAddrs = make([]btcutil.Address, 0, len(cfg.MiningAddrs))
   937  	for _, strAddr := range cfg.MiningAddrs {
   938  		addr, err := btcutil.DecodeAddress(strAddr, activeNetParams.Params)
   939  		if err != nil {
   940  			str := "%s: mining address '%s' failed to decode: %v"
   941  			err := fmt.Errorf(str, funcName, strAddr, err)
   942  			fmt.Fprintln(os.Stderr, err)
   943  			fmt.Fprintln(os.Stderr, usageMessage)
   944  			return nil, nil, err
   945  		}
   946  		if !addr.IsForNet(activeNetParams.Params) {
   947  			str := "%s: mining address '%s' is on the wrong network"
   948  			err := fmt.Errorf(str, funcName, strAddr)
   949  			fmt.Fprintln(os.Stderr, err)
   950  			fmt.Fprintln(os.Stderr, usageMessage)
   951  			return nil, nil, err
   952  		}
   953  		cfg.miningAddrs = append(cfg.miningAddrs, addr)
   954  	}
   955  
   956  	// Ensure there is at least one mining address when the generate flag is
   957  	// set.
   958  	if cfg.Generate && len(cfg.MiningAddrs) == 0 {
   959  		str := "%s: the generate flag is set, but there are no mining " +
   960  			"addresses specified "
   961  		err := fmt.Errorf(str, funcName)
   962  		fmt.Fprintln(os.Stderr, err)
   963  		fmt.Fprintln(os.Stderr, usageMessage)
   964  		return nil, nil, err
   965  	}
   966  
   967  	// Add default port to all listener addresses if needed and remove
   968  	// duplicate addresses.
   969  	cfg.Listeners = normalizeAddresses(cfg.Listeners,
   970  		activeNetParams.DefaultPort)
   971  
   972  	// Add default port to all rpc listener addresses if needed and remove
   973  	// duplicate addresses.
   974  	cfg.RPCListeners = normalizeAddresses(cfg.RPCListeners,
   975  		activeNetParams.rpcPort)
   976  
   977  	// Only allow TLS to be disabled if the RPC is bound to localhost
   978  	// addresses.
   979  	if !cfg.DisableRPC && cfg.DisableTLS {
   980  		for _, addr := range cfg.RPCListeners {
   981  			_, _, err := net.SplitHostPort(addr)
   982  			if err != nil {
   983  				str := "%s: RPC listen interface '%s' is " +
   984  					"invalid: %v"
   985  				err := fmt.Errorf(str, funcName, addr, err)
   986  				fmt.Fprintln(os.Stderr, err)
   987  				fmt.Fprintln(os.Stderr, usageMessage)
   988  				return nil, nil, err
   989  			}
   990  		}
   991  	}
   992  
   993  	// Add default port to all added peer addresses if needed and remove
   994  	// duplicate addresses.
   995  	cfg.AddPeers = normalizeAddresses(cfg.AddPeers,
   996  		activeNetParams.DefaultPort)
   997  	cfg.ConnectPeers = normalizeAddresses(cfg.ConnectPeers,
   998  		activeNetParams.DefaultPort)
   999  
  1000  	// --noonion and --onion do not mix.
  1001  	if cfg.NoOnion && cfg.OnionProxy != "" {
  1002  		err := fmt.Errorf("%s: the --noonion and --onion options may "+
  1003  			"not be activated at the same time", funcName)
  1004  		fmt.Fprintln(os.Stderr, err)
  1005  		fmt.Fprintln(os.Stderr, usageMessage)
  1006  		return nil, nil, err
  1007  	}
  1008  
  1009  	// Check the checkpoints for syntax errors.
  1010  	cfg.addCheckpoints, err = parseCheckpoints(cfg.AddCheckpoints)
  1011  	if err != nil {
  1012  		str := "%s: Error parsing checkpoints: %v"
  1013  		err := fmt.Errorf(str, funcName, err)
  1014  		fmt.Fprintln(os.Stderr, err)
  1015  		fmt.Fprintln(os.Stderr, usageMessage)
  1016  		return nil, nil, err
  1017  	}
  1018  
  1019  	// Tor stream isolation requires either proxy or onion proxy to be set.
  1020  	if cfg.TorIsolation && cfg.Proxy == "" && cfg.OnionProxy == "" {
  1021  		str := "%s: Tor stream isolation requires either proxy or " +
  1022  			"onionproxy to be set"
  1023  		err := fmt.Errorf(str, funcName)
  1024  		fmt.Fprintln(os.Stderr, err)
  1025  		fmt.Fprintln(os.Stderr, usageMessage)
  1026  		return nil, nil, err
  1027  	}
  1028  
  1029  	// Setup dial and DNS resolution (lookup) functions depending on the
  1030  	// specified options.  The default is to use the standard
  1031  	// net.DialTimeout function as well as the system DNS resolver.  When a
  1032  	// proxy is specified, the dial function is set to the proxy specific
  1033  	// dial function and the lookup is set to use tor (unless --noonion is
  1034  	// specified in which case the system DNS resolver is used).
  1035  	cfg.dial = net.DialTimeout
  1036  	cfg.lookup = net.LookupIP
  1037  	if cfg.Proxy != "" {
  1038  		_, _, err := net.SplitHostPort(cfg.Proxy)
  1039  		if err != nil {
  1040  			str := "%s: Proxy address '%s' is invalid: %v"
  1041  			err := fmt.Errorf(str, funcName, cfg.Proxy, err)
  1042  			fmt.Fprintln(os.Stderr, err)
  1043  			fmt.Fprintln(os.Stderr, usageMessage)
  1044  			return nil, nil, err
  1045  		}
  1046  
  1047  		// Tor isolation flag means proxy credentials will be overridden
  1048  		// unless there is also an onion proxy configured in which case
  1049  		// that one will be overridden.
  1050  		torIsolation := false
  1051  		if cfg.TorIsolation && cfg.OnionProxy == "" &&
  1052  			(cfg.ProxyUser != "" || cfg.ProxyPass != "") {
  1053  
  1054  			torIsolation = true
  1055  			fmt.Fprintln(os.Stderr, "Tor isolation set -- "+
  1056  				"overriding specified proxy user credentials")
  1057  		}
  1058  
  1059  		proxy := &socks.Proxy{
  1060  			Addr:         cfg.Proxy,
  1061  			Username:     cfg.ProxyUser,
  1062  			Password:     cfg.ProxyPass,
  1063  			TorIsolation: torIsolation,
  1064  		}
  1065  		cfg.dial = proxy.DialTimeout
  1066  
  1067  		// Treat the proxy as tor and perform DNS resolution through it
  1068  		// unless the --noonion flag is set or there is an
  1069  		// onion-specific proxy configured.
  1070  		if !cfg.NoOnion && cfg.OnionProxy == "" {
  1071  			cfg.lookup = func(host string) ([]net.IP, error) {
  1072  				return connmgr.TorLookupIP(host, cfg.Proxy)
  1073  			}
  1074  		}
  1075  	}
  1076  
  1077  	// Setup onion address dial function depending on the specified options.
  1078  	// The default is to use the same dial function selected above.  However,
  1079  	// when an onion-specific proxy is specified, the onion address dial
  1080  	// function is set to use the onion-specific proxy while leaving the
  1081  	// normal dial function as selected above.  This allows .onion address
  1082  	// traffic to be routed through a different proxy than normal traffic.
  1083  	if cfg.OnionProxy != "" {
  1084  		_, _, err := net.SplitHostPort(cfg.OnionProxy)
  1085  		if err != nil {
  1086  			str := "%s: Onion proxy address '%s' is invalid: %v"
  1087  			err := fmt.Errorf(str, funcName, cfg.OnionProxy, err)
  1088  			fmt.Fprintln(os.Stderr, err)
  1089  			fmt.Fprintln(os.Stderr, usageMessage)
  1090  			return nil, nil, err
  1091  		}
  1092  
  1093  		// Tor isolation flag means onion proxy credentials will be
  1094  		// overridden.
  1095  		if cfg.TorIsolation &&
  1096  			(cfg.OnionProxyUser != "" || cfg.OnionProxyPass != "") {
  1097  			fmt.Fprintln(os.Stderr, "Tor isolation set -- "+
  1098  				"overriding specified onionproxy user "+
  1099  				"credentials ")
  1100  		}
  1101  
  1102  		cfg.oniondial = func(network, addr string, timeout time.Duration) (net.Conn, error) {
  1103  			proxy := &socks.Proxy{
  1104  				Addr:         cfg.OnionProxy,
  1105  				Username:     cfg.OnionProxyUser,
  1106  				Password:     cfg.OnionProxyPass,
  1107  				TorIsolation: cfg.TorIsolation,
  1108  			}
  1109  			return proxy.DialTimeout(network, addr, timeout)
  1110  		}
  1111  
  1112  		// When configured in bridge mode (both --onion and --proxy are
  1113  		// configured), it means that the proxy configured by --proxy is
  1114  		// not a tor proxy, so override the DNS resolution to use the
  1115  		// onion-specific proxy.
  1116  		if cfg.Proxy != "" {
  1117  			cfg.lookup = func(host string) ([]net.IP, error) {
  1118  				return connmgr.TorLookupIP(host, cfg.OnionProxy)
  1119  			}
  1120  		}
  1121  	} else {
  1122  		cfg.oniondial = cfg.dial
  1123  	}
  1124  
  1125  	// Specifying --noonion means the onion address dial function results in
  1126  	// an error.
  1127  	if cfg.NoOnion {
  1128  		cfg.oniondial = func(a, b string, t time.Duration) (net.Conn, error) {
  1129  			return nil, errors.New("tor has been disabled")
  1130  		}
  1131  	}
  1132  
  1133  	// Warn about missing config file only after all other configuration is
  1134  	// done.  This prevents the warning on help messages and invalid
  1135  	// options.  Note this should go directly before the return.
  1136  	if configFileError != nil {
  1137  		btcdLog.Warnf("%v", configFileError)
  1138  	}
  1139  
  1140  	return &cfg, remainingArgs, nil
  1141  }
  1142  
  1143  // createDefaultConfig copies the file sample-lbcd.conf to the given destination path,
  1144  // and populates it with some randomly generated RPC username and password.
  1145  func createDefaultConfigFile(destinationPath string) error {
  1146  	// Create the destination directory if it does not exists
  1147  	err := os.MkdirAll(filepath.Dir(destinationPath), 0700)
  1148  	if err != nil {
  1149  		return err
  1150  	}
  1151  
  1152  	// We assume sample config file path is same as binary
  1153  	path, err := filepath.Abs(filepath.Dir(os.Args[0]))
  1154  	if err != nil {
  1155  		return err
  1156  	}
  1157  	sampleConfigPath := filepath.Join(path, sampleConfigFilename)
  1158  
  1159  	// We generate a random user and password
  1160  	randomBytes := make([]byte, 20)
  1161  	_, err = rand.Read(randomBytes)
  1162  	if err != nil {
  1163  		return err
  1164  	}
  1165  	generatedRPCUser := base64.StdEncoding.EncodeToString(randomBytes)
  1166  
  1167  	_, err = rand.Read(randomBytes)
  1168  	if err != nil {
  1169  		return err
  1170  	}
  1171  	generatedRPCPass := base64.StdEncoding.EncodeToString(randomBytes)
  1172  
  1173  	var reader *bufio.Reader
  1174  	src, err := os.Open(sampleConfigPath)
  1175  	if err != nil {
  1176  		// Fall back to sample config embedded at build time.
  1177  		reader = bufio.NewReader(strings.NewReader(sampleConfig))
  1178  	} else {
  1179  		reader = bufio.NewReader(src)
  1180  		defer src.Close()
  1181  	}
  1182  
  1183  	dest, err := os.OpenFile(destinationPath,
  1184  		os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
  1185  	if err != nil {
  1186  		return err
  1187  	}
  1188  	defer dest.Close()
  1189  
  1190  	// We copy every line from the sample config file to the destination,
  1191  	// only replacing the two lines for rpcuser and rpcpass
  1192  	for err != io.EOF {
  1193  		var line string
  1194  		line, err = reader.ReadString('\n')
  1195  		if err != nil && err != io.EOF {
  1196  			return err
  1197  		}
  1198  
  1199  		if strings.Contains(line, "rpcuser=") {
  1200  			line = "rpcuser=" + generatedRPCUser + "\n"
  1201  		} else if strings.Contains(line, "rpcpass=") {
  1202  			line = "rpcpass=" + generatedRPCPass + "\n"
  1203  		}
  1204  
  1205  		if _, err := dest.WriteString(line); err != nil {
  1206  			return err
  1207  		}
  1208  	}
  1209  
  1210  	return nil
  1211  }
  1212  
  1213  // btcdDial connects to the address on the named network using the appropriate
  1214  // dial function depending on the address and configuration options.  For
  1215  // example, .onion addresses will be dialed using the onion specific proxy if
  1216  // one was specified, but will otherwise use the normal dial function (which
  1217  // could itself use a proxy or not).
  1218  func btcdDial(addr net.Addr) (net.Conn, error) {
  1219  	if strings.Contains(addr.String(), ".onion:") {
  1220  		return cfg.oniondial(addr.Network(), addr.String(),
  1221  			defaultConnectTimeout)
  1222  	}
  1223  	return cfg.dial(addr.Network(), addr.String(), defaultConnectTimeout)
  1224  }
  1225  
  1226  // btcdLookup resolves the IP of the given host using the correct DNS lookup
  1227  // function depending on the configuration options.  For example, addresses will
  1228  // be resolved using tor when the --proxy flag was specified unless --noonion
  1229  // was also specified in which case the normal system DNS resolver will be used.
  1230  //
  1231  // Any attempt to resolve a tor address (.onion) will return an error since they
  1232  // are not intended to be resolved outside of the tor proxy.
  1233  func btcdLookup(host string) ([]net.IP, error) {
  1234  	if strings.HasSuffix(host, ".onion") {
  1235  		return nil, fmt.Errorf("attempt to resolve tor address %s", host)
  1236  	}
  1237  
  1238  	return cfg.lookup(host)
  1239  }