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