multi: Split dcrctl to own repo and update docs

The dcrctl project is being split out of the dcrd repo and module into
its own repo (https://github.com/decred/dcrctl) and module
(decred.org/dcrctl).  This commit removes the dcrctl main package and
updates documentation throughout the repo mentioning dcrctl and its
build instructions.
This commit is contained in:
Josh Rickmar 2020-05-01 18:43:25 +00:00 committed by Dave Collins
parent e12b0a7191
commit 787d3f5c0f
10 changed files with 15 additions and 792 deletions

1
.gitignore vendored
View File

@ -37,7 +37,6 @@ _testmain.go
dcrd
cmd/addblock/addblock
cmd/checkdevpremine/checkdevpremine
cmd/dcrctl/dcrctl
cmd/findcheckpoint/findcheckpoint
cmd/gencerts/gencerts
cmd/promptsecret/promptsecret

View File

@ -24,6 +24,7 @@ Core software:
* dcrd: a Decred full node daemon (this)
* [dcrwallet](https://github.com/decred/dcrwallet): a CLI Decred wallet daemon
* [dcrctl](https://github.com/decred/dcrctl): a CLI client for dcrd and dcrwallet
Bundles:
@ -179,8 +180,9 @@ https://decred.org/downloads
```sh
$ git clone https://github.com/decred/dcrd $HOME/src/dcrd
$ cd $HOME/src/dcrd
$ go install . ./cmd/...
$ git clone https://github.com/decred/dcrctl $HOME/src/dcrctl
$ (cd $HOME/src/dcrd && go install . ./...)
$ (cd $HOME/src/dcrctl && go install)
$ dcrd -V
```

View File

@ -1,416 +0,0 @@
// Copyright (c) 2013-2015 The btcsuite developers
// Copyright (c) 2015-2019 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"io/ioutil"
"net"
"os"
"os/user"
"path/filepath"
"regexp"
"runtime"
"strings"
"github.com/decred/dcrd/dcrjson/v3"
"github.com/decred/dcrd/dcrutil/v3"
"github.com/decred/dcrd/internal/version"
dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v2"
wallettypes "github.com/decred/dcrwallet/rpc/jsonrpc/types"
flags "github.com/jessevdk/go-flags"
)
const (
// unusableFlags are the command usage flags which this utility are not
// able to use. In particular it doesn't support websockets and
// consequently notifications.
unusableFlags = dcrjson.UFWebsocketOnly | dcrjson.UFNotification
)
var (
dcrdHomeDir = dcrutil.AppDataDir("dcrd", false)
dcrctlHomeDir = dcrutil.AppDataDir("dcrctl", false)
dcrwalletHomeDir = dcrutil.AppDataDir("dcrwallet", false)
defaultConfigFile = filepath.Join(dcrctlHomeDir, "dcrctl.conf")
defaultRPCServer = "localhost"
defaultWalletRPCServer = "localhost"
defaultRPCCertFile = filepath.Join(dcrdHomeDir, "rpc.cert")
defaultWalletCertFile = filepath.Join(dcrwalletHomeDir, "rpc.cert")
)
// listCommands categorizes and lists all of the usable commands along with
// their one-line usage.
func listCommands() {
var categories = []struct {
Header string
Method interface{}
Usages []string
}{{
Header: "Chain Server Commands:",
Method: dcrdtypes.Method(""),
}, {
Header: "Wallet Server Commands (--wallet):",
Method: wallettypes.Method(""),
}}
for i := range categories {
method := categories[i].Method
methods := dcrjson.RegisteredMethods(method)
for _, methodStr := range methods {
switch method.(type) {
case dcrdtypes.Method:
method = dcrdtypes.Method(methodStr)
case wallettypes.Method:
method = wallettypes.Method(methodStr)
}
flags, err := dcrjson.MethodUsageFlags(method)
if err != nil {
// This should never happen since the method was just
// returned from the package, but be safe.
continue
}
// Skip the commands that aren't usable from this utility.
if flags&unusableFlags != 0 {
continue
}
usage, err := dcrjson.MethodUsageText(method)
if err != nil {
// This should never happen since the method was just
// returned from the package, but be safe.
continue
}
categories[i].Usages = append(categories[i].Usages, usage)
}
}
// Display the command according to their categories.
for i := range categories {
fmt.Println(categories[i].Header)
for _, usage := range categories[i].Usages {
fmt.Println(usage)
}
fmt.Println()
}
}
// config defines the configuration options for dcrctl.
//
// See loadConfig for details on the configuration load process.
type config struct {
ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
ListCommands bool `short:"l" long:"listcommands" description:"List all of the supported commands and exit"`
ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"`
RPCUser string `short:"u" long:"rpcuser" description:"RPC username"`
RPCPassword string `short:"P" long:"rpcpass" default-mask:"-" description:"RPC password"`
RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to"`
WalletRPCServer string `short:"w" long:"walletrpcserver" description:"Wallet RPC server to connect to"`
RPCCert string `short:"c" long:"rpccert" description:"RPC server certificate chain for validation"`
PrintJSON bool `short:"j" long:"json" description:"Print json messages sent and received"`
NoTLS bool `long:"notls" description:"Disable TLS"`
Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
ProxyUser string `long:"proxyuser" description:"Username for proxy server"`
ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"`
TestNet bool `long:"testnet" description:"Connect to testnet"`
SimNet bool `long:"simnet" description:"Connect to the simulation test network"`
TLSSkipVerify bool `long:"skipverify" description:"Do not verify tls certificates (not recommended!)"`
Wallet bool `long:"wallet" description:"Connect to wallet"`
}
// normalizeAddress returns addr with the passed default port appended if
// there is not already a port specified.
func normalizeAddress(addr string, useTestNet, useSimNet, useWallet bool) string {
_, _, err := net.SplitHostPort(addr)
if err != nil {
var defaultPort string
switch {
case useTestNet:
if useWallet {
defaultPort = "19110"
} else {
defaultPort = "19109"
}
case useSimNet:
if useWallet {
defaultPort = "19557"
} else {
defaultPort = "19556"
}
default:
if useWallet {
defaultPort = "9110"
} else {
defaultPort = "9109"
}
}
return net.JoinHostPort(addr, defaultPort)
}
return addr
}
// cleanAndExpandPath expands environment variables and leading ~ in the
// passed path, cleans the result, and returns it.
func cleanAndExpandPath(path string) string {
// Nothing to do when no path is given.
if path == "" {
return path
}
// NOTE: The os.ExpandEnv doesn't work with Windows cmd.exe-style
// %VARIABLE%, but the variables can still be expanded via POSIX-style
// $VARIABLE.
path = os.ExpandEnv(path)
if !strings.HasPrefix(path, "~") {
return filepath.Clean(path)
}
// Expand initial ~ to the current user's home directory, or ~otheruser
// to otheruser's home directory. On Windows, both forward and backward
// slashes can be used.
path = path[1:]
var pathSeparators string
if runtime.GOOS == "windows" {
pathSeparators = string(os.PathSeparator) + "/"
} else {
pathSeparators = string(os.PathSeparator)
}
userName := ""
if i := strings.IndexAny(path, pathSeparators); i != -1 {
userName = path[:i]
path = path[i:]
}
homeDir := ""
var u *user.User
var err error
if userName == "" {
u, err = user.Current()
} else {
u, err = user.Lookup(userName)
}
if err == nil {
homeDir = u.HomeDir
}
// Fallback to CWD if user lookup fails or user has no home directory.
if homeDir == "" {
homeDir = "."
}
return filepath.Join(homeDir, path)
}
// fileExists 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
}
// loadConfig initializes and parses the config using a config file and command
// line options.
//
// The configuration proceeds as follows:
// 1) Start with a default config with sane settings
// 2) Pre-parse the command line to check for an alternative config file
// 3) Load configuration file overwriting defaults with any specified options
// 4) Parse CLI options and overwrite/add any specified options
//
// The above results in functioning properly without any config settings
// while still allowing the user to override settings with config files and
// command line options. Command line options always take precedence.
func loadConfig() (*config, []string, error) {
// Default config.
cfg := config{
ConfigFile: defaultConfigFile,
RPCServer: defaultRPCServer,
RPCCert: defaultRPCCertFile,
WalletRPCServer: defaultWalletRPCServer,
}
// Pre-parse the command line options to see if an alternative config
// file, the version flag, or the list commands flag was specified. Any
// errors aside from the help message error can be ignored here since
// they will be caught by the final parse below.
preCfg := cfg
preParser := flags.NewParser(&preCfg, flags.HelpFlag)
_, err := preParser.Parse()
if err != nil {
if e, ok := err.(*flags.Error); ok && e.Type != flags.ErrHelp {
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, "")
fmt.Fprintln(os.Stderr, "The special parameter `-` "+
"indicates that a parameter should be read "+
"from the\nnext unread line from standard input.")
os.Exit(1)
} else if ok && e.Type == flags.ErrHelp {
fmt.Fprintln(os.Stdout, err)
fmt.Fprintln(os.Stdout, "")
fmt.Fprintln(os.Stdout, "The special parameter `-` "+
"indicates that a parameter should be read "+
"from the\nnext unread line from standard input.")
os.Exit(0)
}
}
// Show the version and exit if the version flag was specified.
appName := filepath.Base(os.Args[0])
appName = strings.TrimSuffix(appName, filepath.Ext(appName))
usageMessage := fmt.Sprintf("Use %s -h to show options", appName)
if preCfg.ShowVersion {
fmt.Printf("%s version %s (Go version %s %s/%s)\n", appName,
version.String(), runtime.Version(), runtime.GOOS, runtime.GOARCH)
os.Exit(0)
}
// Show the available commands and exit if the associated flag was
// specified.
if preCfg.ListCommands {
listCommands()
os.Exit(0)
}
if !fileExists(preCfg.ConfigFile) {
err := createDefaultConfigFile(preCfg.ConfigFile)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating a default config file: %v\n", err)
}
}
// Load additional config from file.
parser := flags.NewParser(&cfg, flags.Default)
err = flags.NewIniParser(parser).ParseFile(preCfg.ConfigFile)
if err != nil {
if _, ok := err.(*os.PathError); !ok {
fmt.Fprintf(os.Stderr, "Error parsing config file: %v\n",
err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
}
// Parse command line options again to ensure they take precedence.
remainingArgs, err := parser.Parse()
if err != nil {
if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
fmt.Fprintln(os.Stderr, usageMessage)
}
return nil, nil, err
}
// Multiple networks can't be selected simultaneously.
numNets := 0
if cfg.TestNet {
numNets++
}
if cfg.SimNet {
numNets++
}
if numNets > 1 {
str := "%s: the testnet and simnet params can't be used " +
"together -- choose one of the two"
err := fmt.Errorf(str, "loadConfig")
fmt.Fprintln(os.Stderr, err)
return nil, nil, err
}
// Override the RPC certificate if the --wallet flag was specified and
// the user did not specify one.
if cfg.Wallet && cfg.RPCCert == defaultRPCCertFile {
cfg.RPCCert = defaultWalletCertFile
}
// When the --wallet flag is specified, use the walletrpcserver port
// if specified.
if cfg.Wallet && cfg.WalletRPCServer != defaultWalletRPCServer {
cfg.RPCServer = cfg.WalletRPCServer
}
// Handle environment variable expansion in the RPC certificate path.
cfg.RPCCert = cleanAndExpandPath(cfg.RPCCert)
// Add default port to RPC server based on --testnet and --wallet flags
// if needed.
cfg.RPCServer = normalizeAddress(cfg.RPCServer, cfg.TestNet,
cfg.SimNet, cfg.Wallet)
return &cfg, remainingArgs, nil
}
// createDefaultConfig creates a basic config file at the given destination path.
// For this it tries to read the dcrd config file at its default path, and extract
// the RPC user and password from it.
func createDefaultConfigFile(destinationPath string) error {
// Nothing to do when there is no existing dcrd conf file at the default
// path to extract the details from.
dcrdConfigPath := filepath.Join(dcrdHomeDir, "dcrd.conf")
if !fileExists(dcrdConfigPath) {
return nil
}
// Read dcrd.conf from its default path
dcrdConfigFile, err := os.Open(dcrdConfigPath)
if err != nil {
return err
}
defer dcrdConfigFile.Close()
content, err := ioutil.ReadAll(dcrdConfigFile)
if err != nil {
return err
}
// Extract the rpcuser
rpcUserRegexp, err := regexp.Compile(`(?m)^\s*rpcuser=([^\s]+)`)
if err != nil {
return err
}
userSubmatches := rpcUserRegexp.FindSubmatch(content)
if userSubmatches == nil {
// No user found, nothing to do
return nil
}
// Extract the rpcpass
rpcPassRegexp, err := regexp.Compile(`(?m)^\s*rpcpass=([^\s]+)`)
if err != nil {
return err
}
passSubmatches := rpcPassRegexp.FindSubmatch(content)
if passSubmatches == nil {
// No password found, nothing to do
return nil
}
// Create the destination directory if it does not exists
err = os.MkdirAll(filepath.Dir(destinationPath), 0700)
if err != nil {
return err
}
// Create the destination file and write the rpcuser and rpcpass to it
dest, err := os.OpenFile(destinationPath,
os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
defer dest.Close()
dest.WriteString(fmt.Sprintf("rpcuser=%s\nrpcpass=%s",
string(userSubmatches[1]), string(passSubmatches[1])))
return nil
}

View File

@ -1,178 +0,0 @@
// Copyright (c) 2013-2015 The btcsuite developers
// Copyright (c) 2015-2019 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/decred/dcrd/dcrjson/v3"
dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v2"
wallettypes "github.com/decred/dcrwallet/rpc/jsonrpc/types"
)
const (
showHelpMessage = "Specify -h to show available options"
listCmdMessage = "Specify -l to list available commands"
)
// commandUsage display the usage for a specific command.
func commandUsage(method interface{}) {
usage, err := dcrjson.MethodUsageText(method)
if err != nil {
// This should never happen since the method was already checked
// before calling this function, but be safe.
fmt.Fprintln(os.Stderr, "Failed to obtain command usage:", err)
return
}
fmt.Fprintln(os.Stderr, "Usage:")
fmt.Fprintf(os.Stderr, " %s\n", usage)
}
// usage displays the general usage when the help flag is not displayed and
// and an invalid command was specified. The commandUsage function is used
// instead when a valid command was specified.
func usage(errorMessage string) {
appName := filepath.Base(os.Args[0])
appName = strings.TrimSuffix(appName, filepath.Ext(appName))
fmt.Fprintln(os.Stderr, errorMessage)
fmt.Fprintln(os.Stderr, "Usage:")
fmt.Fprintf(os.Stderr, " %s [OPTIONS] <command> <args...>\n\n",
appName)
fmt.Fprintln(os.Stderr, showHelpMessage)
fmt.Fprintln(os.Stderr, listCmdMessage)
}
func main() {
cfg, args, err := loadConfig()
if err != nil {
os.Exit(1)
}
if len(args) < 1 {
usage("No command specified")
os.Exit(1)
}
// Ensure the specified method identifies a valid registered command and
// is one of the usable types.
methodStr := args[0]
var method interface{} = dcrdtypes.Method(methodStr)
usageFlags, err := dcrjson.MethodUsageFlags(method)
if err != nil {
method = wallettypes.Method(methodStr)
usageFlags, err = dcrjson.MethodUsageFlags(method)
}
if err != nil {
fmt.Fprintf(os.Stderr, "Unrecognized command %q\n", methodStr)
fmt.Fprintln(os.Stderr, listCmdMessage)
os.Exit(1)
}
if usageFlags&unusableFlags != 0 {
fmt.Fprintf(os.Stderr, "The '%s' command can only be used via "+
"websockets\n", method)
fmt.Fprintln(os.Stderr, listCmdMessage)
os.Exit(1)
}
// Convert remaining command line args to a slice of interface values
// to be passed along as parameters to new command creation function.
//
// Since some commands, such as submitblock, can involve data which is
// too large for the Operating System to allow as a normal command line
// parameter, support using '-' as an argument to allow the argument
// to be read from a stdin pipe.
bio := bufio.NewReader(os.Stdin)
params := make([]interface{}, 0, len(args[1:]))
for _, arg := range args[1:] {
if arg == "-" {
param, err := bio.ReadString('\n')
if err != nil && err != io.EOF {
fmt.Fprintf(os.Stderr, "Failed to read data "+
"from stdin: %v\n", err)
os.Exit(1)
}
if err == io.EOF && len(param) == 0 {
fmt.Fprintln(os.Stderr, "Not enough lines "+
"provided on stdin")
os.Exit(1)
}
param = strings.TrimRight(param, "\r\n")
params = append(params, param)
continue
}
params = append(params, arg)
}
// Attempt to create the appropriate command using the arguments
// provided by the user.
cmd, err := dcrjson.NewCmd(method, params...)
if err != nil {
// Show the error along with its error code when it's a
// dcrjson.Error as it realistically will always be since the
// NewCmd function is only supposed to return errors of that
// type.
if jerr, ok := err.(dcrjson.Error); ok {
fmt.Fprintf(os.Stderr, "%s command: %v (code: %s)\n",
method, err, jerr.Code)
commandUsage(method)
os.Exit(1)
}
// The error is not a dcrjson.Error and this really should not
// happen. Nevertheless, fallback to just showing the error
// if it should happen due to a bug in the package.
fmt.Fprintf(os.Stderr, "%s command: %v\n", method, err)
commandUsage(method)
os.Exit(1)
}
// Marshal the command into a JSON-RPC byte slice in preparation for
// sending it to the RPC server.
marshalledJSON, err := dcrjson.MarshalCmd("1.0", 1, cmd)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// Send the JSON-RPC request to the server using the user-specified
// connection configuration.
result, err := sendPostRequest(marshalledJSON, cfg)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// Choose how to display the result based on its type.
strResult := string(result)
if strings.HasPrefix(strResult, "{") || strings.HasPrefix(strResult, "[") {
var dst bytes.Buffer
if err := json.Indent(&dst, result, "", " "); err != nil {
fmt.Fprintf(os.Stderr, "Failed to format result: %v",
err)
os.Exit(1)
}
fmt.Println(dst.String())
} else if strings.HasPrefix(strResult, `"`) {
var str string
if err := json.Unmarshal(result, &str); err != nil {
fmt.Fprintf(os.Stderr, "Failed to unmarshal result: %v",
err)
os.Exit(1)
}
fmt.Println(str)
} else if strResult != "null" {
fmt.Println(strResult)
}
}

View File

@ -1,146 +0,0 @@
// Copyright (c) 2013-2015 The btcsuite developers
// Copyright (c) 2015-2019 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"github.com/decred/dcrd/dcrjson/v3"
"github.com/decred/go-socks/socks"
)
// newHTTPClient returns a new HTTP client that is configured according to the
// proxy and TLS settings in the associated connection configuration.
func newHTTPClient(cfg *config) (*http.Client, error) {
// Configure proxy if needed.
var dial func(network, addr string) (net.Conn, error)
if cfg.Proxy != "" {
proxy := &socks.Proxy{
Addr: cfg.Proxy,
Username: cfg.ProxyUser,
Password: cfg.ProxyPass,
}
dial = func(network, addr string) (net.Conn, error) {
c, err := proxy.Dial(network, addr)
if err != nil {
return nil, err
}
return c, nil
}
}
// Configure TLS if needed.
var tlsConfig *tls.Config
if !cfg.NoTLS {
tlsConfig = &tls.Config{
InsecureSkipVerify: cfg.TLSSkipVerify,
}
if !cfg.TLSSkipVerify && cfg.RPCCert != "" {
pem, err := ioutil.ReadFile(cfg.RPCCert)
if err != nil {
return nil, err
}
pool := x509.NewCertPool()
if ok := pool.AppendCertsFromPEM(pem); !ok {
return nil, fmt.Errorf("invalid certificate file: %v",
cfg.RPCCert)
}
tlsConfig.RootCAs = pool
}
}
// Create and return the new HTTP client potentially configured with a
// proxy and TLS.
client := http.Client{
Transport: &http.Transport{
Dial: dial,
TLSClientConfig: tlsConfig,
},
}
return &client, nil
}
// sendPostRequest sends the marshalled JSON-RPC command using HTTP-POST mode
// to the server described in the passed config struct. It also attempts to
// unmarshal the response as a JSON-RPC response and returns either the result
// field or the error field depending on whether or not there is an error.
func sendPostRequest(marshalledJSON []byte, cfg *config) ([]byte, error) {
// Generate a request to the configured RPC server.
protocol := "http"
if !cfg.NoTLS {
protocol = "https"
}
url := protocol + "://" + cfg.RPCServer
if cfg.PrintJSON {
fmt.Println(string(marshalledJSON))
}
bodyReader := bytes.NewReader(marshalledJSON)
httpRequest, err := http.NewRequest("POST", url, bodyReader)
if err != nil {
return nil, err
}
httpRequest.Close = true
httpRequest.Header.Set("Content-Type", "application/json")
// Configure basic access authorization.
httpRequest.SetBasicAuth(cfg.RPCUser, cfg.RPCPassword)
// Create the new HTTP client that is configured according to the user-
// specified options and submit the request.
httpClient, err := newHTTPClient(cfg)
if err != nil {
return nil, err
}
httpResponse, err := httpClient.Do(httpRequest)
if err != nil {
return nil, err
}
// Read the raw bytes and close the response.
respBytes, err := ioutil.ReadAll(httpResponse.Body)
httpResponse.Body.Close()
if err != nil {
err = fmt.Errorf("error reading json reply: %v", err)
return nil, err
}
// Handle unsuccessful HTTP responses
if httpResponse.StatusCode < 200 || httpResponse.StatusCode >= 300 {
// Generate a standard error to return if the server body is
// empty. This should not happen very often, but it's better
// than showing nothing in case the target server has a poor
// implementation.
if len(respBytes) == 0 {
return nil, fmt.Errorf("%d %s", httpResponse.StatusCode,
http.StatusText(httpResponse.StatusCode))
}
return nil, fmt.Errorf("%s", respBytes)
}
// If requested, print raw json response.
if cfg.PrintJSON {
fmt.Println(string(respBytes))
}
// Unmarshal the response.
var resp dcrjson.Response
if err := json.Unmarshal(respBytes, &resp); err != nil {
return nil, err
}
if resp.Error != nil {
return nil, resp.Error
}
return resp.Result, nil
}

View File

@ -1,36 +0,0 @@
[Application Options]
; ------------------------------------------------------------------------------
; Network settings
; ------------------------------------------------------------------------------
; Use testnet (cannot be used with simnet=1).
; testnet=1
; Use simnet (cannot be used with testnet=1).
; simnet=1
; ------------------------------------------------------------------------------
; RPC client settings
; ------------------------------------------------------------------------------
; Connect via a SOCKS5 proxy.
; proxy=127.0.0.1:9050
; proxyuser=
; proxypass=
; Username and password to authenticate connections to a Decred RPC server
; (usually dcrd or dcrwallet)
; rpcuser=
; rpcpass=
; RPC server to connect to
; rpcserver=localhost
; Wallet RPC server to connect to
; walletrpcserver=localhost
; RPC server certificate chain file for validation
; rpccert=~/.dcrd/rpc.cert

View File

@ -55,10 +55,11 @@ options, which can be viewed by running: `$ dcrd --help`.
**2.3 Controlling and Querying dcrd via dcrctl**<br />
dcrctl is a command line utility that can be used to both control and query dcrd
via [RPC](https://www.wikipedia.org/wiki/Remote_procedure_call). dcrd does
**not** enable its RPC server by default; You must configure at minimum both an
RPC username and password or both an RPC limited username and password:
[dcrctl](https://github.com/decred/dcrctl) is a command line utility that can be
used to both control and query dcrd via
[RPC](https://www.wikipedia.org/wiki/Remote_procedure_call). dcrd does **not**
enable its RPC server by default; You must configure at minimum both an RPC
username and password or both an RPC limited username and password:
* dcrd.conf configuration file
```

View File

@ -100,11 +100,11 @@ authenticated will cause the websocket to be closed immediately.
==4. Command-line Utility==
dcrd comes with a separate utility named <code>dcrctl</code> which can be used to issue
these RPC commands via HTTP POST requests to dcrd after configuring it with the
information in the [[#3-authentication|Authentication]] section above. It can also
be used to communicate with any server/daemon/service which provides a JSON-RPC
API compatible with the original dcrd client.
dcrd is built to work with [https://github.com/decred/dcrctl <code>dcrctl</code>]
which can be used to issue these RPC commands via HTTP POST requests to dcrd
after configuring it with the information in the [[#3-authentication|Authentication]]
section above. It can also be used to communicate with any server/daemon/service
which provides a JSON-RPC API compatible with the original dcrd client.
==5. Standard Methods==

3
go.mod
View File

@ -14,7 +14,6 @@ require (
github.com/decred/dcrd/chaincfg/chainhash v1.0.2
github.com/decred/dcrd/chaincfg/v3 v3.0.0-20200215031403-6b2ce76f0986
github.com/decred/dcrd/connmgr/v3 v3.0.0-20200215031403-6b2ce76f0986
github.com/decred/dcrd/crypto/blake256 v1.0.0
github.com/decred/dcrd/crypto/ripemd160 v1.0.0
github.com/decred/dcrd/database/v2 v2.0.1
github.com/decred/dcrd/dcrec v1.0.0
@ -32,7 +31,7 @@ require (
github.com/decred/dcrd/rpcclient/v6 v6.0.0-20200215031403-6b2ce76f0986
github.com/decred/dcrd/txscript/v3 v3.0.0-20200215031403-6b2ce76f0986
github.com/decred/dcrd/wire v1.3.0
github.com/decred/dcrwallet/rpc/jsonrpc/types v1.4.0
github.com/decred/dcrwallet/rpc/jsonrpc/types v1.4.0 // indirect
github.com/decred/go-socks v1.1.0
github.com/decred/slog v1.0.0
github.com/gorilla/websocket v1.4.1

2
go.sum
View File

@ -10,8 +10,6 @@ github.com/decred/base58 v1.0.2 h1:yupIH6bg+q7KYfBk7oUv3xFjKGb5Ypm4+v/61X4keGY=
github.com/decred/base58 v1.0.2/go.mod h1:pXP9cXCfM2sFLb2viz2FNIdeMWmZDBKG3ZBYbiSM78E=
github.com/decred/dcrd/dcrec/edwards/v2 v2.0.0 h1:E5KszxGgpjpmW8vN811G6rBAZg0/S/DftdGqN4FW5x4=
github.com/decred/dcrd/dcrec/edwards/v2 v2.0.0/go.mod h1:d0H8xGMWbiIQP7gN3v2rByWUcuZPm9YsgmnfoxgbINc=
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 h1:3GIJYXQDAKpLEFriGFN8SbSffak10UXHGdIcFaMPykY=
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0/go.mod h1:3s92l0paYkZoIHuj4X93Teg/HB7eGM9x/zokGw+u4mY=
github.com/decred/dcrd/rpc/jsonrpc/types v1.0.1 h1:sWsGtWzdmrna6aysDCHwjANTJh+Lxt2xp6S10ahP79Y=
github.com/decred/dcrd/rpc/jsonrpc/types v1.0.1/go.mod h1:dJUp9PoyFYklzmlImpVkVLOr6j4zKuUv66YgemP2sd8=
github.com/decred/dcrwallet/rpc/jsonrpc/types v1.3.0 h1:yCxtFqK7X6GvZWQzHXjCwoGCy9YVe3tGEwxCjW5rYQk=