OSDN Git Service

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