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