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