Separate out default ports and utility funcs.
This change moves the chain and network parameter definitions, along with the default client and server ports, to a package for reuse by other utilities (most notably, tools in the cmd dir). Along with it, functions commonly used for config parsing and validation are moved to an internal package since they will also be useful for distributed tools.
This commit is contained in:
parent
5482feecf4
commit
b0566e09c8
7 changed files with 214 additions and 106 deletions
115
config.go
115
config.go
|
@ -25,7 +25,9 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcwallet/internal/cfgutil"
|
||||
"github.com/btcsuite/btcwallet/internal/legacy/keystore"
|
||||
"github.com/btcsuite/btcwallet/netparams"
|
||||
flags "github.com/btcsuite/go-flags"
|
||||
)
|
||||
|
||||
|
@ -194,50 +196,6 @@ func parseAndSetDebugLevels(debugLevel string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// removeDuplicateAddresses returns a new slice with all duplicate entries in
|
||||
// addrs removed.
|
||||
func removeDuplicateAddresses(addrs []string) []string {
|
||||
result := []string{}
|
||||
seen := map[string]bool{}
|
||||
for _, val := range addrs {
|
||||
if _, ok := seen[val]; !ok {
|
||||
result = append(result, val)
|
||||
seen[val] = true
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// normalizeAddresses returns a new slice with all the passed peer addresses
|
||||
// normalized with the given default port, and all duplicates removed.
|
||||
func normalizeAddresses(addrs []string, defaultPort string) []string {
|
||||
for i, addr := range addrs {
|
||||
addrs[i] = normalizeAddress(addr, defaultPort)
|
||||
}
|
||||
|
||||
return removeDuplicateAddresses(addrs)
|
||||
}
|
||||
|
||||
// filesExists reports whether the named file or directory exists.
|
||||
func fileExists(name string) bool {
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// normalizeAddress returns addr with the passed default port appended if
|
||||
// there is not already a port specified.
|
||||
func normalizeAddress(addr, defaultPort string) string {
|
||||
_, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return net.JoinHostPort(addr, defaultPort)
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// loadConfig initializes and parses the config using a config file and command
|
||||
// line options.
|
||||
//
|
||||
|
@ -266,7 +224,12 @@ func loadConfig() (*config, []string, error) {
|
|||
}
|
||||
|
||||
// A config file in the current directory takes precedence.
|
||||
if fileExists(defaultConfigFilename) {
|
||||
exists, err := cfgutil.FileExists(defaultConfigFilename)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return nil, nil, err
|
||||
}
|
||||
if exists {
|
||||
cfg.ConfigFile = defaultConfigFile
|
||||
}
|
||||
|
||||
|
@ -274,7 +237,7 @@ func loadConfig() (*config, []string, error) {
|
|||
// file or the version flag was specified.
|
||||
preCfg := cfg
|
||||
preParser := flags.NewParser(&preCfg, flags.Default)
|
||||
_, err := preParser.Parse()
|
||||
_, err = preParser.Parse()
|
||||
if err != nil {
|
||||
if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
|
||||
preParser.WriteHelp(os.Stderr)
|
||||
|
@ -337,11 +300,11 @@ func loadConfig() (*config, []string, error) {
|
|||
// Multiple networks can't be selected simultaneously.
|
||||
numNets := 0
|
||||
if cfg.MainNet {
|
||||
activeNet = &mainNetParams
|
||||
activeNet = &netparams.MainNetParams
|
||||
numNets++
|
||||
}
|
||||
if cfg.SimNet {
|
||||
activeNet = &simNetParams
|
||||
activeNet = &netparams.SimNetParams
|
||||
numNets++
|
||||
}
|
||||
if numNets > 1 {
|
||||
|
@ -403,10 +366,16 @@ func loadConfig() (*config, []string, error) {
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
dbFileExists, err := cfgutil.FileExists(dbPath)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if cfg.CreateTemp {
|
||||
tempWalletExists := false
|
||||
|
||||
if fileExists(dbPath) {
|
||||
if dbFileExists {
|
||||
str := fmt.Sprintf("The wallet already exists. Loading this " +
|
||||
"wallet instead.")
|
||||
fmt.Fprintln(os.Stdout, str)
|
||||
|
@ -429,7 +398,7 @@ func loadConfig() (*config, []string, error) {
|
|||
} else if cfg.Create {
|
||||
// Error if the create flag is set and the wallet already
|
||||
// exists.
|
||||
if fileExists(dbPath) {
|
||||
if dbFileExists {
|
||||
err := fmt.Errorf("The wallet already exists.")
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return nil, nil, err
|
||||
|
@ -449,10 +418,14 @@ func loadConfig() (*config, []string, error) {
|
|||
|
||||
// Created successfully, so exit now with success.
|
||||
os.Exit(0)
|
||||
} else if !fileExists(dbPath) {
|
||||
var err error
|
||||
} else if !dbFileExists {
|
||||
keystorePath := filepath.Join(netDir, keystore.Filename)
|
||||
if !fileExists(keystorePath) {
|
||||
keystoreExists, err := cfgutil.FileExists(keystorePath)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return nil, nil, err
|
||||
}
|
||||
if !keystoreExists {
|
||||
err = fmt.Errorf("The wallet does not exist. Run with the " +
|
||||
"--create option to initialize and create it.")
|
||||
} else {
|
||||
|
@ -464,11 +437,17 @@ func loadConfig() (*config, []string, error) {
|
|||
}
|
||||
|
||||
if cfg.RPCConnect == "" {
|
||||
cfg.RPCConnect = activeNet.connect
|
||||
cfg.RPCConnect = net.JoinHostPort("localhost", activeNet.RPCClientPort)
|
||||
}
|
||||
|
||||
// Add default port to connect flag if missing.
|
||||
cfg.RPCConnect = normalizeAddress(cfg.RPCConnect, activeNet.btcdPort)
|
||||
cfg.RPCConnect, err = cfgutil.NormalizeAddress(cfg.RPCConnect,
|
||||
activeNet.RPCClientPort)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
"Invalid rpcconnect network address: %v\n", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
localhostListeners := map[string]struct{}{
|
||||
"localhost": struct{}{},
|
||||
|
@ -496,9 +475,20 @@ func loadConfig() (*config, []string, error) {
|
|||
|
||||
// If the CA copy does not exist, check if we're connecting to
|
||||
// a local btcd and switch to its RPC cert if it exists.
|
||||
if !fileExists(cfg.CAFile) {
|
||||
certExists, err := cfgutil.FileExists(cfg.CAFile)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return nil, nil, err
|
||||
}
|
||||
if !certExists {
|
||||
if _, ok := localhostListeners[RPCHost]; ok {
|
||||
if fileExists(btcdHomedirCAFile) {
|
||||
btcdCertExists, err := cfgutil.FileExists(
|
||||
btcdHomedirCAFile)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return nil, nil, err
|
||||
}
|
||||
if btcdCertExists {
|
||||
cfg.CAFile = btcdHomedirCAFile
|
||||
}
|
||||
}
|
||||
|
@ -513,15 +503,20 @@ func loadConfig() (*config, []string, error) {
|
|||
}
|
||||
cfg.SvrListeners = make([]string, 0, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
addr = net.JoinHostPort(addr, activeNet.svrPort)
|
||||
addr = net.JoinHostPort(addr, activeNet.RPCServerPort)
|
||||
cfg.SvrListeners = append(cfg.SvrListeners, addr)
|
||||
}
|
||||
}
|
||||
|
||||
// Add default port to all rpc listener addresses if needed and remove
|
||||
// duplicate addresses.
|
||||
cfg.SvrListeners = normalizeAddresses(cfg.SvrListeners,
|
||||
activeNet.svrPort)
|
||||
cfg.SvrListeners, err = cfgutil.NormalizeAddresses(
|
||||
cfg.SvrListeners, activeNet.RPCServerPort)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
"Invalid network address in RPC listeners: %v\n", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Only allow server TLS to be disabled if the RPC is bound to localhost
|
||||
// addresses.
|
||||
|
|
31
internal/cfgutil/file.go
Normal file
31
internal/cfgutil/file.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2015 The btcsuite developers
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package cfgutil
|
||||
|
||||
import "os"
|
||||
|
||||
// FilesExists reports whether the named file or directory exists.
|
||||
func FileExists(filePath string) (bool, error) {
|
||||
_, err := os.Stat(filePath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
62
internal/cfgutil/normalization.go
Normal file
62
internal/cfgutil/normalization.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2015 The btcsuite developers
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package cfgutil
|
||||
|
||||
import "net"
|
||||
|
||||
// NormalizeAddress returns the normalized form of the address, adding a default
|
||||
// port if necessary. An error is returned if the address, even without a port,
|
||||
// is not valid.
|
||||
func NormalizeAddress(addr string, defaultPort string) (hostport string, err error) {
|
||||
// If the first SplitHostPort errors because of a missing port and not
|
||||
// for an invalid host, add the port. If the second SplitHostPort
|
||||
// fails, then a port is not missing and the original error should be
|
||||
// returned.
|
||||
host, port, origErr := net.SplitHostPort(addr)
|
||||
if origErr == nil {
|
||||
return net.JoinHostPort(host, port), nil
|
||||
}
|
||||
addr = net.JoinHostPort(addr, defaultPort)
|
||||
_, _, err = net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return "", origErr
|
||||
}
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// NormalizeAddresses returns a new slice with all the passed peer addresses
|
||||
// normalized with the given default port, and all duplicates removed.
|
||||
func NormalizeAddresses(addrs []string, defaultPort string) ([]string, error) {
|
||||
var (
|
||||
normalized = make([]string, 0, len(addrs))
|
||||
seenSet = make(map[string]struct{})
|
||||
)
|
||||
|
||||
for _, addr := range addrs {
|
||||
normalizedAddr, err := NormalizeAddress(addr, defaultPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, seen := seenSet[normalizedAddr]
|
||||
if !seen {
|
||||
normalized = append(normalized, normalizedAddr)
|
||||
seenSet[normalizedAddr] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return normalized, nil
|
||||
}
|
51
netparams/params.go
Normal file
51
netparams/params.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2015 The btcsuite developers
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package netparams
|
||||
|
||||
import "github.com/btcsuite/btcd/chaincfg"
|
||||
|
||||
// Params is used to group parameters for various networks such as the main
|
||||
// network and test networks.
|
||||
type Params struct {
|
||||
*chaincfg.Params
|
||||
RPCClientPort string
|
||||
RPCServerPort string
|
||||
}
|
||||
|
||||
// MainNetParams contains parameters specific running btcwallet and
|
||||
// btcd on the main network (wire.MainNet).
|
||||
var MainNetParams = Params{
|
||||
Params: &chaincfg.MainNetParams,
|
||||
RPCClientPort: "8334",
|
||||
RPCServerPort: "8332",
|
||||
}
|
||||
|
||||
// TestNet3Params contains parameters specific running btcwallet and
|
||||
// btcd on the test network (version 3) (wire.TestNet3).
|
||||
var TestNet3Params = Params{
|
||||
Params: &chaincfg.TestNet3Params,
|
||||
RPCClientPort: "18334",
|
||||
RPCServerPort: "18332",
|
||||
}
|
||||
|
||||
// SimNetParams contains parameters specific to the simulation test network
|
||||
// (wire.SimNet).
|
||||
var SimNetParams = Params{
|
||||
Params: &chaincfg.SimNetParams,
|
||||
RPCClientPort: "18556",
|
||||
RPCServerPort: "18554",
|
||||
}
|
44
params.go
44
params.go
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2014 The btcsuite developers
|
||||
* Copyright (c) 2013-2015 The btcsuite developers
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -16,44 +16,6 @@
|
|||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
)
|
||||
import "github.com/btcsuite/btcwallet/netparams"
|
||||
|
||||
var activeNet = &testNet3Params
|
||||
|
||||
// params is used to group parameters for various networks such as the main
|
||||
// network and test networks.
|
||||
type params struct {
|
||||
*chaincfg.Params
|
||||
connect string
|
||||
btcdPort string
|
||||
svrPort string
|
||||
}
|
||||
|
||||
// mainNetParams contains parameters specific running btcwallet and
|
||||
// btcd on the main network (wire.MainNet).
|
||||
var mainNetParams = params{
|
||||
Params: &chaincfg.MainNetParams,
|
||||
connect: "localhost:8334",
|
||||
btcdPort: "8334",
|
||||
svrPort: "8332",
|
||||
}
|
||||
|
||||
// testNet3Params contains parameters specific running btcwallet and
|
||||
// btcd on the test network (version 3) (wire.TestNet3).
|
||||
var testNet3Params = params{
|
||||
Params: &chaincfg.TestNet3Params,
|
||||
connect: "localhost:18334",
|
||||
btcdPort: "18334",
|
||||
svrPort: "18332",
|
||||
}
|
||||
|
||||
// simNetParams contains parameters specific to the simulation test network
|
||||
// (wire.SimNet).
|
||||
var simNetParams = params{
|
||||
Params: &chaincfg.SimNetParams,
|
||||
connect: "localhost:18556",
|
||||
btcdPort: "18556",
|
||||
svrPort: "18554",
|
||||
}
|
||||
var activeNet = &netparams.TestNet3Params
|
||||
|
|
|
@ -322,9 +322,11 @@ func newRPCServer(listenAddrs []string, maxPost, maxWebsockets int64) (*rpcServe
|
|||
// Setup TLS if not disabled.
|
||||
listenFunc := net.Listen
|
||||
if !cfg.DisableServerTLS {
|
||||
// Check for existence of cert file and key file
|
||||
if !fileExists(cfg.RPCKey) && !fileExists(cfg.RPCCert) {
|
||||
// if both files do not exist, we generate them.
|
||||
// Check for existence of cert file and key file. Generate a
|
||||
// new keypair if both are missing.
|
||||
_, e1 := os.Stat(cfg.RPCKey)
|
||||
_, e2 := os.Stat(cfg.RPCCert)
|
||||
if os.IsNotExist(e1) && os.IsNotExist(e2) {
|
||||
err := genCertPair(cfg.RPCCert, cfg.RPCKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -432,8 +432,13 @@ func createWallet(cfg *config) error {
|
|||
netDir := networkDir(cfg.DataDir, activeNet.Params)
|
||||
keystorePath := filepath.Join(netDir, keystore.Filename)
|
||||
var legacyKeyStore *keystore.Store
|
||||
if fileExists(keystorePath) {
|
||||
var err error
|
||||
_, err := os.Stat(keystorePath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
// A stat error not due to a non-existant file should be
|
||||
// returned to the caller.
|
||||
return err
|
||||
} else if err == nil {
|
||||
// Keystore file exists.
|
||||
legacyKeyStore, err = keystore.OpenDir(netDir)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
Loading…
Reference in a new issue