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