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.
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"
36 defaultConfigFilename = "btcd.conf"
37 defaultDataDirname = "data"
38 defaultLogLevel = "info"
39 defaultLogDirname = "logs"
40 defaultLogFilename = "btcd.log"
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
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)
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
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 {
90 // config defines the configuration options for btcd.
92 // See loadConfig for details on the configuration load process.
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
170 // serviceOptions defines the configuration options for the daemon as a service on
172 type serviceOptions struct {
173 ServiceCommand string `short:"s" long:"service" description:"Service command {install, remove, start, stop}"`
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)
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))
190 // validLogLevel returns whether or not logLevel is a valid debug log level.
191 func validLogLevel(logLevel string) bool {
209 // supportedSubsystems returns a sorted slice of the supported subsystems for
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)
218 // Sort the subsystems for stable display.
219 sort.Strings(subsystems)
223 // parseAndSetDebugLevels attempts to parse the specified debug level and set
224 // the levels accordingly. An appropriate error is returned if anything is
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)
236 // Change the logging level for all subsystems.
237 setLogLevels(debugLevel)
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)
251 // Extract the specified subsystem and log level.
252 fields := strings.Split(logLevelPair, "=")
253 subsysID, logLevel := fields[0], fields[1]
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())
262 // Validate log level.
263 if !validLogLevel(logLevel) {
264 str := "The specified debug level [%v] is invalid"
265 return fmt.Errorf(str, logLevel)
268 setLogLevel(subsysID, logLevel)
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 {
285 // removeDuplicateAddresses returns a new slice with all duplicate entries in
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{}{}
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)
304 return net.JoinHostPort(addr, defaultPort)
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)
316 return removeDuplicateAddresses(addrs)
319 // newCheckpointFromStr parses checkpoints in the '<height>:<hash>' format.
320 func newCheckpointFromStr(checkpoint string) (chaincfg.Checkpoint, error) {
321 parts := strings.Split(checkpoint, ":")
323 return chaincfg.Checkpoint{}, fmt.Errorf("unable to parse "+
324 "checkpoint %q -- use the syntax <height>:<hash>",
328 height, err := strconv.ParseInt(parts[0], 10, 32)
330 return chaincfg.Checkpoint{}, fmt.Errorf("unable to parse "+
331 "checkpoint %q due to malformed height", checkpoint)
334 if len(parts[1]) == 0 {
335 return chaincfg.Checkpoint{}, fmt.Errorf("unable to parse "+
336 "checkpoint %q due to missing hash", checkpoint)
338 hash, err := chainhash.NewHashFromStr(parts[1])
340 return chaincfg.Checkpoint{}, fmt.Errorf("unable to parse "+
341 "checkpoint %q due to malformed hash", checkpoint)
344 return chaincfg.Checkpoint{
345 Height: int32(height),
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 {
356 checkpoints := make([]chaincfg.Checkpoint, len(checkpointStrings))
357 for i, cpString := range checkpointStrings {
358 checkpoint, err := newCheckpointFromStr(cpString)
362 checkpoints[i] = checkpoint
364 return checkpoints, nil
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) {
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)
386 // loadConfig initializes and parses the config using a config file and command
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
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) {
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,
428 // Service options which are only added on Windows.
429 serviceOpts := serviceOptions{}
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.
436 preParser := newConfigParser(&preCfg, &serviceOpts, flags.HelpFlag)
437 _, err := preParser.Parse()
439 if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
440 fmt.Fprintln(os.Stderr, err)
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())
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)
460 fmt.Fprintln(os.Stderr, err)
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 !=
471 if _, err := os.Stat(preCfg.ConfigFile); os.IsNotExist(err) {
472 err := createDefaultConfigFile(preCfg.ConfigFile)
474 fmt.Fprintf(os.Stderr, "Error creating a "+
475 "default config file: %v\n", err)
479 err := flags.NewIniParser(parser).ParseFile(preCfg.ConfigFile)
481 if _, ok := err.(*os.PathError); !ok {
482 fmt.Fprintf(os.Stderr, "Error parsing config "+
484 fmt.Fprintln(os.Stderr, usageMessage)
487 configFileError = err
491 // Don't add peers from the config file when in regression test mode.
492 if preCfg.RegressionTest && len(cfg.AddPeers) > 0 {
496 // Parse command line options again to ensure they take precedence.
497 remainingArgs, err := parser.Parse()
499 if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
500 fmt.Fprintln(os.Stderr, usageMessage)
505 // Create the home directory if it doesn't already exist.
506 funcName := "loadConfig"
507 err = os.MkdirAll(defaultHomeDir, 0700)
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)
519 str := "%s: Failed to create home directory: %v"
520 err := fmt.Errorf(str, funcName, err)
521 fmt.Fprintln(os.Stderr, err)
525 // Multiple networks can't be selected simultaneously.
527 // Count number of network flags passed; assign active network params
531 activeNetParams = &testNet3Params
533 if cfg.RegressionTest {
535 activeNetParams = ®ressionNetParams
539 // Also disable dns seeding on the simulation test network.
540 activeNetParams = &simNetParams
541 cfg.DisableDNSSeed = true
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)
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
556 relayNonStd := activeNetParams.RelayNonStdTxs
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)
565 case cfg.RejectNonStd:
567 case cfg.RelayNonStd:
570 cfg.RelayNonStd = relayNonStd
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))
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))
586 // Special show command to list supported subsystems and exit.
587 if cfg.DebugLevel == "show" {
588 fmt.Println("Supported subsystems", supportedSubsystems())
592 // Initialize log rotation. After log rotation has been initialized, the
593 // logger variables may be used.
594 initLogRotator(filepath.Join(cfg.LogDir, defaultLogFilename))
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)
604 // Validate database type.
605 if !validDbType(cfg.DbType) {
606 str := "%s: The specified database type [%v] is invalid -- " +
608 err := fmt.Errorf(str, funcName, cfg.DbType, knownDbTypes)
609 fmt.Fprintln(os.Stderr, err)
610 fmt.Fprintln(os.Stderr, usageMessage)
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)
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)
635 // Validate any given whitelisted IP addresses and networks.
636 if len(cfg.Whitelists) > 0 {
638 cfg.whitelists = make([]*net.IPNet, 0, len(cfg.Whitelists))
640 for _, addr := range cfg.Whitelists {
641 _, ipnet, err := net.ParseCIDR(addr)
643 ip = net.ParseIP(addr)
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)
660 Mask: net.CIDRMask(bits, bits),
663 cfg.whitelists = append(cfg.whitelists, ipnet)
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 " +
671 err := fmt.Errorf(str, funcName)
672 fmt.Fprintln(os.Stderr, err)
673 fmt.Fprintln(os.Stderr, usageMessage)
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
683 // Connect means no DNS seeding.
684 if len(cfg.ConnectPeers) > 0 {
685 cfg.DisableDNSSeed = true
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),
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 " +
701 err := fmt.Errorf(str, funcName)
702 fmt.Fprintln(os.Stderr, err)
703 fmt.Fprintln(os.Stderr, usageMessage)
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 " +
711 err := fmt.Errorf(str, funcName)
712 fmt.Fprintln(os.Stderr, err)
713 fmt.Fprintln(os.Stderr, usageMessage)
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
724 btcdLog.Infof("RPC service is disabled")
727 // Default RPC to listen on localhost only.
728 if !cfg.DisableRPC && len(cfg.RPCListeners) == 0 {
729 addrs, err := net.LookupHost("localhost")
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)
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)
749 // Validate the the minrelaytxfee.
750 cfg.minRelayTxFee, err = btcutil.NewAmount(cfg.MinRelayTxFee)
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)
759 // Limit the max block size to a sane value.
760 if cfg.BlockMaxSize < blockMaxSizeMin || cfg.BlockMaxSize >
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)
772 // Limit the max block weight to a sane value.
773 if cfg.BlockMaxWeight < blockMaxWeightMin ||
774 cfg.BlockMaxWeight > blockMaxWeightMax {
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)
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 " +
789 err := fmt.Errorf(str, funcName, cfg.MaxOrphanTxs)
790 fmt.Fprintln(os.Stderr, err)
791 fmt.Fprintln(os.Stderr, usageMessage)
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)
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
804 case cfg.BlockMaxSize == defaultBlockMaxSize &&
805 cfg.BlockMaxWeight != defaultBlockMaxWeight:
807 cfg.BlockMaxSize = blockchain.MaxBlockBaseSize - 1000
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:
814 cfg.BlockMaxWeight = cfg.BlockMaxSize * blockchain.WitnessScaleFactor
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: '/', ':', '(', ')'",
823 fmt.Fprintln(os.Stderr, err)
824 fmt.Fprintln(os.Stderr, usageMessage)
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",
834 fmt.Fprintln(os.Stderr, err)
835 fmt.Fprintln(os.Stderr, usageMessage)
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",
844 fmt.Fprintln(os.Stderr, err)
845 fmt.Fprintln(os.Stderr, usageMessage)
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 "+
856 fmt.Fprintln(os.Stderr, err)
857 fmt.Fprintln(os.Stderr, usageMessage)
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)
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)
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)
879 cfg.miningAddrs = append(cfg.miningAddrs, addr)
882 // Ensure there is at least one mining address when the generate flag is
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)
893 // Add default port to all listener addresses if needed and remove
894 // duplicate addresses.
895 cfg.Listeners = normalizeAddresses(cfg.Listeners,
896 activeNetParams.DefaultPort)
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)
903 // Only allow TLS to be disabled if the RPC is bound to localhost
905 if !cfg.DisableRPC && cfg.DisableTLS {
906 allowedTLSListeners := map[string]struct{}{
911 for _, addr := range cfg.RPCListeners {
912 host, _, err := net.SplitHostPort(addr)
914 str := "%s: RPC listen interface '%s' is " +
916 err := fmt.Errorf(str, funcName, addr, err)
917 fmt.Fprintln(os.Stderr, err)
918 fmt.Fprintln(os.Stderr, usageMessage)
921 if _, ok := allowedTLSListeners[host]; !ok {
922 str := "%s: the --notls option may not be used " +
923 "when binding RPC to non localhost " +
925 err := fmt.Errorf(str, funcName, addr)
926 fmt.Fprintln(os.Stderr, err)
927 fmt.Fprintln(os.Stderr, usageMessage)
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)
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)
949 // Check the checkpoints for syntax errors.
950 cfg.addCheckpoints, err = parseCheckpoints(cfg.AddCheckpoints)
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)
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)
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
978 _, _, err := net.SplitHostPort(cfg.Proxy)
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)
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 != "") {
995 fmt.Fprintln(os.Stderr, "Tor isolation set -- "+
996 "overriding specified proxy user credentials")
999 proxy := &socks.Proxy{
1001 Username: cfg.ProxyUser,
1002 Password: cfg.ProxyPass,
1003 TorIsolation: torIsolation,
1005 cfg.dial = proxy.DialTimeout
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)
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)
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
1033 // Tor isolation flag means onion proxy credentials will be
1035 if cfg.TorIsolation &&
1036 (cfg.OnionProxyUser != "" || cfg.OnionProxyPass != "") {
1037 fmt.Fprintln(os.Stderr, "Tor isolation set -- "+
1038 "overriding specified onionproxy user "+
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,
1049 return proxy.DialTimeout(network, addr, timeout)
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)
1062 cfg.oniondial = cfg.dial
1065 // Specifying --noonion means the onion address dial function results in
1068 cfg.oniondial = func(a, b string, t time.Duration) (net.Conn, error) {
1069 return nil, errors.New("tor has been disabled")
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)
1080 return &cfg, remainingArgs, nil
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)
1092 // We assume sample config file path is same as binary
1093 path, err := filepath.Abs(filepath.Dir(os.Args[0]))
1097 sampleConfigPath := filepath.Join(path, sampleConfigFilename)
1099 // We generate a random user and password
1100 randomBytes := make([]byte, 20)
1101 _, err = rand.Read(randomBytes)
1105 generatedRPCUser := base64.StdEncoding.EncodeToString(randomBytes)
1107 _, err = rand.Read(randomBytes)
1111 generatedRPCPass := base64.StdEncoding.EncodeToString(randomBytes)
1113 src, err := os.Open(sampleConfigPath)
1119 dest, err := os.OpenFile(destinationPath,
1120 os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
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)
1131 line, err = reader.ReadString('\n')
1132 if err != nil && err != io.EOF {
1136 if strings.Contains(line, "rpcuser=") {
1137 line = "rpcuser=" + generatedRPCUser + "\n"
1138 } else if strings.Contains(line, "rpcpass=") {
1139 line = "rpcpass=" + generatedRPCPass + "\n"
1142 if _, err := dest.WriteString(line); err != nil {
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)
1160 return cfg.dial(addr.Network(), addr.String(), defaultConnectTimeout)
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.
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)
1175 return cfg.lookup(host)