github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/config.go (about)

     1  // Copyright (c) 2013-2016 The btcsuite developers
     2  // Copyright (c) 2016 The Dash developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package main
     7  
     8  import (
     9  	"bufio"
    10  	"crypto/rand"
    11  	"encoding/base64"
    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  	flags "github.com/btcsuite/go-flags"
    25  	"github.com/btcsuite/go-socks/socks"
    26  	"github.com/dashpay/godash/database"
    27  	_ "github.com/dashpay/godash/database/ffldb"
    28  	"github.com/dashpay/godash/wire"
    29  	"github.com/dashpay/godashutil"
    30  )
    31  
    32  const (
    33  	defaultConfigFilename        = "btcd.conf"
    34  	defaultDataDirname           = "data"
    35  	defaultLogLevel              = "info"
    36  	defaultLogDirname            = "logs"
    37  	defaultLogFilename           = "btcd.log"
    38  	defaultMaxPeers              = 125
    39  	defaultBanDuration           = time.Hour * 24
    40  	defaultBanThreshold          = 100
    41  	defaultMaxRPCClients         = 10
    42  	defaultMaxRPCWebsockets      = 25
    43  	defaultVerifyEnabled         = false
    44  	defaultDbType                = "ffldb"
    45  	defaultFreeTxRelayLimit      = 15.0
    46  	defaultBlockMinSize          = 0
    47  	defaultBlockMaxSize          = 750000
    48  	blockMaxSizeMin              = 1000
    49  	blockMaxSizeMax              = wire.MaxBlockPayload - 1000
    50  	defaultBlockPrioritySize     = 50000
    51  	defaultGenerate              = false
    52  	defaultMaxOrphanTransactions = 1000
    53  	defaultMaxOrphanTxSize       = 5000
    54  	defaultSigCacheMaxSize       = 100000
    55  	defaultTxIndex               = false
    56  	defaultAddrIndex             = false
    57  )
    58  
    59  var (
    60  	btcdHomeDir        = godashutil.AppDataDir("btcd", false)
    61  	defaultConfigFile  = filepath.Join(btcdHomeDir, defaultConfigFilename)
    62  	defaultDataDir     = filepath.Join(btcdHomeDir, defaultDataDirname)
    63  	knownDbTypes       = database.SupportedDrivers()
    64  	defaultRPCKeyFile  = filepath.Join(btcdHomeDir, "rpc.key")
    65  	defaultRPCCertFile = filepath.Join(btcdHomeDir, "rpc.cert")
    66  	defaultLogDir      = filepath.Join(btcdHomeDir, defaultLogDirname)
    67  )
    68  
    69  // runServiceCommand is only set to a real function on Windows.  It is used
    70  // to parse and execute service commands specified via the -s flag.
    71  var runServiceCommand func(string) error
    72  
    73  // minUint32 is a helper function to return the minimum of two uint32s.
    74  // This avoids a math import and the need to cast to floats.
    75  func minUint32(a, b uint32) uint32 {
    76  	if a < b {
    77  		return a
    78  	}
    79  	return b
    80  }
    81  
    82  // config defines the configuration options for btcd.
    83  //
    84  // See loadConfig for details on the configuration load process.
    85  type config struct {
    86  	ShowVersion        bool          `short:"V" long:"version" description:"Display version information and exit"`
    87  	ConfigFile         string        `short:"C" long:"configfile" description:"Path to configuration file"`
    88  	DataDir            string        `short:"b" long:"datadir" description:"Directory to store data"`
    89  	LogDir             string        `long:"logdir" description:"Directory to log output."`
    90  	AddPeers           []string      `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"`
    91  	ConnectPeers       []string      `long:"connect" description:"Connect only to the specified peers at startup"`
    92  	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"`
    93  	Listeners          []string      `long:"listen" description:"Add an interface/port to listen for connections (default all interfaces port: 8333, testnet: 18333)"`
    94  	MaxPeers           int           `long:"maxpeers" description:"Max number of inbound and outbound peers"`
    95  	DisableBanning     bool          `long:"nobanning" description:"Disable banning of misbehaving peers"`
    96  	BanDuration        time.Duration `long:"banduration" description:"How long to ban misbehaving peers.  Valid time units are {s, m, h}.  Minimum 1 second"`
    97  	BanThreshold       uint32        `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."`
    98  	RPCUser            string        `short:"u" long:"rpcuser" description:"Username for RPC connections"`
    99  	RPCPass            string        `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
   100  	RPCLimitUser       string        `long:"rpclimituser" description:"Username for limited RPC connections"`
   101  	RPCLimitPass       string        `long:"rpclimitpass" default-mask:"-" description:"Password for limited RPC connections"`
   102  	RPCListeners       []string      `long:"rpclisten" description:"Add an interface/port to listen for RPC connections (default port: 8334, testnet: 18334)"`
   103  	RPCCert            string        `long:"rpccert" description:"File containing the certificate file"`
   104  	RPCKey             string        `long:"rpckey" description:"File containing the certificate key"`
   105  	RPCMaxClients      int           `long:"rpcmaxclients" description:"Max number of RPC clients for standard connections"`
   106  	RPCMaxWebsockets   int           `long:"rpcmaxwebsockets" description:"Max number of RPC websocket connections"`
   107  	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"`
   108  	DisableTLS         bool          `long:"notls" description:"Disable TLS for the RPC server -- NOTE: This is only allowed if the RPC server is bound to localhost"`
   109  	DisableDNSSeed     bool          `long:"nodnsseed" description:"Disable DNS seeding for peers"`
   110  	ExternalIPs        []string      `long:"externalip" description:"Add an ip to the list of local addresses we claim to listen on to peers"`
   111  	Proxy              string        `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
   112  	ProxyUser          string        `long:"proxyuser" description:"Username for proxy server"`
   113  	ProxyPass          string        `long:"proxypass" default-mask:"-" description:"Password for proxy server"`
   114  	OnionProxy         string        `long:"onion" description:"Connect to tor hidden services via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
   115  	OnionProxyUser     string        `long:"onionuser" description:"Username for onion proxy server"`
   116  	OnionProxyPass     string        `long:"onionpass" default-mask:"-" description:"Password for onion proxy server"`
   117  	NoOnion            bool          `long:"noonion" description:"Disable connecting to tor hidden services"`
   118  	TorIsolation       bool          `long:"torisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."`
   119  	TestNet3           bool          `long:"testnet" description:"Use the test network"`
   120  	RegressionTest     bool          `long:"regtest" description:"Use the regression test network"`
   121  	SimNet             bool          `long:"simnet" description:"Use the simulation test network"`
   122  	DisableCheckpoints bool          `long:"nocheckpoints" description:"Disable built-in checkpoints.  Don't do this unless you know what you're doing."`
   123  	DbType             string        `long:"dbtype" description:"Database backend to use for the Block Chain"`
   124  	Profile            string        `long:"profile" description:"Enable HTTP profiling on given port -- NOTE port must be between 1024 and 65536"`
   125  	CPUProfile         string        `long:"cpuprofile" description:"Write CPU profile to the specified file"`
   126  	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"`
   127  	Upnp               bool          `long:"upnp" description:"Use UPnP to map our listening port outside of NAT"`
   128  	MinRelayTxFee      float64       `long:"minrelaytxfee" description:"The minimum transaction fee in BTC/kB to be considered a non-zero fee."`
   129  	FreeTxRelayLimit   float64       `long:"limitfreerelay" description:"Limit relay of transactions with no transaction fee to the given amount in thousands of bytes per minute"`
   130  	NoRelayPriority    bool          `long:"norelaypriority" description:"Do not require free or low-fee transactions to have high priority for relaying"`
   131  	MaxOrphanTxs       int           `long:"maxorphantx" description:"Max number of orphan transactions to keep in memory"`
   132  	Generate           bool          `long:"generate" description:"Generate (mine) bitcoins using the CPU"`
   133  	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"`
   134  	BlockMinSize       uint32        `long:"blockminsize" description:"Mininum block size in bytes to be used when creating a block"`
   135  	BlockMaxSize       uint32        `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"`
   136  	BlockPrioritySize  uint32        `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"`
   137  	GetWorkKeys        []string      `long:"getworkkey" description:"DEPRECATED -- Use the --miningaddr option instead"`
   138  	NoPeerBloomFilters bool          `long:"nopeerbloomfilters" description:"Disable bloom filtering support"`
   139  	SigCacheMaxSize    uint          `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"`
   140  	BlocksOnly         bool          `long:"blocksonly" description:"Do not accept transactions from remote peers."`
   141  	TxIndex            bool          `long:"txindex" description:"Maintain a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"`
   142  	DropTxIndex        bool          `long:"droptxindex" description:"Deletes the hash-based transaction index from the database on start up and then exits."`
   143  	AddrIndex          bool          `long:"addrindex" description:"Maintain a full address-based transaction index which makes the searchrawtransactions RPC available"`
   144  	DropAddrIndex      bool          `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up and then exits."`
   145  	onionlookup        func(string) ([]net.IP, error)
   146  	lookup             func(string) ([]net.IP, error)
   147  	oniondial          func(string, string) (net.Conn, error)
   148  	dial               func(string, string) (net.Conn, error)
   149  	miningAddrs        []godashutil.Address
   150  	minRelayTxFee      godashutil.Amount
   151  }
   152  
   153  // serviceOptions defines the configuration options for btcd as a service on
   154  // Windows.
   155  type serviceOptions struct {
   156  	ServiceCommand string `short:"s" long:"service" description:"Service command {install, remove, start, stop}"`
   157  }
   158  
   159  // cleanAndExpandPath expands environment variables and leading ~ in the
   160  // passed path, cleans the result, and returns it.
   161  func cleanAndExpandPath(path string) string {
   162  	// Expand initial ~ to OS specific home directory.
   163  	if strings.HasPrefix(path, "~") {
   164  		homeDir := filepath.Dir(btcdHomeDir)
   165  		path = strings.Replace(path, "~", homeDir, 1)
   166  	}
   167  
   168  	// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
   169  	// but they variables can still be expanded via POSIX-style $VARIABLE.
   170  	return filepath.Clean(os.ExpandEnv(path))
   171  }
   172  
   173  // validLogLevel returns whether or not logLevel is a valid debug log level.
   174  func validLogLevel(logLevel string) bool {
   175  	switch logLevel {
   176  	case "trace":
   177  		fallthrough
   178  	case "debug":
   179  		fallthrough
   180  	case "info":
   181  		fallthrough
   182  	case "warn":
   183  		fallthrough
   184  	case "error":
   185  		fallthrough
   186  	case "critical":
   187  		return true
   188  	}
   189  	return false
   190  }
   191  
   192  // supportedSubsystems returns a sorted slice of the supported subsystems for
   193  // logging purposes.
   194  func supportedSubsystems() []string {
   195  	// Convert the subsystemLoggers map keys to a slice.
   196  	subsystems := make([]string, 0, len(subsystemLoggers))
   197  	for subsysID := range subsystemLoggers {
   198  		subsystems = append(subsystems, subsysID)
   199  	}
   200  
   201  	// Sort the subsystems for stable display.
   202  	sort.Strings(subsystems)
   203  	return subsystems
   204  }
   205  
   206  // parseAndSetDebugLevels attempts to parse the specified debug level and set
   207  // the levels accordingly.  An appropriate error is returned if anything is
   208  // invalid.
   209  func parseAndSetDebugLevels(debugLevel string) error {
   210  	// When the specified string doesn't have any delimters, treat it as
   211  	// the log level for all subsystems.
   212  	if !strings.Contains(debugLevel, ",") && !strings.Contains(debugLevel, "=") {
   213  		// Validate debug log level.
   214  		if !validLogLevel(debugLevel) {
   215  			str := "The specified debug level [%v] is invalid"
   216  			return fmt.Errorf(str, debugLevel)
   217  		}
   218  
   219  		// Change the logging level for all subsystems.
   220  		setLogLevels(debugLevel)
   221  
   222  		return nil
   223  	}
   224  
   225  	// Split the specified string into subsystem/level pairs while detecting
   226  	// issues and update the log levels accordingly.
   227  	for _, logLevelPair := range strings.Split(debugLevel, ",") {
   228  		if !strings.Contains(logLevelPair, "=") {
   229  			str := "The specified debug level contains an invalid " +
   230  				"subsystem/level pair [%v]"
   231  			return fmt.Errorf(str, logLevelPair)
   232  		}
   233  
   234  		// Extract the specified subsystem and log level.
   235  		fields := strings.Split(logLevelPair, "=")
   236  		subsysID, logLevel := fields[0], fields[1]
   237  
   238  		// Validate subsystem.
   239  		if _, exists := subsystemLoggers[subsysID]; !exists {
   240  			str := "The specified subsystem [%v] is invalid -- " +
   241  				"supported subsytems %v"
   242  			return fmt.Errorf(str, subsysID, supportedSubsystems())
   243  		}
   244  
   245  		// Validate log level.
   246  		if !validLogLevel(logLevel) {
   247  			str := "The specified debug level [%v] is invalid"
   248  			return fmt.Errorf(str, logLevel)
   249  		}
   250  
   251  		setLogLevel(subsysID, logLevel)
   252  	}
   253  
   254  	return nil
   255  }
   256  
   257  // validDbType returns whether or not dbType is a supported database type.
   258  func validDbType(dbType string) bool {
   259  	for _, knownType := range knownDbTypes {
   260  		if dbType == knownType {
   261  			return true
   262  		}
   263  	}
   264  
   265  	return false
   266  }
   267  
   268  // removeDuplicateAddresses returns a new slice with all duplicate entries in
   269  // addrs removed.
   270  func removeDuplicateAddresses(addrs []string) []string {
   271  	result := make([]string, 0, len(addrs))
   272  	seen := map[string]struct{}{}
   273  	for _, val := range addrs {
   274  		if _, ok := seen[val]; !ok {
   275  			result = append(result, val)
   276  			seen[val] = struct{}{}
   277  		}
   278  	}
   279  	return result
   280  }
   281  
   282  // normalizeAddress returns addr with the passed default port appended if
   283  // there is not already a port specified.
   284  func normalizeAddress(addr, defaultPort string) string {
   285  	_, _, err := net.SplitHostPort(addr)
   286  	if err != nil {
   287  		return net.JoinHostPort(addr, defaultPort)
   288  	}
   289  	return addr
   290  }
   291  
   292  // normalizeAddresses returns a new slice with all the passed peer addresses
   293  // normalized with the given default port, and all duplicates removed.
   294  func normalizeAddresses(addrs []string, defaultPort string) []string {
   295  	for i, addr := range addrs {
   296  		addrs[i] = normalizeAddress(addr, defaultPort)
   297  	}
   298  
   299  	return removeDuplicateAddresses(addrs)
   300  }
   301  
   302  // filesExists reports whether the named file or directory exists.
   303  func fileExists(name string) bool {
   304  	if _, err := os.Stat(name); err != nil {
   305  		if os.IsNotExist(err) {
   306  			return false
   307  		}
   308  	}
   309  	return true
   310  }
   311  
   312  // newConfigParser returns a new command line flags parser.
   313  func newConfigParser(cfg *config, so *serviceOptions, options flags.Options) *flags.Parser {
   314  	parser := flags.NewParser(cfg, options)
   315  	if runtime.GOOS == "windows" {
   316  		parser.AddGroup("Service Options", "Service Options", so)
   317  	}
   318  	return parser
   319  }
   320  
   321  // loadConfig initializes and parses the config using a config file and command
   322  // line options.
   323  //
   324  // The configuration proceeds as follows:
   325  // 	1) Start with a default config with sane settings
   326  // 	2) Pre-parse the command line to check for an alternative config file
   327  // 	3) Load configuration file overwriting defaults with any specified options
   328  // 	4) Parse CLI options and overwrite/add any specified options
   329  //
   330  // The above results in btcd functioning properly without any config settings
   331  // while still allowing the user to override settings with config files and
   332  // command line options.  Command line options always take precedence.
   333  func loadConfig() (*config, []string, error) {
   334  	// Default config.
   335  	cfg := config{
   336  		ConfigFile:        defaultConfigFile,
   337  		DebugLevel:        defaultLogLevel,
   338  		MaxPeers:          defaultMaxPeers,
   339  		BanDuration:       defaultBanDuration,
   340  		BanThreshold:      defaultBanThreshold,
   341  		RPCMaxClients:     defaultMaxRPCClients,
   342  		RPCMaxWebsockets:  defaultMaxRPCWebsockets,
   343  		DataDir:           defaultDataDir,
   344  		LogDir:            defaultLogDir,
   345  		DbType:            defaultDbType,
   346  		RPCKey:            defaultRPCKeyFile,
   347  		RPCCert:           defaultRPCCertFile,
   348  		MinRelayTxFee:     defaultMinRelayTxFee.ToBTC(),
   349  		FreeTxRelayLimit:  defaultFreeTxRelayLimit,
   350  		BlockMinSize:      defaultBlockMinSize,
   351  		BlockMaxSize:      defaultBlockMaxSize,
   352  		BlockPrioritySize: defaultBlockPrioritySize,
   353  		MaxOrphanTxs:      defaultMaxOrphanTransactions,
   354  		SigCacheMaxSize:   defaultSigCacheMaxSize,
   355  		Generate:          defaultGenerate,
   356  		TxIndex:           defaultTxIndex,
   357  		AddrIndex:         defaultAddrIndex,
   358  	}
   359  
   360  	// Service options which are only added on Windows.
   361  	serviceOpts := serviceOptions{}
   362  
   363  	// Pre-parse the command line options to see if an alternative config
   364  	// file or the version flag was specified.  Any errors aside from the
   365  	// help message error can be ignored here since they will be caught by
   366  	// the final parse below.
   367  	preCfg := cfg
   368  	preParser := newConfigParser(&preCfg, &serviceOpts, flags.HelpFlag)
   369  	_, err := preParser.Parse()
   370  	if err != nil {
   371  		if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
   372  			fmt.Fprintln(os.Stderr, err)
   373  			return nil, nil, err
   374  		}
   375  	}
   376  
   377  	// Show the version and exit if the version flag was specified.
   378  	appName := filepath.Base(os.Args[0])
   379  	appName = strings.TrimSuffix(appName, filepath.Ext(appName))
   380  	usageMessage := fmt.Sprintf("Use %s -h to show usage", appName)
   381  	if preCfg.ShowVersion {
   382  		fmt.Println(appName, "version", version())
   383  		os.Exit(0)
   384  	}
   385  
   386  	// Perform service command and exit if specified.  Invalid service
   387  	// commands show an appropriate error.  Only runs on Windows since
   388  	// the runServiceCommand function will be nil when not on Windows.
   389  	if serviceOpts.ServiceCommand != "" && runServiceCommand != nil {
   390  		err := runServiceCommand(serviceOpts.ServiceCommand)
   391  		if err != nil {
   392  			fmt.Fprintln(os.Stderr, err)
   393  		}
   394  		os.Exit(0)
   395  	}
   396  
   397  	// Load additional config from file.
   398  	var configFileError error
   399  	parser := newConfigParser(&cfg, &serviceOpts, flags.Default)
   400  	if !(preCfg.RegressionTest || preCfg.SimNet) || preCfg.ConfigFile !=
   401  		defaultConfigFile {
   402  
   403  		if _, err := os.Stat(preCfg.ConfigFile); os.IsNotExist(err) {
   404  			err := createDefaultConfigFile(preCfg.ConfigFile)
   405  			if err != nil {
   406  				btcdLog.Warnf("Error creating a default config file: %v", err)
   407  			}
   408  		}
   409  
   410  		err := flags.NewIniParser(parser).ParseFile(preCfg.ConfigFile)
   411  		if err != nil {
   412  			if _, ok := err.(*os.PathError); !ok {
   413  				fmt.Fprintf(os.Stderr, "Error parsing config "+
   414  					"file: %v\n", err)
   415  				fmt.Fprintln(os.Stderr, usageMessage)
   416  				return nil, nil, err
   417  			}
   418  			configFileError = err
   419  		}
   420  	}
   421  
   422  	// Don't add peers from the config file when in regression test mode.
   423  	if preCfg.RegressionTest && len(cfg.AddPeers) > 0 {
   424  		cfg.AddPeers = nil
   425  	}
   426  
   427  	// Parse command line options again to ensure they take precedence.
   428  	remainingArgs, err := parser.Parse()
   429  	if err != nil {
   430  		if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
   431  			fmt.Fprintln(os.Stderr, usageMessage)
   432  		}
   433  		return nil, nil, err
   434  	}
   435  
   436  	// Create the home directory if it doesn't already exist.
   437  	funcName := "loadConfig"
   438  	err = os.MkdirAll(btcdHomeDir, 0700)
   439  	if err != nil {
   440  		// Show a nicer error message if it's because a symlink is
   441  		// linked to a directory that does not exist (probably because
   442  		// it's not mounted).
   443  		if e, ok := err.(*os.PathError); ok && os.IsExist(err) {
   444  			if link, lerr := os.Readlink(e.Path); lerr == nil {
   445  				str := "is symlink %s -> %s mounted?"
   446  				err = fmt.Errorf(str, e.Path, link)
   447  			}
   448  		}
   449  
   450  		str := "%s: Failed to create home directory: %v"
   451  		err := fmt.Errorf(str, funcName, err)
   452  		fmt.Fprintln(os.Stderr, err)
   453  		return nil, nil, err
   454  	}
   455  
   456  	// Multiple networks can't be selected simultaneously.
   457  	numNets := 0
   458  	// Count number of network flags passed; assign active network params
   459  	// while we're at it
   460  	if cfg.TestNet3 {
   461  		numNets++
   462  		activeNetParams = &testNet3Params
   463  	}
   464  	if cfg.RegressionTest {
   465  		numNets++
   466  		activeNetParams = &regressionNetParams
   467  	}
   468  	if cfg.SimNet {
   469  		numNets++
   470  		// Also disable dns seeding on the simulation test network.
   471  		activeNetParams = &simNetParams
   472  		cfg.DisableDNSSeed = true
   473  	}
   474  	if numNets > 1 {
   475  		str := "%s: The testnet, regtest, and simnet params can't be " +
   476  			"used together -- choose one of the three"
   477  		err := fmt.Errorf(str, funcName)
   478  		fmt.Fprintln(os.Stderr, err)
   479  		fmt.Fprintln(os.Stderr, usageMessage)
   480  		return nil, nil, err
   481  	}
   482  
   483  	// Append the network type to the data directory so it is "namespaced"
   484  	// per network.  In addition to the block database, there are other
   485  	// pieces of data that are saved to disk such as address manager state.
   486  	// All data is specific to a network, so namespacing the data directory
   487  	// means each individual piece of serialized data does not have to
   488  	// worry about changing names per network and such.
   489  	cfg.DataDir = cleanAndExpandPath(cfg.DataDir)
   490  	cfg.DataDir = filepath.Join(cfg.DataDir, netName(activeNetParams))
   491  
   492  	// Append the network type to the log directory so it is "namespaced"
   493  	// per network in the same fashion as the data directory.
   494  	cfg.LogDir = cleanAndExpandPath(cfg.LogDir)
   495  	cfg.LogDir = filepath.Join(cfg.LogDir, netName(activeNetParams))
   496  
   497  	// Special show command to list supported subsystems and exit.
   498  	if cfg.DebugLevel == "show" {
   499  		fmt.Println("Supported subsystems", supportedSubsystems())
   500  		os.Exit(0)
   501  	}
   502  
   503  	// Initialize logging at the default logging level.
   504  	initSeelogLogger(filepath.Join(cfg.LogDir, defaultLogFilename))
   505  	setLogLevels(defaultLogLevel)
   506  
   507  	// Parse, validate, and set debug log level(s).
   508  	if err := parseAndSetDebugLevels(cfg.DebugLevel); err != nil {
   509  		err := fmt.Errorf("%s: %v", funcName, err.Error())
   510  		fmt.Fprintln(os.Stderr, err)
   511  		fmt.Fprintln(os.Stderr, usageMessage)
   512  		return nil, nil, err
   513  	}
   514  
   515  	// Validate database type.
   516  	if !validDbType(cfg.DbType) {
   517  		str := "%s: The specified database type [%v] is invalid -- " +
   518  			"supported types %v"
   519  		err := fmt.Errorf(str, funcName, cfg.DbType, knownDbTypes)
   520  		fmt.Fprintln(os.Stderr, err)
   521  		fmt.Fprintln(os.Stderr, usageMessage)
   522  		return nil, nil, err
   523  	}
   524  
   525  	// Validate profile port number
   526  	if cfg.Profile != "" {
   527  		profilePort, err := strconv.Atoi(cfg.Profile)
   528  		if err != nil || profilePort < 1024 || profilePort > 65535 {
   529  			str := "%s: The profile port must be between 1024 and 65535"
   530  			err := fmt.Errorf(str, funcName)
   531  			fmt.Fprintln(os.Stderr, err)
   532  			fmt.Fprintln(os.Stderr, usageMessage)
   533  			return nil, nil, err
   534  		}
   535  	}
   536  
   537  	// Don't allow ban durations that are too short.
   538  	if cfg.BanDuration < time.Duration(time.Second) {
   539  		str := "%s: The banduration option may not be less than 1s -- parsed [%v]"
   540  		err := fmt.Errorf(str, funcName, cfg.BanDuration)
   541  		fmt.Fprintln(os.Stderr, err)
   542  		fmt.Fprintln(os.Stderr, usageMessage)
   543  		return nil, nil, err
   544  	}
   545  
   546  	// --addPeer and --connect do not mix.
   547  	if len(cfg.AddPeers) > 0 && len(cfg.ConnectPeers) > 0 {
   548  		str := "%s: the --addpeer and --connect options can not be " +
   549  			"mixed"
   550  		err := fmt.Errorf(str, funcName)
   551  		fmt.Fprintln(os.Stderr, err)
   552  		fmt.Fprintln(os.Stderr, usageMessage)
   553  		return nil, nil, err
   554  	}
   555  
   556  	// --proxy or --connect without --listen disables listening.
   557  	if (cfg.Proxy != "" || len(cfg.ConnectPeers) > 0) &&
   558  		len(cfg.Listeners) == 0 {
   559  		cfg.DisableListen = true
   560  	}
   561  
   562  	// Connect means no DNS seeding.
   563  	if len(cfg.ConnectPeers) > 0 {
   564  		cfg.DisableDNSSeed = true
   565  	}
   566  
   567  	// Add the default listener if none were specified. The default
   568  	// listener is all addresses on the listen port for the network
   569  	// we are to connect to.
   570  	if len(cfg.Listeners) == 0 {
   571  		cfg.Listeners = []string{
   572  			net.JoinHostPort("", activeNetParams.DefaultPort),
   573  		}
   574  	}
   575  
   576  	// Check to make sure limited and admin users don't have the same username
   577  	if cfg.RPCUser == cfg.RPCLimitUser && cfg.RPCUser != "" {
   578  		str := "%s: --rpcuser and --rpclimituser must not specify the " +
   579  			"same username"
   580  		err := fmt.Errorf(str, funcName)
   581  		fmt.Fprintln(os.Stderr, err)
   582  		fmt.Fprintln(os.Stderr, usageMessage)
   583  		return nil, nil, err
   584  	}
   585  
   586  	// Check to make sure limited and admin users don't have the same password
   587  	if cfg.RPCPass == cfg.RPCLimitPass && cfg.RPCPass != "" {
   588  		str := "%s: --rpcpass and --rpclimitpass must not specify the " +
   589  			"same password"
   590  		err := fmt.Errorf(str, funcName)
   591  		fmt.Fprintln(os.Stderr, err)
   592  		fmt.Fprintln(os.Stderr, usageMessage)
   593  		return nil, nil, err
   594  	}
   595  
   596  	// The RPC server is disabled if no username or password is provided.
   597  	if (cfg.RPCUser == "" || cfg.RPCPass == "") &&
   598  		(cfg.RPCLimitUser == "" || cfg.RPCLimitPass == "") {
   599  		cfg.DisableRPC = true
   600  	}
   601  
   602  	// Default RPC to listen on localhost only.
   603  	if !cfg.DisableRPC && len(cfg.RPCListeners) == 0 {
   604  		addrs, err := net.LookupHost("localhost")
   605  		if err != nil {
   606  			return nil, nil, err
   607  		}
   608  		cfg.RPCListeners = make([]string, 0, len(addrs))
   609  		for _, addr := range addrs {
   610  			addr = net.JoinHostPort(addr, activeNetParams.rpcPort)
   611  			cfg.RPCListeners = append(cfg.RPCListeners, addr)
   612  		}
   613  	}
   614  
   615  	// Validate the the minrelaytxfee.
   616  	cfg.minRelayTxFee, err = godashutil.NewAmount(cfg.MinRelayTxFee)
   617  	if err != nil {
   618  		str := "%s: invalid minrelaytxfee: %v"
   619  		err := fmt.Errorf(str, funcName, err)
   620  		fmt.Fprintln(os.Stderr, err)
   621  		fmt.Fprintln(os.Stderr, usageMessage)
   622  		return nil, nil, err
   623  	}
   624  
   625  	// Limit the max block size to a sane value.
   626  	if cfg.BlockMaxSize < blockMaxSizeMin || cfg.BlockMaxSize >
   627  		blockMaxSizeMax {
   628  
   629  		str := "%s: The blockmaxsize option must be in between %d " +
   630  			"and %d -- parsed [%d]"
   631  		err := fmt.Errorf(str, funcName, blockMaxSizeMin,
   632  			blockMaxSizeMax, cfg.BlockMaxSize)
   633  		fmt.Fprintln(os.Stderr, err)
   634  		fmt.Fprintln(os.Stderr, usageMessage)
   635  		return nil, nil, err
   636  	}
   637  
   638  	// Limit the max orphan count to a sane vlue.
   639  	if cfg.MaxOrphanTxs < 0 {
   640  		str := "%s: The maxorphantx option may not be less than 0 " +
   641  			"-- parsed [%d]"
   642  		err := fmt.Errorf(str, funcName, cfg.MaxOrphanTxs)
   643  		fmt.Fprintln(os.Stderr, err)
   644  		fmt.Fprintln(os.Stderr, usageMessage)
   645  		return nil, nil, err
   646  	}
   647  
   648  	// Limit the block priority and minimum block sizes to max block size.
   649  	cfg.BlockPrioritySize = minUint32(cfg.BlockPrioritySize, cfg.BlockMaxSize)
   650  	cfg.BlockMinSize = minUint32(cfg.BlockMinSize, cfg.BlockMaxSize)
   651  
   652  	// --txindex and --droptxindex do not mix.
   653  	if cfg.TxIndex && cfg.DropTxIndex {
   654  		err := fmt.Errorf("%s: the --txindex and --droptxindex "+
   655  			"options may  not be activated at the same time",
   656  			funcName)
   657  		fmt.Fprintln(os.Stderr, err)
   658  		fmt.Fprintln(os.Stderr, usageMessage)
   659  		return nil, nil, err
   660  	}
   661  
   662  	// --addrindex and --dropaddrindex do not mix.
   663  	if cfg.AddrIndex && cfg.DropAddrIndex {
   664  		err := fmt.Errorf("%s: the --addrindex and --dropaddrindex "+
   665  			"options may not be activated at the same time",
   666  			funcName)
   667  		fmt.Fprintln(os.Stderr, err)
   668  		fmt.Fprintln(os.Stderr, usageMessage)
   669  		return nil, nil, err
   670  	}
   671  
   672  	// --addrindex and --droptxindex do not mix.
   673  	if cfg.AddrIndex && cfg.DropTxIndex {
   674  		err := fmt.Errorf("%s: the --addrindex and --droptxindex "+
   675  			"options may not be activated at the same time "+
   676  			"because the address index relies on the transaction "+
   677  			"index",
   678  			funcName)
   679  		fmt.Fprintln(os.Stderr, err)
   680  		fmt.Fprintln(os.Stderr, usageMessage)
   681  		return nil, nil, err
   682  	}
   683  
   684  	// Check getwork keys are valid and saved parsed versions.
   685  	cfg.miningAddrs = make([]godashutil.Address, 0, len(cfg.GetWorkKeys)+
   686  		len(cfg.MiningAddrs))
   687  	for _, strAddr := range cfg.GetWorkKeys {
   688  		addr, err := godashutil.DecodeAddress(strAddr,
   689  			activeNetParams.Params)
   690  		if err != nil {
   691  			str := "%s: getworkkey '%s' failed to decode: %v"
   692  			err := fmt.Errorf(str, funcName, strAddr, err)
   693  			fmt.Fprintln(os.Stderr, err)
   694  			fmt.Fprintln(os.Stderr, usageMessage)
   695  			return nil, nil, err
   696  		}
   697  		if !addr.IsForNet(activeNetParams.Params) {
   698  			str := "%s: getworkkey '%s' is on the wrong network"
   699  			err := fmt.Errorf(str, funcName, strAddr)
   700  			fmt.Fprintln(os.Stderr, err)
   701  			fmt.Fprintln(os.Stderr, usageMessage)
   702  			return nil, nil, err
   703  		}
   704  		cfg.miningAddrs = append(cfg.miningAddrs, addr)
   705  	}
   706  
   707  	// Check mining addresses are valid and saved parsed versions.
   708  	for _, strAddr := range cfg.MiningAddrs {
   709  		addr, err := godashutil.DecodeAddress(strAddr, activeNetParams.Params)
   710  		if err != nil {
   711  			str := "%s: mining address '%s' failed to decode: %v"
   712  			err := fmt.Errorf(str, funcName, strAddr, err)
   713  			fmt.Fprintln(os.Stderr, err)
   714  			fmt.Fprintln(os.Stderr, usageMessage)
   715  			return nil, nil, err
   716  		}
   717  		if !addr.IsForNet(activeNetParams.Params) {
   718  			str := "%s: mining address '%s' is on the wrong network"
   719  			err := fmt.Errorf(str, funcName, strAddr)
   720  			fmt.Fprintln(os.Stderr, err)
   721  			fmt.Fprintln(os.Stderr, usageMessage)
   722  			return nil, nil, err
   723  		}
   724  		cfg.miningAddrs = append(cfg.miningAddrs, addr)
   725  	}
   726  
   727  	// Ensure there is at least one mining address when the generate flag is
   728  	// set.
   729  	if cfg.Generate && len(cfg.MiningAddrs) == 0 {
   730  		str := "%s: the generate flag is set, but there are no mining " +
   731  			"addresses specified "
   732  		err := fmt.Errorf(str, funcName)
   733  		fmt.Fprintln(os.Stderr, err)
   734  		fmt.Fprintln(os.Stderr, usageMessage)
   735  		return nil, nil, err
   736  	}
   737  
   738  	// Add default port to all listener addresses if needed and remove
   739  	// duplicate addresses.
   740  	cfg.Listeners = normalizeAddresses(cfg.Listeners,
   741  		activeNetParams.DefaultPort)
   742  
   743  	// Add default port to all rpc listener addresses if needed and remove
   744  	// duplicate addresses.
   745  	cfg.RPCListeners = normalizeAddresses(cfg.RPCListeners,
   746  		activeNetParams.rpcPort)
   747  
   748  	// Only allow TLS to be disabled if the RPC is bound to localhost
   749  	// addresses.
   750  	if !cfg.DisableRPC && cfg.DisableTLS {
   751  		allowedTLSListeners := map[string]struct{}{
   752  			"localhost": {},
   753  			"127.0.0.1": {},
   754  			"::1":       {},
   755  		}
   756  		for _, addr := range cfg.RPCListeners {
   757  			host, _, err := net.SplitHostPort(addr)
   758  			if err != nil {
   759  				str := "%s: RPC listen interface '%s' is " +
   760  					"invalid: %v"
   761  				err := fmt.Errorf(str, funcName, addr, err)
   762  				fmt.Fprintln(os.Stderr, err)
   763  				fmt.Fprintln(os.Stderr, usageMessage)
   764  				return nil, nil, err
   765  			}
   766  			if _, ok := allowedTLSListeners[host]; !ok {
   767  				str := "%s: the --notls option may not be used " +
   768  					"when binding RPC to non localhost " +
   769  					"addresses: %s"
   770  				err := fmt.Errorf(str, funcName, addr)
   771  				fmt.Fprintln(os.Stderr, err)
   772  				fmt.Fprintln(os.Stderr, usageMessage)
   773  				return nil, nil, err
   774  			}
   775  		}
   776  	}
   777  
   778  	// Add default port to all added peer addresses if needed and remove
   779  	// duplicate addresses.
   780  	cfg.AddPeers = normalizeAddresses(cfg.AddPeers,
   781  		activeNetParams.DefaultPort)
   782  	cfg.ConnectPeers = normalizeAddresses(cfg.ConnectPeers,
   783  		activeNetParams.DefaultPort)
   784  
   785  	// Tor stream isolation requires either proxy or onion proxy to be set.
   786  	if cfg.TorIsolation && cfg.Proxy == "" && cfg.OnionProxy == "" {
   787  		str := "%s: Tor stream isolation requires either proxy or " +
   788  			"onionproxy to be set"
   789  		err := fmt.Errorf(str, funcName)
   790  		fmt.Fprintln(os.Stderr, err)
   791  		fmt.Fprintln(os.Stderr, usageMessage)
   792  		return nil, nil, err
   793  	}
   794  
   795  	// Setup dial and DNS resolution (lookup) functions depending on the
   796  	// specified options.  The default is to use the standard net.Dial
   797  	// function as well as the system DNS resolver.  When a proxy is
   798  	// specified, the dial function is set to the proxy specific dial
   799  	// function and the lookup is set to use tor (unless --noonion is
   800  	// specified in which case the system DNS resolver is used).
   801  	cfg.dial = net.Dial
   802  	cfg.lookup = net.LookupIP
   803  	if cfg.Proxy != "" {
   804  		_, _, err := net.SplitHostPort(cfg.Proxy)
   805  		if err != nil {
   806  			str := "%s: Proxy address '%s' is invalid: %v"
   807  			err := fmt.Errorf(str, funcName, cfg.Proxy, err)
   808  			fmt.Fprintln(os.Stderr, err)
   809  			fmt.Fprintln(os.Stderr, usageMessage)
   810  			return nil, nil, err
   811  		}
   812  
   813  		if cfg.TorIsolation &&
   814  			(cfg.ProxyUser != "" || cfg.ProxyPass != "") {
   815  			btcdLog.Warn("Tor isolation set -- overriding " +
   816  				"specified proxy user credentials")
   817  		}
   818  
   819  		proxy := &socks.Proxy{
   820  			Addr:         cfg.Proxy,
   821  			Username:     cfg.ProxyUser,
   822  			Password:     cfg.ProxyPass,
   823  			TorIsolation: cfg.TorIsolation,
   824  		}
   825  		cfg.dial = proxy.Dial
   826  		if !cfg.NoOnion {
   827  			cfg.lookup = func(host string) ([]net.IP, error) {
   828  				return torLookupIP(host, cfg.Proxy)
   829  			}
   830  		}
   831  	}
   832  
   833  	// Setup onion address dial and DNS resolution (lookup) functions
   834  	// depending on the specified options.  The default is to use the
   835  	// same dial and lookup functions selected above.  However, when an
   836  	// onion-specific proxy is specified, the onion address dial and
   837  	// lookup functions are set to use the onion-specific proxy while
   838  	// leaving the normal dial and lookup functions as selected above.
   839  	// This allows .onion address traffic to be routed through a different
   840  	// proxy than normal traffic.
   841  	if cfg.OnionProxy != "" {
   842  		_, _, err := net.SplitHostPort(cfg.OnionProxy)
   843  		if err != nil {
   844  			str := "%s: Onion proxy address '%s' is invalid: %v"
   845  			err := fmt.Errorf(str, funcName, cfg.OnionProxy, err)
   846  			fmt.Fprintln(os.Stderr, err)
   847  			fmt.Fprintln(os.Stderr, usageMessage)
   848  			return nil, nil, err
   849  		}
   850  
   851  		if cfg.TorIsolation &&
   852  			(cfg.OnionProxyUser != "" || cfg.OnionProxyPass != "") {
   853  			btcdLog.Warn("Tor isolation set -- overriding " +
   854  				"specified onionproxy user credentials ")
   855  		}
   856  
   857  		cfg.oniondial = func(a, b string) (net.Conn, error) {
   858  			proxy := &socks.Proxy{
   859  				Addr:         cfg.OnionProxy,
   860  				Username:     cfg.OnionProxyUser,
   861  				Password:     cfg.OnionProxyPass,
   862  				TorIsolation: cfg.TorIsolation,
   863  			}
   864  			return proxy.Dial(a, b)
   865  		}
   866  		cfg.onionlookup = func(host string) ([]net.IP, error) {
   867  			return torLookupIP(host, cfg.OnionProxy)
   868  		}
   869  	} else {
   870  		cfg.oniondial = cfg.dial
   871  		cfg.onionlookup = cfg.lookup
   872  	}
   873  
   874  	// Specifying --noonion means the onion address dial and DNS resolution
   875  	// (lookup) functions result in an error.
   876  	if cfg.NoOnion {
   877  		cfg.oniondial = func(a, b string) (net.Conn, error) {
   878  			return nil, errors.New("tor has been disabled")
   879  		}
   880  		cfg.onionlookup = func(a string) ([]net.IP, error) {
   881  			return nil, errors.New("tor has been disabled")
   882  		}
   883  	}
   884  
   885  	// Warn about missing config file only after all other configuration is
   886  	// done.  This prevents the warning on help messages and invalid
   887  	// options.  Note this should go directly before the return.
   888  	if configFileError != nil {
   889  		btcdLog.Warnf("%v", configFileError)
   890  	}
   891  
   892  	return &cfg, remainingArgs, nil
   893  }
   894  
   895  // createDefaultConfig copies the file sample-btcd.conf to the given destination path,
   896  // and populates it with some randomly generated RPC username and password.
   897  func createDefaultConfigFile(destinationPath string) error {
   898  	// Create the destination directory if it does not exists
   899  	os.MkdirAll(filepath.Dir(destinationPath), 0700)
   900  
   901  	// We get the sample config file path, which is in the same directory as this file.
   902  	_, path, _, _ := runtime.Caller(0)
   903  	sampleConfigPath := filepath.Join(filepath.Dir(path), "sample-btcd.conf")
   904  
   905  	// We generate a random user and password
   906  	randomBytes := make([]byte, 20)
   907  	_, err := rand.Read(randomBytes)
   908  	if err != nil {
   909  		return err
   910  	}
   911  	generatedRPCUser := base64.StdEncoding.EncodeToString(randomBytes)
   912  
   913  	_, err = rand.Read(randomBytes)
   914  	if err != nil {
   915  		return err
   916  	}
   917  	generatedRPCPass := base64.StdEncoding.EncodeToString(randomBytes)
   918  
   919  	src, err := os.Open(sampleConfigPath)
   920  	if err != nil {
   921  		return err
   922  	}
   923  	defer src.Close()
   924  
   925  	dest, err := os.OpenFile(destinationPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0700)
   926  	if err != nil {
   927  		return err
   928  	}
   929  	defer dest.Close()
   930  
   931  	// We copy every line from the sample config file to the destination,
   932  	// only replacing the two lines for rpcuser and rpcpass
   933  	reader := bufio.NewReader(src)
   934  	for err != io.EOF {
   935  		var line string
   936  		line, err = reader.ReadString('\n')
   937  		if err != nil && err != io.EOF {
   938  			return err
   939  		}
   940  
   941  		if strings.Contains(line, "rpcuser=") {
   942  			line = "rpcuser=" + string(generatedRPCUser) + "\n"
   943  		} else if strings.Contains(line, "rpcpass=") {
   944  			line = "rpcpass=" + string(generatedRPCPass) + "\n"
   945  		}
   946  
   947  		if _, err := dest.WriteString(line); err != nil {
   948  			return err
   949  		}
   950  	}
   951  
   952  	return nil
   953  }
   954  
   955  // btcdDial connects to the address on the named network using the appropriate
   956  // dial function depending on the address and configuration options.  For
   957  // example, .onion addresses will be dialed using the onion specific proxy if
   958  // one was specified, but will otherwise use the normal dial function (which
   959  // could itself use a proxy or not).
   960  func btcdDial(network, address string) (net.Conn, error) {
   961  	if strings.Contains(address, ".onion:") {
   962  		return cfg.oniondial(network, address)
   963  	}
   964  	return cfg.dial(network, address)
   965  }
   966  
   967  // btcdLookup returns the correct DNS lookup function to use depending on the
   968  // passed host and configuration options.  For example, .onion addresses will be
   969  // resolved using the onion specific proxy if one was specified, but will
   970  // otherwise treat the normal proxy as tor unless --noonion was specified in
   971  // which case the lookup will fail.  Meanwhile, normal IP addresses will be
   972  // resolved using tor if a proxy was specified unless --noonion was also
   973  // specified in which case the normal system DNS resolver will be used.
   974  func btcdLookup(host string) ([]net.IP, error) {
   975  	if strings.HasSuffix(host, ".onion") {
   976  		return cfg.onionlookup(host)
   977  	}
   978  	return cfg.lookup(host)
   979  }