decred.org/dcrdex@v1.0.3/dex/networks/btc/config.go (about)

     1  // This code is available on the terms of the project LICENSE.md file,
     2  // also available online at https://blueoakcouncil.org/license/1.0.0.
     3  
     4  package btc
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  	"path/filepath"
    10  	"strconv"
    11  	"strings"
    12  
    13  	"decred.org/dcrdex/dex"
    14  	"github.com/btcsuite/btcd/btcutil"
    15  )
    16  
    17  // NetPorts are a set of port to use with the different networks.
    18  type NetPorts struct {
    19  	Mainnet string
    20  	Testnet string
    21  	Simnet  string
    22  }
    23  
    24  // RPCPorts are the default BTC ports.
    25  var RPCPorts = NetPorts{
    26  	Mainnet: "8332",
    27  	Testnet: "18332",
    28  	Simnet:  "18443",
    29  }
    30  
    31  // RPCConfig holds the parameters needed to initialize an RPC connection to a btc
    32  // wallet or backend. Default values are used for RPCBind and/or RPCPort if not
    33  // set.
    34  type RPCConfig struct {
    35  	RPCUser    string `ini:"rpcuser"`
    36  	RPCPass    string `ini:"rpcpassword"`
    37  	RPCBind    string `ini:"rpcbind"`
    38  	RPCPort    int    `ini:"rpcport"`
    39  	RPCConnect string `ini:"rpcconnect"` // (bitcoin-cli) if set, reflected in RPCBind
    40  	// IsPublicProvider: Set rpcbind with a URL with protocol https, and we'll
    41  	// assume it's a public RPC provider. This means that we assume TLS and
    42  	// permit omission of the RPCUser and RPCPass, since they might be encoded
    43  	// in the URL.
    44  	IsPublicProvider bool
    45  }
    46  
    47  func CheckRPCConfig(cfg *RPCConfig, name string, network dex.Network, ports NetPorts) error {
    48  
    49  	var port string
    50  	switch network {
    51  	case dex.Mainnet:
    52  		port = ports.Mainnet
    53  	case dex.Testnet:
    54  		port = ports.Testnet
    55  	case dex.Regtest:
    56  		port = ports.Simnet
    57  	default:
    58  		return fmt.Errorf("unknown network ID %v", network)
    59  	}
    60  
    61  	StandardizeRPCConf(cfg, port)
    62  
    63  	// When using a public provider, the credentials can be in the url's path.
    64  	if !cfg.IsPublicProvider {
    65  		if cfg.RPCUser == "" {
    66  			return fmt.Errorf("no rpcuser set in %q config file", name)
    67  		}
    68  		if cfg.RPCPass == "" {
    69  			return fmt.Errorf("no rpcpassword set in %q config file", name)
    70  		}
    71  	}
    72  
    73  	return nil
    74  }
    75  
    76  // StandardizeRPCConf standardizes the RPCBind and RPCPort fields, and returns
    77  // the updated RPCBind field. defaultPort must be either an empty string or a
    78  // valid representation of a positive 16-bit integer.
    79  func StandardizeRPCConf(cfg *RPCConfig, defaultPort string) {
    80  	host := "127.0.0.1" // default if not in RPCBind or RPCConnect
    81  	port := strconv.Itoa(cfg.RPCPort)
    82  	if cfg.RPCPort <= 0 {
    83  		port = defaultPort
    84  	}
    85  
    86  	if cfg.RPCBind != "" {
    87  		// Allow RPC providers
    88  		if strings.HasPrefix(cfg.RPCBind, "https://") {
    89  			cfg.IsPublicProvider = true
    90  			cfg.RPCBind = cfg.RPCBind[len("https://"):]
    91  			port = ""
    92  		}
    93  
    94  		h, p, err := net.SplitHostPort(cfg.RPCBind)
    95  		if err != nil {
    96  			// Will error for i.e. "localhost", but not for "localhost:" or ":1234"
    97  			host = cfg.RPCBind // use port from RPCPort
    98  		} else {
    99  			if h != "" {
   100  				host = h
   101  			}
   102  			// If RPCBind includes a port, it takes precedence over RPCPort.
   103  			if p != "" {
   104  				port = p
   105  			}
   106  		}
   107  	}
   108  
   109  	// If RPCConnect is set, that's how the user has bitcoin-cli configured, so
   110  	// use that instead of rpcbind's host or default (localhost).
   111  	if cfg.RPCConnect != "" {
   112  		host = cfg.RPCConnect
   113  		// RPCConnect does not include port, so use what we got above.
   114  	}
   115  
   116  	if port != "" {
   117  		cfg.RPCBind = net.JoinHostPort(host, port)
   118  		cfg.RPCPort, _ = strconv.Atoi(port)
   119  	} else {
   120  		cfg.RPCBind = host
   121  	}
   122  }
   123  
   124  // SystemConfigPath will return the default config file path for bitcoin-like
   125  // assets.
   126  func SystemConfigPath(asset string) string {
   127  	homeDir := btcutil.AppDataDir(asset, false)
   128  	return filepath.Join(homeDir, fmt.Sprintf("%s.conf", asset))
   129  }