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